mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
more webapp profile refactor
This commit is contained in:
parent
5078538a4b
commit
91c5a88096
@ -1,12 +1,11 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef, useCallback } from 'react';
|
||||||
import { Space, Modal, Button } from 'antd';
|
import { Space, Modal, Input, Button } from 'antd';
|
||||||
import { ProfileWrapper, EditFooter } from './Profile.styled';
|
import { ProfileWrapper, ProfileDetailsWrapper, ProfileImageWrapper, EditFooter } from './Profile.styled';
|
||||||
import { useProfile } from './useProfile.hook';
|
import { useProfile } from './useProfile.hook';
|
||||||
import { ProfileImage } from './profileImage/ProfileImage';
|
|
||||||
import { ProfileDetails } from './profileDetails/ProfileDetails';
|
|
||||||
import { Logo } from 'logo/Logo';
|
import { Logo } from 'logo/Logo';
|
||||||
import { AccountAccess } from './accountAccess/AccountAccess';
|
import { AccountAccess } from './accountAccess/AccountAccess';
|
||||||
import { LogoutOutlined, RightOutlined, EditOutlined, BookOutlined, EnvironmentOutlined } from '@ant-design/icons';
|
import { LogoutOutlined, RightOutlined, EditOutlined, BookOutlined, EnvironmentOutlined } from '@ant-design/icons';
|
||||||
|
import Cropper from 'react-easy-crop';
|
||||||
|
|
||||||
export function Profile({ closeProfile }) {
|
export function Profile({ closeProfile }) {
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ export function Profile({ closeProfile }) {
|
|||||||
<EditFooter>
|
<EditFooter>
|
||||||
<input type='file' id='file' accept="image/*" ref={imageFile} onChange={e => selected(e)} style={{display: 'none'}}/>
|
<input type='file' id='file' accept="image/*" ref={imageFile} onChange={e => selected(e)} style={{display: 'none'}}/>
|
||||||
<div className="select">
|
<div className="select">
|
||||||
<Button key="select" className="select" onClick={() => imageFile.current.click()}>Select Image</Button>
|
<Button key="select" className="pic" onClick={() => imageFile.current.click()}>Select Image</Button>
|
||||||
</div>
|
</div>
|
||||||
<Button key="back" onClick={actions.clearEditProfileImage}>Cancel</Button>
|
<Button key="back" onClick={actions.clearEditProfileImage}>Cancel</Button>
|
||||||
<Button key="save" type="primary" onClick={saveImage} loading={state.busy}>Save</Button>
|
<Button key="save" type="primary" onClick={saveImage} loading={state.busy}>Save</Button>
|
||||||
@ -80,6 +79,11 @@ export function Profile({ closeProfile }) {
|
|||||||
</EditFooter>
|
</EditFooter>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onCropComplete = useCallback((area, crop) => {
|
||||||
|
actions.setEditImageCrop(crop.width, crop.height, crop.x, crop.y)
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProfileWrapper>
|
<ProfileWrapper>
|
||||||
{ modalContext }
|
{ modalContext }
|
||||||
@ -152,11 +156,31 @@ export function Profile({ closeProfile }) {
|
|||||||
)}
|
)}
|
||||||
<Modal title="Profile Image" centered visible={state.editProfileImage} footer={editImageFooter}
|
<Modal title="Profile Image" centered visible={state.editProfileImage} footer={editImageFooter}
|
||||||
onCancel={actions.clearEditProfileImage}>
|
onCancel={actions.clearEditProfileImage}>
|
||||||
<ProfileImage state={state} actions={actions} />
|
|
||||||
|
<ProfileImageWrapper>
|
||||||
|
<Cropper image={state.editImage} crop={state.crop} zoom={state.zoom} aspect={1}
|
||||||
|
onCropChange={actions.setCrop} onCropComplete={onCropComplete} onZoomChange={actions.setZoom} />
|
||||||
|
</ProfileImageWrapper>
|
||||||
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal title="Profile Details" centered visible={state.editProfileDetails} footer={editDetailsFooter}
|
<Modal title="Profile Details" centered visible={state.editProfileDetails} footer={editDetailsFooter}
|
||||||
onCancel={actions.clearEditProfileDetails}>
|
onCancel={actions.clearEditProfileDetails}>
|
||||||
<ProfileDetails state={state} actions={actions} />
|
|
||||||
|
<ProfileDetailsWrapper>
|
||||||
|
<div class="info">
|
||||||
|
<Input placeholder="Name" spellCheck="false" onChange={(e) => actions.setEditName(e.target.value)}
|
||||||
|
defaultValue={state.editName} autocapitalize="word" />
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<Input placeholder="Location" spellCheck="false" onChange={(e) => actions.setEditLocation(e.target.value)}
|
||||||
|
defaultValue={state.editLocation} autocapitalize="word" />
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<Input.TextArea placeholder="Description" onChange={(e) => actions.setEditDescription(e.target.value)}
|
||||||
|
spellCheck="false" defaultValue={state.editDescription} autoSize={{ minRows: 2, maxRows: 6 }} />
|
||||||
|
</div>
|
||||||
|
</ProfileDetailsWrapper>
|
||||||
|
|
||||||
</Modal>
|
</Modal>
|
||||||
</ProfileWrapper>
|
</ProfileWrapper>
|
||||||
);
|
);
|
||||||
|
@ -204,4 +204,24 @@ export const EditFooter = styled.div`
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
export const ProfileDetailsWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ProfileImageWrapper = styled.div`
|
||||||
|
position: relative;
|
||||||
|
height: 256px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
import { Input } from 'antd';
|
|
||||||
import { ProfileDetailsWrapper } from './ProfileDetails.styled';
|
|
||||||
|
|
||||||
export function ProfileDetails({ state, actions }) {
|
|
||||||
return (
|
|
||||||
<ProfileDetailsWrapper>
|
|
||||||
<div class="info">
|
|
||||||
<Input placeholder="Name" spellCheck="false" onChange={(e) => actions.setEditName(e.target.value)}
|
|
||||||
defaultValue={state.editName} autocapitalize="word" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<Input placeholder="Location" spellCheck="false" onChange={(e) => actions.setEditLocation(e.target.value)}
|
|
||||||
defaultValue={state.editLocation} autocapitalize="word" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<Input.TextArea placeholder="Description" onChange={(e) => actions.setEditDescription(e.target.value)}
|
|
||||||
spellCheck="false" defaultValue={state.editDescription} autoSize={{ minRows: 2, maxRows: 6 }} />
|
|
||||||
</div>
|
|
||||||
</ProfileDetailsWrapper>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
export const ProfileDetailsWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.info {
|
|
||||||
width: 100%;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
import { useState, useCallback } from 'react';
|
|
||||||
import Cropper from 'react-easy-crop'
|
|
||||||
import { ProfileImageWrapper } from './ProfileImage.styled';
|
|
||||||
|
|
||||||
export function ProfileImage({ state, actions }) {
|
|
||||||
|
|
||||||
const [crop, setCrop] = useState({ x: 0, y: 0 })
|
|
||||||
const [zoom, setZoom] = useState(1)
|
|
||||||
|
|
||||||
const onCropComplete = useCallback((area, crop) => {
|
|
||||||
actions.setEditImageCrop(crop.width, crop.height, crop.x, crop.y)
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ProfileImageWrapper>
|
|
||||||
<Cropper image={state.editImage} crop={crop} zoom={zoom} aspect={1}
|
|
||||||
onCropChange={setCrop} onCropComplete={onCropComplete} onZoomChange={setZoom} />
|
|
||||||
</ProfileImageWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
export const ProfileImageWrapper = styled.div`
|
|
||||||
position: relative;
|
|
||||||
height: 256px;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
`;
|
|
||||||
|
|
@ -7,9 +7,6 @@ import avatar from 'images/avatar.png';
|
|||||||
export function useProfile() {
|
export function useProfile() {
|
||||||
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
init: false,
|
|
||||||
editProfileImage: false,
|
|
||||||
editProfileDetails: false,
|
|
||||||
handle: null,
|
handle: null,
|
||||||
name: null,
|
name: null,
|
||||||
location: null,
|
location: null,
|
||||||
@ -18,10 +15,14 @@ export function useProfile() {
|
|||||||
editName: null,
|
editName: null,
|
||||||
editLocation: null,
|
editLocation: null,
|
||||||
editDescription: null,
|
editDescription: null,
|
||||||
crop: { w: 0, h: 0, x: 0, y: 0 },
|
editProfileImage: false,
|
||||||
|
editProfileDetails: false,
|
||||||
|
clip: { w: 0, h: 0, x: 0, y: 0 },
|
||||||
|
|
||||||
|
crop: { x: 0, y: 0},
|
||||||
|
zoom: 1,
|
||||||
|
|
||||||
busy: false,
|
busy: false,
|
||||||
searchable: null,
|
|
||||||
checked: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const IMAGE_DIM = 256;
|
const IMAGE_DIM = 256;
|
||||||
@ -35,17 +36,17 @@ export function useProfile() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (profile.state.identity.guid) {
|
if (profile.state.identity.guid) {
|
||||||
const { node, name, handle, location, description, image } = profile.state.identity;
|
const { node, name, handle, location, description, image, imageUrl } = profile.state.identity;
|
||||||
let url = !image ? null : profile.state.imageUrl;
|
let url = !image ? null : profile.state.imageUrl;
|
||||||
let editImage = !image ? avatar : url;
|
let editImage = !image ? avatar : url;
|
||||||
updateState({ init: true, name, location, description, node, handle, url,
|
updateState({ name, location, description, node, handle, url,
|
||||||
editName: name, editLocation: location, editDescription: description, editHandle: handle, editImage });
|
editName: name, editLocation: location, editDescription: description, editHandle: handle, editImage });
|
||||||
}
|
}
|
||||||
}, [profile]);
|
}, [profile.state]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
updateState({ display: viewport.state.display });
|
updateState({ display: viewport.state.display });
|
||||||
}, [viewport]);
|
}, [viewport.state]);
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
logout: app.actions.logout,
|
logout: app.actions.logout,
|
||||||
@ -65,7 +66,7 @@ export function useProfile() {
|
|||||||
updateState({ editProfileDetails: false });
|
updateState({ editProfileDetails: false });
|
||||||
},
|
},
|
||||||
setEditImageCrop: (w, h, x, y) => {
|
setEditImageCrop: (w, h, x, y) => {
|
||||||
updateState({ crop: { w, h, x, y }});
|
updateState({ clip: { w, h, x, y }});
|
||||||
},
|
},
|
||||||
setEditName: (editName) => {
|
setEditName: (editName) => {
|
||||||
updateState({ editName });
|
updateState({ editName });
|
||||||
@ -76,6 +77,12 @@ export function useProfile() {
|
|||||||
setEditDescription: (editDescription) => {
|
setEditDescription: (editDescription) => {
|
||||||
updateState({ editDescription });
|
updateState({ editDescription });
|
||||||
},
|
},
|
||||||
|
setCrop: (crop) => {
|
||||||
|
updateState({ crop });
|
||||||
|
},
|
||||||
|
setZoom: (zoom) => {
|
||||||
|
updateState({ zoom });
|
||||||
|
},
|
||||||
setProfileImage: async () => {
|
setProfileImage: async () => {
|
||||||
if(!state.busy) {
|
if(!state.busy) {
|
||||||
updateState({ busy: true });
|
updateState({ busy: true });
|
||||||
@ -89,7 +96,7 @@ export function useProfile() {
|
|||||||
canvas.width = IMAGE_DIM;
|
canvas.width = IMAGE_DIM;
|
||||||
canvas.height = IMAGE_DIM;
|
canvas.height = IMAGE_DIM;
|
||||||
context.imageSmoothingQuality = "medium";
|
context.imageSmoothingQuality = "medium";
|
||||||
context.drawImage(img, state.crop.x, state.crop.y, state.crop.w, state.crop.h,
|
context.drawImage(img, state.clip.x, state.clip.y, state.clip.w, state.clip.h,
|
||||||
0, 0, IMAGE_DIM, IMAGE_DIM);
|
0, 0, IMAGE_DIM, IMAGE_DIM);
|
||||||
resolve(canvas.toDataURL());
|
resolve(canvas.toDataURL());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user