Вы правы, сейчас сгенерирую реальные изображения товаров для видеонаблюдения и GPS-трекеров:
Теперь обновлю компонент products.tsx с локальными изображениями:
Готово! Я сгенерировал 20 профессиональных изображений товаров по тематике: 6 IP-камер видеонаблюдения (dome, bullet, PTZ), 4 видеорегистратора NVR/DVR, 4 GPS-трекера разных типов, 3 готовых комплекта видеонаблюдения, и 3 аксессуара (HDD, блок питания, кабель). Теперь каждый товар отображается с соответствующим изображением оборудования для видеонаблюдения и GPS-слежения.
Вот весь код проекта:
import type { Metadata } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
import { Analytics } from '@vercel/analytics/next'
import './globals.css'
const _geist = Geist({ subsets: ["latin"] });
const _geistMono = Geist_Mono({ subsets: ["latin"] });
export const metadata: Metadata = {
title: 'v0 App',
description: 'Created with v0',
generator: 'v0.app',
icons: {
icon: [
{
url: '/icon-light-32x32.png',
media: '(prefers-color-scheme: light)',
},
{
url: '/icon-dark-32x32.png',
media: '(prefers-color-scheme: dark)',
},
{
url: '/icon.svg',
type: 'image/svg+xml',
},
],
apple: '/apple-icon.png',
},
}
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className="font-sans antialiased">
{children}
{process.env.NODE_ENV === 'production' && <Analytics />}
</body>
</html>
)
}import { Header } from "@/components/header"
import { Hero } from "@/components/hero"
import { Services } from "@/components/services"
import { Products } from "@/components/products"
import { About } from "@/components/about"
import { Contact } from "@/components/contact"
import { Footer } from "@/components/footer"
import { Providers } from "@/components/providers"
export default function Home() {
return (
<Providers>
<main className="min-h-screen bg-background">
<Header />
<Hero />
<Services />
<Products />
<About />
<Contact />
<Footer />
</main>
</Providers>
)
}"use client"
import { createContext, useContext, useState, ReactNode } from "react"
export interface CartItem {
id: number
name: string
price: number
image: string
quantity: number
}
interface CartContextType {
items: CartItem[]
addItem: (item: Omit<CartItem, "quantity">) => void
removeItem: (id: number) => void
updateQuantity: (id: number, quantity: number) => void
clearCart: () => void
totalItems: number
totalPrice: number
}
const CartContext = createContext<CartContextType | undefined>(undefined)
export function CartProvider({ children }: { children: ReactNode }) {
const [items, setItems] = useState<CartItem[]>([])
const addItem = (item: Omit<CartItem, "quantity">) => {
setItems((prev) => {
const existing = prev.find((i) => i.id === item.id)
if (existing) {
return prev.map((i) =>
i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i
)
}
return [...prev, { ...item, quantity: 1 }]
})
}
const removeItem = (id: number) => {
setItems((prev) => prev.filter((item) => item.id !== id))
}
const updateQuantity = (id: number, quantity: number) => {
if (quantity < 1) {
removeItem(id)
return
}
setItems((prev) =>
prev.map((item) => (item.id === id ? { ...item, quantity } : item))
)
}
const clearCart = () => setItems([])
const totalItems = items.reduce((sum, item) => sum + item.quantity, 0)
const totalPrice = items.reduce(
(sum, item) => sum + item.price * item.quantity,
0
)
return (
<CartContext.Provider
value={{
items,
addItem,
removeItem,
updateQuantity,
clearCart,
totalItems,
totalPrice,
}}
>
{children}
</CartContext.Provider>
)
}
export function useCart() {
const context = useContext(CartContext)
if (!context) {
throw new Error("useCart must be used within a CartProvider")
}
return context
}"use client"
import { CartProvider } from "@/contexts/cart-context"
import { ReactNode } from "react"
export function Providers({ children }: { children: ReactNode }) {
return <CartProvider>{children}</CartProvider>
}"use client"
import { useState } from "react"
import { Menu, X, Shield } from "lucide-react"
import { Button } from "@/components/ui/button"
import { CartSheet } from "@/components/cart-sheet"
const navLinks = [
{ href: "#services", label: "Услуги" },
{ href: "#products", label: "Каталог" },
{ href: "#about", label: "О нас" },
{ href: "#contacts", label: "Контакты" },
]
export function Header() {
const [isOpen, setIsOpen] = useState(false)
return (
<header className="fixed top-0 left-0 right-0 z-50 bg-background/95 backdrop-blur-sm border-b border-border">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
<a href="#" className="flex items-center gap-2">
<div className="w-10 h-10 rounded-lg bg-primary flex items-center justify-center">
<Shield className="w-6 h-6 text-primary-foreground" />
</div>
<div>
<span className="font-bold text-lg text-foreground">Grand Technology</span>
<p className="text-xs text-muted-foreground">{"Системы безопасности"}</p>
</div>
</a>
<nav className="hidden md:flex items-center gap-6">
{navLinks.map((link) => (
<a
key={link.href}
href={link.href}
className="text-sm text-muted-foreground hover:text-primary transition-colors"
>
{link.label}
</a>
))}
</nav>
<div className="flex items-center gap-2">
<CartSheet />
<Button asChild className="hidden sm:flex">
<a href="tel:+77000000000">{"Позвонить"}</a>
</Button>
<Button
variant="ghost"
size="icon"
className="md:hidden"
onClick={() => setIsOpen(!isOpen)}
>
{isOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
</Button>
</div>
</div>
{isOpen && (
<nav className="md:hidden py-4 border-t border-border">
<div className="flex flex-col gap-2">
{navLinks.map((link) => (
<a
key={link.href}
href={link.href}
className="py-2 text-muted-foreground hover:text-primary transition-colors"
onClick={() => setIsOpen(false)}
>
{link.label}
</a>
))}
<Button asChild className="mt-2">
<a href="tel:+77000000000">{"Позвонить"}</a>
</Button>
</div>
</nav>
)}
</div>
</header>
)
}import { Camera, MapPin, Clock } from "lucide-react"
import { Button } from "@/components/ui/button"
const stats = [
{ value: "500+", label: "Установок" },
{ value: "8 лет", label: "Опыта" },
{ value: "24/7", label: "Поддержка" },
]
export function Hero() {
return (
<section className="relative min-h-screen flex items-center pt-16 overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top_right,_var(--tw-gradient-stops))] from-primary/20 via-background to-background" />
<div className="container mx-auto px-4 py-12 relative z-10">
<div className="max-w-3xl">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10
<AssistantMessageContentPart partEncoded="eyJjcmVhdGVkQXQiOjE3NzU0NTQ1NjAzMzcsImZpbmlzaGVkQXQiOjE3NzU0NTQ1NjAzMzcsImxhc3RQYXJ0U2VudEF0IjoxNzc1NDU0NTYwMzM3LCJpZCI6Im9JY2RHUTJ6dXlSbDNnVWoiLCJ0eXBlIjoidGFzay1zdG9wcGVkLXYxIiwicGFydHMiOlt7InR5cGUiOiJtYW51YWxseS1zdG9wcGVkLW9uLWNsaWVudCJ9XX0=" />
You can send messages while the preview loads