feat(frontend): highlight overdue tasks consistently

This commit is contained in:
Dominik Pschenitschni
2025-06-12 09:07:58 +02:00
committed by kolaente
parent a160048cc3
commit cfc7e30ffd
4 changed files with 35 additions and 22 deletions

View File

@@ -10,6 +10,7 @@
:style="{'background-color': color ?? undefined}" :style="{'background-color': color ?? undefined}"
:data-task-id="task.id" :data-task-id="task.id"
:data-project-id="task.projectId" :data-project-id="task.projectId"
:data-is-overdue="isOverdue || undefined"
@click.exact="openTaskDetail()" @click.exact="openTaskDetail()"
@click.ctrl="() => toggleTaskDone(task)" @click.ctrl="() => toggleTaskDone(task)"
@click.meta="() => toggleTaskDone(task)" @click.meta="() => toggleTaskDone(task)"
@@ -44,7 +45,6 @@
<span <span
v-if="task.dueDate > 0" v-if="task.dueDate > 0"
v-tooltip="formatDateLong(task.dueDate)" v-tooltip="formatDateLong(task.dueDate)"
:class="{'overdue': isOverdue}"
class="due-date" class="due-date"
> >
<span class="icon"> <span class="icon">
@@ -277,9 +277,10 @@ $task-background: var(--white);
margin-inline-end: .25rem; margin-inline-end: .25rem;
} }
&.overdue { }
color: var(--danger);
} &[data-is-overdue] .due-date {
color: var(--danger);
} }
.label-wrapper .tag { .label-wrapper .tag {

View File

@@ -3,7 +3,7 @@
<div <div
v-for="(r, index) in reminders" v-for="(r, index) in reminders"
:key="index" :key="index"
:class="{ 'overdue': r.reminder < now }" :data-is-overdue="r.reminder < now || undefined"
class="reminder-input" class="reminder-input"
> >
<ReminderDetail <ReminderDetail
@@ -111,7 +111,7 @@ function removeReminderByIndex(index: number) {
display: flex; display: flex;
align-items: center; align-items: center;
&.overdue :deep(.datepicker .show) { &[data-is-overdue] :deep(.datepicker .show) {
color: var(--danger); color: var(--danger);
} }

View File

@@ -8,6 +8,7 @@
:class="{'is-loading': taskService.loading}" :class="{'is-loading': taskService.loading}"
class="task loader-container single-task" class="task loader-container single-task"
tabindex="-1" tabindex="-1"
:data-is-overdue="isOverdue || undefined"
@click="openTaskDetail" @click="openTaskDetail"
@keyup.enter="openTaskDetail" @keyup.enter="openTaskDetail"
> >
@@ -89,7 +90,6 @@
> >
<time <time
:datetime="formatISO(task.dueDate)" :datetime="formatISO(task.dueDate)"
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
class="is-italic" class="is-italic"
:aria-expanded="isOpen ? 'true' : 'false'" :aria-expanded="isOpen ? 'true' : 'false'"
> >
@@ -223,6 +223,7 @@ import {useIntervalFn} from '@vueuse/core'
import {playPopSound} from '@/helpers/playPop' import {playPopSound} from '@/helpers/playPop'
import {isEditorContentEmpty} from '@/helpers/editorContentEmpty' import {isEditorContentEmpty} from '@/helpers/editorContentEmpty'
import {TASK_REPEAT_MODES} from '@/types/IRepeatMode' import {TASK_REPEAT_MODES} from '@/types/IRepeatMode'
import {useGlobalNow} from '@/composables/useGlobalNow'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
theTask: ITask, theTask: ITask,
@@ -308,6 +309,14 @@ onMounted(updateDueDate)
watch(() => task.value.dueDate, updateDueDate) watch(() => task.value.dueDate, updateDueDate)
const {now} = useGlobalNow()
const isOverdue = computed(() => (
!task.value.done &&
task.value.dueDate !== null &&
task.value.dueDate.getTime() > 0 &&
task.value.dueDate.getTime() <= now.value.getTime()
))
let oldTask let oldTask
async function markAsDone(checked: boolean, wasReverted: boolean = false) { async function markAsDone(checked: boolean, wasReverted: boolean = false) {
@@ -429,23 +438,24 @@ defineExpose({
flex: 1 0 50%; flex: 1 0 50%;
.dueDate { }
display: inline-block;
margin-inline-start: 5px;
&:focus-visible { .dueDate {
box-shadow: none; display: inline-block;
margin-inline-start: 5px;
time { &:focus-visible {
box-shadow: 0 0 0 1px hsla(var(--primary-hsl), 0.5); box-shadow: none;
border-radius: 3px;
} time {
box-shadow: 0 0 0 1px hsla(var(--primary-hsl), 0.5);
border-radius: 3px;
} }
} }
}
.overdue { &[data-is-overdue] .dueDate {
color: var(--danger); color: var(--danger);
}
} }
.task-project { .task-project {

View File

@@ -1,5 +1,8 @@
<template> <template>
<div class="task"> <div
class="task"
:data-is-overdue="task.dueDate <= new Date() && !task.done || undefined"
>
<span> <span>
<span <span
v-if="showProject && typeof project !== 'undefined'" v-if="showProject && typeof project !== 'undefined'"
@@ -55,7 +58,6 @@
> >
<time <time
:datetime="formatISO(task.dueDate)" :datetime="formatISO(task.dueDate)"
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
class="is-italic" class="is-italic"
> >
{{ $t('task.detail.due', {at: formatDisplayDate(task.dueDate)}) }} {{ $t('task.detail.due', {at: formatDisplayDate(task.dueDate)}) }}
@@ -151,7 +153,7 @@ const project = computed(() => projectStore.projects[props.task.projectId])
margin-inline-start: 5px; margin-inline-start: 5px;
} }
.overdue { &[data-is-overdue] .dueDate {
color: var(--danger); color: var(--danger);
} }