Frontend
The Documents module uses the Partial Views pattern to separate the global index and the documents tab of the project show, with a dedicated Alpine modal for upload/edit.
File Structure
resources/views/documents/
├── 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
│ │ ├── _labels.blade.php
│ │ └── _actions.blade.php
│ ├── stats-cards/
│ │ ├── _total.blade.php
│ │ └── _this-month.blade.php
│ └── document-table/
│ ├── _header.blade.php
│ ├── _row.blade.php
│ ├── _row-project.blade.php
│ ├── _row-name.blade.php
│ ├── _row-labels.blade.php
│ ├── _row-uploaded-at.blade.php
│ └── _row-actions.blade.php
└── partials/
├── _document-table.blade.php
├── _modal.blade.php
├── _form-fields.blade.php
├── _file-upload.blade.php
└── document-table/
├── _header.blade.php
├── _row.blade.php
├── _row-name.blade.php
├── _row-labels.blade.php
├── _row-uploaded-at.blade.php
├── _row-size.blade.php
└── _row-actions.blade.php
resources/js/components/
└── documentModal.js
Frontend Pattern
Orchestrator Views
The documents/index.blade.php view acts as an orchestrator:
- includes header, statistics, and filters
- chooses table or empty-state based on results
In the project detail, the documents tab uses projects/show/_tab-documents.blade.php and includes the reusable table documents/partials/_document-table.blade.php.
Reusable Partials
The module separates the two UI contexts:
- Global documents index: partials in
documents/index/* - Documents tab of the project show: partials in
documents/partials/*
Modal (Alpine.js)
Document Modal
Managed in:
- view:
documents/partials/_modal.blade.php - component:
resources/js/components/documentModal.js
Flow:
- open create with
open-document-modalevent - open edit with
edit-documentevent (record payload) - submit to route
documents.store/documents.update
Key behaviors:
- the file upload block is visible only in create (
x-show="!isEdit") - the submit button in create requires both
nameand a selected file - in edit, only metadata/labels are updated
- supports closing with
Escand click outside modal
Form Fields
documents/partials/_form-fields.blade.php handles:
- document name (
name) - multiple labels (
label_ids[]) - notes (
notes)
documents/partials/_file-upload.blade.php handles file input and selected filename display. The documents.file_requirements help text under the dropzone lists all accepted formats (PDF, JPG, JPEG, PNG, WEBP, ZIP, 7Z, RAR, DOC, DOCX, XLS, XLSX) and the real 30MB limit, in all 13 languages — it previously only mentioned PDF/JPG/JPEG/PNG and a stale 10MB figure.
No accept attribute is set on the <input type="file"> — format restriction happens entirely server-side via the request validation mimes: rule, the input itself accepts any file the OS picker offers.
Table Actions
Global index (documents/index/document-table/_row-actions.blade.php)
- view project
- document preview
- document download
Project tab (documents/partials/document-table/_row-actions.blade.php)
- preview
- download
- edit (
edit-documentevent with payload fromtoFormPayload()) - delete (with
data-confirm)
Global JS Wiring
Component registration in resources/js/app.js:
window.documentModal = documentModal
The global data-action listener in app.js dispatches the custom events used by the modal.
Internationalization
Documents frontend strings use:
lang/*/documents.phplang/*/ui.php
Label badge rendering uses the x-documents.label-badge Blade component.
Dark Mode
The module supports dark mode via Tailwind dark:* classes, consistent with the application layout.