mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +00:00
adding profile image selector
This commit is contained in:
parent
65914d9189
commit
3fdc53715a
@ -10,6 +10,7 @@
|
||||
"base-64": "^1.0.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-easy-crop": "^4.1.4",
|
||||
"react-router-dom": "^6.2.2",
|
||||
"react-scripts": "5.0.0",
|
||||
"styled-components": "^5.3.3",
|
||||
|
@ -1,20 +1,24 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { ProfileWrapper, CloseButton } from './Profile.styled';
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { ProfileWrapper, CloseButton, ModalFooter, SelectButton } from './Profile.styled';
|
||||
import { UserOutlined, CloseOutlined, EditOutlined } from '@ant-design/icons';
|
||||
import { useProfile } from './useProfile.hook';
|
||||
import { Button, Modal } from 'antd'
|
||||
import { ProfileInfo } from './ProfileInfo/ProfileInfo';
|
||||
import { ProfileImage } from './ProfileImage/ProfileImage';
|
||||
|
||||
export function Profile(props) {
|
||||
|
||||
const [ logoVisible, setLogoVisible ] = useState(false);
|
||||
const [ infoVisible, setInfoVisible ] = useState(false);
|
||||
const { state, actions } = useProfile();
|
||||
const imageFile = useRef(null)
|
||||
|
||||
const Logo = () => {
|
||||
if (state.imageUrl != null) {
|
||||
if (state.imageUrl === '') {
|
||||
return <div class="logo"><UserOutlined /></div>
|
||||
}
|
||||
return <img class="logo" src={ state.imageUrl } alt="" />
|
||||
}
|
||||
return <></>
|
||||
}
|
||||
@ -46,6 +50,29 @@ export function Profile(props) {
|
||||
}
|
||||
}
|
||||
|
||||
const onSelectImage = () => {
|
||||
imageFile.current.click();
|
||||
};
|
||||
|
||||
const selected = (e) => {
|
||||
var reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
actions.setModalImage(reader.result);
|
||||
}
|
||||
reader.readAsDataURL(e.target.files[0]);
|
||||
}
|
||||
|
||||
const Footer = (
|
||||
<ModalFooter>
|
||||
<input type='file' id='file' ref={imageFile} onChange={e => selected(e)} style={{display: 'none'}}/>
|
||||
<div class="select">
|
||||
<Button key="select" class="select" onClick={() => onSelectImage()}>Select Image</Button>
|
||||
</div>
|
||||
<Button key="select" onClick={() => setLogoVisible(false)}>Cancel</Button>
|
||||
<Button key="save" type="primary" onClick={() => setLogoVisible(false)}>Save</Button>
|
||||
</ModalFooter>
|
||||
);
|
||||
|
||||
return (
|
||||
<ProfileWrapper>
|
||||
<div class="header">
|
||||
@ -53,8 +80,8 @@ export function Profile(props) {
|
||||
<CloseButton type="text" class="close" size={'large'} onClick={() => actions.close()} icon={<CloseOutlined />} />
|
||||
</div>
|
||||
<div class="profile">
|
||||
<div class="avatar">
|
||||
<img class="logo" src={ state.imageUrl } alt="" />
|
||||
<div class="avatar" onClick={() => setLogoVisible(true)}>
|
||||
<Logo />
|
||||
<div class="logoedit">
|
||||
<EditOutlined />
|
||||
</div>
|
||||
@ -66,16 +93,13 @@ export function Profile(props) {
|
||||
<Button type="text" onClick={() => setInfoVisible(true)} icon={<EditOutlined />} />
|
||||
</div>
|
||||
</div>
|
||||
<Modal
|
||||
title="Profile Info"
|
||||
centered
|
||||
visible={infoVisible}
|
||||
okText="Save"
|
||||
onOk={() => onProfileSave()}
|
||||
onCancel={() => setInfoVisible(false)}
|
||||
>
|
||||
<Modal title="Profile Info" centered visible={infoVisible} okText="Save"
|
||||
onOk={() => onProfileSave()} onCancel={() => setInfoVisible(false)}>
|
||||
<ProfileInfo state={state} actions={actions} />
|
||||
</Modal>
|
||||
<Modal title="Profile Image" centered visible={logoVisible} footer={Footer}>
|
||||
<ProfileImage state={state} actions={actions} />
|
||||
</Modal>
|
||||
</ProfileWrapper>
|
||||
)
|
||||
}
|
||||
|
@ -102,6 +102,16 @@ export const ProfileWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export const ModalFooter = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
.select {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
`
|
||||
|
||||
export const CloseButton = styled(Button)`
|
||||
font-size: 24px;
|
||||
color: #aaaaaa;
|
||||
|
33
net/web/src/User/Profile/ProfileImage/ProfileImage.jsx
Normal file
33
net/web/src/User/Profile/ProfileImage/ProfileImage.jsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React, { useState } from 'react';
|
||||
import Cropper from 'react-easy-crop'
|
||||
import { UserOutlined } from '@ant-design/icons';
|
||||
import { ProfileImageWrapper, ProfileDefaultImage } from './ProfileImage.styled';
|
||||
|
||||
export function ProfileImage({ state, actions }) {
|
||||
|
||||
const [crop, setCrop] = useState({ x: 0, y: 0 })
|
||||
const [zoom, setZoom] = useState(1)
|
||||
|
||||
const onCropComplete = (croppedArea, croppedAreaPixels) => {
|
||||
console.log("crop complete");
|
||||
};
|
||||
|
||||
const Logo = () => {
|
||||
if (state.modalImage == null) {
|
||||
return <ProfileDefaultImage class="logo"><UserOutlined /></ProfileDefaultImage>
|
||||
}
|
||||
return <></>
|
||||
}
|
||||
|
||||
const onSelect = () => {
|
||||
console.log("ON SELECT");
|
||||
}
|
||||
|
||||
return (
|
||||
<ProfileImageWrapper>
|
||||
<Cropper onClick={() => onSelect()} image={state.modalImage} crop={crop} zoom={zoom} aspect={1}
|
||||
onCropChange={setCrop} onCropComplete={onCropComplete} onZoomChange={setZoom} />
|
||||
<Logo />
|
||||
</ProfileImageWrapper>
|
||||
)
|
||||
}
|
25
net/web/src/User/Profile/ProfileImage/ProfileImage.styled.js
Normal file
25
net/web/src/User/Profile/ProfileImage/ProfileImage.styled.js
Normal file
@ -0,0 +1,25 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const ProfileImageWrapper = styled.div`
|
||||
position: relative;
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
export const ProfileDefaultImage = styled.div`
|
||||
width: 192px;
|
||||
height: 192px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 8px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
color: #888888;
|
||||
font-size: 6em;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
@ -14,6 +14,7 @@ export function useProfile() {
|
||||
modalName: '',
|
||||
modalLocation: '',
|
||||
modalDescription: '',
|
||||
modalImage: null,
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -36,6 +37,9 @@ export function useProfile() {
|
||||
setModalDescription: (value) => {
|
||||
updateState({ modalDescription: value });
|
||||
},
|
||||
setModalImage: (value) => {
|
||||
updateState({ modalImage: value });
|
||||
},
|
||||
setModalProfile: async () => {
|
||||
let set = false
|
||||
if(!state.modalBusy) {
|
||||
@ -58,8 +62,10 @@ export function useProfile() {
|
||||
let profile = app.state.Data.profile;
|
||||
if (profile.image != null) {
|
||||
updateState({ imageUrl: app.actions.profileImageUrl() })
|
||||
updateState({ modalImage: app.actions.profileImageUrl() })
|
||||
} else {
|
||||
updateState({ imageUrl: '' })
|
||||
updateState({ modalImage: null })
|
||||
}
|
||||
updateState({ name: profile.name });
|
||||
updateState({ modalName: profile.name });
|
||||
|
@ -6187,6 +6187,11 @@ normalize-url@^6.0.1:
|
||||
resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz"
|
||||
integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
|
||||
|
||||
normalize-wheel@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
|
||||
integrity sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=
|
||||
|
||||
npm-run-path@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz"
|
||||
@ -7630,6 +7635,14 @@ react-dom@^17.0.2:
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react-easy-crop@^4.1.4:
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/react-easy-crop/-/react-easy-crop-4.1.4.tgz#71543f7156f038b37bc45c4b7eb141173e623d38"
|
||||
integrity sha512-Gw07jxdeJAGQAFybyNa2HYzviNjNJ3lyNTEApbA0zHcZ9N8f77iH3w1dEB5PbxbrG+LXvxFmMPNgMBoDpz27tQ==
|
||||
dependencies:
|
||||
normalize-wheel "^1.0.1"
|
||||
tslib "2.0.1"
|
||||
|
||||
react-error-overlay@^6.0.10:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz"
|
||||
@ -8738,6 +8751,11 @@ tsconfig-paths@^3.12.0:
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
|
||||
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
|
||||
|
||||
tslib@^1.8.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user