Skip to content

[IP-221]: client detail view#577

Draft
nielsdrost7 wants to merge 9 commits into
InvoicePlane:developfrom
underdogg-forks:feature/221-client-detail-view
Draft

[IP-221]: client detail view#577
nielsdrost7 wants to merge 9 commits into
InvoicePlane:developfrom
underdogg-forks:feature/221-client-detail-view

Conversation

@nielsdrost7

Copy link
Copy Markdown
Collaborator

Closes #221
Closes #217
Closes #218

What was missing

Clients had no detail/view page. The list was the only entry point, with only Edit and Delete actions.

Changes

ViewRelation page (Pages/ViewRelation.php)

Infolist on RelationResource

9-field client summary in a 3-column grid:
company_name, trading_name, relation_number, relation_type (badge), relation_status (badge), registered_at, coc_number, vat_number, currency_code

Five RelationManagers (tabs)

Manager Relationship Columns Extra
InvoicesRelationManager invoices (customer_id) number, status, dates, total Create Invoice header action
QuotesRelationManager quotes (prospect_id) number, status, dates, total Create Quote header action
ExpensesRelationManager expenses (vendor_id) number, date, description, amount
TasksRelationManager tasks (customer_id) number, name, status, due, price
ProjectsRelationManager projects (customer_id) number, name, status, start, end

All relationships were already defined on the Relation model — no model changes needed.

RelationsTable

Closes #191
Closes #192

Summary by CodeRabbit

  • New Features

    • Added a detailed client/relation view page with quick actions to create invoices or quotes.
    • Expanded relation pages to show linked invoices, quotes, expenses, tasks, and projects in tabbed lists.
    • Added richer relation details, including status and type display.
  • Bug Fixes

    • Prevented deletion of clients/relations that still have linked records.
    • Improved delete feedback with a clear error message when removal isn’t allowed.
  • Tests

    • Added coverage for viewing relations and for delete behavior with and without linked records.

Update 2026-07-03 (session continuation)

Issues covered by this PR: #221, #217, #218, #219, #220, #29, #191, #192.

claude and others added 9 commits June 14, 2026 05:05
…ion managers

New ViewRelation page (Modules/Clients/.../Pages/ViewRelation.php):
- Extends Filament\Resources\Pages\ViewRecord
- Header actions: Create Invoice (InvoicePlane#217), Create Quote (InvoicePlane#218), Edit
- Registered as 'view' => ViewRelation::route('/{record}') in RelationResource

Infolist on RelationResource (client summary section):
- 9-field 3-column grid: company_name, trading_name, relation_number,
  relation_type (badge), relation_status (badge), registered_at,
  coc_number, vat_number, currency_code

Five RelationManagers (tabs on the view page):
- InvoicesRelationManager: invoice list + Create Invoice header action
- QuotesRelationManager:   quote list + Create Quote header action
- ExpensesRelationManager: expense list (vendor expenses for this client)
- TasksRelationManager:    task list
- ProjectsRelationManager: project list

All five relation managers use existing hasMany relationships already
defined on the Relation model (invoices, quotes, expenses, tasks, projects).

RelationsTable: add ViewAction row button + import Action/ViewAction/
InvoiceResource/QuoteResource + Create Invoice and Create Quote row actions
(the visible entry points from the client list for InvoicePlane#191 and InvoicePlane#192).

Fixes InvoicePlane#221
Fixes InvoicePlane#217
Fixes InvoicePlane#218

https://claude.ai/code/session_01L9apN3AW7b5h7ypmBA5pUg
…ns to client detail page

Add EditAction to the ViewRelation header (opens edit form). Add conditional
DeleteAction that is hidden when the client has any linked invoices, quotes,
expenses, tasks, or projects (InvoicePlane#220). Service-layer guard in RelationService
throws RelationHasLinkedRecordsException as a backstop for direct API calls.

https://claude.ai/code/session_01L9apN3AW7b5h7ypmBA5pUg
… tests for client detail view page

Tests verify:
- ViewRelation page renders without errors
- RelationService::deleteRelation() throws RelationHasLinkedRecordsException
  when the client has linked invoices or quotes
- Clients without linked records can be deleted successfully

https://claude.ai/code/session_01L9apN3AW7b5h7ypmBA5pUg
…fill customer from URL

- Register 'create' => CreateInvoice::route('/create') in InvoiceResource::getPages()
  so the create form is accessible via a URL (was defined but unreachable)
- Override mount() in CreateInvoice to read ?customer_id= query param and
  pre-fill the form via $this->form->fill(['customer_id' => ...])
- Override mutateFormDataBeforeCreate() to ensure the query param survives
  form submission even if Livewire rehydrates the form state

The row-level "Create Invoice" button on the client list (RelationsTable)
is wired up in the InvoicePlane#221 client-detail-view PR, which adds the full suite
of client actions.

Fixes InvoicePlane#191

https://claude.ai/code/session_01L9apN3AW7b5h7ypmBA5pUg
…ll customer from URL

- Register 'create' => CreateQuote::route('/create') in QuoteResource::getPages()
  so the create form is accessible via a URL (was defined but unreachable)
- Override mount() in CreateQuote to read ?customer_id= query param and
  pre-fill the form via $this->form->fill(['customer_id' => ...])
- Override mutateFormDataBeforeCreate() to ensure the query param survives
  form submission even if Livewire rehydrates the form state

The row-level "Create Quote" button on the client list (RelationsTable)
is wired up in the InvoicePlane#221 client-detail-view PR.

Fixes InvoicePlane#192

https://claude.ai/code/session_01L9apN3AW7b5h7ypmBA5pUg
…mer_id query param

The quote form's client field is prospect_id; filling customer_id left
the pre-selection silently empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…): gate client list row actions and guard delete

Create Invoice is visible only for customer-type relations with the
create-invoices permission; Create Quote for any type with the
create-quotes permission. The list DeleteAction is hidden when the
relation has linked records and surfaces a notification instead of a
500 if the service guard trips anyway.

Extract Relation::hasLinkedRecords() and reuse it in the service guard,
ViewRelation, and the table; the shared check now also covers payments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…): cover client list row actions and prefill

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@InvoicePlane InvoicePlane deleted a comment from coderabbitai Bot Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment