Commit Graph

662 Commits

Author SHA1 Message Date
riyadhafraa 1e3419b0cb Apply row styling only to meeting number and title columns
Removes row background and border styling from the attendees and time columns in the PDF renderer and the web interface. Adjusts the `tintedCellStyle` function to conditionally apply border styling based on `applyRowColor` flag.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ed9f2aec-9e1e-4b42-9747-7e4482299fce
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Msx3Bax
Replit-Helium-Checkpoint-Created: true
2026-05-04 14:11:15 +00:00
riyadhafraa 01c22b90b8 Apply consistent styling to all cells within a table row
Update table cell styling to ensure uniform background and border colors across all cells in a row.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 74773548-ab72-4530-a366-44a49c20bd99
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Msx3Bax
Replit-Helium-Checkpoint-Created: true
2026-05-04 14:06:03 +00:00
riyadhafraa 33ff4803d7 Update open graph image for the project
Replace existing open graph image file with an updated version.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b61754fb-b246-4949-8adc-3525b96164e7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Msx3Bax
Replit-Helium-Checkpoint-Created: true
2026-05-04 14:01:47 +00:00
riyadhafraa c7c34a2b96 Update images for improved visual presentation and branding
Update opengraph image and other attached assets.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ad10fcfd-54ba-4a23-ba79-0ef00fbb5b51
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/8mknY7A
Replit-Helium-Checkpoint-Created: true
2026-05-04 13:22:13 +00:00
riyadhafraa 81833c021c Unify row color styling across all web table cells
Previously, when a meeting row had a color assigned (e.g. red), the
attendees and time cells only received the colored border but not the
background fill. The meeting cell used `tintedCellStyle(col, true)` which
always applies rowBg, while attendees and time used
`tintedCellStyle(col, isMerged)` — meaning they only got the background
when the row was merged.

Changed both attendees and time cells to use `tintedCellStyle(col, true)`
so all four cells (number, meeting, attendees, time) display the same
background fill and border color when a row color is set.

This mirrors the PDF fix from Task #385 which addressed the same
inconsistency in the PDF renderer.

File changed: artifacts/tx-os/src/pages/executive-meetings.tsx (lines 3804, 3825)
2026-05-04 13:07:48 +00:00
riyadhafraa 1a22a8da9e Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: fe4b9181-6973-4466-a34a-a6e3c71a4ce0
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/obqebYr
Replit-Helium-Checkpoint-Created: true
2026-05-04 13:06:45 +00:00
riyadhafraa 3d8b1a9036 Unify row color styling across all PDF table cells
Previously, when a meeting row had a color assigned (e.g. red), only the
number and meeting title cells received both the background fill and colored
border, while the attendees and time cells received only the colored border
(no background fill). This made the row styling inconsistent.

Changed attendees-cell and time-cell to use `coloredStyle` (background +
border) instead of `borderStyle` (border only), matching the number and
meeting cells. All four cells in a colored row now display uniformly.

Rows without a color assignment are unaffected (default gray border, no fill).

File changed: artifacts/api-server/src/lib/pdf-html-renderer.ts (lines 222-223)
2026-05-04 13:03:42 +00:00
riyadhafraa 27553cea73 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1f072505-21b2-4b5f-87e9-c5cf4c34cdec
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/obqebYr
Replit-Helium-Checkpoint-Created: true
2026-05-04 13:02:49 +00:00
riyadhafraa 014f9ecb0e Fix PDF font color not reflecting system settings via per-field merge
Root cause: resolveFontPrefsForUser() used `userRow ?? globalRow` whole-row
precedence. When an admin saved font settings with scope="global", only the
global row was updated. If the admin also had a user-scope row (created by
prior saves with the default scope="user"), ALL fields from the user-scope
row overrode the global row — including fontColor — causing the PDF to show
the old color even after changing global settings.

Schema change (executive-meetings.ts):
- Made fontFamily, fontSize, fontWeight, alignment, fontColor nullable.
  User-scope rows now store NULL for fields that inherit from global,
  and only store non-null values for fields the user explicitly overrode.

