175 lines
6.4 KiB
Vue
175 lines
6.4 KiB
Vue
<script setup>
|
|
|
|
import { Modal } from '@kouts/vue-modal'
|
|
import { ref } from 'vue';
|
|
import { X, GripVertical, MoreVertical, Edit3, CheckCircle2, Star, AlarmClock, Edit2 } from 'lucide-vue-next';
|
|
import DropdownMenu from 'v-dropdown-menu';
|
|
|
|
import { parseISO, isValid as isDateValid, format as formatDate,
|
|
isPast as isDatePast } from 'date-fns';
|
|
|
|
import VueDatePicker from '@vuepic/vue-datepicker';
|
|
import '@vuepic/vue-datepicker/dist/main.css'
|
|
|
|
const showModalDetails = ref(false);
|
|
const showModalEdit = ref(false);
|
|
|
|
const props = defineProps(['item', 'remove', 'currentProject', 'rename'])
|
|
|
|
const parsedDate = parseISO(props.item.dueDate ?? '');
|
|
const isValidDate = isDateValid(parsedDate);
|
|
// const formattedDate = formatDate(parsedDate, 'dd-MM-yyyy');
|
|
|
|
const dateEnabled = ref(isValidDate);
|
|
|
|
const date = ref(isValidDate ? new Date(props.item.dueDate) : null);
|
|
|
|
function editMe(event) {
|
|
event.preventDefault();
|
|
props.rename(event, props.item);
|
|
setTimeout(() => showModalEdit.value = false, 1);
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
|
|
<div class="flex items-center justify-between gap-2 *:block" :class="(item.done ? 'line-through text-slate-300' : '')">
|
|
<p v-if="!item.done"
|
|
class="handle text-xl cursor-pointer rounded-lg
|
|
*:stroke-slate-400 *:stroke-1 hover:*:stroke-slate-300
|
|
active:cursor-move"
|
|
title="Drag">
|
|
|
|
<GripVertical />
|
|
</p>
|
|
|
|
<p class="text-xl cursor-pointer rounded-lg
|
|
*:stroke-slate-400 *:stroke-1 hover:*:stroke-slate-300"
|
|
:class="item.done ? '*:fill-blue-300 *:stroke-slate-800 hover:*:stroke-slate-700 hover:*:fill-blue-400 ' : ''"
|
|
@click="$emit('toggleDone', props.item)"
|
|
title="Toggle status">
|
|
|
|
<CheckCircle2 />
|
|
</p>
|
|
|
|
<p class="!overflow-hidden whitespace-nowrap
|
|
text-ellipsis text-xl flex-1 cursor-pointer
|
|
hover:bg-slate-600 rounded-lg p-1"
|
|
:title="`${props.item.name} - show details`"
|
|
@click="showModalDetails = true"
|
|
:class="showModalDetails ? 'bg-slate-500/50 hover:bg-slate-500/75' : ''">
|
|
|
|
{{ props.item.name }}
|
|
</p>
|
|
|
|
<p class="!overflow-hidden whitespace-nowrap
|
|
text-ellipsis text-sm !flex items-center gap-1
|
|
[&_svg]:w-5 text-slate-200"
|
|
:title="`${props.item.name} - show details`">
|
|
|
|
<AlarmClock v-if="props.item.dueDate" :class="isDatePast(new Date(props.item.dueDate)) ? 'text-red-300' : ''" />
|
|
<p :class="isDatePast(new Date(props.item.dueDate)) ? 'text-red-300' : ''">
|
|
{{ props.item.dueDate ? formatDate(props.item.dueDate, `MMM do ${new Date(props.item.dueDate).getFullYear() == new Date().getFullYear() ? "" : "yyyy"}`) : '' }}
|
|
</p>
|
|
</p>
|
|
|
|
<p class="text-xl cursor-pointer rounded-lg *:stroke-slate-400
|
|
*:stroke-1 hover:*:stroke-slate-300"
|
|
:class="item.priority ? '*:fill-yellow-300 *:stroke-0 hover:*:fill-yellow-400 ' : ''"
|
|
@click="$emit('togglePriority', props.item)"
|
|
title="Toggle priority">
|
|
|
|
<Star />
|
|
</p>
|
|
|
|
<dropdown-menu
|
|
class="relative rounded-full hover:bg-slate-500
|
|
*:hover:[&_button]:*:stroke-slate-300"
|
|
title="More">
|
|
|
|
<template #trigger>
|
|
<button
|
|
class="p-2 *:stroke-slate-400
|
|
hover:*:stroke-slate-300">
|
|
|
|
<MoreVertical />
|
|
</button>
|
|
</template>
|
|
|
|
<template #body>
|
|
<ul class="*:flex absolute right-0
|
|
bg-slate-600 p-2 rounded-lg flex flex-col
|
|
gap-1 *:cursor-pointer *:p-1
|
|
*:rounded border border-slate-500 z-10">
|
|
|
|
<li class="hover:bg-slate-500"
|
|
@click="showModalEdit = true">
|
|
<Edit2 /> Edit
|
|
</li>
|
|
|
|
<li class="hover:bg-slate-500"
|
|
@click="props.remove(item)">
|
|
<X /> Delete
|
|
</li>
|
|
</ul>
|
|
</template>
|
|
</dropdown-menu>
|
|
</div>
|
|
|
|
|
|
<Modal v-model="showModalDetails" title="Task details">
|
|
<template v-slot:default>
|
|
<form>
|
|
<div class="form-group">
|
|
<label for="inputEmail4" class="text-2xl block font-bold">{{ props.item.name }}</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="inputEmail4" class="text-lg block">{{ props.item.description ?? '(no description)' }}</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="inputEmail4" class="text-xl flex items-center gap-1 " :class="isDatePast(new Date(props.item.dueDate)) ? 'text-red-300' : ''">
|
|
<AlarmClock :class="isDatePast(new Date(props.item.dueDate)) ? 'text-red-300' : ''" /> {{ props.item.dueDate ? formatDate(props.item.dueDate, "MMM do yyyy, HH:mm") : '(no due date)' }}
|
|
</label>
|
|
</div>
|
|
<div class="row modal-footer">
|
|
<div class="*:p-2 *:rounded-lg *:border flex gap-2 mt-3">
|
|
<button class="bg-yellow-600/75 font-bold border-slate-600" type="button" @click="showModalEdit = true">Edit</button>
|
|
<button class="bg-slate-700 border-slate-600" type="button" @click="showModalDetails = false">Close</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
</Modal>
|
|
|
|
<Modal v-model="showModalEdit" title="Edit task">
|
|
<template v-slot:default>
|
|
<form method="post" @submit="function (e) {editMe(e)}">
|
|
<div class="form-group">
|
|
<label for="inputEmail4" class="text-xl block">Name</label>
|
|
<input id="inputEmail4" type="text" class="block bg-slate-700 text-lg p-1 rounded-lg border border-slate-600" placeholder="Name" required name="name" :value="props.item.name" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="add-task-description" class="text-xl block">Description</label>
|
|
<textarea id="add-task-description" type="text" class="block bg-slate-700 text-lg p-1 rounded-lg border border-slate-600" placeholder="Description" name="description" :value="props.item.description"></textarea>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="add-task-description" class="text-xl block">Due date</label>
|
|
<input type="checkbox" v-model="dateEnabled" name="due-date-check" id="due-date-check" :value="props.item.dueDate ?? false"> <label for="due-date-check">Enabled</label>
|
|
<VueDatePicker v-model="date" :min-date="new Date()" :dark="true" :disabled="!dateEnabled" :required="dateEnabled" name="vuedate"></VueDatePicker>
|
|
<!-- {{ date.toISOString() }} -->
|
|
</div>
|
|
<div class="row modal-footer">
|
|
<div class="*:p-2 *:rounded-lg *:border flex gap-2 mt-3">
|
|
<button class="bg-green-800 border-green-600" type="submit">Edit</button>
|
|
<button class="bg-red-900 border-red-700" type="button" @click="showModalEdit = false">Discard</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
</Modal>
|
|
|
|
</template>
|
|
|
|
<style scoped>
|
|
</style> |