feat(05-03): add getClientActiveOffers query + active offers section on client detail page
- Add ClientActiveOfferSummary type to admin-queries.ts - Add getClientActiveOffers() function joining project_offers with offer_micros - Only selects public_name (never internal_name) per CLAUDE.md constraint - Update /admin/clients/[id] to fetch active offers in parallel with project data - Add Offerte Attive section at bottom of client detail page
This commit is contained in:
@@ -641,4 +641,47 @@ export async function getClientWithProjects(clientId: string): Promise<ClientWit
|
||||
created_at: p.created_at,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
// ── ClientActiveOfferSummary — used by /admin/clients/[id] offers section ─────
|
||||
|
||||
export type ClientActiveOfferSummary = {
|
||||
offer_id: string;
|
||||
project_id: string;
|
||||
project_name: string;
|
||||
public_name: string; // offer_micros.public_name — NEVER internal_name
|
||||
accepted_total: string | null;
|
||||
};
|
||||
|
||||
export async function getClientActiveOffers(clientId: string): Promise<ClientActiveOfferSummary[]> {
|
||||
const projectRows = await db
|
||||
.select({ id: projects.id, name: projects.name })
|
||||
.from(projects)
|
||||
.where(eq(projects.client_id, clientId));
|
||||
|
||||
if (projectRows.length === 0) return [];
|
||||
|
||||
const projectIds = projectRows.map((p) => p.id);
|
||||
const projectNameMap = new Map(projectRows.map((p) => [p.id, p.name]));
|
||||
|
||||
// Explicit column selection — public_name only, NEVER internal_name
|
||||
const rows = await db
|
||||
.select({
|
||||
offer_id: project_offers.id,
|
||||
project_id: project_offers.project_id,
|
||||
public_name: offer_micros.public_name,
|
||||
accepted_total: project_offers.accepted_total,
|
||||
})
|
||||
.from(project_offers)
|
||||
.innerJoin(offer_micros, eq(project_offers.micro_id, offer_micros.id))
|
||||
.where(inArray(project_offers.project_id, projectIds))
|
||||
.orderBy(asc(project_offers.created_at));
|
||||
|
||||
return rows.map((r) => ({
|
||||
offer_id: r.offer_id,
|
||||
project_id: r.project_id,
|
||||
project_name: projectNameMap.get(r.project_id) ?? "—",
|
||||
public_name: r.public_name,
|
||||
accepted_total: r.accepted_total ? String(r.accepted_total) : null,
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user