Event creation

This commit is contained in:
Milan Paunovic
2024-08-26 13:42:28 +02:00
parent 64ae88a732
commit 96168316b5
22 changed files with 1129 additions and 1191 deletions

View File

@ -0,0 +1,89 @@
import React, {useState} from "react";
import {MaterialIcons} from "@expo/vector-icons";
import {Button, Card, Dialog, PanningProvider, Text, View} from "react-native-ui-lib";
import {TouchableOpacity} from "react-native";
import {ManuallyAddEventModal} from "@/components/pages/calendar/ManuallyAddEventModal";
export const AddEventDialog = () => {
const [show, setShow] = useState(false);
const [showManualInputModal, setShowManualInputModal] = useState(false);
const handleOpenManualInputModal = () => {
setShow(false);
setTimeout(() => {
setShowManualInputModal(true);
}, 500);
};
return (
<>
<Button
style={{
position: "absolute",
bottom: 20,
right: 20,
height: 60,
width: 60,
borderRadius: 30,
backgroundColor: "#fff",
alignItems: 'center',
justifyContent: 'center',
}}
enableShadow
iconSource={() => <MaterialIcons name="add" size={30}/>}
onPress={() => setShow(true)}
/>
<Dialog
visible={show}
onDismiss={() => setShow(false)}
panDirection={PanningProvider.Directions.DOWN}
center
>
<Card style={{padding: 20, justifyContent: 'center', alignItems: "center"}}>
<Text text60>Create a new event</Text>
<View style={{marginTop: 20, alignItems: 'center'}}>
<Button
style={{
marginBottom: 10,
backgroundColor: "#007bff",
}}
onPress={handleOpenManualInputModal}
>
<Text style={{color: "white"}}>Manually Input</Text>
</Button>
<Button
style={{
marginBottom: 10,
backgroundColor: "#007bff",
opacity: 0.5
}}
disabled
>
<Text style={{color: "white"}}>Scan an Image</Text>
</Button>
<Button
style={{
marginBottom: 10,
backgroundColor: "#007bff",
opacity: 0.5
}}
disabled
>
<Text style={{color: "white"}}>Paste in text</Text>
</Button>
</View>
<TouchableOpacity onPress={() => setShow(false)}>
<Text style={{marginTop: 20, color: "#007bff"}}>Go back</Text>
</TouchableOpacity>
</Card>
</Dialog>
<ManuallyAddEventModal show={showManualInputModal} close={() => setShowManualInputModal(false)}/>
</>
)
}

View File

@ -0,0 +1,260 @@
import {
Avatar,
Colors,
DateTimePicker,
LoaderScreen,
Modal,
Picker,
Switch,
Text,
TextField,
View
} from "react-native-ui-lib";
import {ScrollView, TouchableOpacity} from "react-native-gesture-handler";
import {useSafeAreaInsets} from "react-native-safe-area-context";
import {useState} from "react";
import {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";
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}: { show: boolean, close: () => void }) => {
const {user} = useAuthContext()
const insets = useSafeAreaInsets();
const [title, setTitle] = useState<string>("");
const [isAllDay, setIsAllDay] = useState(false);
const [startTime, setStartTime] = useState(new Date());
const [endTime, setEndTime] = useState(new Date())
const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(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 = async () => {
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: Partial<EventData> = {
title,
startDate: finalStartDate,
endDate: finalEndDate,
repeatDays: repeatInterval.map(x => x.toString()),
allDay: isAllDay
};
await createEvent(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: "#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}
/>
{!isAllDay && (
<DateTimePicker
mode="time"
value={startTime}
onChange={setStartTime}
/>
)}
</View>
{!isAllDay && (
<View style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: 20
}}>
<DateTimePicker
mode="date"
dateFormatter={formatDateTime}
value={endDate}
onChange={setEndDate}
/>
<DateTimePicker
mode="time"
value={endTime}
onChange={setEndTime}
/>
</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>
</Modal>
);
};

View File

@ -1,41 +1,49 @@
import { View, Text, Button } from "react-native-ui-lib";
import { TextInput } from "react-native";
import { View, Text, Button, TextField } from "react-native-ui-lib";
import React, { useState } from "react";
import { useSignIn } from "@/hooks/firebase/useSignIn";
const SignInPage = (props: {
setRegister: () => any;
}) => {
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const SignInPage = (props: { setRegister: () => any }) => {
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const { mutateAsync: signIn } = useSignIn();
const { mutateAsync: signIn, error, isError } = useSignIn();
const handleSignIn = async () => {
await signIn({email, password});
}
const handleSignIn = async () => {
await signIn({ email, password });
};
return (
<View marginH-20>
<TextInput placeholder="Email" value={email} onChangeText={setEmail} />
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button label="Login" onPress={handleSignIn} />
<Text>Don't have an account?</Text>
<Button
onPress={props.setRegister}
label="Sign Up"
link
padding-0
margin-0
left
/>
</View>
);
return (
<View padding-10>
<TextField
placeholder="Email"
value={email}
onChangeText={setEmail}
style={{ marginBottom: 10 }}
floatingPlaceholder
/>
<TextField
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
style={{ marginBottom: 10 }}
floatingPlaceholder
/>
<Button label="Login" onPress={handleSignIn} style={{ marginBottom: 20 }} />
{isError && (
<Text center style={{ marginBottom: 20 }}>{`${error}`}</Text>
)}
<Text center style={{ marginBottom: 5 }}>Don't have an account?</Text>
<Button
onPress={props.setRegister}
label="Sign Up"
link
padding-0
margin-0
left
/>
</View>
);
};
export default SignInPage;

View File

@ -1,83 +1,96 @@
import { TextInput } from "react-native";
import React, { useState } from "react";
import { Checkbox, Button, View, Text } from "react-native-ui-lib";
import {Checkbox, Button, View, Text, TextField} from "react-native-ui-lib";
import { useSignUp } from "@/hooks/firebase/useSignUp";
import { ProfileType } from "@/contexts/AuthContext";
const SignUpPage = (props: { unsetRegister: () => any }) => {
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [isParent, setIsParent] = useState<boolean>(true);
const [isChild, setIsChild] = useState<boolean>(false);
const [isCaregiver, setIsCaregiver] = useState<boolean>(false);
const [profileType, setProfileType] = useState<ProfileType>(
ProfileType.PARENT
);
const { mutateAsync: signUp } = useSignUp();
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [isParent, setIsParent] = useState<boolean>(true);
const [isChild, setIsChild] = useState<boolean>(false);
const [isCaregiver, setIsCaregiver] = useState<boolean>(false);
const [profileType, setProfileType] = useState<ProfileType>(
ProfileType.PARENT
);
const { mutateAsync: signUp } = useSignUp();
const handleSignUp = async () => {
await signUp({ email, password });
};
const handleSignUp = async () => {
await signUp({ email, password });
};
return (
<View marginH-20>
<TextInput placeholder="Email" value={email} onChangeText={setEmail} />
<TextInput
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<Button label="Register" onPress={handleSignUp} />
<Text>Choose Profile Type:</Text>
<Checkbox
label="Parent"
value={isParent}
onValueChange={(value) => {
setIsParent(value);
setProfileType(ProfileType.PARENT);
if (value) {
setIsChild(false);
setIsCaregiver(false);
}
}}
/>
<Checkbox
label="Child"
value={isChild}
onValueChange={(value) => {
setIsChild(value);
setProfileType(ProfileType.CHILD);
if (value) {
setIsParent(false);
setIsCaregiver(false);
}
}}
/>
<Checkbox
label="Caregiver"
value={isCaregiver}
onValueChange={(value) => {
setIsCaregiver(value);
setProfileType(ProfileType.CAREGIVER);
if (value) {
setIsParent(false);
setIsChild(false);
}
}}
/>
<Text>
Already have an account?
<Button
label="Sign In"
margin-0
link
text200
onPress={props.unsetRegister}
/>
</Text>
</View>
);
return (
<View padding-10>
<TextField
placeholder="Email"
value={email}
onChangeText={setEmail}
style={{ marginBottom: 10 }}
floatingPlaceholder
/>
<TextField
placeholder="Password"
value={password}
onChangeText={setPassword}
secureTextEntry
style={{ marginBottom: 10 }}
floatingPlaceholder
/>
<Button
label="Register"
onPress={handleSignUp}
style={{ marginBottom: 10 }}
/>
<Text style={{ marginBottom: 10 }}>Choose Profile Type:</Text>
<Checkbox
label="Parent"
value={isParent}
onValueChange={(value) => {
setIsParent(value);
setProfileType(ProfileType.PARENT);
if (value) {
setIsChild(false);
setIsCaregiver(false);
}
}}
style={{ marginBottom: 10 }}
/>
<Checkbox
label="Child"
value={isChild}
onValueChange={(value) => {
setIsChild(value);
setProfileType(ProfileType.CHILD);
if (value) {
setIsParent(false);
setIsCaregiver(false);
}
}}
style={{ marginBottom: 10 }}
/>
<Checkbox
label="Caregiver"
value={isCaregiver}
onValueChange={(value) => {
setIsCaregiver(value);
setProfileType(ProfileType.CAREGIVER);
if (value) {
setIsParent(false);
setIsChild(false);
}
}}
/>
<Text center style={{ marginBottom: 5, marginTop: 10 }}>
Already have an account?
</Text>
<Button
label="Sign In"
margin-0
link
text200
onPress={props.unsetRegister}
/>
</View>
);
};
export default SignUpPage;