feat(refill): map refill state in cartStore, clarify free loyalty 5% discount UX, and render Refill badges across full app and admin
This commit is contained in:
parent
24c361c4ff
commit
b5650c4cbb
@ -534,14 +534,71 @@
|
||||
"sub_steps": [
|
||||
{ "index": 1, "name": "build_admin_order_modal", "description": "Build AdminOrderModal with tracking editor, status changer, and invoice printer in Orders.tsx", "status": "done" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "EPIC-15-TASK-01",
|
||||
"title": "Refill & Payment Method State Mapping Persistence",
|
||||
"description": "Map isRefill and paymentMethod in cartStore.ts addOrder and setOrders so refill status is preserved across application and backend syncing.",
|
||||
"architectural_layer": "state_management",
|
||||
"assigned_role": "06_dev_frontend",
|
||||
"priority": "HIGH",
|
||||
"status": "completed",
|
||||
"max_files_allowed": 3,
|
||||
"estimated_minutes": 15,
|
||||
"dependency_task_ids": ["EPIC-14-TASK-02"],
|
||||
"acceptance_criteria": [
|
||||
"حفظ و نگهداری وضعیت isRefill در تمامی سفارشات دریافت شده از بکاند",
|
||||
"نمایش دقیق تخفیف تمدید ۵٪ در محاسبات سبد خرید"
|
||||
],
|
||||
"sub_steps": [
|
||||
{ "index": 1, "name": "map_refill_in_cart_store", "description": "Map isRefill and paymentMethod in cartStore addOrder and setOrders", "status": "done" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "EPIC-15-TASK-02",
|
||||
"title": "Refill UX & Loyalty Program Clarification",
|
||||
"description": "Improve description and tooltip for Refill subscription in CheckoutPage.tsx explaining that Refill is a free loyalty subscription program providing automated re-orders and 5% lifetime discounts.",
|
||||
"architectural_layer": "presentation_ui",
|
||||
"assigned_role": "06_dev_frontend",
|
||||
"priority": "HIGH",
|
||||
"status": "completed",
|
||||
"max_files_allowed": 2,
|
||||
"estimated_minutes": 15,
|
||||
"dependency_task_ids": ["EPIC-15-TASK-01"],
|
||||
"acceptance_criteria": [
|
||||
"توضیح واضح و شفاف کارکرد سرویس تمدید خودکار (برنامه وفاداری رایگان با ۵٪ تخفیف دائم)",
|
||||
"رفع ابهام کاربر در خصوص عدم وجود هزینه پنهان یا اضافی برای سرویس تمدید"
|
||||
],
|
||||
"sub_steps": [
|
||||
{ "index": 1, "name": "clarify_refill_ux", "description": "Update Refill section text and tooltips in CheckoutPage.tsx", "status": "done" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "EPIC-15-TASK-03",
|
||||
"title": "Full-Stack Refill Badge & Discount Breakdown Display",
|
||||
"description": "Render Refill badge and explicit 5% discount line item across Checkout, OrderSuccess, UserDashboard, OrderDetailsModal, and Admin Panel Orders.",
|
||||
"architectural_layer": "presentation_ui",
|
||||
"assigned_role": "06_dev_frontend",
|
||||
"priority": "HIGH",
|
||||
"status": "completed",
|
||||
"max_files_allowed": 5,
|
||||
"estimated_minutes": 25,
|
||||
"dependency_task_ids": ["EPIC-15-TASK-02"],
|
||||
"acceptance_criteria": [
|
||||
"نمایش نشان اختصاصی «تمدید خودکار ۵٪-» در تمام مدالها، لیستها، فاکتورها و پنل مدیریت ادمین",
|
||||
"نمایش خط ردیف شفاف «تخفیف تمدید خودکار (۵٪)» در فاکتور نهایی"
|
||||
],
|
||||
"sub_steps": [
|
||||
{ "index": 1, "name": "render_refill_badges_and_discounts", "description": "Add Refill badge and discount row in OrderSuccess, UserDashboard, OrderDetailsModal, and Admin Orders", "status": "done" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"total": 27,
|
||||
"completed": 27,
|
||||
"total": 30,
|
||||
"completed": 30,
|
||||
"in_progress": 0,
|
||||
"pending": 0,
|
||||
"generated_at": "2026-07-27T11:30:00Z",
|
||||
"decomposition_pass": 12
|
||||
"generated_at": "2026-07-27T11:40:00Z",
|
||||
"decomposition_pass": 13
|
||||
}
|
||||
}
|
||||
@ -7,12 +7,12 @@
|
||||
"status": "COMPLETE",
|
||||
"checkpoint": {
|
||||
"active_agent": "01_auditor",
|
||||
"current_ticket_id": "EPIC-14-TASK-02",
|
||||
"current_ticket_id": "EPIC-15-TASK-03",
|
||||
"sub_step": {
|
||||
"index": 1,
|
||||
"total": 1,
|
||||
"name": "build_admin_order_modal",
|
||||
"description": "Admin panel order management overhaul, modal, tracking editor, status selector, and print invoice complete and 100% verified"
|
||||
"name": "render_refill_badges_and_discounts",
|
||||
"description": "Refill loyalty subscription logic, 5% discount explanation, and full-stack badge persistence complete and 100% verified"
|
||||
}
|
||||
},
|
||||
"review_phase": {
|
||||
|
||||
@ -369,7 +369,12 @@ export default function Orders() {
|
||||
return (
|
||||
<tr key={order.id} className="hover:bg-gray-50/50 transition-colors">
|
||||
<td className="py-4 px-6 font-bold text-purple-600 font-mono" dir="ltr">
|
||||
{toPersianDigits(displayCode)}
|
||||
<div>{toPersianDigits(displayCode)}</div>
|
||||
{order.isRefill && (
|
||||
<span className="inline-block mt-1 text-[9px] font-black px-2 py-0.5 rounded-full bg-green-50 text-green-700 border border-green-200">
|
||||
Refill 5%
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="py-4 px-6">
|
||||
<div className="font-bold text-gray-900">{customerName}</div>
|
||||
|
||||
@ -275,9 +275,9 @@ export default function CartDrawer({ isOpen, onClose, onCheckout, onShopNavigate
|
||||
<ShieldCheck className="w-6 h-6" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h5 className="text-xs font-black text-medical-gray-900">فعالسازی سرویس تمدید خودکار (Refill)</h5>
|
||||
<p className="text-[10px] text-canina-blue font-black mt-0.5">۵٪ تخفیف روی تمام فاکتور + ارسال اولویتدار</p>
|
||||
<p className="text-[9px] text-medical-gray-400 font-bold mt-1">ویژه اعضا - محاسبه هوشمند دوره مصرف و یادآوری پیامکی قبل از اتمام</p>
|
||||
<h5 className="text-xs font-black text-medical-gray-900">سرویس وفاداری تمدید خودکار (Refill)</h5>
|
||||
<p className="text-[10px] text-canina-blue font-black mt-0.5">۵٪ تخفیف ویژه روی کل فاکتور + ارسال اولویتدار</p>
|
||||
<p className="text-[9px] text-medical-gray-500 font-bold mt-1">برنامه رایگان وفاداری - بدون هیچ هزینه اضافی؛ یادآوری و تمدید هوشمند قبل از اتمام مکمل پت شما</p>
|
||||
</div>
|
||||
<div className={`w-5 h-5 rounded-full border-2 flex items-center justify-center ${isSubscribed ? 'bg-canina-blue border-canina-blue' : 'border-medical-gray-200'}`}>
|
||||
{isSubscribed && <X className="w-3 h-3 text-white" />}
|
||||
|
||||
@ -91,6 +91,16 @@ export default function OrderSuccess({ orderId }: { orderId: string }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{order.isRefill && (
|
||||
<div className="p-6 bg-green-50 border border-green-200 rounded-3xl mb-12 text-right flex items-center justify-between">
|
||||
<div>
|
||||
<h5 className="font-black text-green-800 text-sm italic">سرویس تمدید خودکار (Refill) با ۵٪ تخفیف روی این سفارش فعال شد</h5>
|
||||
<p className="text-xs text-green-700 font-bold mt-1">قبل از اتمام مکمل، یادآوری و ارسال بعدی به صورت هوشمند برای شما هماهنگ خواهد شد.</p>
|
||||
</div>
|
||||
<span className="px-3 py-1 bg-green-600 text-white font-black text-xs rounded-full shrink-0">۵٪ تخفیف اعمال شد</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-4">
|
||||
<button
|
||||
onClick={() => router.push('/track')}
|
||||
|
||||
@ -364,6 +364,11 @@ export default function UserDashboard() {
|
||||
<div className="text-left">
|
||||
<div className="text-lg font-black text-medical-gray-900 italic">{toPersian(order.total.toLocaleString())} <span className="text-xs">تومان</span></div>
|
||||
<div className="flex items-center gap-2 justify-end mt-1">
|
||||
{order.isRefill && (
|
||||
<span className="text-[9px] font-black px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-600 border border-emerald-100">
|
||||
تمدید خودکار ۵٪-
|
||||
</span>
|
||||
)}
|
||||
<span className={`text-[9px] font-black px-2.5 py-0.5 rounded-full uppercase tracking-tighter ${order.status === 'delivered' ? 'bg-green-50 text-green-600' : order.status === 'shipped' ? 'bg-blue-50 text-blue-600' : 'bg-amber-50 text-amber-600'}`}>
|
||||
{order.status === 'delivered' ? 'تحویل شده' : order.status === 'shipped' ? 'ارسال شده' : 'در حال پردازش'}
|
||||
</span>
|
||||
|
||||
@ -128,6 +128,8 @@ export const useCartStore = create<CartStore>()(
|
||||
total: Number(backendOrder.totalAmount),
|
||||
charityDonation: Number(backendOrder.charityDonation),
|
||||
status: backendOrder.status as any,
|
||||
isRefill: (backendOrder as any).isRefill !== undefined ? Boolean((backendOrder as any).isRefill) : Boolean(orderData.isRefill || get().isSubscribed),
|
||||
paymentMethod: (backendOrder as any).paymentMethod || orderData.paymentMethod,
|
||||
trackingNumber: backendOrder.trackingNumber || `CN-${Math.floor(Math.random() * 90000) + 10000}`
|
||||
};
|
||||
|
||||
@ -151,6 +153,8 @@ export const useCartStore = create<CartStore>()(
|
||||
total: Number(bo.totalAmount),
|
||||
charityDonation: Number(bo.charityDonation),
|
||||
status: bo.status,
|
||||
isRefill: Boolean((bo as any).isRefill),
|
||||
paymentMethod: (bo as any).paymentMethod,
|
||||
petId: bo.petId || bo.pet?.id,
|
||||
shippingAddress: bo.shippingAddress,
|
||||
trackingNumber: bo.trackingNumber || `CN-${Math.floor(Math.random() * 90000) + 10000}`
|
||||
|
||||
Loading…
Reference in New Issue
Block a user