Skip to content

Commit

Permalink
feat: add profile created success modal
Browse files Browse the repository at this point in the history
  • Loading branch information
naumovski-filip committed Oct 18, 2023
1 parent 514f3ca commit 296c548
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 42 deletions.
1 change: 1 addition & 0 deletions public/locales/en/menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"close_menu": "Close menu",
"open_menu": "Open menu",
"open_user_menu": "Open user menu",
"profile_icon": "Profile icon",
"select_language": "Select language",
"sign_in": "Sign in",
"sign_up": "Sign up"
Expand Down
7 changes: 5 additions & 2 deletions public/locales/en/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@
"profile": {
"adult": "Adult",
"avatar": "Avatar",
"back_to_profiles": "Back to profiles",
"content_rating": "Content rating",
"create": "Create profile",
"create_message": "Create your profile",
"created_message": "You successfully created your profile. Now go and watch some awesome content and assemble your own personal collection of favorites.",
"created_title": "You’ve created your profile",
"delete": "Delete profile",
"delete_confirmation": "Are you sure you want to delete your profile? You will lose all you watch history and settings connected to this profile.",
"delete_description": "Permanently delete your profile along with all of your watch history and favorites.",
Expand All @@ -136,6 +138,7 @@
"required": "Please enter a name for your profile.",
"too_short": "Please enter at least 2 characters."
}
}
},
"watch_now": "Watch now"
}
}
1 change: 1 addition & 0 deletions public/locales/es/menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"close_menu": "Cerrar menú",
"open_menu": "Abrir menú",
"open_user_menu": "Abrir menú de usuario",
"profile_icon": "",
"select_language": "Seleccionar idioma",
"sign_in": "Iniciar sesión",
"sign_up": "Registrarse"
Expand Down
3 changes: 2 additions & 1 deletion public/locales/es/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
"required": "Por favor",
"too_short": "Por favor"
}
}
},
"watch_now": ""
}
}
8 changes: 5 additions & 3 deletions src/components/Alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ type Props = {
message: string | null;
onClose: () => void;
isSuccess?: boolean;
actionsOverride?: React.ReactNode;
titleOverride?: string;
};

const Alert: React.FC<Props> = ({ open, message, onClose, isSuccess }: Props) => {
const Alert: React.FC<Props> = ({ open, message, onClose, isSuccess, actionsOverride, titleOverride }: Props) => {
const { t } = useTranslation('common');

return (
<Dialog open={open} onClose={onClose}>
<h2 className={styles.title}>{isSuccess ? t('alert.success') : t('alert.title')}</h2>
<h2 className={styles.title}>{titleOverride ?? (isSuccess ? t('alert.success') : t('alert.title'))}</h2>
<p className={styles.body}>{message}</p>
<Button label={t('alert.close')} variant="outlined" onClick={onClose} fullWidth />
{actionsOverride ?? <Button label={t('alert.close')} variant="outlined" onClick={onClose} fullWidth />}
</Dialog>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { UseMutateFunction } from 'react-query';

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

import AccountCircle from '#src/icons/AccountCircle';
import SearchBar, { Props as SearchBarProps } from '#components/SearchBar/SearchBar';
import Logo from '#components/Logo/Logo';
import Menu from '#src/icons/Menu';
Expand All @@ -23,6 +22,7 @@ import Panel from '#components/Panel/Panel';
import type { Profile } from '#types/account';
import ProfileCircle from '#src/icons/ProfileCircle';
import type { AccessModel } from '#types/Config';
import defaultAvatar from '#src/assets/profiles/default_avatar.png';

type TypeHeader = 'static' | 'fixed';

Expand Down Expand Up @@ -138,7 +138,7 @@ const Header: React.FC<Props> = ({
return isLoggedIn ? (
<React.Fragment>
<IconButton className={classNames(styles.iconButton, styles.actionButton)} aria-label={t('open_user_menu')} onClick={openUserMenu}>
{currentProfile?.avatar_url ? <ProfileCircle src={currentProfile.avatar_url} alt={currentProfile.name} /> : <AccountCircle />}
<ProfileCircle src={currentProfile?.avatar_url || defaultAvatar} alt={currentProfile?.name ?? t('profile_icon')} />
</IconButton>
<Popover isOpen={userMenuOpen} onClose={closeUserMenu}>
<Panel>
Expand Down
2 changes: 1 addition & 1 deletion src/containers/Profiles/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const Form = ({ initialValues, formHandler, selectedAvatar, showCancelButton = t
setValue('avatar_url', selectedAvatar?.value || profile?.avatar_url || '');
}, [profile?.avatar_url, selectedAvatar?.value, setValue]);

const formLabel = values?.id ? t('profile.info') : t('profile.create');
const formLabel = t('profile.info');

return (
<form onSubmit={handleSubmit} noValidate>
Expand Down
7 changes: 7 additions & 0 deletions src/containers/Profiles/Profiles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,10 @@
padding-bottom: 6px;
font-size: 20px;
}

.modalActions {
display: flex;
justify-content: flex-end;
width: 100%;
gap: 8px;
}
94 changes: 63 additions & 31 deletions src/containers/Profiles/Profiles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect } from 'react';
import { useNavigate } from 'react-router';
import shallow from 'zustand/shallow';
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';

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

Expand All @@ -13,6 +14,7 @@ import LoadingOverlay from '#src/components/LoadingOverlay/LoadingOverlay';
import Button from '#src/components/Button/Button';
import { useSelectProfile, useProfiles } from '#src/hooks/useProfiles';
import useBreakpoint, { Breakpoint } from '#src/hooks/useBreakpoint';
import Alert from '#components/Alert/Alert';
const MAX_PROFILES = 4;

type Props = {
Expand All @@ -24,6 +26,10 @@ const Profiles = ({ editMode = false }: Props) => {
const { t } = useTranslation('user');
const { loading, user } = useAccountStore(({ loading, user }) => ({ loading, user }), shallow);

const [params] = useSearchParams();
const creationSuccess = params.get('success') === 'true';
const createdProfileId = params.get('id');

const breakpoint: Breakpoint = useBreakpoint();
const isMobile = breakpoint === Breakpoint.xs;

Expand All @@ -40,42 +46,68 @@ const Profiles = ({ editMode = false }: Props) => {

const selectProfile = useSelectProfile();

const createdProfileData = data?.responseData.collection.find((profile: Profile) => profile.id === createdProfileId);

if (loading || isLoading || isFetching) return <LoadingOverlay inline />;

return (
<div className={styles.wrapper}>
{activeProfiles === 0 ? (
<div className={styles.headings}>
<p className={styles.paragraph}>{t('profile.no_one_watching')}</p>
<h2 className={styles.heading}>{t('profile.create_message')}</h2>
<>
<div className={styles.wrapper}>
{activeProfiles === 0 ? (
<div className={styles.headings}>
<p className={styles.paragraph}>{t('profile.no_one_watching')}</p>
<h2 className={styles.heading}>{t('profile.create_message')}</h2>
</div>
) : (
<h2 className={styles.heading}>{t('account.who_is_watching')}</h2>
)}
<div className={styles.flex}>
{data?.responseData.collection?.map((profile: Profile) => (
<ProfileBox
editMode={editMode}
onEdit={() => navigate(`/u/profiles/edit/${profile.id}`)}
onClick={() => selectProfile.mutate({ id: profile.id, avatarUrl: profile.avatar_url })}
key={profile.id}
name={profile.name}
adult={profile.adult}
image={profile.avatar_url}
/>
))}
{canAddNew && <AddNewProfile onClick={() => navigate('/u/profiles/create')} />}
</div>
) : (
<h2 className={styles.heading}>{t('account.who_is_watching')}</h2>
)}
<div className={styles.flex}>
{data?.responseData.collection?.map((profile: Profile) => (
<ProfileBox
editMode={editMode}
onEdit={() => navigate(`/u/profiles/edit/${profile.id}`)}
onClick={() => selectProfile.mutate({ id: profile.id, avatarUrl: profile.avatar_url })}
key={profile.id}
name={profile.name}
adult={profile.adult}
image={profile.avatar_url}
/>
))}
{canAddNew && <AddNewProfile onClick={() => navigate('/u/profiles/create')} />}
{activeProfiles > 0 && (
<div className={styles.buttonContainer}>
{!editMode ? (
<Button onClick={() => navigate('/u/profiles/edit')} label={t('account.manage_profiles')} variant="outlined" size="large" fullWidth={isMobile} />
) : (
<Button onClick={() => navigate('/u/profiles')} label={t('profile.done')} variant="outlined" size="large" fullWidth={isMobile} />
)}
</div>
)}
</div>
{activeProfiles > 0 && (
<div className={styles.buttonContainer}>
{!editMode ? (
<Button onClick={() => navigate('/u/profiles/edit')} label={t('account.manage_profiles')} variant="outlined" size="large" fullWidth={isMobile} />
) : (
<Button onClick={() => navigate('/u/profiles')} label={t('profile.done')} variant="outlined" size="large" fullWidth={isMobile} />
)}
</div>
)}
</div>
<Alert
isSuccess
open={creationSuccess}
titleOverride={t('profile.created_title')}
message={t('profile.created_message')}
onClose={() => navigate('/u/profiles')}
actionsOverride={
<div className={styles.modalActions}>
<Button to="/u/profiles" label={t('profile.back_to_profiles')} variant="text" fullWidth={isMobile} />
<Button
onClick={() => {
navigate('/u/profiles');
createdProfileId && selectProfile.mutate({ id: createdProfileId, avatarUrl: createdProfileData?.avatar_url ?? '' });
}}
label={t('profile.watch_now')}
variant="outlined"
color="primary"
fullWidth={isMobile}
/>
</div>
}
/>
</>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useProfiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const useCreateProfile = (options?: UseMutationOptions<ServiceResponse<Pr
const profile = res?.responseData;
if (profile?.id) {
listProfiles.refetch();
navigate('/u/profiles');
navigate(`/u/profiles?success=true&id=${profile.id}`);
}
},
...options,
Expand Down
9 changes: 9 additions & 0 deletions src/pages/User/User.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
margin: 0 calc(#{variables.$base-spacing} * 1.5);
}
}

.leftColumn {
width: 250px;
margin-right: 24px;
Expand All @@ -30,9 +31,16 @@
}

.button {
max-width: 100%;
height: max-content;
min-height: 36px;
margin-bottom: variables.$base-spacing;
}

.button span {
word-break: break-word;
}

.logoutLi {
margin-bottom: 0;
padding-top: variables.$base-spacing;
Expand Down Expand Up @@ -89,4 +97,5 @@
.profileIcon {
width: 20px;
height: 20px;
border-radius: 50%;
}
3 changes: 2 additions & 1 deletion src/pages/User/User.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { PersonalShelf, useConfigStore } from '#src/stores/ConfigStore';
import { clear as clearFavorites } from '#src/stores/FavoritesController';
import { useProfileStore } from '#src/stores/ProfileStore';
import { useProfiles } from '#src/hooks/useProfiles';
import defaultAvatar from '#src/assets/profiles/default_avatar.png';

const User = (): JSX.Element => {
const { accessModel, favoritesList } = useConfigStore(
Expand Down Expand Up @@ -85,7 +86,7 @@ const User = (): JSX.Element => {
to={`my-profile/${profile?.id}`}
label={profile?.name ?? t('nav.profile')}
variant="text"
startIcon={<img className={styles.profileIcon} src={profile?.avatar_url} alt={profile?.name} />}
startIcon={<img className={styles.profileIcon} src={profile?.avatar_url || defaultAvatar} alt={profile?.name} />}
className={styles.button}
/>
</li>
Expand Down

0 comments on commit 296c548

Please sign in to comment.