diff --git a/App.tsx b/App.tsx index bc4047d..42fb0a1 100644 --- a/App.tsx +++ b/App.tsx @@ -72,10 +72,10 @@ export default function App() { + - diff --git a/app.json b/app.json index 3c600b2..504d47b 100644 --- a/app.json +++ b/app.json @@ -3,7 +3,7 @@ "name": "F1HUB", "slug": "f1hub", "scheme": "com.yabcompany.f1hub", - "version": "1.1.0", + "version": "1.2.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", @@ -20,7 +20,7 @@ }, "android": { "package": "com.yabcompany.f1hub", - "versionCode": 5, + "versionCode": 6, "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#121212" diff --git a/src/components/FlagIcon.tsx b/src/components/FlagIcon.tsx index 4c2f5b0..64924f2 100644 --- a/src/components/FlagIcon.tsx +++ b/src/components/FlagIcon.tsx @@ -1,20 +1,28 @@ import { Image } from "react-native"; import { Entypo } from "@expo/vector-icons"; import { Theme } from "../theme"; +import { + buildCountryFlagUrlByName, + buildCountryFlagUrlByNationality, +} from "../helpers/countries"; type Props = { - url: string | undefined; + nationality?: string | undefined; + country?: string | undefined; }; -export const FlagIcon = ({ url }: Props) => { - if (!url) { +export const FlagIcon = ({ nationality, country }: Props) => { + const urlByNationality = buildCountryFlagUrlByNationality(nationality ?? ""); + const urlByCountry = buildCountryFlagUrlByName(country ?? ""); + + if (!urlByNationality && !urlByCountry) { return ; } return ( { return ( @@ -34,10 +32,10 @@ export const ListItemConstructor = ({ - + - {constructorName} + {konstructor.name} diff --git a/src/components/ListItemCounter.tsx b/src/components/ListItemCounter.tsx index 74f4d05..dfca9cc 100644 --- a/src/components/ListItemCounter.tsx +++ b/src/components/ListItemCounter.tsx @@ -10,11 +10,11 @@ export const ListItemCounter = ({ value }: Props) => { return ( { return ( @@ -39,12 +35,12 @@ export const ListItemDriver = ({ - + - {givenName} {familyName} + {driver.givenName} {driver.familyName} {constructorName} diff --git a/src/components/ListItemRace.tsx b/src/components/ListItemRace.tsx index ac6d7dd..d828810 100644 --- a/src/components/ListItemRace.tsx +++ b/src/components/ListItemRace.tsx @@ -1,42 +1,47 @@ import { View } from "react-native"; -import { Text, TouchableRipple } from "react-native-paper"; -import { useTimezone } from "../hooks/useTimezone"; +import { Text } from "react-native-paper"; import { ListItemCounter } from "./ListItemCounter"; import { FlagIcon } from "./FlagIcon"; -import { buildCountryFlagUrlByName } from "../helpers/countries"; import { Theme } from "../theme"; -import moment from "moment"; import { ListItemTitle } from "./ListItemTitle"; import { ListItemDescription } from "./ListItemDescription"; import { Ionicons } from "@expo/vector-icons"; import { ListItem } from "./ListItem"; import { useNavigation } from "@react-navigation/native"; +import { useLastRaceResults } from "../hooks/useLastRaceResults"; +import { Race } from "../types"; +import { formatDate } from "../helpers/formatDate"; export type Props = { - season: string; - round: string; - country: string; - date: string; - time: string; - raceName: string; - circuitName: string; + race: Race; }; -export const ListItemRace = ({ - season, - round, - country, - date, - time, - raceName, - circuitName, -}: Props) => { - const timezone = useTimezone(); +export const ListItemRace = ({ race }: Props) => { const navigation = useNavigation(); + const { data, isLoading, isError } = useLastRaceResults(); + + if (isLoading || isError || !data) { + return null; + } + + const lastRace = data.MRData.RaceTable.Races[0]; + const existResults = + Number(race.season) < Number(lastRace.season) || + (Number(race.season) === Number(lastRace.season) && + Number(race.round) <= Number(lastRace.round)); + return ( navigation.navigate("RaceResult", { season, round })} + onClick={ + existResults + ? () => + navigation.navigate("RaceResult", { + season: race.season, + round: race.round, + }) + : undefined + } > - - + + @@ -67,14 +72,20 @@ export const ListItemRace = ({ fontFamily: Theme.fonts.special, }} > - {moment(`${date} ${time}`).tz(timezone).format("MMM DD[,] HH:mm")} + {formatDate(race.date, race.time)} - {raceName} - {circuitName} + {race.raceName} + + {race.Circuit.circuitName} + - + ); diff --git a/src/components/ListItemResult.tsx b/src/components/ListItemResult.tsx new file mode 100644 index 0000000..9743210 --- /dev/null +++ b/src/components/ListItemResult.tsx @@ -0,0 +1,45 @@ +import { ListItemCounter } from "./ListItemCounter"; +import { ListItemTitle } from "./ListItemTitle"; +import { ListItemDescription } from "./ListItemDescription"; +import { FlagIcon } from "./FlagIcon"; +import { View } from "react-native"; +import { ListItem } from "./ListItem"; +import { Theme } from "../theme"; +import { ListItemTime } from "./ListItemTime"; +import { Result } from "../types"; + +export type Props = { + result: Result; +}; + +export const ListItemResult = ({ result }: Props) => { + return ( + + + + + + + + + + + {result.Driver.givenName} {result.Driver.familyName} + + {result.Constructor.name} + + + + + + + ); +}; diff --git a/src/components/ListItemTime.tsx b/src/components/ListItemTime.tsx new file mode 100644 index 0000000..6fd06ea --- /dev/null +++ b/src/components/ListItemTime.tsx @@ -0,0 +1,30 @@ +import { View } from "react-native"; +import { Text } from "react-native-paper"; +import { Theme } from "../theme"; + +type Props = { + time?: string; + status?: string; +}; + +export const ListItemTime = ({ time, status }: Props) => { + const timeAlternative = status?.includes("Lap") ? status : "DNF"; + + return ( + + + {time ?? timeAlternative} + + + ); +}; diff --git a/src/components/Picker.tsx b/src/components/Picker.tsx index ff2687d..1c4af5f 100644 --- a/src/components/Picker.tsx +++ b/src/components/Picker.tsx @@ -4,13 +4,15 @@ import { Button, Menu, Text } from "react-native-paper"; import { MaterialCommunityIcons } from "@expo/vector-icons"; import { Theme } from "../theme"; +type Item = { + value: string; + text: string; +}; + type Props = { label: string; selected: string; - items: { - value: string; - text: string; - }[]; + items: Item[]; onSelection: (value: string) => void; }; diff --git a/src/helpers/formatDate.ts b/src/helpers/formatDate.ts new file mode 100644 index 0000000..9629f30 --- /dev/null +++ b/src/helpers/formatDate.ts @@ -0,0 +1,14 @@ +import moment from "moment-timezone"; + +export const getTimezone = () => moment.tz.guess() + +export const convertToMoment = (date: string, time?: string) => { + return date && time ? moment(`${date} ${time}`) : moment(date); +} + +export const formatDate = (date: string, time?: string) => { + const format = date && time ? "MMM DD[,] HH:mm" : "MMM DD" + const timezone = getTimezone(); + const momentValue = convertToMoment(date, time) + return momentValue.tz(timezone).format(format); +}; diff --git a/src/hooks/useTimezone.ts b/src/hooks/useTimezone.ts deleted file mode 100644 index d218046..0000000 --- a/src/hooks/useTimezone.ts +++ /dev/null @@ -1,5 +0,0 @@ -import moment from "moment-timezone"; - -export const useTimezone = () => { - return moment.tz.guess(); -}; diff --git a/src/screens/Archive/Archive.tsx b/src/screens/Archive/Archive.tsx index 0507758..dc78b8f 100644 --- a/src/screens/Archive/Archive.tsx +++ b/src/screens/Archive/Archive.tsx @@ -47,7 +47,7 @@ export const Archive = () => { {selectedSeason && ( <> - + { )} - + diff --git a/src/screens/Archive/ArchiveCalendar.tsx b/src/screens/Archive/ArchiveCalendar.tsx index 5cad9cc..5fec9ec 100644 --- a/src/screens/Archive/ArchiveCalendar.tsx +++ b/src/screens/Archive/ArchiveCalendar.tsx @@ -21,15 +21,6 @@ export const ArchiveCalendar = ({ season }: Props) => { } return data.MRData.RaceTable.Races.map((race) => ( - + )); }; diff --git a/src/screens/Archive/ArchiveConstructors.tsx b/src/screens/Archive/ArchiveConstructors.tsx index f336008..feabba5 100644 --- a/src/screens/Archive/ArchiveConstructors.tsx +++ b/src/screens/Archive/ArchiveConstructors.tsx @@ -26,8 +26,7 @@ export const ArchiveConstructors = ({ season }: Props) => { key={constructor.Constructor.constructorId} position={constructor.position} points={constructor.points} - constructorName={constructor.Constructor.name} - nationality={constructor.Constructor.nationality} + konstructor={constructor.Constructor} /> ) ); diff --git a/src/screens/Archive/ArchiveDrivers.tsx b/src/screens/Archive/ArchiveDrivers.tsx index a939a6a..f1ffcba 100644 --- a/src/screens/Archive/ArchiveDrivers.tsx +++ b/src/screens/Archive/ArchiveDrivers.tsx @@ -24,12 +24,10 @@ export const ArchiveDrivers = ({ season }: Props) => { key={driver.Driver.driverId} position={driver.position} points={driver.points} - givenName={driver.Driver.givenName} - familyName={driver.Driver.familyName} + driver={driver.Driver} constructorName={driver.Constructors.map( (constructor) => constructor.name ).join(" - ")} - nationality={driver.Driver.nationality} /> ) ); diff --git a/src/screens/Calendar/Calendar.tsx b/src/screens/Calendar/Calendar.tsx index 966bcf9..2699e79 100644 --- a/src/screens/Calendar/Calendar.tsx +++ b/src/screens/Calendar/Calendar.tsx @@ -15,16 +15,7 @@ export const Calendar = () => { ) : ( data.MRData.RaceTable.Races.map((race) => ( - + )) )} diff --git a/src/screens/Home/HomeLastRace.tsx b/src/screens/Home/HomeLastRace.tsx index ef2acc5..b22adaa 100644 --- a/src/screens/Home/HomeLastRace.tsx +++ b/src/screens/Home/HomeLastRace.tsx @@ -1,13 +1,12 @@ import { View } from "react-native"; -import { Text } from "react-native-paper"; +import { Button, Text } from "react-native-paper"; import { Race, Result } from "../../types"; import { SectionContainer } from "../../components/SectionContainer"; -import moment from "moment-timezone"; import { Theme } from "../../theme"; -import { useTimezone } from "../../hooks/useTimezone"; -import { ListItemDriver } from "../../components/ListItemDriver"; import { FlagIcon } from "../../components/FlagIcon"; -import { buildCountryFlagUrlByName } from "../../helpers/countries"; +import { ListItemResult } from "../../components/ListItemResult"; +import { formatDate } from "../../helpers/formatDate"; +import { useNavigation } from "@react-navigation/native"; type Props = { race: Race; @@ -15,18 +14,14 @@ type Props = { }; export const HomeLastRace = ({ race, results }: Props) => { - const timezone = useTimezone(); + const navigation = useNavigation(); return ( - } + right={} > { textAlign: "center", }} > - {moment(`${race.date} ${race.time}`) - .tz(timezone) - .format("MMM DD[,] HH:mm")}{" "} - - Podium + {formatDate(race.date, race.time)} - Podium {results.slice(0, 3).map((result) => ( - + ))} + + ); diff --git a/src/screens/Home/HomeNextRace.tsx b/src/screens/Home/HomeNextRace.tsx index a5cc2ce..089011e 100644 --- a/src/screens/Home/HomeNextRace.tsx +++ b/src/screens/Home/HomeNextRace.tsx @@ -4,7 +4,7 @@ import { HomeNextRaceTime } from "./HomeNextRaceTime"; import { SectionContainer } from "../../components/SectionContainer"; import { SectionTitle } from "../../components/SectionTitle"; import { FlagIcon } from "../../components/FlagIcon"; -import { buildCountryFlagUrlByName } from "../../helpers/countries"; +import { convertToMoment } from "../../helpers/formatDate"; type Props = { races: Race[]; @@ -12,7 +12,7 @@ type Props = { export const HomeNextRace = ({ races }: Props) => { const nextRace = races.filter( - (race) => moment(`${race.date} ${race.time}`) > moment() + (race) => convertToMoment(race.date, race.time) > moment() )[0]; if (!nextRace) { @@ -24,11 +24,7 @@ export const HomeNextRace = ({ races }: Props) => { name="NEXT RACE" title={nextRace.raceName} description={nextRace.Circuit.circuitName} - right={ - - } + right={} > <> { - const timezone = useTimezone(); - - const momentDate = moment(`${date} ${time}`).tz(timezone); + const momentDate = convertToMoment(date, time).tz(getTimezone()); return ( constructor.name ).join(" - ")} - nationality={driver.Driver.nationality} /> ))} @@ -52,8 +50,7 @@ export const HomeStandings = ({ key={constructor.Constructor.constructorId} position={constructor.position} points={constructor.points} - constructorName={constructor.Constructor.name} - nationality={constructor.Constructor.nationality} + konstructor={constructor.Constructor} /> ))} diff --git a/src/screens/RaceResult/RaceResult.tsx b/src/screens/RaceResult/RaceResult.tsx index d472359..14db4c9 100644 --- a/src/screens/RaceResult/RaceResult.tsx +++ b/src/screens/RaceResult/RaceResult.tsx @@ -1,5 +1,3 @@ -import { View } from "react-native"; -import { Text } from "react-native-paper"; import { useRoute, RouteProp } from "@react-navigation/native"; import { ScreenContainer } from "../../components/ScreenContainer"; import { useRaceResults } from "../../hooks/useRaceResult"; diff --git a/src/screens/RaceResult/RaceResultContentInfo.tsx b/src/screens/RaceResult/RaceResultContentInfo.tsx index f55eccc..a54549d 100644 --- a/src/screens/RaceResult/RaceResultContentInfo.tsx +++ b/src/screens/RaceResult/RaceResultContentInfo.tsx @@ -2,16 +2,13 @@ import { View } from "react-native"; import { Theme } from "../../theme"; import { InfoItem } from "../../components/InfoItem"; import { Race } from "../../types"; -import { useTimezone } from "../../hooks/useTimezone"; -import moment from "moment"; +import { formatDate } from "../../helpers/formatDate"; type Props = { race: Race; }; export const RaceResultContentInfo = ({ race }: Props) => { - const timezone = useTimezone(); - return ( { title="Season / Round" value={`${race.season} / ${race.round}`} /> - + + {!!race.Results?.length && ( + + )} ); }; diff --git a/src/screens/RaceResult/RaceResultContentResults.tsx b/src/screens/RaceResult/RaceResultContentResults.tsx index 420f6b2..3be70cc 100644 --- a/src/screens/RaceResult/RaceResultContentResults.tsx +++ b/src/screens/RaceResult/RaceResultContentResults.tsx @@ -1,9 +1,12 @@ -import { Race, Result } from "../../types"; +import { ListItemResult } from "../../components/ListItemResult"; +import { Result } from "../../types"; type Props = { results: Result[]; }; export const RaceResultContentResults = ({ results }: Props) => { - return null; + return results.map((result) => ( + + )); }; diff --git a/src/screens/Standings/StandingsContructors.tsx b/src/screens/Standings/StandingsContructors.tsx index 712c352..800a8fc 100644 --- a/src/screens/Standings/StandingsContructors.tsx +++ b/src/screens/Standings/StandingsContructors.tsx @@ -20,8 +20,7 @@ export const StandingsContructors = () => { key={constructor.Constructor.constructorId} position={constructor.position} points={constructor.points} - constructorName={constructor.Constructor.name} - nationality={constructor.Constructor.nationality} + konstructor={constructor.Constructor} /> ) ); diff --git a/src/screens/Standings/StandingsDrivers.tsx b/src/screens/Standings/StandingsDrivers.tsx index 1b2b4f5..343d4b7 100644 --- a/src/screens/Standings/StandingsDrivers.tsx +++ b/src/screens/Standings/StandingsDrivers.tsx @@ -20,12 +20,10 @@ export const StandingsDrivers = () => { key={driver.Driver.driverId} position={driver.position} points={driver.points} - givenName={driver.Driver.givenName} - familyName={driver.Driver.familyName} + driver={driver.Driver} constructorName={driver.Constructors.map( (constructor) => constructor.name ).join(" - ")} - nationality={driver.Driver.nationality} /> ) ); diff --git a/src/types.ts b/src/types.ts index f60222b..e3dd6ae 100644 --- a/src/types.ts +++ b/src/types.ts @@ -21,8 +21,8 @@ export type FastestLap = { AverageSpeed: { units: string; speed: string; - } -} + }; +}; export type Result = { number: string; @@ -34,12 +34,12 @@ export type Result = { grid: string; laps: string; status: string; - Time: { + Time?: { millis: string; time: string; }; - FastestLap: FastestLap -} + FastestLap: FastestLap; +}; export type Race = { season: string; @@ -48,7 +48,7 @@ export type Race = { raceName: string; Circuit: Circuit; date: string; - time: string; + time?: string; FirstPractice: { date: string; time: string; @@ -65,7 +65,7 @@ export type Race = { date: string; time: string; }; - Results?: Result[] + Results?: Result[]; }; export type Driver = { @@ -77,14 +77,14 @@ export type Driver = { familyName: string; dateOfBirth: string; nationality: string; -} +}; export type Constructor = { constructorId: string; url: string; name: string; nationality: string; -} +}; export type DriverStanding = { position: string; @@ -92,23 +92,23 @@ export type DriverStanding = { points: string; wins: string; Driver: Driver; - Constructors: Constructor[] -} + Constructors: Constructor[]; +}; export type ConstructorStanding = { position: string; positionText: string; points: string; wins: string; - Constructor: Constructor -} + Constructor: Constructor; +}; export type Season = { season: string; url: string; -} +}; export enum StandingType { - DRIVERS = 'drivers', - CONSTRUCTORS = 'constructors', + DRIVERS = "drivers", + CONSTRUCTORS = "constructors", }