- Implemented optimistic update when completing todos and groceries to avoid delays

This commit is contained in:
Dejan
2024-12-17 20:13:51 +01:00
parent 79ac1efe63
commit 4b67033aa8
4 changed files with 30 additions and 10 deletions

View File

@ -1,12 +1,11 @@
import { Checkbox, Text, TouchableOpacity, View } from "react-native-ui-lib";
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import { AntDesign } from "@expo/vector-icons";
import { GroceryCategory, useGroceryContext } from "@/contexts/GroceryContext";
import EditGroceryFrequency from "./EditGroceryFrequency";
import EditGroceryItem from "./EditGroceryItem";
import { ImageBackground, StyleSheet } from "react-native";
import { IGrocery } from "@/hooks/firebase/types/groceryData";
import { UserProfile } from "@/hooks/firebase/types/profileTypes";
import { ProfileType, useAuthContext } from "@/contexts/AuthContext";
import { useGetUserById } from "@/hooks/firebase/useGetUserById";
import { useDeleteGrocery } from "@/hooks/firebase/useDeleteGrocery";
@ -15,10 +14,14 @@ const GroceryItem = ({
item,
handleItemApproved,
onInputFocus,
approvedGroceries,
setApprovedGroceries
}: {
item: IGrocery;
handleItemApproved: (id: string, changes: Partial<IGrocery>) => void;
onInputFocus: (y: number) => void;
approvedGroceries?: Array<IGrocery>,
setApprovedGroceries?: Function
}) => {
const { updateGroceryItem } = useGroceryContext();
const { mutateAsync: deleteGrocery } = useDeleteGrocery();
@ -150,9 +153,11 @@ const GroceryItem = ({
borderRadius={50}
color="#fd1575"
hitSlop={20}
onValueChange={() =>
onValueChange={() => {
const updatedApprovedGroceries = approvedGroceries.map((grocery) => grocery.id === item.id ? {...grocery, bought: !item.bought} : grocery);
setApprovedGroceries(updatedApprovedGroceries);
updateGroceryItem({ id: item.id, bought: !item.bought })
}
}}
/>
</View>
)

View File

@ -33,7 +33,7 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
addGrocery,
} = useGroceryContext();
const {profileData} = useAuthContext();
const [approvedGroceries, setapprovedGroceries] = useState<IGrocery[]>(
const [approvedGroceries, setApprovedGroceries] = useState<IGrocery[]>(
groceries?.filter((item) => item.approved)
);
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
@ -94,7 +94,7 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
}, [submit]);
useEffect(() => {
setapprovedGroceries(groceries?.filter((item) => item.approved));
setApprovedGroceries(groceries?.filter((item) => item.approved));
setPendingGroceries(groceries?.filter((item) => !item.approved));
}, [groceries]);
@ -290,6 +290,8 @@ const GroceryList = ({onInputFocus}: {onInputFocus: (y: number) => void}) => {
updateGroceryItem({...changes, id: id})
}
onInputFocus={onInputFocus}
approvedGroceries={approvedGroceries}
setApprovedGroceries={setApprovedGroceries}
/>
)
)}

View File

@ -25,6 +25,8 @@ const ToDoItem = (props: {
item: IToDo;
isSettings?: boolean;
is7Days?: boolean;
localTodos: Array<IToDo>;
setLocalTodos: Function
}) => {
const { updateToDo } = useToDosContext();
const { data: members } = useGetFamilyMembers();
@ -131,6 +133,8 @@ const ToDoItem = (props: {
borderRadius={50}
color="#fd1575"
onValueChange={() => {
const updatedTodos = props.localTodos?.map((item) => item.id === props.item.id ? { ...item, done: !props.item.done } : item);
props.setLocalTodos(updatedTodos);
updateToDo({ id: props.item.id, done: !props.item.done });
if (!props.item.done && isChild) {
handleTodoClickAnimation();

View File

@ -110,6 +110,11 @@ const resolveFilterOptions = (members, user) => {
const ToDosList = ({ isSettings, members }: { isSettings?: boolean, members?: Array<UserProfile> }) => {
const { toDos } = useToDosContext();
const [localTodos, setLocalTodos] = useState([]);
useEffect(() => {
setLocalTodos(toDos);
}, [toDos]);
const [groupedToDos, setGroupedToDos] = useState([]);
const { user } = useAuthContext()
@ -131,18 +136,18 @@ const ToDosList = ({ isSettings, members }: { isSettings?: boolean, members?: Ar
}, [JSON.stringify(members)]);
useEffect(() => {
if (toDos && selectedFilter) {
if (localTodos && selectedFilter) {
let resolvedGroupedTodos;
if (selectedFilter?.value === FILTER_OPTIONS.EVERYONE) {
resolvedGroupedTodos = groupToDosByDate(toDos ?? []);
} else {
let filtered = toDos?.filter((todo) => todo.assignees?.includes(selectedFilter.value)) || [];
let filtered = localTodos?.filter((todo) => todo.assignees?.includes(selectedFilter.value)) || [];
resolvedGroupedTodos = groupToDosByDate(filtered || []);
}
setGroupedToDos(resolvedGroupedTodos || []);
}
}, [selectedFilter, JSON.stringify(toDos)]);
}, [selectedFilter, JSON.stringify(localTodos)]);
const toggleExpand = (dateKey: string) => {
setExpandedGroups((prev) => ({
@ -231,6 +236,8 @@ const ToDosList = ({ isSettings, members }: { isSettings?: boolean, members?: Ar
key={item.id}
item={item}
is7Days={false}
localTodos={localTodos}
setLocalTodos={setLocalTodos}
/>
))}
</View>
@ -281,6 +288,8 @@ const ToDosList = ({ isSettings, members }: { isSettings?: boolean, members?: Ar
key={item.id}
item={item}
is7Days={dateKey === "Next 7 Days"}
localTodos={localTodos}
setLocalTodos={setLocalTodos}
/>
))}
</View>
@ -347,7 +356,7 @@ const ToDosList = ({ isSettings, members }: { isSettings?: boolean, members?: Ar
noDateToDos
.sort((a, b) => Number(a.done) - Number(b.done))
.map((item) => (
<ToDoItem isSettings={isSettings} key={item.id} item={item} />
<ToDoItem isSettings={isSettings} key={item.id} item={item} localTodos={localTodos} setLocalTodos={setLocalTodos} />
))}
</View>
)}