PHP Classes

File: resources/js/components/TodoItem.vue

Recommend this page to a friend!
  Packages of Niko Peikrishvili   Ticker   resources/js/components/TodoItem.vue   Download  
File: resources/js/components/TodoItem.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: 9,056 bytes
 

Contents

Class file image Download
<script setup> import { ref, computed } from 'vue'; const props = defineProps({ todo: { type: Object, required: true, }, }); const emit = defineEmits(['update', 'delete', 'start-working', 'stop-working']); const isEditing = ref(false); const editContent = ref(props.todo.content); const statusColors = { backlog: 'bg-gray-100 text-gray-700', todo: 'bg-blue-100 text-blue-700', in_progress: 'bg-yellow-100 text-yellow-700', done: 'bg-green-100 text-green-700', }; const statusLabels = { backlog: '???????', todo: '????????????', in_progress: '?????????', done: '???????????', }; const formattedTime = computed(() => { const minutes = props.todo.total_time_spent || 0; if (minutes === 0) return null; const hours = Math.floor(minutes / 60); const mins = minutes % 60; return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`; }); const toggleComplete = () => { emit('update', props.todo.id, { is_completed: !props.todo.is_completed }); }; const updateStatus = (status) => { emit('update', props.todo.id, { status }); }; const startEditing = () => { isEditing.value = true; editContent.value = props.todo.content; }; const saveEdit = () => { if (editContent.value.trim()) { emit('update', props.todo.id, { content: editContent.value }); isEditing.value = false; } }; const cancelEdit = () => { isEditing.value = false; editContent.value = props.todo.content; }; const handleDelete = () => { if (confirm('????????? ????? ??????')) { emit('delete', props.todo.id); } }; const toggleWorking = () => { if (props.todo.is_working) { emit('stop-working', props.todo.id); } else { emit('start-working', props.todo.id); } }; </script> <template> <div class="group flex items-start gap-3 py-2 px-3 rounded-lg border transition-all" :class="[ todo.is_working ? 'bg-yellow-50 border-yellow-300 shadow-sm' : 'bg-white border-gray-200 hover:border-blue-300' ]" > <!-- Checkbox --> <button @click="toggleComplete" class="mt-0.5 w-5 h-5 rounded border-2 flex-shrink-0 transition-all flex items-center justify-center opacity-0 group-hover:opacity-100" :class="[ todo.is_completed ? 'bg-primary border-primary text-white opacity-100' : 'border-gray-400 hover:border-primary' ]" > <svg v-if="todo.is_completed" class="w-3 h-3" 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> </button> <!-- Content Area --> <div class="flex-1 min-w-0"> <!-- Display Mode --> <div v-if="!isEditing"> <!-- Top row: Task ID + Status + Time --> <div class="flex items-center gap-2 mb-1"> <span class="text-xs font-mono text-muted-foreground">{{ todo.display_id }}</span> <span class="px-1.5 py-0.5 text-xs rounded-full font-medium" :class="statusColors[todo.status]" > {{ statusLabels[todo.status] }} </span> <span v-if="formattedTime" class="text-xs text-muted-foreground flex items-center gap-1"> <svg class="w-3 h-3" 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> {{ formattedTime }} </span> <span v-if="todo.is_working" class="flex items-center gap-1 text-xs text-yellow-600 font-medium"> <span class="w-2 h-2 bg-yellow-500 rounded-full animate-pulse"></span> ??????? </span> </div> <!-- Content row --> <div class="flex items-start justify-between gap-2"> <p :class="[ 'flex-1 break-words cursor-pointer text-sm', todo.is_completed ? 'line-through text-muted-foreground' : 'text-foreground' ]" @dblclick="startEditing" > {{ todo.content }} </p> <!-- Actions (visible on hover) --> <div class="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity"> <!-- Start/Stop Working Button --> <button v-if="!todo.is_completed" @click="toggleWorking" class="p-1 rounded transition-colors" :class="todo.is_working ? 'text-red-500 hover:text-red-600 hover:bg-red-50' : 'text-green-500 hover:text-green-600 hover:bg-green-50'" :title="todo.is_working ? '????????' : '???????'" > <svg v-if="todo.is_working" 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="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 10a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z" /> </svg> <svg v-else 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="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" /> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg> </button> <button @click="startEditing" class="p-1 text-muted-foreground hover:text-primary transition-colors" title="???????????" > <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="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" /> </svg> </button> <button @click="handleDelete" class="p-1 text-muted-foreground hover:text-red-500 transition-colors" title="?????" > <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="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> </svg> </button> </div> </div> </div> <!-- Edit Mode --> <div v-else class="flex gap-2"> <input v-model="editContent" @keyup.enter="saveEdit" @keyup.esc="cancelEdit" type="text" class="flex-1 px-3 py-1 border border-primary rounded-lg focus:outline-none focus:ring-2 focus:ring-primary text-sm" autofocus /> <button @click="saveEdit" class="px-3 py-1 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 text-sm" > ??????? </button> <button @click="cancelEdit" class="px-3 py-1 bg-muted text-muted-foreground rounded-lg hover:bg-muted/80 text-sm" > ???????? </button> </div> </div> </div> </template>