164 lines
5.9 KiB
TypeScript
164 lines
5.9 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import Header from "@/components/Header";
|
|
import { signOut } from "next-auth/react";
|
|
|
|
export default function YogaDashboard({ user, messages, unreadCount }: any) {
|
|
const router = useRouter();
|
|
const profile = user?.yoga;
|
|
const attendances = profile?.attendances || [];
|
|
const remaining = profile?.sessionsRemaining ?? 0;
|
|
|
|
const pricePerSession = 9;
|
|
const sessionsDone = attendances.length;
|
|
const totalAttendedCost = sessionsDone * pricePerSession;
|
|
|
|
return (
|
|
<main className="min-h-screen pb-16">
|
|
<Header />
|
|
<div className="mx-auto max-w-3xl px-4 py-6">
|
|
<div className="mb-6 flex items-start justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-extrabold">
|
|
🧘 Salut, {user.name.split(" ")[0]} !
|
|
</h1>
|
|
<p className="mt-1 text-sm text-white/60">
|
|
Ton espace Yog4Fight
|
|
</p>
|
|
</div>
|
|
<button
|
|
onClick={() => signOut({ callbackUrl: "/" })}
|
|
className="rounded-xl border border-white/10 bg-white/5 p-2 text-sm text-white/60"
|
|
title="Déconnexion"
|
|
>
|
|
🚪
|
|
</button>
|
|
</div>
|
|
|
|
{/* Compteur de séances */}
|
|
<section className="mb-6">
|
|
<div className="card text-center">
|
|
<p className="text-sm text-white/60">Séances restantes</p>
|
|
<div className="my-2 flex items-center justify-center gap-1 text-5xl font-extrabold text-emerald-300">
|
|
{remaining}
|
|
<span className="text-xl">
|
|
séance{remaining > 1 ? "s" : ""}
|
|
</span>
|
|
</div>
|
|
<p className="text-sm text-white/50">
|
|
{sessionsDone} séance{sessionsDone > 1 ? "s" : ""} suivie
|
|
{sessionsDone > 1 ? "s" : ""}
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Coût */}
|
|
<section className="mb-6">
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div className="card text-center">
|
|
<p className="text-xs text-white/50">Prix par séance</p>
|
|
<p className="mt-1 text-xl font-bold text-emerald-300">
|
|
{pricePerSession} €
|
|
</p>
|
|
</div>
|
|
<div className="card text-center">
|
|
<p className="text-xs text-white/50">Coût si assidu</p>
|
|
<p className="mt-1 text-xl font-bold text-emerald-300">
|
|
Tarif dégressif
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<p className="mt-2 text-center text-xs text-white/50">
|
|
Demande à Juanito le tarif dégressif qui s'applique à
|
|
l'assiduité 💪
|
|
</p>
|
|
</section>
|
|
|
|
{/* Messages de Juanito */}
|
|
<section className="mb-6">
|
|
<div className="mb-3 flex items-center justify-between">
|
|
<h2 className="text-lg font-bold">
|
|
💬 Messages de Juanito{" "}
|
|
{unreadCount > 0 && (
|
|
<span className="ml-1 rounded-full bg-emerald-600 px-2 py-0.5 text-xs font-bold text-white">
|
|
{unreadCount} nouveau(x)
|
|
</span>
|
|
)}
|
|
</h2>
|
|
</div>
|
|
<div className="space-y-3">
|
|
{messages.length === 0 && (
|
|
<p className="card text-sm text-white/50">
|
|
Aucun message pour le moment.
|
|
</p>
|
|
)}
|
|
{messages.map((msg: any) => (
|
|
<div
|
|
key={msg.id}
|
|
className={`card ${!msg.isRead ? "border-emerald-500/40 bg-emerald-500/5" : ""}`}
|
|
onClick={() => {
|
|
if (!msg.isRead) {
|
|
fetch("/api/messages", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ messageId: msg.id }),
|
|
}).then(() => router.refresh());
|
|
}
|
|
}}
|
|
>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div>
|
|
<h3 className="font-semibold">{msg.title}</h3>
|
|
<p className="mt-1 whitespace-pre-line text-sm text-white/75">
|
|
{msg.content}
|
|
</p>
|
|
<p className="mt-2 text-xs text-white/40">
|
|
{new Date(msg.createdAt).toLocaleDateString("fr-FR")}
|
|
</p>
|
|
</div>
|
|
{!msg.isRead && (
|
|
<span className="mt-1 h-3 w-3 shrink-0 rounded-full bg-emerald-500" />
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Historique séances */}
|
|
<section className="card">
|
|
<h3 className="mb-3 font-bold">📋 Mes séances suivies</h3>
|
|
{attendances.length === 0 && (
|
|
<p className="text-sm text-white/50">
|
|
Aucune séance enregistrée pour l'instant.
|
|
</p>
|
|
)}
|
|
<div className="max-h-64 space-y-2 overflow-y-auto">
|
|
{attendances.map((a: any) => (
|
|
<div
|
|
key={a.id}
|
|
className="flex items-center justify-between rounded-xl bg-white/5 px-3 py-2 text-sm"
|
|
>
|
|
<span className="text-white/70">
|
|
{new Date(a.date).toLocaleDateString("fr-FR", {
|
|
weekday: "long",
|
|
day: "numeric",
|
|
month: "long",
|
|
year: "numeric",
|
|
})}
|
|
</span>
|
|
{a.pricePaid !== null && (
|
|
<span className="tabular-nums text-emerald-300 text-xs">
|
|
{a.pricePaid} €
|
|
</span>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
);
|
|
} |