optional variant

This commit is contained in:
hamid zarghami
2025-10-27 12:36:00 +03:30
parent 8ed031229c
commit a68323d3ee
3 changed files with 117 additions and 41 deletions
@@ -2,6 +2,7 @@ import Button from '@/components/Button'
import DefaulModal from '@/components/DefaulModal'
import Input from '@/components/Input'
import Select from '@/components/Select'
import DatePickerComponent from '@/components/DatePicker'
import { useState, type FC } from 'react'
import { useParams } from 'react-router-dom'
import { useCreateProductVariant, useGetProductById, useGetProductVariants } from '../hooks/useProductData'
@@ -44,28 +45,34 @@ const CreateVariant: FC = () => {
: Yup.string().required('انتخاب تنوع الزامی است'),
warrantyId: Yup.string().required('انتخاب گارانتی الزامی است'),
order_limit: Yup.number().required('محدودیت سفارش الزامی است').min(1, 'حداقل ۱ عدد'),
sellerSpecialCode: Yup.string().required('کد ویژه فروشنده الزامی است'),
sellerSpecialCode: Yup.string(),
retail_price: Yup.number().required('قیمت فروش الزامی است').min(0, 'قیمت نمی‌تواند منفی باشد'),
package_weight: Yup.number().required('وزن بسته الزامی است').min(0.1, 'وزن باید حداقل ۰.۱ کیلوگرم باشد'),
package_height: Yup.number().required('ارتفاع بسته الزامی است').min(1, 'ارتفاع باید حداقل ۱ سانتی‌متر باشد'),
package_length: Yup.number().required('طول بسته الزامی است').min(1, 'طول باید حداقل ۱ سانتی‌متر باشد'),
package_width: Yup.number().required('عرض بسته الزامی است').min(1, 'عرض باید حداقل ۱ سانتی‌متر باشد'),
postingTime: Yup.number().required('زمان ارسال الزامی است').min(1, 'زمان ارسال باید حداقل ۱ روز باشد'),
stock: Yup.number().required('موجودی انبار الزامی است').min(0, 'موجودی نمی‌تواند منفی باشد')
stock: Yup.number().required('موجودی انبار الزامی است').min(0, 'موجودی نمی‌تواند منفی باشد'),
specialSale_order_limit: Yup.number().min(0, 'محدودیت فروش ویژه نمی‌تواند منفی باشد'),
specialSale_quantity: Yup.number().min(0, 'تعداد فروش ویژه نمی‌تواند منفی باشد'),
specialSale_endDate: Yup.string()
})
const initialValues = {
variantId: '',
warrantyId: '',
order_limit: '',
sellerSpecialCode: '',
sellerSpecialCode: '' as string | undefined,
retail_price: '',
package_weight: '',
package_height: '',
package_length: '',
package_width: '',
postingTime: '',
stock: ''
stock: '',
specialSale_order_limit: '',
specialSale_quantity: '',
specialSale_endDate: ''
}
const getVariantOptions = () => {
@@ -138,6 +145,15 @@ const CreateVariant: FC = () => {
variantData = baseData
}
if (!values.sellerSpecialCode) {
variantData.sellerSpecialCode = undefined
}
// اضافه کردن فیلدهای فروش ویژه - اگر خالی بودند undefined ارسال شوند
variantData.specialSale_order_limit = values.specialSale_order_limit ? parseInt(values.specialSale_order_limit) : undefined
variantData.specialSale_quantity = values.specialSale_quantity ? parseInt(values.specialSale_quantity) : undefined
variantData.specialSale_endDate = values.specialSale_endDate || undefined
createProductVariant.mutate(variantData, {
onSuccess: () => {
setShowModal(false)
@@ -390,6 +406,54 @@ const CreateVariant: FC = () => {
</div>
</div>
{/* اطلاعات فروش ویژه */}
<div className="border-t pt-4">
<h3 className="text-lg font-medium mb-4">فروش ویژه (اختیاری)</h3>
<div className="grid grid-cols-2 gap-4">
<div>
<Field name="specialSale_order_limit">
{({ field }: FormikFieldProps) => (
<Input
{...field}
label="محدودیت سفارش فروش ویژه"
placeholder="مثال: 5"
type="number"
value={field.value}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFieldValue('specialSale_order_limit', e.target.value)}
/>
)}
</Field>
<ErrorMessage name="specialSale_order_limit" component="div" className="text-red-500 text-sm mt-1" />
</div>
<div>
<Field name="specialSale_quantity">
{({ field }: FormikFieldProps) => (
<Input
{...field}
label="تعداد فروش ویژه"
placeholder="مثال: 100"
type="number"
value={field.value}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFieldValue('specialSale_quantity', e.target.value)}
/>
)}
</Field>
<ErrorMessage name="specialSale_quantity" component="div" className="text-red-500 text-sm mt-1" />
</div>
</div>
<div className="mt-4">
<DatePickerComponent
label="تاریخ پایان فروش ویژه"
placeholder="انتخاب تاریخ"
defaulValue={initialValues.specialSale_endDate}
onChange={(date: string) => setFieldValue('specialSale_endDate', date)}
/>
<ErrorMessage name="specialSale_endDate" component="div" className="text-red-500 text-sm mt-1" />
</div>
</div>
{/* دکمه‌ها */}
<div className="flex gap-3 pt-4 border-t">
<Button
+42 -33
View File
@@ -40,13 +40,18 @@ const UpdateVariant: FC<UpdateVariantProps> = ({ variant, onUpdate }) => {
const validationSchema = Yup.object().shape({
retailPrice: Yup.number().required('قیمت فروش الزامی است').min(0, 'قیمت نمی‌تواند منفی باشد'),
order_limit: Yup.number().required('محدودیت سفارش الزامی است').min(1, 'حداقل ۱ عدد'),
sellerSpecialCode: Yup.string().required('کد ویژه فروشنده الزامی است'),
sellerSpecialCode: Yup.string(),
stock: Yup.number().required('موجودی انبار الزامی است').min(0, 'موجودی نمی‌تواند منفی باشد'),
discount_type: Yup.string().oneOf(['fixed', 'percent'], 'نوع تخفیف باید fixed یا percent باشد').required('نوع تخفیف الزامی است'),
discount_value: Yup.number().when('discount_type', {
is: 'fixed',
then: (schema) => schema.min(0, 'مقدار تخفیف نمی‌تواند منفی باشد'),
otherwise: (schema) => schema.min(0, 'تخفیف نمی‌تواند منفی باشد').max(100, 'تخفیف نمی‌تواند بیش از ۱۰۰٪ باشد')
discount_type: Yup.string().oneOf(['fixed', 'percent'], 'نوع تخفیف باید fixed یا percent باشد'),
discount_value: Yup.lazy((_, context) => {
const discountType = context.parent.discount_type
if (discountType === 'fixed') {
return Yup.number().min(0, 'مقدار تخفیف نمی‌تواند منفی باشد')
} else if (discountType === 'percent') {
return Yup.number().min(0, 'تخفیف نمی‌تواند منفی باشد').max(100, 'تخفیف نمی‌تواند بیش از ۱۰۰٪ باشد')
} else {
return Yup.mixed().optional()
}
}),
specialSale_order_limit: Yup.number().min(0, 'محدودیت فروش ویژه نمی‌تواند منفی باشد'),
specialSale_quantity: Yup.number().min(0, 'تعداد فروش ویژه نمی‌تواند منفی باشد'),
@@ -58,8 +63,8 @@ const UpdateVariant: FC<UpdateVariantProps> = ({ variant, onUpdate }) => {
order_limit: variantData?.results?.productVariant?.price?.order_limit?.toString() || '',
sellerSpecialCode: variantData?.results?.productVariant?.sellerSpecialCode,
stock: variantData?.results?.productVariant?.stock?.toString() || '',
discount_type: 'percent',
discount_value: variantData?.results?.productVariant?.price?.discount_percent?.toString() || '0',
discount_type: '',
discount_value: variantData?.results?.productVariant?.price?.discount_percent?.toString() || '',
specialSale_order_limit: variantData?.results?.productVariant?.price?.specialSale_order_limit?.toString() || '',
specialSale_quantity: variantData?.results?.productVariant?.price?.specialSale_quantity?.toString() || '',
specialSale_endDate: variantData?.results?.productVariant?.price?.specialSale_endDate || ''
@@ -76,15 +81,17 @@ const UpdateVariant: FC<UpdateVariantProps> = ({ variant, onUpdate }) => {
sellerSpecialCode: values.sellerSpecialCode!,
stock: parseInt(values.stock as string),
saleFormat: { wholeSale: [] }, // فعلاً خالی می‌گذاریم
discount_type: values.discount_type as "fixed" | "percent",
...(values.discount_type === 'fixed' ? {
discount_value: discountValue
} : {
discount_percent: discountValue
}),
specialSale_order_limit: parseInt(values.specialSale_order_limit as string) || 0,
specialSale_quantity: parseInt(values.specialSale_quantity as string) || 0,
specialSale_endDate: values.specialSale_endDate || ''
...(values.discount_type ? {
discount_type: values.discount_type as "fixed" | "percent",
...(values.discount_type === 'fixed' ? {
discount_value: discountValue
} : {
discount_percent: discountValue
})
} : {}),
specialSale_order_limit: values.specialSale_order_limit ? parseInt(values.specialSale_order_limit as string) : undefined,
specialSale_quantity: values.specialSale_quantity ? parseInt(values.specialSale_quantity as string) : undefined,
specialSale_endDate: values.specialSale_endDate || undefined
} as UpdateVariantRequestType
updateVariant.mutate(baseData, {
@@ -141,7 +148,7 @@ const UpdateVariant: FC<UpdateVariantProps> = ({ variant, onUpdate }) => {
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{({ setFieldValue }) => (
{({ setFieldValue, values }) => (
<Form className="space-y-4 w-[500px] mt-4">
{/* اطلاعات قیمت و موجودی */}
<div className="grid grid-cols-2 gap-4">
@@ -227,21 +234,23 @@ const UpdateVariant: FC<UpdateVariantProps> = ({ variant, onUpdate }) => {
</div>
</div>
<div>
<Field name="discount_value">
{({ field, form }: FormikFieldProps) => (
<Input
{...field}
label={form.values.discount_type === 'percent' ? 'درصد تخفیف (%)' : 'مقدار تخفیف (تومان)'}
placeholder={form.values.discount_type === 'percent' ? 'مثال: 10' : 'مثال: 50000'}
type="number"
value={field.value}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFieldValue('discount_value', e.target.value)}
/>
)}
</Field>
<ErrorMessage name="discount_value" component="div" className="text-red-500 text-sm mt-1" />
</div>
{values.discount_type && (
<div>
<Field name="discount_value">
{({ field, form }: FormikFieldProps) => (
<Input
{...field}
label={form.values.discount_type === 'percent' ? 'درصد تخفیف (%)' : 'مقدار تخفیف (تومان)'}
placeholder={form.values.discount_type === 'percent' ? 'مثال: 10' : 'مثال: 50000'}
type="number"
value={field.value}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setFieldValue('discount_value', e.target.value)}
/>
)}
</Field>
<ErrorMessage name="discount_value" component="div" className="text-red-500 text-sm mt-1" />
</div>
)}
{/* اطلاعات فروش ویژه */}
<div className="border-t pt-4">
+7 -4
View File
@@ -270,7 +270,7 @@ export type CreateProductVariantRequestType = {
meterageId?: number;
warrantyId: number;
order_limit: number;
sellerSpecialCode: string;
sellerSpecialCode?: string;
retail_price: number;
package_weight: number;
package_height: number;
@@ -278,6 +278,9 @@ export type CreateProductVariantRequestType = {
package_width: number;
postingTime: number;
stock: number;
specialSale_order_limit?: number;
specialSale_quantity?: number;
specialSale_endDate?: string;
};
export type CreateProductVariantResponseType = {
@@ -389,9 +392,9 @@ export type UpdateVariantRequestType = {
discount_type: "fixed" | "percent";
discount_value?: number;
discount_percent?: number;
specialSale_order_limit: number;
specialSale_quantity: number;
specialSale_endDate: string;
specialSale_order_limit?: number;
specialSale_quantity?: number;
specialSale_endDate?: string;
};
export type UpdateVariantResponseType = {