Skip to main content

Frontend

The Costs module uses the Partial Views pattern to keep the global index and costs section in the project show modular and reusable.

File Structure

resources/views/costs/
├── index.blade.php
├── index/
│ ├── _header.blade.php
│ ├── _stats-cards.blade.php
│ ├── _filters.blade.php
│ ├── _table.blade.php
│ ├── _empty-state.blade.php
│ ├── filters/
│ │ ├── _search.blade.php
│ │ ├── _type.blade.php
│ │ ├── _currency.blade.php
│ │ ├── _recurring.blade.php
│ │ ├── _date-range.blade.php
│ │ └── _actions.blade.php
│ ├── stats-cards/
│ │ ├── _total-all-time.blade.php
│ │ ├── _this-month.blade.php
│ │ ├── _this-year.blade.php
│ │ └── _recurring-monthly.blade.php
│ └── cost-table/
│ ├── _header.blade.php
│ ├── _row.blade.php
│ ├── _row-project.blade.php
│ ├── _row-amount.blade.php
│ ├── _row-type.blade.php
│ ├── _row-recurring.blade.php
│ ├── _row-paid-at.blade.php
│ ├── _row-receipt.blade.php
│ └── _row-actions.blade.php
└── partials/
├── _cost-table.blade.php
├── _modal-form.blade.php
├── _form-fields.blade.php
├── _upload-receipt-modal.blade.php
└── cost-table/
├── _header.blade.php
├── _row.blade.php
├── _row-amount.blade.php
├── _row-type.blade.php
├── _row-recurring.blade.php
├── _row-paid-at.blade.php
├── _row-receipt.blade.php
└── _row-actions.blade.php

resources/js/components/
├── costModal.js
└── receiptUploadModal.js

Frontend Pattern

Orchestrator Views

The costs/index.blade.php view acts as an orchestrator:

  • includes header, statistics, filters
  • chooses table or empty-state based on results

Reusable Partials

The module separates the two UI contexts:

  • Global costs index: partials in costs/index/*
  • Costs tab of the project show: partials in costs/partials/*

costs/partials/_cost-table.blade.php is used in the project show (projects/show/_tab-costs.blade.php).

Cost Modal

Managed in:

  • view: costs/partials/_modal-form.blade.php
  • component: resources/js/components/costModal.js

Flow:

  • open create with open-cost-modal event
  • open edit with edit-cost event (record payload)
  • submit to route costs.store / costs.update

The component manages open, isEdit, costId, and formData state.

Upload Receipt Modal

Managed in:

  • view: costs/partials/_upload-receipt-modal.blade.php
  • component: resources/js/components/receiptUploadModal.js

Flow:

  • open with upload-receipt event (passes costId)
  • dynamic uploadUrl construction (/projects/{projectId}/costs/{costId}/receipt)
  • receipt file upload

Cost Table Actions (project show)

In costs/partials/cost-table/_row-receipt.blade.php the following are available:

  • receipt preview
  • receipt download
  • receipt delete
  • receipt upload

Actions use receipts.* routes.

In costs/partials/cost-table/_row-actions.blade.php the following are available:

  • edit cost (edit-cost event with payload from toFormPayload())
  • delete cost (costs.destroy)

Global JS Wiring

Component registration in resources/js/app.js:

  • window.costModal = costModal
  • window.receiptUploadModal = receiptUploadModal

The global data-action listener in app.js dispatches the custom events used by the modals.

Internationalization

Costs frontend strings use:

  • lang/*/costs.php
  • lang/*/receipts.php
  • lang/*/ui.php

Dark Mode

The module supports dark mode via Tailwind dark:* classes, consistent with the application layout.