Skip to content

Conversation

@pxlrbt
Copy link
Contributor

@pxlrbt pxlrbt commented Dec 21, 2025

image image

Summary by CodeRabbit

  • New Features

    • Unread ticket badge and visual unread styling in the chat widget.
    • Automatic tracking of last-viewed messages with debounced updates to reduce server calls and periodic unread-count polling.
  • Bug Fixes / Improvements

    • More accurate unread state handling so ticket lists and notifications reflect what the user has actually seen.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

Walkthrough

Adds per-user "last seen" tracking for tickets: a new TicketLastSeen model, migration, factory, service methods, API endpoints to mark seen and fetch unread counts, frontend debounce and unread-badge UI, trait updates on Ticket, and corresponding tests and fixtures.

Changes

Cohort / File(s) Summary
Database Layer
database/factories/TicketLastSeenFactory.php, database/migrations/2025_12_21_213448_rename_ticket_notifications_to_ticket_last_seen.php, src/Models/TicketLastSeen.php
New Eloquent model TicketLastSeen, factory, and migration that renames ticket_notificationsticket_last_seen and adds nullable last_seen_activity_id and last_notified_activity_id FK columns (referencing ticket_activities).
API Endpoints & Routes
src/Http/Controllers/Api/UnreadTicketCountController.php, src/Http/Controllers/Api/MarkTicketSeenController.php, routes/api.php
New controllers: unread-count (GET) and mark-seen (POST). Unread controller computes per-user unread tickets using ticket_last_seen; mark-seen validates, authorizes, verifies activity ownership, and persists last-seen state. Routes registered under the tickets API group.
Model Layer & Traits
src/Models/Ticket.php, src/Models/Concerns/InteractsWithLastSeen.php
Ticket now uses InteractsWithLastSeen (replacing InteractsWithNotifications). New trait provides submitter and ticketLastSeen relations, recipient collection, shouldSendNotification(), and hasUnreadMessagesFor() logic.
Service & Data Mapping
src/Services/TicketActivityService.php, src/Http/DataMappers/TicketMapper.php
Service renamed/rewired: getLastNotification()getLastSeen() returning ?TicketLastSeen; added markActivitySeen() and markNotificationSent(); markNotificationUpdated() retained as deprecated wrapper. TicketMapper accepts optional user and exposes is_unread.
Frontend Components
resources/js/components/chat-component.js
Adds 2s debounce for marking activities seen: markSeenDebounceTimer, markSeenDebounceMs, debouncedMarkSeen(), markTicketSeen(); flushes pending mark on disconnect.
Frontend Widgets & Styling
resources/js/components/chat-widget.js, resources/js/components/chat-widget/list.js, resources/css/chat-widget.css
Chat widget fetches unread count (poll every 10s), updates a data-unread-badge element, and list items get ticket--unread class. CSS provides .ticket--unread styles and layout adjustments.
Notifications
src/Notifications/TicketNotification.php
Notification flow now records last-notified activity via markNotificationSent() and sources lastNotificationDate from TicketLastSeen relations.
Tests: Model, Service & Feature
tests/Unit/Services/TicketActivityServiceTest.php, tests/Unit/Notifications/TicketNotificationTest.php, tests/Feature/Api/MarkTicketSeenControllerTest.php, tests/Unit/TicketPluginTest.php, tests/Feature/ObserverInheritanceTest.php
Tests updated to use TicketLastSeen and getLastSeen() semantics; new feature tests for mark-seen cover validation, auth, ownership, and idempotent updates.
Test Fixtures & Minor Test Changes
tests/Fixtures/Models/CustomTicketLastSeen.php, tests/Feature/Filament/Resources/Tickets/Actions/CreateLinkedTicketActionTest.php
New fixture CustomTicketLastSeen. Two tests simplified to use plain message strings instead of tiptap document payloads.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant ChatComponent
    participant ChatWidget
    participant API as Server
    participant DB

    User->>Browser: Open chat widget
    Browser->>ChatWidget: init + render
    ChatWidget->>API: GET /padmission-tickets/api/tickets/unread-count
    API->>DB: query unread tickets using ticket_last_seen
    DB-->>API: unread count
    API-->>ChatWidget: return count
    ChatWidget->>Browser: display unread badge
    ChatWidget->>ChatWidget: start polling (10s)

    Note over Browser,ChatComponent: user scrolls / views messages
    ChatComponent->>ChatComponent: IntersectionObserver detects activity
    ChatComponent->>ChatComponent: schedule debouncedMarkSeen (2s)
    ChatComponent->>API: POST /padmission-tickets/api/tickets/{id}/mark-seen
    API->>API: validate, authorize, verify activity belongs to ticket
    API->>DB: create or update ticket_last_seen (last_seen_activity_id)
    DB-->>API: persist
    API-->>ChatComponent: success
    ChatComponent->>ChatComponent: clear debounce timer

    User->>Browser: close widget
    ChatComponent->>ChatComponent: flush pending debounce
    ChatComponent->>API: final POST mark-seen
    API->>DB: persist final last_seen_activity_id
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Focus review areas:
    • src/Services/TicketActivityService.php — method renames, semantics for last_seen vs last_notified, DB updates.
    • src/Http/Controllers/Api/UnreadTicketCountController.php — complex query logic and authorization/scope handling.
    • src/Http/Controllers/Api/MarkTicketSeenController.php — validation, scope bypassing, activity ownership checks.
    • Frontend JS — debounce lifecycle, flush-on-disconnect behavior, and polling interactions.
    • Migration — verify data rename/migration preserves existing state and FK correctness.
    • Tests/Fixtures — ensure all updated tests/fixtures align with new model and relationships.

Poem

🐰
I hopped through rows of tickets bright,
Marked each seen with gentle light,
A two-second pause, then off I sped,
Unread badges bob above my head,
A rabbit's cheer for last-seen spread!


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Free

📥 Commits

Reviewing files that changed from the base of the PR and between e9134ac and 93efaff.

📒 Files selected for processing (1)
  • resources/css/chat-widget.css (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • resources/css/chat-widget.css

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

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

@pxlrbt pxlrbt requested a review from iAmKevinMcKee December 21, 2025 21:34
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