From 33339ef8906f80361f75af8b34372d4be1304874 Mon Sep 17 00:00:00 2001 From: belmirofss Date: Wed, 15 Nov 2023 11:31:56 -0300 Subject: [PATCH] layout adjustments --- app.json | 4 +- src/Routes.tsx | 2 + src/components/ListItemQualifying.tsx | 2 +- src/components/ListItemRace.tsx | 61 ++++++++++------- src/components/SectionContainer.tsx | 50 ++++++++------ src/constants.ts | 1 + src/hooks/useRaceSchedule.ts | 27 ++++++++ src/index.d.ts | 1 + src/screens/Home/HomeNextRace.tsx | 26 ++++--- src/screens/RaceResult/RaceQualifying.tsx | 18 +++-- src/screens/RaceResult/RaceResult.tsx | 15 +++- src/screens/RaceResult/RaceResultSprint.tsx | 18 +++-- src/screens/RaceSchedule/RaceSchedule.tsx | 41 +++++++++++ src/screens/RaceSchedule/RaceScheduleInfo.tsx | 68 +++++++++++++++++++ src/types.ts | 21 ++++-- 15 files changed, 279 insertions(+), 76 deletions(-) create mode 100644 src/hooks/useRaceSchedule.ts create mode 100644 src/screens/RaceSchedule/RaceSchedule.tsx create mode 100644 src/screens/RaceSchedule/RaceScheduleInfo.tsx diff --git a/app.json b/app.json index a38a55b..dd6b247 100644 --- a/app.json +++ b/app.json @@ -3,7 +3,7 @@ "name": "F1HUB", "slug": "f1hub", "scheme": "com.yabcompany.f1hub", - "version": "2.0.0", + "version": "2.1.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", @@ -20,7 +20,7 @@ }, "android": { "package": "com.yabcompany.f1hub", - "versionCode": 7, + "versionCode": 8, "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#121212" diff --git a/src/Routes.tsx b/src/Routes.tsx index 5dad17a..9950f23 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -11,6 +11,7 @@ import { Home } from "./screens/Home/Home"; import { Archive } from "./screens/Archive/Archive"; import { About } from "./screens/About/About"; import { RaceResult } from "./screens/RaceResult/RaceResult"; +import { RaceSchedule } from "./screens/RaceSchedule/RaceSchedule"; type BottomNavigatorProps = { initialRouteName: string; @@ -216,6 +217,7 @@ export const Routes = () => { + ); }; diff --git a/src/components/ListItemQualifying.tsx b/src/components/ListItemQualifying.tsx index f2c4ec2..7b0b8a1 100644 --- a/src/components/ListItemQualifying.tsx +++ b/src/components/ListItemQualifying.tsx @@ -38,7 +38,7 @@ export const ListItemQualifying = ({ result }: Props) => { - + ); diff --git a/src/components/ListItemRace.tsx b/src/components/ListItemRace.tsx index 6fc7cab..bdacf7d 100644 --- a/src/components/ListItemRace.tsx +++ b/src/components/ListItemRace.tsx @@ -33,15 +33,12 @@ export const ListItemRace = ({ race }: Props) => { return ( - navigation.navigate("RaceResult", { - season: race.season, - round: race.round, - raceName: race.raceName, - }) - : undefined + onClick={() => + navigation.navigate(existResults ? "RaceResult" : "RaceSchedule", { + season: race.season, + round: race.round, + raceName: race.raceName, + }) } > { - - {formatDate(race.date, race.time)} - + + + {formatDate(race.date, race.time)}{" "} + + {!existResults && ( + + + | SOON + + + )} + + {race.raceName} {race.Circuit.circuitName} @@ -82,11 +101,7 @@ export const ListItemRace = ({ race }: Props) => { - + ); diff --git a/src/components/SectionContainer.tsx b/src/components/SectionContainer.tsx index 8bc1629..c27f645 100644 --- a/src/components/SectionContainer.tsx +++ b/src/components/SectionContainer.tsx @@ -1,6 +1,6 @@ import { ReactNode, useState } from "react"; import { View } from "react-native"; -import { Text, IconButton } from "react-native-paper"; +import { Text, IconButton, ActivityIndicator } from "react-native-paper"; import { Theme } from "../theme"; import { SectionTitle } from "./SectionTitle"; import { Loading } from "./Loading"; @@ -37,13 +37,15 @@ export const SectionContainer = ({ setContentVisible((isVisible) => !isVisible)} rippleColor={Theme.colors.darken} - disabled={!expansable} + disabled={!expansable || isLoading} > {name} @@ -54,25 +56,28 @@ export const SectionContainer = ({ iconColor={Theme.colors.primary} /> )} + {isLoading && ( + + )} - {isLoading ? ( - - ) : isError ? ( - - ) : ( - <> - + + {contentVisible && ( + <> {title && ( {right} - - {contentVisible && children} - - )} + + )} + + + {contentVisible && <>{isError ? : children}} ); }; diff --git a/src/constants.ts b/src/constants.ts index aef21af..51ad38f 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,3 +1,4 @@ +export const YEAR_SPRINT_RACES_STARTED = 2021; export const F1_API = "https://ergast.com/api/f1/"; export const COUNTRY_FLAGS_URL = "https://flagsapi.com/"; export const BUY_ME_A_COFFEE_URL = "https://www.buymeacoffee.com/belmirofss"; diff --git a/src/hooks/useRaceSchedule.ts b/src/hooks/useRaceSchedule.ts new file mode 100644 index 0000000..951af81 --- /dev/null +++ b/src/hooks/useRaceSchedule.ts @@ -0,0 +1,27 @@ +import { useQuery } from "react-query"; +import { Api } from "../api"; +import { Race } from "../types"; + +type Response = { + MRData: { + RaceTable: { + season: "string"; + Races: Race[]; + }; + }; +}; + +type Props = { + season: string; + round: string; +}; + +export const useRaceSchedule = ({ season, round }: Props) => { + return useQuery( + ["RACE_SCHEDULE", season, round], + () => Api.get(`${season}/${round}.json`), + { + select: (response) => response.data, + } + ); +}; diff --git a/src/index.d.ts b/src/index.d.ts index 6fa043f..8e62a17 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -2,6 +2,7 @@ export declare global { namespace ReactNavigation { interface RootParamList { RaceResult: { season: string; round: string; raceName: string }; + RaceSchedule: { season: string; round: string; raceName: string }; } } diff --git a/src/screens/Home/HomeNextRace.tsx b/src/screens/Home/HomeNextRace.tsx index d34abbc..739c5cf 100644 --- a/src/screens/Home/HomeNextRace.tsx +++ b/src/screens/Home/HomeNextRace.tsx @@ -42,13 +42,15 @@ export const HomeNextRace = () => { /> )} - + {nextRace.Qualifying && ( + + )} - {!nextRace.Sprint && ( + {!nextRace.Sprint && nextRace.SecondPractice && ( { /> )} - + {nextRace.FirstPractice && ( + + )} )} diff --git a/src/screens/RaceResult/RaceQualifying.tsx b/src/screens/RaceResult/RaceQualifying.tsx index 1b2d5bf..ad11def 100644 --- a/src/screens/RaceResult/RaceQualifying.tsx +++ b/src/screens/RaceResult/RaceQualifying.tsx @@ -1,6 +1,8 @@ +import { Text } from "react-native-paper"; import { ListItemQualifying } from "../../components/ListItemQualifying"; import { SectionContainer } from "../../components/SectionContainer"; import { useQualifyingResults } from "../../hooks/useQualifyingResults"; +import { Theme } from "../../theme"; type Props = { season: string; @@ -13,10 +15,6 @@ export const RaceQualifyingResults = ({ season, round }: Props) => { const race = data?.MRData.RaceTable.Races[0]; const results = race?.QualifyingResults; - if (!isLoading && !isError && !results?.length) { - return null; - } - return ( { {results?.map((result) => ( ))} + + {!results?.length && ( + + No qualifying results available + + )} ); }; diff --git a/src/screens/RaceResult/RaceResult.tsx b/src/screens/RaceResult/RaceResult.tsx index 940f1d3..1de79df 100644 --- a/src/screens/RaceResult/RaceResult.tsx +++ b/src/screens/RaceResult/RaceResult.tsx @@ -7,6 +7,7 @@ import { Theme } from "../../theme"; import { Text } from "react-native-paper"; import { RaceResultSprint } from "./RaceResultSprint"; import { RaceQualifyingResults } from "./RaceQualifying"; +import { useRaceSchedule } from "../../hooks/useRaceSchedule"; type ParamList = { RaceResult: { @@ -20,8 +21,18 @@ export const RaceResult = () => { const route = useRoute>(); const { season, round, raceName } = route.params; + const { data, isLoading, isError } = useRaceSchedule({ season, round }); + + const race = data?.MRData.RaceTable.Races[0]; + return ( - + { > - + {race?.Sprint && } diff --git a/src/screens/RaceResult/RaceResultSprint.tsx b/src/screens/RaceResult/RaceResultSprint.tsx index eab1068..df2cfdf 100644 --- a/src/screens/RaceResult/RaceResultSprint.tsx +++ b/src/screens/RaceResult/RaceResultSprint.tsx @@ -1,6 +1,8 @@ +import { Text } from "react-native-paper"; import { ListItemResult } from "../../components/ListItemResult"; import { SectionContainer } from "../../components/SectionContainer"; import { useSprintResults } from "../../hooks/useSprintResults"; +import { Theme } from "../../theme"; type Props = { season: string; @@ -13,10 +15,6 @@ export const RaceResultSprint = ({ season, round }: Props) => { const race = data?.MRData.RaceTable.Races[0]; const results = race?.SprintResults; - if (!isLoading && !isError && !results?.length) { - return null; - } - return ( { {results?.map((result) => ( ))} + + {!results?.length && ( + + No sprint race + + )} ); }; diff --git a/src/screens/RaceSchedule/RaceSchedule.tsx b/src/screens/RaceSchedule/RaceSchedule.tsx new file mode 100644 index 0000000..e9fbc60 --- /dev/null +++ b/src/screens/RaceSchedule/RaceSchedule.tsx @@ -0,0 +1,41 @@ +import { useRoute, RouteProp } from "@react-navigation/native"; +import { View } from "react-native"; +import { ScreenContainer } from "../../components/ScreenContainer"; +import { Theme } from "../../theme"; +import { Text } from "react-native-paper"; +import { RaceScheduleInfo } from "./RaceScheduleInfo"; + +type ParamList = { + RaceSchedule: { + season: string; + round: string; + raceName: string; + }; +}; + +export const RaceSchedule = () => { + const route = useRoute>(); + const { season, round, raceName } = route.params; + + return ( + + + {raceName} + + + + + + + ); +}; diff --git a/src/screens/RaceSchedule/RaceScheduleInfo.tsx b/src/screens/RaceSchedule/RaceScheduleInfo.tsx new file mode 100644 index 0000000..8adb085 --- /dev/null +++ b/src/screens/RaceSchedule/RaceScheduleInfo.tsx @@ -0,0 +1,68 @@ +import { View } from "react-native"; +import { Theme } from "../../theme"; +import { InfoItem } from "../../components/InfoItem"; +import { formatDate } from "../../helpers/formatDate"; +import { SectionContainer } from "../../components/SectionContainer"; +import { useRaceSchedule } from "../../hooks/useRaceSchedule"; + +type Props = { + season: string; + round: string; +}; + +export const RaceScheduleInfo = ({ season, round }: Props) => { + const { data, isLoading, isError } = useRaceSchedule({ season, round }); + + const race = data?.MRData.RaceTable.Races[0]; + + return ( + + {race && ( + + + + {race.Sprint && ( + + )} + {race.Qualifying && ( + + )} + {!race.Sprint && race.SecondPractice && ( + + )} + {race.FirstPractice && ( + + )} + + + + + )} + + ); +}; diff --git a/src/types.ts b/src/types.ts index 4acab1d..7484ce8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -53,7 +53,7 @@ export type QualifyingResult = { Q3: string }; -export type Race = { +export type RaceBase = { season: string; round: string; url: string; @@ -61,27 +61,34 @@ export type Race = { Circuit: Circuit; date: string; time?: string; - FirstPractice: { +} + +export type Race = RaceBase & { + FirstPractice?: { + date: string; + time: string; + }; + Qualifying?: { date: string; time: string; }; - Qualifying: { + SecondPractice?: { date: string; time: string; }; - SecondPractice: { + Sprint?: { date: string; time: string; }; }; -export type RaceResults = Race & { +export type RaceResults = RaceBase & { Results?: Result[]; }; -export type RaceSprintResults = Race & { SprintResults?: Result[] }; +export type RaceSprintResults = RaceBase & { SprintResults?: Result[] }; -export type QualifyingResults = Race & { QualifyingResults?: QualifyingResult[] }; +export type QualifyingResults = RaceBase & { QualifyingResults?: QualifyingResult[] }; export type Driver = { driverId: string;