Colors, fix family view, updated version

This commit is contained in:
Milan Paunovic
2024-10-10 02:00:14 +02:00
parent 2c099740a2
commit ca0b55c494
12 changed files with 545 additions and 659 deletions
+149 -162
View File
@@ -1,189 +1,176 @@
import React, { useEffect, useRef, useState } from "react";
import { LayoutChangeEvent, StyleSheet } from "react-native";
import { Calendar } from "react-native-big-calendar";
import {
Picker,
PickerModes,
SegmentedControl,
View,
Text
} from "react-native-ui-lib";
import { MaterialIcons } from "@expo/vector-icons";
import { AddEventDialog } from "@/components/pages/calendar/AddEventDialog";
import { useAuthContext } from "@/contexts/AuthContext";
import React, {useRef, useState} from "react";
import {LayoutChangeEvent, StyleSheet} from "react-native";
import {Calendar} from "react-native-big-calendar";
import {Picker, PickerModes, SegmentedControl, View} from "react-native-ui-lib";
import {MaterialIcons} from "@expo/vector-icons";
import {AddEventDialog} from "@/components/pages/calendar/AddEventDialog";
import HeaderTemplate from "@/components/shared/HeaderTemplate";
import CalendarViewSwitch from "@/components/pages/calendar/CalendarViewSwitch";
import { ManuallyAddEventModal } from "@/components/pages/calendar/ManuallyAddEventModal";
import { CalendarEvent, useCalendarContext } from "@/contexts/CalendarContext";
import { useSettingsContext } from "@/contexts/SettingsContext";
import {ManuallyAddEventModal} from "@/components/pages/calendar/ManuallyAddEventModal";
import {CalendarEvent} from "@/contexts/CalendarContext";
import {useSettingsContext} from "@/contexts/SettingsContext";
import EditEventDialog from "./EditEventDialog";
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
const modeMap = new Map([
[0, "day"],
[1, "week"],
[2, "month"],
[0, "day"],
[1, "week"],
[2, "month"],
]);
const months = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
export default function CalendarPage() {
const { calendarColor } = useSettingsContext();
const [editVisible, setEditVisible] = useState<boolean>(false);
const [eventForEdit, setEventForEdit] = useState<CalendarEvent>();
const {calendarColor} = useSettingsContext();
const [editVisible, setEditVisible] = useState<boolean>(false);
const [eventForEdit, setEventForEdit] = useState<CalendarEvent>();
const styles = StyleSheet.create({
segmentslblStyle: {
fontSize: 14,
},
calHeader: {
borderWidth: 0,
},
});
const styles = StyleSheet.create({
segmentslblStyle: {
fontSize: 14,
},
calHeader: {
borderWidth: 0,
},
});
const { profileData } = useAuthContext();
const [isFamilyView, setIsFamilyView] = useState<boolean>(true);
const [calendarHeight, setCalendarHeight] = useState(0);
const [mode, setMode] = useState<"week" | "month" | "day">("week");
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
const [selectedNewEventDate, setSelectedNewEndDate] = useState<
Date | undefined
>(undefined);
const [isFamilyView, setIsFamilyView] = useState<boolean>(true);
const [calendarHeight, setCalendarHeight] = useState(0);
const [mode, setMode] = useState<"week" | "month" | "day">("week");
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
const [selectedNewEventDate, setSelectedNewEndDate] = useState<
Date | undefined
>(undefined);
const calendarContainerRef = useRef(null);
// const { events, familyEvents } = useCalendarContext();
const {data: events} = useGetEvents()
const calendarContainerRef = useRef(null);
const {data: events} = useGetEvents(isFamilyView)
const onLayout = (event: LayoutChangeEvent) => {
const { height } = event.nativeEvent.layout;
setCalendarHeight(height);
};
const onLayout = (event: LayoutChangeEvent) => {
const {height} = event.nativeEvent.layout;
setCalendarHeight(height);
};
const handleSegmentChange = (index: number) => {
const selectedMode = modeMap.get(index);
if (selectedMode) {
setMode(selectedMode as "day" | "week" | "month");
}
};
const handleSegmentChange = (index: number) => {
const selectedMode = modeMap.get(index);
if (selectedMode) {
setMode(selectedMode as "day" | "week" | "month");
}
};
const handleMonthChange = (month: string) => {
// Get the current day and year
const currentDay = selectedDate.getDate();
const currentYear = selectedDate.getFullYear();
const handleMonthChange = (month: string) => {
const currentDay = selectedDate.getDate();
const currentYear = selectedDate.getFullYear();
// Find the new month index
const newMonthIndex = months.indexOf(month);
const newMonthIndex = months.indexOf(month);
// Create a new Date object with the selected month, preserving day and year
const updatedDate = new Date(currentYear, newMonthIndex, currentDay);
const updatedDate = new Date(currentYear, newMonthIndex, currentDay);
// Update both selectedDate and activeDate in the Calendar component
setSelectedDate(updatedDate);
};
setSelectedDate(updatedDate);
};
return (
<View style={{ flex: 1, height: "100%", padding: 10 }}>
<HeaderTemplate
message={"Let's get your week started!"}
isWelcome={true}
/>
return (
<View style={{flex: 1, height: "100%", padding: 10}}>
<HeaderTemplate
message={"Let's get your week started!"}
isWelcome={true}
/>
<View
style={{ flex: 1, backgroundColor: "#fff", borderRadius: 30 }}
ref={calendarContainerRef}
onLayout={onLayout}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 10,
paddingVertical: 8,
borderRadius: 20,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
backgroundColor: "white",
marginBottom: 10,
}}
>
<Picker
value={months[selectedDate.getMonth()]} // Get the month from the date
placeholder={"Select Month"}
mode={PickerModes.SINGLE}
onChange={(itemValue) => handleMonthChange(itemValue as string)}
trailingAccessory={<MaterialIcons name={"keyboard-arrow-down"} />}
>
{months.map((month) => (
<Picker.Item key={month} label={month} value={month} />
))}
</Picker>
<View
style={{flex: 1, backgroundColor: "#fff", borderRadius: 30}}
ref={calendarContainerRef}
onLayout={onLayout}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 10,
paddingVertical: 8,
borderRadius: 20,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
backgroundColor: "white",
marginBottom: 10,
}}
>
<Picker
value={months[selectedDate.getMonth()]} // Get the month from the date
placeholder={"Select Month"}
mode={PickerModes.SINGLE}
onChange={(itemValue) => handleMonthChange(itemValue as string)}
trailingAccessory={<MaterialIcons name={"keyboard-arrow-down"}/>}
>
{months.map((month) => (
<Picker.Item key={month} label={month} value={month}/>
))}
</Picker>
<View>
<SegmentedControl
segments={[{ label: "D" }, { label: "W" }, { label: "M" }]}
backgroundColor="#ececec"
inactiveColor="#919191"
activeBackgroundColor="#ea156c"
activeColor="white"
outlineColor="white"
outlineWidth={3}
style={{ backgroundColor: "green" }}
segmentLabelStyle={styles.segmentslblStyle}
onChangeIndex={handleSegmentChange}
initialIndex={mode === "day" ? 0 : mode === "week" ? 1 : 2}
<View>
<SegmentedControl
segments={[{label: "D"}, {label: "W"}, {label: "M"}]}
backgroundColor="#ececec"
inactiveColor="#919191"
activeBackgroundColor="#ea156c"
activeColor="white"
outlineColor="white"
outlineWidth={3}
style={{backgroundColor: "green"}}
segmentLabelStyle={styles.segmentslblStyle}
onChangeIndex={handleSegmentChange}
initialIndex={mode === "day" ? 0 : mode === "week" ? 1 : 2}
/>
</View>
</View>
{calendarHeight > 0 && (
<Calendar
bodyContainerStyle={styles.calHeader}
mode={mode}
events={isFamilyView ? events ?? [] : events ?? []}
eventCellStyle={(event) => ({backgroundColor: event.eventColor})}
onPressEvent={(event) => {
setEditVisible(true);
setEventForEdit(event);
}}
height={calendarHeight}
activeDate={selectedDate}
date={selectedDate}
onPressCell={setSelectedNewEndDate}
/>
)}
</View>
<CalendarViewSwitch viewSwitch={setIsFamilyView}/>
<AddEventDialog/>
{eventForEdit && (
<EditEventDialog
isVisible={editVisible}
setIsVisible={() => {
setEditVisible(!editVisible);
}}
event={eventForEdit}
/>
)}
<ManuallyAddEventModal
key={`${selectedNewEventDate}`}
initialDate={selectedNewEventDate}
show={!!selectedNewEventDate}
close={() => setSelectedNewEndDate(undefined)}
/>
</View>
</View>
{calendarHeight > 0 && (
<Calendar
bodyContainerStyle={styles.calHeader}
mode={mode}
events={isFamilyView ? events ?? [] : events ?? []}
eventCellStyle={{ backgroundColor: isFamilyView ? '#46a80a' : calendarColor }}
onPressEvent={(event) => {
setEditVisible(true);
setEventForEdit(event);
}}
height={calendarHeight}
activeDate={selectedDate}
date={selectedDate}
onPressCell={setSelectedNewEndDate}
/>
)}
</View>
<CalendarViewSwitch viewSwitch={setIsFamilyView} />
<AddEventDialog />
{eventForEdit && (
<EditEventDialog
isVisible={editVisible}
setIsVisible={() => {
setEditVisible(!editVisible);
}}
event={eventForEdit}
/>
)}
<ManuallyAddEventModal
key={`${selectedNewEventDate}`}
initialDate={selectedNewEventDate}
show={!!selectedNewEventDate}
close={() => setSelectedNewEndDate(undefined)}
/>
</View>
);
);
}
@@ -1,5 +1,5 @@
import {AntDesign, Ionicons} from "@expo/vector-icons";
import React, {useState} from "react";
import React, {useCallback, useState} from "react";
import {Button, Checkbox, Text, View} from "react-native-ui-lib";
import {ScrollView, StyleSheet} from "react-native";
import {colorMap} from "@/contexts/SettingsContext";
@@ -11,6 +11,7 @@ import {useAuthContext} from "@/contexts/AuthContext";
import {useUpdateUserData} from "@/hooks/firebase/useUpdateUserData";
import {GoogleSignin} from "@react-native-google-signin/google-signin";
import * as AuthSession from "expo-auth-session";
import debounce from "debounce";
GoogleSignin.configure({
webClientId:
@@ -40,10 +41,12 @@ const microsoftConfig = {
const CalendarSettingsPage = (props: {
setSelectedPage: (page: number) => void;
}) => {
const [selectedColor, setSelectedColor] = useState<string>(colorMap.pink);
const [startDate, setStartDate] = useState<boolean>(true);
const {profileData} = useAuthContext();
const [selectedColor, setSelectedColor] = useState<string>(profileData?.eventColor ?? colorMap.pink);
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(profileData?.eventColor ?? colorMap.pink);
const {mutateAsync: createEventFromProvider} = useCreateEventFromProvider();
const {mutateAsync: updateUserData} = useUpdateUserData();
@@ -162,6 +165,28 @@ const CalendarSettingsPage = (props: {
}
};
const debouncedUpdateUserData = useCallback(
debounce(async (color: string) => {
try {
await updateUserData({
newUserData: {
eventColor: color
}
});
} catch (error) {
console.error("Failed to update color:", error);
setSelectedColor(previousSelectedColor)
}
}, 500),
[]
);
const handleChangeColor = (color: string) => {
setPreviousSelectedColor(selectedColor)
setSelectedColor(color);
debouncedUpdateUserData(color);
};
return (
<ScrollView>
<View marginH-30>
@@ -179,35 +204,35 @@ const CalendarSettingsPage = (props: {
Event Color Preference
</Text>
<View row spread>
<TouchableOpacity onPress={() => setSelectedColor(colorMap.pink)}>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.pink)}>
<View style={styles.colorBox} backgroundColor={colorMap.pink}>
{selectedColor == colorMap.pink && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => setSelectedColor(colorMap.orange)}>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.orange)}>
<View style={styles.colorBox} backgroundColor={colorMap.orange}>
{selectedColor == colorMap.orange && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => setSelectedColor(colorMap.green)}>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.green)}>
<View style={styles.colorBox} backgroundColor={colorMap.green}>
{selectedColor == colorMap.green && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => setSelectedColor(colorMap.teal)}>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.teal)}>
<View style={styles.colorBox} backgroundColor={colorMap.teal}>
{selectedColor == colorMap.teal && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => setSelectedColor(colorMap.purple)}>
<TouchableOpacity onPress={() => handleChangeColor(colorMap.purple)}>
<View style={styles.colorBox} backgroundColor={colorMap.purple}>
{selectedColor == colorMap.purple && (
<AntDesign name="check" size={30} color="white"/>
@@ -344,34 +369,34 @@ const CalendarSettingsPage = (props: {
const styles = StyleSheet.create({
addCalBtn: {
backgroundColor: "#ffffff",
marginBottom: 15,
justifyContent: "flex-start",
paddingLeft: 25,
},
backBtn: {
backgroundColor: "red",
marginLeft: -2,
justifyContent: "flex-start",
},
card: {
backgroundColor: "white",
width: "100%",
padding: 20,
paddingBottom: 30,
marginTop: 20,
borderRadius: 20,
},
colorBox: {
aspectRatio: 1,
justifyContent: "center",
alignItems: "center",
width: 50,
borderRadius: 12,
},
checkbox: {
borderRadius: 50,
},
backgroundColor: "#ffffff",
marginBottom: 15,
justifyContent: "flex-start",
paddingLeft: 25,
},
backBtn: {
backgroundColor: "red",
marginLeft: -2,
justifyContent: "flex-start",
},
card: {
backgroundColor: "white",
width: "100%",
padding: 20,
paddingBottom: 30,
marginTop: 20,
borderRadius: 20,
},
colorBox: {
aspectRatio: 1,
justifyContent: "center",
alignItems: "center",
width: 50,
borderRadius: 12,
},
checkbox: {
borderRadius: 50,
},
});
export default CalendarSettingsPage;