Default Component - Copy this React, Tailwind Component to your project
"use client"; import { useEffect, useState } from "react"; import { supabase } from "../lib/supabase"; import AddDeadline from "../components/AddDeadline"; import Link from "next/link"; import { Card, CardContent } from "@/components/ui/card"; import { Clock, Calendar, Trash2, ArrowLeft, AlertCircle } from "lucide react"; export default function Dashboard() { const [deadlines, setDeadlines] = useState([]); useEffect(() => { const fetchDeadlines = async () => { const { data: { user } } = await supabase.auth.getUser(); if (!user) return; const { data, error } = await supabase .from("deadlines") .select("*") .eq("user_id", user.id) .order("due_date", { ascending: true }); if (error) console.error(error); else setDeadlines(data); }; fetchDeadlines(); const subscription = supabase .channel("realtime deadlines") .on("postgres_changes", { event: "INSERT", schema: "public", table: "deadlines" }, (payload) => { setDeadlines((prev) => [...prev, payload.new]); }) .on("postgres_changes", { event: "DELETE", schema: "public", table: "deadlines" }, (payload) => { setDeadlines((prev) => prev.filter((dl) => dl.id !== payload.old.id)); }) .subscribe(); return () => supabase.removeChannel(subscription); }, []); const deleteDeadline = async (id) => { const { error } = await supabase.from("deadlines").delete().eq("id", id); if (error) { console.error("Lỗi khi xóa:", error.message); } else { setDeadlines((prev) => prev.filter((dl) => dl.id !== id)); } }; const isOverdue = (date) => { return new Date(date) < new Date(); }; const formatDate = (date) => { return new Date(date).toLocaleDateString('vi VN', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2 digit', minute: '2 digit' }); }; const getTimeRemaining = (dueDate) => { const now = new Date(); const due = new Date(dueDate); const diff = due now; if (diff < 0) return 'Đã quá hạn'; const days = Math.floor(diff / (1000 * 60 * 60 * 24)); const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); if (days > 0) return `${days} ngày ${hours} giờ`; return `${hours} giờ`; }; return ( <div className="min h screen bg gray 50 p 6"> <div className="max w 4xl mx auto"> <div className="flex justify between items center mb 8"> <h1 className="text 3xl font bold text gray 800 flex items center gap 2"> <Calendar className="h 8 w 8 text blue 500" /> Quản lý Deadline </h1> <Link href="/" className="flex items center gap 2 text gray 600 hover:text gray 800 transition colors" > <ArrowLeft className="h 5 w 5" /> Quay lại </Link> </div> <div className="grid gap 6 md:grid cols [1fr,2fr]"> <div> <AddDeadline onAdd={(newDeadline) => setDeadlines((prev) => [...prev, newDeadline])} /> </div> <Card className="bg white shadow lg"> <CardContent className="p 0"> {deadlines.length === 0 ? ( <div className="p 6 text center text gray 500 flex flex col items center gap 2"> <Calendar className="h 12 w 12 text gray 400" /> <p>Chưa có deadline nào. Hãy thêm deadline mới!</p> </div> ) : ( <ul className="divide y divide gray 100"> {deadlines.map((dl) => ( <li key={dl.id} className={`p 4 transition colors ${ isOverdue(dl.due_date) ? 'bg red 50' : 'hover:bg gray 50' }`} > <div className="flex justify between items start gap 4"> <div className="flex 1"> <h3 className="font semibold text gray 900 mb 1"> {dl.title} </h3> <div className="flex items center gap 4 text sm text gray 500"> <span className="flex items center gap 1"> <Clock className="h 4 w 4" /> {formatDate(dl.due_date)} </span> {isOverdue(dl.due_date) ? ( <span className="flex items center gap 1 text red 500"> <AlertCircle className="h 4 w 4" /> Đã quá hạn </span> ) : ( <span className="text green 600"> Còn {getTimeRemaining(dl.due_date)} </span> )} </div> </div> <button onClick={() => deleteDeadline(dl.id)} className="p 2 text gray 400 hover:text red 500 rounded full hover:bg red 50 transition colors" title="Xóa deadline" > <Trash2 className="h 5 w 5" /> </button> </div> </li> ))} </ul> )} </CardContent> </Card> </div> </div> </div> ); } làm phần UI của tôi tốt hơn
