Updated mobile view for field jobs

This commit is contained in:
Simon Pocrnjič
2026-04-16 23:11:49 +02:00
parent 187cb4f127
commit 8f8c5c5a12
4 changed files with 896 additions and 614 deletions
+157 -52
View File
@@ -17,6 +17,11 @@ import {
import { Button } from "@/Components/ui/button";
import { Badge } from "@/Components/ui/badge";
import { Separator } from "@/Components/ui/separator";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/Components/ui/collapsible";
import {
Dialog,
DialogContent,
@@ -41,6 +46,7 @@ import { Checkbox } from "@/Components/ui/checkbox";
import {
ArrowLeft,
CheckCircle2,
ChevronDown,
FileText,
Calendar,
Euro,
@@ -370,64 +376,163 @@ const clientSummary = computed(() => {
<Card
v-for="c in contracts"
:key="c.uuid || c.id"
class="border-l-4 border-l-indigo-500"
class="border-l-4 border-l-indigo-500 overflow-hidden"
>
<CardHeader class="pb-3">
<div class="flex items-start justify-between gap-3">
<div class="min-w-0 flex-1">
<div class="flex items-center gap-2 flex-wrap">
<CardTitle class="text-sm">
{{ c.reference || c.uuid }}
</CardTitle>
<Badge v-if="c.type?.name" variant="secondary" class="text-[11px]">
{{ c.type.name }}
</Badge>
</div>
<div v-if="c.account" class="mt-3 flex items-center gap-2">
<Euro class="w-4 h-4 text-gray-400" />
<div class="flex items-baseline gap-2">
<span class="text-xs text-gray-500 uppercase">Odprto</span>
<span
class="text-lg font-semibold text-gray-900 dark:text-gray-100"
>
{{ formatAmount(c.account.balance_amount) }}
</span>
</div>
</div>
</div>
<div class="flex flex-col gap-2 shrink-0">
<Button size="sm" @click="openDrawerAddActivity(c)">
<Plus class="w-4 h-4 mr-1" />
Aktivnost
</Button>
<Button size="sm" variant="secondary" @click="openDocDialog(c)">
<Upload class="w-4 h-4 mr-1" />
Dokument
</Button>
</div>
<!-- Contract header: reference + type badge -->
<CardHeader class="pb-2">
<div class="flex items-center gap-2 flex-wrap">
<CardTitle class="text-base font-semibold">
{{ c.reference || c.uuid }}
</CardTitle>
<Badge v-if="c.type?.name" variant="secondary" class="text-[11px]">
{{ c.type.name }}
</Badge>
</div>
</CardHeader>
<CardContent v-if="c.last_object" class="pt-0">
<Separator class="mb-3" />
<div class="space-y-1">
<p class="text-xs text-gray-500 uppercase">Zadnji predmet</p>
<div class="text-sm font-medium text-gray-800 dark:text-gray-200">
{{ c.last_object.name || c.last_object.reference }}
<span
v-if="c.last_object.type"
class="ml-2 text-xs font-normal text-gray-500"
>
({{ c.last_object.type }})
</span>
</div>
<div
v-if="c.last_object.description"
class="text-sm text-gray-600 dark:text-gray-400"
<!-- Balance row -->
<div
v-if="c.account"
class="mx-4 mb-3 rounded-xl bg-red-50 dark:bg-red-950/20 border border-red-100 dark:border-red-900 px-4 py-3 flex items-center justify-between"
>
<div class="flex items-center gap-2 text-red-500">
<Euro class="w-4 h-4 shrink-0" />
<span class="text-xs font-medium uppercase tracking-wide text-red-400"
>Odprto</span
>
{{ c.last_object.description }}
</div>
</div>
<span
class="text-2xl font-bold text-red-600 dark:text-red-400 tabular-nums"
>
{{ formatAmount(c.account.balance_amount) }}
</span>
</div>
<!-- Collapsibles: description, meta, last object -->
<CardContent
v-if="
c.description || c.last_object || (c.meta && Object.keys(c.meta).length)
"
class="pt-0 px-4 space-y-0"
>
<!-- Description -->
<template v-if="c.description">
<Separator class="mb-3" />
<Collapsible>
<CollapsibleTrigger
class="flex items-center gap-1.5 text-xs text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 group w-full py-1"
>
<ChevronDown
class="w-3.5 h-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180 shrink-0"
/>
<span class="uppercase tracking-wide font-medium">Opis</span>
</CollapsibleTrigger>
<CollapsibleContent>
<p
class="mt-1.5 mb-2 text-sm text-gray-700 dark:text-gray-300 whitespace-pre-line rounded-lg bg-gray-50 dark:bg-gray-800/50 px-3 py-2.5"
>
{{ c.description }}
</p>
</CollapsibleContent>
</Collapsible>
</template>
<!-- Meta -->
<template v-if="c.meta && Object.keys(c.meta).length">
<Separator class="mb-3" :class="c.description ? 'mt-2' : 'mt-0'" />
<Collapsible>
<CollapsibleTrigger
class="flex items-center gap-1.5 text-xs text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 group w-full py-1"
>
<ChevronDown
class="w-3.5 h-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180 shrink-0"
/>
<span class="uppercase tracking-wide font-medium"
>Dodatni podatki</span
>
<span class="ml-auto text-gray-400 font-normal">{{
Object.keys(c.meta).length
}}</span>
</CollapsibleTrigger>
<CollapsibleContent>
<div
class="mt-1.5 mb-2 divide-y divide-gray-100 dark:divide-gray-700 rounded-lg border border-gray-100 dark:border-gray-700 overflow-hidden"
>
<div
v-for="(val, key) in c.meta"
:key="key"
class="flex items-center justify-between gap-3 px-3 py-2 bg-white dark:bg-gray-900 even:bg-gray-50/60 dark:even:bg-gray-800/40"
>
<span
class="text-xs text-gray-500 dark:text-gray-400 shrink-0"
>{{ val?.title || key }}</span
>
<span
class="text-xs font-semibold text-gray-800 dark:text-gray-200 text-right"
>
<template v-if="val?.type === 'date'">{{
formatDateShort(val.value) || val.value || "—"
}}</template>
<template v-else-if="val?.type === 'number'">{{
val.value ?? "—"
}}</template>
<template v-else>{{ val?.value ?? val ?? "—" }}</template>
</span>
</div>
</div>
</CollapsibleContent>
</Collapsible>
</template>
<!-- Last object -->
<template v-if="c.last_object">
<Separator
class="mb-3"
:class="
c.description || (c.meta && Object.keys(c.meta).length)
? 'mt-2'
: 'mt-0'
"
/>
<div class="py-1 space-y-1">
<p class="text-xs text-gray-400 uppercase tracking-wide font-medium">
Zadnji predmet
</p>
<p class="text-sm font-medium text-gray-800 dark:text-gray-200">
{{ c.last_object.name || c.last_object.reference }}
<span
v-if="c.last_object.type"
class="ml-1.5 text-xs font-normal text-gray-400"
>({{ c.last_object.type }})</span
>
</p>
<p
v-if="c.last_object.description"
class="text-xs text-gray-500 dark:text-gray-400"
>
{{ c.last_object.description }}
</p>
</div>
</template>
</CardContent>
<!-- Action buttons: full-width row at bottom -->
<div class="grid grid-cols-2 gap-0 border-t mt-1">
<button
class="flex items-center justify-center gap-2 py-3 text-sm font-medium text-primary hover:bg-primary/5 active:bg-primary/10 transition-colors border-r"
@click="openDrawerAddActivity(c)"
>
<Plus class="w-4 h-4" />
Aktivnost
</button>
<button
class="flex items-center justify-center gap-2 py-3 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 active:bg-gray-100 transition-colors"
@click="openDocDialog(c)"
>
<Upload class="w-4 h-4" />
Dokument
</button>
</div>
</Card>
<p
v-if="!contracts?.length"