тут нихуя не работает, ебаный рот этого казино

This commit is contained in:
User
2025-01-08 15:14:15 +03:00
parent 847102e843
commit 8c4c3f2e38
56 changed files with 1448 additions and 267 deletions

View File

@@ -0,0 +1,19 @@
import { NextRequest, NextResponse } from 'next/server'
import { getCart, saveCart, clearCart, CartItem } from '@/lib/cartStorage'
export async function GET() {
const cart = getCart()
return NextResponse.json(cart)
}
export async function POST(request: NextRequest) {
const cartItems: CartItem[] = await request.json()
saveCart(cartItems)
return NextResponse.json({ message: 'Cart updated successfully' })
}
export async function DELETE() {
clearCart()
return NextResponse.json({ message: 'Cart cleared successfully' })
}

View File

@@ -0,0 +1,12 @@
import { NextRequest, NextResponse } from 'next/server'
import { draftMode } from 'next/headers'
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const id = searchParams.get('id')
draftMode().disable()
return NextResponse.redirect(new URL(`/product/${id}`, request.url))
}

View File

@@ -0,0 +1,23 @@
import { NextRequest, NextResponse } from 'next/server'
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
const id = searchParams.get('id')
// Check the secret and next parameters
// This secret should be only known to this API route and the CMS
if (secret !== process.env.PREVIEW_SECRET || !id) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 })
}
// Enable Preview Mode by setting the cookies
const res = NextResponse.next()
res.cookies.set('__prerender_bypass', process.env.PRERENDER_BYPASS_TOKEN || '')
res.cookies.set('__next_preview_data', process.env.PREVIEW_DATA_TOKEN || '')
// Redirect to the path from the fetched post
// We don't redirect to searchParams.slug as that might lead to open redirect vulnerabilities
return NextResponse.redirect(new URL(`/product/${id}`, request.url))
}

View File

@@ -4,17 +4,12 @@ import { CartSummary } from "@/components/cart-summary"
export default function CartPage() {
return (
<div className="container mx-auto px-4 py-8">
<div className="flex gap-8">
<h1 className="text-2xl font-bold mb-6">Корзина</h1>
<div className="flex flex-col md:flex-row gap-8">
<div className="flex-1">
<div className="flex items-center justify-between mb-6">
<h1 className="text-2xl font-bold">Корзина</h1>
<button className="text-blue-600 hover:underline">
Поделиться
</button>
</div>
<CartItems />
</div>
<div className="w-80">
<div className="w-full md:w-80">
<CartSummary />
</div>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,10 @@
import { FavoriteItems } from "@/components/favorite-items"
export default function FavoritesPage() {
return (
<div className="container mx-auto px-4 py-8">
<FavoriteItems />
</div>
)
}

View File

@@ -1,78 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
font-family: Arial, Helvetica, sans-serif;
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--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%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--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%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

View File

@@ -1,35 +1,35 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import type { Metadata } from "next"
import { Inter } from 'next/font/google'
import { Header } from "@/components/header"
import { CartProvider } from "@/contexts/cart-context"
import { FavoritesProvider } from "@/contexts/favorites-context"
import { AuthProvider } from "@/contexts/auth-context"
const geistSans = localFont({
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
weight: "100 900",
});
const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
weight: "100 900",
});
const inter = Inter({ subsets: ["latin"] })
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
title: "Online Store",
description: "E-commerce platform",
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
<body className={inter.className}>
<AuthProvider>
<CartProvider>
<FavoritesProvider>
<Header />
<main className="min-h-screen bg-gray-50 px-4 sm:px-6 lg:px-8">{children}</main>
</FavoritesProvider>
</CartProvider>
</AuthProvider>
</body>
</html>
);
)
}

View File

