Per feedback, 'New role' (and Edit) now open a dedicated page instead of a
modal:
- New RoleForm full-page component + view at /admin/roles/create and
/admin/roles/{role}/edit (name, description, permission checkboxes; saves
and redirects back to the list).
- RoleManager trimmed: the create/edit modal and its logic removed; 'New role'
and the per-row/view-modal Edit are now links to the new pages.
- Kept the read-only View modal, single + bulk delete, and protections.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per request:
- Migration: add nullable 'description' to the roles table.
- RoleManager Livewire component + view at /admin/roles:
* Roles list table with per-row checkboxes for bulk selection (+ select-all)
and a 'Delete selected' bulk action (protected roles skipped).
* 'New role' opens a modal form with just Name + Description (and permission
checkboxes to assign).
* Per-row View / Edit / Delete buttons (View modal shows description,
counts and assigned permissions).
- Admin role stays protected (no rename/delete/lose 'manage all').
- /admin/users links to the new Roles screen; the phase-1 permission matrix
stays available via a 'Matrix view' link.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1 (additive, doesn't touch existing checks):
- Gate::before grants everything to holders of 'manage all' (the Admin role),
robustly (returns true/null, never false; swallows missing-permission).
- New RolePermissionManager Livewire component + view at /admin/permissions:
editable Roles x Permissions matrix (toggle saves instantly), create/delete
roles, create/delete permissions. Admin role and 'manage all' are protected.
- Link to the screen from /admin/users header.
Roles are editable from the UI as chosen.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Login authenticated fine but the landing page crashed (so it looked like
'login doesn't work'):
- bootstrap/app.php didn't register Spatie's middleware aliases -> any route
with role:/permission: threw 'Target class [role] does not exist'.
Registered role / permission / role_or_permission.
- config/livewire.php absent -> default layout is the non-existent
components.layouts.app. ProjectList, PhaseProgress and ReportsDashboard
lacked #[Layout('layouts.app')] -> MissingLayoutException. Added it (the
other 10 routed components already had it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
web.php referenced App\Http\Controllers\Auth\AuthenticatedSessionController
(and imported 8 other Auth\* controllers) that don't exist — this is a
Breeze+Volt app where auth is handled by Volt pages (routes/auth.php) and
logout by the Volt navigation action (App\Livewire\Actions\Logout).
The broken /logout route made 'php artisan route:list' throw
ReflectionException. Removed the dead route (nothing uses route('logout');
the nav uses wire:click=logout) and the unused Auth controller imports.
Login/register/reset already worked via Volt; logout works via the Volt action.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
User's manual changes: header slots with New-user/New-company actions, wider
max-w-7xl containers on /admin/users and /companies, plus tweaks to
user-view and projects index views. All views compile.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebuilt IssueManager to match the 403-line draft view that had no companion
component:
- Modal create/edit form (title, description, priority, status, assignee,
resolution notes shown when resolved/closed)
- Stats bar (open/in_review/resolved/closed/total) and a styled table
- New methods: openForm/closeForm, resolve, close (+ existing save/delete),
projectUsers for the assignee dropdown, resolved_at kept in sync with status
- render() now points to livewire.issues.issue-manager; deleted the old
89-line stub livewire/issue-manager.blade.php
The Issue model already had everything (resolution_notes, resolved_at,
priority_color/status_color accessors, reporter/feature/assignee relations).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deleted (all superseded, recoverable in git history):
- resources/views/projects/edit.blade.php + ProjectController@edit()
- resources/views/projects/create.blade.php + ProjectController@create()
(projects.create/edit routes point to the Livewire ProjectForm; these
controller methods were excluded from the resource and never invoked)
- app/Livewire/ProjectEditTabs.php + project-edit-tabs.blade.php
(old tabbed editor, functionality recovered inside ProjectForm)
- app/Livewire/LayerUpload.php + layer-upload.blade.php (superseded by LayerManager)
Kept resources/views/livewire/issues/issue-manager.blade.php as a reference
for the future rich Issues screen (its companion component was never built).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point 2 (migrate to Rappasoft tables):
- /admin/users now renders <livewire:user-table /> (+ a New user button)
instead of the custom admin-users component
- /companies now renders <livewire:company-table /> (+ New company button)
instead of the hand-rolled card list
Point 3 (delete): removed resources/views/welcome.blade.php (unused — '/'
redirects to dashboard).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The edit/create project page used a stripped-down inline form. Rewired it
to the existing-but-orphaned pieces:
- Project Data uses the rich partial project-data-form (labels-left/field-right
layout, sections Identification/Location/Planning, address search + Leaflet
map with draggable marker + reverse/forward geocoding, country dropdown)
- When editing, tabs added for Phases / Users / Companies (nested Livewire
components phase-list / project-users / project-companies)
- ProjectForm now provides $countryList (the partial's country dropdown needs it)
- Added the map JS the partial was missing: inits #project-location-map, search
box, and calls $this->setLocation(lat,lng,address,country) so the wire:model
fields update
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
project-form.blade.php referenced $projectId, but the ProjectForm component
exposes $project (the model, null when creating). Caused 'Undefined variable
$projectId' on /projects/{id}/edit. Switched both usages to $project.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1. Editor tabs restyled as spaced DaisyUI buttons (btn-primary when active,
btn-ghost otherwise) — fixes cramped labels and missing active indicator.
2. Layer visibility now works at two levels:
- Phase toggle calls togglePhase() and shows/hides ALL its layers
(checked only when every layer of the phase is active)
- Each layer has its own independent toggle calling toggleLayer()
Map JS regrouped to build one Leaflet group per LAYER (keyed by layer id)
instead of per phase, so activeLayers (layer ids) drives visibility
correctly per layer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The DaisyUI .modal default z-index (999) was below the phases/layers panel
(z-1000) and its reopen button (z-1001), so they showed on top of the modal.
Set the modal to z-[2000].
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1.1 Edit tab: in fullscreen the content splits into 2 columns (Alpine :class)
1.2 Full-width feature title with progress as a number badge on the left;
removed the progress slider and the 'Save progress' button; Responsible
now auto-saves on blur (wire:blur)
2. Features table: zebra/pinned-rows styling, progress badge; removed the
Responsible and Template columns
3. Inspections table: same styling; wired the eye button to viewInspection()
and added the inspection viewer modal (uses existing component state)
6a. Phases/layers collapse button moved into the panel title; a small floating
button reopens it when collapsed (saves space)
6b. Base-layer switcher on the map: Streets / OpenStreetMap / Satellite (Esri)
Issues tab (point 5) intentionally left untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The tab-content wrapper comment contained the text '@if', which Blade
compiles even inside HTML comments, causing a ParseError on page load.
Reworded the comment to avoid the directive token.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The tab panel wrapper used class 'tab-content', which DaisyUI hides by
default (display:none) unless paired with a checked radio .tab sibling.
Since visibility is driven by Livewire @if($activeTab===...), the class
only kept the content permanently hidden. Replaced with a neutral wrapper.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Features and Inspections tab tables read $feature->layer->name and
$inspection->feature->name (and template/user) without null guards. When a
referenced feature/layer was soft-deleted, the relation is null and rendering
threw 'Attempt to read property name on null', returning HTTP 500 on every
Livewire update — which also prevented the tabs from switching (the update
that changes activeTab crashed during re-render).
Made all chained relation reads null-safe with ?-> and '—' fallbacks.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1. Hide the project navigation bar (kept in DOM via 'hidden', not deleted)
2. Move the tabs into the panel header where the 'Map' title was
3. (tabs setActiveTab logic already correct — recompiled)
4. Make the phases/layers panel collapsible via an Alpine toggle button
5. Replace all emoji icons with blade-heroicons (<x-heroicon-o-*>)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recovers the project-map progress from f8a1310 (project navigation bar +
Issues tab + embedded IssueManager) but applied on top of 7d854ff's
COMPLETE, working component (449 lines: setActiveTab, openIssuesCount,
inspection editor, filters, togglePhase/toggleLayer, IDOR checks).
f8a1310 had added this UI to the blade but simultaneously gutted the
component (down to 347 lines, removing setActiveTab) which broke the tabs.
This commit keeps the good component and adds only the blade UI, so the
tabs, inspection editor and Issues tab all work together.
Verified: all blade templates compile, routes (gantt/report/issues/
dashboard) exist, IssueManager::mount(Project) matches the passed param.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pre-existing bug in 7d854ff: the company type CSS-class @if block at
line 258 was closed with a bare 'endif' (no @), causing a ParseError on
GET /companies (unexpected 'endforeach').
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full restore of the 7d854ff snapshot (2026-06-16 18:05, before the security
review). Forward commit, no history rewrite — f8a1310 and all later commits
remain recoverable in history.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restores all files to the f8a1310 security-review snapshot as requested,
plus the 2 boot-critical fixes from a24c8a2 (config/session.php env()
instead of app()->environment(), and removal of the duplicate $activeTab
in ProjectMap.php) so the application actually boots.
Forward commit, no history rewrite. The 7d854ff state remains in history.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restores all 27 files changed by the security commit (f8a1310) and later
work back to their 7d854ff state (2026-06-16 18:05), as requested. The
security rewrite regressed map functionality (tabs, inspection editor,
collapsing layers panel) without adding protections the 7d854ff version
did not already have (XSS escaping + IDOR checks were already present).
Done as a forward commit (no history rewrite / force-push) so f8a1310,
a24c8a2 and the merge remain in history and are fully recoverable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The UrlGenerationException was occurring because the configure() method was overwritten
without properly defining the columns, causing route() calls to receive null parameters.
Restored the original column definitions while keeping the clean configure() structure.