diff --git a/web/.env b/web/.env
new file mode 100644
index 0000000..629a336
--- /dev/null
+++ b/web/.env
@@ -0,0 +1 @@
+NEXT_PUBLIC_BASE_URL=http://localhost:3000
\ No newline at end of file
diff --git a/web/.eslintrc.json b/web/.eslintrc.json
index 3722418..1a1ad7a 100644
--- a/web/.eslintrc.json
+++ b/web/.eslintrc.json
@@ -1,3 +1,6 @@
{
- "extends": ["next/core-web-vitals", "next/typescript"]
+ "extends": ["next/core-web-vitals", "next/typescript"],
+ "rules": {
+ "@next/next/no-img-element": "off"
+ }
}
diff --git a/web/app/drivers/page.tsx b/web/app/drivers/page.tsx
index cb47f5a..ec6e575 100644
--- a/web/app/drivers/page.tsx
+++ b/web/app/drivers/page.tsx
@@ -1,6 +1,12 @@
-import { Driver } from "@/src/components/drivers/Driver";
+import { Suspense } from "react";
+
+import { Drivers as DriversComponent } from "@/src/components/drivers/Drivers";
+import { DriversSkeleton } from "@/src/components/drivers/DriversSkeleton";
export default function Drivers() {
+
+ const year = (new Date()).getFullYear();
+
return (
@@ -13,26 +19,11 @@ export default function Drivers() {
- 2024 Drivers
+ {year} Drivers
-
-
-
+ }>
+
+
diff --git a/web/app/results/page.tsx b/web/app/results/page.tsx
index 8816ad0..6326e19 100644
--- a/web/app/results/page.tsx
+++ b/web/app/results/page.tsx
@@ -1,4 +1,3 @@
-import { Podium } from "@/src/components/results/Podium";
export default function Results() {
return (
diff --git a/web/next.config.mjs b/web/next.config.mjs
index 4678774..adb44b3 100644
--- a/web/next.config.mjs
+++ b/web/next.config.mjs
@@ -1,4 +1,13 @@
/** @type {import('next').NextConfig} */
-const nextConfig = {};
+const nextConfig = {
+ rewrites: async () => {
+ return [
+ {
+ source: '/api/:path*',
+ destination: 'http://api:8080/:path*',
+ },
+ ];
+ },
+};
export default nextConfig;
diff --git a/web/src/components/drivers/Driver.tsx b/web/src/components/drivers/Driver.tsx
index d5da93c..eb99024 100644
--- a/web/src/components/drivers/Driver.tsx
+++ b/web/src/components/drivers/Driver.tsx
@@ -2,21 +2,21 @@ interface DriverProps {
name: string;
img: string;
team: string;
- championships: number
+ number: number
}
-export function Driver (props: DriverProps): JSX.Element {
+export function Driver(props: DriverProps): JSX.Element {
- const { name, img, team, championships } = props;
+ const { name, img, team, number } = props;
return (
-

+
{name}
Team: {team}
-
Championships: {championships}
+
Number: {number}
diff --git a/web/src/components/drivers/Drivers.tsx b/web/src/components/drivers/Drivers.tsx
new file mode 100644
index 0000000..d8fd215
--- /dev/null
+++ b/web/src/components/drivers/Drivers.tsx
@@ -0,0 +1,26 @@
+import { fetchDrivers } from "@/src/lib/api";
+import { Driver } from "./Driver";
+
+export async function Drivers(): Promise {
+
+ // sleep 1 sec just to show the skeleton
+ await new Promise((resolve) => setTimeout(resolve, 10000));
+
+ const drivers = await fetchDrivers();
+
+ return (
+ <>
+ {drivers.map((driver) => {
+ return (
+
+ );
+ })}
+ >
+ );
+}
\ No newline at end of file
diff --git a/web/src/components/drivers/DriversSkeleton.tsx b/web/src/components/drivers/DriversSkeleton.tsx
new file mode 100644
index 0000000..db81ed4
--- /dev/null
+++ b/web/src/components/drivers/DriversSkeleton.tsx
@@ -0,0 +1,28 @@
+export function DriversSkeleton(): JSX.Element {
+
+ const fakeData = (new Array(20)).fill(0);
+
+ return (
+ <>
+ {fakeData.map((_, idx) => {
+ return (
+
+ );
+ })}
+ >
+ );
+}
\ No newline at end of file
diff --git a/web/src/components/results/Podium.tsx b/web/src/components/results/Podium.tsx
index d047125..990a1af 100644
--- a/web/src/components/results/Podium.tsx
+++ b/web/src/components/results/Podium.tsx
@@ -1,3 +1,5 @@
+import Image from "next/image";
+
interface PodiumProps {
title: string;
img: string;
@@ -14,7 +16,7 @@ export function Podium (props: PodiumProps): JSX.Element {
{title}
-

+
Driver: {driver}
diff --git a/web/src/components/teams/Team.tsx b/web/src/components/teams/Team.tsx
index 467228a..92d6464 100644
--- a/web/src/components/teams/Team.tsx
+++ b/web/src/components/teams/Team.tsx
@@ -1,3 +1,5 @@
+import Image from "next/image";
+
interface TeamProps {
name: string;
img: string;
@@ -12,7 +14,7 @@ export function Team (props: TeamProps): JSX.Element {
return (
-

+
{name}
Team Principal: {teamPrincipal}
diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts
new file mode 100644
index 0000000..f13f464
--- /dev/null
+++ b/web/src/lib/api.ts
@@ -0,0 +1,39 @@
+import { DriverInterface } from "../types/driver";
+
+export async function fetchJson
(
+ url: string,
+ reqDetails: RequestInit = {},
+) : Promise {
+
+ const defaultHeaders = {
+ Accept: "application/json",
+ Authorization: "Basic Z286YXBp",
+ };
+
+ reqDetails.headers = {
+ ... defaultHeaders,
+ ...(reqDetails.headers ?? {}),
+ }
+
+ const response = await fetch(
+ url,
+ reqDetails
+ );
+
+ return await response.json();
+}
+
+export async function fetchDrivers(): Promise {
+
+ try {
+
+ return await fetchJson(
+ `${process.env.NEXT_PUBLIC_BASE_URL}/api/drivers`
+ );
+
+ } catch (error) {
+ console.error('Unable to fetch drivers', error);
+ }
+
+ return [];
+}
\ No newline at end of file
diff --git a/web/src/types/driver.ts b/web/src/types/driver.ts
new file mode 100644
index 0000000..2cacc51
--- /dev/null
+++ b/web/src/types/driver.ts
@@ -0,0 +1,7 @@
+export interface DriverInterface {
+ driver_number: number;
+ full_name: string;
+ country_code: string;
+ avatar: string;
+ team_name: string;
+}
\ No newline at end of file