159 lines
10 KiB
PHP
159 lines
10 KiB
PHP
<?php $__env->startSection('content'); ?>
|
|
<div class="space-y-6">
|
|
<!-- Page Header -->
|
|
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
|
<div class="flex items-center gap-4">
|
|
<h1 class="text-2xl font-bold text-gray-900"><?php echo e(__('task.kanban')); ?></h1>
|
|
<a href="<?php echo e(route('tasks.index')); ?>" class="text-sm text-teal-600 hover:text-teal-700"><?php echo e(__('task.listView')); ?></a>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<select id="projectFilter" onchange="filterByProject(this.value)"
|
|
class="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-teal-500">
|
|
<option value=""><?php echo e(__('common.all')); ?> <?php echo e(__('nav.projects')); ?></option>
|
|
<?php $__currentLoopData = $projects; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $project): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
<option value="<?php echo e($project->id); ?>" <?php echo e($selectedProject == $project->id ? 'selected' : ''); ?>><?php echo e($project->name); ?></option>
|
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
</select>
|
|
<a href="<?php echo e(route('tasks.create')); ?>" class="inline-flex items-center gap-2 px-4 py-2 bg-teal-600 text-white text-sm font-medium rounded-lg hover:bg-teal-700 transition-colors">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
|
|
<?php echo e(__('task.create')); ?>
|
|
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Kanban Board -->
|
|
<div class="flex gap-4 overflow-x-auto pb-4" style="min-height: calc(100vh - 280px);">
|
|
<?php $__currentLoopData = [
|
|
'pending' => ['color' => 'gray', 'icon' => 'M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z'],
|
|
'in_progress' => ['color' => 'blue', 'icon' => 'M13 10V3L4 14h7v7l9-11h-7z'],
|
|
'review' => ['color' => 'amber', 'icon' => 'M15 12a3 3 0 11-6 0 3 3 0 016 0z'],
|
|
'done' => ['color' => 'emerald', 'icon' => 'M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z']
|
|
]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $status => $config): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
|
|
<div class="flex-shrink-0 w-72"
|
|
x-data="{ tasks: [] }"
|
|
x-init="tasks = []">
|
|
<!-- Column Header -->
|
|
<div class="flex items-center gap-2 mb-3 px-1">
|
|
<div class="w-7 h-7 bg-<?php echo e($config['color']); ?>-100 text-<?php echo e($config['color']); ?>-600 rounded-lg flex items-center justify-center">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="<?php echo e($config['icon']); ?>"/>
|
|
</svg>
|
|
</div>
|
|
<h3 class="text-sm font-bold text-gray-900"><?php echo e(__('task.status_' . $status)); ?></h3>
|
|
<span class="text-xs bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded-full"><?php echo e($kanbanColumns[$status]->count()); ?></span>
|
|
</div>
|
|
|
|
<!-- Column Body -->
|
|
<div class="bg-gray-100 rounded-xl p-2 min-h-[200px] space-y-2">
|
|
<?php $__empty_1 = true; $__currentLoopData = $kanbanColumns[$status]; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $task): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); $__empty_1 = false; ?>
|
|
<div class="bg-white rounded-lg border border-gray-200 p-3 shadow-sm hover:shadow-md transition-shadow cursor-pointer group">
|
|
<div class="flex items-start justify-between gap-2 mb-2">
|
|
<a href="<?php echo e(route('tasks.show', $task)); ?>" class="text-sm font-medium text-gray-900 hover:text-teal-600 line-clamp-2">
|
|
<?php echo e($task->title); ?>
|
|
|
|
</a>
|
|
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-bold flex-shrink-0
|
|
<?php echo e($task->priority === 'urgent' ? 'bg-red-100 text-red-700' :
|
|
($task->priority === 'high' ? 'bg-orange-100 text-orange-700' :
|
|
($task->priority === 'medium' ? 'bg-amber-100 text-amber-700' : 'bg-gray-100 text-gray-600'))); ?>">
|
|
<?php echo e(__('task.' . $task->priority)); ?>
|
|
|
|
</span>
|
|
</div>
|
|
|
|
<?php if($task->project): ?>
|
|
<p class="text-xs text-gray-500 mb-2"><?php echo e($task->project->name); ?></p>
|
|
<?php endif; ?>
|
|
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-1">
|
|
<?php if($task->due_date): ?>
|
|
<span class="text-xs <?php echo e($task->due_date->isPast() && $status !== 'done' ? 'text-red-600 font-medium' : 'text-gray-400'); ?>">
|
|
<svg class="w-3 h-3 inline-block me-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
|
|
<?php echo e(calendar_date($task->due_date)); ?>
|
|
|
|
</span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="flex items-center gap-1">
|
|
<?php if($task->assignee): ?>
|
|
<div class="w-6 h-6 bg-teal-100 text-teal-700 rounded-full flex items-center justify-center text-[10px] font-bold" title="<?php echo e($task->assignee->name); ?>">
|
|
<?php echo e(mb_strtoupper(mb_substr($task->assignee->name, 0, 1))); ?>
|
|
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="opacity-0 group-hover:opacity-100 transition-opacity flex items-center gap-0.5">
|
|
<?php if($status !== 'pending'): ?>
|
|
<button onclick="moveTask(<?php echo e($task->id); ?>, 'pending')" class="p-0.5 text-gray-400 hover:text-gray-600" title="<?php echo e(__('task.status_pending')); ?>">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
|
</button>
|
|
<?php endif; ?>
|
|
<?php if($status !== 'in_progress'): ?>
|
|
<button onclick="moveTask(<?php echo e($task->id); ?>, 'in_progress')" class="p-0.5 text-blue-400 hover:text-blue-600" title="<?php echo e(__('task.status_in_progress')); ?>">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>
|
|
</button>
|
|
<?php endif; ?>
|
|
<?php if($status !== 'review'): ?>
|
|
<button onclick="moveTask(<?php echo e($task->id); ?>, 'review')" class="p-0.5 text-amber-400 hover:text-amber-600" title="<?php echo e(__('task.status_review')); ?>">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
|
|
</button>
|
|
<?php endif; ?>
|
|
<?php if($status !== 'done'): ?>
|
|
<button onclick="moveTask(<?php echo e($task->id); ?>, 'done')" class="p-0.5 text-emerald-400 hover:text-emerald-600" title="<?php echo e(__('task.status_done')); ?>">
|
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); if ($__empty_1): ?>
|
|
<div class="text-center py-8 text-gray-400 text-xs">
|
|
<?php echo e(__('task.no_tasks')); ?>
|
|
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php $__env->startPush('scripts'); ?>
|
|
<script>
|
|
function filterByProject(projectId) {
|
|
const url = new URL(window.location.href);
|
|
if (projectId) {
|
|
url.searchParams.set('project_id', projectId);
|
|
} else {
|
|
url.searchParams.delete('project_id');
|
|
}
|
|
window.location.href = url.toString();
|
|
}
|
|
|
|
async function moveTask(taskId, newStatus) {
|
|
try {
|
|
const res = await fetch(`/tasks/${taskId}/status`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
},
|
|
body: JSON.stringify({ status: newStatus })
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) {
|
|
location.reload();
|
|
}
|
|
} catch(e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
</script>
|
|
<?php $__env->stopPush(); ?>
|
|
<?php $__env->stopSection(); ?>
|
|
|
|
<?php echo $__env->make('layouts.app', array_diff_key(get_defined_vars(), ['__data' => 1, '__path' => 1]))->render(); ?><?php /**PATH C:\xampp\htdocs\projectra\resources\views/tasks/kanban.blade.php ENDPATH**/ ?>
|