diff --git a/app/(auth)/grocery/index.tsx b/app/(auth)/grocery/index.tsx index 5c9d1e4..052a53e 100644 --- a/app/(auth)/grocery/index.tsx +++ b/app/(auth)/grocery/index.tsx @@ -1,6 +1,3 @@ -import { Text, View } from "react-native-ui-lib"; -import GroceryList from "@/components/pages/grocery/GroceryList"; -import AddGroceryItem from "@/components/pages/grocery/AddGroceryItem"; import { GroceryProvider } from "@/contexts/GroceryContext"; import React from "react"; import GroceryWrapper from "@/components/pages/grocery/GroceryWrapper"; diff --git a/components/pages/calendar/AddEventDialog.tsx b/components/pages/calendar/AddEventDialog.tsx index 02be196..8f0b334 100644 --- a/components/pages/calendar/AddEventDialog.tsx +++ b/components/pages/calendar/AddEventDialog.tsx @@ -51,7 +51,7 @@ export const AddEventDialog = () => { }} onPress={handleOpenManualInputModal} > - Manually Input + Create New + + diff --git a/components/pages/calendar/ManuallyAddEventModal.tsx b/components/pages/calendar/ManuallyAddEventModal.tsx index 23970ed..8d26734 100644 --- a/components/pages/calendar/ManuallyAddEventModal.tsx +++ b/components/pages/calendar/ManuallyAddEventModal.tsx @@ -1,260 +1,320 @@ import { - Avatar, - Colors, - DateTimePicker, - LoaderScreen, - Modal, - Picker, - Switch, - Text, - TextField, - View + Avatar, + Colors, + DateTimePicker, + LoaderScreen, + Modal, + Picker, + Switch, + Text, + TextField, + View, } from "react-native-ui-lib"; -import {ScrollView, TouchableOpacity} from "react-native-gesture-handler"; -import {useSafeAreaInsets} from "react-native-safe-area-context"; -import {useState} from "react"; -import {MaterialIcons} from "@expo/vector-icons"; -import {PickerMultiValue} from "react-native-ui-lib/src/components/picker/types"; -import {useAuthContext} from "@/contexts/AuthContext"; -import {useCreateEvent} from "@/hooks/firebase/useCreateEvent"; -import {EventData} from "@/hooks/firebase/types/eventData"; +import { ScrollView, TouchableOpacity } from "react-native-gesture-handler"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { useState } from "react"; +import { MaterialIcons } from "@expo/vector-icons"; +import { PickerMultiValue } from "react-native-ui-lib/src/components/picker/types"; +import { useAuthContext } from "@/contexts/AuthContext"; +import { useCreateEvent } from "@/hooks/firebase/useCreateEvent"; +import { EventData } from "@/hooks/firebase/types/eventData"; const daysOfWeek = [ - {label: "Monday", value: "monday"}, - {label: "Tuesday", value: "tuesday"}, - {label: "Wednesday", value: "wednesday"}, - {label: "Thursday", value: "thursday"}, - {label: "Friday", value: "friday"}, - {label: "Saturday", value: "saturday"}, - {label: "Sunday", value: "sunday"}, + { label: "Monday", value: "monday" }, + { label: "Tuesday", value: "tuesday" }, + { label: "Wednesday", value: "wednesday" }, + { label: "Thursday", value: "thursday" }, + { label: "Friday", value: "friday" }, + { label: "Saturday", value: "saturday" }, + { label: "Sunday", value: "sunday" }, ]; -export const ManuallyAddEventModal = ({show, close}: { show: boolean, close: () => void }) => { - const {user} = useAuthContext() - const insets = useSafeAreaInsets(); +export const ManuallyAddEventModal = ({ + show, + close, +}: { + show: boolean; + close: () => void; +}) => { + const { user } = useAuthContext(); + const insets = useSafeAreaInsets(); - const [title, setTitle] = useState(""); + const [title, setTitle] = useState(""); - const [isAllDay, setIsAllDay] = useState(false); - const [startTime, setStartTime] = useState(new Date()); - const [endTime, setEndTime] = useState(new Date()) + const [isAllDay, setIsAllDay] = useState(false); + const [startTime, setStartTime] = useState(new Date()); + const [endTime, setEndTime] = useState(new Date()); - const [startDate, setStartDate] = useState(new Date()); - const [endDate, setEndDate] = useState(new Date()) + const [startDate, setStartDate] = useState(new Date()); + const [endDate, setEndDate] = useState(new Date()); - const [repeatInterval, setRepeatInterval] = useState([]); + const [repeatInterval, setRepeatInterval] = useState([]); - const {mutateAsync: createEvent, isLoading, isError} = useCreateEvent() + const { mutateAsync: createEvent, isLoading, isError } = useCreateEvent(); - const formatDateTime = (date: Date) => { - return date.toLocaleDateString('en-US', { - weekday: 'long', - month: 'short', - day: 'numeric' - }); - }; + const formatDateTime = (date: Date) => { + return date.toLocaleDateString("en-US", { + weekday: "long", + month: "short", + day: "numeric", + }); + }; - const combineDateAndTime = (date: Date, time: Date): Date => { - const combined = new Date(date); - combined.setHours(time.getHours()); - combined.setMinutes(time.getMinutes()); - combined.setSeconds(0); - combined.setMilliseconds(0); - return combined; - }; + const combineDateAndTime = (date: Date, time: Date): Date => { + const combined = new Date(date); + combined.setHours(time.getHours()); + combined.setMinutes(time.getMinutes()); + combined.setSeconds(0); + combined.setMilliseconds(0); + return combined; + }; - const handleSave = async () => { - let finalStartDate: Date; - let finalEndDate: Date; + const handleSave = async () => { + let finalStartDate: Date; + let finalEndDate: Date; - if (isAllDay) { - finalStartDate = new Date(startDate); - finalStartDate.setHours(0, 0, 0, 0); + if (isAllDay) { + finalStartDate = new Date(startDate); + finalStartDate.setHours(0, 0, 0, 0); - finalEndDate = new Date(startDate); - finalEndDate.setHours(23, 59, 59, 999); - } else { - finalStartDate = combineDateAndTime(startDate, startTime); - finalEndDate = combineDateAndTime(endDate, endTime); - } - - const eventData: Partial = { - title, - startDate: finalStartDate, - endDate: finalEndDate, - repeatDays: repeatInterval.map(x => x.toString()), - allDay: isAllDay - }; - - await createEvent(eventData) - - close(); - }; - - const getRepeatLabel = () => { - const selectedDays = repeatInterval - const allDays = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]; - const workDays = ["monday", "tuesday", "wednesday", "thursday", "friday"]; - - const isEveryWorkDay = workDays.every(day => selectedDays.includes(day)); - - const isEveryDay = allDays.every(day => selectedDays.includes(day)); - - if (isEveryDay) { - return "Every day"; - } else if (isEveryWorkDay && !selectedDays.includes("saturday") && !selectedDays.includes("sunday")) { - return "Every work day"; - } else { - return selectedDays - .map(item => daysOfWeek.find(day => day.value === item)?.label) - .join(", "); - } - }; - - if (isLoading && !isError) { - return ( - - - - ) + finalEndDate = new Date(startDate); + finalEndDate.setHours(23, 59, 59, 999); + } else { + finalStartDate = combineDateAndTime(startDate, startTime); + finalEndDate = combineDateAndTime(endDate, endTime); } + const eventData: Partial = { + title, + startDate: finalStartDate, + endDate: finalEndDate, + repeatDays: repeatInterval.map((x) => x.toString()), + allDay: isAllDay, + }; + + await createEvent(eventData); + + close(); + }; + + const getRepeatLabel = () => { + const selectedDays = repeatInterval; + const allDays = [ + "sunday", + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday", + ]; + const workDays = ["monday", "tuesday", "wednesday", "thursday", "friday"]; + + const isEveryWorkDay = workDays.every((day) => selectedDays.includes(day)); + + const isEveryDay = allDays.every((day) => selectedDays.includes(day)); + + if (isEveryDay) { + return "Every day"; + } else if ( + isEveryWorkDay && + !selectedDays.includes("saturday") && + !selectedDays.includes("sunday") + ) { + return "Every work day"; + } else { + return selectedDays + .map((item) => daysOfWeek.find((day) => day.value === item)?.label) + .join(", "); + } + }; + + if (isLoading && !isError) { return ( - - - - - Cancel - - Add event - - Save - - - - - - - - - - - - - All-day - - setIsAllDay(value)} - /> - - - - - {!isAllDay && ( - - )} - - - {!isAllDay && ( - - - - - )} - - - - setRepeatInterval(items)} - placeholder="Doest not repeat" - style={{marginLeft: 10, flex: 1}} - mode={Picker.modes.MULTI} - getLabel={getRepeatLabel} - - > - {daysOfWeek.map((option) => ( - - ))} - - - - - - - - - Other - {user?.email} - - - - - - + + + ); + } + + return ( + + + + + Cancel + + Add event + + Save + + + + + + + + + + + + All-day + + setIsAllDay(value)} + /> + + + + + {!isAllDay && ( + + )} + + + {!isAllDay && ( + + + + + )} + + + + setRepeatInterval(items)} + placeholder="Doest not repeat" + style={{ marginLeft: 10, flex: 1 }} + mode={Picker.modes.MULTI} + getLabel={getRepeatLabel} + > + {daysOfWeek.map((option) => ( + + ))} + + + + + + + + + Other + {user?.email} + + + + + + + ); }; diff --git a/components/pages/grocery/EditGroceryItem.tsx b/components/pages/grocery/EditGroceryItem.tsx index 6e4bf68..2d8d6d1 100644 --- a/components/pages/grocery/EditGroceryItem.tsx +++ b/components/pages/grocery/EditGroceryItem.tsx @@ -1,28 +1,60 @@ -import { View, Text } from 'react-native' -import React from 'react' -import { TextField } from 'react-native-ui-lib' -import CategoryDropdown from './CategoryDropdown' -import { GroceryCategory } from '@/contexts/GroceryContext' +import { View, Text } from "react-native"; +import React, { useEffect, useState } from "react"; +import { TextField } from "react-native-ui-lib"; +import { + GroceryCategory, + IGrocery, + useGroceryContext, +} from "@/contexts/GroceryContext"; +import { TouchableWithoutFeedback } from "react-native-gesture-handler"; -const EditGroceryItem = (props: {title: string, setTitle: (value: string) => void, setCategory: (category: GroceryCategory) => void}) => { - return ( - - props.setTitle(value)} - maxLength={25} - /> - - - ) +interface IEditGrocery { + id?: number; + title: string; + setTitle: (value: string) => void; + setCategory?: (category: GroceryCategory) => void; + category: GroceryCategory; + setSubmit?: (value: boolean) => void; + updateCategory?: (id: number, changes: Partial) => void; + closeEdit?: (value: boolean) => void; } -export default EditGroceryItem \ No newline at end of file +const EditGroceryItem = ({ editGrocery }: { editGrocery: IEditGrocery }) => { + const { fuzzyMatchGroceryCategory } = useGroceryContext(); + + useEffect(() => { + if (editGrocery.setCategory) + editGrocery.setCategory(fuzzyMatchGroceryCategory(editGrocery.title)); + }, [editGrocery.title]); + + return ( + + { + editGrocery.setTitle(value); + }} + onSubmitEditing={() => { + if (editGrocery.setSubmit) editGrocery.setSubmit(true); + if (editGrocery.closeEdit) editGrocery.closeEdit(false); + if (editGrocery.updateCategory && editGrocery.id) + editGrocery.updateCategory(editGrocery.id, { + category: fuzzyMatchGroceryCategory(editGrocery.title), title: editGrocery.title + }); + }} + maxLength={25} + /> + {editGrocery.category} + + ); +}; + +export default EditGroceryItem; diff --git a/components/pages/grocery/GroceryItem.tsx b/components/pages/grocery/GroceryItem.tsx index ef12135..05e30c2 100644 --- a/components/pages/grocery/GroceryItem.tsx +++ b/components/pages/grocery/GroceryItem.tsx @@ -17,6 +17,7 @@ import { import EditGroceryFrequency from "./EditGroceryFrequency"; import { TextInput } from "react-native"; import EditGroceryItem from "./EditGroceryItem"; +import { TouchableWithoutFeedback } from "react-native-gesture-handler"; const GroceryItem = ({ item, @@ -31,6 +32,7 @@ const GroceryItem = ({ const [openFreqEdit, setOpenFreqEdit] = useState(false); const [isEditingTitle, setIsEditingTitle] = useState(false); const [newTitle, setNewTitle] = useState(""); + const [category, setCategory] = useState(GroceryCategory.None); const handleTitleChange = (newTitle: string) => { updateGroceryItem(item.id, { title: newTitle }); @@ -46,6 +48,7 @@ const GroceryItem = ({ return ( - {/* - } - />*/} {!isEditingTitle ? ( setIsEditingTitle(true)}> {item.title} - { /* - { - setIsEditingTitle(false); - console.log(groceries); - }} - autoFocus - style={{ - fontSize: 16, - padding: 0, - margin: 0, - fontWeight: "bold", - }} - /> - */} ) : ( - + )} diff --git a/components/pages/grocery/GroceryList.tsx b/components/pages/grocery/GroceryList.tsx index e8ba6c9..25106e7 100644 --- a/components/pages/grocery/GroceryList.tsx +++ b/components/pages/grocery/GroceryList.tsx @@ -31,6 +31,7 @@ const GroceryList = () => { GroceryCategory.Bakery ); const [title, setTitle] = useState(""); + const [submit, setSubmitted] = useState(false); // Group approved groceries by category const approvedGroceriesByCategory = approvedGroceries.reduce( @@ -46,19 +47,27 @@ const GroceryList = () => { ); useEffect(() => { - if (title?.length > 2 && title?.length <= 25) { - addGrocery({ - id: 0, - title: title, - category: category, - approved: false, - recurring: false, - frequency: GroceryFrequency.Never, - bought: false, - }); - - setIsAddingGrocery(false); + if(submit){ + if (title?.length > 2 && title?.length <= 25) { + addGrocery({ + id: 0, + title: title, + category: category, + approved: false, + recurring: false, + frequency: GroceryFrequency.Never, + bought: false, + }); + + setIsAddingGrocery(false); + setSubmitted(false); + setTitle(""); + } } + }, [submit]); + + useEffect(() => { + /**/ }, [category]); useEffect(() => { @@ -67,7 +76,7 @@ const GroceryList = () => { }, [groceries]); return ( - + {