import { Button, ButtonSize, Colors, DateTimePicker, Dialog, LoaderScreen, Modal, Picker, PickerModes, Switch, Text, TextField, TextFieldRef, TouchableOpacity, View, } from "react-native-ui-lib"; import {ScrollView} from "react-native-gesture-handler"; import {useSafeAreaInsets} from "react-native-safe-area-context"; import {useEffect, useRef, useState} from "react"; import {AntDesign, Feather, Ionicons} from "@expo/vector-icons"; import {PickerMultiValue} from "react-native-ui-lib/src/components/picker/types"; import {useCreateEvent} from "@/hooks/firebase/useCreateEvent"; import {EventData} from "@/hooks/firebase/types/eventData"; import {Alert, StyleSheet} from "react-native"; import ClockIcon from "@/assets/svgs/ClockIcon"; import LockIcon from "@/assets/svgs/LockIcon"; import MenuIcon from "@/assets/svgs/MenuIcon"; import CameraIcon from "@/assets/svgs/CameraIcon"; import AssigneesDisplay from "@/components/shared/AssigneesDisplay"; import {useAtom} from "jotai"; import {eventForEditAtom, isAllDayAtom, selectedNewEventDateAtom,} from "@/components/pages/calendar/atoms"; import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers"; import DeleteEventDialog from "./DeleteEventDialog"; import {useDeleteEvent} from "@/hooks/firebase/useDeleteEvent"; import AddPersonIcon from "@/assets/svgs/AddPersonIcon"; import {addHours, format, isAfter, isSameDay, startOfMinute} from "date-fns"; import {ProfileType, useAuthContext} from "@/contexts/AuthContext"; import {Calendar} from "react-native-calendars"; import React from "react"; const daysOfWeek = [ {label: "Monday", value: "monday"}, {label: "Tuesday", value: "tuesday"}, {label: "Wednesday", value: "wednesday"}, {label: "Thursday", value: "thursday"}, {label: "Friday", value: "friday"}, {label: "Saturday", value: "saturday"}, {label: "Sunday", value: "sunday"}, ]; export const ManuallyAddEventModal = () => { const insets = useSafeAreaInsets(); const {user, profileData} = useAuthContext(); const [selectedNewEventDate, setSelectedNewEndDate] = useAtom( selectedNewEventDateAtom ); const [editEvent, setEditEvent] = useAtom(eventForEditAtom); const [allDayAtom, setAllDayAtom] = useAtom(isAllDayAtom); const [deleteModalVisible, setDeleteModalVisible] = useState(false); const {mutateAsync: deleteEvent, isPending: isDeleting} = useDeleteEvent(); const {show, close, initialDate} = { show: !!selectedNewEventDate || !!editEvent, close: () => { setDeleteModalVisible(false); setSelectedNewEndDate(undefined); setEditEvent(undefined); setCreator(null); }, initialDate: selectedNewEventDate || editEvent?.start, }; const detailsRef = useRef(null); const [title, setTitle] = useState(editEvent?.title || ""); const [details, setDetails] = useState(editEvent?.notes || ""); const [isAllDay, setIsAllDay] = useState(editEvent?.allDay || false); const [isPrivate, setIsPrivate] = useState( editEvent?.private || false ); const [location, setLocation] = useState(editEvent?.location ?? ""); const [showStartDatePicker, setShowStartDatePicker] = useState(false); const [showEndDatePicker, setShowEndDatePicker] = useState(false); useEffect(() => { if (allDayAtom === true) setIsAllDay(true); }, [allDayAtom]); const [startTime, setStartTime] = useState(() => { const date = initialDate ?? new Date(); if ( date.getMinutes() > 0 || date.getSeconds() > 0 || date.getMilliseconds() > 0 ) { date.setHours(date.getHours() + 1); } date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0); return date; }); const [endTime, setEndTime] = useState(() => { if (editEvent?.end) { return new Date(editEvent.end); } const baseDate = editEvent?.end ?? initialDate ?? new Date(); return addHours(baseDate, 1); }); const [startDate, setStartDate] = useState(initialDate ?? new Date()); const [endDate, setEndDate] = useState( editEvent?.end ?? initialDate ?? new Date() ); const [selectedAttendees, setSelectedAttendees] = useState( editEvent?.attendees ?? [user?.uid] ); const [repeatInterval, setRepeatInterval] = useState([]); const { mutateAsync: createEvent, isPending: isAdding, isError, } = useCreateEvent(); const {data: members} = useGetFamilyMembers(true); const titleRef = useRef(null); const [creator, setCreator] = useState(""); useEffect(() => { if (editEvent) { let creatorMember = members?.find( (member) => member?.uid === editEvent.creatorId ); const fullName = `${creatorMember?.firstName ?? ""}`; setCreator(fullName); } }, [members]); const isLoading = isDeleting || isAdding; useEffect(() => { setTitle(editEvent?.title || ""); setDetails(editEvent?.notes || ""); setIsAllDay(editEvent?.allDay || false); setIsPrivate(editEvent?.private || false); setStartTime(() => { const date = initialDate ? new Date(initialDate) : new Date(); date.setSeconds(0, 0); return date; }); setEndTime(() => { if (editEvent?.end) { return startOfMinute(new Date(editEvent.end)); } const baseDate = editEvent?.end ?? initialDate ?? new Date(); return addHours(baseDate, 1); }); setStartDate(initialDate ?? new Date()); setEndDate(editEvent?.end ?? initialDate ?? new Date()); setSelectedAttendees(editEvent?.attendees ?? [user?.uid]); setLocation(editEvent?.location ?? ""); setRepeatInterval([]); }, [editEvent, selectedNewEventDate]); useEffect(() => { if (show && !editEvent) { setTimeout(() => { titleRef?.current?.focus(); }, 500); } }, [selectedNewEventDate]); if (!show) return null; const showDeleteEventModal = () => { setDeleteModalVisible(true); }; const handleDeleteEvent = async () => { await deleteEvent({eventId: `${editEvent?.id}`}); close(); }; const hideDeleteEventModal = () => { setDeleteModalVisible(false); }; const combineDateAndTime = (date: Date, time: Date): Date => { const combined = new Date(date); combined.setHours(time.getHours()); combined.setMinutes(time.getMinutes()); combined.setSeconds(0); combined.setMilliseconds(0); return combined; }; const handleSave = async () => { let finalStartDate: Date; let finalEndDate: Date; if (isAllDay) { finalStartDate = new Date(startDate.setHours(0, 0, 0, 0)); finalEndDate = new Date(startDate.setHours(0, 0, 0, 0)); } else { finalStartDate = combineDateAndTime(startDate, startTime); finalEndDate = combineDateAndTime(endDate, endTime); } const eventData: Partial = { title: title, startDate: finalStartDate, endDate: finalEndDate, allDay: isAllDay, attendees: selectedAttendees, notes: details, location: location, private: isPrivate }; if (editEvent?.id) eventData.id = editEvent?.id; if (validateEvent()) { await createEvent(eventData); setEditEvent(undefined); close(); } else { return; } }; const validateEvent = () => { if (!title) { Alert.alert("Alert", "Title field cannot be empty"); return false; } if (!selectedAttendees || selectedAttendees?.length === 0) { Alert.alert('Alert', 'Cannot have an event without any attendees'); return false; } return true; }; if (isLoading && !isError) { return ( ); } const renderCalendarPicker = ( isStart: boolean, visible: boolean, onDismiss: () => void ) => { const currentDate = isStart ? startDate : endDate; const setDate = isStart ? setStartDate : setEndDate; return ( Select Date Done { const newDate = new Date(day.timestamp); newDate.setHours(currentDate.getHours()); newDate.setMinutes(currentDate.getMinutes()); setDate(newDate); if(isStart) { if (startTime.getHours() > endTime.getHours() && (isSameDay(newDate, endDate) || isAfter(newDate, endDate))) { const newEndDate = new Date(newDate); newEndDate.setDate(newEndDate.getDate() + 1); newEndDate.setHours(endDate.getHours()); newEndDate.setMinutes(endDate.getMinutes()); setEndDate(newEndDate); } } else { if (endTime.getHours() < startTime.getHours() && (isSameDay(newDate, startDate) || isAfter(startDate, newDate))) { const newStartDate = new Date(newDate); newStartDate.setDate(newStartDate.getDate() - 1); newStartDate.setHours(startDate.getHours()); newStartDate.setMinutes(startDate.getMinutes()); setStartDate(newStartDate); } } onDismiss(); }} theme={{ selectedDayBackgroundColor: '#ea156c', selectedDayTextColor: '#ffffff', todayTextColor: '#ea156c', arrowColor: '#ea156c', }} enableSwipeMonths={true} /> ); }; const renderDateSection = () => ( All day setIsAllDay(value)} /> setShowStartDatePicker(true)}> {format(startDate, 'MMM d, yyyy')} {!isAllDay && ( { if (endDate.getDate() === startDate.getDate() && time.getHours() >= endTime.getHours() && time.getMinutes() >= endTime.getHours()) { const newEndDate = new Date(endDate); setStartTime(time); newEndDate.setDate(newEndDate.getDate() + 1); setEndDate(newEndDate); } else setStartTime(time); }} minuteInterval={5} mode="time" timeFormat={profileData?.userType === ProfileType.PARENT ? "hh:mm A" : "HH:mm A"} style={[styles.timePicker]} /> )} {!isAllDay && ( setShowEndDatePicker(true)}> {format(endDate, 'MMM d, yyyy')} { setEndTime(time); if ( endDate.getDate() === startDate.getDate() && time.getHours() <= startTime.getHours() && time.getMinutes() <= startTime.getMinutes() ) { const newEndDate = new Date(endDate); newEndDate.setDate(newEndDate.getDate() + 1); setEndDate(newEndDate); } }} minuteInterval={5} mode="time" timeFormat={profileData?.userType === ProfileType.PARENT ? "hh:mm A" : "HH:mm A"} style={[styles.timePicker]} /> )} {renderCalendarPicker(true, showStartDatePicker, () => setShowStartDatePicker(false))} {renderCalendarPicker(false, showEndDatePicker, () => setShowEndDatePicker(false))} ) return ( <> {/*{editEvent ? (*/} {/* <>*/} {/* */} {/* */} {/* */} {/* */} {/* */} {/* */} {/* }*/} {/* onPress={close}*/} {/* />*/} {/* */} {/* }*/} {/* onPress={handleSave}*/} {/* />*/} {/* }*/} {/* onPress={() => {*/} {/* showDeleteEventModal();*/} {/* }}*/} {/* />*/} {/* */} {/* */} {/* */} {/*) : (*/} Cancel Save {/*)}*/} { setTitle(text); }} placeholderTextColor="#2d2d30" style={{fontFamily: "Manrope_500Medium", fontSize: 22}} paddingT-15 paddingL-30 returnKeyType="next" /> {renderDateSection()} Attendees setSelectedAttendees((value as string[]) ?? []) } style={{marginLeft: "auto"}} mode={PickerModes.MULTI} renderInput={() => (