start on 0 seconds

This commit is contained in:
Milan Paunovic
2024-09-28 13:23:53 +02:00
parent 91717c699d
commit 594e54b11b

View File

@ -1,323 +1,331 @@
import { import {
Avatar, Avatar,
Colors, Colors,
DateTimePicker, DateTimePicker,
LoaderScreen, LoaderScreen,
Modal, Modal,
Picker, Picker,
Switch, Switch,
Text, Text,
TextField, TextField,
View, View,
} from "react-native-ui-lib"; } from "react-native-ui-lib";
import { ScrollView, TouchableOpacity } from "react-native-gesture-handler"; import {ScrollView, TouchableOpacity} from "react-native-gesture-handler";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import {useSafeAreaInsets} from "react-native-safe-area-context";
import {useEffect, useState} from "react"; import {useState} from "react";
import { MaterialIcons } from "@expo/vector-icons"; import {MaterialIcons} from "@expo/vector-icons";
import { PickerMultiValue } from "react-native-ui-lib/src/components/picker/types"; import {PickerMultiValue} from "react-native-ui-lib/src/components/picker/types";
import { useAuthContext } from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import { useCreateEvent } from "@/hooks/firebase/useCreateEvent"; import {useCreateEvent} from "@/hooks/firebase/useCreateEvent";
import { EventData } from "@/hooks/firebase/types/eventData"; import {EventData} from "@/hooks/firebase/types/eventData";
import {addHours} from "date-fns"; import {addHours} from "date-fns";
const daysOfWeek = [ const daysOfWeek = [
{ label: "Monday", value: "monday" }, {label: "Monday", value: "monday"},
{ label: "Tuesday", value: "tuesday" }, {label: "Tuesday", value: "tuesday"},
{ label: "Wednesday", value: "wednesday" }, {label: "Wednesday", value: "wednesday"},
{ label: "Thursday", value: "thursday" }, {label: "Thursday", value: "thursday"},
{ label: "Friday", value: "friday" }, {label: "Friday", value: "friday"},
{ label: "Saturday", value: "saturday" }, {label: "Saturday", value: "saturday"},
{ label: "Sunday", value: "sunday" }, {label: "Sunday", value: "sunday"},
]; ];
export const ManuallyAddEventModal = ({ export const ManuallyAddEventModal = ({
show, show,
close, close,
initialDate initialDate
}: { }: {
show: boolean; show: boolean;
close: () => void; close: () => void;
initialDate?: Date initialDate?: Date
}) => { }) => {
const { user } = useAuthContext(); const {user} = useAuthContext();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const [title, setTitle] = useState<string>(""); const [title, setTitle] = useState<string>("");
const [isAllDay, setIsAllDay] = useState(false); const [isAllDay, setIsAllDay] = useState(false);
const [startTime, setStartTime] = useState(initialDate ?? new Date()); const [startTime, setStartTime] = useState(() => {
const [endTime, setEndTime] = useState(initialDate ? addHours(initialDate, 1) : new Date()); const date = initialDate ?? new Date();
date.setSeconds(0, 0);
const [startDate, setStartDate] = useState(initialDate ?? new Date()); return date;
const [endDate, setEndDate] = useState(initialDate ?? new Date()); });
const [endTime, setEndTime] = useState(() => {
const [repeatInterval, setRepeatInterval] = useState<PickerMultiValue>([]); const date = initialDate ? addHours(initialDate, 1) : new Date();
date.setSeconds(0, 0);
const { mutateAsync: createEvent, isLoading, isError } = useCreateEvent(); return date;
const formatDateTime = (date: Date) => {
return date.toLocaleDateString("en-US", {
weekday: "long",
month: "short",
day: "numeric",
}); });
};
const combineDateAndTime = (date: Date, time: Date): Date => { const [startDate, setStartDate] = useState(initialDate ?? new Date());
const combined = new Date(date); const [endDate, setEndDate] = useState(initialDate ?? new Date());
combined.setHours(time.getHours());
combined.setMinutes(time.getMinutes());
combined.setSeconds(0);
combined.setMilliseconds(0);
return combined;
};
const handleSave = async () => { const [repeatInterval, setRepeatInterval] = useState<PickerMultiValue>([]);
let finalStartDate: Date;
let finalEndDate: Date;
if (isAllDay) { const {mutateAsync: createEvent, isLoading, isError} = useCreateEvent();
finalStartDate = new Date(startDate);
finalStartDate.setHours(0, 0, 0, 0);
finalEndDate = new Date(startDate); const formatDateTime = (date: Date) => {
finalEndDate.setHours(23, 59, 59, 999); return date.toLocaleDateString("en-US", {
} else { weekday: "long",
finalStartDate = combineDateAndTime(startDate, startTime); month: "short",
finalEndDate = combineDateAndTime(endDate, endTime); day: "numeric",
} });
const eventData: Partial<EventData> = {
title,
startDate: finalStartDate,
endDate: finalEndDate,
repeatDays: repeatInterval.map((x) => x.toString()),
allDay: isAllDay,
}; };
await createEvent(eventData); 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;
};
close(); const handleSave = async () => {
}; let finalStartDate: Date;
let finalEndDate: Date;
const getRepeatLabel = () => { if (isAllDay) {
const selectedDays = repeatInterval; finalStartDate = new Date(startDate);
const allDays = [ finalStartDate.setHours(0, 0, 0, 0);
"sunday",
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
];
const workDays = ["monday", "tuesday", "wednesday", "thursday", "friday"];
const isEveryWorkDay = workDays.every((day) => selectedDays.includes(day)); finalEndDate = new Date(startDate);
finalEndDate.setHours(23, 59, 59, 999);
} else {
finalStartDate = combineDateAndTime(startDate, startTime);
finalEndDate = combineDateAndTime(endDate, endTime);
}
const isEveryDay = allDays.every((day) => selectedDays.includes(day)); const eventData: Partial<EventData> = {
title,
startDate: finalStartDate,
endDate: finalEndDate,
repeatDays: repeatInterval.map((x) => x.toString()),
allDay: isAllDay,
};
if (isEveryDay) { await createEvent(eventData);
return "Every day";
} else if ( close();
isEveryWorkDay && };
!selectedDays.includes("saturday") &&
!selectedDays.includes("sunday") const getRepeatLabel = () => {
) { const selectedDays = repeatInterval;
return "Every work day"; const allDays = [
} else { "sunday",
return selectedDays "monday",
.map((item) => daysOfWeek.find((day) => day.value === item)?.label) "tuesday",
.join(", "); "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>
);
} }
};
if (isLoading && !isError) {
return ( return (
<Modal <Modal
visible={show} visible={show}
animationType="slide" animationType="slide"
onRequestClose={close} onRequestClose={close}
transparent={false} 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: "#007bff" }}>Cancel</Text>
</TouchableOpacity>
<Text style={{ fontWeight: "bold", fontSize: 16 }}>Add event</Text>
<TouchableOpacity onPress={handleSave}>
<Text style={{ color: "#007bff" }}>Save</Text>
</TouchableOpacity>
</View>
<ScrollView
contentContainerStyle={{ paddingHorizontal: 16, paddingTop: 10 }}
>
<View style={{ marginVertical: 10 }}>
<TextField
placeholder={"Title"}
floatingPlaceholder
value={title}
onChangeText={setTitle}
showCharCounter
maxLength={200}
fieldStyle={{
borderBottomWidth: 1,
borderBottomColor: "black",
borderStyle: "solid",
}}
/>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 20,
}}
>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<MaterialIcons name="schedule" size={24} color="gray" />
<Text style={{ marginLeft: 10 }}>All-day</Text>
</View>
<Switch
value={isAllDay}
onValueChange={(value) => setIsAllDay(value)}
/>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 20,
}}
>
<DateTimePicker
mode="date"
dateFormatter={formatDateTime}
value={startDate}
onChange={setStartDate}
display="default"
/>
{!isAllDay && (
<DateTimePicker
mode="time"
value={startTime}
onChange={setStartTime}
display="spinner"
/>
)}
</View>
{!isAllDay && (
<View <View
style={{ style={{
flexDirection: "row", flex: 1,
justifyContent: "space-between", backgroundColor: "#fff",
alignItems: "center", paddingTop: insets.top, // Safe area inset for top
marginBottom: 20, paddingBottom: insets.bottom, // Safe area inset for bottom
}} paddingLeft: insets.left, // Safe area inset for left
paddingRight: insets.right, // Safe area inset for right
}}
> >
<DateTimePicker <View
mode="date" style={{
dateFormatter={formatDateTime} flexDirection: "row",
value={endDate} justifyContent: "space-between",
onChange={setEndDate} padding: 16,
display="default" }}
/> >
<DateTimePicker <TouchableOpacity onPress={close}>
mode="time" <Text style={{color: "#007bff"}}>Cancel</Text>
value={endTime} </TouchableOpacity>
onChange={setEndTime} <Text style={{fontWeight: "bold", fontSize: 16}}>Add event</Text>
minuteInterval={1} <TouchableOpacity onPress={handleSave}>
display="spinner" <Text style={{color: "#007bff"}}>Save</Text>
/> </TouchableOpacity>
</View>
<ScrollView
contentContainerStyle={{paddingHorizontal: 16, paddingTop: 10}}
>
<View style={{marginVertical: 10}}>
<TextField
placeholder={"Title"}
floatingPlaceholder
value={title}
onChangeText={setTitle}
showCharCounter
maxLength={200}
fieldStyle={{
borderBottomWidth: 1,
borderBottomColor: "black",
borderStyle: "solid",
}}
/>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 20,
}}
>
<View style={{flexDirection: "row", alignItems: "center"}}>
<MaterialIcons name="schedule" size={24} color="gray"/>
<Text style={{marginLeft: 10}}>All-day</Text>
</View>
<Switch
value={isAllDay}
onValueChange={(value) => setIsAllDay(value)}
/>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 20,
}}
>
<DateTimePicker
mode="date"
dateFormatter={formatDateTime}
value={startDate}
onChange={setStartDate}
display="default"
/>
{!isAllDay && (
<DateTimePicker
mode="time"
value={startTime}
onChange={setStartTime}
display="spinner"
/>
)}
</View>
{!isAllDay && (
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 20,
}}
>
<DateTimePicker
mode="date"
dateFormatter={formatDateTime}
value={endDate}
onChange={setEndDate}
display="default"
/>
<DateTimePicker
mode="time"
value={endTime}
onChange={setEndTime}
minuteInterval={1}
display="spinner"
/>
</View>
)}
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 20,
}}
>
<MaterialIcons name="repeat" size={24} color="gray"/>
<Picker
value={repeatInterval}
//@ts-ignore
onChange={(items: PickerMultiValue) => setRepeatInterval(items)}
placeholder="Doest not repeat"
style={{marginLeft: 10, flex: 1}}
mode={Picker.modes.MULTI}
getLabel={getRepeatLabel}
>
{daysOfWeek.map((option) => (
<Picker.Item
key={option.value}
label={option.label}
value={option.value}
/>
))}
</Picker>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 20,
}}
>
<MaterialIcons name="person-add" size={24} color="gray"/>
<TouchableOpacity
style={{
marginLeft: 10,
flexDirection: "row",
alignItems: "center",
flex: 1,
}}
>
<Avatar size={40} backgroundColor={Colors.yellow10}/>
<View style={{marginLeft: 10}}>
<Text>Other</Text>
<Text style={{color: "gray"}}>{user?.email}</Text>
</View>
</TouchableOpacity>
</View>
</ScrollView>
</View> </View>
)} </Modal>
);
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 20,
}}
>
<MaterialIcons name="repeat" size={24} color="gray" />
<Picker
value={repeatInterval}
//@ts-ignore
onChange={(items: PickerMultiValue) => setRepeatInterval(items)}
placeholder="Doest not repeat"
style={{ marginLeft: 10, flex: 1 }}
mode={Picker.modes.MULTI}
getLabel={getRepeatLabel}
>
{daysOfWeek.map((option) => (
<Picker.Item
key={option.value}
label={option.label}
value={option.value}
/>
))}
</Picker>
</View>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 20,
}}
>
<MaterialIcons name="person-add" size={24} color="gray" />
<TouchableOpacity
style={{
marginLeft: 10,
flexDirection: "row",
alignItems: "center",
flex: 1,
}}
>
<Avatar size={40} backgroundColor={Colors.yellow10} />
<View style={{ marginLeft: 10 }}>
<Text>Other</Text>
<Text style={{ color: "gray" }}>{user?.email}</Text>
</View>
</TouchableOpacity>
</View>
</ScrollView>
</View>
</Modal>
);
}; };