Linting fixes

This commit is contained in:
Frank Johnson
2021-09-12 12:42:22 -04:00
parent 690d45ff9a
commit 74a5f9bf2c
12 changed files with 382 additions and 310 deletions

View File

@@ -95,16 +95,17 @@ const IdeHeader = ({
<div /> <div />
)} )}
<div className="text-gray-200 grid grid-flow-col-dense gap-4 mr-4 items-center"> <div className="text-gray-200 grid grid-flow-col-dense gap-4 mr-4 items-center">
{ (!children) {!children ? (
? <DefaultTopButtons <DefaultTopButtons
project={project} project={project}
projectTitle={projectTitle} projectTitle={projectTitle}
_projectOwner={_projectOwner} _projectOwner={_projectOwner}
handleRender={handleRender} handleRender={handleRender}
canEdit={canEdit} canEdit={canEdit}
/> />
: children ) : (
} children
)}
{/* <TopButton>Fork</TopButton> */} {/* <TopButton>Fork</TopButton> */}
<div className="h-8 w-8"> <div className="h-8 w-8">
<NavPlusButton /> <NavPlusButton />
@@ -117,88 +118,95 @@ const IdeHeader = ({
export default IdeHeader export default IdeHeader
function DefaultTopButtons({
function DefaultTopButtons({ project, projectTitle, _projectOwner, handleRender, canEdit }) { project,
return (<> projectTitle,
{canEdit && !projectTitle && ( _projectOwner,
<CaptureButton handleRender,
canEdit={canEdit} canEdit,
projectTitle={project?.title} }) {
userName={project?.user?.userName} return (
shouldUpdateImage={!project?.mainImage} <>
TheButton={({ onClick }) => ( {canEdit && !projectTitle && (
<TopButton <CaptureButton
onClick={onClick} canEdit={canEdit}
name="Save Project Image" projectTitle={project?.title}
className=" bg-ch-blue-650 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300" userName={project?.user?.userName}
> shouldUpdateImage={!project?.mainImage}
<Svg name="camera" className="w-6 h-6 text-ch-blue-400" /> TheButton={({ onClick }) => (
</TopButton> <TopButton
)} onClick={onClick}
/> name="Save Project Image"
)} className=" bg-ch-blue-650 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300"
{!projectTitle && ( >
<TopButton <Svg name="camera" className="w-6 h-6 text-ch-blue-400" />
className="bg-ch-pink-800 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300" </TopButton>
onClick={handleRender} )}
name={canEdit ? 'Save' : 'Preview'}
>
<Svg
name={canEdit ? 'floppy-disk' : 'photograph'}
className="w-6 h-6 text-ch-pink-500"
/> />
</TopButton> )}
)} {!projectTitle && (
{projectTitle && ( <TopButton
<TopButton className="bg-ch-pink-800 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300"
className="bg-ch-pink-800 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300" onClick={handleRender}
onClick={() => name={canEdit ? 'Save' : 'Preview'}
navigate(routes.ide({ userName: _projectOwner, projectTitle })) >
} <Svg
name="Editor" name={canEdit ? 'floppy-disk' : 'photograph'}
> className="w-6 h-6 text-ch-pink-500"
<Svg name="terminal" className="w-6 h-6 text-ch-pink-500" /> />
</TopButton> </TopButton>
)} )}
<Popover className="relative outline-none w-full h-full"> {projectTitle && (
{({ open }) => { <TopButton
return ( className="bg-ch-pink-800 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300"
<> onClick={() =>
<Popover.Button className="h-full w-full outline-none"> navigate(routes.ide({ userName: _projectOwner, projectTitle }))
<TopButton }
Tag="div" name="Editor"
name="Share" >
className=" bg-ch-purple-400 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300" <Svg name="terminal" className="w-6 h-6 text-ch-pink-500" />
> </TopButton>
<Svg )}
name="share" <Popover className="relative outline-none w-full h-full">
className="w-6 h-6 text-ch-purple-500 mt-1" {({ open }) => {
/> return (
</TopButton> <>
</Popover.Button> <Popover.Button className="h-full w-full outline-none">
{open && ( <TopButton
<Popover.Panel className="absolute z-10 mt-4 right-0"> Tag="div"
<Tabs name="Share"
className="bg-ch-purple-gray-200 rounded-md shadow-md overflow-hidden text-gray-700" className=" bg-ch-purple-400 bg-opacity-30 hover:bg-opacity-80 text-ch-gray-300"
selectedTabClassName="bg-ch-gray-700 text-white"
> >
<TabPanel> <Svg
<FullScriptEncoding /> name="share"
</TabPanel> className="w-6 h-6 text-ch-purple-500 mt-1"
<TabPanel> />
<ExternalScript /> </TopButton>
</TabPanel> </Popover.Button>
{open && (
<Popover.Panel className="absolute z-10 mt-4 right-0">
<Tabs
className="bg-ch-purple-gray-200 rounded-md shadow-md overflow-hidden text-gray-700"
selectedTabClassName="bg-ch-gray-700 text-white"
>
<TabPanel>
<FullScriptEncoding />
</TabPanel>
<TabPanel>
<ExternalScript />
</TabPanel>
<TabList className="flex whitespace-nowrap text-gray-700 border-t border-gray-700"> <TabList className="flex whitespace-nowrap text-gray-700 border-t border-gray-700">
<Tab className="p-3 px-5">encoded script</Tab> <Tab className="p-3 px-5">encoded script</Tab>
<Tab className="p-3 px-5">external script</Tab> <Tab className="p-3 px-5">external script</Tab>
</TabList> </TabList>
</Tabs> </Tabs>
</Popover.Panel> </Popover.Panel>
)} )}
</> </>
) )
}} }}
</Popover> </Popover>
</>) </>
)
} }

View File

@@ -11,17 +11,24 @@ import Svg from 'src/components/Svg'
const CLOUDINARY_UPLOAD_PRESET = 'CadHub_project_images' const CLOUDINARY_UPLOAD_PRESET = 'CadHub_project_images'
const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/irevdev/upload' const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/irevdev/upload'
export function ImageFallback({ width = 100, imageId = 'CadHub/eia1kwru54g2kf02s2xx', className = '' }) { export function ImageFallback({
width = 100,
imageId = 'CadHub/eia1kwru54g2kf02s2xx',
className = '',
}) {
return ( return (
<div className="relative overflow-hidden w-full h-full"> <div className="relative overflow-hidden w-full h-full">
<CloudinaryImage <CloudinaryImage
className={"object-cover w-full h-full shadow overflow-hidden " + className } className={
cloudName="irevdev" 'object-cover w-full h-full shadow overflow-hidden ' + className
publicId={imageId} }
width={width} cloudName="irevdev"
crop="scale" publicId={imageId}
/> width={width}
</div>) crop="scale"
/>
</div>
)
} }
export default function ImageUploader({ export default function ImageUploader({
@@ -82,10 +89,7 @@ export default function ImageUploader({
{cloudinaryId && isEditable && ( {cloudinaryId && isEditable && (
<button className="w-full py-1 absolute z-10 bg-ch-blue-650 bg-opacity-50 hover:bg-opacity-80 bottom-0 right-0 left-0 flex items-center justify-center text-ch-gray-300"> <button className="w-full py-1 absolute z-10 bg-ch-blue-650 bg-opacity-50 hover:bg-opacity-80 bottom-0 right-0 left-0 flex items-center justify-center text-ch-gray-300">
<span className="font-fira-code text-sm leading-4">Update</span> <span className="font-fira-code text-sm leading-4">Update</span>
<Svg <Svg name="pencil-solid" className=" h-4 w-4 ml-4 mb-2" />
name="pencil-solid"
className=" h-4 w-4 ml-4 mb-2"
/>
</button> </button>
)} )}
{isEditable && <input {...getInputProps()} />} {isEditable && <input {...getInputProps()} />}

View File

@@ -12,43 +12,46 @@ interface KeyValueType {
} }
const KeyValue = ({ const KeyValue = ({
keyName, keyName,
children, children,
hide = false, hide = false,
canEdit = false, canEdit = false,
onEdit, onEdit,
isEditable = false, isEditable = false,
bottom = false, bottom = false,
className = "", className = '',
} : KeyValueType) => { }: KeyValueType) => {
if (!children || hide) return null if (!children || hide) return null
return ( return (
<div className={"flex flex-col " + className}> <div className={'flex flex-col ' + className}>
<div className={"text-ch-blue-400 font-fira-code flex items-center leading-4 text-sm whitespace-nowrap " + (bottom ? "order-2" : "")}> <div
<span className={isEditable ? "text-ch-blue-300" : ""}>{keyName}</span> className={
{canEdit && 'text-ch-blue-400 font-fira-code flex items-center leading-4 text-sm whitespace-nowrap ' +
(isEditable ? ( (bottom ? 'order-2' : '')
<button }
className="font-fira-sans text-ch-gray-300 items-center ml-4 grid grid-flow-col-dense p-px px-2 gap-2 bg-ch-blue-500 bg-opacity-50 hover:bg-opacity-70 rounded-sm" >
id="rename-button" <span className={isEditable ? 'text-ch-blue-300' : ''}>{keyName}</span>
onClick={onEdit} {canEdit &&
> (isEditable ? (
<Svg <button
name="check" className="font-fira-sans text-ch-gray-300 items-center ml-4 grid grid-flow-col-dense p-px px-2 gap-2 bg-ch-blue-500 bg-opacity-50 hover:bg-opacity-70 rounded-sm"
className="w-6 h-6" id="rename-button"
strokeWidth={3} onClick={onEdit}
/> >
<span>Update</span> <Svg name="check" className="w-6 h-6" strokeWidth={3} />
</button> <span>Update</span>
) : ( </button>
<button onClick={onEdit}> ) : (
<Svg name="pencil-solid" className="h-4 w-4 ml-4 mb-2" /> <button onClick={onEdit}>
</button> <Svg name="pencil-solid" className="h-4 w-4 ml-4 mb-2" />
))} </button>
</div> ))}
<div className={"text-ch-gray-300 " + (bottom ? "mb-1" : "mt-1")}>{children}</div>
</div> </div>
) <div className={'text-ch-gray-300 ' + (bottom ? 'mb-1' : 'mt-1')}>
} {children}
</div>
</div>
)
}
export default KeyValue export default KeyValue

View File

@@ -52,7 +52,11 @@ const NavPlusButton: React.FC = () => {
' px-4 py-1 my-4 bg-opacity-30 hover:bg-opacity-70 grid grid-flow-col-dense items-center gap-2' ' px-4 py-1 my-4 bg-opacity-30 hover:bg-opacity-70 grid grid-flow-col-dense items-center gap-2'
} }
> >
<div className={dotClasses + " justify-self-center w-5 h-5 rounded-full"}></div> <div
className={
dotClasses + ' justify-self-center w-5 h-5 rounded-full'
}
></div>
<Link to={routes.draftProject({ cadPackage: ideType })}> <Link to={routes.draftProject({ cadPackage: ideType })}>
<div>{name}</div> <div>{name}</div>
<div className="text-xs text-ch-gray-400 font-light">{sub}</div> <div className="text-xs text-ch-gray-400 font-light">{sub}</div>

View File

@@ -46,7 +46,8 @@ const ProfileSlashLogin = () => {
<Popover className="relative outline-none h-8 w-8"> <Popover className="relative outline-none h-8 w-8">
<Popover.Button <Popover.Button
disabled={!isAuthenticated || !currentUser} disabled={!isAuthenticated || !currentUser}
className="h-full w-full outline-none border-ch-gray-400 border-2 rounded-full"> className="h-full w-full outline-none border-ch-gray-400 border-2 rounded-full"
>
{!loading && ( {!loading && (
<ImageFallback <ImageFallback
width={80} width={80}
@@ -55,8 +56,8 @@ const ProfileSlashLogin = () => {
/> />
)} )}
</Popover.Button> </Popover.Button>
{ currentUser && ( {currentUser && (
<Popover.Panel className="w-48 absolute z-10 right-0 bg-ch-gray-700 mt-4 px-3 py-2 rounded shadow-md overflow-hidden text-ch-gray-300"> <Popover.Panel className="w-48 absolute z-10 right-0 bg-ch-gray-700 mt-4 px-3 py-2 rounded shadow-md overflow-hidden text-ch-gray-300">
<Link to={routes.user({ userName: user?.userName })}> <Link to={routes.user({ userName: user?.userName })}>
<h3 className="text-lg hover:text-ch-pink-300"> <h3 className="text-lg hover:text-ch-pink-300">
Hello {user?.name} Hello {user?.name}
@@ -65,14 +66,18 @@ const ProfileSlashLogin = () => {
<hr className="my-2" /> <hr className="my-2" />
<Link <Link
className="my-2 mt-4 block hover:text-ch-pink-300" className="my-2 mt-4 block hover:text-ch-pink-300"
to={routes.user({ userName: user?.userName })}> to={routes.user({ userName: user?.userName })}
>
<div>View Your Profile</div> <div>View Your Profile</div>
</Link> </Link>
<a href="#" onClick={logOut} <a
className="text-ch-gray-400 hover:text-ch-pink-300"> href="#"
onClick={logOut}
className="text-ch-gray-400 hover:text-ch-pink-300"
>
Logout Logout
</a> </a>
</Popover.Panel> </Popover.Panel>
)} )}
</Popover> </Popover>
) : ( ) : (

View File

@@ -34,7 +34,7 @@ const ProjectCard = ({ title, mainImage, user, Reaction, cadPackage }) => (
<div className="w-8 h-8 overflow-hidden rounded-full border border-ch-gray-300 shadow"> <div className="w-8 h-8 overflow-hidden rounded-full border border-ch-gray-300 shadow">
<ImageFallback <ImageFallback
imageId={user?.image} // http://res.cloudinary.com/irevdev/image/upload/c_scale,w_50/v1/CadHub/bc7smqwo9qqmrloyf9xr imageId={user?.image} // http://res.cloudinary.com/irevdev/image/upload/c_scale,w_50/v1/CadHub/bc7smqwo9qqmrloyf9xr
width={80} // http://res.cloudinary.com/irevdev/image/upload/c_scale,w_300/v1/CadHub/bc7smqwo9qqmrloyf9xr width={80} // http://res.cloudinary.com/irevdev/image/upload/c_scale,w_300/v1/CadHub/bc7smqwo9qqmrloyf9xr
/> />
</div> </div>
<div className="ml-3 text-lg text-ch-gray-300 font-fira-sans"> <div className="ml-3 text-lg text-ch-gray-300 font-fira-sans">

View File

@@ -257,4 +257,3 @@ const ProjectProfile = ({
} }
export default ProjectProfile export default ProjectProfile

View File

@@ -4,18 +4,24 @@ import { Link, navigate, routes } from '@redwoodjs/router'
import ProjectsOfUser from 'src/components/ProjectsOfUserCell' import ProjectsOfUser from 'src/components/ProjectsOfUserCell'
import IdeHeader from 'src/components/IdeHeader/IdeHeader' import IdeHeader from 'src/components/IdeHeader/IdeHeader'
import Svg from 'src/components/Svg/Svg' import Svg from 'src/components/Svg/Svg'
import { fieldsConfig, fieldReducer, UserProfileType, FieldConfigType } from './userProfileConfig' import {
fieldsConfig,
fieldReducer,
UserProfileType,
FieldConfigType,
} from './userProfileConfig'
function buildFieldsConfig(fieldsConfig, user) { function buildFieldsConfig(fieldsConfig, user) {
Object.entries(fieldsConfig).forEach(([key, field] : [string, FieldConfigType]) => { Object.entries(fieldsConfig).forEach(
field.currentValue = field.newValue = user[key] ([key, field]: [string, FieldConfigType]) => {
field.name = key field.currentValue = field.newValue = user[key]
}) field.name = key
}
)
return fieldsConfig return fieldsConfig
} }
const UserProfile = ({ const UserProfile = ({
user, user,
isEditable, isEditable,
@@ -23,11 +29,13 @@ const UserProfile = ({
onSave, onSave,
error, error,
projects, projects,
} : UserProfileType) => { }: UserProfileType) => {
const { currentUser } = useAuth() const { currentUser } = useAuth()
const hasEditPermission = currentUser?.sub === user.id const hasEditPermission = currentUser?.sub === user.id
useEffect(() => { useEffect(() => {
isEditable && !hasEditPermission && navigate(routes.user({ userName: user.userName })) isEditable &&
!hasEditPermission &&
navigate(routes.user({ userName: user.userName }))
}, [currentUser]) }, [currentUser])
const initializedFields = buildFieldsConfig(fieldsConfig, user) const initializedFields = buildFieldsConfig(fieldsConfig, user)
@@ -49,7 +57,6 @@ const UserProfile = ({
projectOwnerImage={user?.image} projectOwnerImage={user?.image}
projectOwnerId={user?.id} projectOwnerId={user?.id}
> >
<span></span> <span></span>
</IdeHeader> </IdeHeader>
</div> </div>
@@ -95,14 +102,14 @@ const UserProfile = ({
/> />
</div> </div>
<div className="my-5"> <div className="my-5">
<fields.createdAt.component <fields.createdAt.component field={fields.createdAt} />
field={fields.createdAt}
/>
</div> </div>
</section> </section>
{/* Viewer */} {/* Viewer */}
<div className="py-10 px-8 w-full h-full relative bg-ch-gray-800 md:overflow-y-auto ch-scrollbar"> <div className="py-10 px-8 w-full h-full relative bg-ch-gray-800 md:overflow-y-auto ch-scrollbar">
<h3 className="text-2xl text-ch-gray-500 mb-4 md:hidden">Projects</h3> <h3 className="text-2xl text-ch-gray-500 mb-4 md:hidden">
Projects
</h3>
<ProjectsOfUser userName={user?.userName} /> <ProjectsOfUser userName={user?.userName} />
</div> </div>
</div> </div>

View File

@@ -5,149 +5,187 @@ import Editor from 'rich-markdown-editor'
import ImageUploader from 'src/components/ImageUploader' import ImageUploader from 'src/components/ImageUploader'
import { User } from 'types/graphql' import { User } from 'types/graphql'
export interface UserProfileType { export interface UserProfileType {
user: User, user: User
isEditable: boolean, isEditable: boolean
loading: boolean, loading: boolean
error: boolean, error: boolean
onSave: Function, onSave: Function
projects: {}[], projects: {}[]
} }
export interface FieldConfigType { export interface FieldConfigType {
name?: string, // introspection ugh name?: string // introspection ugh
editable: boolean, editable: boolean
component?: ReactNode, component?: ReactNode
needsRef?: boolean, needsRef?: boolean
isEditing?: boolean | undefined, isEditing?: boolean | undefined
onSave?: Function, onSave?: Function
currentValue?: any, currentValue?: any
newValue?: any, newValue?: any
} }
const ProfileKeyValue = ({ field, dispatch, user, save, hasEditPermission, children, bottom = false }) => { const ProfileKeyValue = ({
field,
dispatch,
user,
save,
hasEditPermission,
children,
bottom = false,
}) => {
return (
<KeyValue
keyName={field.name}
hide={!user[field.name] && !hasEditPermission}
canEdit={hasEditPermission}
onEdit={() => {
if (field.isEditing) {
save(user.userName, { [field.name]: field.newValue })
}
dispatch({
type: 'SET_CURRENT_VALUE',
payload: { field: field.name, value: field.newValue },
})
dispatch({ type: 'TOGGLE_EDITING', payload: field.name })
}}
isEditable={hasEditPermission && field.isEditing}
bottom={bottom}
className="mb-4"
>
{children}
</KeyValue>
)
}
const bioField: FieldConfigType = {
editable: true,
needsRef: true,
component: (props) => {
const ref = useRef(null)
const { dispatch, field } = props
return ( return (
<KeyValue <ProfileKeyValue {...props}>
keyName={field.name} <div
hide={!user[field.name] && !hasEditPermission} id="bio-wrap"
canEdit={hasEditPermission} name="bio"
onEdit={() => { className={
if (field.isEditing) { 'markdown-overrides rounded-sm pb-2 mt-2' +
save(user.userName, { [field.name]: field.newValue }) (field.isEditable ? ' min-h-md' : '')
} }
dispatch({ type: "SET_CURRENT_VALUE", payload: { field: field.name, value: field.newValue }}) onClick={(e) =>
dispatch({ type: "TOGGLE_EDITING", payload: field.name }) e?.target?.id === 'bio-wrap' && ref?.current?.focusAtEnd()
}} }
isEditable={hasEditPermission && field.isEditing} >
bottom={bottom} <Editor
className="mb-4" ref={ref}
> defaultValue={field?.currentValue || ''}
{ children } readOnly={!field.isEditing}
onChange={(bio) =>
dispatch({
type: 'SET_NEW_VALUE',
payload: { field: field.bio, value: bio() },
})
}
/>
</div>
</ProfileKeyValue>
)
},
}
const createdAtField: FieldConfigType = {
editable: false,
component: (props) => {
const { field } = props
return (
<KeyValue keyName="Member Since">
<p className="text-ch-gray-300">
{new Date(field.currentValue).toLocaleDateString()}
</p>
</KeyValue> </KeyValue>
) )
} },
}
const bioField : FieldConfigType = { const imageField: FieldConfigType = {
editable: true, editable: true,
needsRef: true, component: (props) => {
component: (props) => { const { field, user, save, hasEditPermission } = props
const ref = useRef(null) return (
<ImageUploader
className="rounded-3xl rounded-tr-none shadow-md border-2 border-ch-gray-300"
onImageUpload={({ cloudinaryPublicId: image }) => {
save(user.userName, {
image,
})
}}
aspectRatio={1}
isEditable={hasEditPermission && !field.isEditing}
imageUrl={user.image}
width={300}
/>
)
},
}
const { dispatch, field } = props const nameField: FieldConfigType = {
editable: true,
component: (props) => {
const { user, dispatch, field } = props
return <ProfileKeyValue {...props}> return (
<div <ProfileKeyValue {...props} bottom={true}>
id="bio-wrap" {!field.isEditing ? (
name="bio" <h1 className="text-4xl">{user?.name}</h1>
className={ ) : (
'markdown-overrides rounded-sm pb-2 mt-2' + <InputText
(field.isEditable ? ' min-h-md' : '') className="text-xl"
value={field.newValue}
onChange={({ target: { value } }) =>
dispatch({
type: 'SET_NEW_VALUE',
payload: { field: field.name, value },
})
} }
onClick={(e) => isEditable={!field.isEditable}
e?.target?.id === 'bio-wrap' && />
ref?.current?.focusAtEnd() )}
</ProfileKeyValue>
)
},
}
const userNameField: FieldConfigType = {
editable: true,
component: (props) => {
const { dispatch, field } = props
return (
<ProfileKeyValue {...props} bottom={true}>
{!field.isEditing ? (
<h2 className="text-ch-gray-400">
@{field?.currentValue?.replace(/([^a-zA-Z\d_:])/g, '-')}
</h2>
) : (
<InputText
className="text-xl"
value={field.newValue}
onChange={({ target: { value } }) =>
dispatch({
type: 'SET_NEW_VALUE',
payload: { field: field.name, value },
})
} }
> isEditable={!field.isEditable}
<Editor />
ref={ref} )}
defaultValue={field?.currentValue || ''} </ProfileKeyValue>
readOnly={!field.isEditing} )
onChange={(bio) => dispatch({ type: "SET_NEW_VALUE", payload: { field: field.bio, value: bio() }})} },
/>
</div>
</ProfileKeyValue>
},
}
const createdAtField : FieldConfigType = {
editable: false,
component: (props) => {
const { field } = props
return <KeyValue keyName="Member Since">
<p className="text-ch-gray-300">{ new Date(field.currentValue).toLocaleDateString() }</p>
</KeyValue>
},
}
const imageField : FieldConfigType = {
editable: true,
component: (props) => {
const { field, user, save, hasEditPermission } = props
return (
<ImageUploader
className="rounded-3xl rounded-tr-none shadow-md border-2 border-ch-gray-300"
onImageUpload={({ cloudinaryPublicId: image }) => {
save(user.userName, {
image,
})
}}
aspectRatio={1}
isEditable={hasEditPermission && !field.isEditing}
imageUrl={user.image}
width={300}
/>
)
},
}
const nameField : FieldConfigType = {
editable: true,
component: (props) => {
const { user, dispatch, field } = props
return <ProfileKeyValue {...props} bottom={true}>
{ (!field.isEditing)
? <h1 className="text-4xl">{ user?.name }</h1>
: <InputText
className="text-xl"
value={field.newValue}
onChange={({ target: { value } }) => dispatch({ type: "SET_NEW_VALUE", payload: { field: field.name, value }})}
isEditable={!field.isEditable}
/>
}
</ProfileKeyValue>
},
}
const userNameField : FieldConfigType = {
editable: true,
component: (props) => {
const { dispatch, field } = props
return <ProfileKeyValue {...props} bottom={true}>
{ (!field.isEditing)
? <h2 className="text-ch-gray-400">@{ field?.currentValue?.replace(/([^a-zA-Z\d_:])/g, '-') }</h2>
: <InputText
className="text-xl"
value={field.newValue}
onChange={({ target: { value } }) => dispatch({ type: "SET_NEW_VALUE", payload: { field: field.name, value }})}
isEditable={!field.isEditable}
/>
}
</ProfileKeyValue>
},
} }
export const fieldsConfig = { export const fieldsConfig = {
@@ -166,21 +204,24 @@ export const fieldsConfig = {
export function fieldReducer(state, action) { export function fieldReducer(state, action) {
switch (action.type) { switch (action.type) {
case "TOGGLE_EDITING": case 'TOGGLE_EDITING':
return { return {
...state, ...state,
[action.payload]: { [action.payload]: {
...state[action.payload], ...state[action.payload],
isEditing: (state[action.payload].editable && !state[action.payload].isEditing) ? true : false, isEditing:
} state[action.payload].editable && !state[action.payload].isEditing
? true
: false,
},
} }
case "SET_NEW_VALUE": case 'SET_NEW_VALUE':
const newState = { const newState = {
...state, ...state,
[action.payload.field]: { [action.payload.field]: {
...state[action.payload.field], ...state[action.payload.field],
newValue: action.payload.value, newValue: action.payload.value,
} },
} }
return newState return newState
default: default:

View File

@@ -135,7 +135,8 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => {
<Popover className="relative outline-none w-full h-full"> <Popover className="relative outline-none w-full h-full">
<Popover.Button <Popover.Button
disabled={!isAuthenticated || !currentUser} disabled={!isAuthenticated || !currentUser}
className="h-full w-full outline-none border-ch-gray-400 border-2 rounded-full"> className="h-full w-full outline-none border-ch-gray-400 border-2 rounded-full"
>
{!loading && ( {!loading && (
<ImageFallback <ImageFallback
width={80} width={80}
@@ -144,8 +145,8 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => {
/> />
)} )}
</Popover.Button> </Popover.Button>
{ currentUser && ( {currentUser && (
<Popover.Panel className="w-48 absolute z-10 right-0 bg-ch-gray-700 mt-4 px-3 py-2 rounded shadow-md overflow-hidden text-ch-gray-300"> <Popover.Panel className="w-48 absolute z-10 right-0 bg-ch-gray-700 mt-4 px-3 py-2 rounded shadow-md overflow-hidden text-ch-gray-300">
<Link to={routes.user({ userName: user?.userName })}> <Link to={routes.user({ userName: user?.userName })}>
<h3 className="text-lg hover:text-ch-pink-300"> <h3 className="text-lg hover:text-ch-pink-300">
Hello {user?.name} Hello {user?.name}
@@ -154,14 +155,18 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => {
<hr className="my-2" /> <hr className="my-2" />
<Link <Link
className="my-2 mt-4 block hover:text-ch-pink-300" className="my-2 mt-4 block hover:text-ch-pink-300"
to={routes.user({ userName: user?.userName })}> to={routes.user({ userName: user?.userName })}
>
<div>View Your Profile</div> <div>View Your Profile</div>
</Link> </Link>
<a href="#" onClick={logOut} <a
className="text-ch-gray-400 hover:text-ch-pink-300"> href="#"
onClick={logOut}
className="text-ch-gray-400 hover:text-ch-pink-300"
>
Logout Logout
</a> </a>
</Popover.Panel> </Popover.Panel>
)} )}
</Popover> </Popover>
</li> </li>

View File

@@ -37,9 +37,7 @@ const AccountRecoveryPage = () => {
className="grid items-center gap-2" className="grid items-center gap-2"
style={{ gridTemplateColumns: 'auto 1fr' }} style={{ gridTemplateColumns: 'auto 1fr' }}
> >
<span className="capitalize text-ch-gray-300 text-sm"> <span className="capitalize text-ch-gray-300 text-sm">email</span>
email
</span>
<InputTextForm <InputTextForm
className="text-xl" className="text-xl"
name="email" name="email"

View File

@@ -49,9 +49,7 @@ const UpdatePasswordPage = () => {
required: true, required: true,
}} }}
/> />
<span className="capitalize text-ch-gray-300 text-sm"> <span className="capitalize text-ch-gray-300 text-sm">confirm</span>
confirm
</span>
<InputTextForm <InputTextForm
className="text-xl" className="text-xl"
name="confirm" name="confirm"