diff --git a/app/api/tournaments/france/route.ts b/app/api/tournaments/france/route.ts index 8770226..7354917 100644 --- a/app/api/tournaments/france/route.ts +++ b/app/api/tournaments/france/route.ts @@ -1,44 +1,18 @@ import clientPromise from "@/lib/mongodb"; +import { dateOrderingFrance } from "@/utils/dbDateOrdering"; -// TODO collate only the country of France - redundant for now but will be needed when new countries are added -// probably do this by passing the country name as parameter /** * Tournament data API endpoint * @route /api/tournaments/france * @internal */ +// TODO cache this result for 24 hours - using cache() export async function GET() { try { const client = await clientPromise; const db = client.db("tournamentsFranceDB"); - /** - * Converts date from string into a date to allow ordering - */ - // TODO add into a middleware? - const data = await db - .collection("tournaments") - .aggregate([ - { - $addFields: { - dateParts: { - $dateFromString: { - dateString: "$date", - format: "%d/%m/%Y", - }, - }, - }, - }, - { - $sort: { - dateParts: 1, - }, - }, - { - $unset: "dateParts", - }, - ]) - .toArray(); + const data = await dateOrderingFrance(db); return new Response(JSON.stringify(data), { status: 200 }); } catch (error) { diff --git a/app/page.tsx b/app/page.tsx index b6b4859..33c3539 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,11 +1,20 @@ import Link from "next/link"; +import Image from "next/image"; import Layout from "@/components/Layout"; +import bgImage from "@/public/images/map-bg.jpg"; export default function Home() { return (
-
+
+ Background image of France +

Echecs France

