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

ui/ux: update week page #370

Merged
merged 11 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
3 changes: 3 additions & 0 deletions api/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.

import { Client, Account, Databases, ID } from 'appwrite';

const URL = process.env.NEXT_PUBLIC_APPWRITE_API_URL as string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.

import { INFLTeam } from '@/api/apiFunctions.interface';
import { INFLTeam, ILeague } from '@/api/apiFunctions.interface';

export interface IWeekParams {
params: {
Expand All @@ -13,7 +13,7 @@ export interface IWeekParams {

export interface IWeekProps {
entry: string;
league: string;
league: ILeague['leagueId'];
NFLTeams: INFLTeam[];
week: string;
}
96 changes: 63 additions & 33 deletions app/league/[leagueId]/entries/[entryId]/week/Week.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

'use client';
import React, { JSX, useEffect, useState } from 'react';
import { Button } from '@/components/Button/Button';
import {
FormField,
FormItem,
Expand All @@ -19,6 +18,10 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { useDataStore } from '@/store/dataStore';
import WeekTeams from './WeekTeams';
import { ISchedule } from './WeekTeams.interface';
import LinkCustom from '@/components/LinkCustom/LinkCustom';
import { ChevronLeft } from 'lucide-react';
import { getCurrentLeague } from '@/api/apiFunctions';
import { ILeague } from '@/api/apiFunctions.interface';

/**
* Renders the weekly picks page.
Expand All @@ -28,12 +31,22 @@ import { ISchedule } from './WeekTeams.interface';
// eslint-disable-next-line no-unused-vars
const Week = ({ league, NFLTeams, week }: IWeekProps): JSX.Element => {
const [schedule, setSchedule] = useState<ISchedule[]>([]);
const [selectedLeague, setSelectedLeague] = useState<ILeague | undefined>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the state be initialized to string? i.e.: const [selectedLeague, setSelectedLeague] = useState<string>('');?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm gonna leave this to @chris-nowicki, since he helped me with this by implementing it Though, initializing it to a string makes sense to me!

const [isLoading, setIsLoading] = useState<boolean>(true);
const [userPick, setUserPick] = useState<string>('');

const { user, updateWeeklyPicks, weeklyPicks } = useDataStore(
(state) => state,
);

/**
* Fetches the selected league.
* @returns {Promise<void>}
*/
const getSelectedLeague = async (): Promise<void> => {
const res = await getCurrentLeague(league);
setSelectedLeague(res);
};

const NFLTeamsList = NFLTeams.map((team) => team.teamName) as [
string,
...string[]
Expand Down Expand Up @@ -110,44 +123,61 @@ const Week = ({ league, NFLTeams, week }: IWeekProps): JSX.Element => {
};

useEffect(() => {
if (!selectedLeague) {
getSelectedLeague();
return;
}
getSchedule(week);
}, [week]);
setIsLoading(false);
}, [week, selectedLeague]);

if (schedule.length === 0) {
if (schedule.length === 0 || isLoading) {
return <p>Loading...</p>;
}

return (
<section className="w-full pt-8" data-testid="weekly-picks">
<h1 className="pb-8 text-center text-[2rem] font-bold text-white">
Your pick sheet
</h1>

<FormProvider {...form}>
<form
className="mx-auto flex w-[90%] max-w-3xl flex-col items-center gap-8"
onSubmit={form.handleSubmit(onSubmit)}
<div>
<nav className="py-6 text-orange-500 hover:no-underline">
<LinkCustom
className="text-orange-500 flex gap-3 items-center font-semibold text-xl hover:no-underline"
href="/league/all"
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the hover:bg-zinc-800 transition from the WeeklyPickButton apply to this still when hovering over it on WeekTeams?

Copy link
Member Author

Choose a reason for hiding this comment

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

IIRC it did in my testing, but now you're making me question myself! I'll confirm tomorrow (7/9/24) and report back.

>
<FormField
control={form.control as Control<object>}
name="type"
render={({ field }) => (
<FormItem>
<FormControl>
<WeekTeams
schedule={schedule}
field={field}
userPick={userPick}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button label="Submit Button" type="submit" />
</form>
</FormProvider>
</section>
<span aria-hidden="true">
<ChevronLeft size={16} />
</span>
{selectedLeague?.leagueName as string}
</LinkCustom>
</nav>
<section className="w-full pt-8" data-testid="weekly-picks">
<h1 className="pb-8 text-center text-[2rem] font-bold text-white">
Week {week} pick
</h1>

<FormProvider {...form}>
<form
className="mx-auto flex w-[90%] max-w-3xl flex-col items-center"
onSubmit={form.handleSubmit(onSubmit)}
>
<FormField
control={form.control as Control<object>}
name="type"
render={({ field }) => (
<FormItem>
<FormControl>
<WeekTeams
schedule={schedule}
field={field}
userPick={userPick}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</FormProvider>
</section>
</div>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface ISchedule {
date: string;
name: string;
shortName: string;
startDate: string;
season: {
year: number;
type: number;
Expand Down
30 changes: 29 additions & 1 deletion app/league/[leagueId]/entries/[entryId]/week/WeekTeams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,31 @@ import { RadioGroup } from '@radix-ui/react-radio-group';
import { IWeekTeamsProps } from './WeekTeams.interface';
import { WeeklyPickButton } from '@/components/WeeklyPickButton/WeeklyPickButton';

/**
* Formats the date to 'day, mon date' format and the time to either 12 or 24-hour format based on the user's locale.
* @param dateStr The date string to format.
* @returns The formatted date and time string.
*/
const formatDateTime = (dateStr: string): string => {
const date = new Date(dateStr);

const dateOptions: Intl.DateTimeFormatOptions = {
weekday: 'short',
month: 'short',
day: 'numeric',
};
const timeOptions: Intl.DateTimeFormatOptions = {
hour: 'numeric',
minute: 'numeric',
hour12: true,
};

const formattedDate = date.toLocaleDateString('en-US', dateOptions);
const formattedTime = date.toLocaleTimeString('en-US', timeOptions);

return `${formattedDate} ・ ${formattedTime}`;
};

/**
* Renders the weekly picks page.
* @param props The parameters for the weekly picks page.
Expand All @@ -26,8 +51,11 @@ const WeekTeams = ({
onValueChange={field.onChange}
defaultValue={userPick}
key={scheduledGame.id}
className="grid w-full grid-cols-2 gap-4"
className="grid w-full grid-cols-2 gap-4 pb-8"
>
<div className="week-page-game-schedule col-span-2 text-center">
<p>{formatDateTime(scheduledGame.date)}</p>
</div>
{scheduledGame.competitions[0].competitors.map((competition) => (
<FormItem key={competition.id}>
<FormControl>
Expand Down
2 changes: 1 addition & 1 deletion components/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const FormItem = React.forwardRef<
return (
// eslint-disable-next-line react/jsx-no-constructed-context-values
<FormItemContext.Provider value={{ id }}>
<div ref={ref} className={cn('mb-4 w-full', className)} {...props} />
<div ref={ref} className={cn('w-full', className)} {...props} />
</FormItemContext.Provider>
);
});
Expand Down
13 changes: 10 additions & 3 deletions components/LinkCustom/LinkCustom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

import Link from 'next/link';
import React, { JSX } from 'react';
import { cn } from '@/utils/utils';

interface ILinkCustomProps {
children: string;
children: React.ReactNode;
className?: string;
href: string;
}

Expand All @@ -14,12 +16,17 @@ interface ILinkCustomProps {
* @param props - The props
* @param props.children - any additional items you want inside the link. This could include things like the link text, icons, etc.
* @param props.href - this is the URL you want the link to point to
* @param props.className - any additional classes you want to add to that instance of the LinkCustom component.
* @returns The custom link component
*/
const LinkCustom = ({ children, href }: ILinkCustomProps): JSX.Element => {
const LinkCustom = ({
children,
className,
href,
}: ILinkCustomProps): JSX.Element => {
return (
<Link
className={'hover:text-orange-600 hover:underline'}
className={cn('hover:text-orange-600 hover:underline', className)}
data-testid="linkCustom"
href={href}
passHref
Expand Down
7 changes: 6 additions & 1 deletion components/WeeklyPickButton/WeeklyPickButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ const WeeklyPickButton: React.FC<WeeklyPickButtonProps> = ({
}): JSX.Element => {
return (
<div className="flex items-center">
<RadioGroupItem value={team} id={team} data-testid="team-radio" />
<RadioGroupItem
value={team}
id={team}
data-testid="team-radio"
type="submit"
/>
<Label htmlFor={team} data-testid="team-label">
<Image
src={src}
Expand Down
Loading