diff --git a/apps/expo/app.config.ts b/apps/expo/app.config.ts index a6fef3c2..6a6202d2 100644 --- a/apps/expo/app.config.ts +++ b/apps/expo/app.config.ts @@ -1,12 +1,14 @@ -import type { ExpoConfig } from "expo/config"; +import type { ConfigContext, ExpoConfig } from "expo/config"; const image = "./assets/zotmeal.png"; +const name = "ZotMeal"; const backgroundColor = "#161B22"; -const defineConfig = (): ExpoConfig => ({ - name: "expo", - slug: "expo", - scheme: "expo", +export default ({ config }: ConfigContext): ExpoConfig => ({ + ...config, + name, + slug: name.toLowerCase(), + scheme: name.toLowerCase(), version: "0.1.0", orientation: "portrait", icon: image, @@ -43,5 +45,3 @@ const defineConfig = (): ExpoConfig => ({ }, plugins: ["expo-router", "expo-font"], }); - -export default defineConfig; diff --git a/apps/expo/babel.config.js b/apps/expo/babel.config.js new file mode 100644 index 00000000..2641eb50 --- /dev/null +++ b/apps/expo/babel.config.js @@ -0,0 +1,20 @@ +/** @type {import("@babel/core").ConfigFunction} */ +module.exports = function (api) { + api.cache(true); + return { + presets: ["babel-preset-expo", "@babel/preset-typescript"], + plugins: [ + [ + "@tamagui/babel-plugin", + { + components: ["tamagui"], + config: "./tamagui.config.ts", + logTimings: true, + disableExtraction: process.env.NODE_ENV === "development", + }, + ], + // NOTE: this is only necessary if you are using reanimated for animations + "react-native-reanimated/plugin", + ], + }; +}; diff --git a/apps/expo/src/app/_layout.tsx b/apps/expo/src/app/_layout.tsx index 419f2856..26dbcac6 100644 --- a/apps/expo/src/app/_layout.tsx +++ b/apps/expo/src/app/_layout.tsx @@ -2,69 +2,22 @@ import { config } from "@tamagui/config/v3"; import "@tamagui/core/reset.css"; -import { useState } from "react"; -import { Platform } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useFonts } from "expo-font"; import { Stack } from "expo-router"; import { StatusBar } from "expo-status-bar"; import { ClerkProvider } from "@clerk/clerk-expo"; -import { Info } from "@tamagui/lucide-icons"; import { ToastProvider, ToastViewport } from "@tamagui/toast"; -import { - Button, - createTamagui, - TamaguiProvider, - Text, - Theme, - View, -} from "tamagui"; +import { createTamagui, TamaguiProvider, Theme } from "tamagui"; -import { Logo } from "~/components"; +import { DevInfo, Logo } from "~/components"; import { HamburgerMenu } from "~/components/navigation/HamburgerMenu"; import { TRPCProvider, useZotmealColorScheme } from "~/utils"; -import { getBaseUrl } from "~/utils/api"; import { tokenCache } from "~/utils/tokenCache"; import { env } from "../utils/env"; const tamaguiConfig = createTamagui(config); -const DevInfo = () => { - const [open, setOpen] = useState(false); - - return ( - setOpen(!open)} - zIndex={10} - width={open ? "60%" : "10%"} - height={open ? "25%" : "10%"} - position="absolute" - bottom={30} - right={10} - > - {open ? ( - - ) : ( - - )} - - ); -}; - export default function RootLayout() { const [loaded] = useFonts({ Inter: require("@tamagui/font-inter/otf/Inter-Medium.otf"), @@ -72,7 +25,7 @@ export default function RootLayout() { }); const colorScheme = useZotmealColorScheme(); - const { top, ...insets } = useSafeAreaInsets(); + const insets = useSafeAreaInsets(); if (!loaded) return null; diff --git a/apps/expo/src/app/index.tsx b/apps/expo/src/app/index.tsx index 0bc1b81e..335f27a7 100644 --- a/apps/expo/src/app/index.tsx +++ b/apps/expo/src/app/index.tsx @@ -1,9 +1,8 @@ import React from "react"; -import { Platform } from "react-native"; -import { AlertTriangle, RefreshCw } from "@tamagui/lucide-icons"; -import { addDays, isWithinInterval } from "date-fns"; +import { Platform, RefreshControl } from "react-native"; +import { AlertTriangle } from "@tamagui/lucide-icons"; +import { isWithinInterval } from "date-fns"; import { - Button, ScrollView, Spinner, Tabs, @@ -23,7 +22,7 @@ import { UniversalDatePicker } from "../components/ui/UniversalDatePicker"; export default function Home() { const theme = useTheme(); - const [date, setDate] = React.useState(addDays(new Date(), -1)); + const [date, setDate] = React.useState(new Date()); const [period, setPeriod] = React.useState(null); const [restaurant, setRestaurant] = React.useState("brandywine"); @@ -68,9 +67,13 @@ export default function Home() { ); // ! Not sure if this is actually working but we do want debouncing for the refresh button - const refetchWithDebounce = useDebounce(() => query.refetch(), 1000, { - leading: true, - }); + const refetchWithDebounce = useDebounce( + async () => await query.refetch(), + 1000, + { + leading: true, + }, + ); // const toast = useToastController(); // useEffect(() => { @@ -87,12 +90,13 @@ export default function Home() { // }, [data, toast]); // TODO: show a toast if there is an error - const brandywineMenuAtPeriod = brandywineInfo?.menus.find( + // Get the stations for the current period + const brandywineStations = brandywineInfo?.menus.find( (menu) => menu.period.name === period, - ); - const anteateryMenuAtPeriod = anteateryInfo?.menus.find( + )?.stations; + const anteateryStations = anteateryInfo?.menus.find( (menu) => menu.period.name === period, - ); + )?.stations; // TODO: make it not possible to click into the menu if it's loading const MenuContent = () => ( @@ -113,8 +117,8 @@ export default function Home() { marginVertical={200} /> ) : null} - {brandywineInfo && brandywineMenuAtPeriod ? ( - + {brandywineInfo && brandywineStations ? ( + ) : query.isPending ? null : ( @@ -138,8 +142,8 @@ export default function Home() { marginVertical={200} /> ) : null} - {anteateryInfo && anteateryMenuAtPeriod ? ( - + {anteateryInfo && anteateryStations ? ( + ) : query.isPending ? null : ( @@ -157,7 +161,20 @@ export default function Home() { anteateryStatus={currentAnteateryPeriod ? "open" : "closed"} brandywineStatus={currentBrandywinePeriod ? "open" : "closed"} > - + + ); +} diff --git a/apps/expo/src/components/ui/UniversalDatePicker.tsx b/apps/expo/src/components/ui/UniversalDatePicker.tsx index 4006577c..e2eabafe 100644 --- a/apps/expo/src/components/ui/UniversalDatePicker.tsx +++ b/apps/expo/src/components/ui/UniversalDatePicker.tsx @@ -16,7 +16,9 @@ export const UniversalDatePicker = ({ date, setDate, }: Readonly<{ date: Date; setDate: (date: Date) => void }>) => { - const [showDatePicker, setShowDatePicker] = useState(false); + const [showDatePicker, setShowDatePicker] = useState( + Platform.OS === "ios", + ); return ( <> @@ -41,9 +43,7 @@ export const UniversalDatePicker = ({ onChange={(_, selectedDate) => { // hide date picker on android setShowDatePicker(Platform.OS === "ios"); - if (selectedDate) { - setDate(selectedDate); - } + if (selectedDate) setDate(selectedDate); }} /> )} diff --git a/apps/expo/src/components/ui/index.ts b/apps/expo/src/components/ui/index.ts index b3d6eab1..1b4e8d65 100644 --- a/apps/expo/src/components/ui/index.ts +++ b/apps/expo/src/components/ui/index.ts @@ -7,3 +7,4 @@ export * from "./UniversalDatePicker"; export * from "./EventToast"; export * from "./DishCard"; export * from "./StationTabs"; +export * from "./DevInfo"; diff --git a/apps/expo/src/hooks/useWarmUpBrowser.tsx b/apps/expo/src/hooks/useWarmUpBrowser.tsx index 22199094..3a626496 100644 --- a/apps/expo/src/hooks/useWarmUpBrowser.tsx +++ b/apps/expo/src/hooks/useWarmUpBrowser.tsx @@ -1,9 +1,13 @@ import React from "react"; +import { Platform } from "react-native"; import * as WebBrowser from "expo-web-browser"; -export const useWarmUpBrowser = () => { - React.useEffect(() => { - void WebBrowser.warmUpAsync(); - return () => void WebBrowser.coolDownAsync(); - }, []); -}; +export const useWarmUpBrowser = + Platform.OS === "web" + ? () => {} + : () => { + React.useEffect(() => { + void WebBrowser.warmUpAsync(); + return () => void WebBrowser.coolDownAsync(); + }, []); + }; diff --git a/apps/expo/src/hooks/useWarmUpBrowser.web.tsx b/apps/expo/src/hooks/useWarmUpBrowser.web.tsx deleted file mode 100644 index e3c00174..00000000 --- a/apps/expo/src/hooks/useWarmUpBrowser.web.tsx +++ /dev/null @@ -1 +0,0 @@ -export const useWarmUpBrowser = () => undefined; diff --git a/apps/server/README.md b/apps/server/README.md index 935e760d..6e3e59c5 100644 --- a/apps/server/README.md +++ b/apps/server/README.md @@ -8,7 +8,7 @@ For detailed instructions, please refer to the [documentation](https://www.serve Depending on your preferred package manager, follow the instructions below to deploy your project. -> **Requirements**: NodeJS `lts/fermium (v.14.15.0)`. If you're using [nvm](https://github.com/nvm-sh/nvm), run `nvm use` to ensure you're using the same Node version in local and in your lambda's runtime. +> **Requirements**: Node version: `lts/*`. If you're using [nvm](https://github.com/nvm-sh/nvm), run `nvm use` to ensure you're using the same Node version in local and in your lambda's runtime. ### Using NPM @@ -43,7 +43,7 @@ Check the [sls invoke local command documentation](https://www.serverless.com/fr Copy and replace your `url` - found in Serverless `deploy` command output - and `name` parameter in the following `curl` command in your terminal or in Postman to test your newly deployed application. -``` +```sh curl --location --request POST 'https://myApiEndpoint/dev/hello' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -60,7 +60,7 @@ The project code base is mainly located within the `src` folder. This folder is - `functions` - containing code base and configuration for your lambda functions - `libs` - containing shared code base between your lambdas -``` +```sh . ├── src │ ├── functions # Lambda configuration and source code folder @@ -87,7 +87,7 @@ The project code base is mainly located within the `src` folder. This folder is ### 3rd party libraries - [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts) - uses JSON-Schema definitions used by API Gateway for HTTP request validation to statically generate TypeScript types in your lambda's handler code base -- [middy](https://github.com/middyjs/middy) - middleware engine for Node.Js lambda. This template uses [http-json-body-parser](https://github.com/middyjs/middy/tree/master/packages/http-json-body-parser) to convert API Gateway `event.body` property, originally passed as a stringified JSON, to its corresponding parsed object +- [middy](https://github.com/middyjs/middy) - middleware engine for Node.js lambda. This template uses [http-json-body-parser](https://github.com/middyjs/middy/tree/master/packages/http-json-body-parser) to convert API Gateway `event.body` property, originally passed as a stringified JSON, to its corresponding parsed object - [@serverless/typescript](https://github.com/serverless/typescript) - provides up-to-date TypeScript definitions for your `serverless.ts` service file ### Advanced usage diff --git a/packages/api/src/notifications/router.ts b/packages/api/src/notifications/router.ts index 042f9c58..bb80649f 100644 --- a/packages/api/src/notifications/router.ts +++ b/packages/api/src/notifications/router.ts @@ -6,9 +6,7 @@ import { pushTokens, PushTokenSchema } from "@zotmeal/db"; export const registerPushToken = publicProcedure .input(PushTokenSchema) - .query(async ({ ctx, input }) => { - const { db } = ctx; - + .query(async ({ ctx: { db }, input }) => { if (!Expo.isExpoPushToken(input.token)) { console.error("pushToken", pushTokens); throw new TRPCError({