From a0145ffd9a3bea7c137e4099fd06c19265cf8ce1 Mon Sep 17 00:00:00 2001
From: parsa aghaei
Date: Sun, 26 Jul 2026 20:44:55 +0330
Subject: [PATCH] fix(pets): persist supplement consumptions array in
usePetStore and update target pet on checkout
---
.ai_agency/memory/backlog.json | 27 ++++++--
.ai_agency/memory/state.json | 10 +--
.../application/components/CheckoutPage.tsx | 7 +-
frontend/application/lib/store/usePetStore.ts | 68 ++++++++++---------
4 files changed, 68 insertions(+), 44 deletions(-)
diff --git a/.ai_agency/memory/backlog.json b/.ai_agency/memory/backlog.json
index 16ef298..2f7c9c8 100644
--- a/.ai_agency/memory/backlog.json
+++ b/.ai_agency/memory/backlog.json
@@ -399,14 +399,33 @@
{ "index": 2, "name": "implement_wallet_deduction_in_orders_service", "description": "Deduct user walletBalance and create WalletTransaction in OrdersService.create", "status": "done" },
{ "index": 3, "name": "wire_checkout_page_wallet_sync", "description": "Send paymentMethod in API call and trigger fetchProfile() in CheckoutPage.tsx", "status": "done" }
]
+ },
+ {
+ "id": "EPIC-11-TASK-01",
+ "title": "Pet Supplement Consumption Tracking & Depletion Monitor Fix",
+ "description": "Ensure updatePet and setPets in usePetStore update and preserve pet consumptions array locally upon order placement so AI depletion monitor displays remaining supplement levels for active pets.",
+ "architectural_layer": "state_management",
+ "assigned_role": "06_dev_frontend",
+ "priority": "HIGH",
+ "status": "completed",
+ "max_files_allowed": 4,
+ "estimated_minutes": 20,
+ "dependency_task_ids": ["EPIC-10-TASK-01"],
+ "acceptance_criteria": [
+ "ثبت واقعی میزان مکملهای خریدهشده در پایش موجودی پت (usePetStore)",
+ "نمایش لحظهای مکملهای خریدهشده، درصد باقیمانده و تخمین اتمام مصرف پت در پروفایل"
+ ],
+ "sub_steps": [
+ { "index": 1, "name": "update_pet_store_consumptions_persistence", "description": "Always update local pets array in updatePet and preserve consumptions in setPets", "status": "done" }
+ ]
}
],
"metadata": {
- "total": 20,
- "completed": 20,
+ "total": 21,
+ "completed": 21,
"in_progress": 0,
"pending": 0,
- "generated_at": "2026-07-26T20:40:00Z",
- "decomposition_pass": 8
+ "generated_at": "2026-07-26T20:45:00Z",
+ "decomposition_pass": 9
}
}
\ No newline at end of file
diff --git a/.ai_agency/memory/state.json b/.ai_agency/memory/state.json
index 12d2c33..0b0d350 100644
--- a/.ai_agency/memory/state.json
+++ b/.ai_agency/memory/state.json
@@ -7,12 +7,12 @@
"status": "COMPLETE",
"checkpoint": {
"active_agent": "01_auditor",
- "current_ticket_id": "EPIC-10-TASK-01",
+ "current_ticket_id": "EPIC-11-TASK-01",
"sub_step": {
- "index": 3,
- "total": 3,
- "name": "wire_checkout_page_wallet_sync",
- "description": "Full-stack wallet balance deduction and charity donation total persistence in PostgreSQL complete and 100% verified"
+ "index": 1,
+ "total": 1,
+ "name": "update_pet_store_consumptions_persistence",
+ "description": "Pet supplement consumption tracking and AI stock monitor persistence complete and 100% verified"
}
},
"review_phase": {
diff --git a/frontend/application/components/CheckoutPage.tsx b/frontend/application/components/CheckoutPage.tsx
index 6a2935a..82b8d0f 100644
--- a/frontend/application/components/CheckoutPage.tsx
+++ b/frontend/application/components/CheckoutPage.tsx
@@ -125,8 +125,9 @@ export default function CheckoutPage() {
await fetchProfile();
// 4. Update pet consumptions and charity contributions for active pet
- if (activePet) {
- const newConsumptions = [...(activePet.consumptions || [])];
+ const targetPet = activePet || usePetStore.getState().pets[0];
+ if (targetPet) {
+ const newConsumptions = [...(targetPet.consumptions || [])];
items.forEach(item => {
const existing = newConsumptions.find(c => c.productId === item.product.id);
@@ -142,7 +143,7 @@ export default function CheckoutPage() {
}
});
- updatePet(activePet.id, {
+ updatePet(targetPet.id, {
consumptions: newConsumptions
});
}
diff --git a/frontend/application/lib/store/usePetStore.ts b/frontend/application/lib/store/usePetStore.ts
index 538ebef..cb25a52 100644
--- a/frontend/application/lib/store/usePetStore.ts
+++ b/frontend/application/lib/store/usePetStore.ts
@@ -135,6 +135,10 @@ export const usePetStore = create()(
return pets.find((p) => p.id === activePetId) || null;
},
updatePet: async (id, updates) => {
+ set((state) => ({
+ pets: state.pets.map((p) => (p.id === id ? { ...p, ...updates } : p)),
+ }));
+
const { useUserStore } = await import("./userStore");
const isLoggedIn = useUserStore.getState().isLoggedIn;
@@ -154,10 +158,6 @@ export const usePetStore = create()(
console.error("Failed to update pet via backend API:", error);
toast.error("خطا در ویرایش اطلاعات پت در سرور");
}
- } else {
- set((state) => ({
- pets: state.pets.map((p) => (p.id === id ? { ...p, ...updates } : p)),
- }));
}
},
addReminder: async (petId, reminder) => {
@@ -191,34 +191,38 @@ export const usePetStore = create()(
}
},
setPets: (backendPets) => {
- const mappedPets: PetProfile[] = backendPets.map(bp => ({
- id: bp.id,
- name: bp.name,
- type: bp.type as any,
- breed: bp.breed,
- age: Number(bp.age),
- weight: Number(bp.weight),
- activityLevel: bp.activityLevel as any,
- medicalConditions: bp.medicalConditions?.map((mc: any) => mc.condition) || [],
- image: bp.imageUrl || undefined,
- reminders: bp.reminders?.map((r: any) => ({
- id: r.id,
- title: r.title,
- time: r.time,
- frequency: r.frequency as any,
- productId: r.productId,
- completedDates: r.completions?.map((c: any) => c.completedDate) || []
- })) || [],
- logs: bp.healthLogs?.map((hl: any) => ({
- id: hl.id,
- date: hl.loggedDate,
- appetite: hl.appetite as any,
- energy: hl.energy as any,
- digestion: hl.digestion as any,
- note: hl.note || undefined
- })) || [],
- consumptions: []
- }));
+ const currentLocalPets = get().pets;
+ const mappedPets: PetProfile[] = backendPets.map(bp => {
+ const existingLocal = currentLocalPets.find(lp => lp.id === bp.id);
+ return {
+ id: bp.id,
+ name: bp.name,
+ type: bp.type as any,
+ breed: bp.breed,
+ age: Number(bp.age),
+ weight: Number(bp.weight),
+ activityLevel: bp.activityLevel as any,
+ medicalConditions: bp.medicalConditions?.map((mc: any) => mc.condition) || [],
+ image: bp.imageUrl || undefined,
+ reminders: bp.reminders?.map((r: any) => ({
+ id: r.id,
+ title: r.title,
+ time: r.time,
+ frequency: r.frequency as any,
+ productId: r.productId,
+ completedDates: r.completions?.map((c: any) => c.completedDate) || []
+ })) || [],
+ logs: bp.healthLogs?.map((hl: any) => ({
+ id: hl.id,
+ date: hl.loggedDate,
+ appetite: hl.appetite as any,
+ energy: hl.energy as any,
+ digestion: hl.digestion as any,
+ note: hl.note || undefined
+ })) || [],
+ consumptions: existingLocal?.consumptions || []
+ };
+ });
set({ pets: mappedPets, activePetId: get().activePetId && mappedPets.some(p => p.id === get().activePetId) ? get().activePetId : (mappedPets[0]?.id || null) });
},
}),