169 lines
3.8 KiB
Vue
169 lines
3.8 KiB
Vue
<template>
|
|
<div class="task-queue">
|
|
<article
|
|
v-for="task in items"
|
|
:key="task.task_id"
|
|
class="task-row"
|
|
:class="{ 'task-row--active': task.task_id === activeTaskId }"
|
|
>
|
|
<button
|
|
class="task-row__select"
|
|
type="button"
|
|
@click="$emit('openTask', task.task_id)"
|
|
>
|
|
<span class="task-row__index">{{ task.queue_sequence ?? '-' }}</span>
|
|
<span class="task-row__main">
|
|
<strong>{{ formatReservationTaskCard(t, task.task_type, task.card_name) }}</strong>
|
|
<small>{{ formatReservationTaskRouteSummary(t, task) }}</small>
|
|
<em :class="{ 'task-row__reason--blocked': !task.can_process }">
|
|
{{ task.can_process ? t('taskList.canProcess') : t('taskList.cannotProcess') }}
|
|
<template v-if="!task.can_process && task.readonly_reason_code">
|
|
· {{ formatReservationReadonlyReason(t, task.readonly_reason_code) }}
|
|
</template>
|
|
</em>
|
|
</span>
|
|
<ReservationStatusBadge :status="task.task_status" />
|
|
</button>
|
|
<div class="task-row__actions">
|
|
<span
|
|
v-if="!task.source_message_id"
|
|
class="task-row__pending"
|
|
>
|
|
{{ t('common.endpointMissing') }}
|
|
</span>
|
|
<RouterLink
|
|
v-else
|
|
class="task-row__link"
|
|
:to="`/reservation/source-messages/${task.source_message_id}/conversation`"
|
|
>
|
|
{{ t('taskList.viewConversation') }}
|
|
</RouterLink>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { RouterLink } from 'vue-router'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
import ReservationStatusBadge from '@/components/reservation/ReservationStatusBadge.vue'
|
|
import type { ReservationOrderTaskTimelineItem } from '@/types/reservation'
|
|
import {
|
|
formatReservationReadonlyReason,
|
|
formatReservationTaskCard,
|
|
formatReservationTaskRouteSummary,
|
|
} from '@/utils/reservationDisplay'
|
|
|
|
defineProps<{
|
|
items: ReservationOrderTaskTimelineItem[]
|
|
activeTaskId: string
|
|
}>()
|
|
|
|
defineEmits<{
|
|
openTask: [taskId: string]
|
|
}>()
|
|
|
|
const { t } = useI18n()
|
|
</script>
|
|
|
|
<style scoped>
|
|
.task-queue {
|
|
display: grid;
|
|
gap: 8px;
|
|
}
|
|
|
|
.task-row {
|
|
border: 1px solid var(--th-color-slate-200);
|
|
border-radius: var(--th-radius-md);
|
|
background: var(--th-color-white);
|
|
color: inherit;
|
|
padding: 10px;
|
|
}
|
|
|
|
.task-row__select {
|
|
display: grid;
|
|
grid-template-columns: 34px minmax(0, 1fr) auto;
|
|
gap: 10px;
|
|
align-items: center;
|
|
width: 100%;
|
|
border: 0;
|
|
background: transparent;
|
|
color: inherit;
|
|
cursor: pointer;
|
|
padding: 0;
|
|
text-align: left;
|
|
}
|
|
|
|
.task-row--active {
|
|
border-color: var(--th-color-blue-600);
|
|
box-shadow: 0 0 0 1px var(--th-color-blue-600);
|
|
}
|
|
|
|
.task-row__index {
|
|
display: inline-flex;
|
|
width: 28px;
|
|
height: 28px;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 999px;
|
|
background: var(--th-color-blue-100);
|
|
color: var(--th-color-blue-600);
|
|
font-size: 12px;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.task-row__main {
|
|
display: grid;
|
|
min-width: 0;
|
|
gap: 3px;
|
|
}
|
|
|
|
.task-row__main strong,
|
|
.task-row__main small,
|
|
.task-row__main em {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.task-row__main strong {
|
|
color: var(--th-color-slate-900);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.task-row__main small {
|
|
color: var(--th-color-slate-500);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.task-row__main em {
|
|
color: var(--th-color-success);
|
|
font-size: 11px;
|
|
font-style: normal;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.task-row__reason--blocked {
|
|
color: var(--th-color-warning);
|
|
}
|
|
|
|
.task-row__actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.task-row__link,
|
|
.task-row__pending {
|
|
color: var(--th-color-slate-500);
|
|
font-size: 11px;
|
|
font-weight: 800;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.task-row__link {
|
|
color: var(--th-color-blue-600);
|
|
}
|
|
</style>
|