Compare commits
6 Commits
8852f62580
...
79c72517c2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79c72517c2 | ||
|
|
c4e3fcda20 | ||
|
|
0f20ad8ad2 | ||
| dc3b8f4488 | |||
| 0f50d6bed1 | |||
| 44e1f915f4 |
@ -155,25 +155,25 @@ export default function Products() {
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
artNo: '',
|
||||
buyPrice: '' as number | string,
|
||||
priceValue: '' as number | string,
|
||||
wholesalePrice: '' as number | string,
|
||||
priceValueMarginPercent: '' as number | string,
|
||||
wholesaleMarginPercent: '' as number | string,
|
||||
priceDisplay: '',
|
||||
unit: '',
|
||||
packageSize: '' as number | string,
|
||||
dosageLogic: '',
|
||||
suitableFor: 'سگ و گربه',
|
||||
imageUrl: '',
|
||||
metaTitle: '',
|
||||
metaDescription: '',
|
||||
nameFa: '',
|
||||
nameEn: '',
|
||||
scientificTagline: '',
|
||||
description: '',
|
||||
shortDescription: '',
|
||||
categoryId: '',
|
||||
buyPrice: '' as number | string,
|
||||
priceValue: 0,
|
||||
wholesalePrice: '' as number | string,
|
||||
priceValueMarginPercent: '' as number | string,
|
||||
wholesaleMarginPercent: '' as number | string,
|
||||
priceDisplay: '',
|
||||
unit: '',
|
||||
packageSize: 0,
|
||||
dosageLogic: '',
|
||||
suitableFor: 'سگ و گربه',
|
||||
imageUrl: '',
|
||||
metaTitle: '',
|
||||
metaDescription: '',
|
||||
keywords: '',
|
||||
canonicalUrl: '',
|
||||
slug: '',
|
||||
@ -195,17 +195,24 @@ export default function Products() {
|
||||
preorderDeposit: '' as number | string
|
||||
});
|
||||
|
||||
const openModal = (product: Product | null = null) => {
|
||||
const openModal = (product?: Product) => {
|
||||
setMediaImageError(false);
|
||||
if (product) {
|
||||
setEditingProduct(product);
|
||||
updateUrlParams({ modal: 'edit', productId: product.id, tab: activeTab || 'general' });
|
||||
const bPrice = product.buyPrice ? Number(product.buyPrice) : '';
|
||||
const pPrice = Number(product.priceValue || 0);
|
||||
const wPrice = product.wholesalePrice ? Number(product.wholesalePrice) : '';
|
||||
|
||||
const pMargin = bPrice && pPrice ? Math.round(((pPrice - Number(bPrice)) / Number(bPrice)) * 100) : '';
|
||||
const wMargin = bPrice && wPrice ? Math.round(((wPrice - Number(bPrice)) / Number(bPrice)) * 100) : '';
|
||||
const bPrice = product.buyPrice ? Number(product.buyPrice) : '';
|
||||
const pPrice = product.priceValue !== undefined && product.priceValue !== null ? Number(product.priceValue) : '';
|
||||
const wPrice = product.wholesalePrice !== undefined && product.wholesalePrice !== null ? Number(product.wholesalePrice) : '';
|
||||
|
||||
let pMargin: number | string = '';
|
||||
let wMargin: number | string = '';
|
||||
if (bPrice && pPrice !== '') {
|
||||
pMargin = Math.round(((Number(pPrice) - Number(bPrice)) / Number(bPrice)) * 100);
|
||||
}
|
||||
if (bPrice && wPrice !== '') {
|
||||
wMargin = Math.round(((Number(wPrice) - Number(bPrice)) / Number(bPrice)) * 100);
|
||||
}
|
||||
|
||||
setFormData({
|
||||
artNo: product.artNo || '',
|
||||
@ -214,7 +221,7 @@ export default function Products() {
|
||||
scientificTagline: product.scientificTagline || '',
|
||||
description: product.description || '',
|
||||
shortDescription: product.shortDescription || '',
|
||||
categoryId: product.categoryId || '',
|
||||
categoryId: typeof product.category === 'object' && product.category !== null ? product.category.id : (product.categoryId || ''),
|
||||
buyPrice: bPrice,
|
||||
priceValue: pPrice,
|
||||
wholesalePrice: wPrice,
|
||||
@ -222,7 +229,7 @@ export default function Products() {
|
||||
wholesaleMarginPercent: wMargin,
|
||||
priceDisplay: product.priceDisplay || '',
|
||||
unit: product.unit || '',
|
||||
packageSize: Number(product.packageSize) || 0,
|
||||
packageSize: product.packageSize !== undefined && product.packageSize !== null ? Number(product.packageSize) : '',
|
||||
dosageLogic: product.dosageLogic || '',
|
||||
suitableFor: product.suitableFor || 'سگ و گربه',
|
||||
imageUrl: product.imageUrl || '',
|
||||
@ -246,15 +253,15 @@ export default function Products() {
|
||||
pdfCover: product.pdfCover || '',
|
||||
symptoms: product.symptoms ? product.symptoms.map((s: { symptom: string } | string) => typeof s === 'string' ? s : s.symptom) : [],
|
||||
isPreorder: Boolean(product.isPreorder),
|
||||
preorderDeposit: product.preorderDeposit || ''
|
||||
preorderDeposit: product.preorderDeposit !== undefined && product.preorderDeposit !== null ? product.preorderDeposit : ''
|
||||
});
|
||||
} else {
|
||||
setEditingProduct(null);
|
||||
updateUrlParams({ modal: 'create', productId: undefined, tab: activeTab || 'general' });
|
||||
setFormData({
|
||||
artNo: '', nameFa: '', nameEn: '', scientificTagline: '', description: '', shortDescription: '', categoryId: '',
|
||||
buyPrice: '', priceValue: 0, wholesalePrice: '', priceValueMarginPercent: '', wholesaleMarginPercent: '',
|
||||
priceDisplay: '', unit: '', packageSize: 0, dosageLogic: '', suitableFor: 'سگ و گربه',
|
||||
buyPrice: '', priceValue: '', wholesalePrice: '', priceValueMarginPercent: '', wholesaleMarginPercent: '',
|
||||
priceDisplay: '', unit: '', packageSize: '', dosageLogic: '', suitableFor: 'سگ و گربه',
|
||||
imageUrl: '', metaTitle: '', metaDescription: '', keywords: '', canonicalUrl: '', slug: '',
|
||||
images: [],
|
||||
podcastUrl: '', podcastTitle: '', podcastDescription: '', podcastCover: '',
|
||||
@ -1111,7 +1118,16 @@ export default function Products() {
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 pt-2">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold text-gray-700">موجودی *</label>
|
||||
<input required type="number" min="0" value={formData.packageSize} onChange={(e) => setFormData({ ...formData, packageSize: Number(e.target.value) })} className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none" dir="ltr" />
|
||||
<input
|
||||
required
|
||||
type="number"
|
||||
min="0"
|
||||
placeholder="0"
|
||||
value={formData.packageSize === '' ? '' : formData.packageSize}
|
||||
onChange={(e) => setFormData({ ...formData, packageSize: e.target.value === '' ? '' : Number(e.target.value) })}
|
||||
className="w-full px-4 py-3 rounded-xl border border-gray-200 focus:border-purple-500 outline-none text-left font-mono font-bold"
|
||||
dir="ltr"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold text-gray-700">واحد سنجش</label>
|
||||
|
||||
@ -178,7 +178,18 @@ export default function ZibalPortalPage() {
|
||||
try {
|
||||
setLoadingQueue(true);
|
||||
const res = await api.get('/payment/admin/checkout-queue');
|
||||
const items = Array.isArray(res.data) ? res.data : (res.data?.data || []);
|
||||
let items: any[] = [];
|
||||
if (Array.isArray(res.data)) {
|
||||
items = res.data;
|
||||
} else if (res.data?.data && Array.isArray(res.data.data)) {
|
||||
items = res.data.data;
|
||||
} else if (res.data?.queue && Array.isArray(res.data.queue)) {
|
||||
items = res.data.queue;
|
||||
} else if (res.data?.checkouts && Array.isArray(res.data.checkouts)) {
|
||||
items = res.data.checkouts;
|
||||
} else if (res.data?.checkoutList && Array.isArray(res.data.checkoutList)) {
|
||||
items = res.data.checkoutList;
|
||||
}
|
||||
setQueueItems(items);
|
||||
} catch (e: any) {
|
||||
toast.error('خطا در دریافت صف تسویههای در انتظار');
|
||||
|
||||
@ -170,7 +170,11 @@ const ArchiveProductCard: React.FC<{ product: Product }> = ({ product }) => {
|
||||
) : (
|
||||
<span className="text-xs font-bold text-amber-600 bg-amber-50 px-2 py-1 rounded-md">تماس جهت استعلام قیمت</span>
|
||||
)}
|
||||
{!useSettingsStore.getState().getText("catalog_disable_cart", "false").includes("true") && (() => {
|
||||
{(product.packageSize !== undefined && product.packageSize !== null ? Number(product.packageSize) : 100) <= 0 ? (
|
||||
<span className="px-2.5 py-1.5 rounded-xl bg-rose-50 text-rose-600 border border-rose-100 text-[11px] font-bold font-vazir">
|
||||
ناموجود
|
||||
</span>
|
||||
) : !useSettingsStore.getState().getText("catalog_disable_cart", "false").includes("true") && (() => {
|
||||
const cartItem = useCartStore.getState().items.find(i => i.product.id === product.id);
|
||||
if (cartItem && cartItem.quantity > 0) {
|
||||
return (
|
||||
|
||||
@ -85,7 +85,7 @@ function ProductCard({ product }: { product: Product }) {
|
||||
>
|
||||
<Eye className="w-5 h-5" />
|
||||
</div>
|
||||
{allowCart && (
|
||||
{allowCart && (product.packageSize !== undefined && product.packageSize !== null ? Number(product.packageSize) : 100) > 0 && (
|
||||
<div
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
@ -143,7 +143,7 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
|
||||
return {
|
||||
...apiProduct,
|
||||
packageSize: apiProduct.packageSize || 100,
|
||||
packageSize: apiProduct.packageSize !== undefined && apiProduct.packageSize !== null ? Number(apiProduct.packageSize) : 100,
|
||||
};
|
||||
}, [product, allProducts]);
|
||||
|
||||
@ -185,8 +185,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
dailyDose = Math.max(1, Math.round(weight * factor));
|
||||
}
|
||||
|
||||
const packageSize = fullProduct.packageSize || 100;
|
||||
const duration = Math.max(1, Math.floor(packageSize / (dailyDose || 1)));
|
||||
const packageSize = fullProduct.packageSize !== undefined && fullProduct.packageSize !== null ? Number(fullProduct.packageSize) : 100;
|
||||
const duration = Math.max(1, Math.floor((packageSize || 100) / (dailyDose || 1)));
|
||||
|
||||
return {
|
||||
dailyDose,
|
||||
@ -220,6 +220,8 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
);
|
||||
if (!product || !fullProduct || !calculation) return <div className="min-h-screen flex items-center justify-center">محصول یافت نشد</div>;
|
||||
|
||||
const isOutOfStock = (product.packageSize !== undefined && product.packageSize !== null ? Number(product.packageSize) : 100) <= 0;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-medical-gray-50 pt-2 pb-36 sm:pb-20 px-4 sm:px-6 lg:px-8 font-vazir" dir="rtl">
|
||||
<div className="max-w-7xl mx-auto w-full">
|
||||
@ -274,10 +276,16 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
title="کلیک برای مشاهده تصویر بزرگتر"
|
||||
>
|
||||
<div className="absolute top-4 left-4 sm:top-6 sm:left-6 flex flex-col gap-1.5 sm:gap-2 z-10 items-start">
|
||||
<div className="px-2.5 py-1 bg-green-500 text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
||||
<CheckCircle2 className="w-3 h-3" />
|
||||
موجود در انبار
|
||||
</div>
|
||||
{isOutOfStock ? (
|
||||
<div className="px-2.5 py-1 bg-rose-500 text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
||||
ناموجود در انبار
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-2.5 py-1 bg-green-500 text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest flex items-center gap-1 font-vazir shadow-sm">
|
||||
<CheckCircle2 className="w-3 h-3" />
|
||||
موجود در انبار
|
||||
</div>
|
||||
)}
|
||||
<div className="px-2.5 py-1 bg-canina-blue text-white rounded-full text-[9px] sm:text-[10px] font-black uppercase tracking-widest font-vazir whitespace-nowrap shadow-sm">
|
||||
گرید دارویی اختصاصی
|
||||
</div>
|
||||
@ -1060,6 +1068,14 @@ export default function ProductPage({ productSlug }: { productSlug: string }) {
|
||||
<Phone className="w-4 h-4" />
|
||||
استعلام و مشاوره
|
||||
</a>
|
||||
) : isOutOfStock ? (
|
||||
<button
|
||||
onClick={() => toast.info("درخواست اطلاعرسانی موجودی ثبت شد")}
|
||||
className="flex-1 bg-amber-500 text-white py-2.5 px-3 rounded-xl font-black text-xs hover:bg-amber-600 transition-all flex items-center justify-center gap-1.5 shadow-md shadow-amber-500/20 whitespace-nowrap"
|
||||
>
|
||||
<Bell className="w-4 h-4" />
|
||||
موجود شد خبر بده
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex items-center gap-1 bg-medical-gray-50 border border-medical-gray-200 rounded-xl p-1 h-11">
|
||||
|
||||
@ -124,7 +124,7 @@ export class ProductService {
|
||||
category: categoryName || '',
|
||||
categorySlug: data.categorySlug || '',
|
||||
unit: data.unit || 'عدد',
|
||||
packageSize: Number(data.packageSize || 100),
|
||||
packageSize: data.packageSize !== undefined && data.packageSize !== null ? Number(data.packageSize) : 100,
|
||||
dosage_logic: data.dosageLogic || '',
|
||||
benefits: data.benefits || '',
|
||||
suitableFor: (data.suitableFor as PetType) || 'سگ',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user