Skip to content
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

Merged
merged 27 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5f705d6
getting started
alexappleget Jul 15, 2024
138a3d1
Merge remote-tracking branch 'origin/develop' into alex/414-bug-bash-…
alexappleget Jul 15, 2024
1c5c905
decoupled onWeeklyPickChange and writing test now
alexappleget Jul 15, 2024
d78d63f
added toast to test
alexappleget Jul 15, 2024
2066acf
updated tests
alexappleget Jul 15, 2024
b59489c
updated functions
alexappleget Jul 15, 2024
e154977
Merge branch 'develop' into alex/414-bug-bash-add-alert-when-pick-is-…
alexappleget Jul 15, 2024
de6cad1
updated code/tests to show team name when a team is picked
alexappleget Jul 15, 2024
a264ede
deleted unused code
alexappleget Jul 16, 2024
29ee3ce
updated type for setUserPick
alexappleget Jul 16, 2024
9e0f3c6
did some voodoo
alexappleget Jul 16, 2024
0b0e05d
alphabetized params
alexappleget Jul 17, 2024
e4ee42d
made changes to handle PR comments
alexappleget Jul 17, 2024
1e89efb
Merge remote-tracking branch 'origin/develop' into alex/414-bug-bash-…
alexappleget Jul 17, 2024
11d5a02
Fix: Moved IData props into Week.interface.ts
alexappleget Jul 19, 2024
1236a94
Fix: Moved onWeeklyPickChange() type objects into Week.interface.ts
alexappleget Jul 19, 2024
1f26a02
Merge branch 'develop' into alex/414-bug-bash-add-alert-when-pick-is-…
alexappleget Jul 19, 2024
f885dfe
Merge branch 'develop' into alex/414-bug-bash-add-alert-when-pick-is-…
alexappleget Jul 19, 2024
9b95801
Merge remote-tracking branch 'origin/develop' into alex/414-bug-bash-…
alexappleget Jul 19, 2024
d739aa1
Merge branch 'develop' into alex/414-bug-bash-add-alert-when-pick-is-…
Clue355 Jul 20, 2024
4e9475b
Merge branch 'develop' into alex/414-bug-bash-add-alert-when-pick-is-…
alexappleget Jul 22, 2024
94eb8cb
Merge branch 'alex/414-bug-bash-add-alert-when-pick-is-upda' of https…
alexappleget Jul 22, 2024
8bd9efb
Fix: delete 'as any' type from 'data' inside week.test. Wasn't needed.
alexappleget Jul 22, 2024
cd074b3
Merge remote-tracking branch 'origin/develop' into alex/414-bug-bash-…
alexappleget Jul 22, 2024
baa8836
Merge branch 'develop' into alex/414-bug-bash-add-alert-when-pick-is-…
alexappleget Jul 26, 2024
4933a40
Fix: Added trycatch() to handleWeeklyPickChange(), added a throw erro…
alexappleget Jul 26, 2024
1473a7a
Fix: Changed errors to better understand where an issue will be.
alexappleget Jul 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Collaborator

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.

target: {
value: string;
};
}

export interface IWeekParams {
params: {
Expand All @@ -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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have an ENUM for the weeks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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

Copy link
Collaborator

Choose a reason for hiding this comment

The 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'];
Expand Down
126 changes: 126 additions & 0 deletions app/(main)/league/[leagueId]/entry/[entryId]/week/Week.test.tsx
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."
/>,
);
});
});
62 changes: 17 additions & 45 deletions app/(main)/league/[leagueId]/entry/[entryId]/week/Week.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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.
Expand Down Expand Up @@ -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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a try/catch here.

};

useEffect(() => {
Expand Down Expand Up @@ -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 />
Expand Down
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);
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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."
/>,
);
}
};