"use client"; import { useState, useCallback, useEffect } from "react"; import { Plus, Pin, Trash2, Edit2, X, ChevronDown, ChevronUp } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent } from "@/components/ui/card"; import { fetchAnnouncements, createAnnouncement, updateAnnouncement, deleteAnnouncement, getUserRole, type Announcement, } from "@/lib/supabase/noticeboard-actions"; import PageSkeleton from "./PageSkeleton"; function formatDate(dateStr: string): string { return new Date(dateStr).toLocaleDateString("en-AU", { day: "numeric", month: "short", year: "numeric", }); } function getInitials(name: string): string { return name .split(" ") .map((n) => n[0]) .join("") .toUpperCase() .slice(0, 2); } export default function NoticeboardPage() { const [announcements, setAnnouncements] = useState([]); const [loading, setLoading] = useState(true); const [role, setRole] = useState("employee"); const [showForm, setShowForm] = useState(false); const [editingId, setEditingId] = useState(null); const [expandedIds, setExpandedIds] = useState>(new Set()); const [selectedAnnouncement, setSelectedAnnouncement] = useState(null); const [formTitle, setFormTitle] = useState(""); const [formBody, setFormBody] = useState(""); const [formPinned, setFormPinned] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; Promise.all([fetchAnnouncements(), getUserRole()]) .then(([anns, r]) => { if (!cancelled) { console.log("[Noticeboard] Role from server:", r); setAnnouncements(anns); setRole(r); } }) .catch((err) => { console.error("[Noticeboard] Failed to load:", err); if (!cancelled) { setAnnouncements([]); setError(`Failed to load noticeboard: ${err.message}`); } }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, []); const isAuthor = role === "owner" || role === "admin" || role === "hr_manager"; const handleSubmit = async () => { setError(null); if (!formTitle.trim() || !formBody.trim()) { setError("Title and body are required"); return; } setSaving(true); try { if (editingId) { const result = await updateAnnouncement(editingId, formTitle, formBody, formPinned); if (!result.success) { setError(result.error || "Failed to update"); return; } setAnnouncements((prev) => prev .map((a) => a.id === editingId ? { ...a, title: formTitle, body: formBody, is_pinned: formPinned } : a ) .sort((a, b) => (b.is_pinned ? 1 : 0) - (a.is_pinned ? 1 : 0) || new Date(b.created_at).getTime() - new Date(a.created_at).getTime()) ); } else { const result = await createAnnouncement(formTitle, formBody, formPinned); if (!result.success) { setError(result.error || "Failed to create"); return; } } // Refresh const anns = await fetchAnnouncements(); setAnnouncements(anns); resetForm(); } catch (e: any) { setError(e.message || "An unexpected error occurred"); } finally { setSaving(false); } }; const handleDelete = async (id: string) => { const result = await deleteAnnouncement(id); if (result.success) setAnnouncements((prev) => prev.filter((a) => a.id !== id)); }; const handleEdit = (a: Announcement) => { setEditingId(a.id); setFormTitle(a.title); setFormBody(a.body); setFormPinned(a.is_pinned); setShowForm(true); }; const resetForm = () => { setShowForm(false); setEditingId(null); setFormTitle(""); setFormBody(""); setFormPinned(false); setError(null); }; const toggleExpanded = (id: string) => { setExpandedIds((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); }; if (loading) return ; return (
{/* Header */}

Noticeboard

Company announcements and updates

{isAuthor && ( )}
{/* Post Form */} {showForm && (

{editingId ? "Edit announcement" : "New announcement"}

{error && (
{error}
)} setFormTitle(e.target.value)} placeholder="Title" className="w-full border border-gray-200 rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-[#1D9E75]/20 focus:border-[#1D9E75]" />