Skip to content

Commit

Permalink
feat(project): update edit and create forms
Browse files Browse the repository at this point in the history
  • Loading branch information
naumovski-filip committed Jul 14, 2023
1 parent 6eacccf commit b40c144
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 151 deletions.
140 changes: 70 additions & 70 deletions src/components/ProfileBox/ProfileBox.module.scss
Original file line number Diff line number Diff line change
@@ -1,83 +1,83 @@
@use 'src/styles/variables';

.inner {
position: relative;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
&:hover {
border: 1px solid variables.$white;
opacity: 0.8;
}
position: relative;
box-sizing: border-box;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
&:hover {
border: 2px solid variables.$white;
opacity: 0.8;
}
}

.selected {
border: 2px solid variables.$deep-blue !important;
border-radius: 4px;
}

.wrapper {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
cursor: pointer;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: min-content;
height: min-content;
cursor: pointer;

.image {
width: 100%;
height: 100%;
}
.image {
width: 100%;
height: 100%;
}

.box {
position: relative;
width: 140px;
height: 140px;
padding: 10px;
img {
position: relative;
transition: all 0.5s ease;
}
.kids {
position: absolute;
top: 5px;
right: 5px;
color: variables.$link;
}
&:hover {
img {
transform: translate(-5px, -5px);
}
}
.box {
position: relative;
width: 140px;
height: 140px;
padding: 10px;
img {
position: relative;
transition: all 0.5s ease;
}
.circle {
display: flex;
justify-content: center;
align-items: center;
// border: 1px solid rgba(255, 255, 255, 0.3);
background: #1F232C;
border: 1px solid transparent;
border-radius: 100px;
.kids {
position: absolute;
top: 5px;
right: 5px;
color: variables.$link;
}
.overlay {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 95%);
border: 1px solid transparent;
border-radius: 4px;
&:hover {
img {
transform: translate(-5px, -5px);
}
}
}
.circle {
display: flex;
justify-content: center;
align-items: center;
// border: 1px solid rgba(255, 255, 255, 0.3);
background: #1f232c;
border: 1px solid transparent;
border-radius: 100px;
}
.overlay {
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 95%);
border: 1px solid transparent;
border-radius: 4px;
}

&:hover {
.box {
border: 1px solid variables.$white;
opacity: 0.8;
}
h2 {
opacity: 0.8;
}
&:hover {
h2 {
opacity: 0.8;
}



}
}

6 changes: 4 additions & 2 deletions src/components/ProfileBox/ProfileBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import classNames from 'classnames';

import styles from './ProfileBox.module.scss';

Expand All @@ -11,12 +12,13 @@ type Props = {
editMode?: boolean;
onClick: () => void;
onEdit: () => void;
selected?: boolean;
};

const ProfileBox = ({ name, image, adult = true, editMode = false, onClick, onEdit }: Props) => {
const ProfileBox = ({ name, image, adult = true, editMode = false, onClick, onEdit, selected = false }: Props) => {
return (
<div className={styles.wrapper}>
<div className={styles.inner}>
<div className={classNames(styles.inner, selected && styles.selected)}>
<div onClick={onClick} className={styles.box}>
<img className={styles.image} src={image} alt="" />
{!adult && <span className={styles.kids}>Kids</span>}
Expand Down
2 changes: 1 addition & 1 deletion src/components/UserMenu/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ const UserMenu = ({ showPaymentsItem, small = false, onClick }: Props) => {
<MenuButton
small={small}
onClick={onClick}
to="/u/profiles"
to={`/u/my-profile/${currentProfile?.id}`}
label={t('nav.profile')}
startIcon={<img className={styles.profileIcon} src={currentProfile?.avatar_url} alt={currentProfile?.name} />}
/>
Expand Down
23 changes: 13 additions & 10 deletions src/containers/Profiles/CreateProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useNavigate } from 'react-router';
import profileStyles from './Profiles.module.scss';
import Form from './Form';
import type { ProfileFormValues } from './types';
import AVATARS from './avatarUrls.json';

import styles from '#src/pages/User/User.module.scss';
import { useAccountStore } from '#src/stores/AccountStore';
Expand All @@ -12,17 +13,11 @@ import type { UseFormOnSubmitHandler } from '#src/hooks/useForm';
import { createProfile } from '#src/stores/AccountController';
import { useListProfiles } from '#src/hooks/useProfiles';

const AVATARS = [
'https://gravatar.com/avatar/5e62c8c13582f94b74ae21cfeb83e28a?s=400&d=robohash&r=x',
'https://gravatar.com/avatar/a82dc2482b1ae8d9070462a37b5e19e9?s=400&d=robohash&r=x',
'https://gravatar.com/avatar/236030198309afe28c9fce9c3ebfec3b?s=400&d=robohash&r=x',
'https://gravatar.com/avatar/c97a042d43cc5cc28802f2bc7bf2e5ab?s=400&d=robohash&r=x',
];

const CreateProfile = () => {
const navigate = useNavigate();
const { canManageProfiles } = useAccountStore.getState();
const [fullName, setFullName] = useState<string>('');
const [avatarUrl, setAvatarUrl] = useState<string>('');

useEffect(() => {
if (!canManageProfiles) navigate('/');
Expand All @@ -45,7 +40,7 @@ const CreateProfile = () => {
await createProfile({
name: formData.name,
adult: formData.adult === 'true',
avatar_url: AVATARS[activeProfiles],
avatar_url: formData.avatar_url,
})
)?.responseData;
if (profile?.id) {
Expand All @@ -70,12 +65,20 @@ const CreateProfile = () => {
<div className={styles.panel}>
<div className={profileStyles.avatar}>
<h2>Howdy{`${fullName && ','} ${fullName}`}</h2>
<img src={AVATARS[activeProfiles]} />
<img src={avatarUrl || AVATARS[activeProfiles]} />
</div>
</div>
</div>
<div className={styles.mainColumn}>
<Form initialValues={initialValues} formHandler={createProfileHandler} setFullName={setFullName} />
<Form
initialValues={initialValues}
formHandler={createProfileHandler}
setFullName={setFullName}
selectedAvatar={{
set: setAvatarUrl,
value: avatarUrl,
}}
/>
</div>
</div>
);
Expand Down
55 changes: 41 additions & 14 deletions src/containers/Profiles/EditProfile.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { useLocation, useNavigate, useParams } from 'react-router';
import { useTranslation } from 'react-i18next';
import classNames from 'classnames';

import profileStyles from './Profiles.module.scss';
import Form from './Form';
Expand All @@ -14,12 +16,21 @@ import Button from '#src/components/Button/Button';
import { addQueryParam } from '#src/utils/location';
import FormFeedback from '#src/components/FormFeedback/FormFeedback';
import { getProfileDetails, updateProfile } from '#src/stores/AccountController';
import { useListProfiles } from '#src/hooks/useProfiles';

const EditProfile = () => {
const { id } = useParams();
type EditProfileProps = {
contained?: boolean;
};

const EditProfile = ({ contained = false }: EditProfileProps) => {
const params = useParams();
const { id } = params;
const location = useLocation();
const navigate = useNavigate();
const [fullName, setFullName] = useState<string>('');
const { t } = useTranslation('user');

const listProfiles = useListProfiles();

const { data, isLoading, isFetching } = useQuery(['getProfileDetails'], () => getProfileDetails({ id: id || '' }), {
staleTime: 0,
Expand All @@ -37,6 +48,8 @@ const EditProfile = () => {
};
}, [profileDetails]);

const [selectedAvatar, setSelectedAvatar] = useState<string | undefined>(initialValues.avatar_url);

if (!id) {
navigate('/u/profiles');
}
Expand All @@ -54,6 +67,7 @@ const EditProfile = () => {

if (profile?.id) {
setSubmitting(false);
listProfiles.refetch();
navigate('/u/profiles');
} else {
setErrors({ form: 'Something went wrong. Please try again later.' });
Expand All @@ -68,23 +82,36 @@ const EditProfile = () => {
if (isLoading || isFetching) return <LoadingOverlay inline />;

return (
<div className={styles.user}>
<div className={styles.leftColumn}>
<div className={styles.panel}>
<div className={profileStyles.avatar}>
<h2>Howdy{`${fullName && ','} ${fullName}`}</h2>
<img src={profileDetails?.avatar_url} />
<div className={classNames(styles.user, contained && profileStyles.contained)}>
{!contained && (
<div className={styles.leftColumn}>
<div className={styles.panel}>
<div className={profileStyles.avatar}>
<h2>
{t('profile.greeting')}
{`${fullName && ','} ${fullName}`}
</h2>
<img src={profileDetails?.avatar_url} />
</div>
</div>
</div>
</div>
<div className={styles.mainColumn}>
<Form initialValues={initialValues} formHandler={updateProfileHandler} setFullName={setFullName} />
)}
<div className={classNames(styles.mainColumn)}>
<Form
initialValues={initialValues}
formHandler={updateProfileHandler}
setFullName={setFullName}
selectedAvatar={{
set: setSelectedAvatar,
value: selectedAvatar || '',
}}
/>
<div className={styles.panel}>
<h2 className={styles.panelHeader}>Delete profile</h2>
{profileDetails?.default && <FormFeedback variant="info">The main profile cannot be deleted.</FormFeedback>}
<h2 className={styles.panelHeader}>{t('profile.delete')}</h2>
{profileDetails?.default && <FormFeedback variant="info">{t('profile.delete_main')}</FormFeedback>}
<Button
onClick={() => navigate(addQueryParam(location, 'action', 'delete-profile'))}
label="Delete profile"
label={t('profile.delete')}
variant="contained"
color="delete"
disabled={profileDetails?.default}
Expand Down
Loading

0 comments on commit b40c144

Please sign in to comment.