From 03acc36ef9c8b84087affd78ce2d92ecbd25e9fe Mon Sep 17 00:00:00 2001 From: Franz Date: Sun, 29 Sep 2024 00:37:12 +0300 Subject: [PATCH 1/2] fullstack --- .env | 24 +- app/(checkout)/layout.tsx | 2 +- app/(root)/layout.tsx | 2 +- app/(root)/page.tsx | 2 +- app/actions.ts | 37 ++- app/api/auth/[...nextauth]/route.ts | 2 + app/api/auth/verify/route.ts | 11 +- app/api/checkout/callback/route.ts | 2 +- app/globals.css | 94 ++++---- app/layout.tsx | 2 +- package-lock.json | 161 ++++++------- package.json | 12 +- prisma/constants.ts | 172 +++++--------- .../migration.sql | 214 ++++++++++++++++++ prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 10 +- prisma/seed.ts | 63 ++++-- public/logo1.png | Bin 0 -> 8066 bytes shared/components/shared/filters.tsx | 14 +- shared/components/shared/header.tsx | 6 +- .../shared/modals/auth-modal/auth-modal.tsx | 2 +- shared/components/shared/pizza-image.tsx | 4 +- shared/components/shared/profile-button.tsx | 2 +- shared/components/shared/providers.tsx | 3 +- shared/components/shared/search-input.tsx | 2 +- shared/constants/pizza.ts | 10 +- shared/lib/get-pizza-details.ts | 4 +- 27 files changed, 551 insertions(+), 309 deletions(-) create mode 100644 prisma/migrations/20240928094222_change_verified_to_boolean/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 public/logo1.png diff --git a/.env b/.env index 5c7a024..2c27af1 100644 --- a/.env +++ b/.env @@ -1,16 +1,26 @@ -POSTGRES_URL="postgresql://postgres:PASSOWRD@localhost:5433/next-pizza?schema=public" +POSTGRES_URL="postgres://default:RKIHbVqs74ni@ep-round-violet-a2drsspn-pooler.eu-central-1.aws.neon.tech:5432/verceldb?sslmode=require" +POSTGRES_PRISMA_URL="postgres://default:RKIHbVqs74ni@ep-round-violet-a2drsspn-pooler.eu-central-1.aws.neon.tech:5432/verceldb?sslmode=require&pgbouncer=true&connect_timeout=15" +POSTGRES_URL_NO_SSL="postgres://default:RKIHbVqs74ni@ep-round-violet-a2drsspn-pooler.eu-central-1.aws.neon.tech:5432/verceldb" +POSTGRES_URL_NON_POOLING="postgres://default:RKIHbVqs74ni@ep-round-violet-a2drsspn.eu-central-1.aws.neon.tech:5432/verceldb?sslmode=require" +POSTGRES_USER="default" +POSTGRES_HOST="ep-round-violet-a2drsspn-pooler.eu-central-1.aws.neon.tech" +POSTGRES_PASSWORD="RKIHbVqs74ni" +POSTGRES_DATABASE="verceldb" + NEXT_PUBLIC_API_URL=/api -RESEND_API_KEY= -NEXTAUTH_SECRET= +RESEND_API_KEY=re_MaQpzHJj_4THr88nyQqhVxSmFsunBh5pF +NEXTAUTH_SECRET=5bNhbW+OgyVX7gMAZh3CalP7BJlYyXgtl7LPOveuHuQ= -YOOKASSA_STORE_ID= -YOOKASSA_API_KEY= +YOOKASSA_STORE_ID=464198 +YOOKASSA_API_KEY=test_DCclawG3sFjXeCKmweaJ3xjVSpSCkqquxCjdYxVzcZE YOOKASSA_CALLBACK_URL=http://localhost:3000/?paid -GITHUB_ID= -GITHUB_SECRET= +GITHUB_ID=Ov23liwDEw73WA1f6Y8L +GITHUB_SECRET=630df005edd445626f18427d61e639b18660d66a + +# когда будем пушить продакшен, надо указать другой URL в developer settings GOOGLE_CLIENT_ID="" GOOGLE_CLIENT_SECRET="" diff --git a/app/(checkout)/layout.tsx b/app/(checkout)/layout.tsx index bb5b1fd..aedbb33 100644 --- a/app/(checkout)/layout.tsx +++ b/app/(checkout)/layout.tsx @@ -3,7 +3,7 @@ import { Metadata } from 'next'; import { Suspense } from 'react'; export const metadata: Metadata = { - title: 'Next Pizza | Корзина', + title: 'Ножи СПБ | Корзина', description: 'Generated by create next app', }; diff --git a/app/(root)/layout.tsx b/app/(root)/layout.tsx index 9064557..09b36a7 100644 --- a/app/(root)/layout.tsx +++ b/app/(root)/layout.tsx @@ -3,7 +3,7 @@ import type { Metadata } from 'next'; import { Suspense } from 'react'; export const metadata: Metadata = { - title: 'Next Pizza | Главная', + title: 'Ножи СПБ | Главная', }; export default function HomeLayout({ diff --git a/app/(root)/page.tsx b/app/(root)/page.tsx index 4fff96f..947780c 100644 --- a/app/(root)/page.tsx +++ b/app/(root)/page.tsx @@ -15,7 +15,7 @@ export default async function Home({ searchParams }: { searchParams: GetSearchPa return ( <> - + <Title text="Все товары" size="lg" className="font-extrabold" /> </Container> <TopBar categories={categories.filter((category) => category.products.length > 0)} /> diff --git a/app/actions.ts b/app/actions.ts index 715328e..e742a71 100644 --- a/app/actions.ts +++ b/app/actions.ts @@ -1,7 +1,8 @@ 'use server'; import { prisma } from '@/prisma/prisma-client'; -import { PayOrderTemplate } from '@/shared/components'; +import { PayOrderTemplate } from '@/shared/components/shared/email-temapltes'; + import { VerificationUserTemplate } from '@/shared/components/shared/email-temapltes/verification-user'; import { CheckoutFormValues } from '@/shared/constants'; import { createPayment, sendEmail } from '@/shared/lib'; @@ -103,7 +104,7 @@ export async function createOrder(data: CheckoutFormValues) { await sendEmail( data.email, - 'Next Pizza / Оплатите заказ #' + order.id, + 'Hoжы СПБ / Оплатите заказ #' + order.id, PayOrderTemplate({ orderId: order.id, totalAmount: order.totalAmount, @@ -156,13 +157,39 @@ export async function registerUser(body: Prisma.UserCreateInput) { }); if (user) { + // Проверяем, если пользователь существует и не верифицирован if (!user.verified) { - throw new Error('Почта не подтверждена'); + // Генерируем новый код подтверждения + const code = Math.floor(100000 + Math.random() * 900000).toString(); + + await prisma.verificationCode.upsert({ + where: { + userId: user.id, + }, + update: { + code, + }, + create: { + code, + userId: user.id, + }, + }); + + await sendEmail( + user.email, + 'Ножи СПБ / 📝 Повторное подтверждение регистрации', + VerificationUserTemplate({ + code, + }), + ); + + throw new Error('Почта не подтверждена. Новый код подтверждения отправлен.'); } - throw new Error('Пользователь уже существует'); + throw new Error('Пользователь уже существует и верифицирован.'); } + // Если пользователь не найден, создаем нового const createdUser = await prisma.user.create({ data: { fullName: body.fullName, @@ -182,7 +209,7 @@ export async function registerUser(body: Prisma.UserCreateInput) { await sendEmail( createdUser.email, - 'Next Pizza / 📝 Подтверждение регистрации', + 'Ножи СПБ / 📝 Подтверждение регистрации', VerificationUserTemplate({ code, }), diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index c7d7e30..bac6794 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -1,6 +1,8 @@ import NextAuth from 'next-auth'; import { authOptions } from '@/shared/constants/auth-options'; +//настройки выносим в отдельную переменнную + const handler = NextAuth(authOptions); export { handler as GET, handler as POST }; diff --git a/app/api/auth/verify/route.ts b/app/api/auth/verify/route.ts index a4de662..25def3a 100644 --- a/app/api/auth/verify/route.ts +++ b/app/api/auth/verify/route.ts @@ -3,13 +3,14 @@ import { NextRequest, NextResponse } from 'next/server'; export async function GET(req: NextRequest) { try { - // const code = req.nextUrl.searchParams.get('code'); - const code = ''; + // Получаем параметр 'code' из URL + const code = req.nextUrl.searchParams.get('code'); if (!code) { return NextResponse.json({ error: 'Неверный код' }, { status: 400 }); } + // Ищем verificationCode в базе данных по коду const verificationCode = await prisma.verificationCode.findFirst({ where: { code, @@ -20,24 +21,28 @@ export async function GET(req: NextRequest) { return NextResponse.json({ error: 'Неверный код' }, { status: 400 }); } + // Обновляем статус пользователя как верифицированный await prisma.user.update({ where: { id: verificationCode.userId, }, data: { - verified: new Date(), + verified: true, // Устанавливаем флаг верификации }, }); + // Удаляем использованный verificationCode await prisma.verificationCode.delete({ where: { id: verificationCode.id, }, }); + // Редиректим на главную с параметром ?verified return NextResponse.redirect(new URL('/?verified', req.url)); } catch (error) { console.error(error); console.log('[VERIFY_GET] Server error', error); + return NextResponse.json({ error: 'Server error' }, { status: 500 }); } } diff --git a/app/api/checkout/callback/route.ts b/app/api/checkout/callback/route.ts index 08d433f..ae884b4 100644 --- a/app/api/checkout/callback/route.ts +++ b/app/api/checkout/callback/route.ts @@ -36,7 +36,7 @@ export async function POST(req: NextRequest) { if (isSucceeded) { await sendEmail( order.email, - 'Next Pizza / Ваш заказ успешно оформлен 🎉', + 'Ножи СПБ / Ваш заказ успешно оформлен 🎉', OrderSuccessTemplate({ orderId: order.id, items }), ); } else { diff --git a/app/globals.css b/app/globals.css index b44f896..272e337 100644 --- a/app/globals.css +++ b/app/globals.css @@ -14,33 +14,58 @@ html { @layer base { :root { - --foreground: 20 14.3% 4.1%; - + --background: 0 0% 100%; + --foreground: 240 10% 3.9%; --card: 0 0% 100%; - --card-foreground: 20 14.3% 4.1%; - + --card-foreground: 240 10% 3.9%; --popover: 0 0% 100%; - --popover-foreground: 20 14.3% 4.1%; - - --primary: 22 100% 50%; - --primary-foreground: 60 9.1% 97.8%; - - --secondary: 32 100% 98%; - --secondary-foreground: 24 9.8% 10%; - - --muted: 60 4.8% 95.9%; - --muted-foreground: 25 5.3% 44.7%; - - --accent: 60 4.8% 95.9%; - --accent-foreground: 24 9.8% 10%; - + --popover-foreground: 240 10% 3.9%; + --primary: 240 5.9% 10%; + --primary-foreground: 0 0% 98%; + --secondary: 240 4.8% 95.9%; + --secondary-foreground: 240 5.9% 10%; + --muted: 240 4.8% 95.9%; + --muted-foreground: 240 3.8% 46.1%; + --accent: 240 4.8% 95.9%; + --accent-foreground: 240 5.9% 10%; --destructive: 0 84.2% 60.2%; - --destructive-foreground: 60 9.1% 97.8%; + --destructive-foreground: 0 0% 98%; + --border: 240 5.9% 90%; + --input: 240 5.9% 90%; + --ring: 240 5.9% 10%; + --radius: 0.5rem; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + } - --border: 20 5.9% 90%; - --input: 0 0% 90%; - --ring: 24.6 95% 53.1%; - --radius: 18px; + .dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; } } @@ -70,25 +95,4 @@ html { .text-balance { text-wrap: balance; } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} - -#nprogress .bar { - @apply bg-primary !important; -} - -#nprogress .peg { - @apply shadow-md shadow-primary !important; -} - -#nprogress .spinner-icon { - @apply border-t-primary border-l-primary !important; -} +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 9018b22..1510ccb 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -17,7 +17,7 @@ export default function RootLayout({ return ( <html lang="en"> <head> - <link data-rh="true" rel="icon" href="/logo.png" /> + <link data-rh="true" rel="icon" href="/logo1.png" /> </head> <body className={nunito.className}> <Providers>{children}</Providers> diff --git a/package-lock.json b/package-lock.json index 643e4d6..1ad8a7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "next-pizza", "version": "0.1.0", + "hasInstallScript": true, "dependencies": { "@hookform/resolvers": "^3.4.2", "@prisma/client": "^5.13.0", @@ -17,25 +18,24 @@ "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-slot": "^1.0.2", "@types/bcrypt": "^5.0.2", - "@types/qs": "^6.9.15", + "@types/qs": "^6.9.16", "axios": "^1.6.8", "bcrypt": "^5.1.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.376.0", "next": "14.2.3", - "next-auth": "^4.24.7", + "next-auth": "^4.24.8", "nextjs-toploader": "^1.6.12", - "prisma": "^5.13.0", - "qs": "^6.12.1", + "qs": "^6.13.0", "react": "^18", "react-dadata": "^2.23.1", "react-dom": "^18", - "react-hook-form": "^7.51.5", + "react-hook-form": "^7.53.0", "react-hot-toast": "^2.4.1", "react-insta-stories": "^2.7.0", "react-use": "^17.5.0", - "resend": "^3.2.0", + "resend": "^3.5.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", "ts-node": "^10.9.2", @@ -50,6 +50,7 @@ "eslint": "^8", "eslint-config-next": "14.2.3", "postcss": "^8", + "prisma": "^5.19.1", "tailwindcss": "^3.4.1", "typescript": "^5" } @@ -551,43 +552,48 @@ } }, "node_modules/@prisma/debug": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.13.0.tgz", - "integrity": "sha512-699iqlEvzyCj9ETrXhs8o8wQc/eVW+FigSsHpiskSFydhjVuwTJEfj/nIYqTaWFYuxiWQRfm3r01meuW97SZaQ==" + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.19.1.tgz", + "integrity": "sha512-lAG6A6QnG2AskAukIEucYJZxxcSqKsMK74ZFVfCTOM/7UiyJQi48v6TQ47d6qKG3LbMslqOvnTX25dj/qvclGg==", + "devOptional": true }, "node_modules/@prisma/engines": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.13.0.tgz", - "integrity": "sha512-hIFLm4H1boj6CBZx55P4xKby9jgDTeDG0Jj3iXtwaaHmlD5JmiDkZhh8+DYWkTGchu+rRF36AVROLnk0oaqhHw==", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.19.1.tgz", + "integrity": "sha512-kR/PoxZDrfUmbbXqqb8SlBBgCjvGaJYMCOe189PEYzq9rKqitQ2fvT/VJ8PDSe8tTNxhc2KzsCfCAL+Iwm/7Cg==", + "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/debug": "5.13.0", - "@prisma/engines-version": "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b", - "@prisma/fetch-engine": "5.13.0", - "@prisma/get-platform": "5.13.0" + "@prisma/debug": "5.19.1", + "@prisma/engines-version": "5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3", + "@prisma/fetch-engine": "5.19.1", + "@prisma/get-platform": "5.19.1" } }, "node_modules/@prisma/engines-version": { - "version": "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b.tgz", - "integrity": "sha512-AyUuhahTINGn8auyqYdmxsN+qn0mw3eg+uhkp8zwknXYIqoT3bChG4RqNY/nfDkPvzWAPBa9mrDyBeOnWSgO6A==" + "version": "5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3.tgz", + "integrity": "sha512-xR6rt+z5LnNqTP5BBc+8+ySgf4WNMimOKXRn6xfNRDSpHvbOEmd7+qAOmzCrddEc4Cp8nFC0txU14dstjH7FXA==", + "devOptional": true }, "node_modules/@prisma/fetch-engine": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.13.0.tgz", - "integrity": "sha512-Yh4W+t6YKyqgcSEB3odBXt7QyVSm0OQlBSldQF2SNXtmOgMX8D7PF/fvH6E6qBCpjB/yeJLy/FfwfFijoHI6sA==", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.19.1.tgz", + "integrity": "sha512-pCq74rtlOVJfn4pLmdJj+eI4P7w2dugOnnTXpRilP/6n5b2aZiA4ulJlE0ddCbTPkfHmOL9BfaRgA8o+1rfdHw==", + "devOptional": true, "dependencies": { - "@prisma/debug": "5.13.0", - "@prisma/engines-version": "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b", - "@prisma/get-platform": "5.13.0" + "@prisma/debug": "5.19.1", + "@prisma/engines-version": "5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3", + "@prisma/get-platform": "5.19.1" } }, "node_modules/@prisma/get-platform": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.13.0.tgz", - "integrity": "sha512-B/WrQwYTzwr7qCLifQzYOmQhZcFmIFhR81xC45gweInSUn2hTEbfKUPd2keAog+y5WI5xLAFNJ3wkXplvSVkSw==", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.19.1.tgz", + "integrity": "sha512-sCeoJ+7yt0UjnR+AXZL7vXlg5eNxaFOwC23h0KvW1YIXUoa7+W2ZcAUhoEQBmJTW4GrFqCuZ8YSP0mkDa4k3Zg==", + "devOptional": true, "dependencies": { - "@prisma/debug": "5.13.0" + "@prisma/debug": "5.19.1" } }, "node_modules/@radix-ui/number": { @@ -1247,40 +1253,20 @@ } }, "node_modules/@react-email/render": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.12.tgz", - "integrity": "sha512-S8WRv/PqECEi6x0QJBj0asnAb5GFtJaHlnByxLETLkgJjc76cxMYDH4r9wdbuJ4sjkcbpwP3LPnVzwS+aIjT7g==", + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.16.tgz", + "integrity": "sha512-wDaMy27xAq1cJHtSFptp0DTKPuV2GYhloqia95ub/DH9Dea1aWYsbdM918MOc/b/HvVS3w1z8DWzfAk13bGStQ==", "dependencies": { "html-to-text": "9.0.5", "js-beautify": "^1.14.11", - "react": "18.2.0", - "react-dom": "18.2.0" + "react-promise-suspense": "0.3.4" }, "engines": { "node": ">=18.0.0" - } - }, - "node_modules/@react-email/render/node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@react-email/render/node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" }, "peerDependencies": { - "react": "^18.2.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" } }, "node_modules/@rushstack/eslint-patch": { @@ -1369,9 +1355,9 @@ "devOptional": true }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==" + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==" }, "node_modules/@types/react": { "version": "18.3.1", @@ -4753,9 +4739,9 @@ } }, "node_modules/next-auth": { - "version": "4.24.7", - "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.7.tgz", - "integrity": "sha512-iChjE8ov/1K/z98gdKbn2Jw+2vLgJtVV39X+rCP5SGnVQuco7QOr19FRNGMIrD8d3LYhHWV9j9sKLzq1aDWWQQ==", + "version": "4.24.8", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.8.tgz", + "integrity": "sha512-SLt3+8UCtklsotnz2p+nB4aN3IHNmpsQFAZ24VLxGotWGzSxkBh192zxNhm/J5wgkcrDWVp0bwqvW0HksK/Lcw==", "dependencies": { "@babel/runtime": "^7.20.13", "@panva/hkdf": "^1.0.2", @@ -4768,12 +4754,16 @@ "uuid": "^8.3.2" }, "peerDependencies": { + "@auth/core": "0.34.2", "next": "^12.2.5 || ^13 || ^14", "nodemailer": "^6.6.5", "react": "^17.0.2 || ^18", "react-dom": "^17.0.2 || ^18" }, "peerDependenciesMeta": { + "@auth/core": { + "optional": true + }, "nodemailer": { "optional": true } @@ -5420,18 +5410,22 @@ "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" }, "node_modules/prisma": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.13.0.tgz", - "integrity": "sha512-kGtcJaElNRAdAGsCNykFSZ7dBKpL14Cbs+VaQ8cECxQlRPDjBlMHNFYeYt0SKovAVy2Y65JXQwB3A5+zIQwnTg==", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.19.1.tgz", + "integrity": "sha512-c5K9MiDaa+VAAyh1OiYk76PXOme9s3E992D7kvvIOhCrNsBQfy2mP2QAQtX0WNj140IgG++12kwZpYB9iIydNQ==", + "devOptional": true, "hasInstallScript": true, "dependencies": { - "@prisma/engines": "5.13.0" + "@prisma/engines": "5.19.1" }, "bin": { "prisma": "build/index.js" }, "engines": { "node": ">=16.13" + }, + "optionalDependencies": { + "fsevents": "2.3.3" } }, "node_modules/prop-types": { @@ -5464,9 +5458,9 @@ } }, "node_modules/qs": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", - "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { "side-channel": "^1.0.6" }, @@ -5535,18 +5529,18 @@ } }, "node_modules/react-hook-form": { - "version": "7.51.5", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.5.tgz", - "integrity": "sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q==", + "version": "7.53.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", + "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", "engines": { - "node": ">=12.22.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/react-hook-form" }, "peerDependencies": { - "react": "^16.8.0 || ^17 || ^18" + "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "node_modules/react-hot-toast": { @@ -5577,6 +5571,19 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-promise-suspense": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.4.tgz", + "integrity": "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==", + "dependencies": { + "fast-deep-equal": "^2.0.1" + } + }, + "node_modules/react-promise-suspense/node_modules/fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" + }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -5755,11 +5762,11 @@ } }, "node_modules/resend": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/resend/-/resend-3.2.0.tgz", - "integrity": "sha512-lDHhexiFYPoLXy7zRlJ8D5eKxoXy6Tr9/elN3+Vv7PkUoYuSSD1fpiIfa/JYXEWyiyN2UczkCTLpkT8dDPJ4Pg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/resend/-/resend-3.5.0.tgz", + "integrity": "sha512-bKu4LhXSecP6krvhfDzyDESApYdNfjirD5kykkT1xO0Cj9TKSiGh5Void4pGTs3Am+inSnp4dg0B5XzdwHBJOQ==", "dependencies": { - "@react-email/render": "0.0.12" + "@react-email/render": "0.0.16" }, "engines": { "node": ">=18" diff --git a/package.json b/package.json index bad8d78..19ea5ec 100644 --- a/package.json +++ b/package.json @@ -25,25 +25,24 @@ "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-slot": "^1.0.2", "@types/bcrypt": "^5.0.2", - "@types/qs": "^6.9.15", + "@types/qs": "^6.9.16", "axios": "^1.6.8", "bcrypt": "^5.1.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "lucide-react": "^0.376.0", "next": "14.2.3", - "next-auth": "^4.24.7", + "next-auth": "^4.24.8", "nextjs-toploader": "^1.6.12", - "prisma": "^5.13.0", - "qs": "^6.12.1", + "qs": "^6.13.0", "react": "^18", "react-dadata": "^2.23.1", "react-dom": "^18", - "react-hook-form": "^7.51.5", + "react-hook-form": "^7.53.0", "react-hot-toast": "^2.4.1", "react-insta-stories": "^2.7.0", "react-use": "^17.5.0", - "resend": "^3.2.0", + "resend": "^3.5.0", "tailwind-merge": "^2.3.0", "tailwindcss-animate": "^1.0.7", "ts-node": "^10.9.2", @@ -58,6 +57,7 @@ "eslint": "^8", "eslint-config-next": "14.2.3", "postcss": "^8", + "prisma": "^5.19.1", "tailwindcss": "^3.4.1", "typescript": "^5" } diff --git a/prisma/constants.ts b/prisma/constants.ts index 4c06a2d..1bc9b6d 100644 --- a/prisma/constants.ts +++ b/prisma/constants.ts @@ -1,198 +1,146 @@ export const categories = [ { - name: 'Пиццы', + name: 'Складные', }, { - name: 'Завтрак', + name: 'Охотничьи', }, { - name: 'Закуски', + name: 'Мультитулы', }, { - name: 'Коктейли', + name: 'Метательные', }, { - name: 'Напитки', + name: 'Кухонные', }, ]; export const _ingredients = [ { - name: 'Сырный бортик', - price: 179, + name: 'Чехол', + price: 2000, imageUrl: - 'https://cdn.dodostatic.net/static/Img/Ingredients/99f5cb91225b4875bd06a26d2e842106.png', + 'https://kizlyar-moscow.ru/image/cache/catalog/li/default/e78d6167f0ebad9fbfd9f2ebcd2678ee-710x475-product_thumb.jpeg', }, { - name: 'Сливочная моцарелла', - price: 79, + name: 'Масло для ножей "Смажь Нож"', + price: 690, imageUrl: - 'https://cdn.dodostatic.net/static/Img/Ingredients/cdea869ef287426386ed634e6099a5ba.png', + 'https://img.nozhikov.ru/images/products/1/505/850027001/DSC05933-Edit.jpg', }, { - name: 'Сыры чеддер и пармезан', - price: 79, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A22FA54A81411E9AFA69C1FE796', + name: 'Заточка', + price: 1290, + imageUrl: 'https://profi-knife.ru/wp-content/uploads/2020/05/4342rb-800x793.jpg', }, { - name: 'Острый перец халапеньо', - price: 59, + name: 'Огниво', + price: 990, imageUrl: - 'https://cdn.dodostatic.net/static/Img/Ingredients/11ee95b6bfdf98fb88a113db92d7b3df.png', + 'https://ir.ozone.ru/s3/multimedia-1-g/c1000/6968271508.jpg', }, { - name: 'Нежный цыпленок', - price: 79, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A39D824A82E11E9AFA5B328D35A', + name: 'Компас', + price: 1390, + imageUrl: 'https://cdn1.ozone.ru/s3/multimedia-5/c600/6617448077.jpg', }, { - name: 'Шампиньоны', - price: 59, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A22FA54A81411E9AFA67259A324', + name: 'Компактный алмазный Брусок 100х16х10, зерно 50/40-20/14', + price: 1590, + imageUrl: 'https://img.nozhikov.ru/images/products/1/5476/514970980/DSC09432.jpg', }, { - name: 'Ветчина', - price: 79, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A39D824A82E11E9AFA61B9A8D61', - }, - { - name: 'Пикантная пепперони', - price: 79, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A22FA54A81411E9AFA6258199C3', - }, - { - name: 'Острая чоризо', - price: 79, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A22FA54A81411E9AFA62D5D6027', - }, - { - name: 'Маринованные огурчики', - price: 59, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A21DA51A81211E9EA89958D782B', - }, - { - name: 'Свежие томаты', - price: 59, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A39D824A82E11E9AFA7AC1A1D67', - }, - { - name: 'Красный лук', - price: 59, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A22FA54A81411E9AFA60AE6464C', - }, - { - name: 'Сочные ананасы', - price: 59, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A21DA51A81211E9AFA6795BA2A0', - }, - { - name: 'Итальянские травы', - price: 39, - imageUrl: - 'https://cdn.dodostatic.net/static/Img/Ingredients/370dac9ed21e4bffaf9bc2618d258734.png', - }, - { - name: 'Сладкий перец', - price: 59, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A22FA54A81411E9AFA63F774C1B', - }, - { - name: 'Кубики брынзы', - price: 79, - imageUrl: 'https://cdn.dodostatic.net/static/Img/Ingredients/000D3A39D824A82E11E9AFA6B0FFC349', - }, - { - name: 'Митболы', - price: 79, - imageUrl: - 'https://cdn.dodostatic.net/static/Img/Ingredients/b2f3a5d5afe44516a93cfc0d2ee60088.png', + name: 'Темляк малый с бусиной "Руна", зеленый', + price: 1110, + imageUrl: 'https://img.nozhikov.ru/images/products/1/3073/772451329/%D1%80%D1%83%D0%BD%D0%B01.jpg', }, ].map((obj, index) => ({ id: index + 1, ...obj })); export const products = [ { - name: 'Омлет с ветчиной и грибами', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7970321044479C1D1085457A36EB.webp', + name: 'Нож Honor Prime X, D2', + imageUrl: 'https://img.nozhikov.ru/images/products/1/2843/865028891/DSC08178-Edit.jpg', categoryId: 2, }, { - name: 'Омлет с пепперони', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE94ECF33B0C46BA410DEC1B1DD6F8.webp', + name: 'Нож Финский Ромб', + imageUrl: 'https://img.nozhikov.ru/images/products/1/2773/616057557/DSC09364-Edit.jpg', categoryId: 2, }, { - name: 'Кофе Латте', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D61B0C26A3F85D97A78FEEE00AD.webp', + name: 'Нож "Басенджи"', + imageUrl: 'https://img.nozhikov.ru/images/products/1/2677/821463669/DSC00711-Edit.jpg', categoryId: 2, }, { - name: 'Дэнвич ветчина и сыр', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE796FF0059B799A17F57A9E64C725.webp', + name: 'Нож перочинный Victorinox Spartan', + imageUrl: 'https://img.nozhikov.ru/images/products/1/6199/286595127/nozh-perochinnyj-victorinox-spartan-stal-x55crmo14-rukoyat-cellidor-krasnyj-1.jpg', categoryId: 3, }, { - name: 'Куриные наггетсы', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D618B5C7EC29350069AE9532C6E.webp', + name: 'Нож перочинный Victorinox Huntsman', + imageUrl: 'https://img.nozhikov.ru/images/products/1/4981/285766517/nozh-perochinnyj-victorinox-huntsman-stal-x55crmo14-rukoyat-cellidor-kamuflyazh-4.jpg', categoryId: 3, }, { - name: 'Картофель из печи с соусом 🌱', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EED646A9CD324C962C6BEA78124F19.webp', + name: 'Мультитул HX OUTDOORS TD-03', + imageUrl: 'https://img.nozhikov.ru/images/products/1/847/839902031/DSC02665.jpg', categoryId: 3, }, { - name: 'Додстер', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE796F96D11392A2F6DD73599921B9.webp', + name: 'Мультитул MQ065, 13 функций', + imageUrl: 'https://img.nozhikov.ru/images/products/1/4460/878276972/DSC00131-Edit.jpg', categoryId: 3, }, { - name: 'Острый Додстер 🌶️🌶️', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE796FD3B594068F7A752DF8161D04.webp', + name: 'Нож перочинный Victorinox Climber', + imageUrl: 'https://img.nozhikov.ru/images/products/1/1269/284476661/nozh-perochinnyj-victorinox-climber-stal-x55crmo14-rukoyat-cellidor-krasnyj-2.jpg', categoryId: 3, }, { - name: 'Банановый молочный коктейль', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EEE20B8772A72A9B60CFB20012C185.webp', + name: 'Спортивный нож «Профессионал-4»', + imageUrl: 'https://img.nozhikov.ru/images/products/1/741/669115109/DSC04930-Edit-2.jpg', categoryId: 4, }, { - name: 'Карамельное яблоко молочный коктейль', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE79702E2A22E693D96133906FB1B8.webp', + name: 'Набор из 3 Спортивных ножей Кунай', + imageUrl: 'https://img.nozhikov.ru/images/products/1/4739/724316803/DSC04970-Edit.jpg', categoryId: 4, }, { - name: 'Молочный коктейль с печеньем Орео', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE796FA1F50F8F8111A399E4C1A1E3.webp', + name: 'Спортивный нож Импульс, Kizlyar Supreme', + imageUrl: 'https://img.nozhikov.ru/images/products/1/7504/729824592/DSC03609.jpg', categoryId: 4, }, { - name: 'Классический молочный коктейль 👶', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE796F93FB126693F96CB1D3E403FB.webp', + name: 'Спортивный нож Лидер', + imageUrl: 'https://img.nozhikov.ru/images/products/1/1716/736093876/DSC01677.jpg', categoryId: 4, }, { - name: 'Ирландский Капучино', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D61999EBDA59C10E216430A6093.webp', + name: 'Кухонный нож универсал Tuotown', + imageUrl: 'https://img.nozhikov.ru/images/products/1/3382/908463414/185011.jpg', categoryId: 5, }, { - name: 'Кофе Карамельный капучино', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D61AED6B6D4BFDAD4E58D76CF56.webp', + name: 'Сербский нож Fissman', + imageUrl: 'https://img.nozhikov.ru/images/products/1/391/660029831/DSC03404-Edit.jpg', categoryId: 5, }, { - name: 'Кофе Кокосовый латте', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D61B19FA07090EE88B0ED347F42.webp', + name: 'Нож Овощной-2, сталь AUS-8', + imageUrl: 'https://img.nozhikov.ru/images/products/1/2728/772090536/DSC01088-Edit.jpg', categoryId: 5, }, { - name: 'Кофе Американо', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D61B044583596548A59078BBD33.webp', + name: 'Нож "Шеф-де-Беф"', + imageUrl: 'https://img.nozhikov.ru/images/products/1/5389/583947533/DSC07598.jpg', categoryId: 5, }, { - name: 'Кофе Латте', - imageUrl: 'https://media.dodostatic.net/image/r:292x292/11EE7D61B0C26A3F85D97A78FEEE00AD.webp', + name: 'Нож кухонный Kanetsune Usabagata 165 мм', + imageUrl: 'https://img.nozhikov.ru/images/products/1/3966/545443710/kc-361-_2_.png', categoryId: 5, }, ]; diff --git a/prisma/migrations/20240928094222_change_verified_to_boolean/migration.sql b/prisma/migrations/20240928094222_change_verified_to_boolean/migration.sql new file mode 100644 index 0000000..02dba01 --- /dev/null +++ b/prisma/migrations/20240928094222_change_verified_to_boolean/migration.sql @@ -0,0 +1,214 @@ +-- CreateEnum +CREATE TYPE "OrderStatus" AS ENUM ('PENDING', 'SUCCEEDED', 'CANCELLED'); + +-- CreateEnum +CREATE TYPE "UserRole" AS ENUM ('USER', 'ADMIN'); + +-- CreateTable +CREATE TABLE "User" ( + "id" SERIAL NOT NULL, + "fullName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "password" TEXT NOT NULL, + "role" "UserRole" NOT NULL DEFAULT 'USER', + "verified" BOOLEAN, + "provider" TEXT, + "providerId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Category" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Category_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Product" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "imageUrl" TEXT NOT NULL, + "categoryId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Product_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProductItem" ( + "id" SERIAL NOT NULL, + "price" INTEGER NOT NULL, + "size" INTEGER, + "pizzaType" INTEGER, + "productId" INTEGER NOT NULL, + + CONSTRAINT "ProductItem_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Ingredient" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "price" INTEGER NOT NULL, + "imageUrl" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Ingredient_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Cart" ( + "id" SERIAL NOT NULL, + "userId" INTEGER, + "token" TEXT NOT NULL, + "totalAmount" INTEGER NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Cart_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "CartItem" ( + "id" SERIAL NOT NULL, + "cartId" INTEGER NOT NULL, + "productItemId" INTEGER NOT NULL, + "quantity" INTEGER NOT NULL DEFAULT 1, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "CartItem_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Order" ( + "id" SERIAL NOT NULL, + "userId" INTEGER, + "token" TEXT NOT NULL, + "totalAmount" INTEGER NOT NULL, + "status" "OrderStatus" NOT NULL, + "paymentId" TEXT, + "items" JSONB NOT NULL, + "fullName" TEXT NOT NULL, + "email" TEXT NOT NULL, + "phone" TEXT NOT NULL, + "address" TEXT NOT NULL, + "comment" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Order_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "VerificationCode" ( + "id" SERIAL NOT NULL, + "userId" INTEGER NOT NULL, + "code" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "VerificationCode_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Story" ( + "id" SERIAL NOT NULL, + "previewImageUrl" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Story_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "StoryItem" ( + "id" SERIAL NOT NULL, + "storyId" INTEGER NOT NULL, + "sourceUrl" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "StoryItem_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "_IngredientToProduct" ( + "A" INTEGER NOT NULL, + "B" INTEGER NOT NULL +); + +-- CreateTable +CREATE TABLE "_CartItemToIngredient" ( + "A" INTEGER NOT NULL, + "B" INTEGER NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "Category_name_key" ON "Category"("name"); + +-- CreateIndex +CREATE UNIQUE INDEX "Cart_userId_key" ON "Cart"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationCode_userId_key" ON "VerificationCode"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "VerificationCode_userId_code_key" ON "VerificationCode"("userId", "code"); + +-- CreateIndex +CREATE UNIQUE INDEX "_IngredientToProduct_AB_unique" ON "_IngredientToProduct"("A", "B"); + +-- CreateIndex +CREATE INDEX "_IngredientToProduct_B_index" ON "_IngredientToProduct"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_CartItemToIngredient_AB_unique" ON "_CartItemToIngredient"("A", "B"); + +-- CreateIndex +CREATE INDEX "_CartItemToIngredient_B_index" ON "_CartItemToIngredient"("B"); + +-- AddForeignKey +ALTER TABLE "Product" ADD CONSTRAINT "Product_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "Category"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProductItem" ADD CONSTRAINT "ProductItem_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Cart" ADD CONSTRAINT "Cart_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "CartItem" ADD CONSTRAINT "CartItem_cartId_fkey" FOREIGN KEY ("cartId") REFERENCES "Cart"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "CartItem" ADD CONSTRAINT "CartItem_productItemId_fkey" FOREIGN KEY ("productItemId") REFERENCES "ProductItem"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Order" ADD CONSTRAINT "Order_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "VerificationCode" ADD CONSTRAINT "VerificationCode_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "StoryItem" ADD CONSTRAINT "StoryItem_storyId_fkey" FOREIGN KEY ("storyId") REFERENCES "Story"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_IngredientToProduct" ADD CONSTRAINT "_IngredientToProduct_A_fkey" FOREIGN KEY ("A") REFERENCES "Ingredient"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_IngredientToProduct" ADD CONSTRAINT "_IngredientToProduct_B_fkey" FOREIGN KEY ("B") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_CartItemToIngredient" ADD CONSTRAINT "_CartItemToIngredient_A_fkey" FOREIGN KEY ("A") REFERENCES "CartItem"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_CartItemToIngredient" ADD CONSTRAINT "_CartItemToIngredient_B_fkey" FOREIGN KEY ("B") REFERENCES "Ingredient"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..fbffa92 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index fe97a4c..cdb48cc 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -4,8 +4,8 @@ generator client { datasource db { provider = "postgresql" - url = env("POSTGRES_PRISMA_URL") // uses connection pooling - directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection + url = env("POSTGRES_PRISMA_URL") + directUrl = env("POSTGRES_URL_NON_POOLING") } model User { @@ -15,7 +15,7 @@ model User { email String @unique password String role UserRole @default(USER) - verified DateTime? + verified Boolean? @default(false) provider String? providerId String? @@ -64,6 +64,9 @@ model ProductItem { product Product @relation(fields: [productId], references: [id]) productId Int + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt } model Ingredient { @@ -144,7 +147,6 @@ model VerificationCode { userId Int @unique code String - createdAt DateTime @default(now()) @@unique([userId, code]) diff --git a/prisma/seed.ts b/prisma/seed.ts index bf09cf8..a28d8f1 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -31,14 +31,14 @@ async function up() { fullName: 'User Test', email: 'user@test.ru', password: hashSync('111111', 10), - verified: new Date(), + verified: true, // Здесь теперь булевое значение role: 'USER', }, { fullName: 'Admin Admin', email: 'admin@test.ru', password: hashSync('111111', 10), - verified: new Date(), + verified: true, // Булевое значение role: 'ADMIN', }, ], @@ -58,36 +58,48 @@ async function up() { const pizza1 = await prisma.product.create({ data: { - name: 'Пепперони фреш', + name: 'Складной нож Honor Ajax', imageUrl: - 'https://media.dodostatic.net/image/r:233x233/11EE7D61304FAF5A98A6958F2BB2D260.webp', + 'https://img.nozhikov.ru/images/products/1/2925/789998445/DSC05498-Edit-Edit.jpg', categoryId: 1, ingredients: { - connect: _ingredients.slice(0, 5), + connect: _ingredients.slice(0, 7), }, }, }); const pizza2 = await prisma.product.create({ data: { - name: 'Сырная', + name: 'Нож Dagger', imageUrl: - 'https://media.dodostatic.net/image/r:233x233/11EE7D610CF7E265B7C72BE5AE757CA7.webp', + 'https://img.nozhikov.ru/images/products/1/4611/629502467/203678.2048x2048.jpg', categoryId: 1, ingredients: { - connect: _ingredients.slice(5, 10), + connect: _ingredients.slice(0, 7), }, }, }); const pizza3 = await prisma.product.create({ data: { - name: 'Чоризо фреш', + name: 'Складной нож Five Knives 15', imageUrl: - 'https://media.dodostatic.net/image/r:584x584/11EE7D61706D472F9A5D71EB94149304.webp', + 'https://img.nozhikov.ru/images/products/1/608/855433824/DSC09909-Edit.jpg', categoryId: 1, ingredients: { - connect: _ingredients.slice(10, 40), + connect: _ingredients.slice(0, 7), + }, + }, + }); + + const pizza4 = await prisma.product.create({ + data: { + name: 'Складной нож Five Knives 15', + imageUrl: + 'https://img.nozhikov.ru/images/products/1/608/855433824/DSC09909-Edit.jpg', + categoryId: 1, + ingredients: { + connect: _ingredients.slice(0, 7), }, }, }); @@ -163,27 +175,27 @@ async function up() { data: [ { previewImageUrl: - 'https://cdn.inappstory.ru/story/xep/xzh/zmc/cr4gcw0aselwvf628pbmj3j/custom_cover/logo-350x440.webp?k=IgAAAAAAAAAE&v=3101815496', + 'https://static.insales-cdn.com/r/Igx7a8HKYP0/rs:fit:1000:0:1/q:100/plain/images/products/1/6970/904469306/DSC08191.jpg@webp', }, { previewImageUrl: - 'https://cdn.inappstory.ru/story/km2/9gf/jrn/sb7ls1yj9fe5bwvuwgym73e/custom_cover/logo-350x440.webp?k=IgAAAAAAAAAE&v=3074015640', + 'https://static.insales-cdn.com/images/products/1/7133/880278493/DSC08293__2_.jpg', }, { previewImageUrl: - 'https://cdn.inappstory.ru/story/quw/acz/zf5/zu37vankpngyccqvgzbohj1/custom_cover/logo-350x440.webp?k=IgAAAAAAAAAE&v=1336215020', + 'https://static.insales-cdn.com/images/products/1/7431/835755271/3__9_.jpg', }, { previewImageUrl: - 'https://cdn.inappstory.ru/story/7oc/5nf/ipn/oznceu2ywv82tdlnpwriyrq/custom_cover/logo-350x440.webp?k=IgAAAAAAAAAE&v=38903958', + 'https://static.insales-cdn.com/r/AThmZSL1O1I/rs:fit:1000:0:1/q:100/plain/images/products/1/3196/915991676/DSC09476.jpg@webp', }, { previewImageUrl: - 'https://cdn.inappstory.ru/story/q0t/flg/0ph/xt67uw7kgqe9bag7spwkkyw/custom_cover/logo-350x440.webp?k=IgAAAAAAAAAE&v=2941222737', + 'https://static.insales-cdn.com/r/qh75IE5DBks/rs:fit:1000:0:1/q:100/plain/images/products/1/6158/618502158/DSC03422.jpg@webp', }, { previewImageUrl: - 'https://cdn.inappstory.ru/story/lza/rsp/2gc/xrar8zdspl4saq4uajmso38/custom_cover/logo-350x440.webp?k=IgAAAAAAAAAE&v=4207486284', + 'https://static.insales-cdn.com/r/qK4L2mJ0YZI/rs:fit:1000:0:1/q:100/plain/images/products/1/4808/736613064/DSC09448__2_.jpg@webp', }, ], }); @@ -193,27 +205,32 @@ async function up() { { storyId: 1, sourceUrl: - 'https://cdn.inappstory.ru/file/dd/yj/sx/oqx9feuljibke3mknab7ilb35t.webp?k=IgAAAAAAAAAE', + 'https://static.insales-cdn.com/r/Igx7a8HKYP0/rs:fit:1000:0:1/q:100/plain/images/products/1/6970/904469306/DSC08191.jpg@webp', + }, + { + storyId: 1, + sourceUrl: + 'https://static.insales-cdn.com/images/products/1/7133/880278493/DSC08293__2_.jpg', }, { storyId: 1, sourceUrl: - 'https://cdn.inappstory.ru/file/jv/sb/fh/io7c5zarojdm7eus0trn7czdet.webp?k=IgAAAAAAAAAE', + 'https://static.insales-cdn.com/images/products/1/7431/835755271/3__9_.jpg', }, { storyId: 1, sourceUrl: - 'https://cdn.inappstory.ru/file/ts/p9/vq/zktyxdxnjqbzufonxd8ffk44cb.webp?k=IgAAAAAAAAAE', + 'https://static.insales-cdn.com/r/AThmZSL1O1I/rs:fit:1000:0:1/q:100/plain/images/products/1/3196/915991676/DSC09476.jpg@webp', }, { storyId: 1, sourceUrl: - 'https://cdn.inappstory.ru/file/ur/uq/le/9ufzwtpdjeekidqq04alfnxvu2.webp?k=IgAAAAAAAAAE', + 'https://static.insales-cdn.com/r/qh75IE5DBks/rs:fit:1000:0:1/q:100/plain/images/products/1/6158/618502158/DSC03422.jpg@webp', }, { storyId: 1, sourceUrl: - 'https://cdn.inappstory.ru/file/sy/vl/c7/uyqzmdojadcbw7o0a35ojxlcul.webp?k=IgAAAAAAAAAE', + 'https://static.insales-cdn.com/r/qK4L2mJ0YZI/rs:fit:1000:0:1/q:100/plain/images/products/1/4808/736613064/DSC09448__2_.jpg@webp', }, ], }); @@ -227,6 +244,8 @@ async function down() { await prisma.$executeRaw`TRUNCATE TABLE "Ingredient" RESTART IDENTITY CASCADE`; await prisma.$executeRaw`TRUNCATE TABLE "Product" RESTART IDENTITY CASCADE`; await prisma.$executeRaw`TRUNCATE TABLE "ProductItem" RESTART IDENTITY CASCADE`; + await prisma.$executeRaw`TRUNCATE TABLE "Story" RESTART IDENTITY CASCADE`; + await prisma.$executeRaw`TRUNCATE TABLE "StoryItem" RESTART IDENTITY CASCADE`; } async function main() { diff --git a/public/logo1.png b/public/logo1.png new file mode 100644 index 0000000000000000000000000000000000000000..436953f9748ef073984c7e2556569e8a6d8cf913 GIT binary patch literal 8066 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 NRdBocjp)<De*lxax`hA$ literal 0 HcmV?d00001 diff --git a/shared/components/shared/filters.tsx b/shared/components/shared/filters.tsx index b2ee464..1fcc1ef 100644 --- a/shared/components/shared/filters.tsx +++ b/shared/components/shared/filters.tsx @@ -30,7 +30,7 @@ export const Filters: React.FC<Props> = ({ className }) => { <Title text="Фильтрация" size="sm" className="mb-5 font-bold" /> {/* Верхние чекбоксы */} - <CheckboxFiltersGroup + {/* <CheckboxFiltersGroup title="Тип теста" name="pizzaTypes" className="mb-5" @@ -53,7 +53,7 @@ export const Filters: React.FC<Props> = ({ className }) => { { text: '30 см', value: '30' }, { text: '40 см', value: '40' }, ]} - /> + /> */} {/* Фильтр цен */} <div className="mt-5 border-y border-y-neutral-100 py-6 pb-7"> @@ -63,15 +63,15 @@ export const Filters: React.FC<Props> = ({ className }) => { type="number" placeholder="0" min={0} - max={1000} + max={10000} value={String(filters.prices.priceFrom)} onChange={(e) => filters.setPrices('priceFrom', Number(e.target.value))} /> <Input type="number" min={100} - max={1000} - placeholder="1000" + max={10000} + placeholder="10000" value={String(filters.prices.priceTo)} onChange={(e) => filters.setPrices('priceTo', Number(e.target.value))} /> @@ -79,7 +79,7 @@ export const Filters: React.FC<Props> = ({ className }) => { <RangeSlider min={0} - max={1000} + max={10000} step={10} value={[filters.prices.priceFrom || 0, filters.prices.priceTo || 1000]} onValueChange={updatePrices} @@ -87,7 +87,7 @@ export const Filters: React.FC<Props> = ({ className }) => { </div> <CheckboxFiltersGroup - title="Ингредиенты" + title="Аксессуары" name="ingredients" className="mt-5" limit={6} diff --git a/shared/components/shared/header.tsx b/shared/components/shared/header.tsx index 2175a50..953d072 100644 --- a/shared/components/shared/header.tsx +++ b/shared/components/shared/header.tsx @@ -51,10 +51,10 @@ export const Header: React.FC<Props> = ({ hasSearch = true, hasCart = true, clas {/* Левая часть */} <Link href="/"> <div className="flex items-center gap-4"> - <Image src="/logo.png" alt="Logo" width={35} height={35} /> + <Image src="/logo1.png" alt="Logo" width={35} height={35} /> <div> - <h1 className="text-2xl uppercase font-black">Next Pizza</h1> - <p className="text-sm text-gray-400 leading-3">вкусней уже некуда</p> + <h1 className="text-2xl uppercase font-black">Ножи СПБ</h1> + <p className="text-sm text-gray-400 leading-3">Доставка по РФ</p> </div> </div> </Link> diff --git a/shared/components/shared/modals/auth-modal/auth-modal.tsx b/shared/components/shared/modals/auth-modal/auth-modal.tsx index 931e60a..d14a334 100644 --- a/shared/components/shared/modals/auth-modal/auth-modal.tsx +++ b/shared/components/shared/modals/auth-modal/auth-modal.tsx @@ -44,7 +44,7 @@ export const AuthModal: React.FC<Props> = ({ open, onClose }) => { } type="button" className="gap-2 h-12 p-2 flex-1"> - <img className="w-6 h-6" src="https://github.githubassets.com/favicons/favicon.svg" /> + <img className="w-6 h-6" src="https://github.githubassets.com/favicons/favicon.svg" /> GitHub </Button> diff --git a/shared/components/shared/pizza-image.tsx b/shared/components/shared/pizza-image.tsx index fbca741..f3b804f 100644 --- a/shared/components/shared/pizza-image.tsx +++ b/shared/components/shared/pizza-image.tsx @@ -20,8 +20,8 @@ export const PizzaImage: React.FC<Props> = ({ imageUrl, size, className }) => { })} /> - <div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border-dashed border-2 rounded-full border-gray-200 w-[450px] h-[450px]" /> - <div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border-dotted border-2 rounded-full border-gray-100 w-[370px] h-[370px]" /> + {/* <div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border-dashed border-2 rounded-full border-gray-200 w-[450px] h-[450px]" /> + <div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 border-dotted border-2 rounded-full border-gray-100 w-[370px] h-[370px]" /> */} </div> ); }; diff --git a/shared/components/shared/profile-button.tsx b/shared/components/shared/profile-button.tsx index 9a3d3b3..5b4bb36 100644 --- a/shared/components/shared/profile-button.tsx +++ b/shared/components/shared/profile-button.tsx @@ -13,7 +13,7 @@ export const ProfileButton: React.FC<Props> = ({ className, onClickSignIn }) => const { data: session } = useSession(); return ( - <div className={className}> + <div className={className}> {!session ? ( <Button onClick={onClickSignIn} variant="outline" className="flex items-center gap-1"> <User size={16} /> diff --git a/shared/components/shared/providers.tsx b/shared/components/shared/providers.tsx index 06bba26..aa00a46 100644 --- a/shared/components/shared/providers.tsx +++ b/shared/components/shared/providers.tsx @@ -8,9 +8,10 @@ import NextTopLoader from 'nextjs-toploader'; export const Providers: React.FC<React.PropsWithChildren> = ({ children }) => { return ( <> - <SessionProvider>{children}</SessionProvider> + <SessionProvider>{children}</SessionProvider> <Toaster /> <NextTopLoader /> </> ); }; +// SessionProvider внутри себя будет хранить контекст, который мы уже будем прокидыать в то место куда нам нужно \ No newline at end of file diff --git a/shared/components/shared/search-input.tsx b/shared/components/shared/search-input.tsx index 42e103a..84a4b2e 100644 --- a/shared/components/shared/search-input.tsx +++ b/shared/components/shared/search-input.tsx @@ -52,7 +52,7 @@ export const SearchInput: React.FC<Props> = ({ className }) => { <input className="rounded-2xl outline-none w-full bg-gray-100 pl-11" type="text" - placeholder="Найти пиццу..." + placeholder="Найти товар..." onFocus={() => setFocused(true)} value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} diff --git a/shared/constants/pizza.ts b/shared/constants/pizza.ts index fcaf784..3abaca2 100644 --- a/shared/constants/pizza.ts +++ b/shared/constants/pizza.ts @@ -1,12 +1,12 @@ export const mapPizzaSize = { - 20: 'Маленькая', - 30: 'Средняя', - 40: 'Большая', + 20: 'Обычный', + 30: 'Средний', + 40: 'Большой', } as const; export const mapPizzaType = { - 1: 'традиционная', - 2: 'тонкая', + 1: 'стандартный', + 2: 'кастомный', } as const; export const pizzaSizes = Object.entries(mapPizzaSize).map(([value, name]) => ({ diff --git a/shared/lib/get-pizza-details.ts b/shared/lib/get-pizza-details.ts index 558551e..7b11428 100644 --- a/shared/lib/get-pizza-details.ts +++ b/shared/lib/get-pizza-details.ts @@ -10,7 +10,7 @@ export const getPizzaDetails = ( selectedIngredients: Set<number>, ) => { const totalPrice = calcTotalPizzaPrice(type, size, items, ingredients, selectedIngredients); - const textDetaills = `${size} см, ${mapPizzaType[type]} пицца`; + const textDetaills = `${size} см, ${mapPizzaType[type]} нож`; - return { totalPrice, textDetaills }; + return { totalPrice, textDetaills}; }; From 8ef8782789163aebaa470a123b05b76d617a06f9 Mon Sep 17 00:00:00 2001 From: Franz <f.o.larionov@gmail.com> Date: Sun, 29 Sep 2024 12:29:00 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B8=D0=BF=20verified:=20=D0=BD=D0=B0=20true?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next-pizza | 1 + shared/constants/auth-options.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 160000 next-pizza diff --git a/next-pizza b/next-pizza new file mode 160000 index 0000000..03acc36 --- /dev/null +++ b/next-pizza @@ -0,0 +1 @@ +Subproject commit 03acc36ef9c8b84087affd78ce2d92ecbd25e9fe diff --git a/shared/constants/auth-options.ts b/shared/constants/auth-options.ts index 431be51..dac59bb 100644 --- a/shared/constants/auth-options.ts +++ b/shared/constants/auth-options.ts @@ -111,7 +111,7 @@ export const authOptions: AuthOptions = { email: user.email, fullName: user.name || 'User #' + user.id, password: hashSync(user.id.toString(), 10), - verified: new Date(), + verified: true, provider: account?.provider, providerId: account?.providerAccountId, },