add workload plans
Some checks failed
Build and Publish / build-release (push) Failing after 18m53s

This commit is contained in:
2026-04-20 16:24:55 -05:00
parent 7a853b94b6
commit 59c4c4626d
6 changed files with 369 additions and 350 deletions

View File

@@ -0,0 +1,177 @@
<script setup lang="ts">
import type { SelectItem } from '@nuxt/ui'
const page = ref(1)
const statusFilter = ref<string | null>(null)
const policyTypeFilter = ref<string | null>(null)
const statusItems = ref<SelectItem[]>([
{ label: 'All Statuses', value: null },
{ label: 'Created', value: 'created' },
{ label: 'Draft', value: 'draft' },
{ label: 'Approved', value: 'approved' },
{ label: 'Completed', value: 'completed' }
])
const policyTypeItems = ref<SelectItem[]>([
{ label: 'All Types', value: null },
{ label: 'Car', value: 'car' },
{ label: 'Life', value: 'life' },
{ label: 'Fire', value: 'fire' }
])
watch([statusFilter, policyTypeFilter], () => { page.value = 1 })
const { data, pending, error, refresh } = useWorkload('/tasks', {
query: computed(() => ({
page: page.value,
page_size: 20,
...(statusFilter.value && { status: statusFilter.value }),
...(policyTypeFilter.value && { policy_type: policyTypeFilter.value })
}))
})
const tasks = computed(() => data.value?.data ?? [])
const meta = computed(() => data.value?.meta)
const total = computed(() => meta.value?.total_count ?? 0)
const totalPages = computed(() => meta.value?.total_pages ?? 0)
const statusColor = (status: string) => {
switch (status) {
case 'created': return 'yellow'
case 'draft': return 'blue'
case 'approved': return 'green'
case 'completed': return 'gray'
default: return 'gray'
}
}
const policyTypeColor = (type: string) => {
switch (type) {
case 'car': return 'blue'
case 'life': return 'purple'
case 'fire': return 'orange'
default: return 'gray'
}
}
const getTaskType = (id: string) => {
const parts = id?.split(':') ?? []
return parts[1] || 'unknown'
}
const formatDate = (date: string) => {
if (!date) return '—'
return new Date(date).toLocaleDateString('es-PA', {
day: '2-digit', month: 'short', year: 'numeric',
hour: '2-digit', minute: '2-digit'
})
}
</script>
<template>
<div class="p-8 space-y-8 bg-gray-50 min-h-screen">
<!-- Header -->
<div class="flex justify-between items-center">
<div>
<h1 class="text-3xl text-slate-900 font-bold">Workload</h1>
<p class="text-gray-500 text-sm">Quote & Solicitation Tasks</p>
</div>
<div class="flex items-center gap-3">
<UBadge color="gray" variant="soft" size="lg">{{ total }} tasks</UBadge>
<UButton
icon="i-heroicons-arrow-path"
color="gray"
variant="soft"
:loading="pending"
@click="refresh()"
>
Refresh
</UButton>
</div>
</div>
<!-- Filters -->
<div class="flex gap-4 items-center flex-wrap">
<USelect v-model="statusFilter" :items="statusItems" class="w-40" />
<USelect v-model="policyTypeFilter" :items="policyTypeItems" class="w-40" />
</div>
<UAlert
v-if="error"
color="red"
variant="soft"
title="Failed to load tasks"
:description="error.message"
/>
<div v-else-if="pending && tasks.length === 0" class="grid gap-4">
<UCard v-for="n in 5" :key="n">
<div class="h-20 animate-pulse bg-gray-200 rounded" />
</UCard>
</div>
<template v-else>
<div class="space-y-3" :class="pending ? 'opacity-60 pointer-events-none' : ''">
<NuxtLink
v-for="task in tasks"
:key="task.id"
:to="`/workload/${encodeURIComponent(task.id)}`"
>
<UCard class="hover:shadow-md transition-shadow cursor-pointer">
<div class="flex items-center justify-between gap-4">
<!-- Left -->
<div class="flex items-center gap-4 min-w-0">
<div class="flex flex-col gap-1">
<UBadge :color="statusColor(task.status)" variant="soft" size="xs">
{{ task.status }}
</UBadge>
<UBadge :color="policyTypeColor(task.task_info?.policy_type)" variant="outline" size="xs">
{{ task.task_info?.policy_type?.toUpperCase() || '—' }}
</UBadge>
</div>
<div class="min-w-0">
<p class="font-mono text-sm font-medium text-slate-800 truncate">
{{ task.application_id }}
</p>
<p class="text-xs text-gray-400">
Provider: <span class="font-mono">{{ task.provider_id }}</span>
</p>
</div>
</div>
<!-- Right -->
<div class="flex items-center gap-6 flex-shrink-0 text-sm text-gray-500">
<div class="text-right">
<p class="text-xs text-gray-400">Type</p>
<UBadge color="gray" variant="soft" size="xs">{{ getTaskType(task.id) }}</UBadge>
</div>
<div class="text-right">
<p class="text-xs text-gray-400">Received</p>
<p>{{ formatDate(task.created_at) }}</p>
</div>
<UIcon name="i-heroicons-chevron-right" class="w-4 h-4 text-gray-400" />
</div>
</div>
</UCard>
</NuxtLink>
<div v-if="tasks.length === 0 && !pending" class="text-center py-16 text-gray-400">
<UIcon name="i-heroicons-inbox" class="w-12 h-12 mx-auto mb-4" />
<p class="text-lg font-medium">No tasks found</p>
<p class="text-sm">Adjust your filters or wait for new requests</p>
</div>
</div>
<!-- Pagination -->
<div v-if="totalPages > 1" class="flex justify-center">
<UPagination
v-model="page"
:total="total"
:page-count="20"
/>
</div>
</template>
</div>
</template>