diff --git a/app/tournois/page.tsx b/app/tournois/page.tsx index 71ecdfb..667f96f 100644 --- a/app/tournois/page.tsx +++ b/app/tournois/page.tsx @@ -1,11 +1,9 @@ -import { Tournament } from "@/types"; - +import clientPromise from "@/lib/mongodb"; import dynamic from "next/dynamic"; import Layout from "@/components/Layout"; import TournamentTable from "@/components/TournamentTable"; -import getTournaments from "@/utils/getTournamentData"; +import { dateOrderingFrance } from "@/utils/dbDateOrdering"; -// TODO can these functions be put into a custom hook? /** * Imports the tournament map component, ensuring CSR only. * @remarks SSR is not supported by react-leaflet @@ -19,17 +17,32 @@ const TournamentMap = dynamic(() => import("@/components/TournamentMap"), { ), }); +export const revalidate = 86400; // cache for 24 hours + +const getTournaments = async () => { + try { + const client = await clientPromise; + const db = client.db("tournamentsFranceDB"); + + const data = await dateOrderingFrance(db); + + return JSON.stringify(data); + } catch (error) { + throw new Error("Error fetching tournament data"); + } +}; + export default async function Tournaments() { - const tournamentData = await getTournaments("france"); + const tournamentData = await getTournaments(); return (
- +
- +
diff --git a/cypress/component/utils.cy.ts b/cypress/component/utils.cy.ts index 16886f8..c3648db 100644 --- a/cypress/component/utils.cy.ts +++ b/cypress/component/utils.cy.ts @@ -1,54 +1,55 @@ -import { Tournament } from "@/types"; -import getTournaments from "@/utils/getTournamentData"; -import { createLayerGroups } from "@/utils/layerGroups"; +// import { Tournament } from "@/types"; +// import getTournaments from "@/utils/getTournamentData"; +// import { createLayerGroups } from "@/utils/layerGroups"; +// -// TODO cy.wrap() for promise resolution -// TODO DRY - variables and data fetching can be done before tests under the first describe block -describe("Unit tests of utils directory", () => { - describe("Retrieve tournament data from DB", () => { - let response: Tournament[]; - let results: Tournament[]; - - describe("France", () => { - before(async () => { - response = await getTournaments("france"); - results = response.splice(0, 5); - }); - - it("log first 5 results", () => { - results.forEach((result) => cy.log(JSON.stringify(result))); - }); - - it("check tournament urls are active", () => { - results.forEach((result) => cy.request(result.url)); - }); - }); - }); - - describe("Create layer groups for map markers", () => { - let response: Tournament[]; - let results: Tournament[]; - describe("France", () => { - const timeControls = [ - { name: "Cadence Lente", colour: "green" }, - { name: "Rapide", colour: "blue" }, - { name: "Blitz", colour: "yellow" }, - { name: "1h KO", colour: "red" }, - ]; - - before(async () => { - response = await getTournaments("france"); - results = response.splice(0, 5); - }); - - it("generate layer groups", () => { - const result = timeControls.map((timeControl) => { - return createLayerGroups(timeControl.name, timeControl.colour, { - tournamentData: results, - }); - }); - cy.wrap(result.length).should("be.greaterThan", 0); - }); - }); - }); -}); +// // TODO rewrite this test suite since I no longer use fetch for the map +// // TODO add tests for the API once it is active +// describe("Unit tests of utils directory", () => { +// describe("Retrieve tournament data from DB", () => { +// let response: Tournament[]; +// let results: Tournament[]; +// +// describe("France", () => { +// before(async () => { +// response = await getTournaments("france"); +// results = response.splice(0, 5); +// }); +// +// it("log first 5 results", () => { +// results.forEach((result) => cy.log(JSON.stringify(result))); +// }); +// +// it("check tournament urls are active", () => { +// results.forEach((result) => cy.request(result.url)); +// }); +// }); +// }); +// +// describe("Create layer groups for map markers", () => { +// let response: Tournament[]; +// let results: Tournament[]; +// describe("France", () => { +// const timeControls = [ +// { name: "Cadence Lente", colour: "green" }, +// { name: "Rapide", colour: "blue" }, +// { name: "Blitz", colour: "yellow" }, +// { name: "1h KO", colour: "red" }, +// ]; +// +// before(async () => { +// response = await getTournaments("france"); +// results = response.splice(0, 5); +// }); +// +// it("generate layer groups", () => { +// const result = timeControls.map((timeControl) => { +// return createLayerGroups(timeControl.name, timeControl.colour, { +// tournamentData: results, +// }); +// }); +// cy.wrap(result.length).should("be.greaterThan", 0); +// }); +// }); +// }); +// }); diff --git a/next.config.js b/next.config.js index 1b0a349..658404a 100644 --- a/next.config.js +++ b/next.config.js @@ -1,7 +1,4 @@ /** @type {import('next').NextConfig} */ -const dotenvExpand = require("dotenv-expand"); - -dotenvExpand.expand({ parsed: { ...process.env } }); const nextConfig = {}; module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index 3f23690..cb96b24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "@types/react-dom": "18.2.4", "@vercel/analytics": "^1.0.1", "autoprefixer": "10.4.14", - "dotenv-expand": "^10.0.0", "eslint": "8.41.0", "eslint-config-next": "13.4.3", "leaflet": "^1.9.4", @@ -3526,14 +3525,6 @@ "node": ">=12" } }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "engines": { - "node": ">=12" - } - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", diff --git a/package.json b/package.json index a3c31d2..e025ebe 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "@types/react-dom": "18.2.4", "@vercel/analytics": "^1.0.1", "autoprefixer": "10.4.14", - "dotenv-expand": "^10.0.0", "eslint": "8.41.0", "eslint-config-next": "13.4.3", "leaflet": "^1.9.4", diff --git a/utils/dbDateOrdering.ts b/utils/dbDateOrdering.ts new file mode 100644 index 0000000..3a6ed06 --- /dev/null +++ b/utils/dbDateOrdering.ts @@ -0,0 +1,30 @@ +import { Db } from "mongodb"; + +/** + * Converts date from string into a date to allow ordering + */ +export const dateOrderingFrance = async (db: Db) => { + return await db + .collection("tournaments") + .aggregate([ + { + $addFields: { + dateParts: { + $dateFromString: { + dateString: "$date", + format: "%d/%m/%Y", + }, + }, + }, + }, + { + $sort: { + dateParts: 1, + }, + }, + { + $unset: "dateParts", + }, + ]) + .toArray(); +}; diff --git a/utils/getTournamentData.tsx b/utils/getTournamentData.tsx deleted file mode 100644 index 9a245b4..0000000 --- a/utils/getTournamentData.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Retrieves tournament data from /api/tournaments/:country - * @remarks The result is cached for the revalidation period in seconds - */ -export default async function getTournaments(country: string) { - const server = process.env.NEXT_PUBLIC_SITE_URL; - const res = await fetch(`${server}/api/tournaments/${country}`, { - next: { revalidate: 300 }, - }); - - if (res.status !== 200) { - throw new Error("Failed to fetch tournament data"); - } - return await res.json(); -}