Backend fix (executive-meetings.ts):
- resolveFontPrefsForUser: per-field merge —
  user non-null → global non-null → schema default.
- PATCH handler for user-scope: after upsert, compares each field with the
  current global values. Fields matching global are set to NULL (= inherit).
  The post-nullification row is returned in the API response and audit log.
- No user-scope rows are deleted; scope isolation is preserved.

Frontend fix (executive-meetings.tsx):
- effectiveFont computed via per-field merge (u?.field ?? g?.field ?? default)
- FontSettingsResponse type updated for nullable fields (FontSettingsRow)
- Scope switching in FontSettingsSection loads the selected scope's values
  (global → globalFont ?? DEFAULT_FONT; user → effective font)
- globalFont prop threaded through SettingsSection → FontSettingsSection

Data migration: existing user-scope rows normalized via SQL — fields matching
global values set to NULL so per-field inheritance applies immediately.

Verified: TypeScript clean, e2e Playwright test passes, API tests confirm
per-field merge, nullification, and PDF color propagation.
2026-05-04 12:30:00 +00:00
riyadhafraa 77538a93c0 Fix PDF font color not reflecting system settings
Root cause: resolveFontPrefsForUser() uses `userRow ?? globalRow` precedence.
When an admin saved font settings with scope="global", only the global row
was updated. If the admin also had a user-scope row (created by prior saves
with the default scope="user"), the user-scope row still overrode the global
row during PDF generation, causing the PDF to show the old color.

Backend fix (executive-meetings.ts):
- When saving with scope="global", delete the current admin's user-scope row
  within the same transaction. This ensures global settings immediately apply
  to the admin who set them. Other users' personal rows are unaffected.

Frontend fix (executive-meetings.tsx):
- Pass both `globalFont` and effective `font` to FontSettingsSection.
- When the scope dropdown changes, the form now loads the selected scope's
  actual saved values instead of always showing the effective (user-override)
  values. This prevents confusion where the admin edits "global" but sees
  their personal values in the form.

Verified end-to-end:
- PATCH font-settings with scope=user + fontColor=#ff0000 → DB updated → PDF uses red
- PATCH font-settings with scope=global + fontColor=#0000ff → global updated,
  user-scope row deleted → PDF resolves to global blue
