From 76f0dfacb4eca06ac668078db8517a53365ce914 Mon Sep 17 00:00:00 2001 From: riyadhafraa <49757212-riyadhafraa@users.noreply.replit.com> Date: Thu, 30 Apr 2026 12:47:50 +0000 Subject: [PATCH] Restart numbering for individuals after each subheading Modify attendee numbering logic to reset at each subheading, ensuring proper sequence and display across different views and PDF outputs. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 17c29c3f-e55d-4765-875c-0387b6936812 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/piUNOmy Replit-Helium-Checkpoint-Created: true --- artifacts/api-server/src/lib/pdf-renderer.ts | 10 ++- .../src/pages/executive-meetings-print.tsx | 8 ++- .../tx-os/src/pages/executive-meetings.tsx | 66 +++++++++++++----- ...ive-meetings-attendee-subheadings.spec.mjs | 13 ++-- attached_assets/image_1777552559341.png | Bin 0 -> 10991 bytes attached_assets/image_1777553124397.png | Bin 0 -> 12178 bytes 6 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 attached_assets/image_1777552559341.png create mode 100644 attached_assets/image_1777553124397.png diff --git a/artifacts/api-server/src/lib/pdf-renderer.ts b/artifacts/api-server/src/lib/pdf-renderer.ts index f913c416..8db8ca8a 100644 --- a/artifacts/api-server/src/lib/pdf-renderer.ts +++ b/artifacts/api-server/src/lib/pdf-renderer.ts @@ -531,15 +531,19 @@ export async function renderSchedulePdf(input: RenderPdfInput): Promise meeting.attendees.length === 0 ? "—" : (() => { - // Walking person counter — subheadings are non-numbered - // labels, so they don't advance the index. Same logic as - // the on-screen AttendeeFlow and the print page. + // Walking person counter — each subheading starts a + // fresh numbered section, so persons restart at 1- after + // every subheading. Same logic as the on-screen + // AttendeeFlow and the client print page. let personIdx = 0; return meeting.attendees .map((a) => { const isSub = (a.kind ?? "person") === "subheading"; const name = htmlToPlain(a.name); if (isSub) { + // Reset the in-section counter so the next person + // starts at 1. + personIdx = 0; // Brackets keep subheadings visually distinct in the // monospace plain-text PDF cell where bold/colour // can't carry. Adapter prefix is non-numeric so a diff --git a/artifacts/tx-os/src/pages/executive-meetings-print.tsx b/artifacts/tx-os/src/pages/executive-meetings-print.tsx index 44525a45..11e4051b 100644 --- a/artifacts/tx-os/src/pages/executive-meetings-print.tsx +++ b/artifacts/tx-os/src/pages/executive-meetings-print.tsx @@ -275,14 +275,16 @@ export default function ExecutiveMeetingsPrintPage() { data-testid={`em-print-attendees-${m.id}`} > {(() => { - // Walking person counter — subheadings are - // labels, so they don't advance the print - // index. Mirrors AttendeeFlow on screen. + // Each subheading starts a fresh numbered + // section. Mirrors AttendeeFlow on screen. let personIdx = 0; return attendees.map((a, idx) => { const isSub = (a.kind ?? "person") === "subheading"; if (isSub) { + // Reset the in-section counter so the + // next person starts at 1. + personIdx = 0; return (
n + ((a.kind ?? "person") === "person" ? 1 : 0), - 0, + // Each subheading starts a fresh numbered section. Within a section, + // persons are numbered 1..N starting over after every subheading. + // Numbering rules: + // - If the cell has NO subheading: keep the legacy "don't number a + // single name" rule (only show numbers when 2+ persons exist). + // - If the cell HAS any subheading: always show numbers, even for + // solo persons inside a section, so the grouping reads clearly. + // Pre-compute per-list-position metadata so the render loop is O(n). + const hasAnySubheading = items.some( + ({ a }) => (a.kind ?? "person") === "subheading", ); + const sectionMeta = items.map(() => ({ + sectionPersonCount: 0, + idxInSection: 0, + })); + { + let secStart = 0; + let secCount = 0; + const finalize = (endExclusive: number) => { + for (let k = secStart; k < endExclusive; k++) { + sectionMeta[k].sectionPersonCount = secCount; + } + }; + items.forEach(({ a }, idx) => { + if ((a.kind ?? "person") === "subheading") { + finalize(idx); + secStart = idx + 1; + secCount = 0; + } else { + sectionMeta[idx].idxInSection = secCount; + secCount += 1; + } + }); + finalize(items.length); + } + // Person count of the trailing (last) section — drives whether the + // pending "+ name" ghost row shows a leading number. + let lastSectionPersonCount = 0; + for (let k = items.length - 1; k >= 0; k--) { + if ((items[k].a.kind ?? "person") === "subheading") break; + lastSectionPersonCount += 1; + } if (items.length === 0 && !showAdd && !isPending) { return ; } - // Walking counter — incremented only as we render person rows. - let personIdx = 0; - return (