add stock

This commit is contained in:
hamid zarghami
2026-02-14 16:18:13 +03:30
parent 1c735fcebb
commit a9c8b89829
4 changed files with 61 additions and 8 deletions
+4 -2
View File
@@ -40,7 +40,9 @@ const CreateProduct: FC = () => {
images: [], images: [],
discount: 0, discount: 0,
isSpecialOffer: false, isSpecialOffer: false,
order: 0 order: 0,
stock: undefined,
maxPurchaseQuantity: undefined
}, },
validationSchema: Yup.object().shape({ validationSchema: Yup.object().shape({
title: Yup.string().required('نام کالا الزامی است'), title: Yup.string().required('نام کالا الزامی است'),
@@ -61,7 +63,7 @@ const CreateProduct: FC = () => {
const variants = const variants =
values.variants.length > 0 values.variants.length > 0
? values.variants ? values.variants
: [{ value: '', price: values.price }] : [{ value: '', price: values.price, ...(values.stock !== undefined && values.stock !== null && { stock: values.stock }) }]
const productData: CreateProductType = { const productData: CreateProductType = {
...values, ...values,
variants, variants,
+9 -4
View File
@@ -46,7 +46,9 @@ const UpdateProduct: FC = () => {
images: [], images: [],
discount: 0, discount: 0,
isSpecialOffer: false, isSpecialOffer: false,
order: 0 order: 0,
stock: undefined,
maxPurchaseQuantity: undefined
}, },
validationSchema: Yup.object().shape({ validationSchema: Yup.object().shape({
title: Yup.string().required('نام کالا الزامی است'), title: Yup.string().required('نام کالا الزامی است'),
@@ -75,9 +77,10 @@ const UpdateProduct: FC = () => {
? values.variants.map((v) => ({ ? values.variants.map((v) => ({
...(v.id && { id: v.id }), ...(v.id && { id: v.id }),
value: v.value ?? '', value: v.value ?? '',
price: v.price ?? 0 price: v.price ?? 0,
...(v.stock !== undefined && v.stock !== null && { stock: v.stock })
})) }))
: [{ value: '', price: values.price }] : [{ value: '', price: values.price, ...(values.stock !== undefined && values.stock !== null && { stock: values.stock }) }]
const productData: CreateProductType = { const productData: CreateProductType = {
...values, ...values,
variants, variants,
@@ -130,7 +133,9 @@ const UpdateProduct: FC = () => {
images: product.images || [], images: product.images || [],
discount: product.discount || 0, discount: product.discount || 0,
isSpecialOffer: product.isSpecialOffer || false, isSpecialOffer: product.isSpecialOffer || false,
order: product.order ?? 0 order: product.order ?? 0,
stock: product.variants?.[0]?.stock,
maxPurchaseQuantity: product.maxPurchaseQuantity
}) })
setIsActive(product.isActive || false) setIsActive(product.isActive || false)
setIsSpecial(product.isSpecialOffer || false) setIsSpecial(product.isSpecialOffer || false)
@@ -41,7 +41,7 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
formik.setFieldValue('variants', [...formik.values.variants, newVariant()]) formik.setFieldValue('variants', [...formik.values.variants, newVariant()])
} }
const updateVariant = (index: number, field: keyof ProductVariant, value: string | number) => { const updateVariant = (index: number, field: keyof ProductVariant, value: string | number | undefined) => {
const next = [...formik.values.variants] const next = [...formik.values.variants]
next[index] = { ...next[index], [field]: value } next[index] = { ...next[index], [field]: value }
formik.setFieldValue('variants', next) formik.setFieldValue('variants', next)
@@ -80,6 +80,22 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
/> />
</div> </div>
<div className='mt-5'>
<Input
name='maxPurchaseQuantity'
label='حداکثر تعداد خرید'
placeholder='خالی = بی‌نهایت'
type='number'
min={0}
value={formik.values.maxPurchaseQuantity === undefined || formik.values.maxPurchaseQuantity === null ? '' : formik.values.maxPurchaseQuantity}
onChange={(e) => {
const v = e.target.value
formik.setFieldValue('maxPurchaseQuantity', v === '' ? undefined : Number(v))
}}
error_text={formik.touched.maxPurchaseQuantity && formik.errors.maxPurchaseQuantity ? formik.errors.maxPurchaseQuantity : ''}
/>
</div>
{/* بخش قیمت‌گذاری و تنوع */} {/* بخش قیمت‌گذاری و تنوع */}
<div className='mt-6 p-5 sm:p-6 rounded-2xl border border-gray-200/80 bg-gray-50/50'> <div className='mt-6 p-5 sm:p-6 rounded-2xl border border-gray-200/80 bg-gray-50/50'>
<div className='text-sm font-medium text-gray-800 mb-1'>قیمتگذاری و تنوع</div> <div className='text-sm font-medium text-gray-800 mb-1'>قیمتگذاری و تنوع</div>
@@ -109,6 +125,19 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
onChange={(e) => formik.setFieldValue('price', Number(e.target.value))} onChange={(e) => formik.setFieldValue('price', Number(e.target.value))}
error_text={formik.touched.price && formik.errors.price ? formik.errors.price : ''} error_text={formik.touched.price && formik.errors.price ? formik.errors.price : ''}
/> />
<Input
name='stock'
label='موجودی'
placeholder='خالی = بی‌نهایت'
type='number'
min={0}
value={formik.values.stock === undefined || formik.values.stock === null ? '' : formik.values.stock}
onChange={(e) => {
const v = e.target.value
formik.setFieldValue('stock', v === '' ? undefined : Number(v))
}}
error_text={formik.touched.stock && formik.errors.stock ? formik.errors.stock : ''}
/>
<Input <Input
name='discount' name='discount'
label='تخفیف (تومان)' label='تخفیف (تومان)'
@@ -163,7 +192,7 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
</div> </div>
<div> <div>
<label className='block text-sm font-medium text-gray-700 mb-2'>تنوعها و قیمت هر کدام</label> <label className='block text-sm font-medium text-gray-700 mb-2'>تنوعها، قیمت و موجودی هر کدام</label>
<div className='space-y-3'> <div className='space-y-3'>
{formik.values.variants.map((v, index) => ( {formik.values.variants.map((v, index) => (
<div <div
@@ -184,6 +213,17 @@ const BasicInfoSection: FC<BasicInfoSectionProps> = ({ formik, categories, initi
onChange={(e) => updateVariant(index, 'price', Number(e.target.value))} onChange={(e) => updateVariant(index, 'price', Number(e.target.value))}
className='flex-1 min-w-0 shrink-0' className='flex-1 min-w-0 shrink-0'
/> />
<Input
placeholder='موجودی (خالی=بی‌نهایت)'
type='number'
min={0}
value={v.stock === undefined || v.stock === null ? '' : v.stock}
onChange={(e) => {
const val = e.target.value
updateVariant(index, 'stock', val === '' ? undefined : Number(val))
}}
className='flex-1 min-w-0 shrink-0'
/>
<div className='min-w-5'> <div className='min-w-5'>
<Trash <Trash
onClick={() => removeVariant(index)} onClick={() => removeVariant(index)}
+6
View File
@@ -4,6 +4,7 @@ export type ProductVariant = {
id?: string; id?: string;
value: string; value: string;
price: number; price: number;
stock?: number;
}; };
export type CreateProductType = { export type CreateProductType = {
@@ -18,6 +19,9 @@ export type CreateProductType = {
discount: number; discount: number;
isSpecialOffer: boolean; isSpecialOffer: boolean;
order: number; order: number;
/** فقط در حالت بدون تنوع استفاده می‌شود */
stock?: number;
maxPurchaseQuantity?: number;
}; };
export type Category = { export type Category = {
@@ -119,6 +123,7 @@ export type Product = {
score?: number; score?: number;
discount: number; discount: number;
isSpecialOffer: boolean; isSpecialOffer: boolean;
maxPurchaseQuantity?: number;
}; };
export type GetProductsParams = { export type GetProductsParams = {
@@ -150,6 +155,7 @@ export type ProductDetails = {
score?: number | null; score?: number | null;
discount: number; discount: number;
isSpecialOffer: boolean; isSpecialOffer: boolean;
maxPurchaseQuantity?: number;
}; };
export type PaginationMeta = { export type PaginationMeta = {