{{-- Projects listing — docs/wireframes-v12/project-management.html, content region for content region. v12's order, top to bottom: the five-tile stat strip in a `.grid-5`, a right-aligned "Add New Project" row, then ONE card that carries the `.filter-bar` and the `.data-table` — the filters are the card's own header strip (border-bottom), not a card of their own. That is the shape every v12 management page uses (unit-inventory, customer-management, user-management, broker-management all draw it), so it is the shape here. DataTables still drives the table. Its own search box stays out of the dom string because the wireframe's search input in the filter bar is the one the user sees; the wiring below feeds the plugin from it. Everything the JS addresses — the ids, the table id, the preXhr filter names — is unchanged from CR-1; only the class names on the controls moved to v12's `.search-input` / `.filter-select`. The table markup and its configuration both come from the html builder, so the column list exists in exactly one place: ProjectsDataTable::getColumns(). --- CR-2b (spec §12). Page title: v12's header reads "Project Management" and nothing else, so the old `@section('subtitle')` line ("All projects across the company") is dropped rather than folded in — the wireframe's index header carries no second line and the title already says what the screen is. --}} @extends('layouts.app') @section('title', __('projects.title')) @section('breadcrumbs') @endsection @section('content') {{-- Stat strip. v12 tints the icon chip per tile and the number with the matching text colour, which it writes inline as `style="color: var(--success)"`; those are classes here. Three of the four are the wireframe's own utilities. `.text-info` is not: style.css declares six `.text-*` rules and that is not one of them, so the name falls through to Metronic's purple `--bs-info`. The app-additions tail writes it to v12's cyan `--info`; see block 12b there before assuming any `.text-*` name is safe. --}}
@foreach ([ 'total' => ['icon' => 'fa-city', 'tone' => 'blue', 'value' => ''], 'ongoing' => ['icon' => 'fa-spinner', 'tone' => 'green', 'value' => 'text-success'], 'planning' => ['icon' => 'fa-clipboard-list', 'tone' => 'blue', 'value' => 'text-primary'], 'completed' => ['icon' => 'fa-circle-check', 'tone' => 'cyan', 'value' => 'text-info'], 'on_hold' => ['icon' => 'fa-pause-circle', 'tone' => 'yellow', 'value' => 'text-warning'], ] as $key => $tile)
{{ $stats[$key] ?? 0 }}
{{ __('projects.stats.'.$key) }}
@endforeach
{{-- v12 puts the primary action on its own row above the listing card, at the right edge, and leaves an empty div on the left. The empty div is kept: `.justify-between` needs two children to push the button right, and the button is gated, so without it a Sales user would get a bare row rather than no row at all. --}} @can('create', \App\Models\Project::class)
{{ __('projects.add_button') }}
@endcan
{{-- The filter bar IS the card's header strip in v12. It is a
here only so Enter does not reload the page; `.filter-bar` is the flex row, so the form element carries it directly. v12 labels none of these controls — a placeholder and an option list are all it draws. The visually-hidden labels are ours and are not a visual change: a select whose only name is its first option is unusable with a screen reader. --}}
{{-- `table-wrapper` is v12's own scroll box. `table-responsive` rides along because it is Bootstrap's name for the same thing and the one the shared component and its test both use; this screen does not go through that component (v12's card has no card-body around the table) but the two names stay together so a later reader does not read the difference as meaningful. --}}
{!! $dataTable->table(['class' => 'data-table']) !!}
{{-- The shared row-delete confirmation (CR-16 item J8). At the END of the content section and outside every `.card`, for the clipping reason the partial's own header records. It also pushes the toaster and the shared delete client, which is why the row buttons need nothing of their own. --}} @include('partials.ajax-delete-modal') @endsection {{-- DataTables is not in the Metronic bundles — plugins.bundle.js carries jQuery and nothing else of the plugin. It is vendored under public/assets/plugins/custom/datatables (see VERSIONS.md there) rather than pulled from a CDN, because a strict CSP is planned. --}} @push('styles') @endpush @push('scripts') {{-- Order is load bearing: jQuery (plugins.bundle.js, already in the layout) → core library → the Bootstrap 5 integration that patches its renderers → yajra's init, which calls $(…).DataTable(…) and would throw without the two above. --}} {!! $dataTable->scripts() !!} @endpush