This commit is contained in:
Milan Paunovic
2024-12-10 20:05:15 +01:00
parent 233427bf38
commit 35608e350f
2 changed files with 792 additions and 740 deletions

View File

@ -10,6 +10,7 @@ import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import {useSetAtom} from "jotai";
import {selectedNewEventDateAtom} from "@/components/pages/calendar/atoms";
import PlusIcon from "@/assets/svgs/PlusIcon";
import {addMinutes, roundToNearestMinutes} from "date-fns";
export const AddEventDialog = () => {
const [show, setShow] = useState(false);
@ -20,7 +21,8 @@ export const AddEventDialog = () => {
const handleOpenManualInputModal = () => {
setShow(false);
setTimeout(() => {
setSelectedNewEndDate(new Date());
const roundedDate = roundToNearestMinutes(new Date(), {nearestTo: 5});
setSelectedNewEndDate(roundedDate);
}, 500);
};
@ -50,7 +52,7 @@ export const AddEventDialog = () => {
onPress={() => setShow(true)}
>
<View row centerV centerH>
<PlusIcon />
<PlusIcon/>
<Text white style={{fontSize: 16, fontFamily: 'Manrope_600SemiBold', marginLeft: 5}}>
New
</Text>

View File

@ -2,7 +2,7 @@ import {
Button,
ButtonSize,
Colors,
DateTimePicker,
DateTimePicker, Dialog,
LoaderScreen,
Modal,
Picker,
@ -14,47 +14,48 @@ import {
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 {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 DropModalIcon from "@/assets/svgs/DropModalIcon";
import { Alert, StyleSheet } from "react-native";
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 {useAtom} from "jotai";
import {
eventForEditAtom,
selectedNewEventDateAtom,
isAllDayAtom,
} from "@/components/pages/calendar/atoms";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
import BinIcon from "@/assets/svgs/BinIcon";
import DeleteEventDialog from "./DeleteEventDialog";
import { useDeleteEvent } from "@/hooks/firebase/useDeleteEvent";
import {useDeleteEvent} from "@/hooks/firebase/useDeleteEvent";
import AddPersonIcon from "@/assets/svgs/AddPersonIcon";
import { addHours, startOfHour, startOfMinute } from "date-fns";
import { useAuthContext } from "@/contexts/AuthContext";
import {addHours, format, startOfHour, startOfMinute} from "date-fns";
import {useAuthContext} from "@/contexts/AuthContext";
import {Calendar} from "react-native-calendars";
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" },
{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 } = useAuthContext();
const {user} = useAuthContext();
const [selectedNewEventDate, setSelectedNewEndDate] = useAtom(
selectedNewEventDateAtom
@ -62,9 +63,9 @@ export const ManuallyAddEventModal = () => {
const [editEvent, setEditEvent] = useAtom(eventForEditAtom);
const [allDayAtom, setAllDayAtom] = useAtom(isAllDayAtom);
const [deleteModalVisible, setDeleteModalVisible] = useState<boolean>(false);
const { mutateAsync: deleteEvent, isLoading: isDeleting } = useDeleteEvent();
const {mutateAsync: deleteEvent, isLoading: isDeleting} = useDeleteEvent();
const { show, close, initialDate } = {
const {show, close, initialDate} = {
show: !!selectedNewEventDate || !!editEvent,
close: () => {
setDeleteModalVisible(false);
@ -84,6 +85,8 @@ export const ManuallyAddEventModal = () => {
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);
@ -126,7 +129,7 @@ export const ManuallyAddEventModal = () => {
isLoading: isAdding,
isError,
} = useCreateEvent();
const { data: members } = useGetFamilyMembers(true);
const {data: members} = useGetFamilyMembers(true);
const titleRef = useRef<TextFieldRef>(null);
const [creator, setCreator] = useState("");
@ -193,7 +196,7 @@ export const ManuallyAddEventModal = () => {
};
const handleDeleteEvent = async () => {
await deleteEvent({ eventId: `${editEvent?.id}` });
await deleteEvent({eventId: `${editEvent?.id}`});
close();
};
@ -305,7 +308,163 @@ export const ManuallyAddEventModal = () => {
);
}
const renderCalendarPicker = (
isStart: boolean,
visible: boolean,
onDismiss: () => void
) => {
const currentDate = isStart ? startDate : endDate;
const setDate = isStart ? setStartDate : setEndDate;
return (
<Dialog
visible={visible}
onDismiss={onDismiss}
panDirection={"down"}
width="100%"
bottom
containerStyle={{
backgroundColor: Colors.white,
borderTopLeftRadius: 12,
borderTopRightRadius: 12,
paddingBottom: insets.bottom,
}}
>
<View padding-20>
<View row spread marginB-20>
<Text text70 style={{fontFamily: "Manrope_600SemiBold"}}>
Select Date
</Text>
<TouchableOpacity onPress={onDismiss}>
<Text style={{color: Colors.$textPrimary}}>Done</Text>
</TouchableOpacity>
</View>
<Calendar
firstDay={1}
current={format(currentDate, 'yyyy-MM-dd')}
minDate={isStart ? undefined : format(startDate, 'yyyy-MM-dd')}
markedDates={{
[format(currentDate, 'yyyy-MM-dd')]: {
selected: true,
selectedColor: '#ea156c'
}
}}
onDayPress={(day) => {
const newDate = new Date(day.timestamp);
newDate.setHours(currentDate.getHours());
newDate.setMinutes(currentDate.getMinutes());
setDate(newDate);
onDismiss();
}}
theme={{
selectedDayBackgroundColor: '#ea156c',
selectedDayTextColor: '#ffffff',
todayTextColor: '#ea156c',
arrowColor: '#ea156c',
}}
enableSwipeMonths={true}
/>
</View>
</Dialog>
);
};
const renderDateSection = () => (
<View marginL-30 centerV>
<View row spread marginB-10 centerV>
<View row>
<AntDesign name="clockcircleo" size={24} color="#919191"/>
<Text
style={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
}}
marginL-10
>
All day
</Text>
</View>
<View right marginR-30>
<Switch
onColor={"#ea156c"}
offColor={"#e1e1e2"}
marginL-10
value={isAllDay}
onValueChange={(value) => setIsAllDay(value)}
/>
</View>
</View>
<TouchableOpacity
onPress={() => setShowStartDatePicker(true)}
style={styles.dateButton}
>
<View row centerV spread paddingR-30>
<View row centerV>
<Feather name="calendar" size={25} color="#919191"/>
<Text marginL-8 style={styles.dateText}>
{format(startDate, 'MMM d, yyyy')}
</Text>
</View>
{!isAllDay && (
<DateTimePicker
value={startTime}
onChange={(time) => {
if (time <= endTime) {
setStartTime(time);
}
}}
minuteInterval={5}
mode="time"
timeFormat="HH:mm"
style={styles.timePicker}
/>
)}
</View>
</TouchableOpacity>
{!isAllDay && (
<TouchableOpacity
onPress={() => setShowEndDatePicker(true)}
style={styles.dateButton}
>
<View row centerV spread paddingR-30>
<View row centerV>
<Feather name="calendar" size={25} color="#919191"/>
<Text marginL-8 style={styles.dateText}>
{format(endDate, 'MMM d, yyyy')}
</Text>
</View>
<DateTimePicker
value={endTime}
onChange={(time) => {
setEndTime(time);
if (
endDate.getDate() === startDate.getDate() &&
time.getHours() < startTime.getHours()
) {
const newEndDate = new Date(endDate);
newEndDate.setDate(newEndDate.getDate() + 1);
setEndDate(newEndDate);
}
}}
minuteInterval={5}
mode="time"
timeFormat="HH:mm"
style={styles.timePicker}
/>
</View>
</TouchableOpacity>
)}
{renderCalendarPicker(true, showStartDatePicker, () => setShowStartDatePicker(false))}
{renderCalendarPicker(false, showEndDatePicker, () => setShowEndDatePicker(false))}
</View>)
return (
<>
<Modal
visible={show}
animationType="slide"
@ -375,7 +534,7 @@ export const ManuallyAddEventModal = () => {
</Text>
</TouchableOpacity>
<View row center>
<DropModalIcon onPress={close} />
<DropModalIcon onPress={close}/>
</View>
<View flexS row gap-10>
<TouchableOpacity onPress={handleSave}>
@ -394,14 +553,14 @@ export const ManuallyAddEventModal = () => {
<Button
style={styles.topBtn}
marginL-5
iconSource={() => <BinIcon />}
iconSource={() => <BinIcon/>}
onPress={showDeleteEventModal}
/>
)}
</View>
</View>
{/*)}*/}
<ScrollView style={{ minHeight: "85%" }}>
<ScrollView style={{minHeight: "85%"}}>
<TextField
placeholder="Add event title"
ref={titleRef}
@ -410,148 +569,38 @@ export const ManuallyAddEventModal = () => {
setTitle(text);
}}
placeholderTextColor="#2d2d30"
style={{ fontFamily: "Manrope_500Medium", fontSize: 22 }}
style={{fontFamily: "Manrope_500Medium", fontSize: 22}}
paddingT-15
paddingL-30
returnKeyType="next"
/>
<View style={styles.divider} marginT-8 />
<View marginL-30 centerV>
<View row spread marginB-10 centerV>
<View row>
<AntDesign name="clockcircleo" size={24} color="#919191" />
<Text
style={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
}}
marginL-10
>
All day
</Text>
</View>
<View right marginR-30>
<Switch
onColor={"#ea156c"}
offColor={"#e1e1e2"}
marginL-10
value={isAllDay}
onValueChange={(value) => setIsAllDay(value)}
/>
</View>
</View>
<View row marginB-10 spread>
<View row centerV>
<Feather name="calendar" size={25} color="#919191" />
<DateTimePicker
value={startDate}
onChange={(date) => {
setStartDate(date);
}}
//maximumDate={endDate}
style={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
}}
marginL-8
/>
</View>
<DateTimePicker
value={startTime}
onChange={(time) => {
if (time <= endTime) {
setStartTime(time);
}
}}
minuteInterval={5}
dateTimeFormatter={(date, mode) =>
date.toLocaleTimeString("en-us", {
hour: "numeric",
minute: "numeric",
})
}
mode="time"
style={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
}}
marginR-30
/>
</View>
<View style={styles.divider} marginT-8/>
{renderDateSection()}
{!isAllDay && (
<View row marginB-10 spread>
<View row centerV>
<Feather name="calendar" size={25} color="#919191" />
<DateTimePicker
value={endDate}
minimumDate={startDate}
text70
marginL-8
onChange={(date) => {
setEndDate(date);
}}
style={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
}}
/>
</View>
<DateTimePicker
value={endTime}
onChange={(time) => {
setEndTime(time);
if (
endDate.getDate() === startDate.getDate() &&
time.getHours() < startTime.getHours()
) {
const newEndDate = new Date(endDate);
newEndDate.setDate(newEndDate.getDate() + 1);
setEndDate(newEndDate);
}
}}
minuteInterval={5}
dateTimeFormatter={(date, mode) =>
date.toLocaleTimeString("en-us", {
hour: "numeric",
minute: "numeric",
})
}
mode="time"
style={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
}}
marginR-30
/>
</View>
)}
</View>
<View style={styles.divider} />
<View style={styles.divider}/>
<View marginH-30 marginB-10 row centerV>
<Ionicons name="person-circle-outline" size={28} color="#919191" />
<Ionicons name="person-circle-outline" size={28} color="#919191"/>
<Text
style={{ fontFamily: "Manrope_600SemiBold", fontSize: 16 }}
style={{fontFamily: "Manrope_600SemiBold", fontSize: 16}}
marginL-10
>
Attendees
</Text>
<View flex-1 />
<View flex-1/>
<Picker
value={selectedAttendees}
onChange={(value) =>
setSelectedAttendees((value as string[]) ?? [])
}
style={{ marginLeft: "auto" }}
style={{marginLeft: "auto"}}
mode={PickerModes.MULTI}
renderInput={() => (
<Button
size={ButtonSize.small}
paddingH-8
iconSource={() => (
<Ionicons name="add-outline" size={20} color="#ea156c" />
<Ionicons name="add-outline" size={20} color="#ea156c"/>
)}
style={{
marginLeft: "auto",
@ -586,10 +635,10 @@ export const ManuallyAddEventModal = () => {
/>
</View>
<View style={styles.divider} />
<View style={styles.divider}/>
<View marginH-30 marginB-0 row spread centerV>
<View row centerV>
<ClockIcon />
<ClockIcon/>
<Text
style={{
fontFamily: "Manrope_600SemiBold",
@ -605,7 +654,7 @@ export const ManuallyAddEventModal = () => {
size={ButtonSize.small}
paddingH-8
iconSource={() => (
<Ionicons name="add-outline" size={20} color="#ea156c" />
<Ionicons name="add-outline" size={20} color="#ea156c"/>
)}
style={{
marginLeft: "auto",
@ -614,16 +663,16 @@ export const ManuallyAddEventModal = () => {
borderColor: "#ea156c",
borderWidth: 1,
}}
labelStyle={{ fontFamily: "Manrope_600SemiBold", fontSize: 14 }}
labelStyle={{fontFamily: "Manrope_600SemiBold", fontSize: 14}}
color="#ea156c"
label="Set Reminder"
/>
</View>
</View>
<View style={styles.divider} />
<View style={styles.divider}/>
<View marginH-30 marginB-0 row spread centerV>
<View row center>
<LockIcon />
<LockIcon/>
<Text
style={{
fontFamily: "PlusJakartaSans_500Medium",
@ -645,10 +694,10 @@ export const ManuallyAddEventModal = () => {
/>
</View>
</View>
<View style={styles.divider} />
<View style={styles.divider}/>
<View marginH-28 marginB-0 centerV flex-1>
<View row centerV style={{ flexGrow: 1 }}>
<Ionicons name="location-outline" size={25} color={"#919191"} />
<View row centerV style={{flexGrow: 1}}>
<Ionicons name="location-outline" size={25} color={"#919191"}/>
<TextField
placeholder="Location"
value={location}
@ -668,10 +717,10 @@ export const ManuallyAddEventModal = () => {
</View>
{editEvent && (
<>
<View style={styles.divider} />
<View style={styles.divider}/>
<View marginH-32 marginB-0 centerV flex-1>
<View row centerV style={{ flexGrow: 1 }}>
<AddPersonIcon />
<View row centerV style={{flexGrow: 1}}>
<AddPersonIcon/>
<TextField
editable={false}
value={creator}
@ -689,11 +738,11 @@ export const ManuallyAddEventModal = () => {
</View>
</>
)}
<View style={styles.divider} />
<View style={styles.divider}/>
<View marginH-30 marginB-0 spread centerV flex-1>
<TouchableOpacity onPress={() => detailsRef?.current?.focus()}>
<View row centerV>
<MenuIcon />
<MenuIcon/>
<Text
style={{
fontFamily: "PlusJakartaSans_500Medium",
@ -714,7 +763,7 @@ export const ManuallyAddEventModal = () => {
multiline
numberOfLines={10}
marginT-10
style={{ flex: 1, minHeight: 180 }}
style={{flex: 1, minHeight: 180}}
/>
</View>
</ScrollView>
@ -724,12 +773,12 @@ export const ManuallyAddEventModal = () => {
marginB-30
label="Create event from image"
text70
style={{ height: 47 }}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium", fontSize: 15 }}
style={{height: 47}}
labelStyle={{fontFamily: "PlusJakartaSans_500Medium", fontSize: 15}}
backgroundColor="#05a8b6"
iconSource={() => (
<View marginR-5>
<CameraIcon color="white" />
<CameraIcon color="white"/>
</View>
)}
/>
@ -743,11 +792,12 @@ export const ManuallyAddEventModal = () => {
/>
)}
</Modal>
</>
);
};
const styles = StyleSheet.create({
divider: { height: 1, backgroundColor: "#e4e4e4", marginVertical: 15 },
divider: {height: 1, backgroundColor: "#e4e4e4", marginVertical: 15},
gradient: {
height: "25%",
position: "absolute",