updates to UI and add archiving option
This commit is contained in:
@@ -73,6 +73,27 @@ function formatAmount(val) {
|
||||
});
|
||||
}
|
||||
|
||||
function formatDateShort(val) {
|
||||
if (!val) return "";
|
||||
try {
|
||||
const d = new Date(val);
|
||||
if (Number.isNaN(d.getTime())) return "";
|
||||
return d.toLocaleDateString("sl-SI", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function activityActionLine(a) {
|
||||
const base = a?.action?.name || "";
|
||||
const decision = a?.decision?.name ? ` → ${a.decision.name}` : "";
|
||||
return base + decision;
|
||||
}
|
||||
|
||||
// Activity drawer state
|
||||
const drawerAddActivity = ref(false);
|
||||
const activityContractUuid = ref(null);
|
||||
@@ -139,6 +160,35 @@ const submitComplete = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Contracts objects (Predmeti) modal state
|
||||
const objectsModal = reactive({ open: false, items: [], contract: null });
|
||||
function getContractObjects(c) {
|
||||
if (!c) return [];
|
||||
// Try a few common property names; fallback empty
|
||||
return c.objects || c.contract_objects || c.items || [];
|
||||
}
|
||||
function openObjectsModal(c) {
|
||||
objectsModal.contract = c;
|
||||
objectsModal.items = getContractObjects(c) || [];
|
||||
objectsModal.open = true;
|
||||
}
|
||||
function closeObjectsModal() {
|
||||
objectsModal.open = false;
|
||||
objectsModal.items = [];
|
||||
objectsModal.contract = null;
|
||||
}
|
||||
|
||||
// Client details (Stranka) summary
|
||||
const clientSummary = computed(() => {
|
||||
const p = props.client?.person || {};
|
||||
return {
|
||||
name: p.full_name || p.name || "—",
|
||||
tax: p.tax_number || p.davcna || p.tax || null,
|
||||
emso: p.emso || p.ems || null,
|
||||
trr: p.trr || p.bank_account || null,
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -172,10 +222,13 @@ const submitComplete = () => {
|
||||
<!-- Client details (account holder) -->
|
||||
<div class="bg-white rounded-lg shadow border overflow-hidden">
|
||||
<div class="p-3 sm:p-4">
|
||||
<SectionTitle>
|
||||
<template #title>Stranka</template>
|
||||
</SectionTitle>
|
||||
<div class="mt-2">
|
||||
<h3
|
||||
class="text-base font-semibold text-gray-900 leading-tight flex items-center gap-2"
|
||||
>
|
||||
<span class="truncate">{{ clientSummary.name }}</span>
|
||||
<span class="chip-base chip-indigo">Naročnik</span>
|
||||
</h3>
|
||||
<div class="mt-4 pt-4 border-t border-dashed">
|
||||
<PersonDetailPhone
|
||||
:types="types"
|
||||
:person="client.person"
|
||||
@@ -188,14 +241,17 @@ const submitComplete = () => {
|
||||
<!-- Person (case person) -->
|
||||
<div class="bg-white rounded-lg shadow border overflow-hidden">
|
||||
<div class="p-3 sm:p-4">
|
||||
<SectionTitle>
|
||||
<template #title>Primer - oseba</template>
|
||||
</SectionTitle>
|
||||
<div class="mt-2">
|
||||
<h3
|
||||
class="text-base font-semibold text-gray-900 leading-tight flex items-center gap-2"
|
||||
>
|
||||
<span class="truncate">{{ client_case.person.full_name }}</span>
|
||||
<span class="chip-base chip-indigo">Primer</span>
|
||||
</h3>
|
||||
<div class="mt-4 pt-4 border-t border-dashed">
|
||||
<PersonDetailPhone
|
||||
:types="types"
|
||||
:person="client_case.person"
|
||||
default-tab="phones"
|
||||
default-tab="addresses"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -211,48 +267,82 @@ const submitComplete = () => {
|
||||
<div
|
||||
v-for="c in contracts"
|
||||
:key="c.uuid || c.id"
|
||||
class="rounded border p-3 sm:p-4"
|
||||
class="rounded border p-3 sm:p-4 bg-white shadow-sm"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="font-medium text-gray-900">{{ c.reference || c.uuid }}</p>
|
||||
<p class="text-sm text-gray-600">Tip: {{ c.type?.name || "—" }}</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="space-y-2">
|
||||
<p v-if="c.account" class="text-sm text-gray-700">
|
||||
Odprto: {{ formatAmount(c.account.balance_amount) }} €
|
||||
<!-- Header Row -->
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="min-w-0">
|
||||
<div class="flex items-center gap-2 flex-wrap">
|
||||
<p
|
||||
class="font-semibold text-gray-900 text-sm leading-tight truncate"
|
||||
>
|
||||
{{ c.reference || c.uuid }}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
class="text-sm px-3 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-700 w-full sm:w-auto"
|
||||
@click="openDrawerAddActivity(c)"
|
||||
<span
|
||||
v-if="c.type?.name"
|
||||
class="inline-flex items-center px-2 py-0.5 rounded-full bg-indigo-100 text-indigo-700 text-[11px] font-medium"
|
||||
>
|
||||
+ Aktivnost
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="text-sm px-3 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-700 w-full sm:w-auto"
|
||||
@click="openDocDialog(c)"
|
||||
{{ c.type.name }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="c.account" class="mt-2 flex items-baseline gap-2">
|
||||
<span class="uppercase tracking-wide text-[11px] text-gray-400"
|
||||
>Odprto</span
|
||||
>
|
||||
<span
|
||||
class="text-lg font-semibold text-gray-900 leading-none tracking-tight"
|
||||
>{{ formatAmount(c.account.balance_amount) }} €</span
|
||||
>
|
||||
+ Dokument
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1.5 w-32 text-right shrink-0">
|
||||
<button
|
||||
type="button"
|
||||
class="text-sm px-3 py-2 rounded-md bg-indigo-600 text-white hover:bg-indigo-700 active:scale-[.97] transition shadow"
|
||||
@click="openDrawerAddActivity(c)"
|
||||
>
|
||||
+ Aktivnost
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="text-sm px-3 py-2 rounded-md bg-indigo-600 text-white hover:bg-indigo-700 active:scale-[.97] transition shadow"
|
||||
@click="openDocDialog(c)"
|
||||
>
|
||||
+ Dokument
|
||||
</button>
|
||||
<!--button
|
||||
type="button"
|
||||
:disabled="!getContractObjects(c).length"
|
||||
@click="openObjectsModal(c)"
|
||||
class="relative text-sm px-3 py-2 rounded-md flex items-center justify-center transition disabled:cursor-not-allowed disabled:opacity-50 bg-slate-600 text-white hover:bg-slate-700 active:scale-[.97] shadow"
|
||||
>
|
||||
Predmeti
|
||||
<span
|
||||
class="ml-1 inline-flex items-center justify-center min-w-[1.1rem] h-5 text-[11px] px-1.5 rounded-full bg-white/90 text-slate-700 font-medium"
|
||||
>{{ getContractObjects(c).length }}</span
|
||||
>
|
||||
</button-->
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="c.last_object" class="mt-2 text-sm text-gray-700">
|
||||
<p class="font-medium">Predmet:</p>
|
||||
<p>
|
||||
<span class="text-gray-900">{{
|
||||
c.last_object.name || c.last_object.reference
|
||||
}}</span>
|
||||
<span v-if="c.last_object.type" class="ml-2 text-gray-500"
|
||||
<!-- Subject / Last Object -->
|
||||
<div v-if="c.last_object" class="mt-3 border-t pt-3">
|
||||
<p class="text-[11px] uppercase tracking-wide text-gray-400 mb-1">
|
||||
Zadnji predmet
|
||||
</p>
|
||||
<div class="text-sm font-medium text-gray-800">
|
||||
{{ 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
|
||||
>
|
||||
</p>
|
||||
<p v-if="c.last_object.description" class="text-gray-600 mt-1">
|
||||
</div>
|
||||
<div
|
||||
v-if="c.last_object.description"
|
||||
class="mt-1 text-sm text-gray-600 leading-snug"
|
||||
>
|
||||
{{ c.last_object.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p v-if="!contracts?.length" class="text-sm text-gray-600">
|
||||
@@ -270,40 +360,66 @@ const submitComplete = () => {
|
||||
<template #title>Aktivnosti</template>
|
||||
</SectionTitle>
|
||||
<button
|
||||
class="text-sm px-3 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-700"
|
||||
class="text-xs font-medium px-3 py-2 rounded-md bg-indigo-600 text-white shadow-sm active:scale-[.98] hover:bg-indigo-700"
|
||||
@click="openDrawerAddActivity()"
|
||||
>
|
||||
Nova
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-2 divide-y">
|
||||
<div v-for="a in activities" :key="a.id" class="py-2 text-sm">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-gray-800">
|
||||
{{ a.action?.name
|
||||
}}<span v-if="a.decision"> → {{ a.decision?.name }}</span>
|
||||
<div class="mt-3 space-y-3">
|
||||
<div
|
||||
v-for="a in activities"
|
||||
:key="a.id"
|
||||
class="rounded-md border border-gray-200 bg-gray-50/70 px-3 py-3 shadow-sm text-[13px]"
|
||||
>
|
||||
<!-- Top line: action + date/user -->
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="font-medium text-gray-800 leading-snug truncate">
|
||||
{{ activityActionLine(a) || "Aktivnost" }}
|
||||
</div>
|
||||
<div class="text-right text-gray-500">
|
||||
<div v-if="a.contract">Pogodba: {{ a.contract.reference }}</div>
|
||||
<div class="text-xs" v-if="a.created_at || a.user || a.user_name">
|
||||
<span v-if="a.created_at">{{
|
||||
new Date(a.created_at).toLocaleDateString("sl-SI")
|
||||
}}</span>
|
||||
<span v-if="(a.user && a.user.name) || a.user_name" class="ml-1"
|
||||
>· {{ a.user?.name || a.user_name }}</span
|
||||
>
|
||||
<div
|
||||
class="shrink-0 text-right text-[11px] text-gray-500 leading-tight"
|
||||
>
|
||||
<div v-if="a.created_at">{{ formatDateShort(a.created_at) }}</div>
|
||||
<div v-if="(a.user && a.user.name) || a.user_name" class="truncate">
|
||||
{{ a.user?.name || a.user_name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="a.note" class="text-gray-600">{{ a.note }}</div>
|
||||
<div class="text-gray-500">
|
||||
<span v-if="a.due_date">Zapadlost: {{ a.due_date }}</span>
|
||||
<span v-if="a.amount != null" class="ml-2"
|
||||
|
||||
<!-- Badges row -->
|
||||
<div class="mt-2 flex flex-wrap gap-1.5">
|
||||
<span
|
||||
v-if="a.contract"
|
||||
class="inline-flex items-center rounded-full bg-indigo-100 text-indigo-700 px-2 py-0.5 text-[10px] font-medium"
|
||||
>Pogodba: {{ a.contract.reference }}</span
|
||||
>
|
||||
<span
|
||||
v-if="a.due_date"
|
||||
class="inline-flex items-center rounded-full bg-amber-100 text-amber-700 px-2 py-0.5 text-[10px] font-medium"
|
||||
>Zapadlost: {{ formatDateShort(a.due_date) || a.due_date }}</span
|
||||
>
|
||||
<span
|
||||
v-if="a.amount != null"
|
||||
class="inline-flex items-center rounded-full bg-emerald-100 text-emerald-700 px-2 py-0.5 text-[10px] font-medium"
|
||||
>Znesek: {{ formatAmount(a.amount) }} €</span
|
||||
>
|
||||
<span
|
||||
v-if="a.status"
|
||||
class="inline-flex items-center rounded-full bg-gray-200 text-gray-700 px-2 py-0.5 text-[10px] font-medium"
|
||||
>{{ a.status }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Note -->
|
||||
<div v-if="a.note" class="mt-2 text-gray-700 leading-snug">
|
||||
{{ a.note }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!activities?.length" class="text-gray-600 py-2">
|
||||
<div
|
||||
v-if="!activities?.length"
|
||||
class="text-gray-600 text-sm py-2 text-center"
|
||||
>
|
||||
Ni aktivnosti.
|
||||
</div>
|
||||
</div>
|
||||
@@ -423,6 +539,65 @@ const submitComplete = () => {
|
||||
</template>
|
||||
</ConfirmationModal>
|
||||
|
||||
<!-- Contract Objects (Predmeti) Modal -->
|
||||
<DialogModal :show="objectsModal.open" @close="closeObjectsModal">
|
||||
<template #title>
|
||||
Predmeti
|
||||
<span
|
||||
v-if="objectsModal.contract"
|
||||
class="block text-xs font-normal text-gray-500 mt-0.5"
|
||||
>
|
||||
{{ objectsModal.contract.reference || objectsModal.contract.uuid }}
|
||||
</span>
|
||||
</template>
|
||||
<template #content>
|
||||
<div
|
||||
v-if="objectsModal.items.length"
|
||||
class="space-y-3 max-h-[60vh] overflow-y-auto pr-1"
|
||||
>
|
||||
<div
|
||||
v-for="(o, idx) in objectsModal.items"
|
||||
:key="o.id || o.uuid || idx"
|
||||
class="rounded border border-gray-200 bg-gray-50 px-3 py-2 text-sm"
|
||||
>
|
||||
<div class="font-medium text-gray-800 truncate">
|
||||
{{ o.name || o.reference || "#" + (o.id || o.uuid || idx + 1) }}
|
||||
</div>
|
||||
<div class="mt-0.5 text-xs text-gray-500 flex flex-wrap gap-x-2 gap-y-0.5">
|
||||
<span
|
||||
v-if="o.type"
|
||||
class="inline-flex items-center bg-indigo-100 text-indigo-700 px-1.5 py-0.5 rounded-full"
|
||||
>{{ o.type }}</span
|
||||
>
|
||||
<span
|
||||
v-if="o.status"
|
||||
class="inline-flex items-center bg-gray-200 text-gray-700 px-1.5 py-0.5 rounded-full"
|
||||
>{{ o.status }}</span
|
||||
>
|
||||
<span
|
||||
v-if="o.amount != null"
|
||||
class="inline-flex items-center bg-emerald-100 text-emerald-700 px-1.5 py-0.5 rounded-full"
|
||||
>{{ formatAmount(o.amount) }} €</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="o.description" class="mt-1 text-gray-600 leading-snug">
|
||||
{{ o.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-gray-600 text-sm">Ni predmetov.</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button
|
||||
type="button"
|
||||
class="px-3 py-2 rounded bg-gray-100 hover:bg-gray-200"
|
||||
@click="closeObjectsModal"
|
||||
>
|
||||
Zapri
|
||||
</button>
|
||||
</template>
|
||||
</DialogModal>
|
||||
|
||||
<!-- Upload Document Modal -->
|
||||
<DialogModal :show="docDialogOpen" @close="closeDocDialog">
|
||||
<template #title>Dodaj dokument</template>
|
||||
@@ -493,4 +668,27 @@ const submitComplete = () => {
|
||||
</AppPhoneLayout>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
/* Using basic CSS since @apply is not processed in this scoped block by default */
|
||||
.chip-base {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.125rem 0.5rem; /* py-0.5 px-2 */
|
||||
border-radius: 9999px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
}
|
||||
.chip-indigo {
|
||||
background: #eef2ff;
|
||||
color: #3730a3;
|
||||
} /* approx indigo-50 / indigo-700 */
|
||||
.chip-default {
|
||||
background: #f1f5f9;
|
||||
color: #334155;
|
||||
} /* slate-100 / slate-700 */
|
||||
.chip-emerald {
|
||||
background: #ecfdf5;
|
||||
color: #047857;
|
||||
} /* emerald-50 / emerald-700 */
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user