mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 08:24:55 +00:00
changes to grocery, todos
This commit is contained in:
@ -1,23 +1,18 @@
|
|||||||
import { ScrollView } from "react-native";
|
import { Text, View } from "react-native-ui-lib";
|
||||||
import { Button, FloatingButton, Text, View } from "react-native-ui-lib";
|
|
||||||
import Octicons from "@expo/vector-icons/Octicons";
|
|
||||||
import GroceryList from "@/components/pages/grocery/GroceryList";
|
import GroceryList from "@/components/pages/grocery/GroceryList";
|
||||||
import AddGroceryItem from "@/components/pages/grocery/AddGroceryItem";
|
import AddGroceryItem from "@/components/pages/grocery/AddGroceryItem";
|
||||||
import { useAuthContext } from "@/contexts/AuthContext";
|
import { GroceryProvider } from "@/contexts/GroceryContext";
|
||||||
import { GroceryProvider, useGroceryContext } from "@/contexts/GroceryContext";
|
|
||||||
import TopDisplay from "@/components/pages/grocery/TopDisplay";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
||||||
|
import { ScrollView } from "react-native-gesture-handler";
|
||||||
|
|
||||||
export default function Screen() {
|
export default function Screen() {
|
||||||
return (
|
return (
|
||||||
<GroceryProvider>
|
<GroceryProvider>
|
||||||
<View>
|
<ScrollView>
|
||||||
<TopDisplay />
|
<GroceryList />
|
||||||
<View>
|
|
||||||
<GroceryList />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<AddGroceryItem />
|
<AddGroceryItem />
|
||||||
|
</ScrollView>
|
||||||
</GroceryProvider>
|
</GroceryProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {Stack} from "expo-router";
|
import {Stack} from "expo-router";
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
return <Stack screenOptions={{title: "Login"}}/>
|
return <Stack screenOptions={{title: ""}}/>
|
||||||
}
|
}
|
||||||
0
app/(unauth)/onboarding_flow/_layout.tsx
Normal file
0
app/(unauth)/onboarding_flow/_layout.tsx
Normal file
5
app/(unauth)/onboarding_flow/index.tsx
Normal file
5
app/(unauth)/onboarding_flow/index.tsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import Entry from "@/components/pages/main/Entry";
|
||||||
|
|
||||||
|
export default function Screen() {
|
||||||
|
return <Entry />;
|
||||||
|
}
|
||||||
BIN
assets/images/splash-clock.png
Normal file
BIN
assets/images/splash-clock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
@ -10,12 +10,13 @@ import {
|
|||||||
PanningProvider,
|
PanningProvider,
|
||||||
} from "react-native-ui-lib";
|
} from "react-native-ui-lib";
|
||||||
import { useGroceryContext } from "@/contexts/GroceryContext";
|
import { useGroceryContext } from "@/contexts/GroceryContext";
|
||||||
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
interface AddGroceryItemProps {
|
interface AddGroceryItemProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
const AddGroceryItem = () => {
|
const AddGroceryItem = () => {
|
||||||
const { setIsShopping, isShopping } = useGroceryContext();
|
const { isAddingGrocery, setIsAddingGrocery } = useGroceryContext();
|
||||||
const [visible, setVisible] = useState<boolean>(false);
|
const [visible, setVisible] = useState<boolean>(false);
|
||||||
|
|
||||||
const handleShowDialog = () => {
|
const handleShowDialog = () => {
|
||||||
@ -24,23 +25,6 @@ const AddGroceryItem = () => {
|
|||||||
const handleHideDialog = () => {
|
const handleHideDialog = () => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
};
|
};
|
||||||
const addGroceryDialog = (
|
|
||||||
<Dialog
|
|
||||||
visible={visible}
|
|
||||||
onDismiss={handleHideDialog}
|
|
||||||
panDirection={PanningProvider.Directions.DOWN}
|
|
||||||
containerStyle={{ borderRadius: 12, backgroundColor: "white" }}
|
|
||||||
>
|
|
||||||
<View style={styles.container}>
|
|
||||||
<Text style={styles.title}>New Grocery</Text>
|
|
||||||
<View style={styles.divider} />
|
|
||||||
<View style={styles.inner}>
|
|
||||||
<Text>Category</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
row
|
row
|
||||||
@ -53,39 +37,18 @@ const AddGroceryItem = () => {
|
|||||||
height: 60,
|
height: 60,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!isShopping ? (
|
<View style={styles.btnContainer} row>
|
||||||
<View style={styles.btnContainer} row>
|
<Button
|
||||||
<Button
|
color="white"
|
||||||
label="View shopping list"
|
backgroundColor="#fd1775"
|
||||||
color="#337a11"
|
label="Add item"
|
||||||
flex-2
|
text70L
|
||||||
marginR-5
|
iconSource={() => <FontAwesome6 name="add" size={18} color="white" />}
|
||||||
backgroundColor="#c6e0b3"
|
style={styles.finishShopBtn}
|
||||||
onPress={() => setIsShopping(true)}
|
enableShadow
|
||||||
/>
|
onPress={() => {setIsAddingGrocery(true)}}
|
||||||
<Button
|
/>
|
||||||
label="Create new"
|
</View>
|
||||||
color="white"
|
|
||||||
flex-1
|
|
||||||
backgroundColor="#19ad61"
|
|
||||||
enableShadow
|
|
||||||
onPress={() => {}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<View style={styles.btnContainer} row>
|
|
||||||
<Button
|
|
||||||
color="white"
|
|
||||||
backgroundColor="#81a861"
|
|
||||||
label="finish shopping"
|
|
||||||
text60L
|
|
||||||
style={styles.finishShopBtn}
|
|
||||||
enableShadow
|
|
||||||
onPress={() => setIsShopping(false)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
{addGroceryDialog}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
27
components/pages/grocery/CategoryDropdown.tsx
Normal file
27
components/pages/grocery/CategoryDropdown.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { View, Text, TouchableOpacity } from "react-native-ui-lib";
|
||||||
|
import { GroceryCategory } from "@/contexts/GroceryContext";
|
||||||
|
import { ScrollView } from "react-native-gesture-handler";
|
||||||
|
|
||||||
|
const CategoryDropdown = () => {
|
||||||
|
const groceryCategories = Object.values(GroceryCategory);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ScrollView height={100}>
|
||||||
|
{groceryCategories.map((category) => (
|
||||||
|
<TouchableOpacity onPress={() => {}}>
|
||||||
|
<View
|
||||||
|
key={category}
|
||||||
|
style={{
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text>{category}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CategoryDropdown;
|
||||||
@ -20,7 +20,7 @@ const GroceryItem = ({
|
|||||||
item: IGrocery;
|
item: IGrocery;
|
||||||
handleItemApproved: (id: number, changes: Partial<IGrocery>) => void;
|
handleItemApproved: (id: number, changes: Partial<IGrocery>) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { iconMapping, updateGroceryItem, groceries, isShopping } =
|
const { updateGroceryItem, groceries } =
|
||||||
useGroceryContext();
|
useGroceryContext();
|
||||||
|
|
||||||
const { profileType } = useAuthContext();
|
const { profileType } = useAuthContext();
|
||||||
@ -38,8 +38,10 @@ const GroceryItem = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
|
style={{borderRadius: 50, marginVertical: 5, height: 55}}
|
||||||
backgroundColor="white"
|
backgroundColor="white"
|
||||||
padding-3
|
centerV
|
||||||
|
padding-0
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setOpenFreqEdit(true);
|
setOpenFreqEdit(true);
|
||||||
}}
|
}}
|
||||||
@ -52,8 +54,8 @@ const GroceryItem = ({
|
|||||||
setOpenFreqEdit(false);
|
setOpenFreqEdit(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ListItem.Part left containerStyle={{ flex: 1, paddingStart: 15 }}>
|
<ListItem.Part left containerStyle={{ flex: 1, paddingStart: 20 }}>
|
||||||
<View
|
{/* <View
|
||||||
height={50}
|
height={50}
|
||||||
width={50}
|
width={50}
|
||||||
style={{ borderRadius: 15 }}
|
style={{ borderRadius: 15 }}
|
||||||
@ -66,7 +68,7 @@ const GroceryItem = ({
|
|||||||
color="orange"
|
color="orange"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>*/}
|
||||||
<View>
|
<View>
|
||||||
{!isEditingTitle ? (
|
{!isEditingTitle ? (
|
||||||
<TouchableOpacity onPress={() => setIsEditingTitle(true)}>
|
<TouchableOpacity onPress={() => setIsEditingTitle(true)}>
|
||||||
@ -89,11 +91,10 @@ const GroceryItem = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Text>{iconMapping[item.category]}</Text>
|
|
||||||
</View>
|
</View>
|
||||||
</ListItem.Part>
|
</ListItem.Part>
|
||||||
<ListItem.Part right containerStyle={{ paddingEnd: 15 }}>
|
<ListItem.Part right containerStyle={{ paddingEnd: 20 }}>
|
||||||
{profileType == ProfileType.PARENT && !isShopping ? (
|
{!item.approved ? (
|
||||||
<View row>
|
<View row>
|
||||||
<Button
|
<Button
|
||||||
padding-0
|
padding-0
|
||||||
|
|||||||
@ -1,33 +1,147 @@
|
|||||||
import { FlatList } from "react-native";
|
import { FlatList } from "react-native";
|
||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { View, Text, ListItem, Button } from "react-native-ui-lib";
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
ListItem,
|
||||||
|
Button,
|
||||||
|
TextField,
|
||||||
|
Picker,
|
||||||
|
} from "react-native-ui-lib";
|
||||||
import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
|
import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
|
||||||
import { useAuthContext } from "@/contexts/AuthContext";
|
import { useAuthContext } from "@/contexts/AuthContext";
|
||||||
import AntDesign from "@expo/vector-icons/AntDesign";
|
import AntDesign from "@expo/vector-icons/AntDesign";
|
||||||
import AddGroceryItem from "./AddGroceryItem";
|
import AddGroceryItem from "./AddGroceryItem";
|
||||||
import GroceryItem from "./GroceryItem";
|
import GroceryItem from "./GroceryItem";
|
||||||
import { useGroceryContext } from "@/contexts/GroceryContext";
|
import {
|
||||||
|
GroceryCategory,
|
||||||
|
IGrocery,
|
||||||
|
useGroceryContext,
|
||||||
|
} from "@/contexts/GroceryContext";
|
||||||
|
import HeaderTemplate from "@/components/shared/HeaderTemplate";
|
||||||
|
import CategoryDropdown from "./CategoryDropdown";
|
||||||
|
|
||||||
const GroceryList = () => {
|
const GroceryList = () => {
|
||||||
const { groceries, updateGroceryItem } = useGroceryContext();
|
const { groceries, updateGroceryItem, isAddingGrocery } = useGroceryContext();
|
||||||
|
const [approvedGroceries, setapprovedGroceries] = useState<IGrocery[]>(
|
||||||
|
groceries.filter((item) => item.approved == true)
|
||||||
|
);
|
||||||
|
const [pendingGroceries, setPendingGroceries] = useState<IGrocery[]>(
|
||||||
|
groceries.filter((item) => item.approved != true)
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setapprovedGroceries(groceries.filter((item) => item.approved == true));
|
||||||
|
setPendingGroceries(groceries.filter((item) => item.approved != true));
|
||||||
|
}, [groceries]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View marginH-20>
|
||||||
<FlatList
|
<HeaderTemplate
|
||||||
ItemSeparatorComponent={() => (
|
message={"Welcome to your grocery list"}
|
||||||
|
isWelcome={false}
|
||||||
|
>
|
||||||
|
<View row spread>
|
||||||
<View
|
<View
|
||||||
style={{
|
backgroundColor="#e2eed8"
|
||||||
height: 1.5,
|
padding-8
|
||||||
backgroundColor: "#e0e0e0",
|
style={{ borderRadius: 50 }}
|
||||||
marginHorizontal: 15,
|
>
|
||||||
}}
|
<Text text70BL color="#46a80a">
|
||||||
/>
|
{approvedGroceries.length} list{" "}
|
||||||
)}
|
{approvedGroceries.length == 1 ? (
|
||||||
data={groceries}
|
<Text text70BL color="#46a80a">
|
||||||
renderItem={({ item }) => (
|
item
|
||||||
<GroceryItem item={item} handleItemApproved={updateGroceryItem} />
|
</Text>
|
||||||
)}
|
) : (
|
||||||
keyExtractor={(item) => item.id.toString()}
|
<Text text70BL color="#46a80a">
|
||||||
/>
|
items
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
backgroundColor="#faead2"
|
||||||
|
padding-8
|
||||||
|
style={{ borderRadius: 50 }}
|
||||||
|
>
|
||||||
|
<Text text70BL color="#e28800">
|
||||||
|
{pendingGroceries.length} pending
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</HeaderTemplate>
|
||||||
|
|
||||||
|
{/* Pending Approval Section */}
|
||||||
|
<View row spread marginT-40 marginB-20 centerV>
|
||||||
|
<Text text70BL>Pending Approval</Text>
|
||||||
|
<View
|
||||||
|
centerV
|
||||||
|
style={{
|
||||||
|
aspectRatio: 1,
|
||||||
|
width: 40,
|
||||||
|
backgroundColor: "#faead2",
|
||||||
|
borderRadius: 50,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text text60L center color="#e28800">
|
||||||
|
{pendingGroceries.length.toString()}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{pendingGroceries.length > 0 ? (
|
||||||
|
<FlatList
|
||||||
|
data={pendingGroceries}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<GroceryItem item={item} handleItemApproved={updateGroceryItem} />
|
||||||
|
)}
|
||||||
|
keyExtractor={(item) => item.id.toString()}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Text>No items pending approval.</Text>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Approved Section */}
|
||||||
|
<View row spread marginT-40 marginB-20 centerV>
|
||||||
|
<Text text70BL>Shopping List</Text>
|
||||||
|
<View
|
||||||
|
centerV
|
||||||
|
style={{
|
||||||
|
aspectRatio: 1,
|
||||||
|
width: 40,
|
||||||
|
backgroundColor: "#e2eed8",
|
||||||
|
borderRadius: 50,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text text60L center color="#46a80a">
|
||||||
|
{approvedGroceries.length.toString()}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{isAddingGrocery && (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
width: "100%",
|
||||||
|
borderRadius: 25,
|
||||||
|
padding: 15,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextField placeholder="Grocery" maxLength={25} />
|
||||||
|
<CategoryDropdown />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
{approvedGroceries.length > 0 ? (
|
||||||
|
<FlatList
|
||||||
|
data={approvedGroceries}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<GroceryItem item={item} handleItemApproved={updateGroceryItem} />
|
||||||
|
)}
|
||||||
|
keyExtractor={(item) => item.id.toString()}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Text>No approved items.</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import React, { useState } from "react";
|
|||||||
import SignUpPage from "./SignUpPage";
|
import SignUpPage from "./SignUpPage";
|
||||||
import SignInPage from "./SignInPage";
|
import SignInPage from "./SignInPage";
|
||||||
import { useSignUp } from "@/hooks/firebase/useSignUp";
|
import { useSignUp } from "@/hooks/firebase/useSignUp";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
const Entry = () => {
|
const Entry = () => {
|
||||||
const [isRegister, setIsRegister] = useState<boolean>(false);
|
const [isRegister, setIsRegister] = useState<boolean>(false);
|
||||||
const {mutateAsync: signUp} = useSignUp();
|
const { mutateAsync: signUp } = useSignUp();
|
||||||
|
|
||||||
const setRegister = () => {
|
const setRegister = () => {
|
||||||
setIsRegister(true);
|
setIsRegister(true);
|
||||||
@ -17,9 +18,7 @@ const Entry = () => {
|
|||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{isRegister ? (
|
{isRegister ? (
|
||||||
<SignUpPage
|
<SignUpPage unsetRegister={unsetRegister} />
|
||||||
unsetRegister={unsetRegister}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<SignInPage setRegister={setRegister} />
|
<SignInPage setRegister={setRegister} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,49 +1,67 @@
|
|||||||
import { View, Text, Button, TextField } from "react-native-ui-lib";
|
import { View, Text, Button, TextField, ButtonSize } from "react-native-ui-lib";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useSignIn } from "@/hooks/firebase/useSignIn";
|
import { useSignIn } from "@/hooks/firebase/useSignIn";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
const SignInPage = (props: { setRegister: () => any }) => {
|
const SignInPage = (props: { setRegister: () => any }) => {
|
||||||
const [email, setEmail] = useState<string>("");
|
const [email, setEmail] = useState<string>("");
|
||||||
const [password, setPassword] = useState<string>("");
|
const [password, setPassword] = useState<string>("");
|
||||||
|
|
||||||
const { mutateAsync: signIn, error, isError } = useSignIn();
|
const { mutateAsync: signIn, error, isError } = useSignIn();
|
||||||
|
|
||||||
const handleSignIn = async () => {
|
const handleSignIn = async () => {
|
||||||
await signIn({ email, password });
|
await signIn({ email, password });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View padding-10>
|
<View padding-10 centerV height={"100%"}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
value={email}
|
value={email}
|
||||||
onChangeText={setEmail}
|
onChangeText={setEmail}
|
||||||
style={{ marginBottom: 10 }}
|
style={styles.textfield}
|
||||||
floatingPlaceholder
|
/>
|
||||||
/>
|
<TextField
|
||||||
<TextField
|
placeholder="Password"
|
||||||
placeholder="Password"
|
value={password}
|
||||||
value={password}
|
onChangeText={setPassword}
|
||||||
onChangeText={setPassword}
|
secureTextEntry
|
||||||
secureTextEntry
|
style={styles.textfield}
|
||||||
style={{ marginBottom: 10 }}
|
/>
|
||||||
floatingPlaceholder
|
<Button
|
||||||
/>
|
label="Login"
|
||||||
<Button label="Login" onPress={handleSignIn} style={{ marginBottom: 20 }} />
|
onPress={handleSignIn}
|
||||||
{isError && (
|
style={{ marginBottom: 20 }}
|
||||||
<Text center style={{ marginBottom: 20 }}>{`${error}`}</Text>
|
backgroundColor="#fd1775"
|
||||||
)}
|
/>
|
||||||
<Text center style={{ marginBottom: 5 }}>Don't have an account?</Text>
|
{isError && <Text center style={{ marginBottom: 20 }}>{`${error}`}</Text>}
|
||||||
<Button
|
<View row centerH>
|
||||||
onPress={props.setRegister}
|
<Text center style={{ marginBottom: 5 }}>
|
||||||
label="Sign Up"
|
Don't have an account?
|
||||||
link
|
</Text>
|
||||||
padding-0
|
<Button
|
||||||
margin-0
|
onPress={props.setRegister}
|
||||||
left
|
label="Sign Up"
|
||||||
/>
|
link
|
||||||
</View>
|
size={ButtonSize.xSmall}
|
||||||
);
|
padding-0
|
||||||
|
margin-0
|
||||||
|
left
|
||||||
|
color="#fd1775"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
textfield: {
|
||||||
|
backgroundColor: "white",
|
||||||
|
marginVertical: 10,
|
||||||
|
padding: 30,
|
||||||
|
height: 45,
|
||||||
|
borderRadius: 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export default SignInPage;
|
export default SignInPage;
|
||||||
|
|||||||
@ -1,46 +1,85 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import {Checkbox, Button, View, Text, TextField} from "react-native-ui-lib";
|
import {
|
||||||
|
Checkbox,
|
||||||
|
Button,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TextField,
|
||||||
|
ButtonSize,
|
||||||
|
} from "react-native-ui-lib";
|
||||||
import { useSignUp } from "@/hooks/firebase/useSignUp";
|
import { useSignUp } from "@/hooks/firebase/useSignUp";
|
||||||
import { ProfileType } from "@/contexts/AuthContext";
|
import { ProfileType } from "@/contexts/AuthContext";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
import { AntDesign } from "@expo/vector-icons";
|
||||||
|
|
||||||
const SignUpPage = (props: { unsetRegister: () => any }) => {
|
const SignUpPage = (props: { unsetRegister: () => any }) => {
|
||||||
const [email, setEmail] = useState<string>("");
|
const [email, setEmail] = useState<string>("");
|
||||||
const [password, setPassword] = useState<string>("");
|
const [firstName, setFirstName] = useState<string>("");
|
||||||
const [isParent, setIsParent] = useState<boolean>(true);
|
const [lastName, setLastName] = useState<string>("");
|
||||||
const [isChild, setIsChild] = useState<boolean>(false);
|
const [password, setPassword] = useState<string>("");
|
||||||
const [isCaregiver, setIsCaregiver] = useState<boolean>(false);
|
const [isParent, setIsParent] = useState<boolean>(true);
|
||||||
const [profileType, setProfileType] = useState<ProfileType>(
|
const [isChild, setIsChild] = useState<boolean>(false);
|
||||||
ProfileType.PARENT
|
const [isCaregiver, setIsCaregiver] = useState<boolean>(false);
|
||||||
);
|
const [profileType, setProfileType] = useState<ProfileType>(
|
||||||
const { mutateAsync: signUp } = useSignUp();
|
ProfileType.PARENT
|
||||||
|
);
|
||||||
|
const { mutateAsync: signUp } = useSignUp();
|
||||||
|
|
||||||
const handleSignUp = async () => {
|
const handleSignUp = async () => {
|
||||||
await signUp({ email, password });
|
await signUp({ email, password });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View padding-10>
|
<View padding-10>
|
||||||
<TextField
|
<Text text30 center>
|
||||||
placeholder="Email"
|
Get started with Kali
|
||||||
value={email}
|
</Text>
|
||||||
onChangeText={setEmail}
|
<Text>Please enter your details.</Text>
|
||||||
style={{ marginBottom: 10 }}
|
<TextField
|
||||||
floatingPlaceholder
|
marginT-60
|
||||||
/>
|
placeholder="First name"
|
||||||
<TextField
|
value={firstName}
|
||||||
placeholder="Password"
|
onChangeText={setFirstName}
|
||||||
value={password}
|
style={styles.textfield}
|
||||||
onChangeText={setPassword}
|
/>
|
||||||
secureTextEntry
|
<TextField
|
||||||
style={{ marginBottom: 10 }}
|
placeholder="Last name"
|
||||||
floatingPlaceholder
|
value={lastName}
|
||||||
/>
|
onChangeText={setLastName}
|
||||||
<Button
|
style={styles.textfield}
|
||||||
label="Register"
|
/>
|
||||||
onPress={handleSignUp}
|
<TextField
|
||||||
style={{ marginBottom: 10 }}
|
placeholder="Email"
|
||||||
/>
|
value={email}
|
||||||
<Text style={{ marginBottom: 10 }}>Choose Profile Type:</Text>
|
onChangeText={setEmail}
|
||||||
|
style={styles.textfield}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
placeholder="Password"
|
||||||
|
value={password}
|
||||||
|
onChangeText={setPassword}
|
||||||
|
secureTextEntry
|
||||||
|
style={styles.textfield}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label="Register"
|
||||||
|
onPress={handleSignUp}
|
||||||
|
style={{ marginBottom: 10, backgroundColor: "#fd1775" }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label="Sign up with Google"
|
||||||
|
backgroundColor="white"
|
||||||
|
color="black"
|
||||||
|
iconSource={() => (
|
||||||
|
<AntDesign
|
||||||
|
name="google"
|
||||||
|
size={24}
|
||||||
|
color="black"
|
||||||
|
style={{ marginRight: 15 }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{/*<Text style={{ marginBottom: 10 }}>Choose Profile Type:</Text>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Parent"
|
label="Parent"
|
||||||
value={isParent}
|
value={isParent}
|
||||||
@ -78,19 +117,33 @@ const SignUpPage = (props: { unsetRegister: () => any }) => {
|
|||||||
setIsChild(false);
|
setIsChild(false);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>*/}
|
||||||
<Text center style={{ marginBottom: 5, marginTop: 10 }}>
|
<View row centerH>
|
||||||
Already have an account?
|
<Text text70 center style={{ marginBottom: 5, marginTop: 10 }}>
|
||||||
</Text>
|
Already have an account?
|
||||||
<Button
|
</Text>
|
||||||
label="Sign In"
|
<Button
|
||||||
margin-0
|
label="Sign In"
|
||||||
link
|
margin-0
|
||||||
text200
|
link
|
||||||
onPress={props.unsetRegister}
|
color="#fd1775"
|
||||||
/>
|
size={ButtonSize.small}
|
||||||
</View>
|
text200
|
||||||
);
|
onPress={props.unsetRegister}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SignUpPage;
|
export default SignUpPage;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
textfield: {
|
||||||
|
backgroundColor: "white",
|
||||||
|
marginVertical: 10,
|
||||||
|
padding: 30,
|
||||||
|
height: 45,
|
||||||
|
borderRadius: 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
22
components/pages/main/WelcomeSplash.tsx
Normal file
22
components/pages/main/WelcomeSplash.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Image } from "react-native";
|
||||||
|
import React from "react";
|
||||||
|
import { View, Text, Button } from "react-native-ui-lib";
|
||||||
|
|
||||||
|
const WelcomeSplash = () => {
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Image
|
||||||
|
source={require("../../../assets/images/splash-clock.png")}
|
||||||
|
height={10}
|
||||||
|
width={10}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label="Continue"
|
||||||
|
style={{ backgroundColor: "#fd1775" }}
|
||||||
|
onPress={() => {}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WelcomeSplash;
|
||||||
84
components/pages/onboarding/OnboardingFlow.tsx
Normal file
84
components/pages/onboarding/OnboardingFlow.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { Image } from "react-native";
|
||||||
|
import React, { useRef } from "react";
|
||||||
|
import { View, Text, Button, TextField } from "react-native-ui-lib";
|
||||||
|
import Onboarding from "react-native-onboarding-swiper";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
import { useAuthContext } from "@/contexts/AuthContext";
|
||||||
|
import { useSignUp } from "@/hooks/firebase/useSignUp";
|
||||||
|
const OnboardingFlow = () => {
|
||||||
|
const onboardingRef = useRef(null);
|
||||||
|
const { mutateAsync: signUp } = useSignUp();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Onboarding
|
||||||
|
showPagination={false}
|
||||||
|
ref={onboardingRef}
|
||||||
|
containerStyles={{ backgroundColor: "#f9f8f7" }}
|
||||||
|
imageContainerStyles={{
|
||||||
|
paddingBottom: 0,
|
||||||
|
paddingTop: 0,
|
||||||
|
}}
|
||||||
|
pages={[
|
||||||
|
{
|
||||||
|
backgroundColor: "#f9f8f7",
|
||||||
|
image: (
|
||||||
|
<Image
|
||||||
|
source={require("../../../assets/images/splash-clock.png")}
|
||||||
|
height={10}
|
||||||
|
width={10}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
title: <Text text30>Welcome to Kali</Text>,
|
||||||
|
subtitle: (
|
||||||
|
<View paddingB-250 marginH-20 spread>
|
||||||
|
<Text text50R>Lightening Mental Loads, One Family at a Time</Text>
|
||||||
|
<Button
|
||||||
|
label="Continue"
|
||||||
|
style={{ backgroundColor: "#fd1775" }}
|
||||||
|
onPress={() => onboardingRef.current.goToPage(1, true)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "#f9f8f7",
|
||||||
|
title: <Text>Get started with Kali</Text>,
|
||||||
|
subtitle: (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
marginBottom: "auto",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View marginH-30>
|
||||||
|
{/*<TextField style={styles.textfield} placeholder="First name" />*/}
|
||||||
|
{/*<TextField style={styles.textfield} placeholder="Last name" />*/}
|
||||||
|
<TextField style={styles.textfield} placeholder="Email" />
|
||||||
|
<TextField style={styles.textfield} placeholder="Password" />
|
||||||
|
<Button
|
||||||
|
label="Login"
|
||||||
|
backgroundColor="#ea156c"
|
||||||
|
onPress={() => {
|
||||||
|
console.log("Onboarding Done");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OnboardingFlow;
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
textfield: {
|
||||||
|
backgroundColor: "white",
|
||||||
|
marginVertical: 10,
|
||||||
|
padding: 30,
|
||||||
|
height: 45,
|
||||||
|
borderRadius: 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
0
components/pages/onboarding/index.ts
Normal file
0
components/pages/onboarding/index.ts
Normal file
@ -12,15 +12,21 @@ import {
|
|||||||
NumberInput,
|
NumberInput,
|
||||||
NumberInputData,
|
NumberInputData,
|
||||||
DateTimePicker,
|
DateTimePicker,
|
||||||
|
Switch,
|
||||||
} from "react-native-ui-lib";
|
} from "react-native-ui-lib";
|
||||||
import { AntDesign, Feather, Ionicons } from "@expo/vector-icons";
|
import { AntDesign, Feather, Ionicons } from "@expo/vector-icons";
|
||||||
import LinearGradient from "react-native-linear-gradient";
|
import LinearGradient from "react-native-linear-gradient";
|
||||||
import { PanningDirectionsEnum } from "react-native-ui-lib/src/components/panningViews/panningProvider";
|
import { PanningDirectionsEnum } from "react-native-ui-lib/src/components/panningViews/panningProvider";
|
||||||
|
import { useToDosContext } from "@/contexts/ToDosContext";
|
||||||
|
|
||||||
const AddChore = () => {
|
const AddChore = () => {
|
||||||
|
const { addToDo, toDos } = useToDosContext();
|
||||||
|
|
||||||
|
const [newTitle, setNewTitle] = useState<string>("");
|
||||||
const [isVisible, setIsVisible] = useState<boolean>(false);
|
const [isVisible, setIsVisible] = useState<boolean>(false);
|
||||||
const [points, setPoints] = useState<number>(10);
|
const [points, setPoints] = useState<number>(10);
|
||||||
const [choreDate, setChoreDate] = useState<Date>(new Date());
|
const [choreDate, setChoreDate] = useState<Date>(new Date());
|
||||||
|
const [rotate, setRotate] = useState<boolean>(false);
|
||||||
|
|
||||||
const handleChange = (text: string) => {
|
const handleChange = (text: string) => {
|
||||||
const numericValue = parseInt(text, 10);
|
const numericValue = parseInt(text, 10);
|
||||||
@ -66,8 +72,38 @@ const AddChore = () => {
|
|||||||
}}
|
}}
|
||||||
visible={isVisible}
|
visible={isVisible}
|
||||||
>
|
>
|
||||||
|
<View row spread>
|
||||||
|
<Button color="#05a8b6" style={styles.topBtn} label="Cancel" onPress={() => {setIsVisible(false)}} />
|
||||||
|
<Button
|
||||||
|
style={styles.topBtn}
|
||||||
|
iconSource={() => (
|
||||||
|
<Feather name="chevron-down" size={24} color="black" />
|
||||||
|
)} onPress={() => {setIsVisible(false)}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
color="#05a8b6"
|
||||||
|
style={styles.topBtn}
|
||||||
|
label="Save"
|
||||||
|
onPress={() => {
|
||||||
|
addToDo({
|
||||||
|
id: 0,
|
||||||
|
title: newTitle,
|
||||||
|
done: false,
|
||||||
|
date: choreDate,
|
||||||
|
points: points,
|
||||||
|
rotate: rotate,
|
||||||
|
});
|
||||||
|
setIsVisible(false);
|
||||||
|
console.log(toDos);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Add chore title"
|
placeholder="Add chore title"
|
||||||
|
value={newTitle}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
setNewTitle(text);
|
||||||
|
}}
|
||||||
placeholderTextColor="#2d2d30"
|
placeholderTextColor="#2d2d30"
|
||||||
text60R
|
text60R
|
||||||
marginT-15
|
marginT-15
|
||||||
@ -134,6 +170,7 @@ const AddChore = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
<Switch onColor={'#ea156c'} value={rotate} style={styles.rotateSwitch} onValueChange={(value) => setRotate(value)} />
|
||||||
<View style={styles.divider} />
|
<View style={styles.divider} />
|
||||||
<View marginH-30 marginB-10 row centerV>
|
<View marginH-30 marginB-10 row centerV>
|
||||||
<Ionicons name="gift-outline" size={30} color="#919191" />
|
<Ionicons name="gift-outline" size={30} color="#919191" />
|
||||||
@ -195,4 +232,12 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: "rgb(253, 23, 117)",
|
backgroundColor: "rgb(253, 23, 117)",
|
||||||
paddingVertical: 20,
|
paddingVertical: 20,
|
||||||
},
|
},
|
||||||
|
topBtn: {
|
||||||
|
backgroundColor: "white",
|
||||||
|
color: "#05a8b6",
|
||||||
|
},
|
||||||
|
rotateSwitch: {
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 35
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,17 +1,37 @@
|
|||||||
import { View, Text, Checkbox } from "react-native-ui-lib";
|
import { View, Text, Checkbox } from "react-native-ui-lib";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { IToDo } from "@/contexts/ToDosContext";
|
import { IToDo, useToDosContext } from "@/contexts/ToDosContext";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
const ToDoItem = (props: { item: IToDo }) => {
|
const ToDoItem = (props: { item: IToDo }) => {
|
||||||
|
const { updateToDo } = useToDosContext();
|
||||||
return (
|
return (
|
||||||
<View centerV backgroundColor="white" paddingV-10 paddingH-10 marginH-25 marginV-10 style={{borderRadius: 22}}>
|
<View
|
||||||
|
centerV
|
||||||
|
backgroundColor="white"
|
||||||
|
paddingV-10
|
||||||
|
paddingH-10
|
||||||
|
marginH-25
|
||||||
|
marginV-10
|
||||||
|
style={{ borderRadius: 22 }}
|
||||||
|
>
|
||||||
<View paddingB-5 row spread>
|
<View paddingB-5 row spread>
|
||||||
<Text text70R>{props.item.title}</Text>
|
<Text text70R>{props.item.title}</Text>
|
||||||
<Checkbox value={props.item.done} />
|
<Checkbox
|
||||||
|
value={props.item.done}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
updateToDo(props.item.id, { done: !props.item.done });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View centerH paddingV-5>
|
<View centerH paddingV-5>
|
||||||
<View centerV height={2} width={"100%"} backgroundColor="#e7e7e7" centerH />
|
<View
|
||||||
|
centerV
|
||||||
|
height={2}
|
||||||
|
width={"100%"}
|
||||||
|
backgroundColor="#e7e7e7"
|
||||||
|
centerH
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View centerH row spread>
|
<View centerH row spread>
|
||||||
{props.item.points && props.item.points > 0 ? (
|
{props.item.points && props.item.points > 0 ? (
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const ToDosList = () => {
|
|||||||
const groupedToDos = groupToDosByDate(toDos);
|
const groupedToDos = groupToDosByDate(toDos);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View marginB-140>
|
||||||
{Object.keys(groupedToDos).map((dateKey) => (
|
{Object.keys(groupedToDos).map((dateKey) => (
|
||||||
<View key={dateKey}>
|
<View key={dateKey}>
|
||||||
<Text text70 style={{ fontWeight: "bold", marginVertical: 8, paddingHorizontal: 20}}>
|
<Text text70 style={{ fontWeight: "bold", marginVertical: 8, paddingHorizontal: 20}}>
|
||||||
|
|||||||
@ -2,14 +2,21 @@ import { View, Text } from "react-native-ui-lib";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useAuthContext } from "@/contexts/AuthContext";
|
import { useAuthContext } from "@/contexts/AuthContext";
|
||||||
|
|
||||||
const HeaderTemplate = (props: { message: string }) => {
|
const HeaderTemplate = (props: { message: string; isWelcome: boolean; children?: React.ReactNode }) => {
|
||||||
const { user, profileData } = useAuthContext();
|
const { user, profileData } = useAuthContext();
|
||||||
return (
|
return (
|
||||||
<View row centerV padding-25>
|
<View row centerV padding-25>
|
||||||
<View backgroundColor="pink" height={65} width={65} style={{borderRadius: 22}} marginR-20 />
|
<View
|
||||||
|
backgroundColor="pink"
|
||||||
|
height={65}
|
||||||
|
width={65}
|
||||||
|
style={{ borderRadius: 22 }}
|
||||||
|
marginR-20
|
||||||
|
/>
|
||||||
<View>
|
<View>
|
||||||
<Text text70L>Welcome, {user?.email}!</Text>
|
{props.isWelcome && <Text text70L>Welcome, {user?.email}!</Text>}
|
||||||
<Text text70BL>{props.message}</Text>
|
<Text text70BL>{props.message}</Text>
|
||||||
|
{props.children && <View>{props.children}</View>}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -54,8 +54,8 @@ interface IGroceryContext {
|
|||||||
groceries: IGrocery[];
|
groceries: IGrocery[];
|
||||||
iconMapping: { [key in GroceryCategory]: MaterialIconNames };
|
iconMapping: { [key in GroceryCategory]: MaterialIconNames };
|
||||||
updateGroceryItem: (id: number, changes: Partial<IGrocery>) => void;
|
updateGroceryItem: (id: number, changes: Partial<IGrocery>) => void;
|
||||||
isShopping: boolean;
|
isAddingGrocery: boolean;
|
||||||
setIsShopping: (value: boolean) => void;
|
setIsAddingGrocery: (value: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GroceryContext = createContext<IGroceryContext | undefined>(undefined);
|
const GroceryContext = createContext<IGroceryContext | undefined>(undefined);
|
||||||
@ -63,7 +63,7 @@ const GroceryContext = createContext<IGroceryContext | undefined>(undefined);
|
|||||||
export const GroceryProvider: React.FC<{ children: React.ReactNode }> = ({
|
export const GroceryProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const [isShopping, setIsShopping] = useState<boolean>(false);
|
const [isAddingGrocery, setIsAddingGrocery] = useState<boolean>(false);
|
||||||
const [groceries, setGroceries] = useState<IGrocery[]>([
|
const [groceries, setGroceries] = useState<IGrocery[]>([
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 0,
|
||||||
@ -113,7 +113,7 @@ export const GroceryProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<GroceryContext.Provider
|
<GroceryContext.Provider
|
||||||
value={{ groceries, iconMapping, updateGroceryItem, isShopping, setIsShopping }}
|
value={{ groceries, iconMapping, updateGroceryItem, isAddingGrocery, setIsAddingGrocery }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</GroceryContext.Provider>
|
</GroceryContext.Provider>
|
||||||
|
|||||||
@ -5,10 +5,12 @@ export interface IToDo {
|
|||||||
done: boolean;
|
done: boolean;
|
||||||
date: Date;
|
date: Date;
|
||||||
points?: number;
|
points?: number;
|
||||||
|
rotate: boolean;
|
||||||
}
|
}
|
||||||
interface IToDosContext {
|
interface IToDosContext {
|
||||||
toDos: IToDo[];
|
toDos: IToDo[];
|
||||||
updateToDo: (id: number, changes: Partial<IToDo>) => void;
|
updateToDo: (id: number, changes: Partial<IToDo>) => void;
|
||||||
|
addToDo: (newToDo: IToDo) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ToDosContext = createContext<IToDosContext>(undefined!);
|
const ToDosContext = createContext<IToDosContext>(undefined!);
|
||||||
@ -17,40 +19,76 @@ export const ToDosContextProvider: FC<{ children: ReactNode }> = ({
|
|||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const [toDos, setToDos] = useState<IToDo[]>([
|
const [toDos, setToDos] = useState<IToDo[]>([
|
||||||
{ id: 0, title: "Pay: Credit card", done: false, date: new Date() },
|
{
|
||||||
{ id: 1, title: "Monthly Log story", done: false, date: new Date() },
|
id: 0,
|
||||||
{ id: 2, title: "Write: Arcade Highlights", done: false, date: new Date() },
|
title: "Pay: Credit card",
|
||||||
|
done: false,
|
||||||
|
date: new Date(),
|
||||||
|
rotate: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Monthly Log story",
|
||||||
|
done: false,
|
||||||
|
date: new Date(),
|
||||||
|
rotate: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Write: Arcade Highlights",
|
||||||
|
done: false,
|
||||||
|
date: new Date(),
|
||||||
|
rotate: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
title: "Dressup: Cat",
|
title: "Dressup: Cat",
|
||||||
done: false,
|
done: false,
|
||||||
date: new Date(Date.now() + 86400000),
|
date: new Date(Date.now() + 86400000),
|
||||||
points: 40,
|
points: 40,
|
||||||
|
rotate: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
title: "Trim: Nails",
|
title: "Trim: Nails",
|
||||||
done: false,
|
done: false,
|
||||||
date: new Date(Date.now() + 86400000),
|
date: new Date(Date.now() + 86400000),
|
||||||
|
rotate: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
title: "Monthly Log",
|
title: "Monthly Log",
|
||||||
done: false,
|
done: false,
|
||||||
date: new Date(Date.now() + 2 * 86400000),
|
date: new Date(Date.now() + 2 * 86400000),
|
||||||
|
rotate: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
title: "Do it",
|
title: "Do it",
|
||||||
done: false,
|
done: false,
|
||||||
date: new Date(Date.now() + 3 * 86400000),
|
date: new Date(Date.now() + 3 * 86400000),
|
||||||
|
rotate: false,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updateToDo = (id: number, changes: Partial<IToDo>) => {};
|
const updateToDo = (id: number, changes: Partial<IToDo>) => {
|
||||||
|
setToDos((prevToDos) =>
|
||||||
|
prevToDos.map((toDo) => (toDo.id === id ? { ...toDo, ...changes } : toDo))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addToDo = (newToDo: IToDo) => {
|
||||||
|
setToDos((prevToDos) => [
|
||||||
|
...prevToDos,
|
||||||
|
{
|
||||||
|
...newToDo,
|
||||||
|
id: prevToDos.length ? prevToDos[prevToDos.length - 1].id + 1 : 0,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToDosContext.Provider value={{ toDos, updateToDo }}>
|
<ToDosContext.Provider value={{ toDos, updateToDo, addToDo }}>
|
||||||
{children}
|
{children}
|
||||||
</ToDosContext.Provider>
|
</ToDosContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
33
package-lock.json
generated
33
package-lock.json
generated
@ -40,6 +40,7 @@
|
|||||||
"react-native-calendars": "^1.1306.0",
|
"react-native-calendars": "^1.1306.0",
|
||||||
"react-native-gesture-handler": "~2.16.1",
|
"react-native-gesture-handler": "~2.16.1",
|
||||||
"react-native-linear-gradient": "^2.8.3",
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
|
"react-native-onboarding-swiper": "^1.3.0",
|
||||||
"react-native-reanimated": "~3.10.1",
|
"react-native-reanimated": "~3.10.1",
|
||||||
"react-native-safe-area-context": "4.10.5",
|
"react-native-safe-area-context": "4.10.5",
|
||||||
"react-native-screens": "3.31.1",
|
"react-native-screens": "3.31.1",
|
||||||
@ -52,6 +53,7 @@
|
|||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/react": "~18.2.45",
|
"@types/react": "~18.2.45",
|
||||||
|
"@types/react-native-onboarding-swiper": "^1.1.9",
|
||||||
"@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",
|
||||||
@ -8294,6 +8296,17 @@
|
|||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-native-onboarding-swiper": {
|
||||||
|
"version": "1.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-native-onboarding-swiper/-/react-native-onboarding-swiper-1.1.9.tgz",
|
||||||
|
"integrity": "sha512-xCvsk7e6gQ9tEsK/xUPGA88mjF4sz8xFWAt+8de5xyjvrp3/nY0RJKPUd8ZtZzhGqcDm2tdsfI6KdNS5XuDxuA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-test-renderer": {
|
"node_modules/@types/react-test-renderer": {
|
||||||
"version": "18.3.0",
|
"version": "18.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz",
|
||||||
@ -12589,9 +12602,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/firebase-functions": {
|
"node_modules/firebase-functions": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-5.1.1.tgz",
|
||||||
"integrity": "sha512-VO46n9lqljrNiqOv4BbnFHYxY+yYCdZcOeUIF1t9DbFxBbVPztHdMM9MvpfCDp0nzXP2PugdmghSgM0hORrNvw==",
|
"integrity": "sha512-KkyKZE98Leg/C73oRyuUYox04PQeeBThdygMfeX+7t1cmKWYKa/ZieYa89U8GHgED+0mF7m7wfNZOfbURYxIKg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/cors": "^2.8.5",
|
"@types/cors": "^2.8.5",
|
||||||
@ -19625,6 +19638,20 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-onboarding-swiper": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-onboarding-swiper/-/react-native-onboarding-swiper-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-2ZPMrZrJFgR5dmVWIj60x/vTBWrm0BZPuc2w7Cz2Sq/8ChypCi3oL8F7GYMrzky1fmknCS6Z0WPphfZVpnLUnQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tinycolor2": "^1.4.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"prop-types": "*",
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-reanimated": {
|
"node_modules/react-native-reanimated": {
|
||||||
"version": "3.10.1",
|
"version": "3.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
"react-native-calendars": "^1.1306.0",
|
"react-native-calendars": "^1.1306.0",
|
||||||
"react-native-gesture-handler": "~2.16.1",
|
"react-native-gesture-handler": "~2.16.1",
|
||||||
"react-native-linear-gradient": "^2.8.3",
|
"react-native-linear-gradient": "^2.8.3",
|
||||||
|
"react-native-onboarding-swiper": "^1.3.0",
|
||||||
"react-native-reanimated": "~3.10.1",
|
"react-native-reanimated": "~3.10.1",
|
||||||
"react-native-safe-area-context": "4.10.5",
|
"react-native-safe-area-context": "4.10.5",
|
||||||
"react-native-screens": "3.31.1",
|
"react-native-screens": "3.31.1",
|
||||||
@ -59,6 +60,7 @@
|
|||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/react": "~18.2.45",
|
"@types/react": "~18.2.45",
|
||||||
|
"@types/react-native-onboarding-swiper": "^1.1.9",
|
||||||
"@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",
|
||||||
|
|||||||
23
yarn.lock
23
yarn.lock
@ -3297,6 +3297,14 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz"
|
resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz"
|
||||||
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
|
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
|
||||||
|
|
||||||
|
"@types/react-native-onboarding-swiper@^1.1.9":
|
||||||
|
version "1.1.9"
|
||||||
|
resolved "https://registry.npmjs.org/@types/react-native-onboarding-swiper/-/react-native-onboarding-swiper-1.1.9.tgz"
|
||||||
|
integrity sha512-xCvsk7e6gQ9tEsK/xUPGA88mjF4sz8xFWAt+8de5xyjvrp3/nY0RJKPUd8ZtZzhGqcDm2tdsfI6KdNS5XuDxuA==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
react-native "*"
|
||||||
|
|
||||||
"@types/react-test-renderer@^18.0.7":
|
"@types/react-test-renderer@^18.0.7":
|
||||||
version "18.3.0"
|
version "18.3.0"
|
||||||
resolved "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz"
|
resolved "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz"
|
||||||
@ -5675,9 +5683,9 @@ find-yarn-workspace-root@~2.0.0:
|
|||||||
"@google-cloud/storage" "^7.7.0"
|
"@google-cloud/storage" "^7.7.0"
|
||||||
|
|
||||||
firebase-functions@^5.1.0:
|
firebase-functions@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.1"
|
||||||
resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-5.1.0.tgz"
|
resolved "https://registry.npmjs.org/firebase-functions/-/firebase-functions-5.1.1.tgz"
|
||||||
integrity sha512-VO46n9lqljrNiqOv4BbnFHYxY+yYCdZcOeUIF1t9DbFxBbVPztHdMM9MvpfCDp0nzXP2PugdmghSgM0hORrNvw==
|
integrity sha512-KkyKZE98Leg/C73oRyuUYox04PQeeBThdygMfeX+7t1cmKWYKa/ZieYa89U8GHgED+0mF7m7wfNZOfbURYxIKg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/cors" "^2.8.5"
|
"@types/cors" "^2.8.5"
|
||||||
"@types/express" "4.17.3"
|
"@types/express" "4.17.3"
|
||||||
@ -8970,6 +8978,13 @@ react-native-linear-gradient@^2.8.3:
|
|||||||
resolved "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz"
|
resolved "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz"
|
||||||
integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==
|
integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==
|
||||||
|
|
||||||
|
react-native-onboarding-swiper@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.npmjs.org/react-native-onboarding-swiper/-/react-native-onboarding-swiper-1.3.0.tgz"
|
||||||
|
integrity sha512-2ZPMrZrJFgR5dmVWIj60x/vTBWrm0BZPuc2w7Cz2Sq/8ChypCi3oL8F7GYMrzky1fmknCS6Z0WPphfZVpnLUnQ==
|
||||||
|
dependencies:
|
||||||
|
tinycolor2 "^1.4.1"
|
||||||
|
|
||||||
react-native-reanimated@*, "react-native-reanimated@>= 1.0.0", react-native-reanimated@>=2.0.0, react-native-reanimated@~3.10.1:
|
react-native-reanimated@*, "react-native-reanimated@>= 1.0.0", react-native-reanimated@>=2.0.0, react-native-reanimated@~3.10.1:
|
||||||
version "3.10.1"
|
version "3.10.1"
|
||||||
resolved "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz"
|
resolved "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz"
|
||||||
@ -10237,7 +10252,7 @@ through2@^2.0.1:
|
|||||||
readable-stream "~2.3.6"
|
readable-stream "~2.3.6"
|
||||||
xtend "~4.0.1"
|
xtend "~4.0.1"
|
||||||
|
|
||||||
tinycolor2@^1.4.2:
|
tinycolor2@^1.4.1, tinycolor2@^1.4.2:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz"
|
resolved "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz"
|
||||||
integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==
|
integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==
|
||||||
|
|||||||
Reference in New Issue
Block a user