Merge remote-tracking branch 'refs/remotes/origin/master'
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-06-14 10:26:04 +03:30
8 changed files with 67 additions and 51 deletions
+5 -16
View File
@@ -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>
)
}
+4 -4
View File
@@ -18,17 +18,17 @@ 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'>
</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'>
<div className='mt-12 sm:mt-16 md:mt-24 px-4 sm:px-8 md:px-20'>
<Banners3 />
</div>
</div>
<div className='mt-12 sm:mt-16 md:mt-24 bg-[#FAF8F6] p-4 sm:p-8 md:p-20'>
<NewestProducts />
+7 -3
View File
@@ -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>
)
+21 -6
View File
@@ -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>
+20 -12
View File
@@ -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'
+1 -1
View File
@@ -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
View File
@@ -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";