Résumé de partie : détail des manches + icônes de catégories
Build and Publish Docker Image / build-and-push-image (push) Successful in 59s
Build and Publish Docker Image / build-and-push-image (push) Successful in 59s
- GameOver : nouvelle section "Détail des manches" (tableau manches × joueurs avec ligne Total) pour les parties multi-manches ; indicateurs Cabo/Kamikaze - ScoringCategory : champs icon (lucide) + color pour un visuel par catégorie - Harmonies : icônes + couleurs de terrain (arbres, montagnes, champs, bâtiments, rivière, animaux, esprits) affichées dans PlayGame et GameOver Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
import { GameConfig, ScoringCategory } from "../../types";
|
||||
|
||||
const BASE_CATEGORIES: ScoringCategory[] = [
|
||||
{ id: "arbres", label: "Arbres" },
|
||||
{ id: "montagnes", label: "Montagnes" },
|
||||
{ id: "champs", label: "Champs" },
|
||||
{ id: "batiments", label: "Bâtiments" },
|
||||
{ id: "eau", label: "Rivière" },
|
||||
{ id: "animaux", label: "Animaux" },
|
||||
{ id: "arbres", label: "Arbres", icon: "TreePine", color: "#16a34a" },
|
||||
{ id: "montagnes", label: "Montagnes", icon: "Mountain", color: "#64748b" },
|
||||
{ id: "champs", label: "Champs", icon: "Wheat", color: "#d97706" },
|
||||
{ id: "batiments", label: "Bâtiments", icon: "Building2", color: "#dc2626" },
|
||||
{ id: "eau", label: "Rivière", icon: "Waves", color: "#0ea5e9" },
|
||||
{ id: "animaux", label: "Animaux", icon: "Rabbit", color: "#a16207" },
|
||||
];
|
||||
|
||||
const NATURE_SPIRIT_CATEGORY: ScoringCategory = {
|
||||
id: "esprits_nature",
|
||||
label: "Esprits de la nature",
|
||||
icon: "Sparkles",
|
||||
color: "#8b5cf6",
|
||||
};
|
||||
|
||||
export const harmonieConfig: GameConfig = {
|
||||
|
||||
+94
-1
@@ -137,7 +137,7 @@ export default function GameOver() {
|
||||
const topWinner = totals.find((t) => t.isWinner)?.player;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen bg-background pb-24">
|
||||
<div className="flex flex-col min-h-screen bg-background pb-40">
|
||||
{/* 💥 Animation de Célébration (disparaît après qq secondes) */}
|
||||
{showCelebration && topWinner && (
|
||||
<CelebrationOverlay winner={topWinner} gameId={gameConfig?.id || ""} />
|
||||
@@ -242,11 +242,21 @@ export default function GameOver() {
|
||||
{categories.map((cat) => {
|
||||
const val = t.details?.[cat.id];
|
||||
if (!val || val === "0") return null;
|
||||
const CatIcon = cat.icon
|
||||
? (Icons as any)[cat.icon]
|
||||
: null;
|
||||
return (
|
||||
<div
|
||||
key={cat.id}
|
||||
className="flex flex-col items-center bg-secondary/30 rounded-lg p-1.5"
|
||||
>
|
||||
{CatIcon && (
|
||||
<CatIcon
|
||||
className="w-4 h-4 mb-0.5"
|
||||
style={{ color: cat.color ?? "currentColor" }}
|
||||
strokeWidth={2.2}
|
||||
/>
|
||||
)}
|
||||
<span className="text-[10px] text-muted-foreground truncate w-full text-center">
|
||||
{cat.label}
|
||||
</span>
|
||||
@@ -262,6 +272,89 @@ export default function GameOver() {
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Round-by-round detail (multi-round games) */}
|
||||
{session.rounds.length > 1 && (
|
||||
<section className="pt-2">
|
||||
<h2 className="text-xl font-semibold px-2 mb-2">
|
||||
Détail des manches
|
||||
</h2>
|
||||
<Card className="overflow-hidden">
|
||||
<CardContent className="p-0 overflow-x-auto">
|
||||
<table className="w-full text-sm border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-border/60">
|
||||
<th className="text-left font-black text-muted-foreground px-3 py-2.5 sticky left-0 bg-card z-10">
|
||||
Manche
|
||||
</th>
|
||||
{session.players.map((p) => (
|
||||
<th
|
||||
key={p.id}
|
||||
className="px-3 py-2.5 text-right font-bold whitespace-nowrap"
|
||||
>
|
||||
{p.name}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{session.rounds.map((round) => (
|
||||
<tr
|
||||
key={round.id}
|
||||
className="border-b border-border/30 last:border-0"
|
||||
>
|
||||
<td className="px-3 py-2 font-bold text-muted-foreground sticky left-0 bg-card z-10">
|
||||
#{round.roundNumber}
|
||||
</td>
|
||||
{session.players.map((p) => {
|
||||
const s = round.scores.find(
|
||||
(sc) => sc.playerId === p.id,
|
||||
);
|
||||
return (
|
||||
<td
|
||||
key={p.id}
|
||||
className="px-3 py-2 text-right tabular-nums"
|
||||
>
|
||||
{s ? s.score : "—"}
|
||||
{s?.caboCall === "success" && (
|
||||
<span className="ml-1 text-[10px] text-green-600 font-bold">
|
||||
✓
|
||||
</span>
|
||||
)}
|
||||
{s?.caboCall === "fail" && (
|
||||
<span className="ml-1 text-[10px] text-destructive font-bold">
|
||||
✗
|
||||
</span>
|
||||
)}
|
||||
{s?.kamikaze && (
|
||||
<span className="ml-1 text-[10px] text-amber-600 font-bold">
|
||||
K
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
<tr className="bg-secondary/50 font-black">
|
||||
<td className="px-3 py-2.5 sticky left-0 bg-secondary/50 z-10">
|
||||
Total
|
||||
</td>
|
||||
{session.players.map((p) => (
|
||||
<td
|
||||
key={p.id}
|
||||
className="px-3 py-2.5 text-right tabular-nums text-primary"
|
||||
>
|
||||
{calculateTotalScore(p.id)}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="fixed bottom-0 left-0 right-0 p-4 bg-background/95 backdrop-blur-md border-t flex flex-wrap gap-3 justify-center max-w-md mx-auto">
|
||||
|
||||
+19
-1
@@ -322,13 +322,31 @@ export default function PlayGame() {
|
||||
{/* Current Round Input Section */}
|
||||
<section className="relative">
|
||||
<div className="flex items-center justify-between px-2 mb-4">
|
||||
<h2 className="text-2xl font-black tracking-tighter drop-shadow-sm">
|
||||
<div className="flex items-center gap-2.5 min-w-0">
|
||||
{categories &&
|
||||
(() => {
|
||||
const cat = categories[currentCategoryIndex];
|
||||
const CatIcon = cat.icon ? (Icons as any)[cat.icon] : null;
|
||||
return CatIcon ? (
|
||||
<span
|
||||
className="w-11 h-11 rounded-2xl grid place-items-center shrink-0 shadow-sm"
|
||||
style={{
|
||||
backgroundColor: `${cat.color ?? "#14b8a6"}22`,
|
||||
color: cat.color ?? "#14b8a6",
|
||||
}}
|
||||
>
|
||||
<CatIcon className="w-6 h-6" strokeWidth={2.2} />
|
||||
</span>
|
||||
) : null;
|
||||
})()}
|
||||
<h2 className="text-2xl font-black tracking-tighter drop-shadow-sm truncate">
|
||||
{categories
|
||||
? categories[currentCategoryIndex].label
|
||||
: isSingleRound
|
||||
? "Saisie des scores"
|
||||
: "À vos marques !"}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{categories && currentCategoryIndex > 0 && (
|
||||
<Button
|
||||
|
||||
@@ -4,6 +4,8 @@ export type ScoreType =
|
||||
export interface ScoringCategory {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: string; // nom d'icône lucide (ex: "TreePine") — visuel de la catégorie
|
||||
color?: string; // teinte d'accent hex pour l'icône
|
||||
}
|
||||
|
||||
export interface GameConfig {
|
||||
|
||||
Reference in New Issue
Block a user