- TypeScript compiles cleanly, e2e Playwright test passes
2026-05-04 12:17:40 +00:00
riyadhafraa 4fcb80b44a Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 8c2bf63c-f2d5-45b8-b0eb-e26a851f3447
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/k1UTYfG
Replit-Helium-Checkpoint-Created: true
2026-05-04 12:04:17 +00:00
riyadhafraa 8810130ef5 Make row borders darker and more prominent
Update border colors and thickness in PDF renderer and UI to ensure visibility and consistency.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0b5defcb-10cb-452f-a4e7-72763eeb98bc
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/k1UTYfG
Replit-Helium-Checkpoint-Created: true
2026-05-04 11:57:42 +00:00
riyadhafraa 8891eca9e6 Task #380: Darken cell borders to match row color in PDF and web UI
When a row has a color (e.g. red), the cell borders now use a darker
shade of the same color instead of the default gray (#d1d5db).

PDF renderer (pdf-html-renderer.ts):
- Added ROW_COLOR_BORDER map with darker shades for each color
- Colored rows now get both background-color and border-color inline
- Non-merged rows: # and meeting cells get bg+border, attendees and
  time cells get border only (preserving partial coloring behavior)
- Merged rows: all cells get bg+border via coloredStyle

Web UI (executive-meetings.tsx):
- Added 'border' field to ROW_COLOR_OPTIONS with matching darker shades
- tintedCellStyle always applies borderColor when rowBorder exists
- Number cell inline style includes borderColor in both rowBg and
  tintBg (current meeting highlight) branches
- Merge cell style includes borderColor in both tint and rowBg branches
- Border color persists even when current-meeting highlight is active

Color mapping:
  red:    fill #fee2e2 → border #fca5a5
  amber:  fill #fef3c7 → border #fcd34d
  green:  fill #dcfce7 → border #86efac
  blue:   fill #dbeafe → border #93c5fd
  violet: fill #ede9fe → border #c4b5fd
  gray:   fill #f3f4f6 → border #d1d5db
2026-05-04 11:33:56 +00:00
riyadhafraa 2d033ca3fd Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 2b7fbc49-730c-46a8-8834-1e87875da2f9
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/nFy3UZm
Replit-Helium-Checkpoint-Created: true
2026-05-04 11:27:50 +00:00
riyadhafraa 02e1856f3d Task #377: Improve PDF cell spacing, line-height, and use system fontColor
Changes in artifacts/api-server/src/lib/pdf-html-renderer.ts:

1. Increased cell padding from 2px 4px to 10px 12px for both header
   and body cells for better readability
2. Increased line-height from 1.05 to 1.8 (body cells) and 1.2 to 1.6
   (header cells and body baseline)
3. Page title (h1) now uses system fontColor instead of hardcoded #000
4. Footer text now uses system fontColor for consistency
5. Empty-state text uses system fontColor with opacity instead of #666
6. Attendee items get direction-aware margin (12px) for better spacing
7. Logo header uses conditional min-height (55px when logo present,
   auto when absent) to prevent overlap and empty space
8. Footer date-line margin increased from 2px to 4px

Header background (#0B1E3F), header text (white), and border color
(#d1d5db) remain as branded defaults — no DB columns exist for these
yet (follow-up task #378 proposed for that).

No changes to web UI, schema, or legacy pdf-renderer.ts.
Tested: AR and EN PDFs generate successfully with correct sizes.
E2E test passed: login, PDF download (both languages), and UI verified.
2026-05-04 11:17:12 +00:00
riyadhafraa ea9217d483 Task #377: Improve PDF cell spacing, line-height, and use system fontColor
Changes in artifacts/api-server/src/lib/pdf-html-renderer.ts:

1. Increased cell padding from 2px 4px to 10px 12px (body cells) and
   3px 4px to 8px 12px (header cells) for better readability
2. Increased line-height from 1.05 to 1.8 (body cells) and 1.2 to 1.6
   (header cells and body baseline)
3. Page title (h1) now uses system fontColor instead of hardcoded #000
4. Footer text now uses system fontColor for consistency
5. Attendee items get direction-aware margin (12px) for better spacing
6. Logo header uses conditional min-height (55px when logo present,
   auto when absent) to prevent overlap and empty space
7. Footer date-line margin increased from 2px to 4px

Header background (#0B1E3F), header text (white), and border color
(#d1d5db) remain as branded defaults — no DB columns exist for these
yet (follow-up task #378 proposed for that).

No changes to web UI, schema, or legacy pdf-renderer.ts.
Tested: AR and EN PDFs generate successfully with correct sizes.
E2E test passed: login, PDF download (both languages), and UI verified.
2026-05-04 11:15:55 +00:00
riyadhafraa 4a3305ba07 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7629a54c-a648-4057-b56d-1f6617787ef9
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/nFy3UZm
Replit-Helium-Checkpoint-Created: true
2026-05-04 11:12:09 +00:00
riyadhafraa 086a037bf4 Apply row coloring consistently across the web and PDF views
Adjust cell styling to ensure row background colors are applied uniformly to both individual and merged rows, matching the PDF rendering behavior in the web interface.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 07cf3bc9-c682-4f05-aa30-52606bcce583
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/nFy3UZm
Replit-Helium-Checkpoint-Created: true
2026-05-04 11:05:57 +00:00
riyadhafraa 204f2ec5b0 Improve PDF export to correctly display partial row coloring
Update PDF generation logic to ensure partial row coloring is applied correctly to specific columns.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 63d5ae46-8988-42c4-8fd5-2e6a5696549c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:59:48 +00:00
riyadhafraa 446ed292b5 PDF row color: apply only to # and meeting columns, full row on merge
Task #375: Changed row coloring behavior in the HTML-table PDF renderer
so that normal rows only color the # (number) and الاجتماع (meeting)
cells, leaving الحضور (attendees) and الوقت (time) cells white.

When a row has merged columns (colspan), the entire row is colored
as before.

Implementation: `buildMeetingRow` now assigns `bgStyle` directly to
the first two cells' `style` field. `renderCells` takes an `allColored`
flag — true for merged rows (applies bgStyle to all cells), false for
normal rows (uses each cell's own style). The `<tr>` element no longer
carries the background style.

File changed: artifacts/api-server/src/lib/pdf-html-renderer.ts
2026-05-04 10:46:10 +00:00
riyadhafraa 86e91207ee Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: e43d5c0d-200e-4af6-a6eb-4ab4ab316817
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:43:58 +00:00
riyadhafraa 405f11ba52 Adjust report layout for title, columns, and date format
Remove manual column reversal for RTL rendering and enforce LTR for footer date to fix display issues.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5d0f535d-8066-49ff-a6bc-362e493b9c3d
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:32:22 +00:00
riyadhafraa 160ff44f04 Update attendee display to prevent text overflow
Modify CSS for attendee lines to allow text wrapping and change attendee item display to inline to ensure long attendee names fit within the PDF rendering.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d40348a8-3046-467d-84f1-d0084b560422
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:28:39 +00:00
riyadhafraa cd4dab15b6 Rebuild PDF generation: HTML <table> + Playwright replaces PDFKit manual drawing
Task #372: Replaced the manual PDFKit coordinate-based PDF renderer with an
HTML table-based approach using Playwright's headless Chromium.

Key changes:
- Created `pdf-html-renderer.ts` with `buildScheduleHtml()` (generates full
  HTML with embedded base64 fonts, proper `<table>`, RTL/LTR support, row
  colors, merged cells, attendees formatting) and `htmlToPdfBuffer()` (renders
  HTML to PDF via Playwright Chromium).
- Updated `pdf-renderer.ts`: `renderSchedulePdf()` now delegates to the new
  HTML renderer via dynamic import. Legacy PDFKit code preserved as
  `renderSchedulePdf_LEGACY()` for fallback reference.
- Added `playwright-core` dependency and configured esbuild externals.
- Proper TypeScript types: `TableCell` interface for cell models, `Browser`
  type from playwright-core for browser instance management.
- Chromium provisioning: searches `.cache/ms-playwright/` with env var override
  (`PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH`), auto-installs via
  `npx playwright-core install chromium` if not found.
- Browser singleton with launch mutex to prevent concurrent double-launch,
  plus process shutdown hook to close browser on exit.

Requirements met:
- Each meeting in exactly one `<tr>` with 4 `<td>` cells
- No text outside table, attendees ~3 per line inline
- Time always in its column, `page-break-inside: avoid`, `table-layout: fixed`
- Matches reference design (blue header, centered text, DIN Next LT Arabic)
2026-05-04 10:26:34 +00:00
riyadhafraa f4d99b6cfd Rebuild PDF generation: HTML <table> + Playwright replaces PDFKit manual drawing
Task #372: Replaced the manual PDFKit coordinate-based PDF renderer with an
HTML table-based approach using Playwright's headless Chromium.

Key changes:
- Created `pdf-html-renderer.ts` with `buildScheduleHtml()` (generates full
  HTML with embedded base64 fonts, proper `<table>`, RTL/LTR support, row
  colors, merged cells, attendees formatting) and `htmlToPdfBuffer()` (renders
  HTML to PDF via Playwright Chromium).
- Updated `pdf-renderer.ts`: `renderSchedulePdf()` now delegates to the new
  HTML renderer via dynamic import. Legacy PDFKit code preserved as
  `renderSchedulePdf_LEGACY()` for fallback reference.
- Added `playwright-core` dependency and configured esbuild externals.
- Chromium binary discovery: searches `.cache/ms-playwright/` directories with
  env var override (`PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH`). Browser instance
  is cached as singleton with launch mutex to prevent concurrent double-launch.
- Process shutdown hook closes browser on exit.

Requirements met:
- Each meeting in exactly one `<tr>` with 4 `<td>` cells
- No text outside table, attendees ~3 per line inline
- Time always in its column, `page-break-inside: avoid`, `table-layout: fixed`
- Matches reference design (blue header, centered text, DIN Next LT Arabic)
2026-05-04 10:24:08 +00:00
riyadhafraa 47e94c0118 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7d3d3bc1-a155-4f7d-9b82-2c84b0a35ff3
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:13:20 +00:00
riyadhafraa c4800a474c Update PDF generation to match reference design and improve alignment
Revert PDF cell padding and text alignment to match the reference design, ensuring centered content and vertical alignment.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 575935a0-0b89-4638-9c64-d47fb0cd4c78
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:06:22 +00:00
riyadhafraa 328d867975 Improve PDF schedule layout for better readability and alignment
Adjust PDF rendering to ensure all meeting details (number, title, attendees, time) are contained within a single row, improve vertical alignment to the top, and set correct text alignment for RTL content.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5cba573f-cf8f-4641-b2db-92b5b87be569
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 09:59:03 +00:00
riyadhafraa 0114ad86d0 Fix PDF table rows splitting across lines (#370)
Root cause: the height measurement probe reimplemented wrapping logic
inline, separate from the actual drawWrappingLine renderer. The two
implementations could diverge, causing the predicted row height to be
shorter than the actual rendered content, making cells overflow their
row borders and visually bleed into the next row.

Fix:
- Extract shared computeVisualLines() function that both the probe
  and drawWrappingLine use as the single source of truth for word-
  wrapping and line counting. This guarantees the predicted height
  always matches the actual rendered height.
- Save/restore doc.y around the probe loop so PDFKit's internal
  cursor doesn't drift between measurement and rendering passes.
- Save/restore doc.y per cell render block to prevent PDFKit cursor
  side effects from affecting adjacent cells.
- Add strict overflow guard: drawWrappingLine accepts a maxY param
  and stops rendering visual lines that would exceed the row bottom.
  The render loop also breaks on y >= rowBottom before starting new
  source lines. Together these form a two-level clamp that prevents
  any content from bleeding beyond row borders.
- drawWrappingLine is now a thin wrapper that calls computeVisualLines
  then draws each line via drawBidiLine, keeping the code DRY.

Tested with Arabic RTL and English LTR PDFs containing meetings with
10+ attendees, long titles, subheadings, and mixed bidi text. All
rows stay properly aligned within their borders.
2026-05-04 09:48:56 +00:00
riyadhafraa 090451ad22 Fix PDF table rows splitting across lines (#370)
Root cause: the height measurement probe reimplemented wrapping logic
inline, separate from the actual drawWrappingLine renderer. The two
implementations could diverge, causing the predicted row height to be
shorter than the actual rendered content, making cells overflow their
row borders and visually bleed into the next row.

Fix:
- Extract shared computeVisualLines() function that both the probe
  and drawWrappingLine use as the single source of truth for word-
  wrapping and line counting. This guarantees the predicted height
  always matches the actual rendered height.
- Save/restore doc.y around the probe loop so PDFKit's internal
  cursor doesn't drift between measurement and rendering passes.
- Add Y-clamp in the render loop: if a cell's text cursor reaches
  rowBottom, stop rendering to prevent overflow as a safety net.
- drawWrappingLine is now a thin wrapper that calls computeVisualLines
  then draws each line via drawBidiLine, keeping the code DRY.

Tested with Arabic RTL and English LTR PDFs containing meetings with
10+ attendees, long titles, subheadings, and mixed bidi text. All
rows stay properly aligned within their borders.
2026-05-04 09:46:49 +00:00
riyadhafraa d05b5297f1 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1441ae22-f1f6-4f78-b140-f28ef6e4048f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 09:40:36 +00:00
riyadhafraa 771cfb5611 Improve PDF generation for meeting tables with better text handling
Update PDF rendering logic to correctly handle bidirectional text, cell merging, and text wrapping for meeting tables.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 36ae937b-a1fc-4edb-8901-b07ed7713220
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 09:24:37 +00:00
riyadhafraa d47c5cf5d3 PDF: compact table with zero gaps, unified lineHeight (Task #368)
User requested maximum table compression with no gaps between rows.
Changes:
- cellPadX: 8→4, cellPadY: 6→0 (zero vertical padding)
- lineHeight: fontSize*1.5 → fontSize*1.05 (very tight)
- All columns (meeting, attendees, time, #) now center-aligned
- Added lineHeight option to DrawOpts type so draw helpers use the
  same metric as row measurement (fixes probe/draw mismatch that
  could cause row overlap with tight padding)
- drawMixedLine and drawWrappingLine now respect opts.lineHeight
  instead of hardcoded fontSize*1.2, falling back to 1.2 when
  lineHeight is not provided (backward compatible)
- Table cell draw calls pass lineHeight to drawWrappingLine
- Both AR and EN PDFs verified valid with logo embedded
2026-05-04 08:51:09 +00:00
riyadhafraa 9f29e7ff83 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: e7b31069-5ece-444c-84e7-6c559f2cfc4f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/ylDMZtF
Replit-Helium-Checkpoint-Created: true
2026-05-04 08:47:39 +00:00
riyadhafraa cbe7e4b748 PDF: match reference spec - column widths, padding, numbering, alignment (Task #366)
User provided detailed PDF formatting spec. Changes:
- Column widths: 6/36/39/19 → 8/30/42/20 to match reference proportions
- Attendees alignment: forced to right for RTL, left for LTR (independent
  of global font alignment setting) to always match reference layout
- Numbering format: "1- name" → "-1 name" (dash before number per reference)
- Cell padding: padX 4→8, padY 2→6 for more spacious cells
- Line height: fontSize*1.2 → fontSize*1.5 for better readability
- Removed stale column-width comment that referenced old proportions
- Both AR and EN PDFs verified valid with logo embedded
- Code review PASSED, e2e tests PASSED
2026-05-04 08:27:02 +00:00
riyadhafraa 515eddc195 PDF: match reference spec - column widths, padding, numbering, alignment (Task #366)
User provided detailed PDF formatting spec. Changes:
- Column widths: 6/36/39/19 → 8/30/42/20 to match reference proportions
- Attendees alignment: "center" → right-aligned (RTL direction-based)
- Numbering format: "1- name" → "-1 name" (dash before number per reference)
- Cell padding: padX 4→8, padY 2→6 for more spacious cells
- Line height: fontSize*1.2 → fontSize*1.5 for better readability
- Both AR and EN PDFs verified valid with logo embedded
- Code review PASSED, e2e tests PASSED
2026-05-04 08:25:14 +00:00
riyadhafraa 43ae5ff90d Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c2314a1f-ae0f-47c2-bf5c-1f075822b8d7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/ylDMZtF
Replit-Helium-Checkpoint-Created: true
2026-05-04 08:22:32 +00:00
riyadhafraa 7a71befb62 PDF: enlarge header logo and center attendees column (Task #364)
- Increased logoBoxSize multiplier from 1.8 to 2.8 so the header logo
  renders noticeably larger in the PDF output.
- Changed attendees column text alignment from direction-based (right for
  RTL) to "center" so attendee names are centered in their column.
- Both AR and EN PDFs verified: valid PDF output, logo embedded, correct
  alignment. Code review PASSED, e2e tests PASSED.
2026-05-04 08:12:02 +00:00
riyadhafraa e6a43b85bf Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c50a00a7-7b14-4d88-b65c-7ca92171a73e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/bEwHL7p
Replit-Helium-Checkpoint-Created: true
2026-05-04 08:09:03 +00:00
riyadhafraa af9d214e37 Fix PDF formatting: subheading groups, vertical centering, "#" header (Task #361)
- Changed attendee subheading formatting from inline join to grouped with
  newline separators between subheading sections. Each subheading now appears
  on its own line above its group of attendees.
- Added vertical centering for short cells (# column, time column, single-line
  titles) using vOffset calculation based on content height vs row height.
- "#" column header label already applied in pdf-labels.ts (from earlier edit).
- Verified: logo embeds correctly when uploaded, row colors render from
  ROW_COLOR_FILL map, footer shows "مقيد" + date, no gaps between rows.
- Code review PASSED, e2e tests PASSED (both AR and EN PDF generation).
2026-05-04 07:57:47 +00:00
riyadhafraa 57096e69a5 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 6a7f1a74-369f-4e38-9f13-96369912cc6c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/TFW8qXL
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:50:43 +00:00
riyadhafraa e802a93b14 Compact PDF table layout to match reference design (Task #359)
Changes to artifacts/api-server/src/lib/pdf-renderer.ts:

- Reduced cellPadX from 6 to 4 (horizontal cell padding)
- Reduced cellPadY from 3 to 2 (vertical cell padding)
- Tightened lineHeight multiplier from 1.25 to 1.2
- Removed +2 padding buffer from heightOfString measurement loop
- Removed +2 from drawWrappingLine return value
- Tightened drawMixedLine return value (1.25→1.2)
- Consolidated header spacing from two moveDown(0.2+0.4) to one moveDown(0.3)
- Tightened title Y offset multiplier from 1.25 to 1.2
- Fixed row height probe to detect script per-line (matching draw path)
  instead of per-cell, preventing measurement/draw mismatch in
  mixed Arabic/Latin content now that the +2 cushion is removed

Result: Table rows are compact with no visible gaps between them,
matching the user's reference PDF (attached_assets/rrr1_1777879598338.pdf).
Row colors, cell borders, and footer positioning are unchanged.
Both AR and EN PDFs generate successfully (200 status).
2026-05-04 07:35:52 +00:00
riyadhafraa 10679127e6 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 6f5061c3-9885-4173-9988-00e335acadc8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HhIDQsV
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:29:50 +00:00
riyadhafraa ec7bbb229d Task #357: Show attendee groups correctly in the upcoming meeting alert
The upcoming meeting alert's details panel was grouping attendees by
the `attendanceType` field, but in practice every attendee is stored
as type=internal regardless of their actual group. Users define groups
via subheading rows in the schedule editor (e.g. "الحضور الخارجي",
"الحضور الداخلي"), but the alert stripped subheadings and lumped
everyone under "داخلي".

Fix: Rewrote the grouping logic in DetailsPanel to walk through the
attendees array in order, using subheading rows as natural group
separators. Each subheading becomes a bold, clearly visible group
header (text-xs font-bold) instead of the old tiny 10px/60% opacity
labels. Person rows are listed under their preceding subheading.

Edge cases handled:
- Persons before any subheading: shown without a group header
- No subheadings at all: flat list without misleading "داخلي" label
- Empty subheading groups (heading with no persons): skipped
- Person count still counts only persons, not subheadings

Changed file:
- artifacts/tx-os/src/components/executive-meetings/upcoming-meeting-alert.tsx
  (DetailsPanel component, lines ~1744-1885)
2026-05-04 07:17:51 +00:00
riyadhafraa 17f1771659 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7d330ba0-531c-4dc4-a3bd-3ac086027533
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HhIDQsV
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:15:12 +00:00
riyadhafraa bcebd7c83e Task #355: Highlight all overlapping current meetings
Previously, `computeCurrentMeetingId` returned the first meeting whose
time range contained the current minute, so only one row ever got the
green highlight. When two meetings overlapped (e.g., 9:30–10:00 and
9:45–10:15), only the first was highlighted.

Changed `computeCurrentMeetingId` → `computeCurrentMeetingIds` to
return a `ReadonlySet<number>` of ALL matching meeting ids. Updated the
`useMemo` and the `isCurrent` prop on each row from
`currentMeetingId === m.id` to `currentMeetingIds.has(m.id)`.

A module-level `EMPTY_MEETING_SET` constant avoids allocating a new
empty Set on every tick when no meetings are in progress.

Changed file:
- artifacts/tx-os/src/pages/executive-meetings.tsx
  - Lines 369-396: new computeCurrentMeetingIds function
  - Line 1092: useMemo now uses computeCurrentMeetingIds
  - Line 2782: isCurrent uses .has() instead of ===
2026-05-04 07:05:40 +00:00
riyadhafraa acd1199d61 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: f68e6e2d-59e7-427a-8220-1cead24caf3b
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HhIDQsV
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:03:37 +00:00
riyadhafraa d310c6b8cb Task #353: Fix current-meeting highlight sticking after device sleep
The green highlight on the currently-in-progress meeting row would get
stuck when the user locked their iPad, switched apps, or the device
slept. The 60-second setInterval timer that drives `nowTick` is frozen
by the browser during background/sleep states. When the user returned,
the timer wouldn't fire immediately, leaving the highlight on the
old meeting.

Fix: Added a `visibilitychange` event listener alongside the existing
interval timer. When the document becomes visible again, it immediately
calls `setNowTick(Date.now())`, which triggers `computeCurrentMeetingId`
to re-evaluate via the existing useMemo dependency. The listener is
properly cleaned up in the effect's return function.

Changed file:
- artifacts/tx-os/src/pages/executive-meetings.tsx (lines 1065-1084)
2026-05-04 06:51:50 +00:00
riyadhafraa 7473e6f2ea Task #352: Make logo upload always visible for admin users
Previously, the logo upload field in Font Settings was hidden behind two
conditions: canEditGlobal AND scope === "global". Admin users had to
first switch the scope dropdown to "Global" before the logo upload
appeared, making it very hard to discover.

Changes:
- Frontend (executive-meetings.tsx): Removed `scope === "global"`
  condition from logo upload rendering — now shows whenever
  `canEditGlobal` is true (admin/executive_office_manager).
- Frontend: Save function now always sends `logoObjectPath` when
  `canEditGlobal` is true, regardless of selected scope.
- Backend (executive-meetings.ts): When an admin saves with user scope
  and includes logoObjectPath, the logo is written to the global row
  (upsert) in the same transaction. This preserves the global-only
  semantics while allowing admins to update the logo from any scope.
- When no global row exists, new row uses safe defaults (system font,
  14px, regular, start, #000000) instead of copying the user's prefs.
- Removed the 400 rejection for logoObjectPath on user-scope saves.
- Authorization preserved: only EM_ADMIN_ROLES can trigger logo writes.

Tested:
- API: PATCH with scope=user + logoObjectPath correctly updates global row
- E2E: Logo upload field visible for admin in user scope (confirmed)
- Code review: APPROVED (addressed comment about safe defaults)
- Pre-existing test failures unchanged (PDF font assertion, notification tests)
2026-05-04 06:44:02 +00:00
riyadhafraa bd939e6f6e Task #352: Make logo upload always visible for admin users
Previously, the logo upload field in Font Settings was hidden behind two
conditions: canEditGlobal AND scope === "global". Admin users had to
first switch the scope dropdown to "Global" before the logo upload
appeared, making it very hard to discover.

Changes:
- Frontend (executive-meetings.tsx): Removed `scope === "global"`
  condition from logo upload rendering — now shows whenever
  `canEditGlobal` is true (admin/executive_office_manager).
- Frontend: Save function now always sends `logoObjectPath` when
  `canEditGlobal` is true, regardless of selected scope.
- Backend (executive-meetings.ts): When an admin saves with user scope
  and includes logoObjectPath, the logo is written to the global row
  (upsert) in the same transaction. This preserves the global-only
  semantics while allowing admins to update the logo from any scope.
- When no global row exists, new row uses safe defaults (system font,
  14px, regular, start, #000000) instead of copying the user's prefs.
- Removed the 400 rejection for logoObjectPath on user-scope saves.
- Authorization preserved: only EM_ADMIN_ROLES can trigger logo writes.

Tested:
- API: PATCH with scope=user + logoObjectPath correctly updates global row
- E2E: Logo upload field visible for admin in user scope (confirmed)
- Code review: APPROVED (addressed comment about safe defaults)
- Pre-existing test failures unchanged (PDF font assertion, notification tests)
2026-05-04 06:42:38 +00:00