Changes to phone view, fixed infinity scroll issues with page refresh, updated design a bit
This commit is contained in:
parent
8f8c5c5a12
commit
92f54f7103
|
|
@ -17,6 +17,11 @@ public function index(Request $request): \Inertia\Response
|
||||||
$search = $request->input('search');
|
$search = $request->input('search');
|
||||||
$clientFilter = $request->input('client');
|
$clientFilter = $request->input('client');
|
||||||
|
|
||||||
|
// On full page loads, always start from page 1
|
||||||
|
if (! $request->header('X-Inertia-Partial-Data')) {
|
||||||
|
$request->merge(['pending' => 1, 'processed' => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
$eagerLoad = [
|
$eagerLoad = [
|
||||||
'contract' => function ($q) {
|
'contract' => function ($q) {
|
||||||
$q->with([
|
$q->with([
|
||||||
|
|
@ -97,6 +102,11 @@ public function completedToday(Request $request): \Inertia\Response
|
||||||
$search = $request->input('search');
|
$search = $request->input('search');
|
||||||
$clientFilter = $request->input('client');
|
$clientFilter = $request->input('client');
|
||||||
|
|
||||||
|
// On full page loads, always start from page 1
|
||||||
|
if (! $request->header('X-Inertia-Partial-Data')) {
|
||||||
|
$request->merge(['completed' => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
$start = now()->startOfDay();
|
$start = now()->startOfDay();
|
||||||
$end = now()->endOfDay();
|
$end = now()->endOfDay();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import {
|
||||||
} from "@/Components/ui/select";
|
} from "@/Components/ui/select";
|
||||||
import { Switch } from "@/Components/ui/switch";
|
import { Switch } from "@/Components/ui/switch";
|
||||||
import { Button } from "@/Components/ui/button";
|
import { Button } from "@/Components/ui/button";
|
||||||
|
import { ScrollArea } from "@/Components/ui/scroll-area";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: { type: Boolean, default: false },
|
show: { type: Boolean, default: false },
|
||||||
|
|
@ -452,11 +453,57 @@ const open = computed({
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<form @submit.prevent="onSubmit" class="space-y-4">
|
<ScrollArea class="max-h-[65vh] pr-1">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<form @submit.prevent="onSubmit" class="space-y-4 pr-3">
|
||||||
<FormField v-slot="{ value, handleChange }" name="profile_id">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<FormField v-slot="{ value, handleChange }" name="profile_id">
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Profil</FormLabel>
|
||||||
|
<Select :model-value="value" @update:model-value="handleChange">
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="—" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem :value="null">—</SelectItem>
|
||||||
|
<SelectItem v-for="p in pageSmsProfiles" :key="p.id" :value="p.id">
|
||||||
|
{{ p.name || "Profil #" + p.id }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField v-slot="{ value, handleChange }" name="sender_id">
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Pošiljatelj</FormLabel>
|
||||||
|
<Select :model-value="value" @update:model-value="handleChange">
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="—" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem :value="null">—</SelectItem>
|
||||||
|
<SelectItem
|
||||||
|
v-for="s in sendersForSelectedProfile"
|
||||||
|
:key="s.id"
|
||||||
|
:value="s.id"
|
||||||
|
>
|
||||||
|
{{ s.name || s.phone || "Sender #" + s.id }}
|
||||||
|
</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FormField v-slot="{ value, handleChange }" name="contract_uuid">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Profil</FormLabel>
|
<FormLabel>Pogodba</FormLabel>
|
||||||
<Select :model-value="value" @update:model-value="handleChange">
|
<Select :model-value="value" @update:model-value="handleChange">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
|
|
@ -465,18 +512,22 @@ const open = computed({
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem :value="null">—</SelectItem>
|
<SelectItem :value="null">—</SelectItem>
|
||||||
<SelectItem v-for="p in pageSmsProfiles" :key="p.id" :value="p.id">
|
<SelectItem v-for="c in contractsForCase" :key="c.uuid" :value="c.uuid">
|
||||||
{{ p.name || "Profil #" + p.id }}
|
{{ c.reference || c.uuid }}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
<p class="mt-1 text-xs text-gray-500">
|
||||||
|
Uporabi podatke pogodbe (in računa) za zapolnitev {contract.*} in
|
||||||
|
{account.*} mest.
|
||||||
|
</p>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField v-slot="{ value, handleChange }" name="sender_id">
|
<FormField v-slot="{ value, handleChange }" name="template_id">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Pošiljatelj</FormLabel>
|
<FormLabel>Predloga</FormLabel>
|
||||||
<Select :model-value="value" @update:model-value="handleChange">
|
<Select :model-value="value" @update:model-value="handleChange">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
|
|
@ -485,125 +536,77 @@ const open = computed({
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem :value="null">—</SelectItem>
|
<SelectItem :value="null">—</SelectItem>
|
||||||
<SelectItem
|
<SelectItem v-for="t in pageSmsTemplates" :key="t.id" :value="t.id">
|
||||||
v-for="s in sendersForSelectedProfile"
|
{{ t.name || "Predloga #" + t.id }}
|
||||||
:key="s.id"
|
|
||||||
:value="s.id"
|
|
||||||
>
|
|
||||||
{{ s.name || s.phone || "Sender #" + s.id }}
|
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</FormField>
|
</FormField>
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormField v-slot="{ value, handleChange }" name="contract_uuid">
|
<FormField v-slot="{ componentField }" name="message">
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Pogodba</FormLabel>
|
<FormLabel>Vsebina sporočila</FormLabel>
|
||||||
<Select :model-value="value" @update:model-value="handleChange">
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<SelectTrigger>
|
<Textarea
|
||||||
<SelectValue placeholder="—" />
|
rows="4"
|
||||||
</SelectTrigger>
|
placeholder="Vpišite SMS vsebino..."
|
||||||
|
v-bind="componentField"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<SelectContent>
|
<FormMessage />
|
||||||
<SelectItem :value="null">—</SelectItem>
|
</FormItem>
|
||||||
<SelectItem v-for="c in contractsForCase" :key="c.uuid" :value="c.uuid">
|
</FormField>
|
||||||
{{ c.reference || c.uuid }}
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<p class="mt-1 text-xs text-gray-500">
|
|
||||||
Uporabi podatke pogodbe (in računa) za zapolnitev {contract.*} in
|
|
||||||
{account.*} mest.
|
|
||||||
</p>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<FormField v-slot="{ value, handleChange }" name="template_id">
|
<!-- Live counters -->
|
||||||
<FormItem>
|
<div class="text-xs text-gray-600 flex flex-col gap-1">
|
||||||
<FormLabel>Predloga</FormLabel>
|
<div>
|
||||||
<Select :model-value="value" @update:model-value="handleChange">
|
<span class="font-medium">Znakov:</span>
|
||||||
<FormControl>
|
<span class="font-mono">{{ charCount }}</span>
|
||||||
<SelectTrigger>
|
<span class="mx-2">|</span>
|
||||||
<SelectValue placeholder="—" />
|
<span class="font-medium">Kodiranje:</span>
|
||||||
</SelectTrigger>
|
<span>{{ smsEncoding }}</span>
|
||||||
</FormControl>
|
<span class="mx-2">|</span>
|
||||||
<SelectContent>
|
<span class="font-medium">Deli SMS:</span>
|
||||||
<SelectItem :value="null">—</SelectItem>
|
<span class="font-mono">{{ segments }}</span>
|
||||||
<SelectItem v-for="t in pageSmsTemplates" :key="t.id" :value="t.id">
|
<span class="mx-2">|</span>
|
||||||
{{ t.name || "Predloga #" + t.id }}
|
<span class="font-medium">Krediti:</span>
|
||||||
</SelectItem>
|
<span class="font-mono">{{ creditsNeeded }}</span>
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<FormField v-slot="{ componentField }" name="message">
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>Vsebina sporočila</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Textarea
|
|
||||||
rows="4"
|
|
||||||
placeholder="Vpišite SMS vsebino..."
|
|
||||||
v-bind="componentField"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<!-- Live counters -->
|
|
||||||
<div class="text-xs text-gray-600 flex flex-col gap-1">
|
|
||||||
<div>
|
|
||||||
<span class="font-medium">Znakov:</span>
|
|
||||||
<span class="font-mono">{{ charCount }}</span>
|
|
||||||
<span class="mx-2">|</span>
|
|
||||||
<span class="font-medium">Kodiranje:</span>
|
|
||||||
<span>{{ smsEncoding }}</span>
|
|
||||||
<span class="mx-2">|</span>
|
|
||||||
<span class="font-medium">Deli SMS:</span>
|
|
||||||
<span class="font-mono">{{ segments }}</span>
|
|
||||||
<span class="mx-2">|</span>
|
|
||||||
<span class="font-medium">Krediti:</span>
|
|
||||||
<span class="font-mono">{{ creditsNeeded }}</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span class="font-medium">Omejitev:</span>
|
|
||||||
<span class="font-mono">{{ maxAllowed }}</span>
|
|
||||||
<span class="mx-2">|</span>
|
|
||||||
<span class="font-medium">Preostanek:</span>
|
|
||||||
<span class="font-mono" :class="{ 'text-red-600': remaining === 0 }">
|
|
||||||
{{ remaining }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p class="text-[11px] text-gray-500 leading-snug">
|
|
||||||
Dolžina 160 znakov velja samo pri pošiljanju sporočil, ki vsebujejo znake, ki
|
|
||||||
ne zahtevajo enkodiranja. Če npr. želite pošiljati šumnike, ki niso del
|
|
||||||
7-bitne abecede GSM, morate uporabiti Unicode enkodiranje (UCS‑2). V tem
|
|
||||||
primeru je največja dolžina enega SMS sporočila 70 znakov (pri daljših
|
|
||||||
sporočilih 67 znakov na del), medtem ko je pri GSM‑7 160 znakov (pri daljših
|
|
||||||
sporočilih 153 znakov na del). Razširjeni znaki (^{{ "{" }}}}\\[]~| in €)
|
|
||||||
štejejo dvojno. Največja dovoljena dolžina po ponudniku: 640 (GSM‑7) oziroma
|
|
||||||
320 (UCS‑2) znakov.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormField v-slot="{ value, handleChange }" name="delivery_report">
|
|
||||||
<FormItem class="flex flex-row items-start space-x-3 space-y-0">
|
|
||||||
<FormControl>
|
|
||||||
<Switch :model-value="value" @update:model-value="handleChange" />
|
|
||||||
</FormControl>
|
|
||||||
<div class="space-y-1 leading-none">
|
|
||||||
<FormLabel>Zahtevaj poročilo o dostavi</FormLabel>
|
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
<div>
|
||||||
</FormField>
|
<span class="font-medium">Omejitev:</span>
|
||||||
</form>
|
<span class="font-mono">{{ maxAllowed }}</span>
|
||||||
|
<span class="mx-2">|</span>
|
||||||
|
<span class="font-medium">Preostanek:</span>
|
||||||
|
<span class="font-mono" :class="{ 'text-red-600': remaining === 0 }">
|
||||||
|
{{ remaining }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-[11px] text-gray-500 leading-snug">
|
||||||
|
Dolžina 160 znakov velja samo pri pošiljanju sporočil, ki vsebujejo znake,
|
||||||
|
ki ne zahtevajo enkodiranja. Če npr. želite pošiljati šumnike, ki niso del
|
||||||
|
7-bitne abecede GSM, morate uporabiti Unicode enkodiranje (UCS‑2). V tem
|
||||||
|
primeru je največja dolžina enega SMS sporočila 70 znakov (pri daljših
|
||||||
|
sporočilih 67 znakov na del), medtem ko je pri GSM‑7 160 znakov (pri daljših
|
||||||
|
sporočilih 153 znakov na del). Razširjeni znaki (^{{ "{" }}}}\\[]~| in €)
|
||||||
|
štejejo dvojno. Največja dovoljena dolžina po ponudniku: 640 (GSM‑7) oziroma
|
||||||
|
320 (UCS‑2) znakov.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<FormField v-slot="{ value, handleChange }" name="delivery_report">
|
||||||
|
<FormItem class="flex flex-row items-start space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<Switch :model-value="value" @update:model-value="handleChange" />
|
||||||
|
</FormControl>
|
||||||
|
<div class="space-y-1 leading-none">
|
||||||
|
<FormLabel>Zahtevaj poročilo o dostavi</FormLabel>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
</form>
|
||||||
|
</ScrollArea>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button variant="outline" @click="closeSmsDialog" :disabled="processing">
|
<Button variant="outline" @click="closeSmsDialog" :disabled="processing">
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ const closeSearch = () => (searchOpen.value = false);
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Page Heading -->
|
<!-- Page Heading -->
|
||||||
<header v-if="$slots.header" class="bg-white border-b border-gray-200 shadow-sm">
|
<header v-if="$slots.header" class="sticky top-16 z-20 bg-white border-b border-gray-200 shadow-sm dark:bg-gray-900 dark:border-gray-700">
|
||||||
<div class="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8 space-y-2">
|
<div class="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8 space-y-2">
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
v-if="$page.props.breadcrumbs && $page.props.breadcrumbs.length"
|
v-if="$page.props.breadcrumbs && $page.props.breadcrumbs.length"
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,11 @@ import { Button } from "@/Components/ui/button";
|
||||||
import { Badge } from "@/Components/ui/badge";
|
import { Badge } from "@/Components/ui/badge";
|
||||||
import { Separator } from "@/Components/ui/separator";
|
import { Separator } from "@/Components/ui/separator";
|
||||||
import {
|
import {
|
||||||
Collapsible,
|
Accordion,
|
||||||
CollapsibleContent,
|
AccordionContent,
|
||||||
CollapsibleTrigger,
|
AccordionItem,
|
||||||
} from "@/Components/ui/collapsible";
|
AccordionTrigger,
|
||||||
|
} from "@/Components/ui/accordion";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
|
@ -46,7 +47,6 @@ import { Checkbox } from "@/Components/ui/checkbox";
|
||||||
import {
|
import {
|
||||||
ArrowLeft,
|
ArrowLeft,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
ChevronDown,
|
|
||||||
FileText,
|
FileText,
|
||||||
Calendar,
|
Calendar,
|
||||||
Euro,
|
Euro,
|
||||||
|
|
@ -321,7 +321,7 @@ const clientSummary = computed(() => {
|
||||||
<div class="py-4 sm:py-6">
|
<div class="py-4 sm:py-6">
|
||||||
<div class="mx-auto max-w-5xl px-2 sm:px-4 space-y-4">
|
<div class="mx-auto max-w-5xl px-2 sm:px-4 space-y-4">
|
||||||
<!-- Client details (account holder) -->
|
<!-- Client details (account holder) -->
|
||||||
<Card>
|
<Card class="gap-3">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle class="flex items-center gap-2 text-base">
|
<CardTitle class="flex items-center gap-2 text-base">
|
||||||
<Building2 class="w-5 h-5 text-gray-500" />
|
<Building2 class="w-5 h-5 text-gray-500" />
|
||||||
|
|
@ -340,8 +340,8 @@ const clientSummary = computed(() => {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Person (case person) -->
|
<!-- Person (case person) -->
|
||||||
<Card>
|
<Card class="gap-3">
|
||||||
<CardHeader>
|
<CardHeader class="px-3">
|
||||||
<CardTitle class="flex items-center gap-2 text-base">
|
<CardTitle class="flex items-center gap-2 text-base">
|
||||||
<User class="w-5 h-5 text-gray-500" />
|
<User class="w-5 h-5 text-gray-500" />
|
||||||
<span class="truncate">{{ client_case.person.full_name }}</span>
|
<span class="truncate">{{ client_case.person.full_name }}</span>
|
||||||
|
|
@ -354,7 +354,7 @@ const clientSummary = computed(() => {
|
||||||
{{ client_case.person.description }}
|
{{ client_case.person.description }}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent class="px-3">
|
||||||
<Separator class="mb-4" />
|
<Separator class="mb-4" />
|
||||||
<PersonDetailPhone
|
<PersonDetailPhone
|
||||||
:types="types"
|
:types="types"
|
||||||
|
|
@ -365,35 +365,32 @@ const clientSummary = computed(() => {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<!-- Contracts assigned to me -->
|
<!-- Contracts assigned to me -->
|
||||||
<Card>
|
<Card class="p-0 pt-3 gap-1">
|
||||||
<CardHeader>
|
<CardHeader class="px-4">
|
||||||
<CardTitle class="flex items-center gap-2">
|
<CardTitle class="flex items-center gap-2">
|
||||||
<FileText class="w-5 h-5" />
|
<FileText class="w-5 h-5" />
|
||||||
Pogodbe
|
Pogodbe
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="space-y-3">
|
<CardContent class="p-2">
|
||||||
<Card
|
<Card
|
||||||
v-for="c in contracts"
|
v-for="c in contracts"
|
||||||
:key="c.uuid || c.id"
|
:key="c.uuid || c.id"
|
||||||
class="border-l-4 border-l-indigo-500 overflow-hidden"
|
class="overflow-hidden p-0 gap-3"
|
||||||
>
|
>
|
||||||
<!-- Contract header: reference + type badge -->
|
<!-- Contract header: reference + type badge -->
|
||||||
<CardHeader class="pb-2">
|
<CardHeader class="p-3 pb-2">
|
||||||
<div class="flex items-center gap-2 flex-wrap">
|
<div class="flex items-center flex-wrap">
|
||||||
<CardTitle class="text-base font-semibold">
|
<CardTitle class="text-base font-semibold">
|
||||||
{{ c.reference || c.uuid }}
|
{{ c.reference || "Šifra pogodbe ni določena" }}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Badge v-if="c.type?.name" variant="secondary" class="text-[11px]">
|
|
||||||
{{ c.type.name }}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<!-- Balance row -->
|
<!-- Balance row -->
|
||||||
<div
|
<div
|
||||||
v-if="c.account"
|
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"
|
class="mx-3 rounded-xl bg-red-50 dark:bg-red-950/20 border border-red-100 dark:border-red-900 px-2 py-2 flex items-center justify-between"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2 text-red-500">
|
<div class="flex items-center gap-2 text-red-500">
|
||||||
<Euro class="w-4 h-4 shrink-0" />
|
<Euro class="w-4 h-4 shrink-0" />
|
||||||
|
|
@ -413,75 +410,76 @@ const clientSummary = computed(() => {
|
||||||
v-if="
|
v-if="
|
||||||
c.description || c.last_object || (c.meta && Object.keys(c.meta).length)
|
c.description || c.last_object || (c.meta && Object.keys(c.meta).length)
|
||||||
"
|
"
|
||||||
class="pt-0 px-4 space-y-0"
|
class="pt-0 px-0 space-y-0"
|
||||||
>
|
>
|
||||||
<!-- Description -->
|
<!-- Description + Meta Accordion -->
|
||||||
<template v-if="c.description">
|
<template v-if="c.description || (c.meta && Object.keys(c.meta).length)">
|
||||||
<Separator class="mb-3" />
|
<Separator />
|
||||||
<Collapsible>
|
<Accordion type="multiple" class="w-full">
|
||||||
<CollapsibleTrigger
|
<AccordionItem
|
||||||
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"
|
v-if="c.description"
|
||||||
|
value="description"
|
||||||
|
class="border-b-0"
|
||||||
>
|
>
|
||||||
<ChevronDown
|
<AccordionTrigger
|
||||||
class="w-3.5 h-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180 shrink-0"
|
class="px-3 py-2 text-xs font-medium uppercase tracking-wide hover:no-underline"
|
||||||
/>
|
|
||||||
<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 }}
|
Opis
|
||||||
</p>
|
</AccordionTrigger>
|
||||||
</CollapsibleContent>
|
<AccordionContent class="px-3 pb-3">
|
||||||
</Collapsible>
|
<p
|
||||||
</template>
|
class="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"
|
||||||
|
|
||||||
<!-- 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
|
{{ c.description }}
|
||||||
class="text-xs text-gray-500 dark:text-gray-400 shrink-0"
|
</p>
|
||||||
>{{ val?.title || key }}</span
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
<AccordionItem
|
||||||
|
v-if="c.meta && Object.keys(c.meta).length"
|
||||||
|
value="meta"
|
||||||
|
class="border-b-0"
|
||||||
|
:class="c.description ? 'border-t' : ''"
|
||||||
|
>
|
||||||
|
<AccordionTrigger
|
||||||
|
class="px-3 py-2 text-xs font-medium uppercase tracking-wide hover:no-underline"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span class="mr-1">Dodatni podatki</span>
|
||||||
|
<Badge
|
||||||
|
class="bg-blue-500 text-white dark:bg-blue-600 h-5 min-w-5 rounded-full px-2 font-mono tabular-nums"
|
||||||
|
>{{ Object.keys(c.meta).length }}</Badge
|
||||||
>
|
>
|
||||||
<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>
|
||||||
</div>
|
</AccordionTrigger>
|
||||||
</CollapsibleContent>
|
<AccordionContent class="pb-2">
|
||||||
</Collapsible>
|
<div
|
||||||
|
class="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>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Last object -->
|
<!-- Last object -->
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user