Files
got-gaming/components/houses/HouseCard.tsx

168 lines
5.3 KiB
TypeScript

"use client";
import { useState } from "react";
import { useSession } from "next-auth/react";
import Card from "@/components/ui/Card";
import Button from "@/components/ui/Button";
import Avatar from "@/components/ui/Avatar";
import { requestToJoin } from "@/actions/houses/requests";
import { useTransition } from "react";
import Alert from "@/components/ui/Alert";
interface House {
id: string;
name: string;
description: string | null;
creator: {
id: string;
username: string;
avatar: string | null;
};
memberships?: Array<{
id: string;
role: string;
user: {
id: string;
username: string;
avatar: string | null;
score?: number;
level?: number;
};
}>;
_count?: {
memberships: number;
};
}
interface HouseCardProps {
house: House;
onRequestSent?: () => void;
}
export default function HouseCard({ house, onRequestSent }: HouseCardProps) {
const { data: session } = useSession();
const [isPending, startTransition] = useTransition();
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
const isMember = house.memberships?.some(
(m) => m.user.id === session?.user?.id
);
const memberCount = house._count?.memberships || house.memberships?.length || 0;
const handleRequestToJoin = () => {
if (!session?.user?.id) return;
setError(null);
setSuccess(null);
startTransition(async () => {
const result = await requestToJoin(house.id);
if (result.success) {
setSuccess("Demande envoyée avec succès");
onRequestSent?.();
} else {
setError(result.error || "Erreur lors de l'envoi de la demande");
}
});
};
return (
<Card className="p-4 sm:p-6">
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4 mb-4">
<div className="flex-1 min-w-0">
<h3 className="text-xl font-bold mb-2 break-words" style={{ color: "var(--foreground)" }}>
{house.name}
</h3>
{house.description && (
<p className="text-sm mb-2 break-words" style={{ color: "var(--muted-foreground)" }}>
{house.description}
</p>
)}
<div className="flex flex-wrap items-center gap-2 sm:gap-4 text-xs" style={{ color: "var(--muted-foreground)" }}>
<span>Créée par {house.creator.username}</span>
<span className="hidden sm:inline"></span>
<span>{memberCount} membre{memberCount > 1 ? "s" : ""}</span>
</div>
</div>
</div>
{error && (
<Alert variant="error" className="mb-4">
{error}
</Alert>
)}
{success && (
<Alert variant="success" className="mb-4">
{success}
</Alert>
)}
{session?.user?.id && !isMember && (
<Button
onClick={handleRequestToJoin}
disabled={isPending}
variant="primary"
size="sm"
className="w-full sm:w-auto"
>
{isPending ? "Envoi..." : "Demander à rejoindre"}
</Button>
)}
{isMember && (
<div className="text-xs mb-4" style={{ color: "var(--success)" }}>
Vous êtes membre
</div>
)}
{/* Members List */}
{house.memberships && house.memberships.length > 0 && (
<div className="mt-4 pt-4 border-t" style={{ borderColor: "var(--border)" }}>
<h4 className="text-xs font-bold uppercase tracking-wider mb-3" style={{ color: "var(--muted-foreground)" }}>
Membres ({house.memberships.length})
</h4>
<div className="flex flex-wrap gap-2">
{house.memberships.map((membership) => (
<div
key={membership.id}
className="flex items-center gap-2 p-2 rounded"
style={{ backgroundColor: "var(--card-hover)" }}
title={`${membership.user.username} (${membership.role})${membership.user.score !== undefined ? ` - ${membership.user.score} pts` : ""}`}
>
<Avatar
src={membership.user.avatar}
username={membership.user.username}
size="sm"
className="flex-shrink-0"
borderClassName="border-pixel-gold/30"
/>
<div className="min-w-0">
<div className="flex items-center gap-1">
<span className="text-xs font-semibold truncate" style={{ color: "var(--foreground)" }}>
{membership.user.username}
</span>
{membership.role === "OWNER" && (
<span className="text-[10px] uppercase" style={{ color: "var(--accent)" }}>
👑
</span>
)}
</div>
{membership.user.score !== undefined && membership.user.level !== undefined && (
<div className="text-[10px]" style={{ color: "var(--muted-foreground)" }}>
{membership.user.score} pts Lv.{membership.user.level}
</div>
)}
</div>
</div>
))}
</div>
</div>
)}
</Card>
);
}