From 6f545b3b2796d384ab2dc19ff9d2f030e338563d Mon Sep 17 00:00:00 2001 From: Cody Epstein Date: Wed, 13 Nov 2024 23:47:24 -0800 Subject: [PATCH 01/12] add edit button and isEditing state --- .../[leagueId]/entry/[entryId]/week/Week.tsx | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx index 6edab010..708eb7b0 100644 --- a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx +++ b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx @@ -33,8 +33,9 @@ import { cn, getNFLTeamLogo } from '@/utils/utils'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; import LinkCustom from '@/components/LinkCustom/LinkCustom'; -import { ChevronLeft } from 'lucide-react'; +import { ChevronLeft, Pen } from 'lucide-react'; import Heading from '@/components/Heading/Heading'; +import { Button } from '@/components/Button/Button'; /** * Renders the weekly picks page. @@ -52,6 +53,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { const [loadingData, setLoadingData] = useState(true); const [loadingTeamName, setLoadingTeamName] = useState(null); const [userPick, setUserPick] = useState(''); + const [isEditing, setIsEditing] = useState(false); const { user, updateCurrentWeek, updateWeeklyPicks, weeklyPicks } = useDataStore((state) => state); const { isSignedIn } = useAuthContext(); @@ -158,7 +160,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { if (!currentEntry) { throw new Error('Entry not found'); } - + setEntryName(currentEntry.name); let entryHistory = currentEntry?.selectedTeams || []; @@ -274,18 +276,34 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { className="flex flex-col items-center w-full pt-8" data-testid="weekly-picks" > - {`Week ${week} pick`} - - {entryName} + + {`Week ${week} pick`} +
+ {isEditing ? ( + <> + + + ) : ( + <> + + {entryName} + + + + )} +
{pickHistory.length > 0 && (
Date: Thu, 14 Nov 2024 00:46:49 -0800 Subject: [PATCH 02/12] add entryNameForm and onSubmit --- .../[leagueId]/entry/[entryId]/week/Week.tsx | 119 ++++++++++++++---- 1 file changed, 98 insertions(+), 21 deletions(-) diff --git a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx index 708eb7b0..e3ee1681 100644 --- a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx +++ b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx @@ -8,8 +8,9 @@ import { FormItem, FormControl, FormMessage, + Form, } from '@/components/Form/Form'; -import { FormProvider, Control, useForm } from 'react-hook-form'; +import { FormProvider, Control, useForm, SubmitHandler } from 'react-hook-form'; import { z } from 'zod'; import { IWeekProps } from './Week.interface'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -33,9 +34,10 @@ import { cn, getNFLTeamLogo } from '@/utils/utils'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; import LinkCustom from '@/components/LinkCustom/LinkCustom'; -import { ChevronLeft, Pen } from 'lucide-react'; +import { Check, ChevronLeft, Pen, X } from 'lucide-react'; import Heading from '@/components/Heading/Heading'; import { Button } from '@/components/Button/Button'; +import { Input } from '@/components/Input/Input'; /** * Renders the weekly picks page. @@ -54,11 +56,35 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { const [loadingTeamName, setLoadingTeamName] = useState(null); const [userPick, setUserPick] = useState(''); const [isEditing, setIsEditing] = useState(false); + const { user, updateCurrentWeek, updateWeeklyPicks, weeklyPicks } = useDataStore((state) => state); const { isSignedIn } = useAuthContext(); const router = useRouter(); + const NFLTeamsList = NFLTeams.map((team) => team.teamName) as [ + string, + ...string[] + ]; + const WeekTeamsFormSchema = z.object({ + type: z.enum(NFLTeamsList, { + required_error: 'You need to select a team.', + }), + }); + const weekTeamsForm = useForm>({ + resolver: zodResolver(WeekTeamsFormSchema), + }); + + const EntryNameFormSchema = z.object({ + name: z.string().min(3).max(50), + }); + const entryNameForm = useForm>({ + resolver: zodResolver(EntryNameFormSchema), + defaultValues: { + name: entryName, + }, + }); + /** * Fetches the current game week. * @returns {Promise} @@ -82,17 +108,6 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { setSelectedLeague(res); }; - const NFLTeamsList = NFLTeams.map((team) => team.teamName) as [ - string, - ...string[] - ]; - - const FormSchema = z.object({ - type: z.enum(NFLTeamsList, { - required_error: 'You need to select a team.', - }), - }); - /** * Fetches the league's weekly pick results for the user and set the user pick. * @returns {Promise} @@ -162,6 +177,8 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { } setEntryName(currentEntry.name); + entryNameForm.reset({ name: currentEntry.name }); + let entryHistory = currentEntry?.selectedTeams || []; if (currentEntry?.selectedTeams.length > 0) { @@ -178,10 +195,6 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { } }; - const form = useForm>({ - resolver: zodResolver(FormSchema), - }); - /** * Get selected teams for the current user entry. * @returns {Promise} The selected teams @@ -230,6 +243,26 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { } }; + /** + * handles the form submission + * @param data - the form data + * @returns {void} + */ + const onSubmit: SubmitHandler> = async ( + data, + ): Promise => { + const { name } = data; + try { + // API call to DB to update Entry Name + console.log('name', name); + setEntryName(name); + entryNameForm.reset({ name: name }); + setIsEditing(false); + } catch (error) { + throw error; + } + }; + useEffect(() => { if (!selectedLeague) { getSelectedLeague(); @@ -282,7 +315,51 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => {
{isEditing ? ( <> - +
+ + } + name="name" + render={({ field }) => ( + + + + + {entryNameForm.formState.errors.name && ( + + {entryNameForm.formState.errors.name.message} + + )} + + )} + /> + + + + ) : ( <> @@ -294,7 +371,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { {entryName}
)} - +
} + control={weekTeamsForm.control as Control} name="type" render={({ field }) => ( From 8b35564d7f5193fb00a52d8ce6f48fd07b88440c Mon Sep 17 00:00:00 2001 From: Cody Epstein Date: Thu, 14 Nov 2024 09:42:53 -0800 Subject: [PATCH 03/12] remove console.log --- app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx index e3ee1681..e3d7186b 100644 --- a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx +++ b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx @@ -254,7 +254,6 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { const { name } = data; try { // API call to DB to update Entry Name - console.log('name', name); setEntryName(name); entryNameForm.reset({ name: name }); setIsEditing(false); From 0903ae4905c73a67175b49a2d56ead8ff046fb07 Mon Sep 17 00:00:00 2001 From: Cody Epstein Date: Thu, 14 Nov 2024 12:47:00 -0800 Subject: [PATCH 04/12] add updateEntryName function --- api/apiFunctions.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/api/apiFunctions.ts b/api/apiFunctions.ts index 2f3b072d..76e1b1a8 100644 --- a/api/apiFunctions.ts +++ b/api/apiFunctions.ts @@ -427,6 +427,35 @@ export async function updateEntry({ } } +/** + * Updates the name of an entry + * @param {Object} params - The parameters object + * @param {string} params.entryId - The ID of the entry to update + * @param {string} params.entryName - The new name for the entry + * @returns {Models.Document | Error} - The entry object or an error + */ +export async function updateEntryName({ + entryId, + entryName, +}: { + entryId: string; + entryName: string; +}): Promise { + try { + return await databases.updateDocument( + appwriteConfig.databaseId, + Collection.ENTRIES, + entryId, + { + name: entryName, + }, + ); + } catch (error) { + console.error(error); + throw new Error('Error updating entry'); + } +} + /** * Retrieves a list of all leagues. * @returns {Models.Document[]} A list of all available leagues. From a6708684565e6d290320d5eeff5cd33bb8b3f07e Mon Sep 17 00:00:00 2001 From: Cody Epstein Date: Thu, 14 Nov 2024 12:47:51 -0800 Subject: [PATCH 05/12] fix error styling and update zod schema --- .../[leagueId]/entry/[entryId]/week/Week.tsx | 75 +++++++++++-------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx index e3d7186b..087236d0 100644 --- a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx +++ b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx @@ -21,6 +21,7 @@ import { getCurrentUserEntries, getCurrentLeague, getGameWeek, + updateEntryName, } from '@/api/apiFunctions'; import { ILeague } from '@/api/apiFunctions.interface'; import WeekTeams from './WeekTeams'; @@ -76,7 +77,10 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { }); const EntryNameFormSchema = z.object({ - name: z.string().min(3).max(50), + name: z + .string() + .min(3, 'Entry name must contain at least 3 characters') + .max(50, 'Entry name must contain no more than 50 characters'), }); const entryNameForm = useForm>({ resolver: zodResolver(EntryNameFormSchema), @@ -252,8 +256,9 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { data, ): Promise => { const { name } = data; + const entryId: string = entry; try { - // API call to DB to update Entry Name + await updateEntryName({ entryId, entryName: name }); setEntryName(name); entryNameForm.reset({ name: name }); setIsEditing(false); @@ -324,47 +329,51 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { control={entryNameForm.control as Control} name="name" render={({ field }) => ( - - - - - {entryNameForm.formState.errors.name && ( - - {entryNameForm.formState.errors.name.message} - - )} + +
+
+ + + + {entryNameForm.formState.errors.name && ( + + )} +
+ + +
)} /> - - ) : ( <> {entryName} From 786fcd82ba8c05ea53c94a74475c401949d46900 Mon Sep 17 00:00:00 2001 From: Cody Epstein Date: Sat, 16 Nov 2024 08:19:31 -0800 Subject: [PATCH 06/12] add testids --- app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx index 087236d0..f39f2eec 100644 --- a/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx +++ b/app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx @@ -334,7 +334,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => {
{ variant="secondary" size="icon" aria-label="Cancel Editing" + data-testid="cancel-editing-button" onClick={() => setIsEditing(false)} > @@ -358,6 +359,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { type="submit" variant="secondary" size="icon" + data-testid="save-entry-name-button" aria-label="Accept Edit" > @@ -381,6 +383,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => {