frontend/app/components/home/colle-card.tsx
Nathan Lamy 85e2552db8
All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m39s
feat: add colle details page
2025-07-29 23:25:10 +02:00

145 lines
4.8 KiB
TypeScript

import type React from "react";
import type { Colle } from "~/lib/api";
import { Link, useNavigate } from "react-router";
import {
Card,
CardContent,
CardHeader,
CardFooter,
} from "~/components/ui/card";
import { User, UserCheck, Paperclip, Star, MapPinHouse } from "lucide-react";
import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button";
import { formatDate, formatGrade, formatTime } from "~/lib/utils";
// TODO: Preferences for subject colors
const getSubjectColor = (_: string) => {
// Mock placeholder function
return "bg-blue-100 text-blue-800"; // Default color
};
const getSubjectEmoji = (_: string) => {
// Mock placeholder function
return "📚"; // Default emoji
};
type ColleCardProps = {
colle: Colle;
onToggleFavorite: (id: number, favorite: boolean) => void;
beforeClick: () => void;
isFavorite: boolean;
};
export default function ColleCard({
colle,
onToggleFavorite,
beforeClick,
isFavorite,
}: ColleCardProps) {
const navigate = useNavigate();
// TODO: Remove this if scroll restoration is not needed (test first)
const handleCardClick = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
beforeClick();
setTimeout(() => navigate(`/colles/${colle.id}`), 100);
};
// TODO: Favorites
const handleToggleFavorite = (e: React.MouseEvent) => {
e.stopPropagation(); // Prevent card click
e.preventDefault();
const newValue = !isFavorite;
onToggleFavorite(colle.id, newValue);
};
const subjectColor = getSubjectColor(colle.subject.name);
const subjectEmoji = getSubjectEmoji(colle.subject.name);
return (
<Link to={`/colles/${colle.id}`} onClick={handleCardClick}>
<Card
id={`colle-${colle.id}`}
className="h-full cursor-pointer hover:shadow-md transition-shadow border-primary"
>
<CardHeader className="pb-0 pt-3 px-4 flex flex-row items-center justify-between">
<div>
<div className="font-medium">{formatDate(colle.date)}</div>
<div className="font-normal text-sm text-muted-foreground">
{formatTime(colle.date)}
</div>
</div>
{colle.grade && (
<div className="flex items-center gap-2 h-full mb-3">
<Button
variant="ghost"
size="icon"
className={`h-8 w-8 ${
isFavorite ? "text-yellow-500" : "text-muted-foreground"
}`}
onClick={handleToggleFavorite}
>
<Star
className={`h-5 w-5 ${isFavorite ? "fill-yellow-500" : ""}`}
/>
<span className="sr-only">Ajouter aux favoris</span>
</Button>
<div
className={`px-2 py-1 rounded-md text-sm font-medium ${subjectColor}`}
>
{formatGrade(colle.grade)}/20
</div>
</div>
)}
</CardHeader>
<CardContent className="pb-0 pt-0 px-4" onClick={handleCardClick}>
<div className="flex items-center justify-between">
<div className="space-y-1">
<div className="flex items-center gap-2">
<User className="h-4 w-4 text-muted-foreground" />
<span className="font-medium">{colle.student.fullName}</span>
</div>
<div className="flex items-center gap-2">
<UserCheck className="h-4 w-4 text-muted-foreground" />
<span>{colle.examiner.name}</span>
</div>
{colle.room && (
<div className="flex items-center gap-2">
<MapPinHouse className="h-4 w-4 text-muted-foreground" />
<span>{colle.room.name}</span>
</div>
)}
</div>
</div>
</CardContent>
<CardFooter className="pt-1 pb-3 px-4 flex flex-col items-start">
<div className="w-full flex justify-between items-center">
<div className="flex items-center gap-1">
<Badge className={subjectColor}>
{colle.subject.name + " " + subjectEmoji}
</Badge>
{isFavorite && (
<Badge variant="secondary">
<Star className="h-3 w-3 fill-yellow-500 text-yellow-500 mr-1" />
Favori
</Badge>
)}
</div>
{/* TODO: Attachments */}
{/* {colle.attachmentsCount > 0 && (
<div className="flex items-center gap-1 text-muted-foreground">
<Paperclip className="h-3.5 w-3.5" />
<span className="text-xs">{colle.attachmentsCount}</span>
</div>
)} */}
</div>
</CardFooter>
</Card>
</Link>
);
}