1- "use client ";
1+ import NoticeBoardView from "@/components/Admin/NoticeBoardView ";
22
3- import { useEffect , useState } from "react" ;
4-
5- interface NotificationItem {
6- id ?: string ;
7- announcelogo : string ;
8- heading : string ;
9- info : string ;
10- createdAt ?: string ;
11- clubname ?: string ;
12- }
13-
14- export default function NoticeBoardView ( ) : JSX . Element {
15- const [ notifications , setNotifications ] = useState < NotificationItem [ ] > ( [ ] ) ;
16- const [ selectedImage , setSelectedImage ] = useState < string | null > ( null ) ;
17- const [ loading , setLoading ] = useState ( true ) ;
18- const [ error , setError ] = useState ( "" ) ;
19-
20- useEffect ( ( ) => {
21- const fetchAnnouncements = async ( ) => {
22- try {
23- setLoading ( true ) ;
24- setError ( "" ) ;
25-
26- const response = await fetch (
27- `${ process . env . NEXT_PUBLIC_BACKEND_URL } /api/v1/notification` ,
28- {
29- method : "GET" ,
30- cache : "no-store" ,
31- }
32- ) ;
33-
34- const data = await response . json ( ) ;
35-
36- if ( ! response . ok ) {
37- throw new Error (
38- data . message || "Failed to fetch announcements."
39- ) ;
40- }
41-
42- if ( Array . isArray ( data ) ) {
43- setNotifications ( [ ...data ] . reverse ( ) ) ;
44- } else if ( Array . isArray ( data . data ) ) {
45- setNotifications ( [ ...data . data ] . reverse ( ) ) ;
46- } else {
47- setNotifications ( [ ] ) ;
48- }
49- } catch ( err : any ) {
50- setError (
51- err ?. message || "Something went wrong while loading announcements."
52- ) ;
53- } finally {
54- setLoading ( false ) ;
55- }
56- } ;
57-
58- fetchAnnouncements ( ) ;
59- } , [ ] ) ;
60-
61- if ( loading ) {
62- return (
63- < div className = "min-h-screen bg-slate-50 flex items-center justify-center px-4" >
64- < p className = "text-slate-600 text-lg" > Loading announcements...</ p >
65- </ div >
66- ) ;
67- }
68-
69- if ( error ) {
70- return (
71- < div className = "min-h-screen bg-slate-50 flex items-center justify-center px-4" >
72- < div className = "max-w-md rounded-xl border border-red-200 bg-red-50 p-6 text-center" >
73- < p className = "text-red-600 font-medium" > { error } </ p >
74- </ div >
75- </ div >
76- ) ;
77- }
78-
79- return (
80- < >
81- < div className = "min-h-screen bg-slate-50 px-4 py-10" >
82- < div className = "mx-auto max-w-5xl" >
83- < div className = "mb-10 text-center" >
84- < h1 className = "text-4xl font-bold text-slate-900" >
85- Announcements
86- </ h1 >
87- < p className = "mt-2 text-slate-500" >
88- Stay updated with the latest notices and updates.
89- </ p >
90- </ div >
91-
92- { notifications . length === 0 ? (
93- < div className = "rounded-2xl border border-slate-200 bg-white p-12 text-center shadow-sm" >
94- < p className = "text-lg font-medium text-slate-600" >
95- No announcements available.
96- </ p >
97- </ div >
98- ) : (
99- < div className = "space-y-6" >
100- { notifications . map ( ( item , index ) => (
101- < div
102- key = { item . id || index }
103- className = "rounded-2xl border border-slate-200 bg-white p-6 shadow-sm hover:shadow-md transition"
104- >
105- < div className = "flex flex-col gap-6 md:flex-row md:items-start md:justify-between" >
106- < div className = "flex-1" >
107- { item . clubname && (
108- < p className = "mb-2 text-sm font-semibold uppercase tracking-wide text-blue-700" >
109- { item . clubname }
110- </ p >
111- ) }
112-
113- < h2 className = "text-2xl font-semibold text-slate-900" >
114- { item . heading }
115- </ h2 >
116-
117- < p className = "mt-4 whitespace-pre-line text-slate-700 leading-7" >
118- { item . info }
119- </ p >
120-
121- { item . createdAt && (
122- < p className = "mt-4 text-sm text-slate-400" >
123- { new Date ( item . createdAt ) . toLocaleString ( ) }
124- </ p >
125- ) }
126- </ div >
127-
128- { item . announcelogo && (
129- < div className = "md:w-32 flex-shrink-0" >
130- < img
131- src = { item . announcelogo }
132- alt = "Announcement logo"
133- onClick = { ( ) =>
134- setSelectedImage ( item . announcelogo )
135- }
136- className = "h-24 w-24 rounded-xl border border-slate-200 object-cover cursor-pointer hover:scale-105 transition"
137- />
138- </ div >
139- ) }
140- </ div >
141- </ div >
142- ) ) }
143- </ div >
144- ) }
145- </ div >
146- </ div >
147-
148- { selectedImage && (
149- < div
150- className = "fixed inset-0 z-50 flex items-center justify-center bg-black/80 px-4"
151- onClick = { ( ) => setSelectedImage ( null ) }
152- >
153- < div
154- className = "relative"
155- onClick = { ( e ) => e . stopPropagation ( ) }
156- >
157- < button
158- type = "button"
159- onClick = { ( ) => setSelectedImage ( null ) }
160- className = "absolute -top-12 right-0 text-white text-4xl font-bold"
161- >
162- ×
163- </ button >
164-
165- < img
166- src = { selectedImage }
167- alt = "Announcement preview"
168- className = "max-h-[85vh] max-w-[90vw] rounded-xl shadow-2xl"
169- />
170- </ div >
171- </ div >
172- ) }
173- </ >
174- ) ;
3+ export default function Page ( ) {
4+ return < NoticeBoardView /> ;
1755}
0 commit comments