Merge remote-tracking branch 'refs/remotes/origin/master'
deploy to danak / build_and_deploy (push) Has been cancelled
deploy to danak / build_and_deploy (push) Has been cancelled
This commit is contained in:
@@ -3,7 +3,6 @@ import React from 'react'
|
||||
import CategoryItem from './CategoryItem'
|
||||
import { useGetCategories } from '@/share/hooks/useShareData'
|
||||
import { Category } from '@/share/types/SharedTypes'
|
||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||
|
||||
const Categories = () => {
|
||||
|
||||
@@ -11,24 +10,14 @@ const Categories = () => {
|
||||
const parentCategories = data?.results?.data?.filter(cat => !cat.parent) || []
|
||||
|
||||
return (
|
||||
<div className='w-full flex justify-center'>
|
||||
<Swiper
|
||||
spaceBetween={16}
|
||||
slidesPerView={'auto'}
|
||||
centeredSlides={true}
|
||||
className='h-full'
|
||||
breakpoints={{
|
||||
640: {
|
||||
spaceBetween: 24,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div className='w-full overflow-x-auto overflow-y-hidden'>
|
||||
<div className='flex justify-center gap-4 sm:gap-6 md:gap-6 w-full min-w-max px-4 sm:px-8 md:px-20'>
|
||||
{parentCategories?.map((item: Category) => (
|
||||
<SwiperSlide key={item._id} className='!w-auto'>
|
||||
<div key={item._id} className='flex-shrink-0'>
|
||||
<CategoryItem image={item.imageUrl} title={item.title_fa} categoryUrl={item.title_en} />
|
||||
</SwiperSlide>
|
||||
</div>
|
||||
))}
|
||||
</Swiper>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
+7
-7
@@ -18,16 +18,16 @@ export const dynamic = 'force-dynamic'
|
||||
const HomePage: NextPage = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='w-full'>
|
||||
<Carousel />
|
||||
<div className='mt-12 sm:mt-16 md:mt-24 px-4 sm:px-8 md:px-20'>
|
||||
<HotOffer />
|
||||
<div className='mt-12 sm:mt-16 md:mt-24'>
|
||||
<Categories />
|
||||
</div>
|
||||
<div className='mt-12 sm:mt-16 md:mt-24'>
|
||||
<Banners3 />
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-12 sm:mt-16 md:mt-24 w-full'>
|
||||
<Categories />
|
||||
</div>
|
||||
<div className='mt-12 sm:mt-16 md:mt-24 px-4 sm:px-8 md:px-20'>
|
||||
<Banners3 />
|
||||
</div>
|
||||
|
||||
<div className='mt-12 sm:mt-16 md:mt-24 bg-[#FAF8F6] p-4 sm:p-8 md:p-20'>
|
||||
|
||||
@@ -4,16 +4,20 @@ import { useSharedStore } from '@/share/store/sharedStore'
|
||||
import OnlineCart from './OnlineCart'
|
||||
import OfflineCart from './OfflineCart'
|
||||
|
||||
const Cart = () => {
|
||||
interface CartProps {
|
||||
stock: number
|
||||
}
|
||||
|
||||
const Cart = ({ stock }: CartProps) => {
|
||||
const { variantId } = useProductStore()
|
||||
const { isLogin } = useSharedStore()
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isLogin ? (
|
||||
<OnlineCart variantId={variantId} />
|
||||
<OnlineCart variantId={variantId} stock={stock} />
|
||||
) : (
|
||||
<OfflineCart variantId={variantId} />
|
||||
<OfflineCart variantId={variantId} stock={stock} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -8,9 +8,10 @@ import { useLocalCart } from '../hooks/useLocalCart'
|
||||
|
||||
interface OfflineCartProps {
|
||||
variantId: string
|
||||
stock: number
|
||||
}
|
||||
|
||||
const OfflineCart: React.FC<OfflineCartProps> = ({ variantId }) => {
|
||||
const OfflineCart: React.FC<OfflineCartProps> = ({ variantId, stock }) => {
|
||||
const { id } = useParams()
|
||||
|
||||
// Local cart hooks for non-logged in users
|
||||
@@ -24,7 +25,11 @@ const OfflineCart: React.FC<OfflineCartProps> = ({ variantId }) => {
|
||||
const [isInCart, setIsInCart] = useState<boolean>(false)
|
||||
const [quantity, setQuantity] = useState<number>(1)
|
||||
|
||||
const isOutOfStock = stock <= 0
|
||||
|
||||
const handleAddToCart = () => {
|
||||
if (isOutOfStock) return
|
||||
|
||||
addToLocalCart(Number(id), variantId, 1)
|
||||
setIsInCart(true)
|
||||
setQuantity(1)
|
||||
@@ -48,8 +53,9 @@ const OfflineCart: React.FC<OfflineCartProps> = ({ variantId }) => {
|
||||
return
|
||||
}
|
||||
|
||||
setQuantity(number)
|
||||
updateLocalCartItem(Number(id), variantId, number)
|
||||
const clampedQuantity = Math.min(number, stock)
|
||||
setQuantity(clampedQuantity)
|
||||
updateLocalCartItem(Number(id), variantId, clampedQuantity)
|
||||
}
|
||||
|
||||
const handleEmptyCart = () => {
|
||||
@@ -59,21 +65,30 @@ const OfflineCart: React.FC<OfflineCartProps> = ({ variantId }) => {
|
||||
setQuantity(0)
|
||||
}
|
||||
|
||||
if (isOutOfStock) {
|
||||
return (
|
||||
<Button className="w-full mt-8" disabled>
|
||||
ناموجود
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
!isInCart ?
|
||||
<Button className='w-full mt-8' onClick={handleAddToCart}>
|
||||
<Button className="w-full mt-8" onClick={handleAddToCart}>
|
||||
افزودن به سبد خرید
|
||||
</Button>
|
||||
:
|
||||
<div className={"flex items-center gap-2 sm:gap-4 mt-8"}>
|
||||
<div className="flex items-center gap-2 sm:gap-4 mt-8">
|
||||
<div className="h-10 sm:h-12 rounded-lg sm:rounded-xl border border-border bg-white px-2 sm:px-4 flex-1 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleQuantityChange(quantity + 1)}
|
||||
className="p-1"
|
||||
className="disabled:opacity-40 disabled:cursor-not-allowed p-1"
|
||||
aria-label="increase quantity"
|
||||
disabled={quantity >= stock}
|
||||
>
|
||||
<Add size={18} color={PRIMARY_COLOR} className="sm:w-5 sm:h-5" />
|
||||
</button>
|
||||
|
||||
@@ -9,9 +9,10 @@ import { extractErrorMessage } from '@/helpers/errorUtils'
|
||||
|
||||
interface OnlineCartProps {
|
||||
variantId: string
|
||||
stock: number
|
||||
}
|
||||
|
||||
const OnlineCart: React.FC<OnlineCartProps> = ({ variantId }) => {
|
||||
const OnlineCart: React.FC<OnlineCartProps> = ({ variantId, stock }) => {
|
||||
const { id } = useParams()
|
||||
|
||||
// API hooks for logged in users
|
||||
@@ -23,7 +24,11 @@ const OnlineCart: React.FC<OnlineCartProps> = ({ variantId }) => {
|
||||
const [isInCart, setIsInCart] = useState<boolean>(false)
|
||||
const [quantity, setQuantity] = useState<number>(1)
|
||||
|
||||
const isOutOfStock = stock <= 0
|
||||
|
||||
const handleAddToCart = () => {
|
||||
if (isOutOfStock) return
|
||||
|
||||
addToCart({
|
||||
productId: Number(id),
|
||||
variantId: variantId,
|
||||
@@ -40,14 +45,8 @@ const OnlineCart: React.FC<OnlineCartProps> = ({ variantId }) => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Check API cart for logged in users
|
||||
console.log('cart', cart);
|
||||
console.log('variantId', variantId);
|
||||
|
||||
const item = cart?.results?.cart?.items?.find(item => item.variant?._id === variantId)
|
||||
|
||||
console.log('item', item);
|
||||
|
||||
if (item) {
|
||||
setIsInCart(true)
|
||||
setQuantity(item.quantity)
|
||||
@@ -62,13 +61,14 @@ const OnlineCart: React.FC<OnlineCartProps> = ({ variantId }) => {
|
||||
return
|
||||
}
|
||||
|
||||
const clampedQuantity = Math.min(number, stock)
|
||||
const oldQuantity = quantity
|
||||
setQuantity(number)
|
||||
setQuantity(clampedQuantity)
|
||||
|
||||
updateCart({
|
||||
productId: Number(id),
|
||||
variantId: variantId,
|
||||
quantity: number,
|
||||
quantity: clampedQuantity,
|
||||
}, {
|
||||
onError: (error: Error) => {
|
||||
toast(extractErrorMessage(error), 'error')
|
||||
@@ -93,22 +93,30 @@ const OnlineCart: React.FC<OnlineCartProps> = ({ variantId }) => {
|
||||
})
|
||||
}
|
||||
|
||||
if (isOutOfStock) {
|
||||
return (
|
||||
<Button className="w-full mt-8" disabled>
|
||||
ناموجود
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
!isInCart && !isPending ?
|
||||
<Button isLoading={isAddingToCart} className='w-full mt-8' onClick={handleAddToCart}>
|
||||
<Button isLoading={isAddingToCart} className="w-full mt-8" onClick={handleAddToCart}>
|
||||
افزودن به سبد خرید
|
||||
</Button>
|
||||
:
|
||||
<div className={"flex items-center gap-2 sm:gap-4 mt-8"}>
|
||||
<div className="flex items-center gap-2 sm:gap-4 mt-8">
|
||||
<div className="h-10 sm:h-12 rounded-lg sm:rounded-xl border border-border bg-white px-2 sm:px-4 flex-1 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleQuantityChange(quantity + 1)}
|
||||
className="disabled:opacity-40 disabled:cursor-not-allowed p-1"
|
||||
aria-label="increase quantity"
|
||||
disabled={isAddingToCart || isUpdatingCart}
|
||||
disabled={isAddingToCart || isUpdatingCart || quantity >= stock}
|
||||
>
|
||||
<Add size={18} color={PRIMARY_COLOR} className="sm:w-5 sm:h-5" />
|
||||
</button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { BoxTick, I3DRotate } from 'iconsax-react'
|
||||
import { I3DRotate } from 'iconsax-react'
|
||||
import React from 'react'
|
||||
import { Product } from '@/types/product.types'
|
||||
import Image from 'next/image'
|
||||
@@ -20,10 +20,10 @@ const ShopInformation = ({ product }: ShopInformationProps) => {
|
||||
? product.variants.find((variant) => variant._id === variantId) || product.default_variant
|
||||
: product.default_variant
|
||||
|
||||
const shop = selectedVariant.shop
|
||||
// const shop = selectedVariant.shop
|
||||
const price = selectedVariant.price
|
||||
const warranty = selectedVariant.warranty
|
||||
const postingTime = selectedVariant.postingTime
|
||||
// const postingTime = selectedVariant.postingTime
|
||||
|
||||
const formatPrice = (price: number) => {
|
||||
return price.toLocaleString('fa-IR')
|
||||
@@ -107,7 +107,7 @@ const ShopInformation = ({ product }: ShopInformationProps) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Cart />
|
||||
<Cart stock={selectedVariant.stock} />
|
||||
{/* <Button
|
||||
onClick={handleChatWithSeller}
|
||||
className='w-full mt-3 bg-[#323232] hover:bg-[#424242] flex items-center justify-center gap-2'
|
||||
|
||||
@@ -35,7 +35,7 @@ const SingleProduct = ({ id }: SingleProductProps) => {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const { product, categoryPath, reviews, stats } = productData.results
|
||||
const { product, categoryPath, stats } = productData.results
|
||||
|
||||
return (
|
||||
<div className='mt-14 px-4 sm:px-6 md:px-8 lg:px-12 xl:px-20'>
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
export const TOKEN_NAME = "sh_token";
|
||||
export const REFRESH_TOKEN_NAME = "sh_refresh_token";
|
||||
// export const BASE_URL = "https://shop-api.dev.danakcorp.com";
|
||||
export const BASE_URL = "http://localhost:4000";
|
||||
export const BASE_URL = "https://api.fajrtabloshop.com";
|
||||
// export const BASE_URL = "http://192.168.99.235:4000";
|
||||
|
||||
export const PRIMARY_COLOR = "#DA2129";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user