Fix: Todo component show empty headers and didn't respect show completed property
This commit is contained in:
@@ -12,7 +12,6 @@ const props = defineProps<{
|
|||||||
}>()
|
}>()
|
||||||
const todos = ref<Todo[]>([])
|
const todos = ref<Todo[]>([])
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
const showCompleted = ref(props.showCompleted)
|
|
||||||
|
|
||||||
watch(() => props.modelValue, value => {
|
watch(() => props.modelValue, value => {
|
||||||
todos.value = value as Todo[];
|
todos.value = value as Todo[];
|
||||||
@@ -55,6 +54,12 @@ const groupedTodos = computed(() => {
|
|||||||
return groups
|
return groups
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const todosEmpty = (todos: Todo[]) => {
|
||||||
|
if (todos.length === 0) return true
|
||||||
|
if (!props.showCompleted && !todos.some(todo => todo.status?.toLowerCase() !== 'completed')) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const todoTitle = (title: string) => {
|
const todoTitle = (title: string) => {
|
||||||
// If there's no title, return empty string
|
// If there's no title, return empty string
|
||||||
if (!title) return '';
|
if (!title) return '';
|
||||||
@@ -82,71 +87,75 @@ const todoBadge = (title: string) => {
|
|||||||
const shouldDisplay = (todo: Todo) => {
|
const shouldDisplay = (todo: Todo) => {
|
||||||
if (todo.status?.toLowerCase() !== 'completed') return true
|
if (todo.status?.toLowerCase() !== 'completed') return true
|
||||||
|
|
||||||
return showCompleted.value; // && moment(todo.dueDate).isSameOrAfter(moment(new Date()), 'day')
|
return props.showCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="todos" v-for="(todos, groupKey) in groupedTodos" :key="groupKey">
|
<div v-if="todos" v-for="(todos, groupKey) in groupedTodos" :key="groupKey">
|
||||||
<!-- Group header -->
|
<div v-if="!todosEmpty(todos)">
|
||||||
<h3 class="mt-4 mb-2 text-sm text-muted-foreground" :class="{
|
<!-- Group header -->
|
||||||
'text-destructive! font-bold': groupKey === 'overdue',
|
<h3 class="mt-4 mb-2 text-sm text-muted-foreground" :class="{
|
||||||
'text-warning! font-bold': groupKey === 'today'
|
'text-destructive! font-bold': groupKey === 'overdue',
|
||||||
}">
|
'text-warning! font-bold': groupKey === 'today'
|
||||||
{{ groupKey === 'today' ? 'Heute' : groupKey === 'overdue' ? 'Verspätet' : groupKey }}
|
}">
|
||||||
</h3>
|
{{ groupKey === 'today' ? 'Heute' : groupKey === 'overdue' ? 'Verspätet' : groupKey }}
|
||||||
<hr>
|
</h3>
|
||||||
|
|
||||||
<ul>
|
<hr>
|
||||||
<li v-for="todo in todos" class="flex gap-3 items-baseline py-2.5 pr-1 transition-all"
|
|
||||||
:class="{ 'scale-y-0 h-0 py-0! my-0 origin-top': !shouldDisplay(todo) }">
|
|
||||||
|
|
||||||
<!-- Check mark -->
|
<ul>
|
||||||
<div
|
<li v-for="todo in todos" class="flex gap-3 items-baseline py-2.5 pr-1 transition-all"
|
||||||
class="relative top-0.75 shrink-0 h-4 aspect-square rounded-full border-muted-foreground has-[input:checked]:border-primary border flex items-center justify-center">
|
:class="{ 'scale-y-0 h-0 py-0! my-0 origin-top': !shouldDisplay(todo) }">
|
||||||
<div class="absolute inset-0.5 rounded-full bg-transparent has-[input:checked]:bg-primary">
|
|
||||||
<input type="checkbox" class="absolute -inset-2 opacity-0"
|
<!-- Check mark -->
|
||||||
:checked="todo.status?.toLowerCase() == 'completed'" :id="todo.id">
|
<div
|
||||||
|
class="relative top-0.75 shrink-0 h-4 aspect-square rounded-full border-muted-foreground has-[input:checked]:border-primary border flex items-center justify-center">
|
||||||
|
<div class="absolute inset-0.5 rounded-full bg-transparent has-[input:checked]:bg-primary">
|
||||||
|
<input type="checkbox" class="absolute -inset-2 opacity-0"
|
||||||
|
:checked="todo.status?.toLowerCase() == 'completed'" :id="todo.id">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Text -->
|
<!-- Text -->
|
||||||
<div class="grow overflow-hidden truncate">
|
<div class="grow overflow-hidden truncate">
|
||||||
<!-- Priority -->
|
<!-- Priority -->
|
||||||
<span v-if="todo.priority < 5 && todo.priority > 0" class="mr-2 text-destructive">!!!</span>
|
<span v-if="todo.priority < 5 && todo.priority > 0" class="mr-2 text-destructive">!!!</span>
|
||||||
<span v-if="todo.priority == 5" class="mr-2 text-warning-foreground">!!</span>
|
<span v-if="todo.priority == 5" class="mr-2 text-warning-foreground">!!</span>
|
||||||
<span v-if="todo.priority > 5" class="mr-2 text-muted-foreground">!</span>
|
<span v-if="todo.priority > 5" class="mr-2 text-muted-foreground">!</span>
|
||||||
|
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<label :for="todo.id" class="my-0 px-0 border-0 outline-0 shadow-none" :class="{
|
<label :for="todo.id" class="my-0 px-0 border-0 outline-0 shadow-none" :class="{
|
||||||
'line-through text-muted-foreground': todo.status?.toLowerCase() == 'completed'
|
'line-through text-muted-foreground': todo.status?.toLowerCase() == 'completed'
|
||||||
}">
|
|
||||||
{{ todoTitle(todo.title) }}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<!-- Date -->
|
|
||||||
<div class="text-xs text-muted-foreground flex gap-3 items-center mt-1">
|
|
||||||
<Badge v-if="props.showTodoable && todoBadge(todo.title)" variant="outline">{{ todoBadge(todo.title)
|
|
||||||
}}
|
|
||||||
</Badge>
|
|
||||||
<span v-if="todo.dueDate" :class="{
|
|
||||||
'text-destructive! font-bold': groupKey === 'overdue',
|
|
||||||
'text-warning! font-bold': groupKey === 'today'
|
|
||||||
}">
|
}">
|
||||||
{{ toDuration(todo.dueDate) }}</span>
|
{{ todoTitle(todo.title) }}
|
||||||
<Repeat v-if="todo.recurring" stroke-width="2" :size="14" />
|
</label>
|
||||||
|
|
||||||
|
<!-- Date -->
|
||||||
|
<div class="text-xs text-muted-foreground flex gap-3 items-center mt-1">
|
||||||
|
<Badge v-if="props.showTodoable && todoBadge(todo.title)" variant="outline">{{
|
||||||
|
todoBadge(todo.title)
|
||||||
|
}}
|
||||||
|
</Badge>
|
||||||
|
<span v-if="todo.dueDate" :class="{
|
||||||
|
'text-destructive! font-bold': groupKey === 'overdue',
|
||||||
|
'text-warning! font-bold': groupKey === 'today'
|
||||||
|
}">
|
||||||
|
{{ toDuration(todo.dueDate) }}</span>
|
||||||
|
<Repeat v-if="todo.recurring" stroke-width="2" :size="14" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Icon -->
|
<!-- Icon -->
|
||||||
<div class="relative top-0.75 text-muted-foreground shrink-0">
|
<div class="relative top-0.75 text-muted-foreground shrink-0">
|
||||||
<PhoneCall v-if="todo.type?.name === 'phoneCall'" :size="18" />
|
<PhoneCall v-if="todo.type?.name === 'phoneCall'" :size="18" />
|
||||||
<ClipboardCheck v-else-if="todo.type?.name === 'todo'" :size="18" />
|
<ClipboardCheck v-else-if="todo.type?.name === 'todo'" :size="18" />
|
||||||
<Mail v-else-if="todo.type?.name === 'mail'" :size="18" />
|
<Mail v-else-if="todo.type?.name === 'mail'" :size="18" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
Reference in New Issue
Block a user