diff --git a/app/announcement/page.tsx b/app/announcement/page.tsx new file mode 100644 index 00000000..67d70e1c --- /dev/null +++ b/app/announcement/page.tsx @@ -0,0 +1,27 @@ +import { getServerSession } from "next-auth/next"; +import { authOptions } from "@/app/api/auth/[...nextauth]/route"; +import { redirect } from "next/navigation"; +import { AnnouncementsPage } from "@/components/announcement/announcements-page"; + +export const metadata = { + title: "Announcements", +}; + +export default async function AnnouncementPage() { + const session = await getServerSession(authOptions); + + if (!session) { + redirect("/signin"); + } + + // Get user role(s) + const userRole = session.user.role || []; + + return ( +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/app/types/announcement.ts b/app/types/announcement.ts new file mode 100644 index 00000000..cdb10e5e --- /dev/null +++ b/app/types/announcement.ts @@ -0,0 +1,10 @@ +export interface Announcement { + id: string; + title: string; + content: string; + createdAt: string; + updatedAt: string; + author: string; + authorId: string; + targetRoles: string[]; +} \ No newline at end of file diff --git a/components/announcement/announcement-form.tsx b/components/announcement/announcement-form.tsx new file mode 100644 index 00000000..82bde590 --- /dev/null +++ b/components/announcement/announcement-form.tsx @@ -0,0 +1,218 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle +} from "@/components/ui/card"; +import { CheckIcon, Loader2 } from "lucide-react"; +import { Badge } from "@/components/ui/badge"; +import { Announcement } from "@/app/types/announcement"; + +// Form schema +const formSchema = z.object({ + title: z.string().min(5, { message: "Title must be at least 5 characters" }), + content: z.string().min(10, { message: "Content must be at least 10 characters" }), + targetRoles: z.array(z.string()).min(1, { message: "Select at least one target role" }), +}); + +interface AnnouncementFormProps { + userRole: string[]; +} + +export function AnnouncementForm({ userRole }: AnnouncementFormProps) { + const [selectedRoles, setSelectedRoles] = useState([]); + const [isSubmitting, setIsSubmitting] = useState(false); + const [isSuccess, setIsSuccess] = useState(false); + + // Initialize form + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + title: "", + content: "", + targetRoles: [], + }, + }); + + // Available roles for selection + const availableRoles = [ + { id: "all", name: "All Users" }, + { id: "admin", name: "Administrators" }, + { id: "entrepreneurship", name: "Entrepreneurship" }, + { id: "communication", name: "Communication" }, + { id: "expression", name: "Expression" }, + { id: "coding", name: "Coding" }, + { id: "dataintelligence", name: "Data Intelligence" }, + { id: "mediation", name: "Mediation" }, + ]; + + // Handle role selection + const handleRoleToggle = (roleId: string) => { + if (roleId === "all") { + // If "all" is selected, clear other selections + setSelectedRoles(["all"]); + form.setValue("targetRoles", ["all"]); + } else { + // Remove "all" if it was previously selected + const newSelection = selectedRoles.filter(id => id !== "all"); + + // Toggle the selected role + if (newSelection.includes(roleId)) { + const updatedSelection = newSelection.filter(id => id !== roleId); + setSelectedRoles(updatedSelection); + form.setValue("targetRoles", updatedSelection); + } else { + const updatedSelection = [...newSelection, roleId]; + setSelectedRoles(updatedSelection); + form.setValue("targetRoles", updatedSelection); + } + } + }; + + // Form submission + const onSubmit = async (data: z.infer) => { + setIsSubmitting(true); + + try { + // In a real implementation, this would be an API call + console.log("Announcement data:", data); + + // Simulate API delay + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Reset form and show success message + form.reset(); + setSelectedRoles([]); + setIsSuccess(true); + + // Hide success message after a delay + setTimeout(() => setIsSuccess(false), 3000); + } catch (error) { + console.error("Error submitting announcement:", error); + } finally { + setIsSubmitting(false); + } + }; + + return ( + + + Create New Announcement + + Create an announcement to be displayed to specific user roles + + + +
+ + ( + + Title + + + + + + )} + /> + + ( + + Content + +