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

Shashi/disable game time #584

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8840b9d
finshed implementing admin menu dropdown
Clue355 Aug 28, 2024
270fcad
completed adding tests and edit profile button directs to /admin/edit…
Clue355 Aug 28, 2024
8aacdcd
attempt at fixing errors
Clue355 Aug 28, 2024
b8cd18b
edit to edit profile route
Clue355 Aug 29, 2024
7a38476
added route change function
Clue355 Aug 29, 2024
d4240cc
added more comments and correct return values
Clue355 Aug 29, 2024
a63b39b
added more jsdoc comments to the /user/edit page
Clue355 Aug 29, 2024
0a4555e
small edit to border stlying to look like figma
Clue355 Sep 4, 2024
f43e026
small edit to styling
Clue355 Sep 4, 2024
e44a123
UI/UX: re-implement league entries UI (#468)
ryandotfurrer Sep 4, 2024
711bae3
#496 Chris/Limit-User-Entries (#498)
chris-nowicki Sep 5, 2024
cb516d6
added in code to fetch all leagues (#491)
vmaineng Sep 5, 2024
39b2646
feat #315: Make a selection page updates (#447)
jennifertieu Sep 5, 2024
82d4d38
delete user layout
Clue355 Sep 10, 2024
6d1f156
deleted blank space in api functions
Clue355 Sep 10, 2024
32a0357
Merge branch 'develop' into clue355/implement-menu-dropdown
Clue355 Sep 10, 2024
43ab662
Merge branch 'develop' into clue355/implement-menu-dropdown
Clue355 Sep 10, 2024
1624e58
update
Clue355 Sep 10, 2024
18e7fb9
deleted merge conflics
Clue355 Sep 10, 2024
c7548a4
fixed tests
Clue355 Sep 11, 2024
806ba0c
implemented shashi changes
Clue355 Sep 12, 2024
ab630c7
changes to text hover color
Clue355 Sep 12, 2024
dc96191
Merge branch 'develop' into clue355/implement-menu-dropdown
Clue355 Sep 12, 2024
131ea7c
Update page.test.tsx
Clue355 Sep 16, 2024
ecfe368
added back spaces
Clue355 Sep 16, 2024
1f8af16
added back spaces
Clue355 Sep 16, 2024
bca6971
Merge branch 'develop' of https://github.com/LetsGetTechnical/gridiro…
ryandotfurrer Sep 20, 2024
989eb27
refine stylig of AdminUserSettings component and merge in develop
ryandotfurrer Sep 20, 2024
bbac284
update adminusersettings test
ryandotfurrer Sep 20, 2024
2652962
Merge branch 'develop' into clue355/implement-menu-dropdown
Clue355 Oct 1, 2024
a94fc7c
Disable teams if the date has eclipsed by current time minus 1 hour
shashilo Oct 4, 2024
8e300ab
Remove unit tests until we mock Date()
shashilo Oct 4, 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
93 changes: 59 additions & 34 deletions app/(main)/league/[leagueId]/entry/[entryId]/week/WeekTeams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ const formatDateTime = (dateString: string): string => {
return `${formattedDate} ・ ${formattedTime}`;
};

/**
* Checks if the current game time is within 1 hour of the current time.
* @param gameTime The game time to check.
* @returns True if the current game time is within 1 hour of the current time, false otherwise.
*/
const checkCurrentGameTime = (gameTime: string): boolean => {
const timestampStr = gameTime;
const timestamp = new Date(timestampStr);
Comment on lines +43 to +44
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I feel like this should just be new Date(gameTime), seems redundant to have timestampStr here.

const currentTime = new Date();

// Subtract 1 hour from the current time
const currentTimeMinus1Hour = new Date(
Comment on lines +47 to +48
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: the function name is self-explanatory here, so the comment here is redundant

currentTime.getTime() - 60 * 60 * 1000,
);

return currentTimeMinus1Hour > timestamp;
};

/**
* Renders the weekly picks page.
* @param props The parameters for the weekly picks page.
Expand All @@ -59,41 +77,48 @@ const WeekTeams = ({
value={userPick}
onChange={field.onChange}
>
{schedule.map((scheduledGame) => (
<div
className="grid w-full grid-cols-[1fr_auto_1fr] gap-4 pb-8"
style={{ direction: 'rtl' }}
key={scheduledGame.id}
>
<div className="week-page-game-schedule col-span-3 text-center">
<p>{formatDateTime(scheduledGame.date)}</p>
{schedule.map((scheduledGame) => {
const disableGame = checkCurrentGameTime(scheduledGame.date);

return (
<div
className="grid w-full grid-cols-[1fr_auto_1fr] gap-4 pb-8"
style={{ direction: 'rtl' }}
key={scheduledGame.id}
>
<div className="week-page-game-schedule col-span-3 text-center">
<p>{formatDateTime(scheduledGame.date)}</p>
</div>
{scheduledGame.competitions[0].competitors.map(
(competition, index) => (
<>
{index > 0 && (
<div className="h-20 flex self-end items-center">
<span>@</span>
</div>
)}
<FormItem key={competition.id} className="text-center">
<FormControl>
<WeeklyPickButton
loadingTeamName={loadingTeamName}
selectedTeam={competition.team.shortDisplayName.toLowerCase()}
homeAway={competition.homeAway}
team={competition.team.name}
src={competition.team.logo}
isDisabled={
disableGame ||
Boolean(loadingTeamName) ||
hasTeamBeenPicked(competition.team.name, selectedTeams)
}
/>
</FormControl>
</FormItem>
</>
),
)}
</div>
{scheduledGame.competitions[0].competitors.map((competition, index) => (
<>
{index > 0 && (
<div className="h-20 flex self-end items-center">
<span>@</span>
</div>
)}
<FormItem key={competition.id} className="text-center">
<FormControl>
<WeeklyPickButton
loadingTeamName={loadingTeamName}
selectedTeam={competition.team.shortDisplayName.toLowerCase()}
homeAway={competition.homeAway}
team={competition.team.name}
src={competition.team.logo}
isDisabled={
Boolean(loadingTeamName) ||
hasTeamBeenPicked(competition.team.name, selectedTeams)
}
/>
</FormControl>
</FormItem>
</>
))}
</div>
))}
);
})}
</RadioGroup>
);
export default WeekTeams;
23 changes: 22 additions & 1 deletion components/AdminNav/AdminNav.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
import { AdminNav } from './AdminNav';
import { AuthContextProvider } from '@/context/AuthContextProvider';
import { render, screen } from '@testing-library/react';
import React from 'react';

const mockPush = jest.fn();
const mockUsePathname = jest.fn();

jest.mock('next/navigation', () => ({
useRouter() {
return {
push: mockPush,
};
},
usePathname() {
return mockUsePathname();
},
}));

describe('AdminNav Component', () => {
beforeEach(() => {
render(<AdminNav />);
jest.clearAllMocks();

render(
<AuthContextProvider>
<AdminNav />
</AuthContextProvider>,
);
});

it('should render the navigation links with correct href attributes', () => {
Expand Down
90 changes: 88 additions & 2 deletions components/AdminUserSettings/AdminUserSettings.test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,98 @@
import { AdminUserSettings } from './AdminUserSettings';
import { render, screen } from '@testing-library/react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import React from 'react';

const mockPush = jest.fn();
const mockUsePathname = jest.fn();
const mockLogoutAccount = jest.fn();

const mockUseAuthContext = {
logoutAccount: mockLogoutAccount,
};

jest.mock('../../context/AuthContextProvider', () => ({
useAuthContext() {
return {
...mockUseAuthContext,
};
},
}));

jest.mock('next/navigation', () => ({
useRouter() {
return {
push: mockPush,
};
},
usePathname() {
return mockUsePathname();
},
}));

describe('AdminUserSettings Component', () => {
it('should render the component', () => {
beforeEach(() => {
jest.clearAllMocks();

render(<AdminUserSettings />);
});

it('should render the component', async () => {
const adminUserSettings = screen.getByTestId('admin-user-settings');

expect(adminUserSettings).toBeInTheDocument();
});

it('should show user options when clicked', () => {
const adminUserSettings = screen.getByTestId('admin-user-settings');

fireEvent.click(adminUserSettings);

waitFor(() => {
expect(screen.getByTestId('edit-profile-link')).toBeInTheDocument();
expect(screen.getByTestId('sign-out-button')).toBeInTheDocument();
});
});

it('should not show user options when closed', () => {
const adminUserSettings = screen.getByTestId('admin-user-settings');

fireEvent.click(adminUserSettings);

fireEvent.click(adminUserSettings);

waitFor(() => {
expect(screen.getByTestId('edit-profile-link')).not.toBeInTheDocument();
expect(screen.getByTestId('sign-out-button')).not.toBeInTheDocument();
});
});

it('should direct to /admin/edit-profile route when the edit profile button is clicked', () => {
const adminUserSettings = screen.getByTestId('admin-user-settings');

fireEvent.click(adminUserSettings);

waitFor(() => {
const editProfileButton = screen.getByTestId('edit-profile-link');
fireEvent.click(editProfileButton);
});

waitFor(() => {
expect(mockPush).toHaveBeenCalledWith('/user/edit');
});
});

it('should direct to /login route when the sign out button is clicked', () => {
const adminUserSettings = screen.getByTestId('admin-user-settings');

fireEvent.click(adminUserSettings);

waitFor(() => {
const signOutButton = screen.getByTestId('sign-out-button');
fireEvent.click(signOutButton);
});

waitFor(() => {
expect(mockPush).toHaveBeenCalledWith('/login');
});
});
});
80 changes: 65 additions & 15 deletions components/AdminUserSettings/AdminUserSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,75 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.

'use client';
import React, { JSX } from 'react';
import { Button } from '../Button/Button';
import { useDataStore } from '@/store/dataStore';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '../TableDropDownMenu/TableDropDownMenu';
import { LucideChevronsUpDown } from 'lucide-react';
import React from 'react';
import { useAuthContext } from '@/context/AuthContextProvider';
import { useRouter } from 'next/navigation';
import LinkCustom from '../LinkCustom/LinkCustom';

/**
* The admin user settings component.
* @returns The rendered admin user settings.
* Renders admin user settings.
* @returns {JSX.Element} The rendered admin user settings component.
*/
export const AdminUserSettings = (): React.JSX.Element => {
export const AdminUserSettings = (): JSX.Element => {
const router = useRouter();
const { logoutAccount } = useAuthContext();
const { user } = useDataStore((state) => state);

/**
* Handles the logout.
* @returns {Promise<void>} The logout promise.
*/
const handleLogout = async (): Promise<void> => {
try {
await logoutAccount();
router.push('/login');
} catch (error) {
throw new Error('Logout failed');
}
};

return (
<div
className="admin-user-settings flex gap-2 px-2 py-2 items-center outline outline-border rounded text-foreground"
data-testid="admin-user-settings"
>
<span className="bg-cyan-500 w-8 h-8 rounded-full" />
<p>Users Name</p>
<LucideChevronsUpDown
className="ml-auto text-muted-foreground"
size={16}
/>
</div>
<DropdownMenu>
<DropdownMenuTrigger
className="w-56 focus:outline-none mx-auto"
data-testid="admin-user-settings"
>
<div className="admin-user-settings w-full flex space-between gap-2 px-2 py-2 items-center border border-border rounded-lg text-foreground overflow-hidden">
<span className="bg-cyan-500 w-8 h-8 rounded-full" />
<p className="truncate ... w-36 ">{user.email}</p>
<LucideChevronsUpDown className="text-muted-foreground" size={16} />
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className="border border-border rounded-lg p-0 w-56 ">
<DropdownMenuItem className="cursor-pointer rounded-b-none flex focus:bg-muted">
<LinkCustom
className="text-base no-underline hover:text-foreground w-full py-2 px-0 text-muted-foreground hover:underline"
href="#"
data-testid="edit-profile-link"
>
Edit Profile
</LinkCustom>
</DropdownMenuItem>
<DropdownMenuItem className="cursor-pointer rounded-none focus:bg-muted">
<Button
className="w-full text-base no-underline py-2 px-0 h-auto text-muted-foreground hover:text-foreground font-normal justify-normal hover:underline"
variant="link"
label="Sign Out"
onClick={handleLogout}
data-testid="sign-out-button"
/>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
};
Loading