feat(tasks): complete task management system with Kanban, Calendar, notifications

- Add Task model with subtasks, priorities, status transitions, dates, hours
- Add Comment polymorphic model for tasks/issues/projects
- Livewire components: TaskManager (list+filters), TaskForm (modal), TaskDetail, TaskKanban (drag&drop), TaskCalendar (FullCalendar)
- TaskPolicy with permissions (view/create/edit/delete/assign/manage all)
- Notifications: assigned, status change, overdue, comment added
- Daily overdue notification job scheduled
- Dashboard widget unifies IssueTask + Task
- i18n: en/es/fr/ru (393 keys each)
- Routes, navigation, offline sync support
- 101 tests passing, Pint compliant on new files
This commit is contained in:
Javier Braña
2026-08-03 13:44:10 +02:00
parent a65d4b12f2
commit ba614bddbc
62 changed files with 5878 additions and 382 deletions
+30 -30
View File
@@ -1,26 +1,26 @@
<x-guest-layout>
<div class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
<h1 class="text-2xl font-bold text-gray-900 mb-6">
Bienvenido, {{ auth()->user()->name }}
{{ __('Welcome, :name', ['name' => auth()->user()->name]) }}
</h1>
<div class="grid gap-6 mb-8">
<div class="lg:col-span-3">
<div class="rounded-lg border border-gray-200 bg-white p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">
Mis Proyectos Activos
{{ __('My Active Projects') }}
</h2>
<livewire:client-projects />
</div>
</div>
<div class="lg:col-span-1">
<div class="rounded-lg border border-gray-200 bg-white p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">
Notificaciones
{{ __('Notifications') }}
</h2>
<div class="space-y-4">
<div class="flex items-start space-x-3">
<div class="flex-shrink-0">
@@ -30,17 +30,17 @@
</div>
<div class="min-w-0 flex-1">
<h3 class="text-sm font-medium text-gray-900">
Proyecto actualizado
{{ __('Project updated') }}
</h3>
<p class="text-sm text-gray-500">
Se han añadido nuevas fotos al proyecto "Centro Comercial Norte"
{{ __('New photos added to project ":name"', ['name' => 'Centro Comercial Norte']) }}
</p>
<p class="text-xs text-gray-400">
Hace 2 horas
{{ __('2 hours ago') }}
</p>
</div>
</div>
<div class="flex items-start space-x-3">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-green-600" viewBox="0 0 20 20" fill="currentColor">
@@ -49,13 +49,13 @@
</div>
<div class="min-w-0 flex-1">
<h3 class="text-sm font-medium text-gray-900">
Orden de cambio aprobada
{{ __('Change order approved') }}
</h3>
<p class="text-sm text-gray-500">
La orden de cambio #123 ha sido aprobada
{{ __('Change order #:id has been approved', ['id' => '123']) }}
</p>
<p class="text-xs text-gray-400">
Hace 1 día
{{ __('1 day ago') }}
</p>
</div>
</div>
@@ -63,60 +63,60 @@
</div>
</div>
</div>
<div class="grid gap-6">
<div class="lg:col-span-6">
<div class="rounded-lg border border-gray-200 bg-white p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">
Galería de Progreso
{{ __('Progress Gallery') }}
</h2>
<div class="gallery-grid">
<!-- Placeholder for gallery items -->
<div class="gallery-item bg-gray-100 flex items-center justify-center h-48">
<span class="text-gray-500">Próximamente: Fotos del avance</span>
<span class="text-gray-500">{{ __('Coming soon: Progress photos') }}</span>
</div>
</div>
</div>
</div>
<div class="lg:col-span-6">
<div class="rounded-lg border border-gray-200 bg-white p-6">
<h2 class="text-lg font-medium text-gray-900 mb-4">
Órdenes de Cambio Pendientes
{{ __('Pending Change Orders') }}
</h2>
<div class="space-y-4">
<div class="change-order-card change-order-pending">
<h3 class="text-sm font-medium text-gray-900 mb-2">
Orden de cambio #124
{{ __('Change order #:id', ['id' => '124']) }}
</h3>
<p class="text-sm text-gray-500 mb-2">
Solicitud de ampliación de zona de almacenamiento
{{ __('Storage area expansion request') }}
</p>
<div class="flex items-center space-x-3 mt-2">
<button class="px-3 py-1 bg-green-600 text-white text-sm rounded hover:bg-green-700">
Aprobar
{{ __('Approve') }}
</button>
<button class="px-3 py-1 bg-red-600 text-white text-sm rounded hover:bg-red-700">
Rechazar
{{ __('Reject') }}
</button>
</div>
</div>
<div class="change-order-card change-order-pending">
<h3 class="text-sm font-medium text-gray-900 mb-2">
Orden de cambio #125
{{ __('Change order #:id', ['id' => '125']) }}
</h3>
<p class="text-sm text-gray-500 mb-2">
Cambio de material en acabados interiores
{{ __('Interior finish material change') }}
</p>
<div class="flex items-center space-x-3 mt-2">
<button class="px-3 py-1 bg-green-600 text-white text-sm rounded hover:bg-green-700">
Aprobar
{{ __('Approve') }}
</button>
<button class="px-3 py-1 bg-red-600 text-white text-sm rounded hover:bg-red-700">
Rechazar
{{ __('Reject') }}
</button>
</div>
</div>