From f4238c5399366cd64d80cf8bfec37e6ce0b02e59 Mon Sep 17 00:00:00 2001 From: Dennis Lustre Date: Thu, 23 May 2024 01:59:35 -0700 Subject: [PATCH 1/2] filter events by restaurant, add events to global state --- apps/expo/src/app/events/_layout.tsx | 18 --- .../events/event/{[id].tsx => [title].tsx} | 41 +++-- apps/expo/src/app/events/eventsContext.tsx | 24 --- apps/expo/src/app/events/index.tsx | 150 ++++++++++-------- apps/expo/src/app/home/index.tsx | 30 ++-- apps/expo/src/app/home/item/[id].tsx | 10 +- apps/expo/src/components/RestaurantTabs.tsx | 4 +- apps/expo/src/utils/api.tsx | 19 +-- apps/expo/src/utils/index.ts | 4 +- .../{useMenuStore.ts => useZotmealStore.ts} | 14 +- 10 files changed, 154 insertions(+), 160 deletions(-) delete mode 100644 apps/expo/src/app/events/_layout.tsx rename apps/expo/src/app/events/event/{[id].tsx => [title].tsx} (73%) delete mode 100644 apps/expo/src/app/events/eventsContext.tsx rename apps/expo/src/utils/{useMenuStore.ts => useZotmealStore.ts} (61%) diff --git a/apps/expo/src/app/events/_layout.tsx b/apps/expo/src/app/events/_layout.tsx deleted file mode 100644 index 0b8d0277..00000000 --- a/apps/expo/src/app/events/_layout.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Stack } from "expo-router" -import { EventsProvider } from "./eventsContext" - -export default function EventsLayout() { - return ( - - - - - - - ) -} \ No newline at end of file diff --git a/apps/expo/src/app/events/event/[id].tsx b/apps/expo/src/app/events/event/[title].tsx similarity index 73% rename from apps/expo/src/app/events/event/[id].tsx rename to apps/expo/src/app/events/event/[title].tsx index bb3be47a..9bb4d8b0 100644 --- a/apps/expo/src/app/events/event/[id].tsx +++ b/apps/expo/src/app/events/event/[title].tsx @@ -1,5 +1,5 @@ -import React, { useContext } from "react"; -import { Stack, useGlobalSearchParams } from "expo-router"; +import React from "react"; +import { Redirect, Stack, useGlobalSearchParams } from "expo-router"; import { CalendarClock, ChevronDown, @@ -22,21 +22,30 @@ import { import type { Event } from "@zotmeal/db"; -import { useMenuStore } from "~/utils"; - -import { useEvents } from "../eventsContext"; +import useZotmealStore from "~/utils/useZotmealStore"; export default function Event() { - const { id } = useGlobalSearchParams(); - const { selectedRestaurant } = useMenuStore(); - const { events } = useEvents() - const eventData = events[Number(id)]! + const { title } = useGlobalSearchParams(); + + if (!title || typeof title !== "string") + throw new Error("title is not a string"); + + const { selectedRestaurant, anteateryEvents, brandywineEvents } = + useZotmealStore(); + + const events = + selectedRestaurant === "anteatery" ? anteateryEvents : brandywineEvents; + + const event = events.find((event) => event.title === title); + + // TODO: Log error if event is not found + if (!event) return ; return ( <> -

{eventData.title}

+

{event.title}

@@ -81,13 +90,13 @@ export default function Event() { - {format(eventData.start.toString(), "LLL do p")} -{" "} - {format(eventData.end.toString(), "LLL do p")} + {format(event.start.toString(), "LLL do p")} -{" "} + {format(event.end.toString(), "LLL do p")} - {eventData.shortDescription} + {event.shortDescription}
@@ -115,7 +124,7 @@ export default function Event() { borderTopLeftRadius={0} borderTopRightRadius={0} > - {eventData.longDescription} + {event.longDescription} diff --git a/apps/expo/src/app/events/eventsContext.tsx b/apps/expo/src/app/events/eventsContext.tsx deleted file mode 100644 index 877a71db..00000000 --- a/apps/expo/src/app/events/eventsContext.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { createContext, useState, useContext, ReactNode } from 'react'; -import type { Event } from "@zotmeal/db" - -interface EventsContextProps { - events: Event[]; - setEvents: React.Dispatch>; -} - -const EventsContext = createContext({events: [], setEvents: () => {}}); - -export function EventsProvider(props: { children: ReactNode }) { - const [events, setEvents] = useState([]); - - return ( - - {props.children} - - ); -}; - -export function useEvents() { - const context = useContext(EventsContext); - return context; - }; \ No newline at end of file diff --git a/apps/expo/src/app/events/index.tsx b/apps/expo/src/app/events/index.tsx index 5780ad63..7acd3c6b 100644 --- a/apps/expo/src/app/events/index.tsx +++ b/apps/expo/src/app/events/index.tsx @@ -1,18 +1,17 @@ -import { useEffect} from "react"; +import { useEffect } from "react"; import { Link } from "expo-router"; import { format } from "date-fns"; -import { H3, Image, ScrollView, Text, YStack } from "tamagui"; +import { H3, Image, Tabs, Text, YStack } from "tamagui"; import type { Event } from "@zotmeal/db"; -import { useEvents } from "./eventsContext"; +import { getRestaurantNameById } from "@zotmeal/utils"; import { RestaurantTabs } from "~/components"; - import { api } from "~/utils/api"; - +import useZotmealStore from "~/utils/useZotmealStore"; // Create a context for events, default value is a test event -const testData: Event = { +const _testData = { start: new Date("2022-01-01 12:00:00"), end: new Date(), title: "Test Event", @@ -25,17 +24,76 @@ const testData: Event = { restaurantId: "3314", } satisfies Event; +const EventCard = ({ event }: Readonly<{ event: Event }>) => ( + + + + + +

{event.title}

+ + {format(event.start.toString(), "LLL do p")} -{" "} + {format(event.end.toString(), "LLL do p")} + +
+ +); + // Events Component export default function Events() { - const { events, setEvents } = useEvents(); + const { + anteateryEvents, + brandywineEvents, + setAnteateryEvents, + setBrandywineEvents, + } = useZotmealStore(); const eventsQuery = api.event.get.useQuery({}); useEffect(() => { - if (eventsQuery?.data) { - setEvents(eventsQuery.data); - } - }, [eventsQuery?.data]); + if (!eventsQuery?.data) return; + + const anteateryEvents = eventsQuery.data.filter( + (event: Event) => event.restaurantId === "3056", + ); + const brandywineEvents = eventsQuery.data.filter( + (event: Event) => event.restaurantId === "3314", + ); + + setAnteateryEvents(anteateryEvents); + setBrandywineEvents(brandywineEvents); + }, [eventsQuery.data, setAnteateryEvents, setBrandywineEvents]); if (eventsQuery?.isLoading) { return Loading...; @@ -44,61 +102,25 @@ export default function Events() { if (eventsQuery?.isError) { return Error: {eventsQuery.error.message}; } + + if (!anteateryEvents || !brandywineEvents) { + return No events found; + } + return ( - - {events.map((event: Event, index: number) => ( - - - - - -

{event.title}

- - {format(event.start.toString(), "LLL do p")} -{" "} - {format(event.end.toString(), "LLL do p")} - -
- - ))} -
+ {[brandywineEvents, anteateryEvents].map((events, index) => ( + + + {events.map((event, index) => ( + + ))} + + + ))}
); } diff --git a/apps/expo/src/app/home/index.tsx b/apps/expo/src/app/home/index.tsx index b162f9cc..ca2a8d1f 100644 --- a/apps/expo/src/app/home/index.tsx +++ b/apps/expo/src/app/home/index.tsx @@ -14,15 +14,15 @@ import { } from "@zotmeal/utils"; import { RestaurantTabs } from "~/components"; -import { useMenuStore } from "~/utils"; import { api } from "~/utils/api"; +import useZotmealStore from "~/utils/useZotmealStore"; +import { EventToast } from "./_components/event-toast"; import { PeriodPicker } from "./_components/period-picker"; import { StationTabs } from "./_components/station-tabs"; -import { EventToast } from './_components/event-toast'; export function Home() { const { anteateryMenu, brandywineMenu, setAnteateryMenu, setBrandywineMenu } = - useMenuStore(); + useZotmealStore(); const toast = useToastController(); @@ -101,6 +101,10 @@ export function Home() { ); } + if (!anteateryMenu || !brandywineMenu) { + return Menus not found; + } + return ( @@ -140,18 +144,14 @@ export function Home() { {[brandywineMenu, anteateryMenu].map((menu) => ( - <> - {menu && ( - - - - )} - + + + ))} ); diff --git a/apps/expo/src/app/home/item/[id].tsx b/apps/expo/src/app/home/item/[id].tsx index f454d2f7..f143707d 100644 --- a/apps/expo/src/app/home/item/[id].tsx +++ b/apps/expo/src/app/home/item/[id].tsx @@ -17,19 +17,19 @@ import { import type { NutritionInfo } from "@zotmeal/db"; import { PinButton } from "~/components"; -import { useMenuStore } from "~/utils"; +import useZotmealStore from "~/utils/useZotmealStore"; import RateItem from "./RateItem"; export default function MenuItem() { const theme = useTheme(); const { id, stationId } = useGlobalSearchParams(); - if (!id || typeof id !== "string") - throw new Error("unreachable: id is not a string"); + if (!id || typeof id !== "string") throw new Error("id is not a string"); if (!stationId || typeof stationId !== "string") - throw new Error("unreachable: stationId is not a string"); + throw new Error("stationId is not a string"); - const { selectedRestaurant, anteateryMenu, brandywineMenu } = useMenuStore(); + const { selectedRestaurant, anteateryMenu, brandywineMenu } = + useZotmealStore(); const menu = selectedRestaurant === "anteatery" ? anteateryMenu : brandywineMenu; diff --git a/apps/expo/src/components/RestaurantTabs.tsx b/apps/expo/src/components/RestaurantTabs.tsx index eea0d576..89226238 100644 --- a/apps/expo/src/components/RestaurantTabs.tsx +++ b/apps/expo/src/components/RestaurantTabs.tsx @@ -5,14 +5,14 @@ import { Image, Tabs, useTheme, useWindowDimensions, View } from "tamagui"; import type { Restaurant } from "@zotmeal/db"; import { getCurrentPeriodName } from "@zotmeal/utils"; -import useMenuStore from "~/utils/useMenuStore"; +import useZotmealStore from "~/utils/useZotmealStore"; export default function RestaurantTabs({ children, }: Readonly<{ children: React.ReactNode; }>) { - const { selectedRestaurant, setSelectedRestaurant } = useMenuStore(); + const { selectedRestaurant, setSelectedRestaurant } = useZotmealStore(); return ( <> diff --git a/apps/expo/src/utils/api.tsx b/apps/expo/src/utils/api.tsx index a156264a..8149ae27 100644 --- a/apps/expo/src/utils/api.tsx +++ b/apps/expo/src/utils/api.tsx @@ -30,16 +30,14 @@ const getBaseUrl = () => { const debuggerHost = Constants.expoConfig?.hostUri; const localhost = debuggerHost?.split(":")[0]; - if (!localhost) { - // return "https://turbo.t3.gg"; - throw new Error( - "Failed to get localhost. Please point to your production server.", - ); - } + // if (!localhost) { + // // return "https://turbo.t3.gg"; + // throw new Error( + // "Failed to get localhost. Please point to your production server.", + // ); + // } - if (Platform.OS == "android") { - return `http://10.0.2.2:3000`; - } + if (Platform.OS === "android") return `http://10.0.2.2:3000`; return `http://localhost:3000`; }; @@ -52,12 +50,11 @@ export function TRPCProvider(props: { children: React.ReactNode }) { const [queryClient] = useState(() => new QueryClient()); const [trpcClient] = useState(() => { const url = getBaseUrl(); - console.error("hello", url); return api.createClient({ links: [ httpBatchLink({ + url, transformer: superjson, - url: url, headers() { const headers = new Map(); headers.set("x-trpc-source", "expo-react"); diff --git a/apps/expo/src/utils/index.ts b/apps/expo/src/utils/index.ts index 2e4d30f2..4766245c 100644 --- a/apps/expo/src/utils/index.ts +++ b/apps/expo/src/utils/index.ts @@ -1,5 +1,5 @@ import { TRPCProvider } from "./api"; import groupBy from "./groupBy"; -import useMenuStore from "./useMenuStore"; +import useZotmealStore from "./useZotmealStore"; -export { TRPCProvider, groupBy, useMenuStore }; +export { TRPCProvider, groupBy, useZotmealStore }; diff --git a/apps/expo/src/utils/useMenuStore.ts b/apps/expo/src/utils/useZotmealStore.ts similarity index 61% rename from apps/expo/src/utils/useMenuStore.ts rename to apps/expo/src/utils/useZotmealStore.ts index 57f04bee..53a6e962 100644 --- a/apps/expo/src/utils/useMenuStore.ts +++ b/apps/expo/src/utils/useZotmealStore.ts @@ -1,27 +1,35 @@ import { create } from "zustand"; -import type { MenuWithRelations, Restaurant } from "@zotmeal/db"; +import type { Event, MenuWithRelations, Restaurant } from "@zotmeal/db"; import type { RestaurantName } from "@zotmeal/utils"; // import { anteateryData, brandywineData } from "../app/home/example_menus"; -interface MenuState { +interface ZotmealState { selectedRestaurant: RestaurantName; anteateryMenu: MenuWithRelations | null; brandywineMenu: MenuWithRelations | null; + anteateryEvents: Event[]; + brandywineEvents: Event[]; setSelectedRestaurant: (restaurant: RestaurantName) => void; setAnteateryMenu: (anteateryMenu: MenuWithRelations) => void; setBrandywineMenu: (brandywineMenu: MenuWithRelations) => void; + setAnteateryEvents: (anteateryEvents: Event[]) => void; + setBrandywineEvents: (brandywineEvents: Event[]) => void; } -export default create((set) => ({ +export default create((set) => ({ selectedRestaurant: "brandywine", anteateryMenu: null, brandywineMenu: null, + anteateryEvents: [], + brandywineEvents: [], setSelectedRestaurant: (selectedRestaurant: Restaurant["name"]) => set({ selectedRestaurant }), setAnteateryMenu: (anteateryMenu: MenuWithRelations) => set({ anteateryMenu }), setBrandywineMenu: (brandywineMenu: MenuWithRelations) => set({ brandywineMenu }), + setAnteateryEvents: (anteateryEvents: Event[]) => set({ anteateryEvents }), + setBrandywineEvents: (brandywineEvents: Event[]) => set({ brandywineEvents }), })); From ae1404161fd91f019cbeffb30cb08a2292feb708 Mon Sep 17 00:00:00 2001 From: Dennis Lustre Date: Thu, 23 May 2024 23:02:26 -0700 Subject: [PATCH 2/2] fix redirect paths --- apps/expo/src/app/events/event/[title].tsx | 2 + apps/expo/src/app/home/index.tsx | 40 +++++++++---------- apps/expo/src/app/home/item/RateItem.tsx | 2 +- apps/expo/src/app/home/item/[id].tsx | 6 +-- .../components/navigation/HamburgerMenu.tsx | 8 +++- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/apps/expo/src/app/events/event/[title].tsx b/apps/expo/src/app/events/event/[title].tsx index 9bb4d8b0..2529e97f 100644 --- a/apps/expo/src/app/events/event/[title].tsx +++ b/apps/expo/src/app/events/event/[title].tsx @@ -46,6 +46,8 @@ export default function Event() { restaurantNames.map((restaurantName) => - t.menu.get({ - date: date.toLocaleDateString("en-US"), - period: periodName, - restaurant: restaurantName, - }), + t.menu.get( + { + date: date.toLocaleDateString("en-US"), + period: periodName, + restaurant: restaurantName, + }, + { + refetchOnWindowFocus: false, + }, + ), ), ); useEffect(() => { - if (anteateryQuery?.data) { - setAnteateryMenu(anteateryQuery.data); - } - - if (brandywineQuery?.data) { - setBrandywineMenu(brandywineQuery.data); - } + if (anteateryQuery?.data) setAnteateryMenu(anteateryQuery.data); + if (brandywineQuery?.data) setBrandywineMenu(brandywineQuery.data); if ( anteateryQuery && @@ -81,14 +81,12 @@ export function Home() { toast, ]); - if (!anteateryQuery || !brandywineQuery) { - return Fetching menus; - } + if (!anteateryQuery || !brandywineQuery) + throw new Error("Unreachable: anteateryQuery and brandywineQuery are null"); // TODO: maybe loading spinner instead - if (anteateryQuery.isLoading || brandywineQuery.isLoading) { + if (anteateryQuery.isLoading || brandywineQuery.isLoading) return Loading...; - } if (anteateryQuery.isError || brandywineQuery.isError) { console.error(anteateryQuery.error, brandywineQuery.error); @@ -100,9 +98,7 @@ export function Home() { ); } - if (!anteateryMenu || !brandywineMenu) { - return Menus not found; - } + if (!anteateryMenu || !brandywineMenu) return Menus not found; return ( @@ -143,7 +139,7 @@ export function Home() { /> )} - + (5); return ( - +