- Introduced `HelpPanel.vue` for displaying keyboard shortcuts and command descriptions. - Added `TodoItemTouch.vue`, a mobile-friendly task item component with updated bindings and improved actions. - Extended task commands with support for tagging, due date parsing, and dynamic text formatting. - Implemented `useActions` utility for parsing and executing command-based task modifications. - Streamlined task editing and creation in `useTasks` for consistency and API integration. - Updated `ListScreen` to support collapsible, categorized task lists with visual enhancements. - Refactored `App.vue` for adaptive input handling on mobile versus desktop views. - Enhanced API communication in `useApi` with cleaner header generation and error handling.
88 lines
3.3 KiB
Vue
88 lines
3.3 KiB
Vue
<script setup lang="ts">
|
|
import type { Task } from '../types.ts'
|
|
import { PhCheckSquare, PhDotsThree, PhFlag, PhPause, PhPlay, PhSquare, PhX } from '@phosphor-icons/vue'
|
|
import { DateTime } from 'luxon'
|
|
import { computed, ref } from 'vue'
|
|
import { useTasks } from '../composables/useTasks.ts'
|
|
import { TaskStatus } from '../types.ts'
|
|
|
|
const { task } = defineProps<{ task: Task }>()
|
|
|
|
const { updateTask } = useTasks()
|
|
|
|
const dueColor = computed(() => {
|
|
const dueDiff = task.dueDate ? DateTime.fromMillis(task.dueDate).diffNow('days').days : undefined
|
|
if (!dueDiff)
|
|
return ''
|
|
if (dueDiff < 0) {
|
|
return 'text-error'
|
|
}
|
|
else if (dueDiff < 2) {
|
|
return 'text-warning'
|
|
}
|
|
else if (dueDiff < 7) {
|
|
return 'text-success'
|
|
}
|
|
else {
|
|
return 'text-neutral'
|
|
}
|
|
})
|
|
|
|
const statusSelectVisible = ref(false)
|
|
|
|
async function handleClick(update: Partial<Task>) {
|
|
updateTask({ ...task, ...update })
|
|
statusSelectVisible.value = false
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<li class="list-row">
|
|
<div class="flex items-center justify-center">
|
|
<button class="btn btn-square btn-ghost" @click="statusSelectVisible = !statusSelectVisible">
|
|
<PhX v-if="statusSelectVisible" :size="20" />
|
|
<template v-else>
|
|
<PhSquare v-if="task.status === TaskStatus.WAIT" :size="20" />
|
|
<PhCheckSquare v-else-if="task.status === TaskStatus.DONE" :size="20" weight="fill" class="text-success" />
|
|
<PhFlag v-else-if="task.status === TaskStatus.FLAG" :size="20" weight="fill" class="text-warning" />
|
|
<PhPlay v-else-if="task.status === TaskStatus.WIP" :size="20" weight="fill" class="text-info" />
|
|
</template>
|
|
</button>
|
|
<Transition>
|
|
<div v-if="statusSelectVisible" class="">
|
|
<template v-if="task.status !== TaskStatus.WIP">
|
|
<button v-if="task.status !== TaskStatus.DONE" class="btn btn-square btn-ghost" @click="handleClick({ status: TaskStatus.DONE })">
|
|
<PhCheckSquare :size="24" weight="regular" class="text-success" />
|
|
</button>
|
|
<button v-if="task.status !== TaskStatus.WAIT" class="btn btn-square btn-ghost" @click="handleClick({ status: TaskStatus.WAIT })">
|
|
<PhSquare :size="24" weight="regular" />
|
|
</button>
|
|
<button v-if="task.status !== TaskStatus.FLAG" class="btn btn-square btn-ghost" @click="handleClick({ status: TaskStatus.FLAG })">
|
|
<PhFlag :size="24" weight="fill" class="text-warning" />
|
|
</button>
|
|
<button class="btn btn-square btn-ghost" @click="handleClick({ status: TaskStatus.WIP })">
|
|
<PhPlay :size="24" weight="fill" class="text-info" />
|
|
</button>
|
|
</template>
|
|
<button v-else class="btn btn-square btn-ghost" @click="handleClick({ status: TaskStatus.WAIT })">
|
|
<PhPause :size="24" weight="fill" class="text-info" />
|
|
</button>
|
|
</div>
|
|
</Transition>
|
|
</div>
|
|
<div class="flex flex-col justify-center">
|
|
<div>{{ task.id }} {{ task.id_ }} {{ task.title }}</div>
|
|
<div v-if="task.dueDate" :class="dueColor">
|
|
{{ DateTime.fromMillis(task.dueDate).toFormat('dd/MM/yyyy') }}
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-square btn-ghost">
|
|
<PhDotsThree :size="24" weight="regular" />
|
|
</button>
|
|
</li>
|
|
</template>
|
|
|
|
<style scoped>
|
|
|
|
</style>
|