1- export default function Events ( ) {
2- return < main > Events</ main > ;
3- }
1+ "use client" ;
2+
3+ import { Calendar } from "@/components/calendar" ;
4+ import { EventList } from "@/components/event-list" ;
5+ import PromotionalCard from "@/components/promotional-card" ;
6+ import { useDictionary } from "@/contexts/dictionary-provider" ;
7+ import getEvents from "@/lib/api/getEvents" ;
8+ import { type Event , CardType } from "@/lib/types" ;
9+ import { useEffect , useState } from "react" ;
10+ import { isSameDay } from "@/lib/utils" ;
11+ import { horizontalPadding , verticalPadding } from "@/lib/styling" ;
12+ import AppLink from "@/components/link" ;
13+ import Markdown from "markdown-to-jsx" ;
14+
15+ export default function EventsPage ( ) {
16+ const dict = useDictionary ( ) ;
17+ const [ events , setEvents ] = useState < Event [ ] > ( [ ] ) ;
18+ const [ isLoading , setIsLoading ] = useState ( true ) ;
19+ const [ selectedDate , setSelectedDate ] = useState < Date | null > ( null ) ;
20+
21+ useEffect ( ( ) => {
22+ async function fetchEvents ( ) {
23+ try {
24+ setIsLoading ( true ) ;
25+ const eventsData = await getEvents ( ) ;
26+ setEvents ( eventsData ) ;
27+ } catch ( error ) {
28+ console . error ( "Failed to fetch events:" , error ) ;
29+ } finally {
30+ setIsLoading ( false ) ;
31+ }
32+ }
33+
34+ void fetchEvents ( ) ;
35+ } , [ ] ) ;
36+
37+ const handleDateSelect = ( date : Date | null ) => {
38+ setSelectedDate ( ( prevDate ) =>
39+ prevDate && date && isSameDay ( prevDate , date ) ? null : date ,
40+ ) ;
41+ } ;
42+
43+ const handleClearDate = ( ) => {
44+ setSelectedDate ( null ) ;
45+ } ;
46+
47+ return (
48+ < main
49+ className = { `flex flex-col gap-10 lg:gap-14 ${ horizontalPadding } ${ verticalPadding } ` }
50+ >
51+ < div className = "flex items-center justify-between" >
52+ < h1 className = "font-title text-3xl font-medium" > { dict . events . title } </ h1 >
53+ < div className = "hidden items-center gap-4 lg:flex" >
54+ < AppLink
55+ href = "https://calendario.cesium.di.uminho.pt/"
56+ arrow = "outward"
57+ title = "Calendarium"
58+ />
59+ < AppLink
60+ href = "https://instagram.com/cesiuminho"
61+ arrow = "outward"
62+ title = "Instagram"
63+ />
64+ </ div >
65+ </ div >
66+
67+ < div className = "md:flex md:gap-12" >
68+ < div className = "mb-8 flex w-full flex-col gap-14 md:mb-0 md:w-2/5" >
69+ < Calendar
70+ events = { events }
71+ onDateSelect = { handleDateSelect }
72+ selectedDate = { selectedDate }
73+ className = "your-calendar-class"
74+ />
75+ < div className = "hidden md:block" >
76+ < PromotionalCard mobileOnlyLayout type = { CardType . Membership } />
77+ </ div >
78+ </ div >
79+ < div className = "flex flex-1 flex-col gap-6" >
80+ < EventList
81+ events = { events }
82+ isLoading = { isLoading }
83+ selectedDate = { selectedDate }
84+ onClearDate = { handleClearDate }
85+ />
86+ < div className = "text-sm" >
87+ < h2 className = "mb-4 font-title text-2xl font-medium" >
88+ { dict . events . warningTitle }
89+ </ h2 >
90+ < div className = "text-black/50" >
91+ < Markdown
92+ options = { {
93+ overrides : {
94+ a : {
95+ props : {
96+ className : "font-bold text-primary hover:underline" ,
97+ target : "_blank" ,
98+ rel : "noopener noreferrer" ,
99+ } ,
100+ } ,
101+ } ,
102+ } }
103+ >
104+ { dict . events . warning }
105+ </ Markdown >
106+ </ div >
107+ </ div >
108+ < div className = "md:hidden" >
109+ < PromotionalCard type = { CardType . Membership } />
110+ </ div >
111+ </ div >
112+ </ div >
113+ </ main >
114+ ) ;
115+ }
0 commit comments