feat: service offer tags, catalog cleanup, offer editor filter
- Import 58 offer membership tags for all 55 services (entity_type="services") via scripts/import-service-offer-tags.ts (already run on prod) - ServiceTable: remove Categoria column, rename Tag → Offerta; QuickAddRow no longer has a category field (offer tags set post-creation) - offer-queries: getOfferEditorData fetches offerTags per service (join on tags WHERE entity_type="services") and exposes them in OfferEditorData - OfferEditorClient: filter chips above "Servizi Inclusi" — Tutti / Entry Offer / Signature Offer / Retainer Offer, derived from actual tag data Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,7 @@ export type OfferEditorData = {
|
||||
name: string;
|
||||
unit_price: string;
|
||||
category: string | null;
|
||||
offerTags: string[];
|
||||
}>;
|
||||
tipoTags: string[];
|
||||
obiettivoTags: string[];
|
||||
@@ -206,9 +207,8 @@ export async function getOfferEditorData(macroId: string): Promise<OfferEditorDa
|
||||
servicesTotal: totalsMap.get(tier.id) ?? "0",
|
||||
}));
|
||||
|
||||
// Full service catalog (unfiltered by category) — category filtering happens
|
||||
// client-side so changing the category field doesn't wipe the service list.
|
||||
const availableServices = await db
|
||||
// Full service catalog with offer membership tags (entity_type = "services").
|
||||
const allServices = await db
|
||||
.select({
|
||||
id: services.id,
|
||||
name: services.name,
|
||||
@@ -218,6 +218,27 @@ export async function getOfferEditorData(macroId: string): Promise<OfferEditorDa
|
||||
.from(services)
|
||||
.where(eq(services.active, true));
|
||||
|
||||
const serviceIds = allServices.map((s) => s.id);
|
||||
const offerTagRows =
|
||||
serviceIds.length > 0
|
||||
? await db
|
||||
.select({ entity_id: tags.entity_id, name: tags.name })
|
||||
.from(tags)
|
||||
.where(and(eq(tags.entity_type, "services"), inArray(tags.entity_id, serviceIds)))
|
||||
: [];
|
||||
|
||||
const tagsByServiceId = new Map<string, string[]>();
|
||||
for (const row of offerTagRows) {
|
||||
const list = tagsByServiceId.get(row.entity_id) ?? [];
|
||||
list.push(row.name);
|
||||
tagsByServiceId.set(row.entity_id, list);
|
||||
}
|
||||
|
||||
const availableServices = allServices.map((s) => ({
|
||||
...s,
|
||||
offerTags: tagsByServiceId.get(s.id) ?? [],
|
||||
}));
|
||||
|
||||
// Tipo/Obiettivo tags for this macro.
|
||||
const tagRows = await db
|
||||
.select({ name: tags.name, type: tags.entity_type })
|
||||
|
||||
Reference in New Issue
Block a user