feat: add 404 page, migrate to UUID v7, and consolidate DB
This commit is contained in:
@@ -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'existe pas sur WikiRush.
|
||||||
|
<br />
|
||||||
|
Tu t'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'accueil
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = {
|
|||||||
"clientVersion": "7.7.0",
|
"clientVersion": "7.7.0",
|
||||||
"engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711",
|
"engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711",
|
||||||
"activeProvider": "sqlite",
|
"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": {
|
"runtimeDataModel": {
|
||||||
"models": {},
|
"models": {},
|
||||||
"enums": {},
|
"enums": {},
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ import { PrismaClient } from "./generated/prisma/client";
|
|||||||
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
|
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
|
||||||
|
|
||||||
function createPrisma() {
|
function createPrisma() {
|
||||||
const adapter = new PrismaBetterSqlite3({ url: "./wikirace.db" });
|
const adapter = new PrismaBetterSqlite3({ url: "./wikirush.db" });
|
||||||
return new PrismaClient({ adapter });
|
return new PrismaClient({ adapter });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ const config = {
|
|||||||
path: "prisma/migrations",
|
path: "prisma/migrations",
|
||||||
},
|
},
|
||||||
datasource: {
|
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");
|
|
||||||
+30
@@ -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
|
-- CreateTable
|
||||||
CREATE TABLE "DailyPuzzle" (
|
CREATE TABLE "DailyPuzzle" (
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
"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
|
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
|
-- CreateIndex
|
||||||
CREATE UNIQUE INDEX "DailyPuzzle_date_key" ON "DailyPuzzle"("date");
|
CREATE UNIQUE INDEX "DailyPuzzle_date_key" ON "DailyPuzzle"("date");
|
||||||
|
|
||||||
+26
-28
@@ -7,36 +7,34 @@ datasource db {
|
|||||||
provider = "sqlite"
|
provider = "sqlite"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid(7))
|
||||||
name String
|
name String
|
||||||
email String @unique
|
email String @unique
|
||||||
password String
|
password String
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
games Game[]
|
games Game[]
|
||||||
dailyResults DailyResult[]
|
dailyResults DailyResult[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Game {
|
model Game {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid(7))
|
||||||
userId String
|
userId String
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
mode String // "solo" | "multi" | "daily" | "blitz"
|
mode String // "solo" | "multi" | "daily" | "blitz"
|
||||||
startArticle String
|
startArticle String
|
||||||
targetArticle String
|
targetArticle String
|
||||||
path String // JSON array de titres
|
path String // JSON array de titres
|
||||||
clicks Int
|
clicks Int
|
||||||
timeSeconds Float
|
timeSeconds Float
|
||||||
won Boolean @default(true)
|
won Boolean @default(true)
|
||||||
playedAt DateTime @default(now())
|
playedAt DateTime @default(now())
|
||||||
|
|
||||||
@@index([userId])
|
@@index([userId])
|
||||||
}
|
}
|
||||||
|
|
||||||
model DailyPuzzle {
|
model DailyPuzzle {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid(7))
|
||||||
date String @unique // "YYYY-MM-DD"
|
date String @unique // "YYYY-MM-DD"
|
||||||
startArticle String
|
startArticle String
|
||||||
targetArticle String
|
targetArticle String
|
||||||
@@ -44,16 +42,16 @@ model DailyPuzzle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model DailyResult {
|
model DailyResult {
|
||||||
id String @id @default(cuid())
|
id String @id @default(uuid(7))
|
||||||
puzzleId String
|
puzzleId String
|
||||||
puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)
|
puzzle DailyPuzzle @relation(fields: [puzzleId], references: [id], onDelete: Cascade)
|
||||||
userId String
|
userId String
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
path String // JSON
|
path String // JSON
|
||||||
clicks Int
|
clicks Int
|
||||||
timeSeconds Float
|
timeSeconds Float
|
||||||
won Boolean
|
won Boolean
|
||||||
playedAt DateTime @default(now())
|
playedAt DateTime @default(now())
|
||||||
|
|
||||||
@@unique([puzzleId, userId])
|
@@unique([puzzleId, userId])
|
||||||
@@index([puzzleId])
|
@@index([puzzleId])
|
||||||
|
|||||||
BIN
Binary file not shown.
Reference in New Issue
Block a user