Merge remote-tracking branch 'origin/dev' into tablet

This commit is contained in:
ivic00
2024-11-10 13:54:23 +01:00
14 changed files with 1227 additions and 1081 deletions

View File

@ -6,6 +6,7 @@ import {useAtom, useSetAtom} from "jotai";
import {
editVisibleAtom,
eventForEditAtom,
isAllDayAtom,
modeAtom,
selectedDateAtom,
selectedNewEventDateAtom,
@ -34,6 +35,7 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
const [mode, setMode] = useAtom(modeAtom);
const setEditVisible = useSetAtom(editVisibleAtom);
const [isAllDay, setIsAllDay] = useAtom(isAllDayAtom);
const setEventForEdit = useSetAtom(eventForEditAtom);
const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom);
@ -67,6 +69,16 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
[mode, setSelectedNewEndDate, setSelectedDate]
);
const handlePressDayHeader = useCallback(
(date: Date) => {
setIsAllDay(true);
console.log(isAllDay);
setSelectedNewEndDate(date);
setEditVisible(true);
},
[setSelectedNewEndDate]
);
const handleSwipeEnd = useCallback(
(date: Date) => {
setSelectedDate(date);
@ -84,7 +96,10 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
[profileData]
);
console.log({memoizedWeekStartsOn, profileData: profileData?.firstDayOfWeek})
console.log({
memoizedWeekStartsOn,
profileData: profileData?.firstDayOfWeek,
});
const isSameDate = useCallback((date1: Date, date2: Date) => {
return (
@ -117,32 +132,34 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
}
}, [mode]);
const { enrichedEvents, filteredEvents } = useMemo(() => {
const startTime = Date.now(); // Start timer
const startOffset = mode === "month" ? 40 : mode === "week" ? 10 : 1;
const endOffset = mode === "month" ? 40 : mode === "week" ? 10 : 1;
const filteredEvents = events?.filter(event =>
event.start && event.end &&
const filteredEvents =
events?.filter(
(event) =>
event.start &&
event.end &&
isWithinInterval(event.start, {
start: subDays(selectedDate, startOffset),
end: addDays(selectedDate, endOffset)
end: addDays(selectedDate, endOffset),
}) &&
isWithinInterval(event.end, {
start: subDays(selectedDate, startOffset),
end: addDays(selectedDate, endOffset)
end: addDays(selectedDate, endOffset),
})
) ?? [];
const enrichedEvents = filteredEvents.reduce((acc, event) => {
const dateKey = event.start.toISOString().split('T')[0];
const dateKey = event.start.toISOString().split("T")[0];
acc[dateKey] = acc[dateKey] || [];
acc[dateKey].push({
...event,
overlapPosition: false,
overlapCount: 0
overlapCount: 0,
});
acc[dateKey].sort((a, b) => compareAsc(a.start, b.start));
@ -151,7 +168,11 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
}, {} as Record<string, CalendarEvent[]>);
const endTime = Date.now();
console.log("memoizedEvents computation time:", endTime - startTime, "ms");
console.log(
"memoizedEvents computation time:",
endTime - startTime,
"ms"
);
return { enrichedEvents, filteredEvents };
}, [events, selectedDate, mode]);
@ -262,6 +283,7 @@ export const EventCalendar: React.FC<EventCalendarProps> = React.memo(
dayHeaderHighlightColor={"white"}
showAdjacentMonths
hourStyle={styles.hourStyle}
onPressDateHeader={handlePressDayHeader}
ampm
// renderCustomDateForMonth={renderCustomDateForMonth}
/>

View File

@ -29,8 +29,12 @@ import LockIcon from "@/assets/svgs/LockIcon";
import MenuIcon from "@/assets/svgs/MenuIcon";
import CameraIcon from "@/assets/svgs/CameraIcon";
import AssigneesDisplay from "@/components/shared/AssigneesDisplay";
import {useAtom} from "jotai";
import {eventForEditAtom, selectedNewEventDateAtom,} from "@/components/pages/calendar/atoms";
import { useAtom, useAtomValue } from "jotai";
import {
eventForEditAtom,
selectedNewEventDateAtom,
isAllDayAtom,
} from "@/components/pages/calendar/atoms";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import BinIcon from "@/assets/svgs/BinIcon";
import DeleteEventDialog from "./DeleteEventDialog";
@ -53,8 +57,9 @@ export const ManuallyAddEventModal = () => {
selectedNewEventDateAtom
);
const [editEvent, setEditEvent] = useAtom(eventForEditAtom);
const [allDayAtom, setAllDayAtom] = useAtom(isAllDayAtom);
const [deleteModalVisible, setDeleteModalVisible] = useState<boolean>(false);
const {mutateAsync: deleteEvent, isLoading: isDeleting} = useDeleteEvent()
const { mutateAsync: deleteEvent, isLoading: isDeleting } = useDeleteEvent();
const { show, close, initialDate } = {
show: !!selectedNewEventDate || !!editEvent,
@ -74,22 +79,51 @@ export const ManuallyAddEventModal = () => {
const [isPrivate, setIsPrivate] = useState<boolean>(
editEvent?.private || false
);
useEffect(() => {
console.log(allDayAtom);
return () => {
setAllDayAtom(false);
};
}, []);
const [startTime, setStartTime] = useState(() => {
const date = initialDate ?? new Date();
date.setSeconds(0, 0);
if (
date.getMinutes() > 0 ||
date.getSeconds() > 0 ||
date.getMilliseconds() > 0
) {
date.setHours(date.getHours() + 1);
}
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
});
const [endTime, setEndTime] = useState(() => {
if (editEvent?.end) {
const date = new Date(editEvent.end);
date.setSeconds(0, 0);
return date;
}
const date =
editEvent?.end ?? initialDate
? addHours(editEvent?.end ?? initialDate!, 1)
: addHours(new Date(), 1);
date.setSeconds(0, 0);
const baseDate = editEvent?.end ?? initialDate ?? new Date();
const date = new Date(baseDate);
if (
date.getMinutes() > 0 ||
date.getSeconds() > 0 ||
date.getMilliseconds() > 0
) {
date.setHours(date.getHours() + 1);
}
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
date.setHours(date.getHours() + 1);
return date;
});
const [startDate, setStartDate] = useState(initialDate ?? new Date());
@ -101,35 +135,57 @@ export const ManuallyAddEventModal = () => {
);
const [repeatInterval, setRepeatInterval] = useState<PickerMultiValue>([]);
const {mutateAsync: createEvent, isLoading: isAdding, isError} = useCreateEvent();
const {
mutateAsync: createEvent,
isLoading: isAdding,
isError,
} = useCreateEvent();
const { data: members } = useGetFamilyMembers(true);
const titleRef = useRef<TextFieldRef>(null)
const titleRef = useRef<TextFieldRef>(null);
const isLoading = isDeleting || isAdding
const isLoading = isDeleting || isAdding;
useEffect(() => {
setTitle(editEvent?.title || "");
setDetails(editEvent?.notes || "");
setIsAllDay(editEvent?.allDay || false);
setIsPrivate(editEvent?.private || false);
setStartTime(() => {
const date = initialDate ?? new Date();
date.setSeconds(0, 0);
const date = new Date(initialDate ?? new Date());
const minutes = date.getMinutes();
date.setMinutes(0, 0, 0);
if (minutes >= 30) {
date.setHours(date.getHours() + 1);
}
return date;
});
setEndTime(() => {
if (editEvent?.end) {
const date = new Date(editEvent.end);
date.setSeconds(0, 0);
return date;
}
const date =
editEvent?.end ?? initialDate
? addHours(editEvent?.end ?? initialDate!, 1)
: addHours(new Date(), 1);
date.setSeconds(0, 0);
const baseDate = editEvent?.end ?? initialDate ?? new Date();
const date = new Date(baseDate);
if (
date.getMinutes() > 0 ||
date.getSeconds() > 0 ||
date.getMilliseconds() > 0
) {
date.setHours(date.getHours() + 1);
}
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
date.setHours(date.getHours() + 1);
return date;
});
setStartDate(initialDate ?? new Date());
setEndDate(editEvent?.end ?? initialDate ?? new Date());
setSelectedAttendees(editEvent?.participants ?? []);
@ -139,7 +195,7 @@ export const ManuallyAddEventModal = () => {
useEffect(() => {
if (show && !editEvent) {
setTimeout(() => {
titleRef?.current?.focus()
titleRef?.current?.focus();
}, 500);
}
}, [selectedNewEventDate]);
@ -160,8 +216,8 @@ export const ManuallyAddEventModal = () => {
};
const handleDeleteEvent = async () => {
await deleteEvent({eventId: `${editEvent?.id}`})
close()
await deleteEvent({ eventId: `${editEvent?.id}` });
close();
};
const hideDeleteEventModal = () => {
@ -246,7 +302,10 @@ export const ManuallyAddEventModal = () => {
onRequestClose={close}
transparent={false}
>
<LoaderScreen message={isDeleting ? "Deleting event..." : "Saving event..."} color={Colors.grey40}/>
<LoaderScreen
message={isDeleting ? "Deleting event..." : "Saving event..."}
color={Colors.grey40}
/>
</Modal>
);
}
@ -345,7 +404,6 @@ export const ManuallyAddEventModal = () => {
/>
)}
</View>
</View>
{/*)}*/}
<ScrollView style={{ minHeight: "85%" }}>

View File

@ -2,6 +2,7 @@ import { atom } from "jotai";
import { CalendarEvent } from "@/components/pages/calendar/interfaces";
export const editVisibleAtom = atom<boolean>(false);
export const isAllDayAtom = atom<boolean>(false);
export const eventForEditAtom = atom<CalendarEvent | undefined>(undefined);
export const isFamilyViewAtom = atom<boolean>(false);
export const modeAtom = atom<"week" | "month" | "day">("week");

View File

@ -1,4 +1,4 @@
import {AntDesign, Ionicons} from "@expo/vector-icons";
import {Ionicons} from "@expo/vector-icons";
import React, {useCallback, useState} from "react";
import {Button, Checkbox, Text, View} from "react-native-ui-lib";
import {ActivityIndicator, ScrollView, StyleSheet} from "react-native";
@ -10,7 +10,6 @@ import AppleIcon from "@/assets/svgs/AppleIcon";
import GoogleIcon from "@/assets/svgs/GoogleIcon";
import OutlookIcon from "@/assets/svgs/OutlookIcon";
import ExpoLocalization from "expo-localization/src/ExpoLocalization";
import {colorMap} from "@/constants/colorMap";
import {useSetAtom} from "jotai";
import {settingsPageIndex} from "../calendar/atoms";
import CalendarSettingsDialog from "./calendar_components/CalendarSettingsDialog";
@ -53,13 +52,6 @@ const CalendarSettingsPage = () => {
setModalVisible(false);
};
const [selectedColor, setSelectedColor] = useState<string>(
profileData?.eventColor ?? colorMap.pink
);
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(
profileData?.eventColor ?? colorMap.pink
);
const {mutateAsync: updateUserData} = useUpdateUserData();
const {mutateAsync: clearToken} = useClearTokens();
@ -78,22 +70,6 @@ const CalendarSettingsPage = () => {
fetchAndSaveAppleEvents
} = useCalSync()
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 debouncedUpdateFirstDayOfWeek = useCallback(
debounce(async (firstDayOfWeek: string) => {
try {
@ -114,12 +90,6 @@ const CalendarSettingsPage = () => {
debouncedUpdateFirstDayOfWeek(firstDayOfWeek);
};
const handleChangeColor = (color: string) => {
setPreviousSelectedColor(selectedColor);
setSelectedColor(color);
debouncedUpdateUserData(color);
};
return (
<ScrollView>
<TouchableOpacity onPress={() => setPageIndex(0)}>
@ -140,52 +110,6 @@ const CalendarSettingsPage = () => {
</TouchableOpacity>
<View marginH-30 marginB-30>
<Text style={styles.subTitle}>Calendar settings</Text>
<View style={styles.card}>
<Text style={styles.cardTitle} marginB-14>
Event Color Preference
</Text>
<View row spread>
<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={() => handleChangeColor(colorMap.orange)}
>
<View style={styles.colorBox} backgroundColor={colorMap.orange}>
{selectedColor == colorMap.orange && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<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={() => handleChangeColor(colorMap.teal)}>
<View style={styles.colorBox} backgroundColor={colorMap.teal}>
{selectedColor == colorMap.teal && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.purple)}
>
<View style={styles.colorBox} backgroundColor={colorMap.purple}>
{selectedColor == colorMap.purple && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
</View>
</View>
<View style={styles.card}>
<Text style={styles.cardTitle}>Weekly Start Date</Text>
<View row marginV-5 marginT-20>

View File

@ -25,7 +25,7 @@ const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
containerStyle={styles.dialog}
>
<View centerH>
<Feather name="alert-triangle" size={70} color="#FF5449" />
<Feather name="alert-triangle" size={70} color="#ff1637" />
</View>
<Text center style={styles.title}>
Are you sure?
@ -101,7 +101,7 @@ const DeleteProfileDialogs: React.FC<ConfirmationDialogProps> = ({
// Empty stylesheet for future styles
const styles = StyleSheet.create({
confirmBtn: {
backgroundColor: "#FF5449",
backgroundColor: "#ff1637",
},
cancelBtn: {
backgroundColor: "white",

View File

@ -178,7 +178,7 @@ const MyGroup: React.FC<MyGroupProps> = ({onNewUserClick, setOnNewUserClick}) =>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
user={member}
/>
</View>
</Card>
@ -220,7 +220,7 @@ const MyGroup: React.FC<MyGroupProps> = ({onNewUserClick, setOnNewUserClick}) =>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
user={member}
/>
</Card>
))}
@ -259,7 +259,7 @@ const MyGroup: React.FC<MyGroupProps> = ({onNewUserClick, setOnNewUserClick}) =>
<UserMenu
setShowQRCodeDialog={(val) => setShowQRCodeDialog(val)}
showQRCodeDialog={showQRCodeDialog === member?.uid}
userId={member?.uid!}
user={member}
/>
</Card>
))}

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from "react";
import React, {useCallback, useEffect, useRef, useState} from "react";
import { StyleSheet, TouchableOpacity } from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import * as ImagePicker from "expo-image-picker";
@ -20,6 +20,7 @@ import { useUpdateUserData } from "@/hooks/firebase/useUpdateUserData";
import { useChangeProfilePicture } from "@/hooks/firebase/useChangeProfilePicture";
import { colorMap } from "@/constants/colorMap";
import DeleteProfileDialogs from "../user_components/DeleteProfileDialogs";
import {AntDesign} from "@expo/vector-icons";
const MyProfile = () => {
const { user, profileData } = useAuthContext();
@ -34,6 +35,13 @@ const MyProfile = () => {
string | ImagePicker.ImagePickerAsset | null
>(profileData?.pfp || null);
const [selectedColor, setSelectedColor] = useState<string>(
profileData?.eventColor ?? colorMap.pink
);
const [previousSelectedColor, setPreviousSelectedColor] = useState<string>(
profileData?.eventColor ?? colorMap.pink
);
const [showDeleteDialog, setShowDeleteDialog] = useState<boolean>(false);
const handleHideDeleteDialog = () => {
@ -102,6 +110,28 @@ const MyProfile = () => {
? profileImage.uri
: profileImage;
const handleChangeColor = (color: string) => {
setPreviousSelectedColor(selectedColor);
setSelectedColor(color);
debouncedUpdateUserData(color);
};
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),
[]
);
return (
<ScrollView style={{ paddingBottom: 20, flex: 1 }}>
<View style={styles.card}>
@ -125,8 +155,8 @@ const MyProfile = () => {
}}
>
<Text style={styles.pfpTxt}>
{user?.email?.at(0)}
{user?.email?.at(1)}
{profileData?.firstName?.at(0)}
{profileData?.lastName?.at(0)}
</Text>
</View>
)}
@ -215,9 +245,55 @@ const MyProfile = () => {
</Picker>
</View>
</View>
<View style={styles.card}>
<Text style={styles.cardTitle} marginB-14>
Color Preference
</Text>
<View row spread>
<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={() => handleChangeColor(colorMap.orange)}
>
<View style={styles.colorBox} backgroundColor={colorMap.orange}>
{selectedColor == colorMap.orange && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<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={() => handleChangeColor(colorMap.teal)}>
<View style={styles.colorBox} backgroundColor={colorMap.teal}>
{selectedColor == colorMap.teal && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={() => handleChangeColor(colorMap.purple)}
>
<View style={styles.colorBox} backgroundColor={colorMap.purple}>
{selectedColor == colorMap.purple && (
<AntDesign name="check" size={30} color="white"/>
)}
</View>
</TouchableOpacity>
</View>
</View>
<Button
size="large"
backgroundColor="#FF5449"
backgroundColor="#ff1637"
label="Delete Profile"
style={{ marginTop: 10 }}
labelStyle={{ fontFamily: "PlusJakartaSans_500Medium", fontSize: 15 }}
@ -229,7 +305,9 @@ const MyProfile = () => {
}}
visible={showDeleteDialog}
onDismiss={handleHideDeleteDialog}
onConfirm={() => {console.log('delete account here')}}
onConfirm={() => {
console.log("delete account here");
}}
/>
</ScrollView>
);
@ -246,6 +324,17 @@ const timeZoneItems = Object.keys(tz.zones)
));
const styles = StyleSheet.create({
cardTitle: {
fontFamily: "Manrope_500Medium",
fontSize: 15,
},
colorBox: {
aspectRatio: 1,
justifyContent: "center",
alignItems: "center",
width: 51,
borderRadius: 12,
},
card: {
marginVertical: 15,
backgroundColor: "white",

View File

@ -1,28 +1,35 @@
import React from 'react';
import {Button, Card, Dialog, Text, TouchableOpacity} from 'react-native-ui-lib';
import QRCode from 'react-native-qrcode-svg';
import React from "react";
import {
Button,
Card,
Dialog,
Text,
TouchableOpacity,
} from "react-native-ui-lib";
import QRCode from "react-native-qrcode-svg";
import { PanningDirectionsEnum } from "react-native-ui-lib/src/components/panningViews/panningProvider";
import Ionicons from "@expo/vector-icons/Ionicons";
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import { StyleSheet } from "react-native";
import { ProfileType } from "@/contexts/AuthContext";
const UserMenu = ({
userId,
user,
showQRCodeDialog,
setShowQRCodeDialog
setShowQRCodeDialog,
}: {
userId: string,
showQRCodeDialog: boolean,
setShowQRCodeDialog: (value: string | boolean) => void
user: UserProfile;
showQRCodeDialog: boolean;
setShowQRCodeDialog: (value: string | boolean) => void;
}) => {
const handleShowQRCode = () => {
setShowQRCodeDialog(userId);
setShowQRCodeDialog(user.uid!);
};
return (
<>
<TouchableOpacity
onPress={handleShowQRCode}
>
<TouchableOpacity onPress={handleShowQRCode}>
<Ionicons name="qr-code-outline" size={24} color="black" />
</TouchableOpacity>
@ -32,14 +39,26 @@ const UserMenu = ({
panDirection={PanningDirectionsEnum.DOWN}
>
<Card padding-20 center>
<Text center marginB-10 style={{fontSize: 16, maxWidth: "80%"}}>Ask your family to download the app
and then scan the
QR Code to join the family group:
<Text
center
marginT-15
marginH-15
marginB-25
style={{ fontSize: 18, fontFamily: "Manrope_500Medium" }}
>
{user.userType !== ProfileType.FAMILY_DEVICE
? `Open Cally on ${user.firstName}'s device and scan the code to link it to your family group`
: "Open Cally on the family device and scan the code to link it to your family group"}
</Text>
<QRCode value={userId} size={150}/>
<QRCode value={user.uid!} size={150} />
<Button
marginT-20
style={styles.button}
label="Close"
labelStyle={{
fontFamily: "PlusJakartaSans_500Medium",
fontSize: 15,
}}
onPress={() => setShowQRCodeDialog(false)}
/>
</Card>
@ -48,4 +67,12 @@ const UserMenu = ({
);
};
const styles = StyleSheet.create({
button: {
backgroundColor: "#d9d9d9",
width: 117,
height: 47,
},
});
export default UserMenu;

View File

@ -25,6 +25,7 @@ import CalendarIcon from "@/assets/svgs/CalendarIcon";
import ClockOIcon from "@/assets/svgs/ClockOIcon";
import ProfileIcon from "@/assets/svgs/ProfileIcon";
import RepeatFreq from "./RepeatFreq";
import {useAuthContext} from "@/contexts/AuthContext";
interface IAddChoreDialog {
isVisible: boolean;
@ -44,6 +45,7 @@ const defaultTodo = {
};
const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => {
const {user} = useAuthContext()
const {addToDo, updateToDo} = useToDosContext();
const [todo, setTodo] = useState<IToDo>(
addChoreDialogProps.selectedTodo ?? defaultTodo
@ -57,6 +59,11 @@ const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => {
const titleRef = useRef<TextFieldRef>(null)
const {data: members} = useGetFamilyMembers();
let sortedMembers = members?.sort((a, b) => {
if (a.uid === user?.uid) return -1;
if (b.uid === user?.uid) return 1;
return 0;
})
const handleClose = () => {
setTodo(defaultTodo);
@ -272,7 +279,7 @@ const AddChoreDialog = (addChoreDialogProps: IAddChoreDialog) => {
/>
)}
>
{members?.map((member) => (
{sortedMembers?.map((member) => (
<Picker.Item
key={member.uid}
label={member?.firstName + " " + member?.lastName}

View File

@ -111,7 +111,7 @@ const ToDoItem = (props: {
height={0.7}
width={"100%"}
style={{
backgroundColor: props.item.done ? "#b8b8b8" : "#e7e7e7",
backgroundColor: "#e7e7e7",
}}
centerH
/>

View File

@ -9,7 +9,7 @@ import { useGetChildrenByParentId } from "@/hooks/firebase/useGetChildrenByParen
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import { child } from "@react-native-firebase/storage";
import CachedImage from 'expo-cached-image'
import CachedImage from "expo-cached-image";
const HeaderTemplate = (props: {
message: string;
@ -71,7 +71,10 @@ const HeaderTemplate = (props: {
useEffect(() => {
if (members) {
const childrenMembers = members.filter(
(member) => member.userType === ProfileType.CHILD
(member) =>
member.userType === ProfileType.CHILD ||
member.userType === ProfileType.CAREGIVER ||
member.userType === ProfileType.PARENT
);
setChildren(childrenMembers);
}
@ -81,10 +84,15 @@ const HeaderTemplate = (props: {
<View row centerV marginV-15 style={styles.bottomMarg}>
{profileData?.pfp ? (
<View>
<CachedImage source={{ uri: profileData.pfp, }} style={styles.pfp} cacheKey={profileData.pfp}/>
<CachedImage
source={{ uri: profileData.pfp }}
style={styles.pfp}
cacheKey={profileData.pfp}
/>
{isFamilyView && props.isCalendar && (
<View style={styles.childrenPfpArr} row>
{children?.slice(0, 3).map((child, index) => {
const bgColor: string = child.eventColor || colorMap.pink;
return child.pfp ? (
<Image
source={{ uri: child.pfp }}
@ -92,7 +100,10 @@ const HeaderTemplate = (props: {
/>
) : (
<View
style={[styles.childrenPfp, { left: index * 19 }]}
style={[
styles.childrenPfp,
{ left: index * 19, backgroundColor: bgColor },
]}
center
>
<Text style={{ color: "white" }}>
@ -104,7 +115,15 @@ const HeaderTemplate = (props: {
})}
{children?.length > 3 && (
<View style={[styles.childrenPfp, { left: 3 * 19 }]} center>
<Text style={{ color: "white", fontFamily: "Manrope_600SemiBold", fontSize: 12 }}>+{children.length - 3}</Text>
<Text
style={{
color: "white",
fontFamily: "Manrope_600SemiBold",
fontSize: 12,
}}
>
+{children.length - 3}
</Text>
</View>
)}
</View>
@ -113,8 +132,8 @@ const HeaderTemplate = (props: {
) : (
<View style={styles.pfp} center>
<Text style={styles.pfpTxt}>
{user?.email?.at(0)}
{user?.email?.at(1)}
{profileData?.firstName?.at(0)}
{profileData?.lastName?.at(0)}
</Text>
</View>
)}

View File

@ -13,7 +13,7 @@ const PointsSlider = (props: {
value={props.points}
onValueChange={(value) => props.setPoints(value)}
minimumValue={0}
step={10}
step={5}
thumbTintColor="white"
minimumTrackTintColor="#91d5ff"
thumbStyle={{borderWidth: 3, borderColor: '#91d5ff'}}
@ -21,7 +21,7 @@ const PointsSlider = (props: {
/>
<View row spread>
<Text style={{fontSize: 13, color: '#858585'}}>0</Text>
<Text style={{fontSize: 13, color: '#858585'}}>50</Text>
<Text style={{fontSize: 13, color: '#858585', marginLeft: 15}}>50</Text>
<Text style={{fontSize: 13, color: '#858585'}}>100</Text>
</View>
</View>

View File

@ -61,9 +61,8 @@ export const useCreateTodo = () => {
dates.push(newDate);
});
// TODO: for the next 52 weeks
let index = 1;
for (let i = 0; i < 4; i++) {
for (let i = 0; i < 52; i++) {
dates?.forEach((dateToAdd) => {
index ++;
let newTodoDate = addWeeks(dateToAdd, i);

View File

@ -73,7 +73,7 @@ export const useUpdateTodo = () => {
dates.push(newDate);
});
let todosToAddCycles = 4;
let todosToAddCycles = 52;
if (firstTodo?.repeatType === REPEAT_TYPE.EVERY_WEEK) {
todosToAddCycles = filteredTodos?.length / firstTodo?.repeatDays?.length;
}