Skip to content

Commit

Permalink
Merge pull request #339 from jwplayer/feat/profiles-edit-create-form
Browse files Browse the repository at this point in the history
feat(project): update edit and create forms
  • Loading branch information
naumovski-filip authored Jul 18, 2023
2 parents a35f4d1 + 3fae481 commit 7a7a209
Show file tree
Hide file tree
Showing 18 changed files with 352 additions and 169 deletions.
15 changes: 15 additions & 0 deletions public/locales/en/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,20 @@
"transactions": "Transactions",
"update_payment_details": "Update payment details",
"weekly_subscription": "Weekly subscription"
},
"profile": {
"adult": "Adult",
"avatar": "Avatar",
"content_rating": "Content rating",
"create": "Create profile",
"delete": "Delete profile",
"delete_description": "Permanently delete your profile along with all of your watch history and favorites.",
"delete_main": "The main profile cannot be deleted.",
"description": "Profiles allow you to watch content and assemble your own personal collection of favorites.",
"greeting": "Howdy",
"greeting_with_name": "Howdy, {{name}}",
"info": "Profile info",
"kids": "Kids",
"name": "User name"
}
}
15 changes: 15 additions & 0 deletions public/locales/es/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,20 @@
"transactions": "Transacciones",
"update_payment_details": "Actualizar detalles de pago",
"weekly_subscription": "Suscripción semanal"
},
"profile": {
"adult": "",
"avatar": "",
"content_rating": "",
"create": "",
"delete": "",
"delete_description": "",
"delete_main": "",
"description": "",
"greeting": "",
"greeting_with_name": "",
"info": "",
"kids": "",
"name": ""
}
}
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;
.kidsLabel {
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;
}



}
}

8 changes: 5 additions & 3 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,15 +12,16 @@ 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>}
{!adult && <span className={styles.kidsLabel}>Kids</span>}
</div>
{editMode && (
<div onClick={onEdit} className={styles.overlay}>
Expand Down
9 changes: 7 additions & 2 deletions src/components/Root/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FC, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';
import { Navigate, useSearchParams } from 'react-router-dom';
import { Navigate, useLocation, useSearchParams } from 'react-router-dom';

import ErrorPage from '#components/ErrorPage/ErrorPage';
import AccountModal from '#src/containers/AccountModal/AccountModal';
Expand All @@ -25,6 +25,7 @@ const Root: FC = () => {
});

const [searchParams, setSearchParams] = useSearchParams();
const location = useLocation();

const configSource = useMemo(() => getConfigSource(searchParams, settingsQuery.data), [searchParams, settingsQuery.data]);

Expand All @@ -46,7 +47,7 @@ const Root: FC = () => {
registerCustomScreens();
}, []);

const userData = useAccountStore((s) => ({ loading: s.loading, user: s.user }));
const userData = useAccountStore((s) => ({ loading: s.loading, user: s.user, profile: s.profile, canManageProfiles: s.canManageProfiles }));

if (userData.user && !userData.loading && window.location.href.includes('#token')) {
return <Navigate to="/" />; // component instead of hook to prevent extra re-renders
Expand All @@ -59,6 +60,10 @@ const Root: FC = () => {
return <LoadingOverlay />;
}

if (userData.canManageProfiles && !userData.profile && !location.pathname.includes('/u/profiles')) {
return <Navigate to="/u/profiles" />;
}

if (settingsQuery.isError) {
return (
<ErrorPage
Expand Down
11 changes: 8 additions & 3 deletions src/components/UserMenu/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useConfigStore } from '#src/stores/ConfigStore';
import { useAccountStore } from '#src/stores/AccountStore';
import LoadingOverlay from '#components/LoadingOverlay/LoadingOverlay';
import Plus from '#src/icons/Plus';
import { useHandleProfileSelection, useListProfiles } from '#src/hooks/useProfiles';
import { useSelectProfile, useListProfiles, unpersistProfile } from '#src/hooks/useProfiles';

type Props = {
small?: boolean;
Expand All @@ -32,7 +32,12 @@ const UserMenu = ({ showPaymentsItem, small = false, onClick }: Props) => {
const { data, isFetching } = useListProfiles();
const profiles = data?.responseData.collection;

const selectProfile = useHandleProfileSelection();
if (canManageProfiles && !profiles?.length) {
unpersistProfile();
navigate('/u/profiles');
}

const selectProfile = useSelectProfile();

const onLogout = useCallback(async () => {
if (onClick) {
Expand Down Expand Up @@ -80,7 +85,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
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exports[`<UserMenu> > renders and matches snapshot 1`] = `
<a
aria-label="nav.profile"
class="_menuButton_91706b"
href="/u/profiles"
href="/u/my-profile/"
tabindex="0"
>
<div
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
Loading

0 comments on commit 7a7a209

Please sign in to comment.