feat: enhance pricing and persona synchronization logic for improved data consistency
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions

This commit is contained in:
Najjar\NajjarV02
2026-04-17 16:08:11 +04:00
parent 13050a6541
commit 11ab8908fa
3 changed files with 87 additions and 19 deletions
+62 -13
View File
@@ -48,25 +48,74 @@ export default function AdminPage() {
const res = await fetch('/api/admin/pricing/');
const data = await res.json();
const serverItems: { id: string; label: string; price: number; modelPath: string | null }[] = data.items ?? [];
const localItems = pricingStore.getState().items;
if (serverItems.length > 0) {
// Sync server data into local stores
serverItems.forEach(({ id, label, price, modelPath }) => {
const existing = pricingStore.getState().items.find((i) => i.id === id);
if (existing) {
pricingStore.getState().updateItem(id, { label, price, modelPath: modelPath ?? undefined });
} else {
pricingStore.getState().addItem({ id, label, price, modelPath: modelPath ?? undefined });
// Merge: server wins for label/price, but keep whichever modelPath exists
const serverMap = new Map(serverItems.map((s) => [s.id, s]));
const localMap = new Map(localItems.map((l) => [l.id, l]));
const itemsToUpdate: { id: string; label: string; price: number; modelPath?: string }[] = [];
// Merge server items with local modelPaths
for (const server of serverItems) {
const local = localMap.get(server.id);
// If local has a modelPath but server doesn't, push it to server
const mergedModelPath = server.modelPath || local?.modelPath;
pricingStore.getState().updateItem(server.id, {
label: server.label,
price: server.price,
modelPath: mergedModelPath ?? undefined,
});
// If we don't already have this item locally, add it
if (!local) {
pricingStore.getState().addItem({
id: server.id,
label: server.label,
price: server.price,
modelPath: mergedModelPath ?? undefined,
});
}
// If local had a modelPath but server didn't, push to server
if (!server.modelPath && local?.modelPath) {
itemsToUpdate.push({ id: server.id, label: server.label, price: server.price, modelPath: local.modelPath });
}
// Sync persona store
if (modelPath) {
const existingPersona = personaStore.getState().personas.find((p) => p.id === id);
if (mergedModelPath && server.id !== 'base') {
const existingPersona = personaStore.getState().personas.find((p) => p.id === server.id);
if (existingPersona) {
personaStore.getState().updatePersona(id, { modelPath });
} else if (id !== 'base') {
personaStore.getState().addPersona({ id, label, description: label, colors: { torso: '#3b82f6', legs: '#3b82f6' }, modelPath });
personaStore.getState().updatePersona(server.id, { modelPath: mergedModelPath });
} else {
personaStore.getState().addPersona({ id: server.id, label: server.label, description: server.label, colors: { torso: '#3b82f6', legs: '#3b82f6' }, modelPath: mergedModelPath });
}
}
});
}
// Add any local items that are missing from server
for (const local of localItems) {
if (!serverMap.has(local.id)) {
itemsToUpdate.push({ id: local.id, label: local.label, price: local.price, modelPath: local.modelPath });
}
}
// Push missing data back to server
if (itemsToUpdate.length > 0) {
for (const item of itemsToUpdate) {
fetch('/api/admin/pricing/', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(item),
}).catch(() => {});
}
}
} else {
// DB is empty — push local items to server so they persist for all users
if (localItems.length > 0) {
await fetch('/api/admin/pricing/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ items: localItems.map((item, i) => ({ ...item, sortOrder: i })) }),
});
}
}
} catch {
// Fall back to localStorage data (already hydrated)