Skip to content

Commit

Permalink
chore: consume standings data from server
Browse files Browse the repository at this point in the history
Initialize the use of standings data from the server
Refactor the drivers and constructors standings ui
Include results type declarations at results.d.ts
Update faker data to match standings schema
  • Loading branch information
Lombardoc4 committed Jan 22, 2024
1 parent 7a30bb2 commit 50afa96
Show file tree
Hide file tree
Showing 10 changed files with 320 additions and 165 deletions.
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm typecheck
npx lint-staged
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"typecheck": "tsc --pretty --noEmit --incremental false"
},
"dependencies": {
"axios": "^1.6.5",
"axios": "latest",
"clsx": "latest",
"jotai": "latest",
"jotai-effect": "latest",
Expand Down
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 34 additions & 64 deletions src/app/lib/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,64 +40,7 @@ export const f1Seasons = (): string[] => {
);
};

export interface ISchedule {
RoundNumber: number;
Country: string;
Location: string;
OfficialEventName: string;
EventDate: string;
EventName: string;
EventFormat: string;
Session1: string;
Session1Date: string;
Session1DateUtc: string;
Session2: string;
Session2Date: string;
Session2DateUtc: string;
Session3: string;
Session3Date: string;
Session3DateUtc: string;
Session4: string;
Session4Date: string;
Session4DateUtc: string;
Session5: string;
Session5Date: string;
Session5DateUtc: string;
F1ApiSupport: boolean;
}

// Raw Fetch Format
export type IConstructorStandingsFetch = {
[key in 'position' | 'points' | 'wins']: string;
} & {
Constructor: {
name: string;
};
};
// UI format
export type IConstructorStandings = {
[key in 'pos' | 'points' | 'wins' | 'name']: string;
};

interface IDataConfigs {
seasons: string[];
schedule: ISchedule[];
drivers: string[];
sessions: string[];
standings: {
// drivers: {
// position: string,
// points: string,
// wins: string,
// Constructor?: {
// name: string,
// }
// }[],
constructors: IConstructorStandingsFetch[];
};
}

