final commit before execution
This commit is contained in:
@@ -8,7 +8,6 @@ export default async function AuthLayout({
|
|||||||
return (
|
return (
|
||||||
<section className='relative w-full'>
|
<section className='relative w-full'>
|
||||||
<div className='flex h-screen items-center justify-center bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-brand-violet-400 to-brand-yellow-200'>
|
<div className='flex h-screen items-center justify-center bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-brand-violet-400 to-brand-yellow-200'>
|
||||||
{/**/}
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -3,9 +3,15 @@
|
|||||||
import {useTranslations} from 'next-intl'
|
import {useTranslations} from 'next-intl'
|
||||||
|
|
||||||
import CartItems from '@/components/pages/cart/items'
|
import CartItems from '@/components/pages/cart/items'
|
||||||
|
import useCartStore from '@/store/cart-store'
|
||||||
|
|
||||||
export default function Cart() {
|
export default function Cart() {
|
||||||
const t = useTranslations('cart')
|
const t = useTranslations('cart')
|
||||||
|
const {cartItems} = useCartStore()
|
||||||
|
const totalSum = cartItems.reduce(
|
||||||
|
(total, product) => total + parseFloat(product.price) * product.quantity,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
// const subtotal = items.reduce(
|
// const subtotal = items.reduce(
|
||||||
// (total, item) => total + item.price * item.quantity,
|
// (total, item) => total + item.price * item.quantity,
|
||||||
@@ -26,6 +32,13 @@ export default function Cart() {
|
|||||||
<div className='col text-right'>{t('amount')}</div>
|
<div className='col text-right'>{t('amount')}</div>
|
||||||
</header>
|
</header>
|
||||||
<CartItems />
|
<CartItems />
|
||||||
|
<footer className='my-8 flex border-y border-y-brand-violet py-4 text-xl'>
|
||||||
|
<div className='col'></div>
|
||||||
|
<div className='flex-none'>{t('total')}:</div>
|
||||||
|
<div className='col text-right font-bold'>
|
||||||
|
{totalSum.toFixed(2)} грн
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export default function LoginForm() {
|
|||||||
</div>
|
</div>
|
||||||
<FormError message={error} />
|
<FormError message={error} />
|
||||||
<Button type='submit' className='w-full' disabled={loading}>
|
<Button type='submit' className='w-full' disabled={loading}>
|
||||||
{loading ? 'Loading...' : 'Login'}
|
{loading ? 'Loading...' : 'Увійти'}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -23,20 +23,7 @@ export default function CartItems() {
|
|||||||
removeItemFromCart(productId)
|
removeItemFromCart(productId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cartItems && cartItems.length < 1) {
|
if (cartItems && cartItems.length > 0) {
|
||||||
return (
|
|
||||||
<div className='flex h-72 flex-col items-center justify-center'>
|
|
||||||
<h2 className='mb-5 mt-10 text-3xl font-bold'>Cart is Empty</h2>
|
|
||||||
<Link
|
|
||||||
href={'/catalog'}
|
|
||||||
className='rounded-md bg-orange-500 px-6 py-2 text-white'
|
|
||||||
>
|
|
||||||
Shop
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{cartItems?.map((item: CartItem, i: number) => (
|
{cartItems?.map((item: CartItem, i: number) => (
|
||||||
@@ -85,3 +72,15 @@ export default function CartItems() {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return (
|
||||||
|
<div className='flex h-72 flex-col items-center justify-center'>
|
||||||
|
<h2 className='mb-5 mt-10 text-3xl font-bold'>Cart is Empty</h2>
|
||||||
|
<Link
|
||||||
|
href={'/catalog'}
|
||||||
|
className='rounded-md bg-orange-500 px-6 py-2 text-white'
|
||||||
|
>
|
||||||
|
Продовжити покупки
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export default function ProductCarousel({
|
|||||||
selected={index === selectedIndex}
|
selected={index === selectedIndex}
|
||||||
index={index}
|
index={index}
|
||||||
/>
|
/>
|
||||||
<DialogContent className='overflow w-full'>
|
<DialogContent className='overflow max-w-screen rounded-0 h-screen p-0'>
|
||||||
<Image
|
<Image
|
||||||
src={image.uri}
|
src={image.uri}
|
||||||
alt=''
|
alt=''
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {ProductResource} from '@prisma/client'
|
import {ProductResource} from '@prisma/client'
|
||||||
import {getProductByIdWitData} from '@prisma/client/sql'
|
import {getProductByIdWitData} from '@prisma/client/sql'
|
||||||
|
import {ChevronDown, ChevronsUpDown} from 'lucide-react'
|
||||||
import {getTranslations} from 'next-intl/server'
|
import {getTranslations} from 'next-intl/server'
|
||||||
import {notFound} from 'next/navigation'
|
import {notFound} from 'next/navigation'
|
||||||
|
|
||||||
@@ -13,10 +14,20 @@ import {
|
|||||||
BreadcrumbPage,
|
BreadcrumbPage,
|
||||||
BreadcrumbSeparator
|
BreadcrumbSeparator
|
||||||
} from '@/components/ui/breadcrumb'
|
} from '@/components/ui/breadcrumb'
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger
|
||||||
|
} from '@/components/ui/collapsible'
|
||||||
|
import {Select, SelectTrigger, SelectValue} from '@/components/ui/select'
|
||||||
|
import products from '@/data/products'
|
||||||
|
import {Link} from '@/i18n/routing'
|
||||||
|
import {getMetaOfFile} from '@/lib/config/resources'
|
||||||
import {getProductResources} from '@/lib/data/models/product'
|
import {getProductResources} from '@/lib/data/models/product'
|
||||||
import {CategoryPageSqlSchema} from '@/lib/data/models/sqlSchemas'
|
import {CategoryPageSqlSchema} from '@/lib/data/models/sqlSchemas'
|
||||||
import {db} from '@/lib/db/prisma/client'
|
import {db} from '@/lib/db/prisma/client'
|
||||||
import {thisLocale, toPrice} from '@/lib/utils'
|
import {dump, thisLocale, toPrice} from '@/lib/utils'
|
||||||
|
import {Button} from '@/ui/button'
|
||||||
import {Separator} from '@/ui/separator'
|
import {Separator} from '@/ui/separator'
|
||||||
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/ui/tabs'
|
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/ui/tabs'
|
||||||
|
|
||||||
@@ -35,6 +46,7 @@ export default async function ProductPageIndex({id}: {id: string}) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
//const files = await getMetaOfFile(locale.productId)
|
//const files = await getMetaOfFile(locale.productId)
|
||||||
|
const attrs = products.find(products => products.id === parseInt(id))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-1'>
|
<div className='mt-1'>
|
||||||
@@ -80,10 +92,21 @@ export default async function ProductPageIndex({id}: {id: string}) {
|
|||||||
<TabsTrigger value='instuction'>Інструкція</TabsTrigger>
|
<TabsTrigger value='instuction'>Інструкція</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsContent value='article'>
|
<TabsContent value='article'>
|
||||||
|
<div>
|
||||||
|
<h1 className='my-6 ml-12 text-3xl font-bold text-brand-violet'>
|
||||||
|
{locale.headingTitle}
|
||||||
|
</h1>
|
||||||
|
<div
|
||||||
|
className='ml-8 w-[88%] rounded-lg border-x-4 border-brand-violet bg-zinc-50 p-4 leading-relaxed'
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: locale.description as string
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
<article
|
<article
|
||||||
className='bw-product__text'
|
className='bw-product__text'
|
||||||
dangerouslySetInnerHTML={{__html: locale.content as string}}
|
dangerouslySetInnerHTML={{__html: locale.content as string}}
|
||||||
></article>
|
></article>
|
||||||
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value='instuction'>
|
<TabsContent value='instuction'>
|
||||||
<div
|
<div
|
||||||
@@ -93,13 +116,74 @@ export default async function ProductPageIndex({id}: {id: string}) {
|
|||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
<section className='bw-product-col-right bg-gray-50 pt-3'>
|
<section className='bw-product-col-right mt-16 pt-3'>
|
||||||
<div className=''>
|
<div className=''>
|
||||||
{t('price')}:
|
{t('price')}:
|
||||||
<span className='ml-2 flex-auto text-right text-xl font-bold text-brand-violet'>
|
<span className='ml-2 flex-auto text-right text-xl font-bold text-brand-violet'>
|
||||||
{toPrice(locale.price)}
|
{toPrice(locale.price)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
{attrs && (
|
||||||
|
<>
|
||||||
|
<Select>
|
||||||
|
<SelectTrigger className='my-4 w-full'>
|
||||||
|
<SelectValue placeholder={attrs?.title} />
|
||||||
|
</SelectTrigger>
|
||||||
|
</Select>
|
||||||
|
<Button className='mb-4 w-full text-brand-violet'>Купити</Button>
|
||||||
|
<div>Є в наявності</div>
|
||||||
|
|
||||||
|
<div className='mb-4 mt-8 font-bold'>Характеристики</div>
|
||||||
|
|
||||||
|
<div className='flex items-center justify-between border-y-2 py-3 pl-1 text-sm'>
|
||||||
|
<div className='text-gray-600'>Категорія</div>
|
||||||
|
<div className='text-brand-violet'>
|
||||||
|
<Link href={`/category/${locale.categorySlug}`}>
|
||||||
|
{locale.categoryTitle}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Collapsible className='border-b-2 py-3 pl-1 text-sm'>
|
||||||
|
<CollapsibleTrigger className='flex w-full items-center justify-between'>
|
||||||
|
<div className='text-gray-600'>Склад</div>
|
||||||
|
<div>
|
||||||
|
<ChevronDown color='#4b5563' />
|
||||||
|
</div>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent className='py-3 text-sm text-gray-600'>
|
||||||
|
Склад 1 капсула містить:
|
||||||
|
<br />
|
||||||
|
сухий екстракт ламінарії (Laminaria japonica Extract 1%
|
||||||
|
iodine) – 15,0 мг (mg), що еквівалентно 150,0 мкг (μg) йоду,
|
||||||
|
<br />
|
||||||
|
селенометіонін ̶ 250,0 мкг (μg), що еквівалентно 100,0 мкг (μg)
|
||||||
|
селену;
|
||||||
|
<br />
|
||||||
|
допоміжні речовини: наповнювач: целюлоза мікрокристалічна,
|
||||||
|
антиспікаючий агент: кремнію діоксид колоїдний безводний,
|
||||||
|
кальцію стеарат.
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
|
||||||
|
<div className='flex items-center justify-between border-b-2 py-3 pl-1 text-sm'>
|
||||||
|
<div className='text-gray-600'>Форма</div>
|
||||||
|
<div className='text-brand-violet'>{attrs?.form}</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center justify-between border-b-2 py-3 pl-1 text-sm'>
|
||||||
|
<div className='text-gray-600'>Виробник</div>
|
||||||
|
<div className='text-brand-violet'>{attrs?.vendor}</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex items-center justify-between border-b-2 py-3 pl-1 text-sm'>
|
||||||
|
<div className='text-gray-600'>Країна-виробник</div>
|
||||||
|
<div className='text-brand-violet'>{attrs?.country}</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className='ml-1 mt-4 inline-block border-b border-dashed border-b-brand-violet pb-2 text-sm text-brand-violet'>
|
||||||
|
Завантажити інструкцію
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function HeaderControls() {
|
|||||||
const t = useTranslations('cart')
|
const t = useTranslations('cart')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex w-full justify-end gap-x-9 text-brand-violet'>
|
<div className='flex w-full justify-end gap-x-6 text-brand-violet'>
|
||||||
<CabinetButton />
|
<CabinetButton />
|
||||||
|
|
||||||
<Link href={'#' as never} className='header-button' aria-label='Вибране'>
|
<Link href={'#' as never} className='header-button' aria-label='Вибране'>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import {useLocale} from 'next-intl'
|
||||||
import {useState} from 'react'
|
import {useState} from 'react'
|
||||||
|
|
||||||
import {Link} from '@/i18n/routing'
|
import {Link} from '@/i18n/routing'
|
||||||
@@ -8,7 +9,7 @@ import {Button} from '@/ui/button'
|
|||||||
|
|
||||||
export default function NavbarMenu() {
|
export default function NavbarMenu() {
|
||||||
const bp = 'md'
|
const bp = 'md'
|
||||||
|
const locale = useLocale()
|
||||||
const [menuOpened, setMenuOpened] = useState(false)
|
const [menuOpened, setMenuOpened] = useState(false)
|
||||||
|
|
||||||
function ToggleNavbar() {
|
function ToggleNavbar() {
|
||||||
@@ -19,11 +20,13 @@ export default function NavbarMenu() {
|
|||||||
<>
|
<>
|
||||||
<div className={`hidden ${bp}:block w-full`}>
|
<div className={`hidden ${bp}:block w-full`}>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
{data.headerMenus.map(item => (
|
{data[locale === 'uk' ? 'headerMenus' : 'headerMenusRus'].map(
|
||||||
|
item => (
|
||||||
<Link href='/about-us' className='' key={item.name}>
|
<Link href='/about-us' className='' key={item.name}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
)
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/*<div className={`flex items-center ${bp}:hidden`}>
|
{/*<div className={`flex items-center ${bp}:hidden`}>
|
||||||
|
|||||||
@@ -1,9 +1,42 @@
|
|||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
id: 0,
|
id: 6,
|
||||||
qnt: '14',
|
title: '30 капсул у блістері',
|
||||||
form: 'порошок',
|
qnt: '30',
|
||||||
vendor: 'Fine Foods & Pharmaceuticals N.T.M. SpA',
|
form: 'капсули',
|
||||||
|
vendor: 'ТОВ «АКТІЛАЙФ НУТРІШН»',
|
||||||
|
country: 'Україна'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
title: '20 питних ампул',
|
||||||
|
qnt: '20',
|
||||||
|
form: 'ампули',
|
||||||
|
vendor: 'Фармлабор-Продутос Фармасеутікос С.А.',
|
||||||
|
country: 'Португалія'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
title: '30 таблеток «ДЕНЬ» та 30 таблеток «НІЧ»',
|
||||||
|
qnt: '60',
|
||||||
|
form: 'таблетки',
|
||||||
|
vendor: 'Ерба Віта Груп С.п.А.',
|
||||||
country: 'Італія'
|
country: 'Італія'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
title: '60 таблеток у блicтерi',
|
||||||
|
qnt: '60',
|
||||||
|
form: 'таблетки',
|
||||||
|
vendor: 'ТОВ «АКТІЛАЙФ НУТРІШН»',
|
||||||
|
country: 'Україна'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
title: '10 саше у картонній коробці',
|
||||||
|
qnt: '10',
|
||||||
|
form: 'порошок',
|
||||||
|
vendor: 'ТОВ «Еубіон Корпорейшн»',
|
||||||
|
country: 'Польща'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
127
lib/data.ts
127
lib/data.ts
@@ -1,98 +1,51 @@
|
|||||||
import {slug} from '@/lib/utils'
|
|
||||||
|
|
||||||
export const data = {
|
export const data = {
|
||||||
headerMenus: [
|
headerMenus: [
|
||||||
{
|
{
|
||||||
name: 'Про нас',
|
name: 'Про нас',
|
||||||
slug: slug('Про нас'),
|
|
||||||
href: '/about-us'
|
href: '/about-us'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Цікаво про здоров'я",
|
name: "Цікаво про здоров'я",
|
||||||
slug: slug("Цікаво про здоров'я"),
|
|
||||||
href: '/search?tag='
|
href: '/search?tag='
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Програма лояльності',
|
name: 'Програма лояльності',
|
||||||
slug: slug('Програма лояльності'),
|
|
||||||
href: '/search?tag='
|
href: '/search?tag='
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Доставка і повернення',
|
name: 'Доставка і повернення',
|
||||||
slug: slug('Доставка і повернення'),
|
|
||||||
href: '/search?tag='
|
href: '/search?tag='
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Контакти',
|
name: 'Контакти',
|
||||||
slug: slug('Контакти'),
|
href: '/search?tag='
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
headerMenusRus: [
|
||||||
|
{
|
||||||
|
name: 'О нас',
|
||||||
|
href: '/about-us'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Интересно о здоровье',
|
||||||
|
href: '/search?tag='
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Программа лояльности',
|
||||||
|
href: '/search?tag='
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Доставка и возврат',
|
||||||
|
href: '/search?tag='
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Контакты',
|
||||||
href: '/search?tag='
|
href: '/search?tag='
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const categories = [
|
|
||||||
{
|
|
||||||
name: "Жіноче здоров'я",
|
|
||||||
rus: 'Женское здоровье',
|
|
||||||
slug: slug("Жіноче здоров'я")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Чоловіче здоров'я",
|
|
||||||
rus: 'Мужское здоровье',
|
|
||||||
slug: slug("Чоловіче здоров'я")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Краса (шкіра, волосся, нігті)',
|
|
||||||
rus: 'Красота (кожа, волосы, ногти)',
|
|
||||||
slug: slug('Краса (шкіра, волосся, нігті)')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Здоровий сон',
|
|
||||||
rus: 'Здоровый сон',
|
|
||||||
slug: slug('Здоровий сон')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Імунітет',
|
|
||||||
rus: 'Иммунитет',
|
|
||||||
slug: slug('Імунітет')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Для кісток та суглобів',
|
|
||||||
rus: 'Для костей и суставов',
|
|
||||||
slug: slug('Для кісток та суглобів')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Для зниження цукру в крові',
|
|
||||||
rus: 'Для снижения уровня сахара в крови',
|
|
||||||
slug: slug('Для зниження цукру в крові')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Детоксикація',
|
|
||||||
rus: 'Детоксикация',
|
|
||||||
slug: slug('Детоксикація')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Здоров'я печінки",
|
|
||||||
rus: 'Здоровье печени',
|
|
||||||
slug: slug("Здоров'я печінки")
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Для щитовидної залози',
|
|
||||||
rus: 'Для щитовидной железы',
|
|
||||||
slug: slug('Для щитовидної залози')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Життєвий тонус',
|
|
||||||
rus: 'Жизненный тонус',
|
|
||||||
slug: slug('Життєвий тонус')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Антистрес',
|
|
||||||
rus: 'Антистресс',
|
|
||||||
slug: slug('Антистрес')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
export const carousels = [
|
export const carousels = [
|
||||||
{
|
{
|
||||||
title: 'The Children of the Serpent',
|
title: 'The Children of the Serpent',
|
||||||
@@ -116,37 +69,3 @@ export const carousels = [
|
|||||||
isPublished: true
|
isPublished: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
export const cards = [
|
|
||||||
{
|
|
||||||
title: 'Пінеал Тенс',
|
|
||||||
image: '/uploads/637393-1500x1500-ea2f.jpg',
|
|
||||||
href: slug('Пінеал Тенс'),
|
|
||||||
price: 720
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Вістакеа Остеостронг',
|
|
||||||
image: '/uploads/1256-vistacare_osteostrong_tablets_box_livo_1.png',
|
|
||||||
href: slug('Вістакеа Остеостронг'),
|
|
||||||
price: 640
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Вістакеа Детокс',
|
|
||||||
image:
|
|
||||||
'/uploads/1ca3d021-a55d-4c0a-aa7b-06ecb5f905b0-w1000-h1000-wm-frame.jpg',
|
|
||||||
href: slug('Вістакеа Детокс'),
|
|
||||||
price: 850
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Тіромодал',
|
|
||||||
image: '/uploads/189238-192172-orig-1500-1500-d76a.jpg',
|
|
||||||
href: slug('Тіромодал'),
|
|
||||||
price: 535
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Артросульфур С',
|
|
||||||
image: '/uploads/79282077-e324-4248-9f5d-184242ec4dd4.webp',
|
|
||||||
href: slug('Артросульфур С'),
|
|
||||||
price: 535
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
},
|
},
|
||||||
"Common": {
|
"Common": {
|
||||||
"home": "Главная",
|
"home": "Главная",
|
||||||
"price": "Цена"
|
"price": "Цена",
|
||||||
|
"buy": "Купить"
|
||||||
},
|
},
|
||||||
"Error": {
|
"Error": {
|
||||||
"title": "Произошла ошибка",
|
"title": "Произошла ошибка",
|
||||||
@@ -33,7 +34,11 @@
|
|||||||
"favorites": "Избранное",
|
"favorites": "Избранное",
|
||||||
"empty": "Корзина пуста",
|
"empty": "Корзина пуста",
|
||||||
"continue": "Продолжить покупки",
|
"continue": "Продолжить покупки",
|
||||||
"checkout": "Оформить заказ"
|
"checkout": "Оформить заказ",
|
||||||
|
"title": "Название",
|
||||||
|
"quantity": "Количество",
|
||||||
|
"amount": "Стоимость",
|
||||||
|
"total": "Всего"
|
||||||
},
|
},
|
||||||
"cabinet": {
|
"cabinet": {
|
||||||
"personal-information": {
|
"personal-information": {
|
||||||
|
|||||||
247
package-lock.json
generated
247
package-lock.json
generated
@@ -16,7 +16,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.5",
|
"@radix-ui/react-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.1.1",
|
||||||
"@radix-ui/react-select": "^2.1.4",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.1",
|
"@radix-ui/react-separator": "^1.1.1",
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.1.1",
|
||||||
"@radix-ui/react-switch": "^1.1.2",
|
"@radix-ui/react-switch": "^1.1.2",
|
||||||
@@ -2239,32 +2239,253 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@radix-ui/react-select": {
|
"node_modules/@radix-ui/react-select": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz",
|
||||||
"integrity": "sha512-eVV7N8jBXAXnyrc+PsOF89O9AfVgGnbLxUtBb0clJ8y8ENMWLARGMI/1/SBRLz7u4HqxLgN71BJ17eono3wcjA==",
|
"integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/number": "1.1.0",
|
"@radix-ui/number": "1.1.0",
|
||||||
"@radix-ui/primitive": "1.1.1",
|
"@radix-ui/primitive": "1.1.1",
|
||||||
"@radix-ui/react-collection": "1.1.1",
|
"@radix-ui/react-collection": "1.1.2",
|
||||||
"@radix-ui/react-compose-refs": "1.1.1",
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
"@radix-ui/react-context": "1.1.1",
|
"@radix-ui/react-context": "1.1.1",
|
||||||
"@radix-ui/react-direction": "1.1.0",
|
"@radix-ui/react-direction": "1.1.0",
|
||||||
"@radix-ui/react-dismissable-layer": "1.1.4",
|
"@radix-ui/react-dismissable-layer": "1.1.5",
|
||||||
"@radix-ui/react-focus-guards": "1.1.1",
|
"@radix-ui/react-focus-guards": "1.1.1",
|
||||||
"@radix-ui/react-focus-scope": "1.1.1",
|
"@radix-ui/react-focus-scope": "1.1.2",
|
||||||
"@radix-ui/react-id": "1.1.0",
|
"@radix-ui/react-id": "1.1.0",
|
||||||
"@radix-ui/react-popper": "1.2.1",
|
"@radix-ui/react-popper": "1.2.2",
|
||||||
"@radix-ui/react-portal": "1.1.3",
|
"@radix-ui/react-portal": "1.1.4",
|
||||||
"@radix-ui/react-primitive": "2.0.1",
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
"@radix-ui/react-slot": "1.1.1",
|
"@radix-ui/react-slot": "1.1.2",
|
||||||
"@radix-ui/react-use-callback-ref": "1.1.0",
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
"@radix-ui/react-use-controllable-state": "1.1.0",
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
||||||
"@radix-ui/react-use-layout-effect": "1.1.0",
|
"@radix-ui/react-use-layout-effect": "1.1.0",
|
||||||
"@radix-ui/react-use-previous": "1.1.0",
|
"@radix-ui/react-use-previous": "1.1.0",
|
||||||
"@radix-ui/react-visually-hidden": "1.1.1",
|
"@radix-ui/react-visually-hidden": "1.1.2",
|
||||||
"aria-hidden": "^1.2.4",
|
"aria-hidden": "^1.2.4",
|
||||||
"react-remove-scroll": "^2.6.2"
|
"react-remove-scroll": "^2.6.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-arrow": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-primitive": "2.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-collection": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-context": "1.1.1",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-slot": "1.1.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-dismissable-layer": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/primitive": "1.1.1",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
|
"@radix-ui/react-use-escape-keydown": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-focus-scope": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-popper": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@floating-ui/react-dom": "^2.0.0",
|
||||||
|
"@radix-ui/react-arrow": "1.1.2",
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1",
|
||||||
|
"@radix-ui/react-context": "1.1.1",
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-use-callback-ref": "1.1.0",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0",
|
||||||
|
"@radix-ui/react-use-rect": "1.1.0",
|
||||||
|
"@radix-ui/react-use-size": "1.1.0",
|
||||||
|
"@radix-ui/rect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-primitive": "2.0.2",
|
||||||
|
"@radix-ui/react-use-layout-effect": "1.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-slot": "1.1.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-dom": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||||
|
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-primitive": "2.0.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@types/react": "*",
|
"@types/react": "*",
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.5",
|
"@radix-ui/react-dialog": "^1.1.5",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||||
"@radix-ui/react-label": "^2.1.1",
|
"@radix-ui/react-label": "^2.1.1",
|
||||||
"@radix-ui/react-select": "^2.1.4",
|
"@radix-ui/react-select": "^2.1.6",
|
||||||
"@radix-ui/react-separator": "^1.1.1",
|
"@radix-ui/react-separator": "^1.1.1",
|
||||||
"@radix-ui/react-slot": "^1.1.1",
|
"@radix-ui/react-slot": "^1.1.1",
|
||||||
"@radix-ui/react-switch": "^1.1.2",
|
"@radix-ui/react-switch": "^1.1.2",
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ const useCartStore = create(
|
|||||||
set({cartItems: [...get().cartItems]})
|
set({cartItems: [...get().cartItems]})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
decreaseQuantity: productId => {
|
decreaseQuantity: productId => {
|
||||||
const itemExists = get().cartItems.find(
|
const itemExists = get().cartItems.find(
|
||||||
cartItem => cartItem.id === productId
|
cartItem => cartItem.id === productId
|
||||||
|
|||||||
Reference in New Issue
Block a user