diff --git a/packages/explorer/src/views/Browse.js b/packages/explorer/src/views/Browse.js index e45d99b..f0cb116 100644 --- a/packages/explorer/src/views/Browse.js +++ b/packages/explorer/src/views/Browse.js @@ -102,12 +102,20 @@ const Page = () => { const created = Date.now() - meta.created return (
  • -

    {humanize(created)}

    -

    {profile.memberId}

    {profile.name} ({profile.pronouns})

    + + {profile.avatar && +
    + avatar +
    }

    {profile.city} - {profile.company}

    {profile.bio}

    {profile.email} - {profile.twitter}

    +

    {profile.memberId}

    +

    {humanize(created)}

  • ) })} diff --git a/packages/profile/package.json b/packages/profile/package.json index 6c9b960..02a5d5f 100644 --- a/packages/profile/package.json +++ b/packages/profile/package.json @@ -17,6 +17,7 @@ "ethers": "5.6.8", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-image-file-resizer": "^0.4.8", "react-router-dom": "^6.2.2", "react-scripts": "5.0.0", "sass": "^1.50.0", diff --git a/packages/profile/src/index.scss b/packages/profile/src/index.scss index b5c61c9..a5e3ae8 100644 --- a/packages/profile/src/index.scss +++ b/packages/profile/src/index.scss @@ -1,3 +1,9 @@ @tailwind base; + +@layer base { + a { + @apply text-kernel-eggplant-light + } +} @tailwind components; @tailwind utilities; diff --git a/packages/profile/src/views/Profile.jsx b/packages/profile/src/views/Profile.jsx index a8fdfec..2acffca 100644 --- a/packages/profile/src/views/Profile.jsx +++ b/packages/profile/src/views/Profile.jsx @@ -8,11 +8,21 @@ import { useEffect, useReducer } from 'react' import { useNavigate } from 'react-router-dom' +import Resizer from 'react-image-file-resizer' import { Switch } from '@headlessui/react' -import { useServices, Navbar, Footer, Alert } from '@kernel/common' +import { useServices, Navbar, Footer, Alert, getUrl } from '@kernel/common' import AppConfig from 'App.config' +const AVATAR_CONFIG = { + maxHeight: 500, + maxWidth: 500, + format: 'PNG', + quality: 100, // maximum: no compression + rotation: 0, + outputType: 'base64' +} + const FORM_INPUT = ['email', 'name', 'pronouns', 'twitter', 'city', 'company', 'bio'] // initializes state in the form: @@ -21,6 +31,7 @@ const INITIAL_FORM_KEYS = ['wallet'].concat(FORM_INPUT) const INITIAL_FORM_FIELDS_STATE = INITIAL_FORM_KEYS .reduce((acc, key) => Object.assign(acc, { [key]: '' }), {}) INITIAL_FORM_FIELDS_STATE.consent = true +INITIAL_FORM_FIELDS_STATE.avatar = null const INITIAL_FORM_SUBMISSION_STATE = { formStatus: 'clean', @@ -56,6 +67,13 @@ const reducer = (state, action) => { const change = (dispatch, type, e) => { try { const target = e.target + + if (type === 'avatar') { + onAvatarChange(dispatch, target) + target.value = null // reset so onChange will fire even for same image + return + } + const payload = target.type === 'checkbox' ? target.checked : target.value dispatch({ type, payload }) } catch (error) { @@ -63,6 +81,32 @@ const change = (dispatch, type, e) => { } } +const onAvatarChange = (dispatch, target) => { + if (target.files.length === 0) { + return + } + + const { maxHeight, maxWidth, format, quality, rotation, outputType } = AVATAR_CONFIG + + Resizer.imageFileResizer( + target.files[0], + maxWidth, + maxHeight, + format, + quality, + rotation, + (uri) => { + console.log(uri) + dispatch({ type: 'avatar', payload: uri }) + }, + outputType + ) +} + +const removeAvatar = (dispatch) => { + dispatch({ type: 'avatar', payload: null }) +} + const value = (state, type) => state[type] const save = async (state, dispatch, e) => { @@ -127,7 +171,12 @@ const ProfileAlert = ({ formStatus, errorMessage }) => { case 'submitting': return Saving your changes... case 'success': - return Your changes have been saved! + return ( + + Your changes have been saved!  + Start exploring. + + ) case 'error': return Something went wrong. {errorMessage} default: @@ -207,6 +256,64 @@ const Profile = () => { ) })} +
    + + +
    + Upload a JPEG or PNG. Recommended size is 500 x 500. +
    + +
    + {state.avatar + ? avatar + : add an image} +
    + +
    + {state.avatar && +
    + + +
    } + {!state.avatar && +
    + +
    } +
    +
    + +
    +