feat(wholesale): implement Bulk Order Matrix with role-based wholesale pricing display [TASK-104]
This commit is contained in:
parent
9122035784
commit
3ab4541933
@ -46,7 +46,7 @@
|
||||
"title": "پیادهسازی پنل و جدول سفارش حجمی (Bulk Order Matrix) برای خریداران عمده تاییدشده",
|
||||
"priority": "HIGH",
|
||||
"assigned_role": "05_dev_frontend",
|
||||
"status": "pending",
|
||||
"status": "completed",
|
||||
"max_file_count": 3,
|
||||
"estimated_minutes": 15,
|
||||
"dependency_task_ids": ["TASK-103"],
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
"checkpoint": {
|
||||
"stage": "DEVELOPMENT",
|
||||
"active_agent": "05_dev_frontend",
|
||||
"current_ticket_id": "TASK-104",
|
||||
"sub_step_index": 4,
|
||||
"current_ticket_id": "TASK-105",
|
||||
"sub_step_index": 5,
|
||||
"total_sub_steps": 5
|
||||
},
|
||||
"execution_guards": {
|
||||
@ -16,11 +16,11 @@
|
||||
"token_usage_total": 0
|
||||
},
|
||||
"git_state": {
|
||||
"active_branch": "feature/TASK-103",
|
||||
"active_branch": "feature/TASK-104",
|
||||
"last_healthy_commit": "HEAD"
|
||||
},
|
||||
"context_buffer": {
|
||||
"last_agent_summary": "TASK-103 (Wholesale Buyer Verification & License Form) completed and verified."
|
||||
"last_agent_summary": "TASK-104 (Bulk Order Matrix and Wholesale Pricing Tiers) completed and verified."
|
||||
},
|
||||
"last_updated": "2026-07-26T14:35:00Z"
|
||||
"last_updated": "2026-07-26T14:36:00Z"
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Product } from "../lib/data/products";
|
||||
import { useCartStore } from "../lib/store/cartStore";
|
||||
import { useUserStore } from "../lib/store/userStore";
|
||||
import { productService } from "../lib/services/productService";
|
||||
import { motion, AnimatePresence } from "motion/react";
|
||||
import {
|
||||
@ -12,9 +13,12 @@ import {
|
||||
FileText,
|
||||
Package,
|
||||
CheckCircle2,
|
||||
Lock,
|
||||
Percent,
|
||||
X
|
||||
} from "lucide-react";
|
||||
import SafeImage from "./SafeImage";
|
||||
import { toPersian } from "../lib/utils";
|
||||
|
||||
interface QuickOrderItem {
|
||||
product: Product;
|
||||
@ -26,8 +30,11 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
||||
const [quantities, setQuantities] = useState<Record<string, number>>({});
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const { addItem } = useCartStore();
|
||||
const { role } = useUserStore();
|
||||
const [showSuccess, setShowSuccess] = useState(false);
|
||||
|
||||
const isWholesaleVerified = (role as string) === "User_Wholesale" || (role as string) === "ADMIN" || (role as string) === "User_Partner";
|
||||
|
||||
useEffect(() => {
|
||||
productService.getProducts({ limit: 999 }).then(res => setProducts(res.data));
|
||||
}, []);
|
||||
@ -57,6 +64,16 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
||||
};
|
||||
|
||||
const totalItems = Object.values(quantities).reduce((acc: number, val) => acc + (val as any), 0);
|
||||
const totalWholesalePrice = Object.entries(quantities).reduce((sum, [id, qty]) => {
|
||||
const numQty = qty as number;
|
||||
const prod = products.find(p => p.id === id);
|
||||
if (prod && numQty > 0) {
|
||||
const basePrice = prod.priceValue || 0;
|
||||
const wholesalePrice = basePrice * 0.7; // 30% discount for wholesale
|
||||
return sum + (wholesalePrice * numQty);
|
||||
}
|
||||
return sum;
|
||||
}, 0);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
@ -135,12 +152,16 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
||||
<tr>
|
||||
<th className="px-6 py-4 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">تصویر</th>
|
||||
<th className="px-6 py-4 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">نام و کد کالا</th>
|
||||
<th className="px-6 py-4 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">وضعیت موجودی</th>
|
||||
<th className="px-6 py-4 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">قیمت تکفروشی</th>
|
||||
<th className="px-6 py-4 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">قیمت عمده (همکار)</th>
|
||||
<th className="px-6 py-4 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest">تعداد سفارش</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-medical-gray-100">
|
||||
{filteredProducts.map(product => (
|
||||
{filteredProducts.map(product => {
|
||||
const basePrice = product.priceValue || 0;
|
||||
const wholesalePrice = basePrice * 0.7; // 30% discount
|
||||
return (
|
||||
<tr key={product.id} className="hover:bg-medical-gray-50/50 transition-colors">
|
||||
<td className="px-6 py-4">
|
||||
<SafeImage src={product.image} className="w-12 h-12" imgClassName="object-contain" alt={product.name} />
|
||||
@ -149,11 +170,21 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
||||
<div className="font-black text-medical-gray-900">{product.name}</div>
|
||||
<div className="text-[10px] font-vazir text-medical-gray-400 mt-1">شناسه کالا: {product.artNo}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-xs font-bold text-medical-gray-500">
|
||||
{toPersian(basePrice.toLocaleString())} تومان
|
||||
</td>
|
||||
<td className="px-6 py-4">
|
||||
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-green-50 text-green-600 rounded-full text-[10px] font-bold">
|
||||
<CheckCircle2 className="w-3 h-3" />
|
||||
آماده ارسال
|
||||
{isWholesaleVerified ? (
|
||||
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-amber-50 text-amber-700 rounded-full text-xs font-black">
|
||||
<Percent className="w-3 h-3 text-amber-600" />
|
||||
{toPersian(wholesalePrice.toLocaleString())} تومان
|
||||
</span>
|
||||
) : (
|
||||
<span className="inline-flex items-center gap-1.5 px-3 py-1 bg-gray-100 text-gray-500 rounded-full text-[10px] font-bold">
|
||||
<Lock className="w-3 h-3 text-gray-400" />
|
||||
نیازمند تایید ادمین
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-6 py-4">
|
||||
<input
|
||||
@ -166,7 +197,8 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user