-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Alex/bug bash: add alert when pick is updated #415
Changes from 23 commits
5f705d6
138a3d1
1c5c905
d78d63f
2066acf
b59489c
e154977
de6cad1
a264ede
29ee3ce
9e0f3c6
0b0e05d
e4ee42d
1e89efb
11d5a02
1236a94
1f26a02
f885dfe
9b95801
d739aa1
4e9475b
94eb8cb
8bd9efb
cd074b3
baa8836
4933a40
1473a7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,19 @@ | ||
// Copyright (c) Gridiron Survivor. | ||
// Licensed under the MIT License. | ||
|
||
import { INFLTeam, ILeague } from '@/api/apiFunctions.interface'; | ||
import React from 'react'; | ||
import { | ||
INFLTeam, | ||
ILeague, | ||
IWeeklyPicks, | ||
IUser, | ||
} from '@/api/apiFunctions.interface'; | ||
|
||
export interface IData { | ||
target: { | ||
value: string; | ||
}; | ||
} | ||
|
||
export interface IWeekParams { | ||
params: { | ||
|
@@ -11,6 +23,18 @@ export interface IWeekParams { | |
}; | ||
} | ||
|
||
export interface IWeeklyPickChange { | ||
data: IData; | ||
entry: string; | ||
league: string; | ||
NFLTeams: INFLTeam[]; | ||
setUserPick: React.Dispatch<React.SetStateAction<string>>; | ||
updateWeeklyPicks: ({}: IWeeklyPicks) => void; | ||
user: IUser; | ||
weeklyPicks: IWeeklyPicks; | ||
week: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have an ENUM for the weeks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we do not. when i looked into it, it is just something that gets passed in as a string There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: We should look to adding it later. There's only week 1-18 available. |
||
} | ||
|
||
export interface IWeekProps { | ||
entry: string; | ||
league: ILeague['leagueId']; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import React from 'react'; | ||
import Alert from '@/components/AlertNotification/AlertNotification'; | ||
import { AlertVariants } from '@/components/AlertNotification/Alerts.enum'; | ||
import { toast } from 'react-hot-toast'; | ||
import { onWeeklyPickChange } from './WeekHelper'; | ||
import { createWeeklyPicks } from '@/api/apiFunctions'; | ||
import { parseUserPick } from '@/utils/utils'; | ||
import { IWeeklyPicks } from '@/api/apiFunctions.interface'; | ||
|
||
jest.mock('@/api/apiFunctions', () => ({ | ||
createWeeklyPicks: jest.fn(), | ||
})); | ||
|
||
jest.mock('react-hot-toast', () => ({ | ||
toast: { | ||
custom: jest.fn(), | ||
}, | ||
})); | ||
|
||
describe('Week', () => { | ||
const data = { | ||
target: { value: 'Browns' }, | ||
preventDefault: jest.fn(), | ||
stopPropagation: jest.fn(), | ||
}; | ||
const NFLTeams = [{ teamName: 'Browns', teamId: '1234' }]; | ||
const user = { id: '12345', email: '[email protected]', leagues: [] }; | ||
const entry = 'mockEntry'; | ||
const league = 'mockLeague'; | ||
const week = 'mockWeek'; | ||
const updateWeeklyPicks = jest.fn(); | ||
const setUserPick = jest.fn(); | ||
|
||
const weeklyPicks: IWeeklyPicks = { | ||
leagueId: '123', | ||
gameWeekId: '123456', | ||
userResults: {}, | ||
}; | ||
|
||
const teamID = NFLTeams[0].teamName; | ||
|
||
const updatedWeeklyPicks = { | ||
...weeklyPicks.userResults, | ||
[user.id]: { | ||
...weeklyPicks.userResults[user.id], | ||
[entry]: { | ||
...weeklyPicks.userResults[user.id]?.[entry], | ||
...parseUserPick(user.id, entry, teamID || '')[user.id][entry], | ||
}, | ||
}, | ||
}; | ||
|
||
const mockParseUserPick = jest.fn().mockReturnValue({ | ||
[user.id]: { | ||
[entry]: { | ||
teamName: 'Browns', | ||
}, | ||
}, | ||
}); | ||
|
||
jest.mock('@/utils/utils', () => ({ | ||
parseUserPick: mockParseUserPick, | ||
})); | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
test('should show success notification after changing your team pick', async () => { | ||
(createWeeklyPicks as jest.Mock).mockResolvedValue({}); | ||
|
||
const currentUserPick = mockParseUserPick(user.id, entry, teamID); | ||
|
||
await onWeeklyPickChange({ | ||
data, | ||
NFLTeams, | ||
user, | ||
entry, | ||
weeklyPicks, | ||
league, | ||
week, | ||
updateWeeklyPicks, | ||
setUserPick, | ||
}); | ||
|
||
expect(createWeeklyPicks).toHaveBeenCalledWith({ | ||
leagueId: league, | ||
gameWeekId: week, | ||
userResults: updatedWeeklyPicks, | ||
}); | ||
|
||
expect(mockParseUserPick).toHaveBeenCalledWith(user.id, entry, teamID); | ||
|
||
expect(toast.custom).toHaveBeenCalledWith( | ||
<Alert | ||
variant={AlertVariants.Success} | ||
message={`You have successfully pick the ${ | ||
currentUserPick[user.id][entry].teamName | ||
} for your team!`} | ||
/>, | ||
); | ||
}); | ||
|
||
test('should show error notification when changing your team fails', async () => { | ||
(createWeeklyPicks as jest.Mock).mockRejectedValue(new Error('error')); | ||
|
||
await onWeeklyPickChange({ | ||
data, | ||
NFLTeams, | ||
user, | ||
entry, | ||
weeklyPicks, | ||
league, | ||
week, | ||
updateWeeklyPicks, | ||
setUserPick, | ||
}); | ||
|
||
expect(toast.custom).toHaveBeenCalledWith( | ||
<Alert | ||
variant={AlertVariants.Error} | ||
message="There was an error processing your request." | ||
/>, | ||
); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,6 @@ import { | |
import { FormProvider, Control, useForm } from 'react-hook-form'; | ||
import { z } from 'zod'; | ||
import { IWeekProps } from './Week.interface'; | ||
import { createWeeklyPicks } from '@/api/apiFunctions'; | ||
import { parseUserPick } from '@/utils/utils'; | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import { useDataStore } from '@/store/dataStore'; | ||
import { ISchedule } from './WeekTeams.interface'; | ||
|
@@ -22,6 +20,7 @@ import { ChevronLeft } from 'lucide-react'; | |
import { getCurrentLeague } from '@/api/apiFunctions'; | ||
import { ILeague } from '@/api/apiFunctions.interface'; | ||
import WeekTeams from './WeekTeams'; | ||
import { onWeeklyPickChange } from './WeekHelper'; | ||
|
||
/** | ||
* Renders the weekly picks page. | ||
|
@@ -84,52 +83,25 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { | |
}); | ||
|
||
/** | ||
* Handles the form submission. | ||
* @param data - The form data. | ||
* Handles the weekly picks | ||
* @param data - data of the pick | ||
* @returns {void} | ||
*/ | ||
const onWeeklyPickChange = async ( | ||
const handleWeeklyPickChange = async ( | ||
data: ChangeEvent<HTMLInputElement>, | ||
): Promise<void> => { | ||
try { | ||
const teamSelect = data.target.value; | ||
const teamID = NFLTeams.find( | ||
(team) => team.teamName === teamSelect, | ||
)?.teamName; | ||
|
||
const currentUserPick = parseUserPick(user.id, entry, teamID || ''); | ||
|
||
// combines current picks and the user pick into one object. | ||
// if the user pick exists then it overrides the pick of the user. | ||
const updatedWeeklyPicks = { | ||
...weeklyPicks.userResults, | ||
[user.id]: { | ||
...weeklyPicks.userResults[user.id], | ||
[entry]: { | ||
...weeklyPicks.userResults[user.id]?.[entry], | ||
...currentUserPick[user.id][entry], | ||
}, | ||
}, | ||
}; | ||
|
||
// update weekly picks in the database | ||
await createWeeklyPicks({ | ||
leagueId: league, | ||
gameWeekId: week, | ||
userResults: updatedWeeklyPicks, | ||
}); | ||
|
||
// update weekly picks in the data store | ||
updateWeeklyPicks({ | ||
leagueId: league, | ||
gameWeekId: week, | ||
userResults: updatedWeeklyPicks, | ||
}); | ||
|
||
setUserPick(currentUserPick[user.id][entry].teamName); | ||
} catch (error) { | ||
console.error('Submission error:', error); | ||
} | ||
const params = { | ||
data, | ||
entry, | ||
league, | ||
NFLTeams, | ||
setUserPick, | ||
updateWeeklyPicks, | ||
user, | ||
weeklyPicks, | ||
week, | ||
}; | ||
await onWeeklyPickChange(params); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a try/catch here. |
||
}; | ||
|
||
useEffect(() => { | ||
|
@@ -175,7 +147,7 @@ const Week = ({ entry, league, NFLTeams, week }: IWeekProps): JSX.Element => { | |
schedule={schedule} | ||
field={field} | ||
userPick={userPick} | ||
onWeeklyPickChange={onWeeklyPickChange} | ||
onWeeklyPickChange={handleWeeklyPickChange} | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright (c) Gridiron Survivor. | ||
// Licensed under the MIT License. | ||
|
||
import React from 'react'; | ||
import { createWeeklyPicks } from '@/api/apiFunctions'; | ||
import { parseUserPick } from '@/utils/utils'; | ||
import Alert from '@/components/AlertNotification/AlertNotification'; | ||
import { AlertVariants } from '@/components/AlertNotification/Alerts.enum'; | ||
import { toast } from 'react-hot-toast'; | ||
import { IWeeklyPickChange } from './Week.interface'; | ||
|
||
/** | ||
* Handles the form submission. | ||
* @param props - data, NFLTeams, user, entry, weeklyPicks, league, week, updateWeeklyPicks, setUserPick | ||
* @param props.data - The form data. | ||
* @param props.NFLTeams - Props for NFL teams | ||
* @param props.user - Props for user | ||
* @param props.entry - Prop for the entry string | ||
* @param props.weeklyPicks - Props for the weeklyPicks | ||
* @param props.league - Prop value for the leagueId in createWeeklyPicks | ||
* @param props.week - Prop value for gameWeekId in updateWeeklyPicks | ||
* @param props.updateWeeklyPicks - Prop for the updateWeeklyPicks function | ||
* @param props.setUserPick - Prop for the setUserPick function | ||
* @returns {void} | ||
*/ | ||
export const onWeeklyPickChange = async ({ | ||
data, | ||
entry, | ||
league, | ||
NFLTeams, | ||
setUserPick, | ||
updateWeeklyPicks, | ||
user, | ||
weeklyPicks, | ||
week, | ||
}: IWeeklyPickChange): Promise<void> => { | ||
try { | ||
const teamSelect = data.target.value; | ||
const teamID = NFLTeams.find( | ||
(team) => team.teamName === teamSelect, | ||
)?.teamName; | ||
|
||
const currentUserPick = parseUserPick(user.id, entry, teamID || ''); | ||
|
||
// combines current picks and the user pick into one object. | ||
// if the user pick exists then it overrides the pick of the user. | ||
const updatedWeeklyPicks = { | ||
...weeklyPicks.userResults, | ||
[user.id]: { | ||
...weeklyPicks.userResults[user.id], | ||
[entry]: { | ||
...weeklyPicks.userResults[user.id]?.[entry], | ||
...currentUserPick[user.id][entry], | ||
}, | ||
}, | ||
}; | ||
|
||
// update weekly picks in the database | ||
await createWeeklyPicks({ | ||
leagueId: league, | ||
gameWeekId: week, | ||
userResults: updatedWeeklyPicks, | ||
}); | ||
|
||
// update weekly picks in the data store | ||
updateWeeklyPicks({ | ||
leagueId: league, | ||
gameWeekId: week, | ||
userResults: updatedWeeklyPicks, | ||
}); | ||
|
||
setUserPick(currentUserPick[user.id][entry].teamName); | ||
|
||
toast.custom( | ||
<Alert | ||
variant={AlertVariants.Success} | ||
message={`You have successfully pick the ${ | ||
currentUserPick[user.id][entry].teamName | ||
} for your team!`} | ||
/>, | ||
); | ||
} catch (error) { | ||
console.error('Submission error:', error); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change this to throw a new error and allow the function to catch the error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this basically so that we can more easily catch where the issue lies when it errors? So, the trycatch() being added into handleWeeklyPickChange() and then changing this console.error() will allow us to figure out where an issue lies? |
||
toast.custom( | ||
<Alert | ||
variant={AlertVariants.Error} | ||
message="There was an error processing your request." | ||
/>, | ||
); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this more specific. IData is a generic name that could be for anything. Match the data structure. IWeekData is a much clearer name.