108 lines
3.5 KiB
TypeScript
108 lines
3.5 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue
|
|
} from "@/components/ui/select";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Announcement } from "@/app/types/announcement";
|
|
|
|
export function AnnouncementsDropdown() {
|
|
const [announcements, setAnnouncements] = useState<Announcement[]>([]);
|
|
const [selectedAnnouncement, setSelectedAnnouncement] = useState<Announcement | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
// Fetch announcements from the API
|
|
const fetchAnnouncements = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const response = await fetch('/api/announcements');
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Failed to fetch announcements');
|
|
}
|
|
|
|
const data = await response.json();
|
|
setAnnouncements(data);
|
|
|
|
if (data.length > 0) {
|
|
setSelectedAnnouncement(data[0]);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching announcements:', err);
|
|
setError('Failed to load announcements');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchAnnouncements();
|
|
}, []);
|
|
|
|
const handleAnnouncementChange = (announcementId: string) => {
|
|
const announcement = announcements.find(a => a.id === announcementId);
|
|
if (announcement) {
|
|
setSelectedAnnouncement(announcement);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col space-y-4">
|
|
{loading ? (
|
|
<div className="flex items-center justify-center h-40">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900"></div>
|
|
</div>
|
|
) : error ? (
|
|
<div className="text-center py-10 text-red-500">
|
|
{error}
|
|
</div>
|
|
) : announcements.length === 0 ? (
|
|
<div className="text-center py-10 text-gray-500">
|
|
No announcements available
|
|
</div>
|
|
) : (
|
|
<>
|
|
<div className="w-full max-w-md">
|
|
<Select
|
|
onValueChange={handleAnnouncementChange}
|
|
defaultValue={selectedAnnouncement?.id}
|
|
>
|
|
<SelectTrigger className="w-full bg-white text-gray-800 border-gray-300">
|
|
<SelectValue placeholder="Select an announcement" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{announcements.map(announcement => (
|
|
<SelectItem key={announcement.id} value={announcement.id}>
|
|
{announcement.title}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{selectedAnnouncement && (
|
|
<Card className="w-full bg-white">
|
|
<CardHeader className="bg-white text-gray-800">
|
|
<CardTitle>{selectedAnnouncement.title}</CardTitle>
|
|
<div className="text-sm text-gray-500">
|
|
Posted by {selectedAnnouncement.author.email} on {new Date(selectedAnnouncement.createdAt).toLocaleDateString()}
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="prose max-h-[300px] overflow-y-auto pr-2">
|
|
{selectedAnnouncement.content}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|