mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
@ -159,6 +159,8 @@ export default function TabLayout() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View marginR-16 row centerV>
|
<View marginR-16 row centerV>
|
||||||
|
{Device.deviceType === DeviceType.TABLET && isCalendarPage && <View flex-1 center><CalendarHeader />
|
||||||
|
</View>}
|
||||||
{isCalendarPage && (
|
{isCalendarPage && (
|
||||||
<View marginR-16><RefreshButton onRefresh={onRefresh} isSyncing={isLoading} /></View>
|
<View marginR-16><RefreshButton onRefresh={onRefresh} isSyncing={isLoading} /></View>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -9,7 +9,9 @@ import {useFormattedEvents} from "@/components/pages/calendar/useFormattedEvents
|
|||||||
import {useCalendarControls} from "@/components/pages/calendar/useCalendarControls";
|
import {useCalendarControls} from "@/components/pages/calendar/useCalendarControls";
|
||||||
import {EventCell} from "@/components/pages/calendar/EventCell";
|
import {EventCell} from "@/components/pages/calendar/EventCell";
|
||||||
import {isToday} from "date-fns";
|
import {isToday} from "date-fns";
|
||||||
import {View} from "react-native-ui-lib";
|
import { View } from "react-native-ui-lib";
|
||||||
|
import { DeviceType } from "expo-device";
|
||||||
|
import * as Device from "expo-device"
|
||||||
import {useAtomCallback} from 'jotai/utils'
|
import {useAtomCallback} from 'jotai/utils'
|
||||||
|
|
||||||
interface EventCalendarProps {
|
interface EventCalendarProps {
|
||||||
@ -112,7 +114,7 @@ export const DetailedCalendar: React.FC<EventCalendarProps> = React.memo((
|
|||||||
{...bodyProps}
|
{...bodyProps}
|
||||||
renderEvent={renderEvent}
|
renderEvent={renderEvent}
|
||||||
/>
|
/>
|
||||||
<View marginB-0/>
|
{Device.deviceType === DeviceType.TABLET && <View style={{backgroundColor: 'white', height: '9%', width: '100%'}}/>}
|
||||||
</CalendarContainer>
|
</CalendarContainer>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -255,7 +255,7 @@ export const MonthCalendar: React.FC<EventCalendarProps> = React.memo(
|
|||||||
ampm
|
ampm
|
||||||
// renderCustomDateForMonth={renderCustomDateForMonth}
|
// renderCustomDateForMonth={renderCustomDateForMonth}
|
||||||
/>
|
/>
|
||||||
{/*<View style={{backgroundColor: 'white', height: 50, width: '100%'}}/>*/}
|
{Device.deviceType === DeviceType.TABLET && <View style={{backgroundColor: 'white', height: '9%', width: '100%'}}/>}
|
||||||
</>
|
</>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,33 +1,43 @@
|
|||||||
import { Text, TextField, TextFieldRef, View } from "react-native-ui-lib";
|
import { Text, TextField, TextFieldRef, View } from "react-native-ui-lib";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { GroceryCategory, useGroceryContext } from "@/contexts/GroceryContext";
|
import { GroceryCategory, GroceryFrequency, useGroceryContext } from "@/contexts/GroceryContext";
|
||||||
import { Dropdown } from "react-native-element-dropdown";
|
import { Dropdown } from "react-native-element-dropdown";
|
||||||
import CloseXIcon from "@/assets/svgs/CloseXIcon";
|
import CloseXIcon from "@/assets/svgs/CloseXIcon";
|
||||||
import { findNodeHandle, StyleSheet, UIManager } from "react-native";
|
import {Alert, findNodeHandle, StyleSheet, UIManager} from "react-native";
|
||||||
import DropdownIcon from "@/assets/svgs/DropdownIcon";
|
import DropdownIcon from "@/assets/svgs/DropdownIcon";
|
||||||
import { AntDesign } from "@expo/vector-icons";
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
|
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
|
||||||
|
import { IGrocery } from "@/hooks/firebase/types/groceryData";
|
||||||
|
|
||||||
interface IEditGrocery {
|
const defaultGroceryItem = {
|
||||||
id?: string;
|
id: "",
|
||||||
title: string;
|
title: "",
|
||||||
category: GroceryCategory;
|
category: GroceryCategory.None,
|
||||||
setTitle: (value: string) => void;
|
approved: false,
|
||||||
setCategory?: (category: GroceryCategory) => void;
|
recurring: false,
|
||||||
setSubmit?: (value: boolean) => void;
|
frequency: GroceryFrequency.Never,
|
||||||
closeEdit?: () => void;
|
bought: false,
|
||||||
handleEditSubmit?: Function;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const EditGroceryItem = ({
|
const EditGroceryItem = ({
|
||||||
editGrocery,
|
editGrocery,
|
||||||
onInputFocus,
|
onInputFocus,
|
||||||
|
closeEdit
|
||||||
}: {
|
}: {
|
||||||
editGrocery: IEditGrocery;
|
editGrocery?: IGrocery;
|
||||||
onInputFocus: (y: number) => void;
|
onInputFocus: (y: number) => void;
|
||||||
|
closeEdit?: Function
|
||||||
}) => {
|
}) => {
|
||||||
const { fuzzyMatchGroceryCategory } = useGroceryContext();
|
const { fuzzyMatchGroceryCategory } = useGroceryContext();
|
||||||
const inputRef = useRef<TextFieldRef>(null);
|
const inputRef = useRef<TextFieldRef>(null);
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
|
const { profileData } = useAuthContext();
|
||||||
|
const {
|
||||||
|
updateGroceryItem,
|
||||||
|
addGrocery,
|
||||||
|
} = useGroceryContext();
|
||||||
|
|
||||||
|
const [grocery, setGrocery] = useState(editGrocery ?? defaultGroceryItem);
|
||||||
|
|
||||||
const handleFocus = () => {
|
const handleFocus = () => {
|
||||||
if (containerRef.current) {
|
if (containerRef.current) {
|
||||||
@ -57,29 +67,47 @@ const EditGroceryItem = ({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setGrocery(defaultGroceryItem);
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
inputRef?.current?.blur();
|
if (validateGrocery()) {
|
||||||
if (editGrocery.setSubmit) {
|
if (grocery?.id === "") {
|
||||||
editGrocery.setSubmit(true);
|
addGrocery({...grocery, approved: profileData?.userType === ProfileType.PARENT || profileData?.userType === ProfileType.CAREGIVER});
|
||||||
|
} else {
|
||||||
|
updateGroceryItem(grocery);
|
||||||
|
}
|
||||||
|
setGrocery(defaultGroceryItem);
|
||||||
|
if (closeEdit) {
|
||||||
|
closeEdit();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const validateGrocery = () => {
|
||||||
|
if (!grocery?.title || grocery?.title === "") {
|
||||||
|
Alert.alert('Alert', 'Title field cannot be empty');
|
||||||
|
return false;
|
||||||
|
} else if (grocery.title?.length < 3 || grocery.title?.length > 25) {
|
||||||
|
Alert.alert('Alert', 'Title should be between 3 and 25 characters');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grocery?.category || grocery?.category === "") {
|
||||||
|
Alert.alert('Alert', 'Category cannot be empty');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (editGrocery.handleEditSubmit) {
|
|
||||||
editGrocery.handleEditSubmit({
|
|
||||||
id: editGrocery.id,
|
|
||||||
title: editGrocery.title,
|
|
||||||
category: editGrocery.category,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (editGrocery.closeEdit) {
|
|
||||||
editGrocery.closeEdit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (inputRef.current) {
|
if (inputRef.current) {
|
||||||
inputRef.current.focus();
|
inputRef.current.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(editGrocery.category);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -100,37 +128,36 @@ const EditGroceryItem = ({
|
|||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
onFocus={handleFocus}
|
onFocus={handleFocus}
|
||||||
placeholder="Grocery"
|
placeholder="Grocery"
|
||||||
value={editGrocery.title}
|
value={grocery?.title}
|
||||||
onSubmitEditing={handleSubmit}
|
onSubmitEditing={handleSubmit}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
returnKeyType="done"
|
returnKeyType="done"
|
||||||
onChangeText={(value) => {
|
onChangeText={(value) => {
|
||||||
editGrocery.setTitle(value);
|
|
||||||
let groceryCategory = fuzzyMatchGroceryCategory(value);
|
let groceryCategory = fuzzyMatchGroceryCategory(value);
|
||||||
if (editGrocery.setCategory) {
|
setGrocery((oldData) => ({...oldData, title: value, category: groceryCategory}));
|
||||||
editGrocery.setCategory(groceryCategory);
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
maxLength={25}
|
maxLength={25}
|
||||||
/>
|
/>
|
||||||
{(editGrocery.title || editGrocery.title !== "") && <View row centerV>
|
{(grocery?.title !== "") &&
|
||||||
<AntDesign
|
<View row centerV>
|
||||||
name="check"
|
{grocery.title?.length > 2 && grocery.title?.length <= 25 &&
|
||||||
size={24}
|
<AntDesign
|
||||||
style={{
|
name="check"
|
||||||
color: "green",
|
size={24}
|
||||||
marginRight: 15,
|
style={{
|
||||||
}}
|
color: "green",
|
||||||
onPress={handleSubmit}
|
marginRight: 15,
|
||||||
/>
|
}}
|
||||||
<CloseXIcon
|
onPress={handleSubmit}
|
||||||
onPress={() => {
|
/>
|
||||||
if (editGrocery.closeEdit) {
|
|
||||||
editGrocery.closeEdit();
|
|
||||||
}
|
}
|
||||||
}}
|
<CloseXIcon
|
||||||
/>
|
onPress={() => {
|
||||||
</View>}
|
handleClose();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
</View>
|
</View>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
style={{ marginTop: 15 }}
|
style={{ marginTop: 15 }}
|
||||||
@ -143,7 +170,7 @@ const EditGroceryItem = ({
|
|||||||
}}
|
}}
|
||||||
labelField="label"
|
labelField="label"
|
||||||
valueField="value"
|
valueField="value"
|
||||||
value={editGrocery.category}
|
value={grocery?.category ?? GroceryCategory.None}
|
||||||
iconColor="white"
|
iconColor="white"
|
||||||
activeColor={"#fd1775"}
|
activeColor={"#fd1775"}
|
||||||
containerStyle={styles.dropdownStyle}
|
containerStyle={styles.dropdownStyle}
|
||||||
@ -154,7 +181,7 @@ const EditGroceryItem = ({
|
|||||||
<DropdownIcon
|
<DropdownIcon
|
||||||
style={{ marginRight: 8 }}
|
style={{ marginRight: 8 }}
|
||||||
color={
|
color={
|
||||||
editGrocery.category == GroceryCategory.None
|
grocery?.category == GroceryCategory.None
|
||||||
? "#7b7b7b"
|
? "#7b7b7b"
|
||||||
: "#fd1775"
|
: "#fd1775"
|
||||||
}
|
}
|
||||||
@ -168,17 +195,7 @@ const EditGroceryItem = ({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onChange={(item) => {
|
onChange={(item) => {
|
||||||
if (editGrocery.handleEditSubmit) {
|
setGrocery((oldData) => ({...oldData, category: item.value}));
|
||||||
editGrocery.handleEditSubmit({
|
|
||||||
id: editGrocery.id,
|
|
||||||
category: item.value,
|
|
||||||
});
|
|
||||||
if (editGrocery.closeEdit) editGrocery.closeEdit();
|
|
||||||
} else {
|
|
||||||
if (editGrocery.setCategory) {
|
|
||||||
editGrocery.setCategory(item.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Checkbox, Text, TouchableOpacity, View } from "react-native-ui-lib";
|
import { Checkbox, Text, TouchableOpacity, View } from "react-native-ui-lib";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { AntDesign } from "@expo/vector-icons";
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
import { GroceryCategory, useGroceryContext } from "@/contexts/GroceryContext";
|
import { useGroceryContext } from "@/contexts/GroceryContext";
|
||||||
import EditGroceryFrequency from "./EditGroceryFrequency";
|
import EditGroceryFrequency from "./EditGroceryFrequency";
|
||||||
import EditGroceryItem from "./EditGroceryItem";
|
import EditGroceryItem from "./EditGroceryItem";
|
||||||
import { ImageBackground, StyleSheet } from "react-native";
|
import { ImageBackground, StyleSheet } from "react-native";
|
||||||
@ -32,10 +32,6 @@ const GroceryItem = ({
|
|||||||
|
|
||||||
const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false);
|
const [openFreqEdit, setOpenFreqEdit] = useState<boolean>(false);
|
||||||
const [isEditingTitle, setIsEditingTitle] = useState<boolean>(false);
|
const [isEditingTitle, setIsEditingTitle] = useState<boolean>(false);
|
||||||
const [newTitle, setNewTitle] = useState<string>(item.title ?? "");
|
|
||||||
const [category, setCategory] = useState<GroceryCategory>(
|
|
||||||
item.category ?? GroceryCategory.None
|
|
||||||
);
|
|
||||||
|
|
||||||
const closeEdit = () => setIsEditingTitle(false);
|
const closeEdit = () => setIsEditingTitle(false);
|
||||||
|
|
||||||
@ -72,15 +68,9 @@ const GroceryItem = ({
|
|||||||
|
|
||||||
{isEditingTitle ? (
|
{isEditingTitle ? (
|
||||||
<EditGroceryItem
|
<EditGroceryItem
|
||||||
editGrocery={{
|
editGrocery={item}
|
||||||
id: item.id,
|
|
||||||
title: newTitle,
|
|
||||||
category: category,
|
|
||||||
setTitle: setNewTitle,
|
|
||||||
setCategory: setCategory,
|
|
||||||
closeEdit: closeEdit,
|
|
||||||
}}
|
|
||||||
onInputFocus={onInputFocus}
|
onInputFocus={onInputFocus}
|
||||||
|
closeEdit={closeEdit}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<View flex>
|
<View flex>
|
||||||
|
|||||||
@ -2,11 +2,10 @@ import { ActivityIndicator, Dimensions, FlatList, StyleSheet } from "react-nativ
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Text, TouchableOpacity, View } from "react-native-ui-lib";
|
import { Text, TouchableOpacity, View } from "react-native-ui-lib";
|
||||||
import GroceryItem from "./GroceryItem";
|
import GroceryItem from "./GroceryItem";
|
||||||
import { GroceryCategory, GroceryFrequency, useGroceryContext } from "@/contexts/GroceryContext";
|
import { useGroceryContext } from "@/contexts/GroceryContext";
|
||||||
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
||||||
import { AntDesign } from "@expo/vector-icons";
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
import EditGroceryItem from "./EditGroceryItem";
|
import EditGroceryItem from "./EditGroceryItem";
|
||||||
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
|
|
||||||
import { IGrocery } from "@/hooks/firebase/types/groceryData";
|
import { IGrocery } from "@/hooks/firebase/types/groceryData";
|
||||||
import Ionicons from '@expo/vector-icons/Ionicons';
|
import Ionicons from '@expo/vector-icons/Ionicons';
|
||||||
import AddChoreDialog from "@/components/pages/todos/AddChoreDialog";
|
import AddChoreDialog from "@/components/pages/todos/AddChoreDialog";
|
||||||
@ -28,24 +27,14 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
|
|||||||
const {
|
const {
|
||||||
groceries,
|
groceries,
|
||||||
updateGroceryItem,
|
updateGroceryItem,
|
||||||
isAddingGrocery,
|
|
||||||
setIsAddingGrocery,
|
|
||||||
addGrocery,
|
|
||||||
} = useGroceryContext();
|
} = useGroceryContext();
|
||||||
|
|
||||||
const { profileData } = useAuthContext();
|
|
||||||
const [approvedGroceries, setApprovedGroceries] = useState<IGrocery[]>(
|
const [approvedGroceries, setApprovedGroceries] = useState<IGrocery[]>(
|
||||||
groceries?.filter((item) => item.approved)
|
groceries?.filter((item) => item.approved)
|
||||||
);
|
);
|
||||||
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
|
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
|
||||||
groceries?.filter((item) => !item.approved)
|
groceries?.filter((item) => !item.approved)
|
||||||
);
|
);
|
||||||
const [category, setCategory] = useState<GroceryCategory>(
|
|
||||||
GroceryCategory.None
|
|
||||||
);
|
|
||||||
|
|
||||||
const [title, setTitle] = useState<string>("");
|
|
||||||
const [submit, setSubmitted] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const [pendingVisible, setPendingVisible] = useState<boolean>(true);
|
const [pendingVisible, setPendingVisible] = useState<boolean>(true);
|
||||||
const [approvedVisible, setApprovedVisible] = useState<boolean>(true);
|
const [approvedVisible, setApprovedVisible] = useState<boolean>(true);
|
||||||
@ -74,37 +63,11 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (submit) {
|
|
||||||
if (title?.length > 2 && title?.length <= 25) {
|
|
||||||
addGrocery({
|
|
||||||
id: "",
|
|
||||||
title: title,
|
|
||||||
category: category,
|
|
||||||
approved: profileData?.userType === ProfileType.PARENT || profileData?.userType === ProfileType.CAREGIVER,
|
|
||||||
recurring: false,
|
|
||||||
frequency: GroceryFrequency.Never,
|
|
||||||
bought: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
setIsAddingGrocery(false);
|
|
||||||
setSubmitted(false);
|
|
||||||
setTitle("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [submit]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setApprovedGroceries(groceries?.filter((item) => item.approved));
|
setApprovedGroceries(groceries?.filter((item) => item.approved));
|
||||||
setPendingGroceries(groceries?.filter((item) => !item.approved));
|
setPendingGroceries(groceries?.filter((item) => !item.approved));
|
||||||
}, [groceries]);
|
}, [groceries]);
|
||||||
|
|
||||||
const handleCancelAddGrocery = () => {
|
|
||||||
setIsAddingGrocery(false);
|
|
||||||
setTitle("");
|
|
||||||
setCategory(GroceryCategory.None)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!groceries &&
|
{!groceries &&
|
||||||
@ -260,14 +223,6 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
|
|||||||
</View>
|
</View>
|
||||||
<View style={{marginTop: 8}}>
|
<View style={{marginTop: 8}}>
|
||||||
<EditGroceryItem
|
<EditGroceryItem
|
||||||
editGrocery={{
|
|
||||||
title: title,
|
|
||||||
setCategory: setCategory,
|
|
||||||
category: category,
|
|
||||||
setTitle: setTitle,
|
|
||||||
setSubmit: setSubmitted,
|
|
||||||
closeEdit: handleCancelAddGrocery
|
|
||||||
}}
|
|
||||||
onInputFocus={onInputFocus}
|
onInputFocus={onInputFocus}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Dimensions, ScrollView, Keyboard, Platform } from "react-native";
|
import { Dimensions, ScrollView, Keyboard, Platform } from "react-native";
|
||||||
import { View } from "react-native-ui-lib";
|
import { View } from "react-native-ui-lib";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import AddGroceryItem from "./AddGroceryItem";
|
|
||||||
import GroceryList from "./GroceryList";
|
import GroceryList from "./GroceryList";
|
||||||
import { useGroceryContext } from "@/contexts/GroceryContext";
|
import { useGroceryContext } from "@/contexts/GroceryContext";
|
||||||
|
|
||||||
|
|||||||
@ -77,7 +77,7 @@ const ToDosPage = () => {
|
|||||||
{pageIndex == 2 && <UserChoresProgress setPageIndex={setPageIndex} />}
|
{pageIndex == 2 && <UserChoresProgress setPageIndex={setPageIndex} />}
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<AddChore />
|
{pageIndex === 0 && <AddChore />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,78 +1,74 @@
|
|||||||
import React from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import { BarChart } from "react-native-gifted-charts";
|
import { BarChart } from "react-native-gifted-charts";
|
||||||
|
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
|
||||||
|
|
||||||
const FamilyChart = () => {
|
const FamilyChart = ({ children }: {
|
||||||
// Define the data for the bars
|
children: Array<UserProfile>;
|
||||||
const data = [
|
}) => {
|
||||||
{
|
const [dataList, setDataList] = useState([]);
|
||||||
value: 600, // Total value of the bar
|
|
||||||
stacks: [
|
useEffect(() => {
|
||||||
{ value: 290, color: "#e7d526" }, // First part of the bar
|
let dayPointsMap = {
|
||||||
{ value: 310, color: "#00a8b6" }, // Second part of the bar
|
Monday: {},
|
||||||
],
|
Tuesday: {},
|
||||||
label: "M",
|
Wednesday: {},
|
||||||
},
|
Thursday: {},
|
||||||
{
|
Friday: {},
|
||||||
value: 400,
|
Saturday: {},
|
||||||
stacks: [
|
Sunday: {},
|
||||||
{ value: 190, color: "#e7d526" },
|
};
|
||||||
{ value: 210, color: "#00a8b6" },
|
children?.forEach((child) => {
|
||||||
],
|
let weeklyDayPoints = child.weeklyDayPoints || {
|
||||||
label: "Tu",
|
Monday: 0,
|
||||||
},
|
Tuesday: 0,
|
||||||
{
|
Wednesday: 0,
|
||||||
value: 400,
|
Thursday: 0,
|
||||||
stacks: [
|
Friday: 0,
|
||||||
{ value: 210, color: "#e7d526" },
|
Saturday: 0,
|
||||||
{ value: 190, color: "#00a8b6" },
|
Sunday: 0,
|
||||||
],
|
};
|
||||||
label: "W",
|
|
||||||
},
|
Object.keys(weeklyDayPoints).forEach((day) => {
|
||||||
{
|
dayPointsMap = {
|
||||||
value: 800,
|
...dayPointsMap,
|
||||||
stacks: [
|
[day]: {
|
||||||
{ value: 410, color: "#e7d526" },
|
...dayPointsMap[day],
|
||||||
{ value: 390, color: "#00a8b6" },
|
[child.uid]: weeklyDayPoints[day]
|
||||||
],
|
}
|
||||||
label: "Th",
|
}
|
||||||
},
|
})
|
||||||
{
|
})
|
||||||
value: 600,
|
|
||||||
stacks: [
|
const data = Object.keys(dayPointsMap).map((day) => {
|
||||||
{ value: 220, color: "#e7d526" },
|
const userMap = dayPointsMap[day];
|
||||||
{ value: 380, color: "#00a8b6" },
|
let stacks = Object.keys(userMap).map((userId) => {
|
||||||
],
|
|
||||||
label: "F",
|
let userProfile = children?.find((child) => child.uid === userId);
|
||||||
},
|
return {
|
||||||
{
|
value: userMap[userId],
|
||||||
value: 200,
|
color: userProfile.eventColor
|
||||||
stacks: [
|
}
|
||||||
{ value: 160, color: "#e7d526" },
|
});
|
||||||
{ value: 40, color: "#00a8b6" },
|
|
||||||
],
|
return {
|
||||||
label: "Sa",
|
stacks: stacks,
|
||||||
},
|
label: day,
|
||||||
{
|
}
|
||||||
value: 200,
|
});
|
||||||
stacks: [
|
setDataList(data);
|
||||||
{ value: 160, color: "#e7d526" },
|
}, [children])
|
||||||
{ value: 40, color: "#00a8b6" },
|
|
||||||
],
|
|
||||||
label: "Su",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BarChart
|
<BarChart
|
||||||
stackData={data}
|
stackData={dataList}
|
||||||
width={250}
|
width={250}
|
||||||
height={150} // Height of the chart
|
height={150} // Height of the chart
|
||||||
barWidth={20} // Width of each bar
|
barWidth={20} // Width of each bar
|
||||||
noOfSections={5} // Number of horizontal sections (for 0 to 1000 in steps of 200)
|
noOfSections={5} // Number of horizontal sections (for 0 to 1000 in steps of 200)
|
||||||
maxValue={1000} // Max value on the chart
|
maxValue={500} // Max value on the chart
|
||||||
stepValue={200} // Step size for horizontal lines
|
stepValue={100} // Step size for horizontal lines
|
||||||
yAxisThickness={0} // Hide the Y-axis line
|
yAxisThickness={0} // Hide the Y-axis line
|
||||||
yAxisLabelTexts={["0", "200", "400", "600", "800", "1000"]} // Custom Y-axis labels
|
// yAxisLabelTexts={["0", "100", "200", "300", "400", "500"]} // Custom Y-axis labels
|
||||||
hideRules={false} // Show the horizontal lines
|
hideRules={false} // Show the horizontal lines
|
||||||
rulesType="solid"
|
rulesType="solid"
|
||||||
rulesThickness={1.2}
|
rulesThickness={1.2}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { View, Text } from "react-native-ui-lib";
|
import { View, Text } from "react-native-ui-lib";
|
||||||
import React from "react";
|
import React, {useCallback} from "react";
|
||||||
import { ImageBackground, StyleSheet } from "react-native";
|
import { ImageBackground, StyleSheet } from "react-native";
|
||||||
import FamilyChart from "./FamilyChart";
|
import FamilyChart from "./FamilyChart";
|
||||||
import { TouchableOpacity } from "react-native-ui-lib/src/incubator";
|
import { TouchableOpacity } from "react-native-ui-lib/src/incubator";
|
||||||
@ -7,17 +7,25 @@ import { Ionicons } from "@expo/vector-icons";
|
|||||||
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
|
import { useGetFamilyMembers } from "@/hooks/firebase/useGetFamilyMembers";
|
||||||
import { ProfileType } from "@/contexts/AuthContext";
|
import { ProfileType } from "@/contexts/AuthContext";
|
||||||
import { ScrollView } from "react-native-gesture-handler";
|
import { ScrollView } from "react-native-gesture-handler";
|
||||||
|
import {useFocusEffect} from "@react-navigation/core";
|
||||||
|
import {UserProfile} from "@/hooks/firebase/types/profileTypes";
|
||||||
|
|
||||||
const FamilyChoresProgress = ({
|
const FamilyChoresProgress = ({
|
||||||
setPageIndex,
|
setPageIndex,
|
||||||
}: {
|
}: {
|
||||||
setPageIndex: (value: number) => void;
|
setPageIndex: (value: number) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { data: familyMembers } = useGetFamilyMembers();
|
const { data: familyMembers, refetch: refetchFamilyMembers } = useGetFamilyMembers();
|
||||||
const children = familyMembers?.filter(
|
const children = familyMembers?.filter(
|
||||||
(member) => member.userType === ProfileType.CHILD
|
(member) => member.userType === ProfileType.CHILD
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
refetchFamilyMembers();
|
||||||
|
}, [refetchFamilyMembers])
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View marginT-20 marginH-5 marginB-100>
|
<View marginT-20 marginH-5 marginB-100>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
@ -47,35 +55,37 @@ const FamilyChoresProgress = ({
|
|||||||
Points earned this week
|
Points earned this week
|
||||||
</Text>
|
</Text>
|
||||||
<View row>
|
<View row>
|
||||||
{children?.map((child, index) => (
|
{children?.map((child: UserProfile) => {
|
||||||
<View
|
return child.weeklyPoints && child.weeklyPoints > 0 ? (
|
||||||
key={child.uid}
|
<View
|
||||||
style={styles.pfpSmall}
|
key={child.uid}
|
||||||
backgroundColor={child.eventColor || "#05a8b6"}
|
style={styles.pfpSmall}
|
||||||
center
|
backgroundColor={child.eventColor || "#05a8b6"}
|
||||||
>
|
center
|
||||||
{child.pfp ? (
|
>
|
||||||
<ImageBackground
|
{child.pfp ? (
|
||||||
source={{ uri: child.pfp }}
|
<ImageBackground
|
||||||
style={{
|
source={{ uri: child.pfp }}
|
||||||
height: 25,
|
style={{
|
||||||
aspectRatio: 1,
|
height: 25,
|
||||||
borderRadius: 22,
|
aspectRatio: 1,
|
||||||
overflow: "hidden",
|
borderRadius: 22,
|
||||||
}}
|
overflow: "hidden",
|
||||||
/>
|
}}
|
||||||
) : (
|
/>
|
||||||
<Text color="white" style={{fontSize: 15}}>
|
) : (
|
||||||
{child.firstName.at(0)}
|
<Text color="white" style={{fontSize: 15}}>
|
||||||
{child.lastName.at(0)}
|
{child.firstName.at(0)}
|
||||||
</Text>
|
{child.lastName.at(0)}
|
||||||
)}
|
</Text>
|
||||||
</View>
|
)}
|
||||||
))}
|
</View>
|
||||||
|
) : null
|
||||||
|
})}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.card} paddingL-10>
|
<View style={styles.card} paddingL-10>
|
||||||
<FamilyChart />
|
<FamilyChart children={children} />
|
||||||
</View>
|
</View>
|
||||||
<Text
|
<Text
|
||||||
text70
|
text70
|
||||||
|
|||||||
@ -31,13 +31,13 @@ const UserChoresProgress = ({
|
|||||||
style={{fontFamily: "Poppins_400Regular", fontSize: 14.71}}
|
style={{fontFamily: "Poppins_400Regular", fontSize: 14.71}}
|
||||||
color="#979797"
|
color="#979797"
|
||||||
>
|
>
|
||||||
Return to To Do's
|
Return to To Dos
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View>
|
<View>
|
||||||
<Text style={{fontFamily: "Manrope_700Bold", fontSize: 20}}>
|
<Text style={{fontFamily: "Manrope_700Bold", fontSize: 20}}>
|
||||||
Your To Do's Progress Report
|
Your To Dos Progress Report
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View row spread marginT-25 marginB-5>
|
<View row spread marginT-25 marginB-5>
|
||||||
|
|||||||
@ -139,7 +139,8 @@ export const useUpdateTodo = () => {
|
|||||||
Saturday: 0,
|
Saturday: 0,
|
||||||
Sunday: 0,
|
Sunday: 0,
|
||||||
};
|
};
|
||||||
const currentDay = getCurrentDay();
|
|
||||||
|
const currentDay = getCurrentDay(todoUpdate.date);
|
||||||
const updatedPointsPerDay = todoData.done
|
const updatedPointsPerDay = todoData.done
|
||||||
? pointsPerDay[currentDay] + todoUpdate.points
|
? pointsPerDay[currentDay] + todoUpdate.points
|
||||||
: pointsPerDay[currentDay] - todoUpdate.points;
|
: pointsPerDay[currentDay] - todoUpdate.points;
|
||||||
@ -158,7 +159,7 @@ export const useUpdateTodo = () => {
|
|||||||
userData = {
|
userData = {
|
||||||
...userData,
|
...userData,
|
||||||
weeklyPoints: weeklyPoints >= 0 ? weeklyPoints : 0,
|
weeklyPoints: weeklyPoints >= 0 ? weeklyPoints : 0,
|
||||||
weeklyDayPoints: updatedPointsPerDay,
|
weeklyDayPoints: pointsPerDay,
|
||||||
allTimePoints: allTimePoints >= 0 ? allTimePoints : 0,
|
allTimePoints: allTimePoints >= 0 ? allTimePoints : 0,
|
||||||
weeklyCompletedTodos: weeklyCompletedTodos >= 0 ? weeklyCompletedTodos : 0
|
weeklyCompletedTodos: weeklyCompletedTodos >= 0 ? weeklyCompletedTodos : 0
|
||||||
}
|
}
|
||||||
@ -184,8 +185,8 @@ export const useUpdateTodo = () => {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCurrentDay = () => {
|
const getCurrentDay = (date) => {
|
||||||
|
let selectedDate = new Date(date.seconds * 1000);
|
||||||
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||||||
const now = new Date();
|
return days[selectedDate.getDay()];
|
||||||
return days[now.getDay()];
|
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user