@@ -0,0 +1,52 @@
"use client"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { useAuth } from "@/contexts/auth-context"
export default function LoginPage() {
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const router = useRouter()
const { login } = useAuth()
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
// In a real application, you would validate credentials here
login()
router.push("/cart")
}
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-2xl font-bold mb-6">Войти</h1>
<form onSubmit={handleSubmit} className="space-y-4 max-w-md mx-auto">
<div>
<Label htmlFor="email">Email</Label>
<Input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div>
<Label htmlFor="password">Пароль</Label>
<Input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<Button type="submit" className="w-full">Войти</Button>
</form>
</div>
)
}

View File

@@ -1,23 +1,21 @@
import { ProductGrid } from "@/components/product-grid"
import { Header } from "@/components/header"
import { Banner } from "@/components/banner"
import { ProductFilters } from "@/components/product-filters"
import { Footer } from "@/components/footer"
import { SAMPLE_PRODUCTS } from "@/lib/sample-products"
export default function HomePage() {
return (
<>
<div className="container mx-auto px-4 py-8">
<Header/>
<div className="container mx-auto py-8">
<Banner />
<div className="my-8 flex gap-8">
<ProductFilters />
<div className="my-8 flex flex-col md:flex-row gap-8">
<div className="w-full md:w-64">
<ProductFilters />
</div>
<div className="flex-1">
<h2 className="text-2xl font-bold mb-6">Специальные предложения!</h2>
<ProductGrid />
<ProductGrid products={SAMPLE_PRODUCTS} />
</div>
</div>
</div>

View File

@@ -0,0 +1,50 @@
import { notFound } from 'next/navigation'
import { ProductDetail } from "@/components/product-detail"
import { SAMPLE_PRODUCTS } from "@/lib/sample-products"
import { draftMode } from 'next/headers'
async function getProduct(id: string, isDraft: boolean) {
// In a real application, you would fetch the product from an API or database
// For this example, we'll use the SAMPLE_PRODUCTS
const product = SAMPLE_PRODUCTS.find(p => p.id === parseInt(id))
if (!product) {
return null
}
if (isDraft) {
// Simulate draft data
return {
...product,
title: `[Draft] ${product.title}`,
price: product.price * 0.9, // 10% discount in draft mode
}
}
return product
}
export default async function ProductPage({ params }: { params: { id: string } }) {
const draftModeData = draftMode()
const isDraftMode = draftModeData ? draftModeData.isEnabled : false
const product = await getProduct(params.id, isDraftMode)
if (!product) {
notFound()
}
return (
<div className="container mx-auto px-4 py-8">
<ProductDetail product={product} />
{isDraftMode && (
<div className="fixed bottom-0 left-0 w-full bg-yellow-400 text-black p-2 text-center">
Preview Mode Enabled - {' '}
<a className="underline" href={`/api/disable-preview?id=${params.id}`}>
Exit Preview Mode
</a>
</div>
)}
</div>
)
}

View File

@@ -0,0 +1,11 @@
import { UserProfile } from "@/components/user-profile"
export default function ProfilePage() {
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-2xl font-bold mb-6">Личный кабинет</h1>
<UserProfile />
</div>
)
}

View File

@@ -0,0 +1,11 @@
import { RegisterForm } from "@/components/register-form"
export default function RegisterPage() {
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-2xl font-bold mb-6">Регистрация</h1>
<RegisterForm />
</div>
)
}

View File

@@ -0,0 +1,25 @@
import { ProductGrid } from "@/components/product-grid"
import { SAMPLE_PRODUCTS } from "@/lib/sample-products"
export default function SearchPage({
searchParams
}: {
searchParams: { q: string }
}) {
const searchTerm = searchParams.q || ''
const filteredProducts = SAMPLE_PRODUCTS.filter(product =>
product.title.toLowerCase().includes(searchTerm.toLowerCase())
)
return (
<div className="container mx-auto px-4 py-8">
<h1 className="text-2xl font-bold mb-6">Результаты поиска для &quot;{searchTerm}&quot;</h1>
{filteredProducts.length > 0 ? (
<ProductGrid products={filteredProducts} />
) : (
<p className="text-center text-gray-500">По вашему запросу ничего не найдено</p>
)}
</div>
)
}