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
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
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 type { Metadata } from "next";
|
||||||
import { Orbitron, Rajdhani } from "next/font/google";
|
import { Orbitron, Rajdhani } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
import SessionProvider from "@/components/SessionProvider";
|
||||||
|
|
||||||
const orbitron = Orbitron({
|
const orbitron = Orbitron({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
@@ -26,8 +27,9 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="fr" className={`${orbitron.variable} ${rajdhani.variable}`}>
|
<html lang="fr" className={`${orbitron.variable} ${rajdhani.variable}`}>
|
||||||
<body className="antialiased">{children}</body>
|
<body className="antialiased">
|
||||||
|
<SessionProvider>{children}</SessionProvider>
|
||||||
|
</body>
|
||||||
</html>
|
</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";
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface Event {
|
interface Event {
|
||||||
id: number;
|
id: string;
|
||||||
date: string;
|
date: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
type: "summit" | "launch" | "festival" | "competition";
|
type: "SUMMIT" | "LAUNCH" | "FESTIVAL" | "COMPETITION";
|
||||||
status: "upcoming" | "live" | "past";
|
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"]) => {
|
const getEventTypeColor = (type: Event["type"]) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "summit":
|
case "SUMMIT":
|
||||||
return "from-blue-600 to-cyan-500";
|
return "from-blue-600 to-cyan-500";
|
||||||
case "launch":
|
case "LAUNCH":
|
||||||
return "from-purple-600 to-pink-500";
|
return "from-purple-600 to-pink-500";
|
||||||
case "festival":
|
case "FESTIVAL":
|
||||||
return "from-pixel-gold to-orange-500";
|
return "from-pixel-gold to-orange-500";
|
||||||
case "competition":
|
case "COMPETITION":
|
||||||
return "from-red-600 to-orange-500";
|
return "from-red-600 to-orange-500";
|
||||||
default:
|
default:
|
||||||
return "from-gray-600 to-gray-500";
|
return "from-gray-600 to-gray-500";
|
||||||
@@ -83,13 +28,13 @@ const getEventTypeColor = (type: Event["type"]) => {
|
|||||||
|
|
||||||
const getEventTypeLabel = (type: Event["type"]) => {
|
const getEventTypeLabel = (type: Event["type"]) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "summit":
|
case "SUMMIT":
|
||||||
return "Sommet";
|
return "Sommet";
|
||||||
case "launch":
|
case "LAUNCH":
|
||||||
return "Lancement";
|
return "Lancement";
|
||||||
case "festival":
|
case "FESTIVAL":
|
||||||
return "Festival";
|
return "Festival";
|
||||||
case "competition":
|
case "COMPETITION":
|
||||||
return "Compétition";
|
return "Compétition";
|
||||||
default:
|
default:
|
||||||
return type;
|
return type;
|
||||||
@@ -98,19 +43,19 @@ const getEventTypeLabel = (type: Event["type"]) => {
|
|||||||
|
|
||||||
const getStatusBadge = (status: Event["status"]) => {
|
const getStatusBadge = (status: Event["status"]) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "upcoming":
|
case "UPCOMING":
|
||||||
return (
|
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">
|
<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
|
À venir
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
case "live":
|
case "LIVE":
|
||||||
return (
|
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">
|
<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
|
En direct
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
case "past":
|
case "PAST":
|
||||||
return (
|
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">
|
<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é
|
Passé
|
||||||
@@ -120,6 +65,29 @@ const getStatusBadge = (status: Event["status"]) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function EventsPageSection() {
|
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 (
|
return (
|
||||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||||
{/* Background Image */}
|
{/* Background Image */}
|
||||||
@@ -198,17 +166,17 @@ export default function EventsPageSection() {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Action Button */}
|
{/* 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">
|
<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
|
S'inscrire maintenant
|
||||||
</button>
|
</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">
|
<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
|
Rejoindre en direct
|
||||||
</button>
|
</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">
|
<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é
|
Événement terminé
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,26 +1,44 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface Event {
|
interface Event {
|
||||||
|
id: string;
|
||||||
date: string;
|
date: string;
|
||||||
name: 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() {
|
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 (
|
return (
|
||||||
<section className="w-full bg-gray-950 border-t border-pixel-gold/30 py-16">
|
<section className="w-full bg-gray-950 border-t border-pixel-gold/30 py-16">
|
||||||
<div className="max-w-7xl mx-auto px-8">
|
<div className="max-w-7xl mx-auto px-8">
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface LeaderboardEntry {
|
interface LeaderboardEntry {
|
||||||
rank: number;
|
rank: number;
|
||||||
username: string;
|
username: string;
|
||||||
score: number;
|
score: number;
|
||||||
level: number;
|
level: number;
|
||||||
|
avatar?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format number with consistent locale to avoid hydration mismatch
|
// Format number with consistent locale to avoid hydration mismatch
|
||||||
@@ -12,20 +15,32 @@ const formatScore = (score: number): string => {
|
|||||||
return score.toLocaleString("en-US");
|
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() {
|
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 (
|
return (
|
||||||
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
|
<section className="w-full bg-black py-16 px-6 border-t-2 border-pixel-dark-purple">
|
||||||
<div className="max-w-4xl mx-auto">
|
<div className="max-w-4xl mx-auto">
|
||||||
@@ -44,7 +59,7 @@ export default function Leaderboard() {
|
|||||||
|
|
||||||
{/* Entries */}
|
{/* Entries */}
|
||||||
<div className="divide-y divide-pixel-gold/10">
|
<div className="divide-y divide-pixel-gold/10">
|
||||||
{mockLeaderboard.map((entry) => (
|
{leaderboard.map((entry) => (
|
||||||
<div
|
<div
|
||||||
key={entry.rank}
|
key={entry.rank}
|
||||||
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface LeaderboardEntry {
|
interface LeaderboardEntry {
|
||||||
rank: number;
|
rank: number;
|
||||||
username: string;
|
username: string;
|
||||||
score: number;
|
score: number;
|
||||||
level: number;
|
level: number;
|
||||||
avatar?: string;
|
avatar?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format number with consistent locale to avoid hydration mismatch
|
// Format number with consistent locale to avoid hydration mismatch
|
||||||
@@ -13,25 +15,30 @@ const formatScore = (score: number): string => {
|
|||||||
return score.toLocaleString("en-US");
|
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() {
|
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 (
|
return (
|
||||||
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
<section className="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden pt-24 pb-16">
|
||||||
{/* Background Image */}
|
{/* Background Image */}
|
||||||
@@ -78,7 +85,7 @@ export default function LeaderboardSection() {
|
|||||||
|
|
||||||
{/* Entries */}
|
{/* Entries */}
|
||||||
<div className="divide-y divide-pixel-gold/10">
|
<div className="divide-y divide-pixel-gold/10">
|
||||||
{mockLeaderboard.map((entry) => (
|
{leaderboard.map((entry) => (
|
||||||
<div
|
<div
|
||||||
key={entry.rank}
|
key={entry.rank}
|
||||||
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
className={`grid grid-cols-12 gap-4 p-4 hover:bg-gray-900/50 transition ${
|
||||||
@@ -106,11 +113,21 @@ export default function LeaderboardSection() {
|
|||||||
|
|
||||||
{/* Player */}
|
{/* Player */}
|
||||||
<div className="col-span-6 flex items-center gap-3">
|
<div className="col-span-6 flex items-center gap-3">
|
||||||
|
{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">
|
<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">
|
<span className="text-pixel-gold text-xs font-bold">
|
||||||
{entry.username.charAt(0).toUpperCase()}
|
{entry.username.charAt(0).toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<span
|
<span
|
||||||
className={`font-bold ${
|
className={`font-bold ${
|
||||||
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
entry.rank <= 3 ? "text-pixel-gold" : "text-white"
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useSession, signOut } from "next-auth/react";
|
||||||
import PlayerStats from "./PlayerStats";
|
import PlayerStats from "./PlayerStats";
|
||||||
|
|
||||||
export default function Navigation() {
|
export default function Navigation() {
|
||||||
|
const { data: session } = useSession();
|
||||||
|
|
||||||
return (
|
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">
|
<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">
|
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||||
@@ -39,11 +42,44 @@ export default function Navigation() {
|
|||||||
>
|
>
|
||||||
LEADERBOARD
|
LEADERBOARD
|
||||||
</Link>
|
</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>
|
</div>
|
||||||
|
|
||||||
{/* Player Stats - Right */}
|
{/* Right Side */}
|
||||||
<div>
|
<div className="flex items-center gap-4">
|
||||||
|
{session ? (
|
||||||
|
<>
|
||||||
<PlayerStats />
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -1,31 +1,68 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
interface PlayerStatsProps {
|
|
||||||
username?: string;
|
|
||||||
avatar?: string;
|
|
||||||
hp?: number;
|
|
||||||
maxHp?: number;
|
|
||||||
xp?: number;
|
|
||||||
maxXp?: number;
|
|
||||||
level?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format number with consistent locale to avoid hydration mismatch
|
// Format number with consistent locale to avoid hydration mismatch
|
||||||
const formatNumber = (num: number): string => {
|
const formatNumber = (num: number): string => {
|
||||||
return num.toLocaleString("en-US");
|
return num.toLocaleString("en-US");
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function PlayerStats({
|
export default function PlayerStats() {
|
||||||
username = "DragonSlayer99",
|
const { data: session } = useSession();
|
||||||
avatar = "/got-2.jpg",
|
const [userData, setUserData] = useState({
|
||||||
hp = 750,
|
username: "Guest",
|
||||||
maxHp = 1000,
|
avatar: null as string | null,
|
||||||
xp = 3250,
|
hp: 1000,
|
||||||
maxXp = 5000,
|
maxHp: 1000,
|
||||||
level = 42,
|
xp: 0,
|
||||||
}: PlayerStatsProps) {
|
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 [hpPercentage, setHpPercentage] = useState(0);
|
||||||
const [xpPercentage, setXpPercentage] = useState(0);
|
const [xpPercentage, setXpPercentage] = useState(0);
|
||||||
|
|
||||||
@@ -56,12 +93,18 @@ export default function PlayerStats({
|
|||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{/* Avatar */}
|
{/* Avatar */}
|
||||||
<div className="w-10 h-10 rounded-full border border-pixel-gold/20 overflow-hidden bg-gray-900">
|
<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
|
<img
|
||||||
src={avatar}
|
src={avatar}
|
||||||
alt={username}
|
alt={username}
|
||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<span className="text-pixel-gold text-xs font-bold">
|
||||||
|
{username.charAt(0).toUpperCase()}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats */}
|
{/* 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",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"db:seed": "tsx prisma/seed.ts"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "tsx prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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": "15.5.7",
|
||||||
|
"next-auth": "5.0.0-beta.30",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0"
|
"react-dom": "^19.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/bcryptjs": "^3.0.0",
|
||||||
|
"@types/better-sqlite3": "^7.6.13",
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@types/react": "^19.0.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^19.0.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"postcss": "^8.4.40",
|
"postcss": "^8.4.40",
|
||||||
|
"prisma": "^7.1.0",
|
||||||
"tailwindcss": "^3.4.7",
|
"tailwindcss": "^3.4.7",
|
||||||
|
"tsx": "^4.21.0",
|
||||||
"typescript": "^5.6.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