Skip to main content
Glama
lallen30
by lallen30
CalendarScreen.tsx9.1 kB
import React, { useState, useEffect, useMemo } from 'react'; import { View, Text, ScrollView, TouchableOpacity } from 'react-native'; import { Calendar } from 'react-native-calendars'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { styles } from './Styles'; import axiosRequest from '../../../helper/axiosRequest'; import { API } from '../../../helper/config'; import axios from 'axios'; import { colors } from '../../../theme/colors'; interface CalendarEvent { event_id: string; event_title: string; event_content: string; event_date: string; event_to_time: string; event_from_time: string; event_street_address: string; event_apt_suite: string; event_city: string; event_state: string; event_zip: string; event_longitude: string | null; event_latitude: string | null; event_price: string | null; } interface MarkedDates { [date: string]: { marked?: boolean; selected?: boolean; dotColor?: string; }; } const CalendarScreen = ({ navigation }: any) => { const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]); const [events, setEvents] = useState<CalendarEvent[]>([]); const [markedDates, setMarkedDates] = useState<MarkedDates>({}); const fetchEvents = async () => { try { // Try to get token from both possible storage locations let token = await AsyncStorage.getItem('userToken'); if (!token) { const userDataStr = await AsyncStorage.getItem('userData'); if (userDataStr) { const userData = JSON.parse(userDataStr); token = userData?.loginInfo?.token; } } if (!token) { console.error('No token found in either storage location'); return; } console.log('Fetching events with token'); const response = await axiosRequest.get(API.ENDPOINTS.GET_EVENTS, { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, params: { month: new Date(selectedDate).getMonth() + 1, // Adding 1 because getMonth() returns 0-11 year: new Date(selectedDate).getFullYear() } }); console.log('Events API Response:', response); if (response?.data?.status === 'ok' && Array.isArray(response?.data?.listing)) { const eventsData = response.data.listing; console.log('Events found:', eventsData); setEvents(eventsData); // Mark dates that have events const marked: MarkedDates = {}; eventsData.forEach((event: CalendarEvent) => { const eventDate = event.event_date; marked[eventDate] = { marked: true, dotColor: colors.tertiary }; }); // Also mark the selected date const selectedDateKey = new Date(selectedDate).toISOString().split('T')[0]; marked[selectedDateKey] = { ...marked[selectedDateKey], selected: true, selectedColor: colors.primary // Add this to make selected date more visible }; setMarkedDates(marked); } else { console.warn('Unexpected response format:', response); setEvents([]); setMarkedDates({ [selectedDate]: { selected: true, selectedColor: colors.primary } }); } } catch (error) { console.error('Error fetching events:', error); if (axios.isAxiosError(error)) { console.error('Error details:', { status: error.response?.status, statusText: error.response?.statusText, url: error.config?.url, method: error.config?.method, headers: error.config?.headers, params: error.config?.params, response: error.response?.data }); } setEvents([]); setMarkedDates({ [selectedDate]: { selected: true } }); } }; useEffect(() => { fetchEvents(); }, [selectedDate]); // Re-fetch when selected date changes useEffect(() => { console.log('Selected date changed to:', selectedDate); console.log('Current events:', events); console.log('Filtered events:', filteredEvents); }, [selectedDate, events, filteredEvents]); const onDayPress = (day: any) => { console.log('Day pressed - raw data:', day); const newSelectedDate = day.dateString; console.log('Setting new selected date:', newSelectedDate); // Update marked dates to include the new selection const newMarkedDates = { ...markedDates }; // Remove selected state from previous date const previousSelectedDateKey = new Date(selectedDate).toISOString().split('T')[0]; if (markedDates[previousSelectedDateKey]) { newMarkedDates[previousSelectedDateKey] = { ...markedDates[previousSelectedDateKey], selected: false }; // If the date only had selected: true, remove it entirely if (!newMarkedDates[previousSelectedDateKey].marked) { delete newMarkedDates[previousSelectedDateKey]; } } // Add selected state to new date newMarkedDates[newSelectedDate] = { ...markedDates[newSelectedDate], selected: true }; // Update states setMarkedDates(newMarkedDates); setSelectedDate(newSelectedDate); }; // Filter events for selected date const filteredEvents = useMemo(() => { console.log('Filtering events for date:', selectedDate); console.log('Available events:', events); const filtered = events.filter(event => event.event_date === selectedDate); console.log('Filtered events for selected date:', filtered); return filtered; }, [events, selectedDate]); const formatDate = (dateString: string) => { console.log('Formatting date:', dateString); try { const [year, month, day] = dateString.split('-').map(num => parseInt(num, 10)); const date = new Date(year, month - 1, day); // month is 0-based in Date constructor console.log('Constructed date:', date); return date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); } catch (error) { console.error('Error formatting date:', error); return dateString; } }; const formattedSelectedDate = useMemo(() => { return formatDate(selectedDate); }, [selectedDate]); useEffect(() => { console.log('Selected date state updated:', selectedDate); console.log('Formatted date:', formatDate(selectedDate)); }, [selectedDate]); const formatTime = (timeStr: string) => { const [hours, minutes] = timeStr.split(':'); const date = new Date(); date.setHours(parseInt(hours, 10)); date.setMinutes(parseInt(minutes, 10)); return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); }; return ( <View style={styles.container}> <Calendar style={styles.calendar} onDayPress={onDayPress} markedDates={markedDates} theme={{ selectedDayBackgroundColor: colors.secondary, selectedDayTextColor: colors.white, todayTextColor: colors.primary, dotColor: colors.danger, arrowColor: colors.dark, monthTextColor: colors.dark, textDayFontWeight: '300', textMonthFontWeight: 'bold', textDayHeaderFontWeight: '500', textDayColor: colors.tertiary, textDayHeaderColor: colors.secondary }} /> <View style={[styles.sectionHeader, { padding: 20, marginVertical: 15 }]}> <Text style={[styles.sectionTitle, { fontSize: 20, fontWeight: '600' }]}> Events for {formatDate(selectedDate)} </Text> </View> <ScrollView style={styles.eventsContainer}> {filteredEvents.length > 0 ? ( filteredEvents.map((event) => ( <TouchableOpacity key={event.event_id} style={styles.eventCard} onPress={() => navigation.navigate('EventDetails', { event })} > <Text style={styles.eventTitle}>{event.event_title}</Text> <Text style={styles.eventTime}> {formatTime(event.event_from_time)} - {formatTime(event.event_to_time)} </Text> <Text style={styles.eventLocation}> {event.event_street_address} {event.event_apt_suite ? `, ${event.event_apt_suite}` : ''} {event.event_city ? `, ${event.event_city}` : ''} {event.event_state ? `, ${event.event_state}` : ''} {event.event_zip ? ` ${event.event_zip}` : ''} </Text> </TouchableOpacity> )) ) : ( <Text style={styles.noEventsText}>No events on this date</Text> )} </ScrollView> </View> ); }; export default CalendarScreen;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lallen30/mcp-remote-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server