Skip to content

feat: meetings page — outcome filter, lead links & detail redesign - #223

Merged
hdmGOAT merged 3 commits into
developmentfrom
feat/meetings-page-enhancements
Jul 6, 2026
Merged

feat: meetings page — outcome filter, lead links & detail redesign#223
hdmGOAT merged 3 commits into
developmentfrom
feat/meetings-page-enhancements

Conversation

@potakaaa

@potakaaa potakaaa commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a free-text outcome filter to the /meetings list query and panel.
  • Makes the lead name a clickable link to the lead detail page from the meeting list, with a keyboard double-navigation fix.
  • Audit/polish pass on the meetings list surface.
  • Full redesign of the meeting detail page: header hero, two-column layout, attendee avatar chips, all fields rendered with empty states, and a Join-meeting button. Adds video/link/clock icons to the shared Icon component to support the new layout.

Verification

  • bun run check: green (0 errors; 1 pre-existing warning in leads/[id]/+page.svelte, unrelated to this change)
  • bun run lint: green
  • meetings.spec.ts: 22/22 passing (via bun run test:unit:ci, full suite 342 passed | 107 skipped)
  • DB/e2e gates are pre-accepted repo-wide known-gaps (shared Playwright auth fixture not yet available — see process/features/auth/backlog/e2e-auth-bootstrap_NOTE_01-07-26.md)

Test plan

  • bun run check — 0 errors
  • bun run lint — clean
  • bun run test:unit:ci — meetings.spec.ts 22/22, full suite green
  • Manual click-through of /meetings outcome filter and lead link (recommended before merge)
  • Manual click-through of meeting detail page redesign (recommended before merge)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an outcome filter on the Meetings page to quickly narrow results by text, with search preserved as you move through pages.
  • Bug Fixes

    • Made lead names in cross-lead meeting cards open the lead details page without also opening the meeting card.
    • Improved meeting detail and card rendering for better empty-state handling, clearer date/time display, and more polished layout.

potakaaa and others added 3 commits July 6, 2026 10:27
Adds a free-text outcome filter to the meetings list query and panel,
and makes the lead name a clickable link to the lead detail page
(with a keyboard double-nav fix). Updates meetings tests accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebuilds the meeting detail page with a header hero, two-column
layout, attendee avatar chips, empty states for all fields, and a
Join-meeting button. Adds video/link/clock icons to the shared Icon
component to support the new layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Documents the plan and outcome for the meetings-page outcome filter,
lead-link, and detail-page redesign work.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
veent-crm Ready Ready Preview, Comment Jul 6, 2026 2:32am

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds an outcome free-text filter to meetings listing (DB query, route loader, and toolbar UI), makes lead names in meeting cards clickable links to lead pages without triggering card navigation, adds new icon definitions, redesigns the meeting detail page layout, includes related unit tests, and adds process plan/report documentation.

Changes

Process Documentation

Layer / File(s) Summary
Feature plan
process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_PLAN_06-07-26.md
Documents workstreams, checklist, acceptance criteria, and verification strategy for outcome filtering and lead-link polish.
Execution report
process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_REPORT_06-07-26.md
Records completed workstreams, test gate results, test infra gaps, and closeout status.

Meetings Outcome Filter and Page Polish

Layer / File(s) Summary
Outcome filter contract and DB query
src/lib/server/db/meetings.ts
Adds optional outcome to MeetingListFilters/parseMeetingFilterParams, trims/normalizes the query param, and applies an ILIKE condition shared by results and count queries.
Route loader wiring
src/routes/meetings/+page.server.ts
Passes outcome and sortDir into the filters object built during page load.
Toolbar input and lead link
src/lib/components/meetings/MeetingsPanel.svelte
Adds an outcome text input wired to setFilter/navigate with a loading spinner, and converts lead name text into a clickable link to /leads/:id that stops event propagation.
New icon definitions
src/lib/components/shared/Icon.svelte
Adds trash, video, link, and clock entries to ICONS, expanding IconName.
Meeting detail page redesign
src/routes/meetings/[id]/+page.svelte
Replaces date formatting helpers with formatDay/formatTime/relativeDay, and restructures the layout into a hero header plus rail sections for outcome, notes, host, attendees, and meeting link.
Outcome filter and parser tests
src/tests/meetings-filters.spec.ts, src/tests/meetings.spec.ts
Extends seeding/helpers for outcome, adds case-insensitive substring match test, and adds parser trimming/decoding unit tests.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

  • potakaaa/veent-crm#112: Builds on the meetings CRUD/database foundations extended by the new outcome filter.
  • potakaaa/veent-crm#157: Extends the same parseMeetingFilterParams/listMeetingsPaginated filter infrastructure and toolbar wiring.
  • potakaaa/veent-crm#165: Shares overlapping modifications to the meeting filters/query plumbing in src/lib/server/db/meetings.ts.

Poem

