Files
cally/components/pages/calendar/ManuallyAddEventModal.tsx
2024-10-05 23:41:44 +02:00

416 lines
12 KiB
TypeScript

import {
Avatar,
Button,
ButtonSize,
Colors,
DateTimePicker,
LoaderScreen,
Modal,
Picker,
Switch,
Text,
TextField,
TouchableOpacity,
View,
} from "react-native-ui-lib";
import { ScrollView } from "react-native-gesture-handler";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useState } from "react";
import {
AntDesign,
Feather,
Ionicons,
MaterialIcons,
} from "@expo/vector-icons";
import { PickerMultiValue } from "react-native-ui-lib/src/components/picker/types";
import { useAuthContext } from "@/contexts/AuthContext";
import { useCreateEvent } from "@/hooks/firebase/useCreateEvent";
import { EventData } from "@/hooks/firebase/types/eventData";
import { addHours, setDate } from "date-fns";
import DropModalIcon from "@/assets/svgs/DropModalIcon";
import { CalendarEvent, useCalendarContext } from "@/contexts/CalendarContext";
import { repeatOptions } from "@/contexts/ToDosContext";
import { 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";
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 = ({
show,
close,
initialDate,
}: {
show: boolean;
close: () => void;
initialDate?: Date;
}) => {
const { addEvent } = useCalendarContext();
const { user } = useAuthContext();
const insets = useSafeAreaInsets();
const [title, setTitle] = useState<string>("");
const [isAllDay, setIsAllDay] = useState(false);
const [isPrivate, setIsPrivate] = useState<boolean>(false);
const [startTime, setStartTime] = useState(() => {
const date = initialDate ?? new Date();
date.setSeconds(0, 0);
return date;
});
const [endTime, setEndTime] = useState(() => {
const date = initialDate ? addHours(initialDate, 1) : new Date();
date.setSeconds(0, 0);
return date;
});
const [startDate, setStartDate] = useState(initialDate ?? new Date());
const [endDate, setEndDate] = useState(initialDate ?? new Date());
const [repeatInterval, setRepeatInterval] = useState<PickerMultiValue>([]);
const { mutateAsync: createEvent, isLoading, isError } = useCreateEvent();
const formatDateTime = (date: Date) => {
return date.toLocaleDateString("en-US", {
weekday: "long",
month: "short",
day: "numeric",
});
};
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 = () => {
let finalStartDate: Date;
let finalEndDate: Date;
if (isAllDay) {
finalStartDate = new Date(startDate);
finalStartDate.setHours(0, 0, 0, 0);
finalEndDate = new Date(startDate);
finalEndDate.setHours(23, 59, 59, 999);
} else {
finalStartDate = combineDateAndTime(startDate, startTime);
finalEndDate = combineDateAndTime(endDate, endTime);
}
const eventData: CalendarEvent = {
title: title,
start: finalStartDate,
end: finalEndDate,
allDay: isAllDay,
private: isPrivate,
};
addEvent(eventData);
close();
};
const getRepeatLabel = () => {
const selectedDays = repeatInterval;
const allDays = [
"sunday",
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
];
const workDays = ["monday", "tuesday", "wednesday", "thursday", "friday"];
const isEveryWorkDay = workDays.every((day) => selectedDays.includes(day));
const isEveryDay = allDays.every((day) => selectedDays.includes(day));
if (isEveryDay) {
return "Every day";
} else if (
isEveryWorkDay &&
!selectedDays.includes("saturday") &&
!selectedDays.includes("sunday")
) {
return "Every work day";
} else {
return selectedDays
.map((item) => daysOfWeek.find((day) => day.value === item)?.label)
.join(", ");
}
};
if (isLoading && !isError) {
return (
<Modal
visible={show}
animationType="slide"
onRequestClose={close}
transparent={false}
>
<LoaderScreen message={"Saving event..."} color={Colors.grey40} />
</Modal>
);
}
return (
<Modal
visible={show}
animationType="slide"
onRequestClose={close}
transparent={false}
>
<View
style={{
flex: 1,
backgroundColor: "#fff",
paddingTop: insets.top, // Safe area inset for top
paddingBottom: insets.bottom, // Safe area inset for bottom
paddingLeft: insets.left, // Safe area inset for left
paddingRight: insets.right, // Safe area inset for right
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
padding: 16,
}}
>
<TouchableOpacity onPress={close}>
<Text style={{ color: "#05a8b6" }} text70>
Cancel
</Text>
</TouchableOpacity>
<DropModalIcon onPress={close} />
<TouchableOpacity onPress={handleSave}>
<Text style={{ color: "#05a8b6" }} text70>
Save
</Text>
</TouchableOpacity>
</View>
<ScrollView>
<TextField
placeholder="Add event title"
value={title}
onChangeText={(text) => {
setTitle(text);
}}
placeholderTextColor="#2d2d30"
text60R
marginT-15
marginL-30
/>
<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 text70 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}
text70
marginL-8
onChange={(date) => {
setStartDate(date);
}}
/>
</View>
<DateTimePicker text70 value={startDate} mode="time" marginR-30/>
</View>
{!isAllDay && <View row marginB-10 spread>
<View row centerV>
<Feather name="calendar" size={25} color="#919191" />
<DateTimePicker
value={endDate}
text70
marginL-8
onChange={(date) => {
setEndDate(date);
}}
/>
</View>
<DateTimePicker text70 value={endDate} mode="time" marginR-30/>
</View>}
</View>
<View style={styles.divider} />
<View marginH-30 marginB-10 row centerV>
<Ionicons name="person-circle-outline" size={28} color="#919191" />
<Text text70R marginL-10>
Assignees
</Text>
<Button
size={ButtonSize.small}
paddingH-8
iconSource={() => (
<Ionicons name="add-outline" size={20} color="#ea156c" />
)}
style={{
marginLeft: "auto",
borderRadius: 8,
backgroundColor: "#ffe8f1",
borderColor: "#ea156c",
borderWidth: 1,
}}
color="#ea156c"
label="Assign"
/>
</View>
<View row marginH-13 marginT-13>
<View
marginL-30
style={{
aspectRatio: 1,
width: 50,
backgroundColor: "red",
borderRadius: 50,
}}
/>
<View
marginL-30
style={{
aspectRatio: 1,
width: 50,
backgroundColor: "red",
borderRadius: 50,
}}
/>
</View>
<View style={styles.divider} />
<View marginH-30 marginB-0 row spread centerV>
<View row centerV>
<ClockIcon />
<Text text70 marginL-10>
Reminder
</Text>
</View>
<View>
<Button
size={ButtonSize.small}
paddingH-8
iconSource={() => (
<Ionicons name="add-outline" size={20} color="#ea156c" />
)}
style={{
marginLeft: "auto",
borderRadius: 8,
backgroundColor: "#ffe8f1",
borderColor: "#ea156c",
borderWidth: 1,
}}
color="#ea156c"
label="Set Reminder"
/>
</View>
</View>
<View style={styles.divider} />
<View marginH-30 marginB-0 row spread centerV>
<View row>
<LockIcon />
<Text text70 marginL-10>
Mark as Private
</Text>
</View>
<View>
<Switch
onColor={"#ea156c"}
offColor={"#e1e1e2"}
marginL-10
value={isPrivate}
onValueChange={(value) => setIsPrivate(value)}
/>
</View>
</View>
<View style={styles.divider} />
<View marginH-30 marginB-0 row spread centerV>
<View row centerV>
<MenuIcon />
<Text text70 marginL-10>
Add Details
</Text>
</View>
<View></View>
</View>
</ScrollView>
<Button
marginH-30
marginB-15
label="Create event from image"
text70
backgroundColor="#05a8b6"
iconSource={() => (
<View marginR-5>
<CameraIcon color="white" />
</View>
)}
/>
</View>
</Modal>
);
};
const styles = StyleSheet.create({
divider: { height: 1, backgroundColor: "#e4e4e4", marginVertical: 15 },
gradient: {
height: "25%",
position: "absolute",
bottom: 0,
width: "100%",
},
buttonContainer: {
position: "absolute",
bottom: 25,
width: "100%",
},
button: {
backgroundColor: "rgb(253, 23, 117)",
paddingVertical: 20,
},
topBtn: {
backgroundColor: "white",
color: "#05a8b6",
},
rotateSwitch: {
marginLeft: 35,
marginBottom: 10,
marginTop: 25,
},
});