Add house leaderboard feature: Integrate house leaderboard functionality in LeaderboardPage and LeaderboardSection components. Update userStatsService to fetch house leaderboard data, and enhance UI to display house rankings, scores, and member details. Update Prisma schema to include house-related models and relationships, and seed database with initial house data.
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled
This commit is contained in:
90
components/houses/HouseForm.tsx
Normal file
90
components/houses/HouseForm.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useTransition } from "react";
|
||||
import Button from "@/components/ui/Button";
|
||||
import Input from "@/components/ui/Input";
|
||||
import Textarea from "@/components/ui/Textarea";
|
||||
import Alert from "@/components/ui/Alert";
|
||||
import { createHouse } from "@/actions/houses/create";
|
||||
import { updateHouse } from "@/actions/houses/update";
|
||||
|
||||
interface HouseFormProps {
|
||||
house?: {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
};
|
||||
onSuccess?: () => void;
|
||||
onCancel?: () => void;
|
||||
}
|
||||
|
||||
export default function HouseForm({
|
||||
house,
|
||||
onSuccess,
|
||||
onCancel,
|
||||
}: HouseFormProps) {
|
||||
const [name, setName] = useState(house?.name || "");
|
||||
const [description, setDescription] = useState(house?.description || "");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError(null);
|
||||
|
||||
startTransition(async () => {
|
||||
const result = house
|
||||
? await updateHouse(house.id, { name, description: description || null })
|
||||
: await createHouse({ name, description: description || null });
|
||||
|
||||
if (result.success) {
|
||||
onSuccess?.();
|
||||
} else {
|
||||
setError(result.error || "Une erreur est survenue");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{error && <Alert variant="error">{error}</Alert>}
|
||||
|
||||
<Input
|
||||
label="Nom de la maison"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
minLength={3}
|
||||
maxLength={50}
|
||||
disabled={isPending}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
label="Description (optionnelle)"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
maxLength={500}
|
||||
disabled={isPending}
|
||||
rows={4}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-2">
|
||||
<Button type="submit" disabled={isPending} variant="primary" className="w-full sm:w-auto">
|
||||
{isPending ? "Enregistrement..." : house ? "Modifier" : "Créer"}
|
||||
</Button>
|
||||
{onCancel && (
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onCancel}
|
||||
disabled={isPending}
|
||||
variant="secondary"
|
||||
className="w-full sm:w-auto"
|
||||
>
|
||||
Annuler
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user