From 3fdc53715a51bf9c640adbfab5e7a03278e0d7c7 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Wed, 23 Mar 2022 14:28:07 -0700 Subject: [PATCH] adding profile image selector --- net/web/package.json | 1 + net/web/src/User/Profile/Profile.jsx | 48 ++++++++++++++----- net/web/src/User/Profile/Profile.styled.js | 10 ++++ .../Profile/ProfileImage/ProfileImage.jsx | 33 +++++++++++++ .../ProfileImage/ProfileImage.styled.js | 25 ++++++++++ net/web/src/User/Profile/useProfile.hook.js | 6 +++ net/web/yarn.lock | 18 +++++++ 7 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 net/web/src/User/Profile/ProfileImage/ProfileImage.jsx create mode 100644 net/web/src/User/Profile/ProfileImage/ProfileImage.styled.js diff --git a/net/web/package.json b/net/web/package.json index 2600e485..45b580ab 100644 --- a/net/web/package.json +++ b/net/web/package.json @@ -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", diff --git a/net/web/src/User/Profile/Profile.jsx b/net/web/src/User/Profile/Profile.jsx index e9883f58..2415084d 100644 --- a/net/web/src/User/Profile/Profile.jsx +++ b/net/web/src/User/Profile/Profile.jsx @@ -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 } + return } 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 = ( + + selected(e)} style={{display: 'none'}}/> +
+ +
+ + +
+ ); + return (
@@ -53,8 +80,8 @@ export function Profile(props) { actions.close()} icon={} />
-
- +
setLogoVisible(true)}> +
@@ -66,16 +93,13 @@ export function Profile(props) {
- onProfileSave()} - onCancel={() => setInfoVisible(false)} - > + onProfileSave()} onCancel={() => setInfoVisible(false)}> + + + ) } diff --git a/net/web/src/User/Profile/Profile.styled.js b/net/web/src/User/Profile/Profile.styled.js index dd4e5662..c2fd62e0 100644 --- a/net/web/src/User/Profile/Profile.styled.js +++ b/net/web/src/User/Profile/Profile.styled.js @@ -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; diff --git a/net/web/src/User/Profile/ProfileImage/ProfileImage.jsx b/net/web/src/User/Profile/ProfileImage/ProfileImage.jsx new file mode 100644 index 00000000..4eaa604a --- /dev/null +++ b/net/web/src/User/Profile/ProfileImage/ProfileImage.jsx @@ -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 + } + return <> + } + + const onSelect = () => { + console.log("ON SELECT"); + } + + return ( + + onSelect()} image={state.modalImage} crop={crop} zoom={zoom} aspect={1} + onCropChange={setCrop} onCropComplete={onCropComplete} onZoomChange={setZoom} /> + + + ) +} diff --git a/net/web/src/User/Profile/ProfileImage/ProfileImage.styled.js b/net/web/src/User/Profile/ProfileImage/ProfileImage.styled.js new file mode 100644 index 00000000..416a02a0 --- /dev/null +++ b/net/web/src/User/Profile/ProfileImage/ProfileImage.styled.js @@ -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; +`; + diff --git a/net/web/src/User/Profile/useProfile.hook.js b/net/web/src/User/Profile/useProfile.hook.js index 400e9f4c..b99a501c 100644 --- a/net/web/src/User/Profile/useProfile.hook.js +++ b/net/web/src/User/Profile/useProfile.hook.js @@ -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 }); diff --git a/net/web/yarn.lock b/net/web/yarn.lock index cc6add26..9483ef5c 100644 --- a/net/web/yarn.lock +++ b/net/web/yarn.lock @@ -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"