Add database and Prisma configurations, enhance event and leaderboard components with API integration, and update navigation for session management
This commit is contained in:
10
.env
Normal file
10
.env
Normal file
@@ -0,0 +1,10 @@
|
||||
# Environment variables declared in this file are NOT automatically loaded by Prisma.
|
||||
# Please add `import "dotenv/config";` to your `prisma.config.ts` file, or use the Prisma CLI with Bun
|
||||
# to load environment variables from .env files: https://pris.ly/prisma-config-env-vars.
|
||||
|
||||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
||||
|
||||
DATABASE_URL="file:./dev.db"
|
||||
AUTH_SECRET="your-secret-key-change-this-in-production"
|
||||
AUTH_URL="http://localhost:3000"
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -34,3 +34,10 @@ yarn-error.log*
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# database
|
||||
*.db
|
||||
*.db-journal
|
||||
dev.db*
|
||||
|
||||
# prisma
|
||||
/app/generated/prisma
|
||||
|
||||
253
app/admin/page.tsx
Normal file
253
app/admin/page.tsx
Normal file
@@ -0,0 +1,253 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Navigation from "@/components/Navigation";
|
||||
|
||||
interface UserPreferences {
|
||||
id: string;
|
||||
userId: string;
|
||||
homeBackground: string | null;
|
||||
eventsBackground: string | null;
|
||||
leaderboardBackground: string | null;
|
||||
user: {
|
||||
id: string;
|
||||
username: string;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default function AdminPage() {
|
||||
const { data: session, status } = useSession();
|
||||
const router = useRouter();
|
||||
const [preferences, setPreferences] = useState<UserPreferences[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [editingUserId, setEditingUserId] = useState<string | null>(null);
|
||||
const [formData, setFormData] = useState({
|
||||
homeBackground: "",
|
||||
eventsBackground: "",
|
||||
leaderboardBackground: "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (status === "unauthenticated") {
|
||||
router.push("/login");
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === "authenticated" && session?.user?.role !== "ADMIN") {
|
||||
router.push("/");
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === "authenticated" && session?.user?.role === "ADMIN") {
|
||||
fetchPreferences();
|
||||
}
|
||||
}, [status, session, router]);
|
||||
|
||||
const fetchPreferences = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/admin/preferences");
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setPreferences(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching preferences:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEdit = (pref: UserPreferences) => {
|
||||
setEditingUserId(pref.userId);
|
||||
setFormData({
|
||||
homeBackground: pref.homeBackground || "",
|
||||
eventsBackground: pref.eventsBackground || "",
|
||||
leaderboardBackground: pref.leaderboardBackground || "",
|
||||
});
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!editingUserId) return;
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/admin/preferences", {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
userId: editingUserId,
|
||||
...formData,
|
||||
}),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
await fetchPreferences();
|
||||
setEditingUserId(null);
|
||||
setFormData({
|
||||
homeBackground: "",
|
||||
eventsBackground: "",
|
||||
leaderboardBackground: "",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating preferences:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setEditingUserId(null);
|
||||
setFormData({
|
||||
homeBackground: "",
|
||||
eventsBackground: "",
|
||||
leaderboardBackground: "",
|
||||
});
|
||||
};
|
||||
|
||||
if (status === "loading" || loading) {
|
||||
return (
|
||||
<main className="min-h-screen bg-black relative">
|
||||
<Navigation />
|
||||
<div className="flex items-center justify-center min-h-screen text-pixel-gold">
|
||||
Chargement...
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black relative">
|
||||
<Navigation />
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center overflow-hidden pt-24 pb-16">
|
||||
<div className="relative z-10 w-full max-w-6xl mx-auto px-8 py-16">
|
||||
<h1 className="text-4xl font-gaming font-black mb-8 text-center">
|
||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||
ADMIN - GESTION DES PRÉFÉRENCES UI
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-6 backdrop-blur-sm">
|
||||
<div className="space-y-4">
|
||||
{preferences.map((pref) => (
|
||||
<div
|
||||
key={pref.id}
|
||||
className="bg-black/60 border border-pixel-gold/20 rounded p-4"
|
||||
>
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<div>
|
||||
<h3 className="text-pixel-gold font-bold text-lg">
|
||||
{pref.user.username}
|
||||
</h3>
|
||||
<p className="text-gray-400 text-sm">{pref.user.email}</p>
|
||||
</div>
|
||||
{editingUserId !== pref.userId && (
|
||||
<button
|
||||
onClick={() => handleEdit(pref)}
|
||||
className="px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 transition"
|
||||
>
|
||||
Modifier
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{editingUserId === pref.userId ? (
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label className="block text-sm text-gray-300 mb-1">
|
||||
Background Home
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.homeBackground}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
homeBackground: e.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="/got-2.jpg"
|
||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm text-gray-300 mb-1">
|
||||
Background Events
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.eventsBackground}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
eventsBackground: e.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="/got-2.jpg"
|
||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm text-gray-300 mb-1">
|
||||
Background Leaderboard
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.leaderboardBackground}
|
||||
onChange={(e) =>
|
||||
setFormData({
|
||||
...formData,
|
||||
leaderboardBackground: e.target.value,
|
||||
})
|
||||
}
|
||||
placeholder="/leaderboard-bg.jpg"
|
||||
className="w-full px-3 py-2 bg-black/60 border border-pixel-gold/30 rounded text-white text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="px-4 py-2 border border-green-500/50 bg-green-900/20 text-green-400 uppercase text-xs tracking-widest rounded hover:bg-green-900/30 transition"
|
||||
>
|
||||
Enregistrer
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCancel}
|
||||
className="px-4 py-2 border border-gray-600/50 bg-gray-900/20 text-gray-400 uppercase text-xs tracking-widest rounded hover:bg-gray-900/30 transition"
|
||||
>
|
||||
Annuler
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2 text-sm text-gray-400">
|
||||
<div>
|
||||
Home: {pref.homeBackground || "Par défaut"}
|
||||
</div>
|
||||
<div>
|
||||
Events: {pref.eventsBackground || "Par défaut"}
|
||||
</div>
|
||||
<div>
|
||||
Leaderboard:{" "}
|
||||
{pref.leaderboardBackground || "Par défaut"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{preferences.length === 0 && (
|
||||
<div className="text-center text-gray-400 py-8">
|
||||
Aucune préférence trouvée
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
76
app/api/admin/preferences/route.ts
Normal file
76
app/api/admin/preferences/route.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { Role } from "@/prisma/generated/prisma/client";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const session = await auth();
|
||||
|
||||
if (!session?.user || session.user.role !== Role.ADMIN) {
|
||||
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
}
|
||||
|
||||
// Récupérer toutes les préférences utilisateur
|
||||
const preferences = await prisma.userPreferences.findMany({
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(preferences);
|
||||
} catch (error) {
|
||||
console.error("Error fetching admin preferences:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération des préférences" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: Request) {
|
||||
try {
|
||||
const session = await auth();
|
||||
|
||||
if (!session?.user || session.user.role !== Role.ADMIN) {
|
||||
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { userId, homeBackground, eventsBackground, leaderboardBackground } =
|
||||
body;
|
||||
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: "userId requis" }, { status: 400 });
|
||||
}
|
||||
|
||||
const preferences = await prisma.userPreferences.upsert({
|
||||
where: { userId },
|
||||
update: {
|
||||
homeBackground: homeBackground ?? undefined,
|
||||
eventsBackground: eventsBackground ?? undefined,
|
||||
leaderboardBackground: leaderboardBackground ?? undefined,
|
||||
},
|
||||
create: {
|
||||
userId,
|
||||
homeBackground: homeBackground ?? null,
|
||||
eventsBackground: eventsBackground ?? null,
|
||||
leaderboardBackground: leaderboardBackground ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(preferences);
|
||||
} catch (error) {
|
||||
console.error("Error updating admin preferences:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la mise à jour des préférences" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
4
app/api/auth/[...nextauth]/route.ts
Normal file
4
app/api/auth/[...nextauth]/route.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { handlers } from "@/lib/auth";
|
||||
|
||||
export const { GET, POST } = handlers;
|
||||
|
||||
21
app/api/events/route.ts
Normal file
21
app/api/events/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const events = await prisma.event.findMany({
|
||||
orderBy: {
|
||||
date: "asc",
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(events);
|
||||
} catch (error) {
|
||||
console.error("Error fetching events:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération des événements" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
37
app/api/leaderboard/route.ts
Normal file
37
app/api/leaderboard/route.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const users = await prisma.user.findMany({
|
||||
orderBy: {
|
||||
score: "desc",
|
||||
},
|
||||
take: 10,
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
score: true,
|
||||
level: true,
|
||||
avatar: true,
|
||||
},
|
||||
});
|
||||
|
||||
const leaderboard = users.map((user: { id: string; username: string; score: number; level: number; avatar: string | null }, index: number) => ({
|
||||
rank: index + 1,
|
||||
username: user.username,
|
||||
score: user.score,
|
||||
level: user.level,
|
||||
avatar: user.avatar,
|
||||
}));
|
||||
|
||||
return NextResponse.json(leaderboard);
|
||||
} catch (error) {
|
||||
console.error("Error fetching leaderboard:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération du leaderboard" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
65
app/api/preferences/route.ts
Normal file
65
app/api/preferences/route.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { Role } from "@/prisma/generated/prisma/client";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const session = await auth();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
||||
}
|
||||
|
||||
const preferences = await prisma.userPreferences.findUnique({
|
||||
where: { userId: session.user.id },
|
||||
});
|
||||
|
||||
return NextResponse.json(preferences || {});
|
||||
} catch (error) {
|
||||
console.error("Error fetching preferences:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération des préférences" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: Request) {
|
||||
try {
|
||||
const session = await auth();
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const { homeBackground, eventsBackground, leaderboardBackground, theme } =
|
||||
body;
|
||||
|
||||
const preferences = await prisma.userPreferences.upsert({
|
||||
where: { userId: session.user.id },
|
||||
update: {
|
||||
homeBackground: homeBackground ?? undefined,
|
||||
eventsBackground: eventsBackground ?? undefined,
|
||||
leaderboardBackground: leaderboardBackground ?? undefined,
|
||||
theme: theme ?? undefined,
|
||||
},
|
||||
create: {
|
||||
userId: session.user.id,
|
||||
homeBackground: homeBackground ?? null,
|
||||
eventsBackground: eventsBackground ?? null,
|
||||
leaderboardBackground: leaderboardBackground ?? null,
|
||||
theme: theme ?? "default",
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(preferences);
|
||||
} catch (error) {
|
||||
console.error("Error updating preferences:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la mise à jour des préférences" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
62
app/api/register/route.ts
Normal file
62
app/api/register/route.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { email, username, password } = body;
|
||||
|
||||
if (!email || !username || !password) {
|
||||
return NextResponse.json(
|
||||
{ error: "Tous les champs sont requis" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (password.length < 6) {
|
||||
return NextResponse.json(
|
||||
{ error: "Le mot de passe doit contenir au moins 6 caractères" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si l'email existe déjà
|
||||
const existingUser = await prisma.user.findFirst({
|
||||
where: {
|
||||
OR: [{ email }, { username }],
|
||||
},
|
||||
});
|
||||
|
||||
if (existingUser) {
|
||||
return NextResponse.json(
|
||||
{ error: "Cet email ou nom d'utilisateur est déjà utilisé" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// Hasher le mot de passe
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
// Créer l'utilisateur
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
email,
|
||||
username,
|
||||
password: hashedPassword,
|
||||
},
|
||||
});
|
||||
|
||||
return NextResponse.json(
|
||||
{ message: "Compte créé avec succès", userId: user.id },
|
||||
{ status: 201 }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Registration error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Une erreur est survenue lors de l'inscription" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
50
app/api/users/[id]/route.ts
Normal file
50
app/api/users/[id]/route.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const session = await auth();
|
||||
const { id } = await params;
|
||||
|
||||
if (!session?.user) {
|
||||
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
||||
}
|
||||
|
||||
// Vérifier que l'utilisateur demande ses propres données ou est admin
|
||||
if (session.user.id !== id && session.user.role !== "ADMIN") {
|
||||
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id },
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
avatar: true,
|
||||
hp: true,
|
||||
maxHp: true,
|
||||
xp: true,
|
||||
maxXp: true,
|
||||
level: true,
|
||||
score: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "Utilisateur non trouvé" }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json(user);
|
||||
} catch (error) {
|
||||
console.error("Error fetching user:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la récupération de l'utilisateur" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Orbitron, Rajdhani } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import SessionProvider from "@/components/SessionProvider";
|
||||
|
||||
const orbitron = Orbitron({
|
||||
subsets: ["latin"],
|
||||
@@ -26,8 +27,9 @@ export default function RootLayout({
|
||||
}>) {
|
||||
return (
|
||||
<html lang="fr" className={`${orbitron.variable} ${rajdhani.variable}`}>
|
||||
<body className="antialiased">{children}</body>
|
||||
<body className="antialiased">
|
||||
<SessionProvider>{children}</SessionProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
141
app/login/page.tsx
Normal file
141
app/login/page.tsx
Normal file
@@ -0,0 +1,141 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { signIn } from "next-auth/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Navigation from "@/components/Navigation";
|
||||
|
||||
export default function LoginPage() {
|
||||
const router = useRouter();
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError("");
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const result = await signIn("credentials", {
|
||||
email,
|
||||
password,
|
||||
redirect: false,
|
||||
callbackUrl: "/",
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
setError("Email ou mot de passe incorrect");
|
||||
setLoading(false);
|
||||
} else if (result?.ok) {
|
||||
router.push("/");
|
||||
router.refresh();
|
||||
} else {
|
||||
setError("Une erreur est survenue lors de la connexion");
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Login error:", err);
|
||||
setError("Une erreur est survenue");
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black relative">
|
||||
<Navigation />
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
|
||||
{/* Background Image */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: `url('/got-2.jpg')`,
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||
</div>
|
||||
|
||||
{/* Login Form */}
|
||||
<div className="relative z-10 w-full max-w-md mx-auto px-8">
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-8 backdrop-blur-sm">
|
||||
<h1 className="text-4xl font-gaming font-black mb-2 text-center">
|
||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||
CONNEXION
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-gray-400 text-sm text-center mb-8">
|
||||
Connectez-vous à votre compte
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition"
|
||||
placeholder="votre@email.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full px-6 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ? "Connexion..." : "Se connecter"}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center">
|
||||
<p className="text-gray-400 text-sm">
|
||||
Pas encore de compte ?{" "}
|
||||
<Link
|
||||
href="/register"
|
||||
className="text-pixel-gold hover:text-orange-400 transition"
|
||||
>
|
||||
S'inscrire
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
204
app/register/page.tsx
Normal file
204
app/register/page.tsx
Normal file
@@ -0,0 +1,204 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Navigation from "@/components/Navigation";
|
||||
|
||||
export default function RegisterPage() {
|
||||
const router = useRouter();
|
||||
const [formData, setFormData] = useState({
|
||||
email: "",
|
||||
username: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
});
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[e.target.name]: e.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError("");
|
||||
|
||||
if (formData.password !== formData.confirmPassword) {
|
||||
setError("Les mots de passe ne correspondent pas");
|
||||
return;
|
||||
}
|
||||
|
||||
if (formData.password.length < 6) {
|
||||
setError("Le mot de passe doit contenir au moins 6 caractères");
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/register", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: formData.email,
|
||||
username: formData.username,
|
||||
password: formData.password,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
setError(data.error || "Une erreur est survenue");
|
||||
return;
|
||||
}
|
||||
|
||||
router.push("/login?registered=true");
|
||||
} catch (err) {
|
||||
setError("Une erreur est survenue");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black relative">
|
||||
<Navigation />
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24">
|
||||
{/* Background Image */}
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat"
|
||||
style={{
|
||||
backgroundImage: `url('/got-2.jpg')`,
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/60 to-black/80"></div>
|
||||
</div>
|
||||
|
||||
{/* Register Form */}
|
||||
<div className="relative z-10 w-full max-w-md mx-auto px-8">
|
||||
<div className="bg-black/80 border border-pixel-gold/30 rounded-lg p-8 backdrop-blur-sm">
|
||||
<h1 className="text-4xl font-gaming font-black mb-2 text-center">
|
||||
<span className="bg-gradient-to-r from-pixel-gold via-orange-400 to-pixel-gold bg-clip-text text-transparent">
|
||||
INSCRIPTION
|
||||
</span>
|
||||
</h1>
|
||||
<p className="text-gray-400 text-sm text-center mb-8">
|
||||
Créez votre compte pour commencer
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{error && (
|
||||
<div className="bg-red-900/50 border border-red-500/50 text-red-400 px-4 py-3 rounded text-sm">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition"
|
||||
placeholder="votre@email.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="username"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Nom d'utilisateur
|
||||
</label>
|
||||
<input
|
||||
id="username"
|
||||
name="username"
|
||||
type="text"
|
||||
value={formData.username}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition"
|
||||
placeholder="VotrePseudo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Mot de passe
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
htmlFor="confirmPassword"
|
||||
className="block text-sm font-semibold text-gray-300 mb-2 uppercase tracking-wider"
|
||||
>
|
||||
Confirmer le mot de passe
|
||||
</label>
|
||||
<input
|
||||
id="confirmPassword"
|
||||
name="confirmPassword"
|
||||
type="password"
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="w-full px-4 py-3 bg-black/60 border border-pixel-gold/30 rounded text-white placeholder-gray-500 focus:outline-none focus:border-pixel-gold transition"
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full px-6 py-3 border border-pixel-gold/50 bg-black/60 text-white uppercase text-sm tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ? "Inscription..." : "S'inscrire"}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 text-center">
|
||||
<p className="text-gray-400 text-sm">
|
||||
Déjà un compte ?{" "}
|
||||
<Link
|
||||
href="/login"
|
||||
className="text-pixel-gold hover:text-orange-400 transition"
|
||||
>
|
||||
Se connecter
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,80 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Event {
|
||||
id: number;
|
||||
id: string;
|
||||
date: string;
|
||||
name: string;
|
||||
description: string;
|
||||
type: "summit" | "launch" | "festival" | "competition";
|
||||
status: "upcoming" | "live" | "past";
|
||||
type: "SUMMIT" | "LAUNCH" | "FESTIVAL" | "COMPETITION";
|
||||
status: "UPCOMING" | "LIVE" | "PAST";
|
||||
}
|
||||
|
||||
const events: Event[] = [
|
||||
{
|
||||
id: 1,
|
||||
date: "18 NOVEMBRE 2023",
|
||||
name: "Sommet de l'Innovation Tech",
|
||||
description:
|
||||
"Rejoignez les leaders de l'industrie et les innovateurs pour une journée de discussions sur les technologies de pointe, les percées de l'IA et des opportunités de networking.",
|
||||
type: "summit",
|
||||
status: "past",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
date: "3 DÉCEMBRE 2023",
|
||||
name: "Lancement de la Révolution IA",
|
||||
description:
|
||||
"Assistez au lancement de systèmes d'IA révolutionnaires qui vont remodeler le paysage du gaming. Aperçus exclusifs et opportunités d'accès anticipé.",
|
||||
type: "launch",
|
||||
status: "past",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
date: "22 DÉCEMBRE 2023",
|
||||
name: "Festival du Code d'Hiver",
|
||||
description:
|
||||
"Une célébration de l'excellence en programmation avec des hackathons, des défis de codage et des prix. Montrez vos compétences et rivalisez avec les meilleurs développeurs.",
|
||||
type: "festival",
|
||||
status: "past",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
date: "15 JANVIER 2024",
|
||||
name: "Expo Informatique Quantique",
|
||||
description:
|
||||
"Explorez l'avenir de l'informatique quantique dans le gaming. Démonstrations interactives, conférences d'experts et ateliers pratiques pour tous les niveaux.",
|
||||
type: "summit",
|
||||
status: "upcoming",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
date: "8 FÉVRIER 2024",
|
||||
name: "Championnat Cyber Arena",
|
||||
description:
|
||||
"L'événement de gaming compétitif ultime. Compétissez pour la gloire, des récompenses exclusives et le titre de Champion Cyber Arena. Inscriptions ouvertes.",
|
||||
type: "competition",
|
||||
status: "upcoming",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
date: "12 MARS 2024",
|
||||
name: "Gala Tech du Printemps",
|
||||
description:
|
||||
"Une soirée élégante célébrant les réalisations technologiques. Cérémonie de remise de prix, networking et annonces exclusives des plus grandes entreprises tech.",
|
||||
type: "festival",
|
||||
status: "upcoming",
|
||||
},
|
||||
];
|
||||
|
||||
const getEventTypeColor = (type: Event["type"]) => {
|
||||
switch (type) {
|
||||
case "summit":
|
||||
case "SUMMIT":
|
||||
return "from-blue-600 to-cyan-500";
|
||||
case "launch":
|
||||
case "LAUNCH":
|
||||
return "from-purple-600 to-pink-500";
|
||||
case "festival":
|
||||
case "FESTIVAL":
|
||||
return "from-pixel-gold to-orange-500";
|
||||
case "competition":
|
||||
case "COMPETITION":
|
||||
return "from-red-600 to-orange-500";
|
||||
default:
|
||||
return "from-gray-600 to-gray-500";
|
||||
@@ -83,13 +28,13 @@ const getEventTypeColor = (type: Event["type"]) => {
|
||||
|
||||
const getEventTypeLabel = (type: Event["type"]) => {
|
||||
switch (type) {
|
||||
case "summit":
|
||||
case "SUMMIT":
|
||||
return "Sommet";
|
||||
case "launch":
|
||||
case "LAUNCH":
|
||||
return "Lancement";
|
||||
case "festival":
|
||||
case "FESTIVAL":
|
||||
return "Festival";
|
||||
case "competition":
|
||||
case "COMPETITION":
|
||||
return "Compétition";
|
||||
default:
|
||||
return type;
|
||||
@@ -98,19 +43,19 @@ const getEventTypeLabel = (type: Event["type"]) => {
|
||||
|
||||
const getStatusBadge = (status: Event["status"]) => {
|
||||
switch (status) {
|
||||
case "upcoming":
|
||||
case "UPCOMING":
|
||||
return (
|
||||
<span className="px-3 py-1 bg-green-900/50 border border-green-500/50 text-green-400 text-xs uppercase tracking-widest rounded">
|
||||
À venir
|
||||
</span>
|
||||
);
|
||||
case "live":
|
||||
case "LIVE":
|
||||
return (
|
||||
<span className="px-3 py-1 bg-red-900/50 border border-red-500/50 text-red-400 text-xs uppercase tracking-widest rounded animate-pulse">
|
||||
En direct
|
||||
</span>
|
||||
);
|
||||
case "past":
|
||||
case "PAST":
|
||||
return (
|
||||
<span className="px-3 py-1 bg-gray-800/50 border border-gray-600/50 text-gray-400 text-xs uppercase tracking-widest rounded">
|
||||
Passé
|
||||
@@ -120,6 +65,29 @@ const getStatusBadge = (status: Event["status"]) => {
|
||||
};
|
||||
|
||||
export default function EventsPageSection() {
|
||||
const [events, setEvents] = useState<Event[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetch("/api/events")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setEvents(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error fetching events:", err);
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||
<div className="text-pixel-gold text-xl">Chargement...</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||
{/* Background Image */}
|
||||
@@ -198,17 +166,17 @@ export default function EventsPageSection() {
|
||||
</p>
|
||||
|
||||
{/* Action Button */}
|
||||
{event.status === "upcoming" && (
|
||||
{event.status === "UPCOMING" && (
|
||||
<button className="w-full px-4 py-2 border border-pixel-gold/50 bg-black/40 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition">
|
||||
S'inscrire maintenant
|
||||
</button>
|
||||
)}
|
||||
{event.status === "live" && (
|
||||
{event.status === "LIVE" && (
|
||||
<button className="w-full px-4 py-2 border border-red-500/50 bg-red-900/20 text-red-400 uppercase text-xs tracking-widest rounded hover:bg-red-900/30 transition animate-pulse">
|
||||
Rejoindre en direct
|
||||
</button>
|
||||
)}
|
||||
{event.status === "past" && (
|
||||
{event.status === "PAST" && (
|
||||
<button className="w-full px-4 py-2 border border-gray-600/50 bg-gray-900/20 text-gray-500 uppercase text-xs tracking-widest rounded cursor-not-allowed">
|
||||
Événement terminé
|
||||
</button>
|
||||
|
||||
@@ -1,26 +1,44 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Event {
|
||||
id: string;
|
||||
date: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const events: Event[] = [
|
||||
{
|
||||
date: "18 NOVEMBRE 2023",
|
||||
name: "Sommet de l'Innovation Tech",
|
||||
},
|
||||
{
|
||||
date: "3 DÉCEMBRE 2023",
|
||||
name: "Lancement de la Révolution IA",
|
||||
},
|
||||
{
|
||||
date: "22 DÉCEMBRE 2023",
|
||||
name: "Festival du Code d'Hiver",
|
||||
},
|
||||
];
|
||||
|
||||
export default function EventsSection() {
|
||||
const [events, setEvents] = useState<Event[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetch("/api/events")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
// Prendre seulement les 3 premiers événements pour la section d'accueil
|
||||
setEvents(data.slice(0, 3));
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error fetching events:", err);
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<section className="w-full bg-gray-950 border-t border-pixel-gold/30 py-16">
|
||||
<div className="max-w-7xl mx-auto px-8 text-center text-pixel-gold">
|
||||
Chargement...
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
if (events.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<section className="w-full bg-gray-950 border-t border-pixel-gold/30 py-16">
|
||||
<div className="max-w-7xl mx-auto px-8">
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface LeaderboardEntry {
|
||||
rank: number;
|
||||
username: string;
|
||||
score: number;
|
||||
level: number;
|
||||
avatar?: string | null;
|
||||
}
|
||||
|
||||
// Format number with consistent locale to avoid hydration mismatch
|
||||
@@ -12,20 +15,32 @@ const formatScore = (score: number): string => {
|
||||
return score.toLocaleString("en-US");
|
||||
};
|
||||
|
||||
const mockLeaderboard: LeaderboardEntry[] = [
|
||||
{ rank: 1, username: "DragonSlayer99", score: 125000, level: 85 },
|
||||
{ rank: 2, username: "MineMaster", score: 118500, level: 82 },
|
||||
{ rank: 3, username: "CraftKing", score: 112000, level: 80 },
|
||||
{ rank: 4, username: "PixelWarrior", score: 105500, level: 78 },
|
||||
{ rank: 5, username: "FarminePro", score: 99000, level: 75 },
|
||||
{ rank: 6, username: "GoldDigger", score: 92500, level: 73 },
|
||||
{ rank: 7, username: "EpicGamer", score: 87000, level: 71 },
|
||||
{ rank: 8, username: "Legendary", score: 81500, level: 69 },
|
||||
{ rank: 9, username: "MysticMiner", score: 76000, level: 67 },
|
||||
{ rank: 10, username: "TopPlayer", score: 70500, level: 65 },
|
||||
];
|
||||
|
||||
export default function Leaderboard() {
|
||||
const [leaderboard, setLeaderboard] = useState<LeaderboardEntry[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetch("/api/leaderboard")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setLeaderboard(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error fetching leaderboard:", err);
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
|
||||
<div className="max-w-4xl mx-auto text-center text-pixel-gold">
|
||||
Chargement...
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
@@ -44,7 +59,7 @@ export default function Leaderboard() {
|
||||
|
||||
{/* Entries */}
|
||||
<div className="divide-y divide-pixel-gold/10">
|
||||
{mockLeaderboard.map((entry) => (
|
||||
{leaderboard.map((entry) => (
|
||||
<div
|
||||
key={entry.rank}
|
||||
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface LeaderboardEntry {
|
||||
rank: number;
|
||||
username: string;
|
||||
score: number;
|
||||
level: number;
|
||||
avatar?: string;
|
||||
avatar?: string | null;
|
||||
}
|
||||
|
||||
// Format number with consistent locale to avoid hydration mismatch
|
||||
@@ -13,25 +15,30 @@ const formatScore = (score: number): string => {
|
||||
return score.toLocaleString("en-US");
|
||||
};
|
||||
|
||||
const mockLeaderboard: LeaderboardEntry[] = [
|
||||
{ rank: 1, username: "TechMaster2024", score: 125000, level: 85 },
|
||||
{ rank: 2, username: "CodeWarrior", score: 118500, level: 82 },
|
||||
{ rank: 3, username: "AIGenius", score: 112000, level: 80 },
|
||||
{ rank: 4, username: "DevLegend", score: 105500, level: 78 },
|
||||
{ rank: 5, username: "InnovationPro", score: 99000, level: 75 },
|
||||
{ rank: 6, username: "TechNinja", score: 92500, level: 73 },
|
||||
{ rank: 7, username: "DigitalHero", score: 87000, level: 71 },
|
||||
{ rank: 8, username: "CodeCrusher", score: 81500, level: 69 },
|
||||
{ rank: 9, username: "TechWizard", score: 76000, level: 67 },
|
||||
{ rank: 10, username: "InnovationKing", score: 70500, level: 65 },
|
||||
{ rank: 11, username: "DevMaster", score: 68000, level: 64 },
|
||||
{ rank: 12, username: "TechElite", score: 65500, level: 63 },
|
||||
{ rank: 13, username: "CodeChampion", score: 63000, level: 62 },
|
||||
{ rank: 14, username: "AIVisionary", score: 60500, level: 61 },
|
||||
{ rank: 15, username: "TechPioneer", score: 58000, level: 60 },
|
||||
];
|
||||
|
||||
export default function LeaderboardSection() {
|
||||
const [leaderboard, setLeaderboard] = useState<LeaderboardEntry[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetch("/api/leaderboard")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setLeaderboard(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error fetching leaderboard:", err);
|
||||
setLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||
<div className="text-pixel-gold text-xl">Chargement...</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||
{/* Background Image */}
|
||||
@@ -78,7 +85,7 @@ export default function LeaderboardSection() {
|
||||
|
||||
{/* Entries */}
|
||||
<div className="divide-y divide-pixel-gold/10">
|
||||
{mockLeaderboard.map((entry) => (
|
||||
{leaderboard.map((entry) => (
|
||||
<div
|
||||
key={entry.rank}
|
||||
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
||||
@@ -106,11 +113,21 @@ export default function LeaderboardSection() {
|
||||
|
||||
{/* Player */}
|
||||
<div className="col-span-6 flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-gray-800 to-gray-900 border border-pixel-gold/30 flex items-center justify-center">
|
||||
<span className="text-pixel-gold text-xs font-bold">
|
||||
{entry.username.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
{entry.avatar ? (
|
||||
<div className="w-10 h-10 rounded-full border border-pixel-gold/30 overflow-hidden">
|
||||
<img
|
||||
src={entry.avatar}
|
||||
alt={entry.username}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-gray-800 to-gray-900 border border-pixel-gold/30 flex items-center justify-center">
|
||||
<span className="text-pixel-gold text-xs font-bold">
|
||||
{entry.username.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<span
|
||||
className={`font-bold ${
|
||||
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useSession, signOut } from "next-auth/react";
|
||||
import PlayerStats from "./PlayerStats";
|
||||
|
||||
export default function Navigation() {
|
||||
const { data: session } = useSession();
|
||||
|
||||
return (
|
||||
<nav className="w-full fixed top-0 left-0 z-50 px-8 py-3 bg-black/80 backdrop-blur-sm border-b border-gray-800/30">
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||
@@ -39,11 +42,44 @@ export default function Navigation() {
|
||||
>
|
||||
LEADERBOARD
|
||||
</Link>
|
||||
{session?.user?.role === "ADMIN" && (
|
||||
<Link
|
||||
href="/admin"
|
||||
className="text-pixel-gold hover:text-orange-400 transition text-xs font-normal uppercase tracking-widest"
|
||||
>
|
||||
ADMIN
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Player Stats - Right */}
|
||||
<div>
|
||||
<PlayerStats />
|
||||
{/* Right Side */}
|
||||
<div className="flex items-center gap-4">
|
||||
{session ? (
|
||||
<>
|
||||
<PlayerStats />
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className="text-gray-400 hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||
>
|
||||
Déconnexion
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Link
|
||||
href="/login"
|
||||
className="text-white hover:text-pixel-gold transition text-xs font-normal uppercase tracking-widest"
|
||||
>
|
||||
Connexion
|
||||
</Link>
|
||||
<Link
|
||||
href="/register"
|
||||
className="px-4 py-2 border border-pixel-gold/50 bg-black/60 text-white uppercase text-xs tracking-widest rounded hover:bg-pixel-gold/10 hover:border-pixel-gold transition"
|
||||
>
|
||||
Inscription
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,31 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface PlayerStatsProps {
|
||||
username?: string;
|
||||
avatar?: string;
|
||||
hp?: number;
|
||||
maxHp?: number;
|
||||
xp?: number;
|
||||
maxXp?: number;
|
||||
level?: number;
|
||||
}
|
||||
import { useSession } from "next-auth/react";
|
||||
|
||||
// Format number with consistent locale to avoid hydration mismatch
|
||||
const formatNumber = (num: number): string => {
|
||||
return num.toLocaleString("en-US");
|
||||
};
|
||||
|
||||
export default function PlayerStats({
|
||||
username = "DragonSlayer99",
|
||||
avatar = "/got-2.jpg",
|
||||
hp = 750,
|
||||
maxHp = 1000,
|
||||
xp = 3250,
|
||||
maxXp = 5000,
|
||||
level = 42,
|
||||
}: PlayerStatsProps) {
|
||||
export default function PlayerStats() {
|
||||
const { data: session } = useSession();
|
||||
const [userData, setUserData] = useState({
|
||||
username: "Guest",
|
||||
avatar: null as string | null,
|
||||
hp: 1000,
|
||||
maxHp: 1000,
|
||||
xp: 0,
|
||||
maxXp: 5000,
|
||||
level: 1,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (session?.user?.id) {
|
||||
fetch(`/api/users/${session.user.id}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
if (data) {
|
||||
setUserData({
|
||||
username: data.username || "Guest",
|
||||
avatar: data.avatar,
|
||||
hp: data.hp || 1000,
|
||||
maxHp: data.maxHp || 1000,
|
||||
xp: data.xp || 0,
|
||||
maxXp: data.maxXp || 5000,
|
||||
level: data.level || 1,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Utiliser les données de session si l'API échoue
|
||||
setUserData({
|
||||
username: session.user.username || "Guest",
|
||||
avatar: null,
|
||||
hp: 1000,
|
||||
maxHp: 1000,
|
||||
xp: 0,
|
||||
maxXp: 5000,
|
||||
level: 1,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
setUserData({
|
||||
username: "Guest",
|
||||
avatar: null,
|
||||
hp: 1000,
|
||||
maxHp: 1000,
|
||||
xp: 0,
|
||||
maxXp: 5000,
|
||||
level: 1,
|
||||
});
|
||||
}
|
||||
}, [session]);
|
||||
|
||||
const { username, avatar, hp, maxHp, xp, maxXp, level } = userData;
|
||||
const [hpPercentage, setHpPercentage] = useState(0);
|
||||
const [xpPercentage, setXpPercentage] = useState(0);
|
||||
|
||||
@@ -56,12 +93,18 @@ export default function PlayerStats({
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Avatar */}
|
||||
<div className="w-10 h-10 rounded-full border border-pixel-gold/20 overflow-hidden bg-gray-900">
|
||||
<img
|
||||
src={avatar}
|
||||
alt={username}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="w-10 h-10 rounded-full border border-pixel-gold/20 overflow-hidden bg-gray-900 flex items-center justify-center">
|
||||
{avatar ? (
|
||||
<img
|
||||
src={avatar}
|
||||
alt={username}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<span className="text-pixel-gold text-xs font-bold">
|
||||
{username.charAt(0).toUpperCase()}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
|
||||
16
components/SessionProvider.tsx
Normal file
16
components/SessionProvider.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { SessionProvider as NextAuthSessionProvider } from "next-auth/react";
|
||||
|
||||
export default function SessionProvider({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<NextAuthSessionProvider basePath="/api/auth">
|
||||
{children}
|
||||
</NextAuthSessionProvider>
|
||||
);
|
||||
}
|
||||
|
||||
71
lib/auth.ts
Normal file
71
lib/auth.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import NextAuth from "next-auth";
|
||||
import Credentials from "next-auth/providers/credentials";
|
||||
import { prisma } from "./prisma";
|
||||
import bcrypt from "bcryptjs";
|
||||
import type { Role } from "@/prisma/generated/prisma/client";
|
||||
|
||||
export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
trustHost: true,
|
||||
providers: [
|
||||
Credentials({
|
||||
credentials: {
|
||||
email: { label: "Email", type: "email" },
|
||||
password: { label: "Password", type: "password" },
|
||||
},
|
||||
authorize: async (credentials) => {
|
||||
if (!credentials?.email || !credentials?.password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: credentials.email as string },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isPasswordValid = await bcrypt.compare(
|
||||
credentials.password as string,
|
||||
user.password
|
||||
);
|
||||
|
||||
if (!isPasswordValid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
username: user.username,
|
||||
role: user.role,
|
||||
};
|
||||
},
|
||||
}),
|
||||
],
|
||||
callbacks: {
|
||||
jwt: async ({ token, user }) => {
|
||||
if (user) {
|
||||
token.id = user.id;
|
||||
token.username = user.username;
|
||||
token.role = user.role;
|
||||
}
|
||||
return token;
|
||||
},
|
||||
session: async ({ session, token }) => {
|
||||
if (session.user && token) {
|
||||
session.user.id = token.id as string;
|
||||
session.user.username = token.username as string;
|
||||
session.user.role = token.role as Role;
|
||||
}
|
||||
return session;
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
signIn: "/login",
|
||||
},
|
||||
session: {
|
||||
strategy: "jwt",
|
||||
},
|
||||
});
|
||||
|
||||
22
lib/prisma.ts
Normal file
22
lib/prisma.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { PrismaClient } from "@/prisma/generated/prisma/client";
|
||||
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
||||
|
||||
const adapter = new PrismaBetterSqlite3({
|
||||
url: process.env.DATABASE_URL || "file:./dev.db",
|
||||
});
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined;
|
||||
};
|
||||
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
adapter,
|
||||
log:
|
||||
process.env.NODE_ENV === "development"
|
||||
? ["query", "error", "warn"]
|
||||
: ["error"],
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
||||
15
package.json
15
package.json
@@ -6,20 +6,33 @@
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "next lint",
|
||||
"db:seed": "tsx prisma/seed.ts"
|
||||
},
|
||||
"prisma": {
|
||||
"seed": "tsx prisma/seed.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/adapter-better-sqlite3": "^7.1.0",
|
||||
"@prisma/client": "^7.1.0",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"better-sqlite3": "^12.5.0",
|
||||
"next": "15.5.7",
|
||||
"next-auth": "5.0.0-beta.30",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/node": "^22.0.0",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"postcss": "^8.4.40",
|
||||
"prisma": "^7.1.0",
|
||||
"tailwindcss": "^3.4.7",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
1369
pnpm-lock.yaml
generated
1369
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
14
prisma.config.ts
Normal file
14
prisma.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// This file was generated by Prisma and assumes you have installed the following:
|
||||
// npm install --save-dev prisma dotenv
|
||||
import "dotenv/config";
|
||||
import { defineConfig, env } from "prisma/config";
|
||||
|
||||
export default defineConfig({
|
||||
schema: "prisma/schema.prisma",
|
||||
migrations: {
|
||||
path: "prisma/migrations",
|
||||
},
|
||||
datasource: {
|
||||
url: env("DATABASE_URL"),
|
||||
},
|
||||
});
|
||||
34
prisma/generated/prisma/browser.ts
Normal file
34
prisma/generated/prisma/browser.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* This file should be your main import to use Prisma-related types and utilities in a browser.
|
||||
* Use it to get access to models, enums, and input types.
|
||||
*
|
||||
* This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only.
|
||||
* See `client.ts` for the standard, server-side entry point.
|
||||
*
|
||||
* 🟢 You can import this file directly.
|
||||
*/
|
||||
|
||||
import * as Prisma from './internal/prismaNamespaceBrowser'
|
||||
export { Prisma }
|
||||
export * as $Enums from './enums'
|
||||
export * from './enums';
|
||||
/**
|
||||
* Model User
|
||||
*
|
||||
*/
|
||||
export type User = Prisma.UserModel
|
||||
/**
|
||||
* Model UserPreferences
|
||||
*
|
||||
*/
|
||||
export type UserPreferences = Prisma.UserPreferencesModel
|
||||
/**
|
||||
* Model Event
|
||||
*
|
||||
*/
|
||||
export type Event = Prisma.EventModel
|
||||
56
prisma/generated/prisma/client.ts
Normal file
56
prisma/generated/prisma/client.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.
|
||||
* If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.
|
||||
*
|
||||
* 🟢 You can import this file directly.
|
||||
*/
|
||||
|
||||
import * as process from 'node:process'
|
||||
import * as path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
import * as runtime from "@prisma/client/runtime/client"
|
||||
import * as $Enums from "./enums"
|
||||
import * as $Class from "./internal/class"
|
||||
import * as Prisma from "./internal/prismaNamespace"
|
||||
|
||||
export * as $Enums from './enums'
|
||||
export * from "./enums"
|
||||
/**
|
||||
* ## Prisma Client
|
||||
*
|
||||
* Type-safe database client for TypeScript
|
||||
* @example
|
||||
* ```
|
||||
* const prisma = new PrismaClient()
|
||||
* // Fetch zero or more Users
|
||||
* const users = await prisma.user.findMany()
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/client).
|
||||
*/
|
||||
export const PrismaClient = $Class.getPrismaClientClass()
|
||||
export type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions["omit"] = Prisma.PrismaClientOptions["omit"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>
|
||||
export { Prisma }
|
||||
|
||||
/**
|
||||
* Model User
|
||||
*
|
||||
*/
|
||||
export type User = Prisma.UserModel
|
||||
/**
|
||||
* Model UserPreferences
|
||||
*
|
||||
*/
|
||||
export type UserPreferences = Prisma.UserPreferencesModel
|
||||
/**
|
||||
* Model Event
|
||||
*
|
||||
*/
|
||||
export type Event = Prisma.EventModel
|
||||
374
prisma/generated/prisma/commonInputTypes.ts
Normal file
374
prisma/generated/prisma/commonInputTypes.ts
Normal file
@@ -0,0 +1,374 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* This file exports various common sort, input & filter types that are not directly linked to a particular model.
|
||||
*
|
||||
* 🟢 You can import this file directly.
|
||||
*/
|
||||
|
||||
import type * as runtime from "@prisma/client/runtime/client"
|
||||
import * as $Enums from "./enums"
|
||||
import type * as Prisma from "./internal/prismaNamespace"
|
||||
|
||||
|
||||
export type StringFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
in?: string[]
|
||||
notIn?: string[]
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringFilter<$PrismaModel> | string
|
||||
}
|
||||
|
||||
export type EnumRoleFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.Role | Prisma.EnumRoleFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.Role[]
|
||||
notIn?: $Enums.Role[]
|
||||
not?: Prisma.NestedEnumRoleFilter<$PrismaModel> | $Enums.Role
|
||||
}
|
||||
|
||||
export type IntFilter<$PrismaModel = never> = {
|
||||
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
in?: number[]
|
||||
notIn?: number[]
|
||||
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedIntFilter<$PrismaModel> | number
|
||||
}
|
||||
|
||||
export type StringNullableFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
|
||||
in?: string[] | null
|
||||
notIn?: string[] | null
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
|
||||
}
|
||||
|
||||
export type DateTimeFilter<$PrismaModel = never> = {
|
||||
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
in?: Date[] | string[]
|
||||
notIn?: Date[] | string[]
|
||||
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string
|
||||
}
|
||||
|
||||
export type SortOrderInput = {
|
||||
sort: Prisma.SortOrder
|
||||
nulls?: Prisma.NullsOrder
|
||||
}
|
||||
|
||||
export type StringWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
in?: string[]
|
||||
notIn?: string[]
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedStringFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedStringFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type EnumRoleWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.Role | Prisma.EnumRoleFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.Role[]
|
||||
notIn?: $Enums.Role[]
|
||||
not?: Prisma.NestedEnumRoleWithAggregatesFilter<$PrismaModel> | $Enums.Role
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedEnumRoleFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedEnumRoleFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type IntWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
in?: number[]
|
||||
notIn?: number[]
|
||||
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_avg?: Prisma.NestedFloatFilter<$PrismaModel>
|
||||
_sum?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type StringNullableWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
|
||||
in?: string[] | null
|
||||
notIn?: string[] | null
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null
|
||||
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedStringNullableFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type DateTimeWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
in?: Date[] | string[]
|
||||
notIn?: Date[] | string[]
|
||||
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedDateTimeFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedDateTimeFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type EnumEventTypeFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventType | Prisma.EnumEventTypeFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventType[]
|
||||
notIn?: $Enums.EventType[]
|
||||
not?: Prisma.NestedEnumEventTypeFilter<$PrismaModel> | $Enums.EventType
|
||||
}
|
||||
|
||||
export type EnumEventStatusFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventStatus | Prisma.EnumEventStatusFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventStatus[]
|
||||
notIn?: $Enums.EventStatus[]
|
||||
not?: Prisma.NestedEnumEventStatusFilter<$PrismaModel> | $Enums.EventStatus
|
||||
}
|
||||
|
||||
export type EnumEventTypeWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventType | Prisma.EnumEventTypeFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventType[]
|
||||
notIn?: $Enums.EventType[]
|
||||
not?: Prisma.NestedEnumEventTypeWithAggregatesFilter<$PrismaModel> | $Enums.EventType
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedEnumEventTypeFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedEnumEventTypeFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type EnumEventStatusWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventStatus | Prisma.EnumEventStatusFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventStatus[]
|
||||
notIn?: $Enums.EventStatus[]
|
||||
not?: Prisma.NestedEnumEventStatusWithAggregatesFilter<$PrismaModel> | $Enums.EventStatus
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedEnumEventStatusFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedEnumEventStatusFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedStringFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
in?: string[]
|
||||
notIn?: string[]
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringFilter<$PrismaModel> | string
|
||||
}
|
||||
|
||||
export type NestedEnumRoleFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.Role | Prisma.EnumRoleFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.Role[]
|
||||
notIn?: $Enums.Role[]
|
||||
not?: Prisma.NestedEnumRoleFilter<$PrismaModel> | $Enums.Role
|
||||
}
|
||||
|
||||
export type NestedIntFilter<$PrismaModel = never> = {
|
||||
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
in?: number[]
|
||||
notIn?: number[]
|
||||
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedIntFilter<$PrismaModel> | number
|
||||
}
|
||||
|
||||
export type NestedStringNullableFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
|
||||
in?: string[] | null
|
||||
notIn?: string[] | null
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
|
||||
}
|
||||
|
||||
export type NestedDateTimeFilter<$PrismaModel = never> = {
|
||||
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
in?: Date[] | string[]
|
||||
notIn?: Date[] | string[]
|
||||
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string
|
||||
}
|
||||
|
||||
export type NestedStringWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
in?: string[]
|
||||
notIn?: string[]
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedStringFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedStringFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedEnumRoleWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.Role | Prisma.EnumRoleFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.Role[]
|
||||
notIn?: $Enums.Role[]
|
||||
not?: Prisma.NestedEnumRoleWithAggregatesFilter<$PrismaModel> | $Enums.Role
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedEnumRoleFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedEnumRoleFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedIntWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
in?: number[]
|
||||
notIn?: number[]
|
||||
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_avg?: Prisma.NestedFloatFilter<$PrismaModel>
|
||||
_sum?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedFloatFilter<$PrismaModel = never> = {
|
||||
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel>
|
||||
in?: number[]
|
||||
notIn?: number[]
|
||||
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
|
||||
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
|
||||
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
|
||||
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedFloatFilter<$PrismaModel> | number
|
||||
}
|
||||
|
||||
export type NestedStringNullableWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
|
||||
in?: string[] | null
|
||||
notIn?: string[] | null
|
||||
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null
|
||||
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedStringNullableFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedIntNullableFilter<$PrismaModel = never> = {
|
||||
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
|
||||
in?: number[] | null
|
||||
notIn?: number[] | null
|
||||
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null
|
||||
}
|
||||
|
||||
export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
in?: Date[] | string[]
|
||||
notIn?: Date[] | string[]
|
||||
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
|
||||
not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedDateTimeFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedDateTimeFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedEnumEventTypeFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventType | Prisma.EnumEventTypeFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventType[]
|
||||
notIn?: $Enums.EventType[]
|
||||
not?: Prisma.NestedEnumEventTypeFilter<$PrismaModel> | $Enums.EventType
|
||||
}
|
||||
|
||||
export type NestedEnumEventStatusFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventStatus | Prisma.EnumEventStatusFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventStatus[]
|
||||
notIn?: $Enums.EventStatus[]
|
||||
not?: Prisma.NestedEnumEventStatusFilter<$PrismaModel> | $Enums.EventStatus
|
||||
}
|
||||
|
||||
export type NestedEnumEventTypeWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventType | Prisma.EnumEventTypeFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventType[]
|
||||
notIn?: $Enums.EventType[]
|
||||
not?: Prisma.NestedEnumEventTypeWithAggregatesFilter<$PrismaModel> | $Enums.EventType
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedEnumEventTypeFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedEnumEventTypeFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
export type NestedEnumEventStatusWithAggregatesFilter<$PrismaModel = never> = {
|
||||
equals?: $Enums.EventStatus | Prisma.EnumEventStatusFieldRefInput<$PrismaModel>
|
||||
in?: $Enums.EventStatus[]
|
||||
notIn?: $Enums.EventStatus[]
|
||||
not?: Prisma.NestedEnumEventStatusWithAggregatesFilter<$PrismaModel> | $Enums.EventStatus
|
||||
_count?: Prisma.NestedIntFilter<$PrismaModel>
|
||||
_min?: Prisma.NestedEnumEventStatusFilter<$PrismaModel>
|
||||
_max?: Prisma.NestedEnumEventStatusFilter<$PrismaModel>
|
||||
}
|
||||
|
||||
|
||||
36
prisma/generated/prisma/enums.ts
Normal file
36
prisma/generated/prisma/enums.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* This file exports all enum related types from the schema.
|
||||
*
|
||||
* 🟢 You can import this file directly.
|
||||
*/
|
||||
|
||||
export const Role = {
|
||||
USER: 'USER',
|
||||
ADMIN: 'ADMIN'
|
||||
} as const
|
||||
|
||||
export type Role = (typeof Role)[keyof typeof Role]
|
||||
|
||||
|
||||
export const EventType = {
|
||||
SUMMIT: 'SUMMIT',
|
||||
LAUNCH: 'LAUNCH',
|
||||
FESTIVAL: 'FESTIVAL',
|
||||
COMPETITION: 'COMPETITION'
|
||||
} as const
|
||||
|
||||
export type EventType = (typeof EventType)[keyof typeof EventType]
|
||||
|
||||
|
||||
export const EventStatus = {
|
||||
UPCOMING: 'UPCOMING',
|
||||
LIVE: 'LIVE',
|
||||
PAST: 'PAST'
|
||||
} as const
|
||||
|
||||
export type EventStatus = (typeof EventStatus)[keyof typeof EventStatus]
|
||||
210
prisma/generated/prisma/internal/class.ts
Normal file
210
prisma/generated/prisma/internal/class.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* WARNING: This is an internal file that is subject to change!
|
||||
*
|
||||
* 🛑 Under no circumstances should you import this file directly! 🛑
|
||||
*
|
||||
* Please import the `PrismaClient` class from the `client.ts` file instead.
|
||||
*/
|
||||
|
||||
import * as runtime from "@prisma/client/runtime/client"
|
||||
import type * as Prisma from "./prismaNamespace"
|
||||
|
||||
|
||||
const config: runtime.GetPrismaClientConfig = {
|
||||
"previewFeatures": [],
|
||||
"clientVersion": "7.1.0",
|
||||
"engineVersion": "ab635e6b9d606fa5c8fb8b1a7f909c3c3c1c98ba",
|
||||
"activeProvider": "sqlite",
|
||||
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"./generated/prisma\"\n}\n\ndatasource db {\n provider = \"sqlite\"\n}\n\nenum Role {\n USER\n ADMIN\n}\n\nenum EventType {\n SUMMIT\n LAUNCH\n FESTIVAL\n COMPETITION\n}\n\nenum EventStatus {\n UPCOMING\n LIVE\n PAST\n}\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n password String\n username String @unique\n role Role @default(USER)\n score Int @default(0)\n level Int @default(1)\n hp Int @default(1000)\n maxHp Int @default(1000)\n xp Int @default(0)\n maxXp Int @default(5000)\n avatar String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n preferences UserPreferences?\n\n @@index([score])\n @@index([email])\n}\n\nmodel UserPreferences {\n id String @id @default(cuid())\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Background images for each page\n homeBackground String?\n eventsBackground String?\n leaderboardBackground String?\n\n // Other UI preferences can be added here\n theme String? @default(\"default\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel Event {\n id String @id @default(cuid())\n date String\n name String\n description String\n type EventType\n status EventStatus\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([status])\n @@index([date])\n}\n",
|
||||
"runtimeDataModel": {
|
||||
"models": {},
|
||||
"enums": {},
|
||||
"types": {}
|
||||
}
|
||||
}
|
||||
|
||||
config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"Role\"},{\"name\":\"score\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"level\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"hp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxHp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"xp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxXp\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"avatar\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"preferences\",\"kind\":\"object\",\"type\":\"UserPreferences\",\"relationName\":\"UserToUserPreferences\"}],\"dbName\":null},\"UserPreferences\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToUserPreferences\"},{\"name\":\"homeBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"eventsBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"leaderboardBackground\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"theme\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"EventType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"EventStatus\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
|
||||
|
||||
async function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {
|
||||
const { Buffer } = await import('node:buffer')
|
||||
const wasmArray = Buffer.from(wasmBase64, 'base64')
|
||||
return new WebAssembly.Module(wasmArray)
|
||||
}
|
||||
|
||||
config.compilerWasm = {
|
||||
getRuntime: async () => await import("@prisma/client/runtime/query_compiler_bg.sqlite.mjs"),
|
||||
|
||||
getQueryCompilerWasmModule: async () => {
|
||||
const { wasm } = await import("@prisma/client/runtime/query_compiler_bg.sqlite.wasm-base64.mjs")
|
||||
return await decodeBase64AsWasm(wasm)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export type LogOptions<ClientOptions extends Prisma.PrismaClientOptions> =
|
||||
'log' extends keyof ClientOptions ? ClientOptions['log'] extends Array<Prisma.LogLevel | Prisma.LogDefinition> ? Prisma.GetEvents<ClientOptions['log']> : never : never
|
||||
|
||||
export interface PrismaClientConstructor {
|
||||
/**
|
||||
* ## Prisma Client
|
||||
*
|
||||
* Type-safe database client for TypeScript
|
||||
* @example
|
||||
* ```
|
||||
* const prisma = new PrismaClient()
|
||||
* // Fetch zero or more Users
|
||||
* const users = await prisma.user.findMany()
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/client).
|
||||
*/
|
||||
|
||||
new <
|
||||
Options extends Prisma.PrismaClientOptions = Prisma.PrismaClientOptions,
|
||||
LogOpts extends LogOptions<Options> = LogOptions<Options>,
|
||||
OmitOpts extends Prisma.PrismaClientOptions['omit'] = Options extends { omit: infer U } ? U : Prisma.PrismaClientOptions['omit'],
|
||||
ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs
|
||||
>(options: Prisma.Subset<Options, Prisma.PrismaClientOptions> ): PrismaClient<LogOpts, OmitOpts, ExtArgs>
|
||||
}
|
||||
|
||||
/**
|
||||
* ## Prisma Client
|
||||
*
|
||||
* Type-safe database client for TypeScript
|
||||
* @example
|
||||
* ```
|
||||
* const prisma = new PrismaClient()
|
||||
* // Fetch zero or more Users
|
||||
* const users = await prisma.user.findMany()
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/client).
|
||||
*/
|
||||
|
||||
export interface PrismaClient<
|
||||
in LogOpts extends Prisma.LogLevel = never,
|
||||
in out OmitOpts extends Prisma.PrismaClientOptions['omit'] = undefined,
|
||||
in out ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs
|
||||
> {
|
||||
[K: symbol]: { types: Prisma.TypeMap<ExtArgs>['other'] }
|
||||
|
||||
$on<V extends LogOpts>(eventType: V, callback: (event: V extends 'query' ? Prisma.QueryEvent : Prisma.LogEvent) => void): PrismaClient;
|
||||
|
||||
/**
|
||||
* Connect with the database
|
||||
*/
|
||||
$connect(): runtime.Types.Utils.JsPromise<void>;
|
||||
|
||||
/**
|
||||
* Disconnect from the database
|
||||
*/
|
||||
$disconnect(): runtime.Types.Utils.JsPromise<void>;
|
||||
|
||||
/**
|
||||
* Executes a prepared raw query and returns the number of affected rows.
|
||||
* @example
|
||||
* ```
|
||||
* const result = await prisma.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};`
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/raw-queries).
|
||||
*/
|
||||
$executeRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise<number>;
|
||||
|
||||
/**
|
||||
* Executes a raw query and returns the number of affected rows.
|
||||
* Susceptible to SQL injections, see documentation.
|
||||
* @example
|
||||
* ```
|
||||
* const result = await prisma.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com')
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/raw-queries).
|
||||
*/
|
||||
$executeRawUnsafe<T = unknown>(query: string, ...values: any[]): Prisma.PrismaPromise<number>;
|
||||
|
||||
/**
|
||||
* Performs a prepared raw query and returns the `SELECT` data.
|
||||
* @example
|
||||
* ```
|
||||
* const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};`
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/raw-queries).
|
||||
*/
|
||||
$queryRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise<T>;
|
||||
|
||||
/**
|
||||
* Performs a raw query and returns the `SELECT` data.
|
||||
* Susceptible to SQL injections, see documentation.
|
||||
* @example
|
||||
* ```
|
||||
* const result = await prisma.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com')
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://pris.ly/d/raw-queries).
|
||||
*/
|
||||
$queryRawUnsafe<T = unknown>(query: string, ...values: any[]): Prisma.PrismaPromise<T>;
|
||||
|
||||
|
||||
/**
|
||||
* Allows the running of a sequence of read/write operations that are guaranteed to either succeed or fail as a whole.
|
||||
* @example
|
||||
* ```
|
||||
* const [george, bob, alice] = await prisma.$transaction([
|
||||
* prisma.user.create({ data: { name: 'George' } }),
|
||||
* prisma.user.create({ data: { name: 'Bob' } }),
|
||||
* prisma.user.create({ data: { name: 'Alice' } }),
|
||||
* ])
|
||||
* ```
|
||||
*
|
||||
* Read more in our [docs](https://www.prisma.io/docs/concepts/components/prisma-client/transactions).
|
||||
*/
|
||||
$transaction<P extends Prisma.PrismaPromise<any>[]>(arg: [...P], options?: { isolationLevel?: Prisma.TransactionIsolationLevel }): runtime.Types.Utils.JsPromise<runtime.Types.Utils.UnwrapTuple<P>>
|
||||
|
||||
$transaction<R>(fn: (prisma: Omit<PrismaClient, runtime.ITXClientDenyList>) => runtime.Types.Utils.JsPromise<R>, options?: { maxWait?: number, timeout?: number, isolationLevel?: Prisma.TransactionIsolationLevel }): runtime.Types.Utils.JsPromise<R>
|
||||
|
||||
$extends: runtime.Types.Extensions.ExtendsHook<"extends", Prisma.TypeMapCb<OmitOpts>, ExtArgs, runtime.Types.Utils.Call<Prisma.TypeMapCb<OmitOpts>, {
|
||||
extArgs: ExtArgs
|
||||
}>>
|
||||
|
||||
/**
|
||||
* `prisma.user`: Exposes CRUD operations for the **User** model.
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* // Fetch zero or more Users
|
||||
* const users = await prisma.user.findMany()
|
||||
* ```
|
||||
*/
|
||||
get user(): Prisma.UserDelegate<ExtArgs, { omit: OmitOpts }>;
|
||||
|
||||
/**
|
||||
* `prisma.userPreferences`: Exposes CRUD operations for the **UserPreferences** model.
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* // Fetch zero or more UserPreferences
|
||||
* const userPreferences = await prisma.userPreferences.findMany()
|
||||
* ```
|
||||
*/
|
||||
get userPreferences(): Prisma.UserPreferencesDelegate<ExtArgs, { omit: OmitOpts }>;
|
||||
|
||||
/**
|
||||
* `prisma.event`: Exposes CRUD operations for the **Event** model.
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* // Fetch zero or more Events
|
||||
* const events = await prisma.event.findMany()
|
||||
* ```
|
||||
*/
|
||||
get event(): Prisma.EventDelegate<ExtArgs, { omit: OmitOpts }>;
|
||||
}
|
||||
|
||||
export function getPrismaClientClass(): PrismaClientConstructor {
|
||||
return runtime.getPrismaClient(config) as unknown as PrismaClientConstructor
|
||||
}
|
||||
945
prisma/generated/prisma/internal/prismaNamespace.ts
Normal file
945
prisma/generated/prisma/internal/prismaNamespace.ts
Normal file
@@ -0,0 +1,945 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* WARNING: This is an internal file that is subject to change!
|
||||
*
|
||||
* 🛑 Under no circumstances should you import this file directly! 🛑
|
||||
*
|
||||
* All exports from this file are wrapped under a `Prisma` namespace object in the client.ts file.
|
||||
* While this enables partial backward compatibility, it is not part of the stable public API.
|
||||
*
|
||||
* If you are looking for your Models, Enums, and Input Types, please import them from the respective
|
||||
* model files in the `model` directory!
|
||||
*/
|
||||
|
||||
import * as runtime from "@prisma/client/runtime/client"
|
||||
import type * as Prisma from "../models"
|
||||
import { type PrismaClient } from "./class"
|
||||
|
||||
export type * from '../models'
|
||||
|
||||
export type DMMF = typeof runtime.DMMF
|
||||
|
||||
export type PrismaPromise<T> = runtime.Types.Public.PrismaPromise<T>
|
||||
|
||||
/**
|
||||
* Prisma Errors
|
||||
*/
|
||||
|
||||
export const PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError
|
||||
export type PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError
|
||||
|
||||
export const PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError
|
||||
export type PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError
|
||||
|
||||
export const PrismaClientRustPanicError = runtime.PrismaClientRustPanicError
|
||||
export type PrismaClientRustPanicError = runtime.PrismaClientRustPanicError
|
||||
|
||||
export const PrismaClientInitializationError = runtime.PrismaClientInitializationError
|
||||
export type PrismaClientInitializationError = runtime.PrismaClientInitializationError
|
||||
|
||||
export const PrismaClientValidationError = runtime.PrismaClientValidationError
|
||||
export type PrismaClientValidationError = runtime.PrismaClientValidationError
|
||||
|
||||
/**
|
||||
* Re-export of sql-template-tag
|
||||
*/
|
||||
export const sql = runtime.sqltag
|
||||
export const empty = runtime.empty
|
||||
export const join = runtime.join
|
||||
export const raw = runtime.raw
|
||||
export const Sql = runtime.Sql
|
||||
export type Sql = runtime.Sql
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decimal.js
|
||||
*/
|
||||
export const Decimal = runtime.Decimal
|
||||
export type Decimal = runtime.Decimal
|
||||
|
||||
export type DecimalJsLike = runtime.DecimalJsLike
|
||||
|
||||
/**
|
||||
* Extensions
|
||||
*/
|
||||
export type Extension = runtime.Types.Extensions.UserArgs
|
||||
export const getExtensionContext = runtime.Extensions.getExtensionContext
|
||||
export type Args<T, F extends runtime.Operation> = runtime.Types.Public.Args<T, F>
|
||||
export type Payload<T, F extends runtime.Operation = never> = runtime.Types.Public.Payload<T, F>
|
||||
export type Result<T, A, F extends runtime.Operation> = runtime.Types.Public.Result<T, A, F>
|
||||
export type Exact<A, W> = runtime.Types.Public.Exact<A, W>
|
||||
|
||||
export type PrismaVersion = {
|
||||
client: string
|
||||
engine: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Prisma Client JS version: 7.1.0
|
||||
* Query Engine version: ab635e6b9d606fa5c8fb8b1a7f909c3c3c1c98ba
|
||||
*/
|
||||
export const prismaVersion: PrismaVersion = {
|
||||
client: "7.1.0",
|
||||
engine: "ab635e6b9d606fa5c8fb8b1a7f909c3c3c1c98ba"
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility Types
|
||||
*/
|
||||
|
||||
export type Bytes = runtime.Bytes
|
||||
export type JsonObject = runtime.JsonObject
|
||||
export type JsonArray = runtime.JsonArray
|
||||
export type JsonValue = runtime.JsonValue
|
||||
export type InputJsonObject = runtime.InputJsonObject
|
||||
export type InputJsonArray = runtime.InputJsonArray
|
||||
export type InputJsonValue = runtime.InputJsonValue
|
||||
|
||||
|
||||
export const NullTypes = {
|
||||
DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull),
|
||||
JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull),
|
||||
AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull),
|
||||
}
|
||||
/**
|
||||
* Helper for filtering JSON entries that have `null` on the database (empty on the db)
|
||||
*
|
||||
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
||||
*/
|
||||
export const DbNull = runtime.DbNull
|
||||
|
||||
/**
|
||||
* Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
|
||||
*
|
||||
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
||||
*/
|
||||
export const JsonNull = runtime.JsonNull
|
||||
|
||||
/**
|
||||
* Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
|
||||
*
|
||||
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
||||
*/
|
||||
export const AnyNull = runtime.AnyNull
|
||||
|
||||
|
||||
type SelectAndInclude = {
|
||||
select: any
|
||||
include: any
|
||||
}
|
||||
|
||||
type SelectAndOmit = {
|
||||
select: any
|
||||
omit: any
|
||||
}
|
||||
|
||||
/**
|
||||
* From T, pick a set of properties whose keys are in the union K
|
||||
*/
|
||||
type Prisma__Pick<T, K extends keyof T> = {
|
||||
[P in K]: T[P];
|
||||
};
|
||||
|
||||
export type Enumerable<T> = T | Array<T>;
|
||||
|
||||
/**
|
||||
* Subset
|
||||
* @desc From `T` pick properties that exist in `U`. Simple version of Intersection
|
||||
*/
|
||||
export type Subset<T, U> = {
|
||||
[key in keyof T]: key extends keyof U ? T[key] : never;
|
||||
};
|
||||
|
||||
/**
|
||||
* SelectSubset
|
||||
* @desc From `T` pick properties that exist in `U`. Simple version of Intersection.
|
||||
* Additionally, it validates, if both select and include are present. If the case, it errors.
|
||||
*/
|
||||
export type SelectSubset<T, U> = {
|
||||
[key in keyof T]: key extends keyof U ? T[key] : never
|
||||
} &
|
||||
(T extends SelectAndInclude
|
||||
? 'Please either choose `select` or `include`.'
|
||||
: T extends SelectAndOmit
|
||||
? 'Please either choose `select` or `omit`.'
|
||||
: {})
|
||||
|
||||
/**
|
||||
* Subset + Intersection
|
||||
* @desc From `T` pick properties that exist in `U` and intersect `K`
|
||||
*/
|
||||
export type SubsetIntersection<T, U, K> = {
|
||||
[key in keyof T]: key extends keyof U ? T[key] : never
|
||||
} &
|
||||
K
|
||||
|
||||
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
||||
|
||||
/**
|
||||
* XOR is needed to have a real mutually exclusive union type
|
||||
* https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types
|
||||
*/
|
||||
export type XOR<T, U> =
|
||||
T extends object ?
|
||||
U extends object ?
|
||||
(Without<T, U> & U) | (Without<U, T> & T)
|
||||
: U : T
|
||||
|
||||
|
||||
/**
|
||||
* Is T a Record?
|
||||
*/
|
||||
type IsObject<T extends any> = T extends Array<any>
|
||||
? False
|
||||
: T extends Date
|
||||
? False
|
||||
: T extends Uint8Array
|
||||
? False
|
||||
: T extends BigInt
|
||||
? False
|
||||
: T extends object
|
||||
? True
|
||||
: False
|
||||
|
||||
|
||||
/**
|
||||
* If it's T[], return T
|
||||
*/
|
||||
export type UnEnumerate<T extends unknown> = T extends Array<infer U> ? U : T
|
||||
|
||||
/**
|
||||
* From ts-toolbelt
|
||||
*/
|
||||
|
||||
type __Either<O extends object, K extends Key> = Omit<O, K> &
|
||||
{
|
||||
// Merge all but K
|
||||
[P in K]: Prisma__Pick<O, P & keyof O> // With K possibilities
|
||||
}[K]
|
||||
|
||||
type EitherStrict<O extends object, K extends Key> = Strict<__Either<O, K>>
|
||||
|
||||
type EitherLoose<O extends object, K extends Key> = ComputeRaw<__Either<O, K>>
|
||||
|
||||
type _Either<
|
||||
O extends object,
|
||||
K extends Key,
|
||||
strict extends Boolean
|
||||
> = {
|
||||
1: EitherStrict<O, K>
|
||||
0: EitherLoose<O, K>
|
||||
}[strict]
|
||||
|
||||
export type Either<
|
||||
O extends object,
|
||||
K extends Key,
|
||||
strict extends Boolean = 1
|
||||
> = O extends unknown ? _Either<O, K, strict> : never
|
||||
|
||||
export type Union = any
|
||||
|
||||
export type PatchUndefined<O extends object, O1 extends object> = {
|
||||
[K in keyof O]: O[K] extends undefined ? At<O1, K> : O[K]
|
||||
} & {}
|
||||
|
||||
/** Helper Types for "Merge" **/
|
||||
export type IntersectOf<U extends Union> = (
|
||||
U extends unknown ? (k: U) => void : never
|
||||
) extends (k: infer I) => void
|
||||
? I
|
||||
: never
|
||||
|
||||
export type Overwrite<O extends object, O1 extends object> = {
|
||||
[K in keyof O]: K extends keyof O1 ? O1[K] : O[K];
|
||||
} & {};
|
||||
|
||||
type _Merge<U extends object> = IntersectOf<Overwrite<U, {
|
||||
[K in keyof U]-?: At<U, K>;
|
||||
}>>;
|
||||
|
||||
type Key = string | number | symbol;
|
||||
type AtStrict<O extends object, K extends Key> = O[K & keyof O];
|
||||
type AtLoose<O extends object, K extends Key> = O extends unknown ? AtStrict<O, K> : never;
|
||||
export type At<O extends object, K extends Key, strict extends Boolean = 1> = {
|
||||
1: AtStrict<O, K>;
|
||||
0: AtLoose<O, K>;
|
||||
}[strict];
|
||||
|
||||
export type ComputeRaw<A extends any> = A extends Function ? A : {
|
||||
[K in keyof A]: A[K];
|
||||
} & {};
|
||||
|
||||
export type OptionalFlat<O> = {
|
||||
[K in keyof O]?: O[K];
|
||||
} & {};
|
||||
|
||||
type _Record<K extends keyof any, T> = {
|
||||
[P in K]: T;
|
||||
};
|
||||
|
||||
// cause typescript not to expand types and preserve names
|
||||
type NoExpand<T> = T extends unknown ? T : never;
|
||||
|
||||
// this type assumes the passed object is entirely optional
|
||||
export type AtLeast<O extends object, K extends string> = NoExpand<
|
||||
O extends unknown
|
||||
? | (K extends keyof O ? { [P in K]: O[P] } & O : O)
|
||||
| {[P in keyof O as P extends K ? P : never]-?: O[P]} & O
|
||||
: never>;
|
||||
|
||||
type _Strict<U, _U = U> = U extends unknown ? U & OptionalFlat<_Record<Exclude<Keys<_U>, keyof U>, never>> : never;
|
||||
|
||||
export type Strict<U extends object> = ComputeRaw<_Strict<U>>;
|
||||
/** End Helper Types for "Merge" **/
|
||||
|
||||
export type Merge<U extends object> = ComputeRaw<_Merge<Strict<U>>>;
|
||||
|
||||
export type Boolean = True | False
|
||||
|
||||
export type True = 1
|
||||
|
||||
export type False = 0
|
||||
|
||||
export type Not<B extends Boolean> = {
|
||||
0: 1
|
||||
1: 0
|
||||
}[B]
|
||||
|
||||
export type Extends<A1 extends any, A2 extends any> = [A1] extends [never]
|
||||
? 0 // anything `never` is false
|
||||
: A1 extends A2
|
||||
? 1
|
||||
: 0
|
||||
|
||||
export type Has<U extends Union, U1 extends Union> = Not<
|
||||
Extends<Exclude<U1, U>, U1>
|
||||
>
|
||||
|
||||
export type Or<B1 extends Boolean, B2 extends Boolean> = {
|
||||
0: {
|
||||
0: 0
|
||||
1: 1
|
||||
}
|
||||
1: {
|
||||
0: 1
|
||||
1: 1
|
||||
}
|
||||
}[B1][B2]
|
||||
|
||||
export type Keys<U extends Union> = U extends unknown ? keyof U : never
|
||||
|
||||
export type GetScalarType<T, O> = O extends object ? {
|
||||
[P in keyof T]: P extends keyof O
|
||||
? O[P]
|
||||
: never
|
||||
} : never
|
||||
|
||||
type FieldPaths<
|
||||
T,
|
||||
U = Omit<T, '_avg' | '_sum' | '_count' | '_min' | '_max'>
|
||||
> = IsObject<T> extends True ? U : T
|
||||
|
||||
export type GetHavingFields<T> = {
|
||||
[K in keyof T]: Or<
|
||||
Or<Extends<'OR', K>, Extends<'AND', K>>,
|
||||
Extends<'NOT', K>
|
||||
> extends True
|
||||
? // infer is only needed to not hit TS limit
|
||||
// based on the brilliant idea of Pierre-Antoine Mills
|
||||
// https://github.com/microsoft/TypeScript/issues/30188#issuecomment-478938437
|
||||
T[K] extends infer TK
|
||||
? GetHavingFields<UnEnumerate<TK> extends object ? Merge<UnEnumerate<TK>> : never>
|
||||
: never
|
||||
: {} extends FieldPaths<T[K]>
|
||||
? never
|
||||
: K
|
||||
}[keyof T]
|
||||
|
||||
/**
|
||||
* Convert tuple to union
|
||||
*/
|
||||
type _TupleToUnion<T> = T extends (infer E)[] ? E : never
|
||||
type TupleToUnion<K extends readonly any[]> = _TupleToUnion<K>
|
||||
export type MaybeTupleToUnion<T> = T extends any[] ? TupleToUnion<T> : T
|
||||
|
||||
/**
|
||||
* Like `Pick`, but additionally can also accept an array of keys
|
||||
*/
|
||||
export type PickEnumerable<T, K extends Enumerable<keyof T> | keyof T> = Prisma__Pick<T, MaybeTupleToUnion<K>>
|
||||
|
||||
/**
|
||||
* Exclude all keys with underscores
|
||||
*/
|
||||
export type ExcludeUnderscoreKeys<T extends string> = T extends `_${string}` ? never : T
|
||||
|
||||
|
||||
export type FieldRef<Model, FieldType> = runtime.FieldRef<Model, FieldType>
|
||||
|
||||
type FieldRefInputType<Model, FieldType> = Model extends never ? never : FieldRef<Model, FieldType>
|
||||
|
||||
|
||||
export const ModelName = {
|
||||
User: 'User',
|
||||
UserPreferences: 'UserPreferences',
|
||||
Event: 'Event'
|
||||
} as const
|
||||
|
||||
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
|
||||
|
||||
|
||||
|
||||
export interface TypeMapCb<GlobalOmitOptions = {}> extends runtime.Types.Utils.Fn<{extArgs: runtime.Types.Extensions.InternalArgs }, runtime.Types.Utils.Record<string, any>> {
|
||||
returns: TypeMap<this['params']['extArgs'], GlobalOmitOptions>
|
||||
}
|
||||
|
||||
export type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> = {
|
||||
globalOmitOptions: {
|
||||
omit: GlobalOmitOptions
|
||||
}
|
||||
meta: {
|
||||
modelProps: "user" | "userPreferences" | "event"
|
||||
txIsolationLevel: TransactionIsolationLevel
|
||||
}
|
||||
model: {
|
||||
User: {
|
||||
payload: Prisma.$UserPayload<ExtArgs>
|
||||
fields: Prisma.UserFieldRefs
|
||||
operations: {
|
||||
findUnique: {
|
||||
args: Prisma.UserFindUniqueArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload> | null
|
||||
}
|
||||
findUniqueOrThrow: {
|
||||
args: Prisma.UserFindUniqueOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>
|
||||
}
|
||||
findFirst: {
|
||||
args: Prisma.UserFindFirstArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload> | null
|
||||
}
|
||||
findFirstOrThrow: {
|
||||
args: Prisma.UserFindFirstOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>
|
||||
}
|
||||
findMany: {
|
||||
args: Prisma.UserFindManyArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>[]
|
||||
}
|
||||
create: {
|
||||
args: Prisma.UserCreateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>
|
||||
}
|
||||
createMany: {
|
||||
args: Prisma.UserCreateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
createManyAndReturn: {
|
||||
args: Prisma.UserCreateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>[]
|
||||
}
|
||||
delete: {
|
||||
args: Prisma.UserDeleteArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>
|
||||
}
|
||||
update: {
|
||||
args: Prisma.UserUpdateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>
|
||||
}
|
||||
deleteMany: {
|
||||
args: Prisma.UserDeleteManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateMany: {
|
||||
args: Prisma.UserUpdateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateManyAndReturn: {
|
||||
args: Prisma.UserUpdateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>[]
|
||||
}
|
||||
upsert: {
|
||||
args: Prisma.UserUpsertArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>
|
||||
}
|
||||
aggregate: {
|
||||
args: Prisma.UserAggregateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.AggregateUser>
|
||||
}
|
||||
groupBy: {
|
||||
args: Prisma.UserGroupByArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.UserGroupByOutputType>[]
|
||||
}
|
||||
count: {
|
||||
args: Prisma.UserCountArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.UserCountAggregateOutputType> | number
|
||||
}
|
||||
}
|
||||
}
|
||||
UserPreferences: {
|
||||
payload: Prisma.$UserPreferencesPayload<ExtArgs>
|
||||
fields: Prisma.UserPreferencesFieldRefs
|
||||
operations: {
|
||||
findUnique: {
|
||||
args: Prisma.UserPreferencesFindUniqueArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload> | null
|
||||
}
|
||||
findUniqueOrThrow: {
|
||||
args: Prisma.UserPreferencesFindUniqueOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>
|
||||
}
|
||||
findFirst: {
|
||||
args: Prisma.UserPreferencesFindFirstArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload> | null
|
||||
}
|
||||
findFirstOrThrow: {
|
||||
args: Prisma.UserPreferencesFindFirstOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>
|
||||
}
|
||||
findMany: {
|
||||
args: Prisma.UserPreferencesFindManyArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>[]
|
||||
}
|
||||
create: {
|
||||
args: Prisma.UserPreferencesCreateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>
|
||||
}
|
||||
createMany: {
|
||||
args: Prisma.UserPreferencesCreateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
createManyAndReturn: {
|
||||
args: Prisma.UserPreferencesCreateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>[]
|
||||
}
|
||||
delete: {
|
||||
args: Prisma.UserPreferencesDeleteArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>
|
||||
}
|
||||
update: {
|
||||
args: Prisma.UserPreferencesUpdateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>
|
||||
}
|
||||
deleteMany: {
|
||||
args: Prisma.UserPreferencesDeleteManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateMany: {
|
||||
args: Prisma.UserPreferencesUpdateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateManyAndReturn: {
|
||||
args: Prisma.UserPreferencesUpdateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>[]
|
||||
}
|
||||
upsert: {
|
||||
args: Prisma.UserPreferencesUpsertArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPreferencesPayload>
|
||||
}
|
||||
aggregate: {
|
||||
args: Prisma.UserPreferencesAggregateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.AggregateUserPreferences>
|
||||
}
|
||||
groupBy: {
|
||||
args: Prisma.UserPreferencesGroupByArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.UserPreferencesGroupByOutputType>[]
|
||||
}
|
||||
count: {
|
||||
args: Prisma.UserPreferencesCountArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.UserPreferencesCountAggregateOutputType> | number
|
||||
}
|
||||
}
|
||||
}
|
||||
Event: {
|
||||
payload: Prisma.$EventPayload<ExtArgs>
|
||||
fields: Prisma.EventFieldRefs
|
||||
operations: {
|
||||
findUnique: {
|
||||
args: Prisma.EventFindUniqueArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload> | null
|
||||
}
|
||||
findUniqueOrThrow: {
|
||||
args: Prisma.EventFindUniqueOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>
|
||||
}
|
||||
findFirst: {
|
||||
args: Prisma.EventFindFirstArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload> | null
|
||||
}
|
||||
findFirstOrThrow: {
|
||||
args: Prisma.EventFindFirstOrThrowArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>
|
||||
}
|
||||
findMany: {
|
||||
args: Prisma.EventFindManyArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>[]
|
||||
}
|
||||
create: {
|
||||
args: Prisma.EventCreateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>
|
||||
}
|
||||
createMany: {
|
||||
args: Prisma.EventCreateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
createManyAndReturn: {
|
||||
args: Prisma.EventCreateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>[]
|
||||
}
|
||||
delete: {
|
||||
args: Prisma.EventDeleteArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>
|
||||
}
|
||||
update: {
|
||||
args: Prisma.EventUpdateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>
|
||||
}
|
||||
deleteMany: {
|
||||
args: Prisma.EventDeleteManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateMany: {
|
||||
args: Prisma.EventUpdateManyArgs<ExtArgs>
|
||||
result: BatchPayload
|
||||
}
|
||||
updateManyAndReturn: {
|
||||
args: Prisma.EventUpdateManyAndReturnArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>[]
|
||||
}
|
||||
upsert: {
|
||||
args: Prisma.EventUpsertArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.PayloadToResult<Prisma.$EventPayload>
|
||||
}
|
||||
aggregate: {
|
||||
args: Prisma.EventAggregateArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.AggregateEvent>
|
||||
}
|
||||
groupBy: {
|
||||
args: Prisma.EventGroupByArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.EventGroupByOutputType>[]
|
||||
}
|
||||
count: {
|
||||
args: Prisma.EventCountArgs<ExtArgs>
|
||||
result: runtime.Types.Utils.Optional<Prisma.EventCountAggregateOutputType> | number
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} & {
|
||||
other: {
|
||||
payload: any
|
||||
operations: {
|
||||
$executeRaw: {
|
||||
args: [query: TemplateStringsArray | Sql, ...values: any[]],
|
||||
result: any
|
||||
}
|
||||
$executeRawUnsafe: {
|
||||
args: [query: string, ...values: any[]],
|
||||
result: any
|
||||
}
|
||||
$queryRaw: {
|
||||
args: [query: TemplateStringsArray | Sql, ...values: any[]],
|
||||
result: any
|
||||
}
|
||||
$queryRawUnsafe: {
|
||||
args: [query: string, ...values: any[]],
|
||||
result: any
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enums
|
||||
*/
|
||||
|
||||
export const TransactionIsolationLevel = runtime.makeStrictEnum({
|
||||
Serializable: 'Serializable'
|
||||
} as const)
|
||||
|
||||
export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel]
|
||||
|
||||
|
||||
export const UserScalarFieldEnum = {
|
||||
id: 'id',
|
||||
email: 'email',
|
||||
password: 'password',
|
||||
username: 'username',
|
||||
role: 'role',
|
||||
score: 'score',
|
||||
level: 'level',
|
||||
hp: 'hp',
|
||||
maxHp: 'maxHp',
|
||||
xp: 'xp',
|
||||
maxXp: 'maxXp',
|
||||
avatar: 'avatar',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum]
|
||||
|
||||
|
||||
export const UserPreferencesScalarFieldEnum = {
|
||||
id: 'id',
|
||||
userId: 'userId',
|
||||
homeBackground: 'homeBackground',
|
||||
eventsBackground: 'eventsBackground',
|
||||
leaderboardBackground: 'leaderboardBackground',
|
||||
theme: 'theme',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type UserPreferencesScalarFieldEnum = (typeof UserPreferencesScalarFieldEnum)[keyof typeof UserPreferencesScalarFieldEnum]
|
||||
|
||||
|
||||
export const EventScalarFieldEnum = {
|
||||
id: 'id',
|
||||
date: 'date',
|
||||
name: 'name',
|
||||
description: 'description',
|
||||
type: 'type',
|
||||
status: 'status',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type EventScalarFieldEnum = (typeof EventScalarFieldEnum)[keyof typeof EventScalarFieldEnum]
|
||||
|
||||
|
||||
export const SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
} as const
|
||||
|
||||
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]
|
||||
|
||||
|
||||
export const NullsOrder = {
|
||||
first: 'first',
|
||||
last: 'last'
|
||||
} as const
|
||||
|
||||
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Field references
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'String'
|
||||
*/
|
||||
export type StringFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'String'>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'Role'
|
||||
*/
|
||||
export type EnumRoleFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Role'>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'Int'
|
||||
*/
|
||||
export type IntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Int'>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'DateTime'
|
||||
*/
|
||||
export type DateTimeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'DateTime'>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'EventType'
|
||||
*/
|
||||
export type EnumEventTypeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'EventType'>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'EventStatus'
|
||||
*/
|
||||
export type EnumEventStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'EventStatus'>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reference to a field of type 'Float'
|
||||
*/
|
||||
export type FloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float'>
|
||||
|
||||
|
||||
/**
|
||||
* Batch Payload for updateMany & deleteMany & createMany
|
||||
*/
|
||||
export type BatchPayload = {
|
||||
count: number
|
||||
}
|
||||
|
||||
export const defineExtension = runtime.Extensions.defineExtension as unknown as runtime.Types.Extensions.ExtendsHook<"define", TypeMapCb, runtime.Types.Extensions.DefaultArgs>
|
||||
export type DefaultPrismaClient = PrismaClient
|
||||
export type ErrorFormat = 'pretty' | 'colorless' | 'minimal'
|
||||
export type PrismaClientOptions = ({
|
||||
/**
|
||||
* Instance of a Driver Adapter, e.g., like one provided by `@prisma/adapter-pg`.
|
||||
*/
|
||||
adapter: runtime.SqlDriverAdapterFactory
|
||||
accelerateUrl?: never
|
||||
} | {
|
||||
/**
|
||||
* Prisma Accelerate URL allowing the client to connect through Accelerate instead of a direct database.
|
||||
*/
|
||||
accelerateUrl: string
|
||||
adapter?: never
|
||||
}) & {
|
||||
/**
|
||||
* @default "colorless"
|
||||
*/
|
||||
errorFormat?: ErrorFormat
|
||||
/**
|
||||
* @example
|
||||
* ```
|
||||
* // Shorthand for `emit: 'stdout'`
|
||||
* log: ['query', 'info', 'warn', 'error']
|
||||
*
|
||||
* // Emit as events only
|
||||
* log: [
|
||||
* { emit: 'event', level: 'query' },
|
||||
* { emit: 'event', level: 'info' },
|
||||
* { emit: 'event', level: 'warn' }
|
||||
* { emit: 'event', level: 'error' }
|
||||
* ]
|
||||
*
|
||||
* / Emit as events and log to stdout
|
||||
* og: [
|
||||
* { emit: 'stdout', level: 'query' },
|
||||
* { emit: 'stdout', level: 'info' },
|
||||
* { emit: 'stdout', level: 'warn' }
|
||||
* { emit: 'stdout', level: 'error' }
|
||||
*
|
||||
* ```
|
||||
* Read more in our [docs](https://pris.ly/d/logging).
|
||||
*/
|
||||
log?: (LogLevel | LogDefinition)[]
|
||||
/**
|
||||
* The default values for transactionOptions
|
||||
* maxWait ?= 2000
|
||||
* timeout ?= 5000
|
||||
*/
|
||||
transactionOptions?: {
|
||||
maxWait?: number
|
||||
timeout?: number
|
||||
isolationLevel?: TransactionIsolationLevel
|
||||
}
|
||||
/**
|
||||
* Global configuration for omitting model fields by default.
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* const prisma = new PrismaClient({
|
||||
* omit: {
|
||||
* user: {
|
||||
* password: true
|
||||
* }
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
omit?: GlobalOmitConfig
|
||||
/**
|
||||
* SQL commenter plugins that add metadata to SQL queries as comments.
|
||||
* Comments follow the sqlcommenter format: https://google.github.io/sqlcommenter/
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* const prisma = new PrismaClient({
|
||||
* adapter,
|
||||
* comments: [
|
||||
* traceContext(),
|
||||
* queryInsights(),
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
comments?: runtime.SqlCommenterPlugin[]
|
||||
}
|
||||
export type GlobalOmitConfig = {
|
||||
user?: Prisma.UserOmit
|
||||
userPreferences?: Prisma.UserPreferencesOmit
|
||||
event?: Prisma.EventOmit
|
||||
}
|
||||
|
||||
/* Types for Logging */
|
||||
export type LogLevel = 'info' | 'query' | 'warn' | 'error'
|
||||
export type LogDefinition = {
|
||||
level: LogLevel
|
||||
emit: 'stdout' | 'event'
|
||||
}
|
||||
|
||||
export type CheckIsLogLevel<T> = T extends LogLevel ? T : never;
|
||||
|
||||
export type GetLogType<T> = CheckIsLogLevel<
|
||||
T extends LogDefinition ? T['level'] : T
|
||||
>;
|
||||
|
||||
export type GetEvents<T extends any[]> = T extends Array<LogLevel | LogDefinition>
|
||||
? GetLogType<T[number]>
|
||||
: never;
|
||||
|
||||
export type QueryEvent = {
|
||||
timestamp: Date
|
||||
query: string
|
||||
params: string
|
||||
duration: number
|
||||
target: string
|
||||
}
|
||||
|
||||
export type LogEvent = {
|
||||
timestamp: Date
|
||||
message: string
|
||||
target: string
|
||||
}
|
||||
/* End Types for Logging */
|
||||
|
||||
|
||||
export type PrismaAction =
|
||||
| 'findUnique'
|
||||
| 'findUniqueOrThrow'
|
||||
| 'findMany'
|
||||
| 'findFirst'
|
||||
| 'findFirstOrThrow'
|
||||
| 'create'
|
||||
| 'createMany'
|
||||
| 'createManyAndReturn'
|
||||
| 'update'
|
||||
| 'updateMany'
|
||||
| 'updateManyAndReturn'
|
||||
| 'upsert'
|
||||
| 'delete'
|
||||
| 'deleteMany'
|
||||
| 'executeRaw'
|
||||
| 'queryRaw'
|
||||
| 'aggregate'
|
||||
| 'count'
|
||||
| 'runCommandRaw'
|
||||
| 'findRaw'
|
||||
| 'groupBy'
|
||||
|
||||
/**
|
||||
* `PrismaClient` proxy available in interactive transactions.
|
||||
*/
|
||||
export type TransactionClient = Omit<DefaultPrismaClient, runtime.ITXClientDenyList>
|
||||
|
||||
134
prisma/generated/prisma/internal/prismaNamespaceBrowser.ts
Normal file
134
prisma/generated/prisma/internal/prismaNamespaceBrowser.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* WARNING: This is an internal file that is subject to change!
|
||||
*
|
||||
* 🛑 Under no circumstances should you import this file directly! 🛑
|
||||
*
|
||||
* All exports from this file are wrapped under a `Prisma` namespace object in the browser.ts file.
|
||||
* While this enables partial backward compatibility, it is not part of the stable public API.
|
||||
*
|
||||
* If you are looking for your Models, Enums, and Input Types, please import them from the respective
|
||||
* model files in the `model` directory!
|
||||
*/
|
||||
|
||||
import * as runtime from "@prisma/client/runtime/index-browser"
|
||||
|
||||
export type * from '../models'
|
||||
export type * from './prismaNamespace'
|
||||
|
||||
export const Decimal = runtime.Decimal
|
||||
|
||||
|
||||
export const NullTypes = {
|
||||
DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull),
|
||||
JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull),
|
||||
AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull),
|
||||
}
|
||||
/**
|
||||
* Helper for filtering JSON entries that have `null` on the database (empty on the db)
|
||||
*
|
||||
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
||||
*/
|
||||
export const DbNull = runtime.DbNull
|
||||
|
||||
/**
|
||||
* Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
|
||||
*
|
||||
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
||||
*/
|
||||
export const JsonNull = runtime.JsonNull
|
||||
|
||||
/**
|
||||
* Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
|
||||
*
|
||||
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
|
||||
*/
|
||||
export const AnyNull = runtime.AnyNull
|
||||
|
||||
|
||||
export const ModelName = {
|
||||
User: 'User',
|
||||
UserPreferences: 'UserPreferences',
|
||||
Event: 'Event'
|
||||
} as const
|
||||
|
||||
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
|
||||
|
||||
/*
|
||||
* Enums
|
||||
*/
|
||||
|
||||
export const TransactionIsolationLevel = {
|
||||
Serializable: 'Serializable'
|
||||
} as const
|
||||
|
||||
export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel]
|
||||
|
||||
|
||||
export const UserScalarFieldEnum = {
|
||||
id: 'id',
|
||||
email: 'email',
|
||||
password: 'password',
|
||||
username: 'username',
|
||||
role: 'role',
|
||||
score: 'score',
|
||||
level: 'level',
|
||||
hp: 'hp',
|
||||
maxHp: 'maxHp',
|
||||
xp: 'xp',
|
||||
maxXp: 'maxXp',
|
||||
avatar: 'avatar',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum]
|
||||
|
||||
|
||||
export const UserPreferencesScalarFieldEnum = {
|
||||
id: 'id',
|
||||
userId: 'userId',
|
||||
homeBackground: 'homeBackground',
|
||||
eventsBackground: 'eventsBackground',
|
||||
leaderboardBackground: 'leaderboardBackground',
|
||||
theme: 'theme',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type UserPreferencesScalarFieldEnum = (typeof UserPreferencesScalarFieldEnum)[keyof typeof UserPreferencesScalarFieldEnum]
|
||||
|
||||
|
||||
export const EventScalarFieldEnum = {
|
||||
id: 'id',
|
||||
date: 'date',
|
||||
name: 'name',
|
||||
description: 'description',
|
||||
type: 'type',
|
||||
status: 'status',
|
||||
createdAt: 'createdAt',
|
||||
updatedAt: 'updatedAt'
|
||||
} as const
|
||||
|
||||
export type EventScalarFieldEnum = (typeof EventScalarFieldEnum)[keyof typeof EventScalarFieldEnum]
|
||||
|
||||
|
||||
export const SortOrder = {
|
||||
asc: 'asc',
|
||||
desc: 'desc'
|
||||
} as const
|
||||
|
||||
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]
|
||||
|
||||
|
||||
export const NullsOrder = {
|
||||
first: 'first',
|
||||
last: 'last'
|
||||
} as const
|
||||
|
||||
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]
|
||||
|
||||
14
prisma/generated/prisma/models.ts
Normal file
14
prisma/generated/prisma/models.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
||||
/* eslint-disable */
|
||||
// biome-ignore-all lint: generated file
|
||||
// @ts-nocheck
|
||||
/*
|
||||
* This is a barrel export file for all models and their related types.
|
||||
*
|
||||
* 🟢 You can import this file directly.
|
||||
*/
|
||||
export type * from './models/User'
|
||||
export type * from './models/UserPreferences'
|
||||
export type * from './models/Event'
|
||||
export type * from './commonInputTypes'
|
||||
1234
prisma/generated/prisma/models/Event.ts
Normal file
1234
prisma/generated/prisma/models/Event.ts
Normal file
File diff suppressed because it is too large
Load Diff
1670
prisma/generated/prisma/models/User.ts
Normal file
1670
prisma/generated/prisma/models/User.ts
Normal file
File diff suppressed because it is too large
Load Diff
1384
prisma/generated/prisma/models/UserPreferences.ts
Normal file
1384
prisma/generated/prisma/models/UserPreferences.ts
Normal file
File diff suppressed because it is too large
Load Diff
63
prisma/migrations/20251209055617_init/migration.sql
Normal file
63
prisma/migrations/20251209055617_init/migration.sql
Normal file
@@ -0,0 +1,63 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"email" TEXT NOT NULL,
|
||||
"password" TEXT NOT NULL,
|
||||
"username" TEXT NOT NULL,
|
||||
"role" TEXT NOT NULL DEFAULT 'USER',
|
||||
"score" INTEGER NOT NULL DEFAULT 0,
|
||||
"level" INTEGER NOT NULL DEFAULT 1,
|
||||
"hp" INTEGER NOT NULL DEFAULT 1000,
|
||||
"maxHp" INTEGER NOT NULL DEFAULT 1000,
|
||||
"xp" INTEGER NOT NULL DEFAULT 0,
|
||||
"maxXp" INTEGER NOT NULL DEFAULT 5000,
|
||||
"avatar" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "UserPreferences" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"userId" TEXT NOT NULL,
|
||||
"homeBackground" TEXT,
|
||||
"eventsBackground" TEXT,
|
||||
"leaderboardBackground" TEXT,
|
||||
"theme" TEXT DEFAULT 'default',
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "UserPreferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Event" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"date" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "User_score_idx" ON "User"("score");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "User_email_idx" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "UserPreferences_userId_key" ON "UserPreferences"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Event_status_idx" ON "Event"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Event_date_idx" ON "Event"("date");
|
||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "sqlite"
|
||||
81
prisma/schema.prisma
Normal file
81
prisma/schema.prisma
Normal file
@@ -0,0 +1,81 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "./generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
}
|
||||
|
||||
enum Role {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
enum EventType {
|
||||
SUMMIT
|
||||
LAUNCH
|
||||
FESTIVAL
|
||||
COMPETITION
|
||||
}
|
||||
|
||||
enum EventStatus {
|
||||
UPCOMING
|
||||
LIVE
|
||||
PAST
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
password String
|
||||
username String @unique
|
||||
role Role @default(USER)
|
||||
score Int @default(0)
|
||||
level Int @default(1)
|
||||
hp Int @default(1000)
|
||||
maxHp Int @default(1000)
|
||||
xp Int @default(0)
|
||||
maxXp Int @default(5000)
|
||||
avatar String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
preferences UserPreferences?
|
||||
|
||||
@@index([score])
|
||||
@@index([email])
|
||||
}
|
||||
|
||||
model UserPreferences {
|
||||
id String @id @default(cuid())
|
||||
userId String @unique
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Background images for each page
|
||||
homeBackground String?
|
||||
eventsBackground String?
|
||||
leaderboardBackground String?
|
||||
|
||||
// Other UI preferences can be added here
|
||||
theme String? @default("default")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Event {
|
||||
id String @id @default(cuid())
|
||||
date String
|
||||
name String
|
||||
description String
|
||||
type EventType
|
||||
status EventStatus
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([status])
|
||||
@@index([date])
|
||||
}
|
||||
144
prisma/seed.ts
Normal file
144
prisma/seed.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import {
|
||||
PrismaClient,
|
||||
EventType,
|
||||
EventStatus,
|
||||
} from "@/prisma/generated/prisma/client";
|
||||
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
const adapter = new PrismaBetterSqlite3({
|
||||
url: process.env.DATABASE_URL || "file:./dev.db",
|
||||
});
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
async function main() {
|
||||
// Créer un utilisateur admin
|
||||
const adminPassword = await bcrypt.hash("admin123", 10);
|
||||
const admin = await prisma.user.upsert({
|
||||
where: { email: "admin@got-mc.com" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "admin@got-mc.com",
|
||||
username: "Admin",
|
||||
password: adminPassword,
|
||||
role: "ADMIN",
|
||||
score: 0,
|
||||
level: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// Créer quelques utilisateurs de test
|
||||
const userPassword = await bcrypt.hash("user123", 10);
|
||||
const users = await Promise.all([
|
||||
prisma.user.upsert({
|
||||
where: { email: "user1@got-mc.com" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "user1@got-mc.com",
|
||||
username: "DragonSlayer99",
|
||||
password: userPassword,
|
||||
score: 125000,
|
||||
level: 85,
|
||||
hp: 750,
|
||||
maxHp: 1000,
|
||||
xp: 3250,
|
||||
maxXp: 5000,
|
||||
},
|
||||
}),
|
||||
prisma.user.upsert({
|
||||
where: { email: "user2@got-mc.com" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "user2@got-mc.com",
|
||||
username: "MineMaster",
|
||||
password: userPassword,
|
||||
score: 118500,
|
||||
level: 82,
|
||||
},
|
||||
}),
|
||||
prisma.user.upsert({
|
||||
where: { email: "user3@got-mc.com" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "user3@got-mc.com",
|
||||
username: "CraftKing",
|
||||
password: userPassword,
|
||||
score: 112000,
|
||||
level: 80,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// Créer des événements (vérifier s'ils existent déjà)
|
||||
const eventData = [
|
||||
{
|
||||
date: "18 NOVEMBRE 2023",
|
||||
name: "Sommet de l'Innovation Tech",
|
||||
description:
|
||||
"Rejoignez les leaders de l'industrie et les innovateurs pour une journée de discussions sur les technologies de pointe, les percées de l'IA et des opportunités de networking.",
|
||||
type: EventType.SUMMIT,
|
||||
status: EventStatus.PAST,
|
||||
},
|
||||
{
|
||||
date: "3 DÉCEMBRE 2023",
|
||||
name: "Lancement de la Révolution IA",
|
||||
description:
|
||||
"Assistez au lancement de systèmes d'IA révolutionnaires qui vont remodeler le paysage du gaming. Aperçus exclusifs et opportunités d'accès anticipé.",
|
||||
type: EventType.LAUNCH,
|
||||
status: EventStatus.PAST,
|
||||
},
|
||||
{
|
||||
date: "22 DÉCEMBRE 2023",
|
||||
name: "Festival du Code d'Hiver",
|
||||
description:
|
||||
"Une célébration de l'excellence en programmation avec des hackathons, des défis de codage et des prix. Montrez vos compétences et rivalisez avec les meilleurs développeurs.",
|
||||
type: EventType.FESTIVAL,
|
||||
status: EventStatus.PAST,
|
||||
},
|
||||
{
|
||||
date: "15 JANVIER 2024",
|
||||
name: "Expo Informatique Quantique",
|
||||
description:
|
||||
"Explorez l'avenir de l'informatique quantique dans le gaming. Démonstrations interactives, conférences d'experts et ateliers pratiques pour tous les niveaux.",
|
||||
type: EventType.SUMMIT,
|
||||
status: EventStatus.UPCOMING,
|
||||
},
|
||||
{
|
||||
date: "8 FÉVRIER 2024",
|
||||
name: "Championnat Cyber Arena",
|
||||
description:
|
||||
"L'événement de gaming compétitif ultime. Compétissez pour la gloire, des récompenses exclusives et le titre de Champion Cyber Arena. Inscriptions ouvertes.",
|
||||
type: EventType.COMPETITION,
|
||||
status: EventStatus.UPCOMING,
|
||||
},
|
||||
{
|
||||
date: "12 MARS 2024",
|
||||
name: "Gala Tech du Printemps",
|
||||
description:
|
||||
"Une soirée élégante célébrant les réalisations technologiques. Cérémonie de remise de prix, networking et annonces exclusives des plus grandes entreprises tech.",
|
||||
type: EventType.FESTIVAL,
|
||||
status: EventStatus.UPCOMING,
|
||||
},
|
||||
];
|
||||
|
||||
const events = await Promise.all(
|
||||
eventData.map(async (data) => {
|
||||
const existing = await prisma.event.findFirst({
|
||||
where: { name: data.name },
|
||||
});
|
||||
if (existing) return existing;
|
||||
return prisma.event.create({ data });
|
||||
})
|
||||
);
|
||||
|
||||
console.log("Seed completed:", { admin, users, events });
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
27
types/next-auth.d.ts
vendored
Normal file
27
types/next-auth.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Role } from "@/prisma/generated/prisma/client";
|
||||
import "next-auth";
|
||||
|
||||
declare module "next-auth" {
|
||||
interface User {
|
||||
id: string;
|
||||
username: string;
|
||||
role: Role;
|
||||
}
|
||||
|
||||
interface Session {
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
role: Role;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare module "next-auth/jwt" {
|
||||
interface JWT {
|
||||
id: string;
|
||||
username: string;
|
||||
role: Role;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user