feat: add 404 page, migrate to UUID v7, and consolidate DB

This commit is contained in:
jessy-david-dev
2026-04-10 22:48:15 +02:00
parent ba7a625298
commit 19d9afd2b4
8 changed files with 95 additions and 60 deletions
+36
View File
@@ -0,0 +1,36 @@
import type { Metadata } from "next";
import Link from "next/link";
export const metadata: Metadata = {
title: "Page introuvable - WikiRush",
description: "Cette page n'existe pas.",
};
export default function NotFound() {
return (
<div className="min-h-dvh bg-[#0f0f0f] text-[#f0f0f0] px-4 py-12 flex flex-col items-center justify-center">
<div className="w-full max-w-md flex flex-col items-center gap-8 text-center">
<div className="flex flex-col gap-2">
<span className="text-7xl font-bold text-[#2e2e2e]">404</span>
<h1 className="text-xl font-bold">Page introuvable</h1>
<p className="text-[#888] text-sm leading-relaxed">
Cet article n&apos;existe pas sur WikiRush.
<br />
Tu t&apos;es peut-être perdu en chemin ?
</p>
</div>
<Link
href="/"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl text-sm font-medium
bg-[#1f1f1f] border border-[#2e2e2e] text-[#e5e5e5]
hover:bg-[#2a2a2a] hover:border-[#3a3a3a]
transition-all duration-200"
>
<span className="text-base"></span>
Retour à l&apos;accueil
</Link>
</div>
</div>
);
}
+1 -1
View File
@@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = {
"clientVersion": "7.7.0",
"engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711",
"activeProvider": "sqlite",
"inlineSchema": "generator client {\n provider = \"prisma-client\"\n output = \"../lib/generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nmodel User {\n id String @id @default(cuid())\n name String\n email String @unique\n password String\n createdAt DateTime @default(now())\n games Game[]\n dailyResults DailyResult[]\n}\n\nmodel Game {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n mode String // \"solo\" | \"multi\" | \"daily\" | \"blitz\"\n startArticle String\n targetArticle String\n path String // JSON array de titres\n clicks Int\n timeSeconds Float\n won Boolean @default(true)\n playedAt DateTime @default(now())\n\n @@index([userId])\n}\n\nmodel DailyPuzzle {\n id String @id @default(cuid())\n date String @unique // \"YYYY-MM-DD\"\n startArticle String\n targetArticle String\n results DailyResult[]\n}\n\nmodel DailyResult {\n id String @id @default(cuid())\n puzzleId String\n puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n path String // JSON\n clicks Int\n timeSeconds Float\n won Boolean\n playedAt DateTime @default(now())\n\n @@unique([puzzleId, userId])\n @@index([puzzleId])\n}\n",
"inlineSchema": "generator client {\n provider = \"prisma-client\"\n output = \"../lib/generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nmodel User {\n id String @id @default(uuid(7))\n name String\n email String @unique\n password String\n createdAt DateTime @default(now())\n games Game[]\n dailyResults DailyResult[]\n}\n\nmodel Game {\n id String @id @default(uuid(7))\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n mode String // \"solo\" | \"multi\" | \"daily\" | \"blitz\"\n startArticle String\n targetArticle String\n path String // JSON array de titres\n clicks Int\n timeSeconds Float\n won Boolean @default(true)\n playedAt DateTime @default(now())\n\n @@index([userId])\n}\n\nmodel DailyPuzzle {\n id String @id @default(uuid(7))\n date String @unique // \"YYYY-MM-DD\"\n startArticle String\n targetArticle String\n results DailyResult[]\n}\n\nmodel DailyResult {\n id String @id @default(uuid(7))\n puzzleId String\n puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n path String // JSON\n clicks Int\n timeSeconds Float\n won Boolean\n playedAt DateTime @default(now())\n\n @@unique([puzzleId, userId])\n @@index([puzzleId])\n}\n",
"runtimeDataModel": {
"models": {},
"enums": {},
+1 -1
View File
@@ -5,7 +5,7 @@ import { PrismaClient } from "./generated/prisma/client";
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
function createPrisma() {
const adapter = new PrismaBetterSqlite3({ url: "./wikirace.db" });
const adapter = new PrismaBetterSqlite3({ url: "./wikirush.db" });
return new PrismaClient({ adapter });
}
+1 -1
View File
@@ -4,7 +4,7 @@ const config = {
path: "prisma/migrations",
},
datasource: {
url: "file:./wikirace.db",
url: "file:./wikirush.db",
},
};
@@ -1,29 +0,0 @@
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "Game" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"mode" TEXT NOT NULL,
"startArticle" TEXT NOT NULL,
"targetArticle" TEXT NOT NULL,
"path" TEXT NOT NULL,
"clicks" INTEGER NOT NULL,
"timeSeconds" REAL NOT NULL,
"won" BOOLEAN NOT NULL DEFAULT true,
"playedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Game_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- CreateIndex
CREATE INDEX "Game_userId_idx" ON "Game"("userId");
@@ -1,3 +1,27 @@
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "Game" (
"id" TEXT NOT NULL PRIMARY KEY,
"userId" TEXT NOT NULL,
"mode" TEXT NOT NULL,
"startArticle" TEXT NOT NULL,
"targetArticle" TEXT NOT NULL,
"path" TEXT NOT NULL,
"clicks" INTEGER NOT NULL,
"timeSeconds" REAL NOT NULL,
"won" BOOLEAN NOT NULL DEFAULT true,
"playedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Game_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "DailyPuzzle" (
"id" TEXT NOT NULL PRIMARY KEY,
@@ -20,6 +44,12 @@ CREATE TABLE "DailyResult" (
CONSTRAINT "DailyResult_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- CreateIndex
CREATE INDEX "Game_userId_idx" ON "Game"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "DailyPuzzle_date_key" ON "DailyPuzzle"("date");
+26 -28
View File
@@ -7,36 +7,34 @@ datasource db {
provider = "sqlite"
}
model User {
id String @id @default(cuid())
name String
email String @unique
password String
createdAt DateTime @default(now())
id String @id @default(uuid(7))
name String
email String @unique
password String
createdAt DateTime @default(now())
games Game[]
dailyResults DailyResult[]
}
model Game {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
mode String // "solo" | "multi" | "daily" | "blitz"
startArticle String
id String @id @default(uuid(7))
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
mode String // "solo" | "multi" | "daily" | "blitz"
startArticle String
targetArticle String
path String // JSON array de titres
clicks Int
timeSeconds Float
won Boolean @default(true)
playedAt DateTime @default(now())
path String // JSON array de titres
clicks Int
timeSeconds Float
won Boolean @default(true)
playedAt DateTime @default(now())
@@index([userId])
}
model DailyPuzzle {
id String @id @default(cuid())
id String @id @default(uuid(7))
date String @unique // "YYYY-MM-DD"
startArticle String
targetArticle String
@@ -44,16 +42,16 @@ model DailyPuzzle {
}
model DailyResult {
id String @id @default(cuid())
puzzleId String
puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
path String // JSON
clicks Int
timeSeconds Float
won Boolean
playedAt DateTime @default(now())
id String @id @default(uuid(7))
puzzleId String
puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
path String // JSON
clicks Int
timeSeconds Float
won Boolean
playedAt DateTime @default(now())
@@unique([puzzleId, userId])
@@index([puzzleId])
BIN
View File
Binary file not shown.