const dataConfig: IDataConfigs = {
const dataConfig: DataConfigSchema = {
seasons: f1Seasons(),
schedule: Array.from(Array(3).keys()).map(() => ({
RoundNumber: 0,
Expand Down Expand Up @@ -134,21 +77,48 @@ const dataConfig: IDataConfigs = {
],
sessions: ['Practice 1', 'Practice 2', 'Practice 3', 'Qualifying', 'Race'],
standings: {
// drivers: {

// },
constructors: Array.from(Array(10).keys()).map(() => ({
DriverStandings: Array.from(Array(5).keys()).map(() => ({
positionText: faker.number.int(20).toString(),
position: faker.number.int(20).toString(),
points: faker.number.int(25).toString(),
wins: faker.number.int(10).toString(),
Driver: {
driverId: faker.person.middleName(),
permanentNumber: faker.number.int(99).toString(),
code: faker.word.sample(3),
url: faker.internet.domainName(),
givenName: faker.person.firstName(),
familyName: faker.person.lastName(),
dateOfBirth: faker.date.birthdate().toString(),
nationality: faker.location.country(),
},
Constructors: [
{
constructorId: faker.person.middleName(),
url: faker.internet.domainName(),
name: faker.person.middleName(),
nationality: faker.location.country(),
},
],
})),
ConstructorStandings: Array.from(Array(5).keys()).map(() => ({
positionText: faker.number.int(20).toString(),
position: faker.number.int(20).toString(),
points: faker.number.int(25).toString(),
wins: faker.number.int(10).toString(),
Constructor: {
constructorId: faker.person.middleName(),
url: faker.internet.domainName(),
name: faker.person.middleName(),
nationality: faker.location.country(),
},
})),
season: 0,
round: 0,
},
};

const serverURL = 'http://0.0.0.0:8081';
const serverURL = 'http://127.0.0.1:8081';
export const fetchAPI = async (
endpoint: string,
statusCheck: boolean = false,
Expand All @@ -158,7 +128,7 @@ export const fetchAPI = async (
const options = statusCheck ? { headers: { cache: 'no-store' } } : {};

// Get dummy data or return false
const dummy: string[] | ISchedule[] | false =
const dummy: string[] | ScheduleSchema[] | false =
dataConfig[
endpoint.split('?')[0] as 'seasons' | 'schedule' | 'drivers' | 'sessions'
] || false;
Expand Down
6 changes: 2 additions & 4 deletions src/app/results/RaceResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { useMemo } from 'react';

import { seasonRacesAtom } from '@/atoms/results';

import { ISchedule } from '../lib/utils';

const ResultCard = ({ data }: { data: ISchedule }) => {
const ResultCard = ({ data }: { data: ScheduleSchema }) => {
const eventDate = new Date(data.EventDate);
const eventPassed = new Date() > eventDate;

Expand Down Expand Up @@ -49,7 +47,7 @@ const ResultCard = ({ data }: { data: ISchedule }) => {
);
};

const WinterTesting = ({ data }: { data: ISchedule }) => {
const WinterTesting = ({ data }: { data: ScheduleSchema }) => {
const eventDate = new Date(data.EventDate);
const eventPassed = new Date() > eventDate;

Expand Down
79 changes: 18 additions & 61 deletions src/app/results/SeasonResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,76 +2,33 @@

import { useAtom } from 'jotai';

import { constructorStandingsAtom, fetchStandings } from '@/atoms/results';
import {
constructorStandingsAtom,
driverStandingsAtom,
fetchStandings,
} from '@/atoms/results';

import { RaceSchedule } from './RaceResults';
import { driverData, DriverHeadings } from '../lib/placerholder-results';
import { IConstructorStandings, positionEnding } from '../lib/utils';
import { Table } from '../ui/Table';
import { StandingsTimeline } from './StandingsTimeline';
import { Tabs } from '../ui/Tabs';

const ConstuctorHeadings = ['position', 'points', 'wins', 'name'];

const ConstructorCard = ({ data }: { data: IConstructorStandings }) => (
<div className='card overflow-hidden bg-base-100 shadow-xl'>
<div className='card-body px-0 pb-4 pt-2'>
<h3 className='card-title max-w-64'>
{positionEnding(data.pos)} {data.name}
</h3>
<div className='flex'>
<p className='flex-1'>
Points:
<br />
{data.points}
</p>
<p className='flex-1'>
Wins:
<br />
{data.wins}
</p>
</div>
</div>
</div>
);

const ConstructorResults = () => {
const [constructorStandings] = useAtom(constructorStandingsAtom);
export default function ResultsPage() {
useAtom(fetchStandings);
const [constructorStandings] = useAtom(constructorStandingsAtom);
const [driverStandings] = useAtom(driverStandingsAtom);

return (
<>
<div className='mt-8 grid gap-8 lg:hidden'>
{constructorStandings.map((constructor) => (
<ConstructorCard key={constructor.name} data={constructor} />
))}
</div>
<div className='hidden lg:block'>
<Table
key='Constructors Championship'
headings={ConstuctorHeadings}
data={constructorStandings}
/>
</div>
</>
);
};

const tabHeaders = ['Races', 'Drivers', 'Constructors'];
const tabs = [
<RaceSchedule key='Race Results' />,
<Table
key='Drivers Championship'
headings={DriverHeadings}
data={driverData}
/>,
];

export default function ResultsPage() {
return (
<main>
<Tabs
headers={tabHeaders}
containers={[...tabs, <ConstructorResults key='ConstructorResults' />]}
headers={['Races', 'Drivers', 'Constructors']}
containers={[
<RaceSchedule key='Race Results' />,
<StandingsTimeline key='Driver Standings' data={driverStandings} />,
<StandingsTimeline
key='Constructor Standings'
data={constructorStandings}
/>,
]}
/>
</main>
);
Expand Down
Loading

0 comments on commit 50afa96

Please sign in to comment.