mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
fixed profile patching
This commit is contained in:
parent
f25d627b4e
commit
60dffc2353
6 changed files with 209 additions and 60 deletions
106
src/containers/profile/ProfileAvatar/index.tsx
Normal file
106
src/containers/profile/ProfileAvatar/index.tsx
Normal file
|
@ -0,0 +1,106 @@
|
|||
import React, { FC, useCallback, useEffect, useState } from "react";
|
||||
import styles from "./styles.scss";
|
||||
import { connect } from "react-redux";
|
||||
import { getURL } from "~/utils/dom";
|
||||
import pick from "ramda/es/pick";
|
||||
import { selectAuthUser, selectAuthProfile } from "~/redux/auth/selectors";
|
||||
import { PRESETS } from "~/constants/urls";
|
||||
import { selectUploads } from "~/redux/uploads/selectors";
|
||||
import { IFileWithUUID } from "~/redux/types";
|
||||
import uuid from "uuid4";
|
||||
import {
|
||||
UPLOAD_SUBJECTS,
|
||||
UPLOAD_TARGETS,
|
||||
UPLOAD_TYPES
|
||||
} from "~/redux/uploads/constants";
|
||||
import path from "ramda/es/path";
|
||||
import * as UPLOAD_ACTIONS from "~/redux/uploads/actions";
|
||||
import * as AUTH_ACTIONS from "~/redux/auth/actions";
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
user: pick(["id"], selectAuthUser(state)),
|
||||
profile: pick(["is_loading", "user"], selectAuthProfile(state)),
|
||||
uploads: pick(["statuses", "files"], selectUploads(state))
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
uploadUploadFiles: UPLOAD_ACTIONS.uploadUploadFiles,
|
||||
authPatchUser: AUTH_ACTIONS.authPatchUser
|
||||
};
|
||||
|
||||
type IProps = ReturnType<typeof mapStateToProps> &
|
||||
typeof mapDispatchToProps & {};
|
||||
|
||||
const ProfileAvatarUnconnected: FC<IProps> = ({
|
||||
user: { id },
|
||||
profile: { is_loading, user },
|
||||
uploads: { statuses, files },
|
||||
uploadUploadFiles,
|
||||
authPatchUser
|
||||
}) => {
|
||||
const can_edit = !is_loading && id && id === user.id;
|
||||
|
||||
const [temp, setTemp] = useState<string>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!can_edit) return;
|
||||
|
||||
Object.entries(statuses).forEach(([id, status]) => {
|
||||
if (temp === id && !!status.uuid && files[status.uuid]) {
|
||||
authPatchUser({ photo: files[status.uuid] });
|
||||
setTemp(null);
|
||||
}
|
||||
});
|
||||
}, [statuses, files, temp, can_edit, authPatchUser]);
|
||||
|
||||
const onUpload = useCallback(
|
||||
(uploads: File[]) => {
|
||||
const items: IFileWithUUID[] = Array.from(uploads).map(
|
||||
(file: File): IFileWithUUID => ({
|
||||
file,
|
||||
temp_id: uuid(),
|
||||
subject: UPLOAD_SUBJECTS.AVATAR,
|
||||
target: UPLOAD_TARGETS.PROFILES,
|
||||
type: UPLOAD_TYPES.IMAGE
|
||||
})
|
||||
);
|
||||
|
||||
setTemp(path([0, "temp_id"], items));
|
||||
uploadUploadFiles(items.slice(0, 1));
|
||||
},
|
||||
[uploadUploadFiles, setTemp]
|
||||
);
|
||||
|
||||
const onInputChange = useCallback(
|
||||
event => {
|
||||
if (!can_edit) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (!event.target.files || !event.target.files.length) return;
|
||||
|
||||
onUpload(Array.from(event.target.files));
|
||||
},
|
||||
[onUpload, can_edit]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.avatar}
|
||||
style={{
|
||||
backgroundImage: is_loading
|
||||
? null
|
||||
: `url("${user && getURL(user.photo, PRESETS.avatar)}")`
|
||||
}}
|
||||
>
|
||||
{can_edit && <input type="file" onInput={onInputChange} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ProfileAvatar = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ProfileAvatarUnconnected);
|
||||
|
||||
export { ProfileAvatar };
|
11
src/containers/profile/ProfileAvatar/styles.scss
Normal file
11
src/containers/profile/ProfileAvatar/styles.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
.avatar {
|
||||
@include outer_shadow();
|
||||
|
||||
border-radius: $radius;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: $content_bg 50% 50% no-repeat/cover;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: $gap;
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
import React, { FC } from 'react';
|
||||
import { IUser } from '~/redux/auth/types';
|
||||
import styles from './styles.scss';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Placeholder } from '~/components/placeholders/Placeholder';
|
||||
import { getURL, getPrettyDate } from '~/utils/dom';
|
||||
import { PRESETS } from '~/constants/urls';
|
||||
import { ProfileTabs } from '../ProfileTabs';
|
||||
import { MessageForm } from '~/components/profile/MessageForm';
|
||||
import React, { FC } from "react";
|
||||
import { IUser } from "~/redux/auth/types";
|
||||
import styles from "./styles.scss";
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Placeholder } from "~/components/placeholders/Placeholder";
|
||||
import { getURL, getPrettyDate } from "~/utils/dom";
|
||||
import { PRESETS } from "~/constants/urls";
|
||||
import { ProfileTabs } from "../ProfileTabs";
|
||||
import { MessageForm } from "~/components/profile/MessageForm";
|
||||
import { ProfileAvatar } from "../ProfileAvatar";
|
||||
|
||||
interface IProps {
|
||||
user?: IUser;
|
||||
|
@ -19,24 +20,21 @@ interface IProps {
|
|||
}
|
||||
|
||||
const TAB_HEADERS = {
|
||||
messages: <MessageForm is_sending_message={false} />,
|
||||
messages: <MessageForm is_sending_message={false} />
|
||||
};
|
||||
|
||||
const ProfileInfo: FC<IProps> = ({ user, tab, is_loading, is_own, setTab }) => (
|
||||
<div>
|
||||
<Group className={styles.wrap} horizontal>
|
||||
<div
|
||||
className={styles.avatar}
|
||||
style={{
|
||||
backgroundImage: is_loading
|
||||
? null
|
||||
: `url("${user && getURL(user.photo, PRESETS.avatar)}")`,
|
||||
}}
|
||||
/>
|
||||
<ProfileAvatar />
|
||||
|
||||
<div className={styles.field}>
|
||||
<div className={styles.name}>
|
||||
{is_loading ? <Placeholder width="80%" /> : user.fullname || user.username}
|
||||
{is_loading ? (
|
||||
<Placeholder width="80%" />
|
||||
) : (
|
||||
user.fullname || user.username
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.description}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue