Added react native big calendar patch

This commit is contained in:
Milan Paunovic
2024-10-31 02:35:50 +01:00
parent 01274fcb6d
commit 37f3d27999
11 changed files with 2934 additions and 269 deletions

View File

@ -23,7 +23,7 @@ import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import NavBrainDumpIcon from "@/assets/svgs/NavBrainDumpIcon"; import NavBrainDumpIcon from "@/assets/svgs/NavBrainDumpIcon";
import NavCalendarIcon from "@/assets/svgs/NavCalendarIcon"; import NavCalendarIcon from "@/assets/svgs/NavCalendarIcon";
import NavSettingsIcon from "@/assets/svgs/NavSettingsIcon"; import NavSettingsIcon from "@/assets/svgs/NavSettingsIcon";
import { useAtom } from "jotai"; import {useAtom, useSetAtom} from "jotai";
import { import {
settingsPageIndex, settingsPageIndex,
toDosPageIndex, toDosPageIndex,
@ -32,9 +32,9 @@ import {
export default function TabLayout() { export default function TabLayout() {
const { mutateAsync: signOut } = useSignOut(); const { mutateAsync: signOut } = useSignOut();
const [pageIndex, setPageIndex] = useAtom(settingsPageIndex); const setPageIndex = useSetAtom(settingsPageIndex);
const [userView, setUserView] = useAtom(userSettingsView); const setUserView = useSetAtom(userSettingsView);
const [toDosIndex, setToDosIndex] = useAtom(toDosPageIndex); const setToDosIndex = useSetAtom(toDosPageIndex);
return ( return (
<Drawer <Drawer
@ -47,7 +47,6 @@ export default function TabLayout() {
backgroundColor: "#f9f8f7", backgroundColor: "#f9f8f7",
height: "100%", height: "100%",
}, },
drawerIcon: () => <MenuIcon />,
}} }}
drawerContent={(props) => { drawerContent={(props) => {
return ( return (
@ -234,7 +233,7 @@ export default function TabLayout() {
name="todos" name="todos"
options={{ options={{
drawerLabel: "To-Do", drawerLabel: "To-Do",
title: "To-Do's", title: "To-Dos",
}} }}
/> />
</Drawer> </Drawer>

View File

@ -13,6 +13,8 @@ import { Dimensions, Keyboard, StyleSheet } from "react-native";
import DropModalIcon from "@/assets/svgs/DropModalIcon"; import DropModalIcon from "@/assets/svgs/DropModalIcon";
import { useBrainDumpContext } from "@/contexts/DumpContext"; import { useBrainDumpContext } from "@/contexts/DumpContext";
import KeyboardManager from "react-native-keyboard-manager";
interface IAddBrainDumpProps { interface IAddBrainDumpProps {
isVisible: boolean; isVisible: boolean;
@ -29,14 +31,26 @@ const AddBrainDump = ({
const [dumpDesc, setDumpDesc] = useState<string>(""); const [dumpDesc, setDumpDesc] = useState<string>("");
const { width } = Dimensions.get("screen"); const { width } = Dimensions.get("screen");
// Refs for the two TextFields // Refs for the two TextFields
const descriptionRef = useRef<TextFieldRef>(null); const descriptionRef = useRef<TextFieldRef>(null);
const titleRef = useRef<TextFieldRef>(null);
useEffect(() => { useEffect(() => {
setDumpDesc(""); setDumpDesc("");
setDumpTitle(""); setDumpTitle("");
}, [addBrainDumpProps.isVisible]); }, [addBrainDumpProps.isVisible]);
useEffect(() => {
setTimeout(() => {
titleRef?.current?.focus()
}, 500)
}, []);
useEffect(() => {
KeyboardManager.setEnableAutoToolbar(false);
},[])
return ( return (
<Dialog <Dialog
bottom={true} bottom={true}
@ -72,7 +86,7 @@ const AddBrainDump = ({
<View marginH-20> <View marginH-20>
<TextField <TextField
value={dumpTitle} value={dumpTitle}
autoFocus ref={titleRef}
placeholder="Set Title" placeholder="Set Title"
text60R text60R
onChangeText={(text) => { onChangeText={(text) => {

View File

@ -1,293 +1,325 @@
import React, { useCallback, useEffect, useMemo, useState } from "react"; import React, {useCallback, useEffect, useMemo, useState} from "react";
import { Calendar } from "react-native-big-calendar"; import {Calendar} from "react-native-big-calendar";
import { ActivityIndicator, StyleSheet, View, ViewStyle } from "react-native"; import {ActivityIndicator, StyleSheet, View, ViewStyle} from "react-native";
import { useGetEvents } from "@/hooks/firebase/useGetEvents"; import {useGetEvents} from "@/hooks/firebase/useGetEvents";
import { useAtom, useSetAtom } from "jotai"; import {useAtom, useSetAtom} from "jotai";
import { import {
editVisibleAtom, editVisibleAtom,
eventForEditAtom, eventForEditAtom,
modeAtom, modeAtom,
selectedDateAtom, selectedDateAtom,
selectedNewEventDateAtom, selectedNewEventDateAtom,
} from "@/components/pages/calendar/atoms"; } from "@/components/pages/calendar/atoms";
import { useAuthContext } from "@/contexts/AuthContext"; import {useAuthContext} from "@/contexts/AuthContext";
import { CalendarEvent } from "@/components/pages/calendar/interfaces"; import {CalendarEvent} from "@/components/pages/calendar/interfaces";
import { Text } from "react-native-ui-lib"; import {Text} from "react-native-ui-lib";
import {addDays, isWithinInterval, subDays} from "date-fns"; import { isWithinInterval, subDays, addDays, compareAsc } from "date-fns";
interface EventCalendarProps { interface EventCalendarProps {
calendarHeight: number; calendarHeight: number;
// WAS USED FOR SCROLLABLE CALENDARS, PERFORMANCE WAS NOT OPTIMAL // WAS USED FOR SCROLLABLE CALENDARS, PERFORMANCE WAS NOT OPTIMAL
calendarWidth: number; calendarWidth: number;
} }
const getTotalMinutes = () => { const getTotalMinutes = () => {
const date = new Date(); const date = new Date();
return Math.abs(date.getUTCHours() * 60 + date.getUTCMinutes() - 200); return Math.abs(date.getUTCHours() * 60 + date.getUTCMinutes() - 200);
}; };
export const EventCalendar: React.FC<EventCalendarProps> = React.memo( export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
({ calendarHeight }) => { ({calendarHeight}) => {
const { data: events, isLoading } = useGetEvents(); const {data: events, isLoading} = useGetEvents();
const { profileData } = useAuthContext(); const {profileData} = useAuthContext();
const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom); const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom);
const [mode, setMode] = useAtom(modeAtom); const [mode, setMode] = useAtom(modeAtom);
const setEditVisible = useSetAtom(editVisibleAtom); const setEditVisible = useSetAtom(editVisibleAtom);
const setEventForEdit = useSetAtom(eventForEditAtom); const setEventForEdit = useSetAtom(eventForEditAtom);
const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom); const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom);
const [isRendering, setIsRendering] = useState(true); const [isRendering, setIsRendering] = useState(true);
const [offsetMinutes, setOffsetMinutes] = useState(getTotalMinutes()); const [offsetMinutes, setOffsetMinutes] = useState(getTotalMinutes());
const todaysDate = new Date(); const todaysDate = new Date();
useEffect(() => { useEffect(() => {
if (events && mode) { if (events && mode) {
setIsRendering(true); setIsRendering(true);
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
setIsRendering(false); setIsRendering(false);
}, 10 ); }, 10);
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
} }
}, [events, mode]); }, [events, mode]);
const handlePressEvent = useCallback( const handlePressEvent = useCallback(
(event: CalendarEvent) => { (event: CalendarEvent) => {
if (mode === "day" || mode === "week") { if (mode === "day" || mode === "week") {
setEditVisible(true); setEditVisible(true);
console.log({ event }); console.log({event});
setEventForEdit(event); setEventForEdit(event);
} else { } else {
setMode("day"); setMode("day");
setSelectedDate(event.start); setSelectedDate(event.start);
} }
}, },
[setEditVisible, setEventForEdit, mode] [setEditVisible, setEventForEdit, mode]
); );
const handlePressCell = useCallback( const handlePressCell = useCallback(
(date: Date) => { (date: Date) => {
if (mode === "day" || mode === "week") { if (mode === "day" || mode === "week") {
setSelectedNewEndDate(date); setSelectedNewEndDate(date);
} else { } else {
setMode("day"); setMode("day");
setSelectedDate(date); setSelectedDate(date);
} }
}, },
[mode, setSelectedNewEndDate, setSelectedDate] [mode, setSelectedNewEndDate, setSelectedDate]
); );
const handleSwipeEnd = useCallback( const handleSwipeEnd = useCallback(
(date: Date) => { (date: Date) => {
setSelectedDate(date); setSelectedDate(date);
}, },
[setSelectedDate] [setSelectedDate]
); );
const memoizedEventCellStyle = useCallback( const memoizedEventCellStyle = useCallback(
(event: CalendarEvent) => ({ backgroundColor: event.eventColor }), (event: CalendarEvent) => ({backgroundColor: event.eventColor}),
[] []
); );
const memoizedWeekStartsOn = useMemo( const memoizedWeekStartsOn = useMemo(
() => (profileData?.firstDayOfWeek === "Mondays" ? 1 : 0), () => (profileData?.firstDayOfWeek === "Mondays" ? 1 : 0),
[profileData] [profileData]
); );
const isSameDate = useCallback((date1: Date, date2: Date) => { const isSameDate = useCallback((date1: Date, date2: Date) => {
return ( return (
date1.getDate() === date2.getDate() && date1.getDate() === date2.getDate() &&
date1.getMonth() === date2.getMonth() && date1.getMonth() === date2.getMonth() &&
date1.getFullYear() === date2.getFullYear() date1.getFullYear() === date2.getFullYear()
); );
}, []); }, []);
const dayHeaderColor = useMemo(() => { const dayHeaderColor = useMemo(() => {
return isSameDate(todaysDate, selectedDate) ? "white" : "#4d4d4d"; return isSameDate(todaysDate, selectedDate) ? "white" : "#4d4d4d";
}, [selectedDate, mode]); }, [selectedDate, mode]);
const dateStyle = useMemo(() => { const dateStyle = useMemo(() => {
if (mode === "week") return undefined; if (mode === "week") return undefined;
return isSameDate(todaysDate, selectedDate) && mode === "day" return isSameDate(todaysDate, selectedDate) && mode === "day"
? styles.dayHeader ? styles.dayHeader
: styles.otherDayHeader; : styles.otherDayHeader;
}, [selectedDate, mode]); }, [selectedDate, mode]);
const memoizedHeaderContentStyle = useMemo(() => { const memoizedHeaderContentStyle = useMemo(() => {
if (mode === "day") { if (mode === "day") {
return styles.dayModeHeader; return styles.dayModeHeader;
} else if (mode === "week") { } else if (mode === "week") {
return styles.weekModeHeader; return styles.weekModeHeader;
} else if (mode === "month") { } else if (mode === "month") {
return styles.monthModeHeader; return styles.monthModeHeader;
} else { } else {
return {}; return {};
} }
}, [mode]); }, [mode]);
const memoizedEvents = useMemo(() => {
const startOffset = mode === "month" ? 40 : mode === "week" ? 10 : 1;
const endOffset = mode === "month" ? 40 : mode === "week" ? 10 : 1;
return events?.filter(event => const { enrichedEvents, filteredEvents } = useMemo(() => {
event.start && event.end && const startTime = Date.now(); // Start timer
isWithinInterval(event.start, { start: subDays(selectedDate, startOffset), end: addDays(selectedDate, endOffset) }) &&
isWithinInterval(event.end, { start: subDays(selectedDate, startOffset), end: addDays(selectedDate, endOffset) }) const startOffset = mode === "month" ? 40 : mode === "week" ? 10 : 1;
) ?? []; const endOffset = mode === "month" ? 40 : mode === "week" ? 10 : 1;
}, [events, selectedDate, mode]);
const filteredEvents = events?.filter(event =>
event.start && event.end &&
isWithinInterval(event.start, {
start: subDays(selectedDate, startOffset),
end: addDays(selectedDate, endOffset)
}) &&
isWithinInterval(event.end, {
start: subDays(selectedDate, startOffset),
end: addDays(selectedDate, endOffset)
})
) ?? [];
const enrichedEvents = filteredEvents.reduce((acc, event) => {
const dateKey = event.start.toISOString().split('T')[0];
acc[dateKey] = acc[dateKey] || [];
acc[dateKey].push({
...event,
overlapPosition: false,
overlapCount: 0
});
// Sort events for this dateKey from oldest to newest by event.start
acc[dateKey].sort((a, b) => compareAsc(a.start, b.start));
return acc;
}, {} as Record<string, CalendarEvent[]>);
const endTime = Date.now(); // End timer
console.log("memoizedEvents computation time:", endTime - startTime, "ms");
return { enrichedEvents, filteredEvents };
}, [events, selectedDate, mode]);
const renderCustomDateForMonth = (date: Date) => { const renderCustomDateForMonth = (date: Date) => {
const circleStyle = useMemo<ViewStyle>( const circleStyle = useMemo<ViewStyle>(
() => ({ () => ({
width: 30, width: 30,
height: 30, height: 30,
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
borderRadius: 15, borderRadius: 15,
}), }),
[] []
); );
const defaultStyle = useMemo<ViewStyle>( const defaultStyle = useMemo<ViewStyle>(
() => ({ () => ({
...circleStyle, ...circleStyle,
}), }),
[circleStyle] [circleStyle]
); );
const currentDateStyle = useMemo<ViewStyle>( const currentDateStyle = useMemo<ViewStyle>(
() => ({ () => ({
...circleStyle, ...circleStyle,
backgroundColor: "#4184f2", backgroundColor: "#4184f2",
}), }),
[circleStyle] [circleStyle]
); );
const renderDate = useCallback( const renderDate = useCallback(
(date: Date) => { (date: Date) => {
const isCurrentDate = isSameDate(todaysDate, date); const isCurrentDate = isSameDate(todaysDate, date);
const appliedStyle = isCurrentDate ? currentDateStyle : defaultStyle; const appliedStyle = isCurrentDate ? currentDateStyle : defaultStyle;
return ( return (
<View style={{ alignItems: "center" }}> <View style={{alignItems: "center"}}>
<View style={appliedStyle}> <View style={appliedStyle}>
<Text style={{ color: isCurrentDate ? "white" : "black" }}> <Text style={{color: isCurrentDate ? "white" : "black"}}>
{date.getDate()} {date.getDate()}
</Text> </Text>
</View> </View>
</View> </View>
); );
}, },
[todaysDate, currentDateStyle, defaultStyle] // dependencies [todaysDate, currentDateStyle, defaultStyle] // dependencies
); );
return renderDate(date); return renderDate(date);
}; };
useEffect(() => { useEffect(() => {
setOffsetMinutes(getTotalMinutes()); setOffsetMinutes(getTotalMinutes());
}, [events, mode]); }, [events, mode]);
if (isLoading || isRendering) { if (isLoading || isRendering) {
return ( return (
<View style={styles.loadingContainer}> <View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#0000ff" /> <ActivityIndicator size="large" color="#0000ff"/>
</View> </View>
); );
} }
return ( // console.log(enrichedEvents, filteredEvents)
<Calendar
bodyContainerStyle={styles.calHeader}
swipeEnabled
enableEnrichedEvents
mode={mode}
events={memoizedEvents}
eventCellStyle={memoizedEventCellStyle}
onPressEvent={handlePressEvent}
weekStartsOn={memoizedWeekStartsOn}
height={calendarHeight}
activeDate={todaysDate}
date={selectedDate}
onPressCell={handlePressCell}
headerContentStyle={memoizedHeaderContentStyle}
onSwipeEnd={handleSwipeEnd}
scrollOffsetMinutes={offsetMinutes}
theme={{
palette: {
nowIndicator: profileData?.eventColor || "#fd1575",
gray: {
"100": "#e8eaed",
"200": "#e8eaed",
"500": "#b7b7b7",
"800": "#919191",
},
},
typography: {
fontFamily: "PlusJakartaSans_500Medium",
sm: { fontFamily: "Manrope_600SemiBold", fontSize: 15 },
xl: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
},
moreLabel: {},
xs: { fontSize: 10 },
},
}}
dayHeaderStyle={dateStyle}
dayHeaderHighlightColor={"white"}
// renderCustomDateForMonth={renderCustomDateForMonth}
showAdjacentMonths
hourStyle={styles.hourStyle}
ampm
return (
<Calendar
bodyContainerStyle={styles.calHeader}
swipeEnabled
mode={mode}
enableEnrichedEvents={true}
sortedMonthView
enrichedEventsByDate={enrichedEvents}
events={filteredEvents}
// eventCellStyle={memoizedEventCellStyle}
onPressEvent={handlePressEvent}
weekStartsOn={memoizedWeekStartsOn}
height={calendarHeight}
activeDate={todaysDate}
date={selectedDate}
onPressCell={handlePressCell}
headerContentStyle={memoizedHeaderContentStyle}
onSwipeEnd={handleSwipeEnd}
scrollOffsetMinutes={offsetMinutes}
theme={{
palette: {
nowIndicator: profileData?.eventColor || "#fd1575",
gray: {
"100": "#e8eaed",
"200": "#e8eaed",
"500": "#b7b7b7",
"800": "#919191",
},
},
typography: {
fontFamily: "PlusJakartaSans_500Medium",
sm: {fontFamily: "Manrope_600SemiBold", fontSize: 15},
xl: {
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 16,
},
moreLabel: {},
xs: {fontSize: 10},
},
}}
dayHeaderStyle={dateStyle}
dayHeaderHighlightColor={"white"}
showAdjacentMonths
hourStyle={styles.hourStyle}
ampm
// renderCustomDateForMonth={renderCustomDateForMonth}
/> />
); );
} }
); );
const styles = StyleSheet.create({ const styles = StyleSheet.create({
segmentslblStyle: { segmentslblStyle: {
fontSize: 12, fontSize: 12,
fontFamily: "Manrope_600SemiBold", fontFamily: "Manrope_600SemiBold",
}, },
calHeader: { calHeader: {
borderWidth: 0, borderWidth: 0,
}, },
dayModeHeader: { dayModeHeader: {
alignSelf: "flex-start", alignSelf: "flex-start",
justifyContent: "space-between", justifyContent: "space-between",
alignContent: "center", alignContent: "center",
width: 38, width: 38,
right: 42, right: 42,
height: 13, height: 13,
}, },
weekModeHeader: {}, weekModeHeader: {},
monthModeHeader: {}, monthModeHeader: {},
loadingContainer: { loadingContainer: {
flex: 1, flex: 1,
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
}, },
dayHeader: { dayHeader: {
backgroundColor: "#4184f2", backgroundColor: "#4184f2",
aspectRatio: 1, aspectRatio: 1,
borderRadius: 100, borderRadius: 100,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}, },
otherDayHeader: { otherDayHeader: {
backgroundColor: "transparent", backgroundColor: "transparent",
color: "#919191", color: "#919191",
aspectRatio: 1, aspectRatio: 1,
borderRadius: 100, borderRadius: 100,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}, },
hourStyle: { hourStyle: {
color: "#5f6368", color: "#5f6368",
fontSize: 12, fontSize: 12,
fontFamily: "Manrope_500Medium", fontFamily: "Manrope_500Medium",
}, },
}); });

View File

@ -10,5 +10,7 @@ export interface CalendarEvent {
eventColor?: string; // Optional color to represent the event eventColor?: string; // Optional color to represent the event
participants?: string[]; // Optional list of participants or attendees participants?: string[]; // Optional list of participants or attendees
private?: boolean; private?: boolean;
notes?: string notes?: string,
overlapPosition?: number
overlapCount?: number
} }

View File

@ -28,7 +28,7 @@ import CircledXIcon from "@/assets/svgs/CircledXIcon";
import ProfileIcon from "@/assets/svgs/ProfileIcon"; import ProfileIcon from "@/assets/svgs/ProfileIcon";
import NavToDosIcon from "@/assets/svgs/NavToDosIcon"; import NavToDosIcon from "@/assets/svgs/NavToDosIcon";
import Ionicons from "@expo/vector-icons/Ionicons"; import Ionicons from "@expo/vector-icons/Ionicons";
import { PreviousNextView } from "react-native-keyboard-manager"; import KeyboardManager, { PreviousNextView } from "react-native-keyboard-manager";
const MyGroup = () => { const MyGroup = () => {
const [showAddUserDialog, setShowAddUserDialog] = useState(false); const [showAddUserDialog, setShowAddUserDialog] = useState(false);
@ -100,12 +100,17 @@ const MyGroup = () => {
} }
}; };
useEffect(() => {
KeyboardManager.setEnableAutoToolbar(true);
},[])
useEffect(() => { useEffect(() => {
setFirstName(""); setFirstName("");
setLastName(""); setLastName("");
setEmail(""); setEmail("");
}, []); }, []);
// @ts-ignore // @ts-ignore
return ( return (
<View style={{ flex: 1, minHeight: 500 }}> <View style={{ flex: 1, minHeight: 500 }}>

2353
firebase/functions/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@ -450,7 +450,7 @@
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = com.cally.app; PRODUCT_BUNDLE_IDENTIFIER = com.cally.app;
PRODUCT_NAME = "Cally"; PRODUCT_NAME = Cally;
SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -484,7 +484,7 @@
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = com.cally.app; PRODUCT_BUNDLE_IDENTIFIER = com.cally.app;
PRODUCT_NAME = "Cally"; PRODUCT_NAME = Cally;
SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";

View File

@ -133,6 +133,7 @@
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
</array> </array>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>SplashScreen</string> <string>SplashScreen</string>

View File

@ -21,7 +21,8 @@
"prebuild": "npx expo prebuild -p ios", "prebuild": "npx expo prebuild -p ios",
"prebuild-build-submit-ios": "yarn run prebuild && yarn run build-ios && yarn run submit", "prebuild-build-submit-ios": "yarn run prebuild && yarn run build-ios && yarn run submit",
"prebuild-build-submit-ios-cicd": "yarn build-ios-cicd", "prebuild-build-submit-ios-cicd": "yarn build-ios-cicd",
"prebuild-build-submit-cicd": "yarn build-cicd" "prebuild-build-submit-cicd": "yarn build-cicd",
"postinstall": "patch-package"
}, },
"jest": { "jest": {
"preset": "jest-expo" "preset": "jest-expo"
@ -69,11 +70,12 @@
"firebase-functions": "^5.1.0", "firebase-functions": "^5.1.0",
"fuzzysort": "^3.0.2", "fuzzysort": "^3.0.2",
"jotai": "^2.9.1", "jotai": "^2.9.1",
"patch-package": "^8.0.0",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-native": "0.74.3", "react-native": "0.74.3",
"react-native-app-auth": "^8.0.0", "react-native-app-auth": "^8.0.0",
"react-native-big-calendar": "^4.14.0", "react-native-big-calendar": "^4.15.1",
"react-native-calendars": "^1.1306.0", "react-native-calendars": "^1.1306.0",
"react-native-element-dropdown": "^2.12.2", "react-native-element-dropdown": "^2.12.2",
"react-native-gesture-handler": "~2.16.1", "react-native-gesture-handler": "~2.16.1",
@ -102,6 +104,7 @@
"@types/react-test-renderer": "^18.0.7", "@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1", "jest": "^29.2.1",
"jest-expo": "~51.0.3", "jest-expo": "~51.0.3",
"postinstall-postinstall": "^2.1.0",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"typescript": "~5.3.3" "typescript": "~5.3.3"
}, },

View File

@ -0,0 +1,186 @@
diff --git a/node_modules/react-native-big-calendar/build/index.js b/node_modules/react-native-big-calendar/build/index.js
index 848ceba..57fbaed 100644
--- a/node_modules/react-native-big-calendar/build/index.js
+++ b/node_modules/react-native-big-calendar/build/index.js
@@ -9,6 +9,17 @@ var isoWeek = require('dayjs/plugin/isoWeek');
var React = require('react');
var reactNative = require('react-native');
var calendarize = require('calendarize');
+var {
+ startOfDay,
+ endOfDay,
+ startOfWeek,
+ isAfter,
+ isBefore,
+ isSameDay,
+ differenceInDays,
+ add,
+ getTime
+} = require('date-fns');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -1000,87 +1011,91 @@ function _CalendarBodyForMonthView(_a) {
var start = _a.start, end = _a.end;
return day.isBetween(dayjs__default["default"](start).startOf('day'), dayjs__default["default"](end).endOf('day'), null, '[)');
});
- }
- else {
- /**
- * Better way to sort overlapping events that spans accross multiple days
- * For example, if you want following events
- * Event 1, start = 01/01 12:00, end = 02/01 12:00
- * Event 2, start = 02/01 12:00, end = 03/01 12:00
- * Event 3, start = 03/01 12:00, end = 04/01 12:00
- *
- * When drawing calendar in month view, event 3 should be placed at 3rd index for 03/01, because Event 2 are placed at 2nd index for 02/01 and 03/01
- *
- */
- var min_1 = day.startOf('day'), max_1 = day.endOf('day');
- //filter all events that starts from the current week until the current day, and sort them by reverse starting time
- var filteredEvents_1 = events
- .filter(function (_a) {
- var start = _a.start, end = _a.end;
- return dayjs__default["default"](end).isAfter(day.startOf('week')) && dayjs__default["default"](start).isBefore(max_1);
- })
- .sort(function (a, b) {
- if (dayjs__default["default"](a.start).isSame(b.start, 'day')) {
- var aDuration = dayjs__default["default"].duration(dayjs__default["default"](a.end).diff(dayjs__default["default"](a.start))).days();
- var bDuration = dayjs__default["default"].duration(dayjs__default["default"](b.end).diff(dayjs__default["default"](b.start))).days();
- return aDuration - bDuration;
- }
- return b.start.getTime() - a.start.getTime();
+ } else {
+ // Convert day once and cache all the commonly used dates/times
+ const jsDay = day?.toDate?.() || day;
+ const weekStart = startOfWeek(jsDay);
+ var min_1 = startOfDay(jsDay);
+ var max_1 = endOfDay(jsDay);
+ const max1Time = getTime(max_1);
+ const min1Time = getTime(min_1);
+
+ // Pre-process events with dates and cache timestamps
+ const processedEvents = events.map(event => {
+ const startDay = event.start?.toDate?.() || new Date(event.start);
+ const endDay = event.end?.toDate?.() || new Date(event.end);
+ return {
+ ...event,
+ startDay,
+ endDay,
+ startTime: getTime(startDay),
+ endTime: getTime(endDay),
+ startDayStart: startOfDay(startDay)
+ };
});
- /**
- * find the most relevant min date to filter the events
- * in the example:
- * 1. when rendering for 01/01, min date will be 01/01 (start of day for event 1)
- * 2. when rendering for 02/01, min date will be 01/01 (start of day for event 1)
- * 3. when rendering for 03/01, min date will be 01/01 (start of day for event 1)
- * 4. when rendering for 04/01, min date will be 01/01 (start of day for event 1)
- * 5. when rendering for 05/01, min date will be 05/01 (no event overlaps with 05/01)
- */
- filteredEvents_1.forEach(function (_a) {
- var start = _a.start, end = _a.end;
- if (dayjs__default["default"](end).isAfter(min_1) && dayjs__default["default"](start).isBefore(min_1)) {
- min_1 = dayjs__default["default"](start).startOf('day');
+
+ // Filter events within the weekly range and sort by reverse start time
+ let filteredEvents_1 = processedEvents
+ .filter(({ startTime, endTime }) =>
+ endTime > getTime(weekStart) && startTime < max1Time
+ )
+ .sort((a, b) => {
+ if (isSameDay(a.startDay, b.startDay)) {
+ // Pre-calculate durations since they're used in sorting
+ const aDuration = differenceInDays(a.endDay, a.startDay);
+ const bDuration = differenceInDays(b.endDay, b.startDay);
+ return bDuration - aDuration;
+ }
+ return b.startTime - a.startTime;
+ });
+
+ // Update min_1 to the earliest startDay for overlapping events
+ for (const event of filteredEvents_1) {
+ if (event.endTime > min1Time && event.startTime < min1Time) {
+ min_1 = event.startDayStart;
+ break; // We only need the first one due to the sort order
}
- });
+ }
+
+ // Filter to keep only events that overlap the min to max range, then reverse
+ const min1TimeUpdated = getTime(min_1);
filteredEvents_1 = filteredEvents_1
- .filter(function (_a) {
- var start = _a.start, end = _a.end;
- return dayjs__default["default"](end).endOf('day').isAfter(min_1) && dayjs__default["default"](start).isBefore(max_1);
- })
+ .filter(({ startTime, endDay }) =>
+ getTime(endOfDay(endDay)) > min1TimeUpdated && startTime < max1Time
+ )
.reverse();
- /**
- * We move eligible event to the top
- * For example, when rendering for 03/01, Event 3 should be moved to the top, since there is a gap left by Event 1
- */
- var finalEvents_1 = [];
- var tmpDay_1 = day.startOf('week');
- //re-sort events from the start of week until the calendar cell date
- //optimize sorting of event nodes and make sure that no empty gaps are left on top of calendar cell
- while (!tmpDay_1.isAfter(day)) {
- filteredEvents_1.forEach(function (event) {
- if (dayjs__default["default"](event.end).isBefore(tmpDay_1.startOf('day'))) {
- var eventToMoveUp = filteredEvents_1.find(function (e) {
- return dayjs__default["default"](e.start).startOf('day').isSame(tmpDay_1.startOf('day'));
- });
- if (eventToMoveUp != undefined) {
- //remove eventToMoveUp from finalEvents first
- if (finalEvents_1.indexOf(eventToMoveUp) > -1) {
- finalEvents_1.splice(finalEvents_1.indexOf(eventToMoveUp), 1);
- }
- if (finalEvents_1.indexOf(event) > -1) {
- finalEvents_1.splice(finalEvents_1.indexOf(event), 1, eventToMoveUp);
- }
- else {
+
+ // Move eligible events to the top, preventing duplicate entries
+ const finalEvents_1 = [];
+ const seenEvents = new Set(); // Use Set for faster lookups
+ let tmpDay_1 = weekStart;
+
+ while (!isAfter(tmpDay_1, jsDay)) {
+ const tmpDayTime = getTime(tmpDay_1);
+
+ for (const event of filteredEvents_1) {
+ const eventEndDayTime = getTime(startOfDay(event.endDay));
+
+ if (!seenEvents.has(event)) {
+ if (eventEndDayTime < tmpDayTime) {
+ // Find event starting on tmpDay
+ const eventToMoveUp = filteredEvents_1.find(e =>
+ isSameDay(e.startDayStart, tmpDay_1)
+ );
+ if (eventToMoveUp && !seenEvents.has(eventToMoveUp)) {
finalEvents_1.push(eventToMoveUp);
+ seenEvents.add(eventToMoveUp);
}
+ } else {
+ finalEvents_1.push(event);
+ seenEvents.add(event);
}
}
- else if (finalEvents_1.indexOf(event) == -1) {
- finalEvents_1.push(event);
- }
- });
- tmpDay_1 = tmpDay_1.add(1, 'day');
+ }
+ tmpDay_1 = add(tmpDay_1, { days: 1 });
}
+
+ console.log(finalEvents_1);
return finalEvents_1;
}
}, [events, sortedMonthView]);

View File

@ -3183,6 +3183,11 @@
resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz" resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz"
integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g== integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==
"@yarnpkg/lockfile@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
"@zxing/text-encoding@0.9.0": "@zxing/text-encoding@0.9.0":
version "0.9.0" version "0.9.0"
resolved "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz" resolved "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz"
@ -3982,7 +3987,7 @@ ci-info@^2.0.0:
resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz"
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
ci-info@^3.2.0, ci-info@^3.3.0: ci-info@^3.2.0, ci-info@^3.3.0, ci-info@^3.7.0:
version "3.9.0" version "3.9.0"
resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz"
integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
@ -4456,7 +4461,7 @@ date-fns@^3.6.0:
resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz" resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz"
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww== integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
dayjs@^1.11.10, dayjs@^1.8.15: dayjs@^1.11.13, dayjs@^1.8.15:
version "1.11.13" version "1.11.13"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz" resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
@ -5543,7 +5548,7 @@ find-up@^5.0.0, find-up@~5.0.0:
locate-path "^6.0.0" locate-path "^6.0.0"
path-exists "^4.0.0" path-exists "^4.0.0"
find-yarn-workspace-root@~2.0.0: find-yarn-workspace-root@^2.0.0, find-yarn-workspace-root@~2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz" resolved "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz"
integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
@ -7215,6 +7220,16 @@ json-schema-traverse@^1.0.0:
resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
json-stable-stringify@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454"
integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==
dependencies:
call-bind "^1.0.5"
isarray "^2.0.5"
jsonify "^0.0.1"
object-keys "^1.1.1"
json5@^1.0.1: json5@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz"
@ -7243,6 +7258,11 @@ jsonfile@^6.0.1:
optionalDependencies: optionalDependencies:
graceful-fs "^4.1.6" graceful-fs "^4.1.6"
jsonify@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==
jsonwebtoken@^9.0.0: jsonwebtoken@^9.0.0:
version "9.0.2" version "9.0.2"
resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz" resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz"
@ -7315,6 +7335,13 @@ kind-of@^6.0.0, kind-of@^6.0.1, kind-of@^6.0.2:
resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
klaw-sync@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c"
integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==
dependencies:
graceful-fs "^4.1.11"
kleur@^3.0.3: kleur@^3.0.3:
version "3.0.3" version "3.0.3"
resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz"
@ -8260,7 +8287,7 @@ open@^6.2.0:
dependencies: dependencies:
is-wsl "^1.1.0" is-wsl "^1.1.0"
open@^7.0.3: open@^7.0.3, open@^7.4.2:
version "7.4.2" version "7.4.2"
resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz" resolved "https://registry.npmjs.org/open/-/open-7.4.2.tgz"
integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
@ -8434,6 +8461,27 @@ password-prompt@^1.0.4:
ansi-escapes "^4.3.2" ansi-escapes "^4.3.2"
cross-spawn "^7.0.3" cross-spawn "^7.0.3"
patch-package@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61"
integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
chalk "^4.1.2"
ci-info "^3.7.0"
cross-spawn "^7.0.3"
find-yarn-workspace-root "^2.0.0"
fs-extra "^9.0.0"
json-stable-stringify "^1.0.2"
klaw-sync "^6.0.0"
minimist "^1.2.6"
open "^7.4.2"
rimraf "^2.6.3"
semver "^7.5.3"
slash "^2.0.0"
tmp "^0.0.33"
yaml "^2.2.2"
path-exists@^3.0.0: path-exists@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz"
@ -8559,6 +8607,11 @@ postcss@~8.4.32:
picocolors "^1.0.1" picocolors "^1.0.1"
source-map-js "^1.2.0" source-map-js "^1.2.0"
postinstall-postinstall@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3"
integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==
pretty-bytes@5.6.0: pretty-bytes@5.6.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz" resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz"
@ -8827,13 +8880,13 @@ react-native-base64@0.0.2:
resolved "https://registry.npmjs.org/react-native-base64/-/react-native-base64-0.0.2.tgz" resolved "https://registry.npmjs.org/react-native-base64/-/react-native-base64-0.0.2.tgz"
integrity sha512-Fu/J1a2y0X22EJDWqJR2oEa1fpP4gTFjYxk8ElJdt1Yak3HOXmFJ7EohLVHU2DaQkgmKfw8qb7u/48gpzveRbg== integrity sha512-Fu/J1a2y0X22EJDWqJR2oEa1fpP4gTFjYxk8ElJdt1Yak3HOXmFJ7EohLVHU2DaQkgmKfw8qb7u/48gpzveRbg==
react-native-big-calendar@^4.14.0: react-native-big-calendar@^4.15.1:
version "4.14.0" version "4.15.1"
resolved "https://registry.npmjs.org/react-native-big-calendar/-/react-native-big-calendar-4.14.0.tgz" resolved "https://registry.yarnpkg.com/react-native-big-calendar/-/react-native-big-calendar-4.15.1.tgz#9cfef290e40a51cbc59b1be4d065804b21f2f74f"
integrity sha512-EYCxqXnRAg8QWsW3Npq3JI/9+lXlo9o6Gri7WttQQSqE/cGkVrVeKXObpvN6Cc4qrIUvnc4cgLAeM/j4+bOb6g== integrity sha512-hNrzkM+9Kb2T0J/1fW9AMaeN+AuhakCfNtQPaQL29l3JXgOO14ikJ3iPqQkmNVbuiWYiMrpI25hrmXffiOVIgQ==
dependencies: dependencies:
calendarize "^1.1.1" calendarize "^1.1.1"
dayjs "^1.11.10" dayjs "^1.11.13"
react-native-calendars@^1.1306.0: react-native-calendars@^1.1306.0:
version "1.1306.0" version "1.1306.0"
@ -9303,6 +9356,13 @@ rimraf@3.0.2, rimraf@^3.0.2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
dependencies:
glob "^7.1.3"
rimraf@~2.6.2: rimraf@~2.6.2:
version "2.6.3" version "2.6.3"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz"
@ -9606,6 +9666,11 @@ sisteransi@^1.0.5:
resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz"
integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
slash@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
slash@^3.0.0: slash@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
@ -10931,6 +10996,11 @@ yaml@^2.2.1:
resolved "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz" resolved "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz"
integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==
yaml@^2.2.2:
version "2.6.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3"
integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==
yargs-parser@^18.1.2: yargs-parser@^18.1.2:
version "18.1.3" version "18.1.3"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz"