PHP Classes

File: resources/js/components/Weekly/BacklogColumn.vue

Recommend this page to a friend!
  Packages of Niko Peikrishvili   Ticker   resources/js/components/Weekly/BacklogColumn.vue   Download  
File: resources/js/components/Weekly/BacklogColumn.vue
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Ticker
Application to track and manage to do tasks
Author: By
Last change:
Date: 2 months ago
Size: 7,572 bytes
 

Contents

Class file image Download
<script setup> import { ref } from 'vue'; import { useWeeklyPlanner } from '@/composables/useWeeklyPlanner'; import { useTodos } from '@/composables/useTodos'; const emit = defineEmits(['taskDropped']); const { backlog, moveToBacklog } = useWeeklyPlanner(); const { addTodo } = useTodos(); const isDragOver = ref(false); const newTaskContent = ref(''); const isAddingTask = ref(false); const handleDragOver = (e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; isDragOver.value = true; }; const handleDragLeave = (e) => { if (!e.currentTarget.contains(e.relatedTarget)) { isDragOver.value = false; } }; const handleDrop = async (e) => { e.preventDefault(); isDragOver.value = false; try { const data = JSON.parse(e.dataTransfer.getData('text/plain')); if (!data.fromBacklog) { await moveToBacklog(data.todoId); emit('taskDropped', data.todoId); } } catch (err) { console.error('Failed to drop task to backlog:', err); } }; const handleDragStart = (e, task) => { e.dataTransfer.setData('text/plain', JSON.stringify({ todoId: task.id, fromBacklog: true, })); e.dataTransfer.effectAllowed = 'move'; }; const handleAddTask = async () => { if (!newTaskContent.value.trim()) return; try { // Pass null as date to create a backlog item (no date assigned) await addTodo(newTaskContent.value.trim(), 'todo', 3, null); newTaskContent.value = ''; isAddingTask.value = false; emit('taskDropped', null); } catch (err) { console.error('Failed to add task:', err); } }; const handleKeyDown = (e) => { if (e.key === 'Enter') { handleAddTask(); } else if (e.key === 'Escape') { isAddingTask.value = false; newTaskContent.value = ''; } }; </script> <template> <div class="flex flex-col bg-background rounded-xl shadow-sm overflow-hidden transition-all border" :style="{ borderColor: isDragOver ? 'var(--primary-color)' : 'var(--border-color)', boxShadow: isDragOver ? '0 0 0 2px var(--primary-color)' : undefined }" @dragover="handleDragOver" @dragleave="handleDragLeave" @drop="handleDrop" > <!-- Header --> <div class="px-4 py-3 flex items-center justify-between" style="background-color: var(--primary-color)"> <h3 class="text-white font-semibold text-sm">???????</h3> <button @click="isAddingTask = true" class="p-1 rounded hover:bg-white/20 transition-colors" title="????? ????????" > <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" /> </svg> </button> </div> <!-- Tasks Container --> <div class="flex-1 p-3 space-y-2 overflow-y-auto"> <!-- Add Task Input --> <div v-if="isAddingTask" class="mb-2"> <input v-model="newTaskContent" type="text" class="w-full px-3 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2" :style="{ borderColor: 'var(--border-color)', color: 'var(--text-color)' }" placeholder="????? ????????..." @keydown="handleKeyDown" autofocus /> <div class="flex gap-2 mt-2"> <button @click="handleAddTask" class="flex-1 px-3 py-1 text-white text-sm rounded-lg transition-colors" style="background-color: var(--primary-color)" > ???????? </button> <button @click="isAddingTask = false; newTaskContent = ''" class="px-3 py-1 text-sm rounded-lg transition-colors" style="color: var(--secondary-text-color)" > ???????? </button> </div> </div> <!-- Backlog Tasks --> <div v-for="task in backlog" :key="task.id" class="group relative bg-card rounded-lg shadow-sm border p-3 cursor-grab active:cursor-grabbing transition-all hover:shadow-md" :style="{ borderColor: 'var(--border-color)' }" draggable="true" @dragstart="(e) => handleDragStart(e, task)" > <div class="flex items-start gap-3"> <div class="mt-0.5 w-5 h-5 rounded border-2 flex-shrink-0" :style="task.is_completed ? { backgroundColor: 'var(--primary-color)', borderColor: 'var(--primary-color)' } : { borderColor: 'var(--secondary-text-color)' }" > <svg v-if="task.is_completed" class="w-full h-full text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7" /> </svg> </div> <span class="flex-1 text-sm" :style="{ color: task.is_completed ? 'var(--secondary-text-color)' : 'var(--text-color)' }" :class="{ 'line-through': task.is_completed }" > {{ task.content }} </span> </div> </div> <!-- Empty State --> <div v-if="backlog.length === 0 && !isAddingTask" class="h-full flex flex-col items-center justify-center text-sm py-8" style="color: var(--secondary-text-color)" > <svg class="w-8 h-8 mb-2 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" /> </svg> <span>??????? ????????</span> </div> <!-- Drop Zone Indicator --> <div v-if="isDragOver" class="border-2 border-dashed rounded-lg p-4 text-center text-sm" style="border-color: var(--primary-color); color: var(--primary-color)" > ?? ?????? </div> </div> <!-- Task Count --> <div class="px-4 py-2 border-t" :style="{ backgroundColor: 'var(--bg-color)', opacity: 0.5, borderColor: 'var(--border-color)' }" > <span class="text-xs" style="color: var(--secondary-text-color)"> {{ backlog.length }} ???????? </span> </div> </div> </template>