A rabbit hopped through meetings' halls,
Found "outcome" hiding behind the walls,
Now leads click through with just one tap,
New icons sparkle on the map,
Thump thump — the plan is now complete! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely captures the main meetings page changes: outcome filtering, lead links, and the detail-page redesign.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/meetings-page-enhancements

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/routes/meetings/[id]/+page.svelte (1)

22-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a time-only formatter here. replace(/^.*?,\s*/, '') still couples formatTime to the exact punctuation/layout returned by formatDate; a dedicated formatTime helper or toLocaleTimeString would be clearer and avoid string slicing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/meetings/`[id]/+page.svelte around lines 22 - 24, `formatTime` is
still depending on `formatDate` output shape and stripping the date with string
replacement; update the `formatTime` helper in the meetings page to use a
time-only formatter directly, such as a dedicated time helper or
`toLocaleTimeString`, and remove the `replace(/^.*?,\s*/, '')` slicing so the
function no longer relies on punctuation from `formatDate`.
src/lib/server/db/meetings.ts (1)

218-221: 🚀 Performance & Scalability | 🔵 Trivial

Leading-wildcard ILIKE can't use a standard B-tree index.

%...% substring matching forces a sequential scan on crmMeetings.outcome as the table grows. If this filter is expected to see heavy usage on a large table, consider a pg_trgm GIN index (CREATE INDEX ... USING gin (outcome gin_trgm_ops)) to keep it performant.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/server/db/meetings.ts` around lines 218 - 221, The outcome filter in
the meetings query uses a leading-wildcard ILIKE on crmMeetings.outcome, which
will not benefit from a normal B-tree index. Update the database
schema/migration to add a pg_trgm GIN index on the outcome column used by this
filter, and keep the existing meetings query logic in
src/lib/server/db/meetings.ts unchanged so filters.outcome still works while
remaining performant on large tables.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_PLAN_06-07-26.md`:
- Around line 255-259: The fenced example blocks in this markdown plan are
missing language identifiers, which triggers markdownlint and hurts readability.
Update each affected fenced block to include an appropriate tag such as text or
bash, and apply the same change consistently to the other referenced fenced
examples. Use the existing markdown examples around the TDD stub snippets in the
meetings page plan to locate and update them.
- Around line 2-12: The plan currently uses mixed date conventions, so update
the date fields in this document and the paired report to a single consistent
format. Keep the same style across both files by normalizing the date value in
the frontmatter and any related headings or references, using the existing
date-related fields as the anchor for the change.

In `@src/routes/meetings/`[id]/+page.svelte:
- Around line 136-146: Restrict the meeting URL handling in the meeting schema
and the meeting detail page so only http and https links are allowed. Update the
validation for meetingUrl, and in the +page.svelte link rendering for
meeting.meetingUrl, ensure non-http(s) schemes are rejected or filtered out
before binding to href. Use the meeting schema and the meeting.meetingUrl
rendering block as the main places to fix this.

---

Nitpick comments:
In `@src/lib/server/db/meetings.ts`:
- Around line 218-221: The outcome filter in the meetings query uses a
leading-wildcard ILIKE on crmMeetings.outcome, which will not benefit from a
normal B-tree index. Update the database schema/migration to add a pg_trgm GIN
index on the outcome column used by this filter, and keep the existing meetings
query logic in src/lib/server/db/meetings.ts unchanged so filters.outcome still
works while remaining performant on large tables.

In `@src/routes/meetings/`[id]/+page.svelte:
- Around line 22-24: `formatTime` is still depending on `formatDate` output
shape and stripping the date with string replacement; update the `formatTime`
helper in the meetings page to use a time-only formatter directly, such as a
dedicated time helper or `toLocaleTimeString`, and remove the
`replace(/^.*?,\s*/, '')` slicing so the function no longer relies on
punctuation from `formatDate`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cd12f8f3-b008-45ea-93e7-6b80488f0d34

📥 Commits

Reviewing files that changed from the base of the PR and between 1b27c43 and f58246e.

📒 Files selected for processing (9)
  • process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_PLAN_06-07-26.md
  • process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_REPORT_06-07-26.md
  • src/lib/components/meetings/MeetingsPanel.svelte
  • src/lib/components/shared/Icon.svelte
  • src/lib/server/db/meetings.ts
  • src/routes/meetings/+page.server.ts
  • src/routes/meetings/[id]/+page.svelte
  • src/tests/meetings-filters.spec.ts
  • src/tests/meetings.spec.ts

Comment on lines +2 to +12
name: plan:meetings-page-gaps-polish
description: "Add outcome free-text filter, clickable lead-name link, and small audit/polish fixes to the existing /meetings page"
date: 06-07-26
feature: meetings
---

# Meetings Page — Gaps + Audit/Polish

**Date**: 06-07-26
**Status**: DRAFT — pending VALIDATE
**Complexity**: SIMPLE (single feature area, ~4 files touched, no schema/auth/API-contract changes, one net-new filter param + one UI link + a review pass).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the plan and the paired report, then inspect the relevant lines and any nearby date usage.
plan="process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_PLAN_06-07-26.md"
report_dir="process/features/meetings/active/meetings-page-gaps-polish_06-07-26"

printf '\n== Plan file ==\n'
wc -l "$plan"
cat -n "$plan" | sed -n '1,40p'

printf '\n== Nearby feature files mentioning dates ==\n'
rg -n --no-heading -S '06-07-26|2026-07-06|06/07/26|07-06-26|date:' "$report_dir" || true

printf '\n== File list in feature task folder ==\n'
find "$report_dir" -maxdepth 1 -type f | sort

Repository: potakaaa/veent-crm

Length of output: 5777


Normalize the date format. The plan currently mixes 06-07-26 and 2026-07-06, while the paired report uses ISO 2026-07-06; pick one convention and keep both files consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_PLAN_06-07-26.md`
around lines 2 - 12, The plan currently uses mixed date conventions, so update
the date fields in this document and the paired report to a single consistent
format. Keep the same style across both files by normalizing the date value in
the frontmatter and any related headings or references, using the existing
date-related fields as the anchor for the change.

