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 0000000..7307eb0
Binary files /dev/null and b/public/assets/badges/organic_ingredient.png differ
diff --git a/public/assets/badges/water_recycling.png b/public/assets/badges/water_recycling.png
new file mode 100644
index 0000000..89c0d0c
Binary files /dev/null and b/public/assets/badges/water_recycling.png differ
diff --git a/public/assets/badges/well_begin.png b/public/assets/badges/well_begin.png
new file mode 100644
index 0000000..184a50f
Binary files /dev/null and b/public/assets/badges/well_begin.png differ
diff --git a/public/assets/badges/zero_waste.png b/public/assets/badges/zero_waste.png
new file mode 100644
index 0000000..7a8a676
Binary files /dev/null and b/public/assets/badges/zero_waste.png differ
diff --git a/src/components/CardRestaurant.tsx b/src/components/CardRestaurant.tsx
index 39476ab..bd20473 100644
--- a/src/components/CardRestaurant.tsx
+++ b/src/components/CardRestaurant.tsx
@@ -1,30 +1,39 @@
-import React from "react";
+import React, { type FC } from "react";
import { LazyImage } from "./LazyImage";
+import { getBadgeUrl } from "@ywc19/utils/badge";
-export const CardRestaurant = () => {
- 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 (
-
- );
+ return (
+
+ );
};
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
+
+
+
+
+
+
-
-
- {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`
+}