From aa18f7a5dde599adb895f61f9edb55646ef17adc Mon Sep 17 00:00:00 2001 From: Peam Date: Sun, 16 Jul 2023 10:27:38 +0700 Subject: [PATCH] feat: restaurant api & badge --- package.json | 121 +++---- .../20230715022448_dev/migration.sql | 75 ----- .../20230716025203_add/migration.sql | 148 +++++++++ .../20230716025230_make_default/migration.sql | 5 + .../20230716030605_edit_tag/migration.sql | 32 ++ .../20230716031152_rm_icon/migration.sql | 12 + prisma/schema.prisma | 47 ++- prisma/seed.ts | 44 +++ public/assets/badges/organic_ingredient.png | Bin 0 -> 16601 bytes public/assets/badges/water_recycling.png | Bin 0 -> 2958 bytes public/assets/badges/well_begin.png | Bin 0 -> 14004 bytes public/assets/badges/zero_waste.png | Bin 0 -> 15403 bytes src/components/CardRestaurant.tsx | 61 ++-- src/components/Caruosel.tsx | 142 ++++---- src/pages/index.tsx | 306 ++++++++++-------- src/server/api/routers/restaurant.ts | 54 +++- src/utils/badge.ts | 3 + 17 files changed, 668 insertions(+), 382 deletions(-) delete mode 100644 prisma/migrations/20230715022448_dev/migration.sql create mode 100644 prisma/migrations/20230716025203_add/migration.sql create mode 100644 prisma/migrations/20230716025230_make_default/migration.sql create mode 100644 prisma/migrations/20230716030605_edit_tag/migration.sql create mode 100644 prisma/migrations/20230716031152_rm_icon/migration.sql create mode 100644 prisma/seed.ts create mode 100644 public/assets/badges/organic_ingredient.png create mode 100644 public/assets/badges/water_recycling.png create mode 100644 public/assets/badges/well_begin.png create mode 100644 public/assets/badges/zero_waste.png create mode 100644 src/utils/badge.ts diff --git a/package.json b/package.json index 7d7ea3a..a1e67f1 100644 --- a/package.json +++ b/package.json @@ -1,61 +1,64 @@ { - "name": "ywc19-hackathon-h", - "version": "0.1.0", - "private": true, - "scripts": { - "build": "next build", - "dev": "next dev", - "postinstall": "prisma generate", - "lint": "next lint", - "start": "next start" - }, - "dependencies": { - "@next-auth/prisma-adapter": "^1.0.5", - "@prisma/client": "^4.14.0", - "@t3-oss/env-nextjs": "^0.3.1", - "@tanstack/react-query": "^4.29.7", - "@trpc/client": "^10.26.0", - "@trpc/next": "^10.26.0", - "@trpc/react-query": "^10.26.0", - "@trpc/server": "^10.26.0", - "flowbite": "^1.7.0", - "flowbite-react": "^0.4.11", - "framer-motion": "^10.12.21", - "next": "^13.4.2", - "next-auth": "^4.22.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-lazy-load-image-component": "^1.6.0", - "superjson": "1.12.2", - "swiper": "^10.0.4", - "tailwind-merge": "^1.13.2", - "zod": "^3.21.4" - }, - "devDependencies": { - "@types/eslint": "^8.37.0", - "@types/node": "^18.16.0", - "@types/prettier": "^2.7.2", - "@types/react": "^18.2.6", - "@types/react-dom": "^18.2.4", - "@types/react-lazy-load-image-component": "^1.5.3", - "@typescript-eslint/eslint-plugin": "^5.59.6", - "@typescript-eslint/parser": "^5.59.6", - "autoprefixer": "^10.4.14", - "eslint": "^8.40.0", - "eslint-config-next": "^13.4.2", - "postcss": "^8.4.21", - "prettier": "^2.8.8", - "prettier-plugin-tailwindcss": "^0.2.8", - "prisma": "^4.14.0", - "prisma-zod-generator": "^0.8.13", - "tailwindcss": "^3.3.0", - "typescript": "^5.0.4" - }, - "ct3aMetadata": { - "initVersion": "7.15.0" - }, - "volta": { - "node": "16.20.1", - "yarn": "3.6.1" - } + "name": "ywc19-hackathon-h", + "version": "0.1.0", + "private": true, + "scripts": { + "build": "next build", + "dev": "next dev", + "postinstall": "prisma generate", + "lint": "next lint", + "start": "next start" + }, + "dependencies": { + "@next-auth/prisma-adapter": "^1.0.5", + "@prisma/client": "^4.14.0", + "@t3-oss/env-nextjs": "^0.3.1", + "@tanstack/react-query": "^4.29.7", + "@trpc/client": "^10.26.0", + "@trpc/next": "^10.26.0", + "@trpc/react-query": "^10.26.0", + "@trpc/server": "^10.26.0", + "flowbite": "^1.7.0", + "flowbite-react": "^0.4.11", + "framer-motion": "^10.12.21", + "next": "^13.4.2", + "next-auth": "^4.22.1", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-lazy-load-image-component": "^1.6.0", + "superjson": "1.12.2", + "swiper": "^10.0.4", + "tailwind-merge": "^1.13.2", + "zod": "^3.21.4" + }, + "devDependencies": { + "@types/eslint": "^8.37.0", + "@types/node": "^18.16.0", + "@types/prettier": "^2.7.2", + "@types/react": "^18.2.6", + "@types/react-dom": "^18.2.4", + "@types/react-lazy-load-image-component": "^1.5.3", + "@typescript-eslint/eslint-plugin": "^5.59.6", + "@typescript-eslint/parser": "^5.59.6", + "autoprefixer": "^10.4.14", + "eslint": "^8.40.0", + "eslint-config-next": "^13.4.2", + "postcss": "^8.4.21", + "prettier": "^2.8.8", + "prettier-plugin-tailwindcss": "^0.2.8", + "prisma": "^4.14.0", + "prisma-zod-generator": "^0.8.13", + "tailwindcss": "^3.3.0", + "typescript": "^5.0.4" + }, + "ct3aMetadata": { + "initVersion": "7.15.0" + }, + "volta": { + "node": "16.20.1", + "yarn": "3.6.1" + }, + "prisma": { + "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" + } } diff --git a/prisma/migrations/20230715022448_dev/migration.sql b/prisma/migrations/20230715022448_dev/migration.sql deleted file mode 100644 index 8f88957..0000000 --- a/prisma/migrations/20230715022448_dev/migration.sql +++ /dev/null @@ -1,75 +0,0 @@ --- CreateTable -CREATE TABLE "Example" ( - "id" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Example_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Account" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "type" TEXT NOT NULL, - "provider" TEXT NOT NULL, - "providerAccountId" TEXT NOT NULL, - "refresh_token" TEXT, - "access_token" TEXT, - "expires_at" INTEGER, - "token_type" TEXT, - "scope" TEXT, - "id_token" TEXT, - "session_state" TEXT, - - CONSTRAINT "Account_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Session" ( - "id" TEXT NOT NULL, - "sessionToken" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "expires" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Session_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "User" ( - "id" TEXT NOT NULL, - "name" TEXT, - "email" TEXT, - "emailVerified" TIMESTAMP(3), - "image" TEXT, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "VerificationToken" ( - "identifier" TEXT NOT NULL, - "token" TEXT NOT NULL, - "expires" TIMESTAMP(3) NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId"); - --- CreateIndex -CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken"); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); - --- CreateIndex -CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token"); - --- CreateIndex -CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token"); - --- AddForeignKey -ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20230716025203_add/migration.sql b/prisma/migrations/20230716025203_add/migration.sql new file mode 100644 index 0000000..79b69ae --- /dev/null +++ b/prisma/migrations/20230716025203_add/migration.sql @@ -0,0 +1,148 @@ +-- CreateEnum +CREATE TYPE "BookingStatus" AS ENUM ('NOT_PAID', 'PAID'); + +-- CreateTable +CREATE TABLE "Example" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Example_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Account" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "type" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "providerAccountId" TEXT NOT NULL, + "refresh_token" TEXT, + "access_token" TEXT, + "expires_at" INTEGER, + "token_type" TEXT, + "scope" TEXT, + "id_token" TEXT, + "session_state" TEXT, + + CONSTRAINT "Account_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Session" ( + "id" TEXT NOT NULL, + "sessionToken" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Session_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "name" TEXT, + "email" TEXT, + "emailVerified" TIMESTAMP(3), + "image" TEXT, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "VerificationToken" ( + "identifier" TEXT NOT NULL, + "token" TEXT NOT NULL, + "expires" TIMESTAMP(3) NOT NULL +); + +-- CreateTable +CREATE TABLE "Booking" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "bookedTime" TIMESTAMP(3) NOT NULL, + "status" "BookingStatus" NOT NULL, + + CONSTRAINT "Booking_pkey" PRIMARY KEY ("userId","menuId","id") +); + +-- CreateTable +CREATE TABLE "Restaurant" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "location" TEXT NOT NULL, + "imageUrl" TEXT, + "isRecommended" BOOLEAN NOT NULL, + + CONSTRAINT "Restaurant_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Menu" ( + "id" TEXT NOT NULL, + "restaurantId" TEXT, + "name" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "isRecommended" BOOLEAN NOT NULL, + + CONSTRAINT "Menu_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Tag" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "icon" TEXT NOT NULL, + + CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_MenuToTag" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token"); + +-- CreateIndex +CREATE UNIQUE INDEX "_MenuToTag_AB_unique" ON "_MenuToTag"("A", "B"); + +-- CreateIndex +CREATE INDEX "_MenuToTag_B_index" ON "_MenuToTag"("B"); + +-- AddForeignKey +ALTER TABLE "Account" ADD CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Booking" ADD CONSTRAINT "Booking_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Booking" ADD CONSTRAINT "Booking_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Menu" ADD CONSTRAINT "Menu_restaurantId_fkey" FOREIGN KEY ("restaurantId") REFERENCES "Restaurant"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_MenuToTag" ADD CONSTRAINT "_MenuToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Menu"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_MenuToTag" ADD CONSTRAINT "_MenuToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20230716025230_make_default/migration.sql b/prisma/migrations/20230716025230_make_default/migration.sql new file mode 100644 index 0000000..add2cd0 --- /dev/null +++ b/prisma/migrations/20230716025230_make_default/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "Menu" ALTER COLUMN "isRecommended" SET DEFAULT false; + +-- AlterTable +ALTER TABLE "Restaurant" ALTER COLUMN "isRecommended" SET DEFAULT false; diff --git a/prisma/migrations/20230716030605_edit_tag/migration.sql b/prisma/migrations/20230716030605_edit_tag/migration.sql new file mode 100644 index 0000000..52ca4de --- /dev/null +++ b/prisma/migrations/20230716030605_edit_tag/migration.sql @@ -0,0 +1,32 @@ +/* + Warnings: + + - You are about to drop the `_MenuToTag` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "_MenuToTag" DROP CONSTRAINT "_MenuToTag_A_fkey"; + +-- DropForeignKey +ALTER TABLE "_MenuToTag" DROP CONSTRAINT "_MenuToTag_B_fkey"; + +-- DropTable +DROP TABLE "_MenuToTag"; + +-- CreateTable +CREATE TABLE "_RestaurantToTag" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "_RestaurantToTag_AB_unique" ON "_RestaurantToTag"("A", "B"); + +-- CreateIndex +CREATE INDEX "_RestaurantToTag_B_index" ON "_RestaurantToTag"("B"); + +-- AddForeignKey +ALTER TABLE "_RestaurantToTag" ADD CONSTRAINT "_RestaurantToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Restaurant"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_RestaurantToTag" ADD CONSTRAINT "_RestaurantToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20230716031152_rm_icon/migration.sql b/prisma/migrations/20230716031152_rm_icon/migration.sql new file mode 100644 index 0000000..4b12922 --- /dev/null +++ b/prisma/migrations/20230716031152_rm_icon/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - You are about to drop the column `icon` on the `Tag` table. All the data in the column will be lost. + - A unique constraint covering the columns `[name]` on the table `Tag` will be added. If there are existing duplicate values, this will fail. + +*/ +-- AlterTable +ALTER TABLE "Tag" DROP COLUMN "icon"; + +-- CreateIndex +CREATE UNIQUE INDEX "Tag_name_key" ON "Tag"("name"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 96119ec..0029126 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -52,7 +52,7 @@ model User { image String? accounts Account[] sessions Session[] - Booking Booking[] + bookings Booking[] } model VerificationToken { @@ -64,16 +64,45 @@ model VerificationToken { } model Booking { - id String @default(cuid()) - userId String - user User @relation(fields: [userId], references: [id]) - restaurantId String - restaurant Restaurant @relation(fields: [restaurantId], references: [id]) + id String @default(cuid()) + userId String + user User @relation(fields: [userId], references: [id]) + menuId String + menu Menu @relation(fields: [menuId], references: [id]) + bookedTime DateTime + status BookingStatus - @@id([userId, restaurantId, id]) + @@id([userId, menuId, id]) } model Restaurant { - id String @id @default(cuid()) - Booking Booking[] + id String @id @default(cuid()) + name String + description String + location String + imageUrl String? + menus Menu[] + isRecommended Boolean @default(false) + tags Tag[] +} + +model Menu { + id String @id @default(cuid()) + restaurant Restaurant? @relation(fields: [restaurantId], references: [id]) + restaurantId String? + name String + price Int + booking Booking[] + isRecommended Boolean @default(false) +} + +model Tag { + id String @id @default(cuid()) + name String @unique + restaurants Restaurant[] +} + +enum BookingStatus { + NOT_PAID + PAID } diff --git a/prisma/seed.ts b/prisma/seed.ts new file mode 100644 index 0000000..615b0f9 --- /dev/null +++ b/prisma/seed.ts @@ -0,0 +1,44 @@ +import { type Prisma, PrismaClient } from '@prisma/client' + +const prisma = new PrismaClient() +async function main() { + + await prisma.tag.createMany({ + data: [ + { + id: 'well', + name: 'well_begin', + }, + { + id: 'water', + name: 'water_recycling', + }, + { + id: 'zero', + name: 'zero_waste', + }, + { + id: 'organic', + name: 'organic_ingredient', + }, + ] + }) + + for (let i = 0; i < 100; i++) { + await prisma.restaurant.create({ + data: { + name: `Restaurant ${i}`, + location: 'Bangkok', + imageUrl: 'https://picsum.photos/200', + description: 'Lorem ipsum dolor sit amet', + tags: { + connect: { + id: 'well' + } + } + } + }) + } +} + +void main() diff --git a/public/assets/badges/organic_ingredient.png b/public/assets/badges/organic_ingredient.png new file mode 100644 index 0000000000000000000000000000000000000000..7307eb0a6fbd623c9379f8b3971cc041b5e38254 GIT binary patch literal 16601 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 VSFLQ>GqeBz002ovPDHLkV1l { - return ( -
- -
-
- SDGs point 9.1/10.0 -
-
-
Hubuntu Restaurant
-

- Egestas elit dui scelerisque ut eu purus aliquam vitae habitasse. - Egestas elit dui Egestas elit dui scelerisque ut eu purus -

-
1.1 km
+interface ICardRestaurantProps { + name: string; + badges?: string[]; +} + +export const CardRestaurant: FC = (props) => { + const { name, badges = [] } = props + return ( +
+ +
+
+ { + badges.map((v, i) => ) + } +
+
+
{name}
+

+ Egestas elit dui scelerisque ut eu purus aliquam vitae habitasse. + Egestas elit dui Egestas elit dui scelerisque ut eu purus +

+
1.1 km
+
+
-
-
- ); + ); }; diff --git a/src/components/Caruosel.tsx b/src/components/Caruosel.tsx index 83592a2..8d540b4 100644 --- a/src/components/Caruosel.tsx +++ b/src/components/Caruosel.tsx @@ -8,78 +8,80 @@ import "swiper/css"; // import required modules import { Mousewheel, Keyboard } from "swiper/modules"; -export const Caruosel: FC<{ children: ReactNode; sliderPerPage: number }> = ({ - children, - sliderPerPage, +export const Caruosel: FC<{ children: ReactNode; sliderPerPage: number, onNext?: () => Promise }> = ({ + children, + sliderPerPage, + onNext, }) => { - const sliderRef = useRef(null); + const sliderRef = useRef(null); - const handlePrev = useCallback(() => { - if (!sliderRef.current) return; - sliderRef.current.swiper.slidePrev(); - }, []); + const handlePrev = useCallback(() => { + if (!sliderRef.current) return; + sliderRef.current.swiper.slidePrev(); + }, []); - const handleNext = useCallback(() => { - if (!sliderRef.current) return; - sliderRef.current.swiper.slideNext(); - }, []); + const handleNext = useCallback(async () => { + if (!sliderRef.current) return; + await onNext?.() + sliderRef.current.swiper.slideNext(); + }, [onNext, sliderRef]); - return ( -
- - {children} - -
- - - -
-
- - - -
-
- ); + return ( +
+ + {children} + +
+ + + +
+
+ + + +
+
+ ); }; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 0726d01..2acf6b9 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -5,145 +5,179 @@ import Head from "next/head"; import { CardMenu } from "@ywc19/components/CardMenu"; import { LazyImage } from "@ywc19/components/LazyImage"; import { type INavbarProps, Navbar } from "@ywc19/components/Navbar"; +import { Footer } from "@ywc19/components/Footer"; +import { api } from "@ywc19/utils/api"; import ModalConfirm from "@ywc19/components/ModalConfirm"; export default function Home() { - const mock = [1, 2, 3, 4, 5, 6, 7, 8]; - const category = [ - { - id: 0, - img: "/assets/appetizers.png", - name: "Appetizers", - }, - { - id: 1, - img: "/assets/dishes.png", - name: "Dishes", - }, - { - id: 2, - img: "/assets/desserts.png", - name: "Desserts", - }, - { - id: 3, - img: "/assets/drinks.png", - name: "Drinks", - }, - ]; + const mock = [1, 2, 3, 4, 5, 6, 7, 8]; + const { data: restaurant, fetchNextPage, isLoading } = api.restaurant.findMany.useInfiniteQuery( + { + limit: 2, + }, + { + getNextPageParam: (lastPage) => lastPage.nextCursor, + }, + ) + const category = [ + { + id: 0, + img: "/assets/appetizers.png", + name: "Appetizers", + }, + { + id: 1, + img: "/assets/dishes.png", + name: "Dishes", + }, + { + id: 2, + img: "/assets/desserts.png", + name: "Desserts", + }, + { + id: 3, + img: "/assets/drinks.png", + name: "Drinks", + }, + ]; - return ( - <> - - Create T3 App - - - -
- -
-

Content

+ const menu: INavbarProps["data"] = [ + { + name: "Home", + href: "#", + }, + { + name: "About", + href: "#", + }, + { + name: "Contact", + href: "#", + }, + { + name: "Service", + href: "#", + }, + ]; + return ( + <> + + Create T3 App + + + +
+ +
+

Content

-
- -
-
- - - -
- -
-
-
-
-
- {category.map((item) => ( - - ))} -
-
-
-

- Recommended Restaurants -

- -
- - {mock.map((item) => ( - - - - ))} - -
-
-
-

- Restaurant Nearby me -

- -
- - {mock.map((item) => ( - - - - ))} - -
-
-
-

Recommended Menu

- -
- - {mock.map((item) => ( - - - - ))} - -
- -
-

-
-
-
- - ); +
+ +
+
+ + + +
+ +
+
+
+
+
+ {category.map((item) => ( + + ))} +
+
+
+

+ Recommended Restaurants +

+ +
+ { + + {mock.map((item) => ( + + + + ))} + + } +
+
+
+

+ Restaurant Nearby me +

+ +
+ + {mock.map((item) => ( + + + + ))} + +
+
+
+

Recommended Menu

+ +
+ void await fetchNextPage()}> + {restaurant && restaurant.pages.map((page, i) => ( +
+ {page.items.map((item, j) => ( + + v.name)} /> + + ))} +
+ ))} +
+
+
+

+
+
+
+ + ); } diff --git a/src/server/api/routers/restaurant.ts b/src/server/api/routers/restaurant.ts index 9159b69..18bd3a3 100644 --- a/src/server/api/routers/restaurant.ts +++ b/src/server/api/routers/restaurant.ts @@ -2,13 +2,53 @@ import { createTRPCRouter, publicProcedure, } from "@ywc19/server/api/trpc"; -// import { UserFindManySchema, UserFindUniqueSchema } from "prisma/generated/schemas"; +import { z } from "zod"; + +const UserFindManySchema = z.object({ + where: z.object({ + name: z.string().optional(), + isRecommended: z.boolean().optional(), + }).optional(), + limit: z.number().min(1).max(100).nullish(), + cursor: z.string().nullish(), +}) + +const UserFindUniqueSchema = z.object({ + where: z.object({ + id: z.string() + }) +}) export const restaurantRouter = createTRPCRouter({ - // findMany: publicProcedure.input(UserFindManySchema).query(({ input, ctx }) => { - // return ctx.prisma.user.findMany(input) - // }), - // findUnique: publicProcedure.input(UserFindUniqueSchema).query(({ input, ctx }) => { - // return ctx.prisma.user.findUnique(input) - // }), + findMany: publicProcedure.input(UserFindManySchema).query(async ({ input, ctx }) => { + const limit = input.limit ?? 50; + const items = await ctx.prisma.restaurant.findMany({ + where: input.where?.name ? { + name: input.where?.name ? { + contains: input.where.name + } : undefined, + isRecommended: input.where?.isRecommended ? input.where.isRecommended : undefined, + } : undefined, + cursor: input.cursor ? { id: input.cursor } : undefined, + take: limit + 1, + orderBy: { id: 'asc' }, + include: { + tags: true + } + }) + + let nextCursor: typeof input.cursor | undefined = undefined; + if (items.length > limit) { + const nextItem = items.pop(); + nextCursor = nextItem?.id; + } + return { + items, + nextCursor, + }; + }), + + findUnique: publicProcedure.input(UserFindUniqueSchema).query(({ input, ctx }) => { + return ctx.prisma.user.findUnique(input) + }), }); diff --git a/src/utils/badge.ts b/src/utils/badge.ts new file mode 100644 index 0000000..aa23c35 --- /dev/null +++ b/src/utils/badge.ts @@ -0,0 +1,3 @@ +export const getBadgeUrl = (badge: string) => { + return `/assets/badges/${badge}.png` +}