Comment on lines +255 to +259
```
test("should treat empty/whitespace outcome param as undefined", () => {
throw new Error("NOT IMPLEMENTED — TDD stub: parseMeetingFilterParams empty/whitespace outcome -> undefined")
})
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add language identifiers to the fenced examples.

markdownlint already flags these blocks. Tag them (text, bash, etc.) so the docs stay lint-clean and easier to scan.

Suggested fix
-```
+```text
 test("should treat empty/whitespace outcome param as undefined", () => {
   throw new Error("NOT IMPLEMENTED — TDD stub: parseMeetingFilterParams empty/whitespace outcome -> undefined")
 })
-```
+```

Apply the same change to the other fenced blocks.

Also applies to: 261-265, 297-300

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 255-255: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@process/features/meetings/active/meetings-page-gaps-polish_06-07-26/meetings-page-gaps-polish_PLAN_06-07-26.md`
around lines 255 - 259, The fenced example blocks in this markdown plan are
missing language identifiers, which triggers markdownlint and hurts readability.
Update each affected fenced block to include an appropriate tag such as text or
bash, and apply the same change consistently to the other referenced fenced
examples. Use the existing markdown examples around the TDD stub snippets in the
meetings page plan to locate and update them.

Source: Linters/SAST tools

Comment on lines +136 to +146
{#if meeting.meetingUrl}
<a
href={meeting.meetingUrl}
target="_blank"
rel="noopener noreferrer"
class="{buttonVariants({ variant: 'default' })} gap-1.5"
aria-label="Join meeting (opens in a new tab)"
>
<Icon name="video" size={15} stroke={2} /> Join meeting
</a>
{/if}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether meetingUrl is validated to http(s) anywhere in the form/API layer
rg -n -C3 'meetingUrl' src/lib/components/meetings/MeetingFormModal.svelte src/routes/api 2>/dev/null

Repository: potakaaa/veent-crm

Length of output: 4511


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate validation/schema definitions and the page render path for meetingUrl
rg -n -C3 'meetingUrl|createMeeting|updateMeeting|zod|url|scheme|http:|https:' src/lib src/routes src | sed -n '1,240p'

# Inspect the meeting detail page around the links
sed -n '120,240p' src/routes/meetings/[id]/+page.svelte

# Inspect the form modal around the meeting URL field
sed -n '1,240p' src/lib/components/meetings/MeetingFormModal.svelte

# Inspect API routes that accept meetingUrl
sed -n '1,200p' src/routes/api/meetings/+server.ts
sed -n '1,200p' src/routes/api/meetings/[id]/+server.ts

Repository: potakaaa/veent-crm

Length of output: 30646


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the meeting schemas and any URL-related helpers
sed -n '1,260p' src/lib/zod/schemas.ts

# If there are reusable URL validators, list them
rg -n -C3 'url\(|http:|https:|scheme|javascript|zod.*url|meetingUrl' src/lib/zod src/lib/server src/routes | sed -n '1,240p'

Repository: potakaaa/veent-crm

Length of output: 25586


Restrict meetingUrl to http(s) URLs. meetingUrl is already accepted as a URL in the meeting schema, but that still allows non-HTTP schemes. Since it’s bound directly to both href attributes, a stored javascript: URL can still execute when opened. Allow only http:/https: in the schema or before rendering.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/meetings/`[id]/+page.svelte around lines 136 - 146, Restrict the
meeting URL handling in the meeting schema and the meeting detail page so only
http and https links are allowed. Update the validation for meetingUrl, and in
the +page.svelte link rendering for meeting.meetingUrl, ensure non-http(s)
schemes are rejected or filtered out before binding to href. Use the meeting
schema and the meeting.meetingUrl rendering block as the main places to fix
this.

@hdmGOAT
hdmGOAT merged commit 39fdf81 into development Jul 6, 2026
5 checks passed
@hdmGOAT
hdmGOAT deleted the feat/meetings-page-enhancements branch July 10, 2026 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants