Files
policy-ui/app/components/back-office/KanbanTaskCard.vue
2026-04-29 16:25:11 -05:00

111 lines
3.5 KiB
Vue

<script setup lang="ts">
const props = defineProps<{
task: any
urgent?: boolean
}>()
const emit = defineEmits<{
click: [task: any]
}>()
const policyTypeColors: Record<string, string> = {
car: 'bg-blue-100 text-blue-700',
life: 'bg-violet-100 text-violet-700',
fire: 'bg-amber-100 text-amber-700'
}
function onClick() {
emit('click', props.task)
}
function daysInStage(createdAt: string): string {
const days = Math.floor((Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24))
return days === 0 ? 'Today' : `${days}d`
}
function formatDate(date: string, format: 'short' = 'short'): string {
if (!date) return '—'
const d = new Date(date)
if (format === 'short') {
return d.toLocaleDateString('es-PA', { month: 'short', day: 'numeric' })
}
return d.toLocaleDateString('es-PA', {
day: '2-digit',
month: 'short',
year: 'numeric'
})
}
</script>
<template>
<div
class="kanban-task-card rounded-xl border px-3.5 py-3 shadow-sm ring-1 transition hover:shadow-md"
:class="urgent
? 'border-rose-300 bg-rose-50/50 ring-rose-100 hover:border-rose-400'
: 'border-[var(--card-border)] bg-[var(--surface)] ring-[var(--surface)] hover:border-[var(--brand)]/30'"
@click="onClick"
>
<!-- Header row: Application ID + Policy type badge -->
<div class="flex items-start justify-between gap-1 mb-1">
<p class="text-[13px] font-mono font-semibold leading-tight text-[var(--text-primary)] truncate">
{{ task.application_id }}
</p>
<span
class="ml-1 shrink-0 rounded-md px-1.5 py-0.5 text-[10px] font-semibold"
:class="policyTypeColors[task.policy_type] || 'bg-gray-100 text-gray-700'"
>
{{ task.policy_type?.toUpperCase() }}
</span>
</div>
<!-- Provider name -->
<p class="text-[12px] text-[var(--text-muted)] truncate">
{{ task.provider_name || 'Unknown Provider' }}
</p>
<!-- Urgent flag -->
<span v-if="urgent" class="mt-1.5 inline-flex items-center gap-1 rounded-full bg-rose-100 px-1.5 py-0.5 text-[9px] font-bold uppercase tracking-wide text-rose-600">
<span class="h-1.5 w-1.5 rounded-full bg-rose-500" />
Urgent
</span>
<!-- Meta row -->
<div class="mt-2.5 flex items-center justify-between border-t border-[var(--divider)] pt-2">
<div class="flex items-center gap-1">
<!-- Assignee -->
<div v-if="task.assignee" class="flex items-center gap-1 text-[11px] text-[var(--text-muted)]">
<UIcon name="i-heroicons-user" class="w-3 h-3" />
<span class="truncate max-w-[60px]">{{ task.assignee.name }}</span>
</div>
<div v-else class="flex items-center gap-1 text-[11px] text-[var(--text-muted)] opacity-50">
<UIcon name="i-heroicons-user-minus" class="w-3 h-3" />
<span>Unassigned</span>
</div>
</div>
<div class="flex items-center gap-1.5 text-[11px] text-[var(--text-muted)]">
<!-- Due date if present -->
<span v-if="task.due_date" class="truncate">
Due: {{ formatDate(task.due_date, 'short') }}
</span>
<!-- Days in stage -->
<span class="flex items-center gap-0.5">
<UIcon name="i-heroicons-clock" class="w-3 h-3" />
{{ daysInStage(task.created_at) }}
</span>
</div>
</div>
</div>
</template>
<style scoped>
.kanban-task-card {
cursor: pointer;
transition: all 0.15s ease;
}
.kanban-task-card:hover {
transform: translateY(-1px);
}
</style>