front end updates
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import AppLayout from "@/Layouts/AppLayout.vue";
|
||||
import { Link, useForm } from "@inertiajs/vue3";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import DataTableClient from "@/Components/DataTable/DataTableClient.vue";
|
||||
|
||||
const props = defineProps({
|
||||
setting: Object,
|
||||
@@ -138,39 +139,129 @@ const assignedContractsFiltered = computed(() => {
|
||||
return list.filter(matchesSearch);
|
||||
});
|
||||
|
||||
// Pagination state
|
||||
// DataTableClient state per table
|
||||
const unassignedSort = ref({ key: null, direction: null });
|
||||
const unassignedPage = ref(1);
|
||||
const unassignedPerPage = ref(10);
|
||||
const unassignedPageSize = ref(10);
|
||||
const assignedSort = ref({ key: null, direction: null });
|
||||
const assignedPage = ref(1);
|
||||
const assignedPerPage = ref(10);
|
||||
const assignedPageSize = ref(10);
|
||||
|
||||
// Reset pages when filters change
|
||||
watch([search], () => {
|
||||
watch([search, assignedFilterUserId], () => {
|
||||
unassignedPage.value = 1;
|
||||
assignedPage.value = 1;
|
||||
});
|
||||
watch([assignedFilterUserId], () => {
|
||||
assignedPage.value = 1;
|
||||
});
|
||||
|
||||
// Paginated lists
|
||||
const unassignedTotal = computed(() => unassignedFiltered.value.length);
|
||||
const unassignedTotalPages = computed(() =>
|
||||
Math.max(1, Math.ceil(unassignedTotal.value / unassignedPerPage.value))
|
||||
);
|
||||
const unassignedPageItems = computed(() => {
|
||||
const start = (unassignedPage.value - 1) * unassignedPerPage.value;
|
||||
return unassignedFiltered.value.slice(start, start + unassignedPerPage.value);
|
||||
});
|
||||
// Column definitions for DataTableClient
|
||||
const unassignedColumns = [
|
||||
{ key: "reference", label: "Pogodba", sortable: true, class: "w-32" },
|
||||
{
|
||||
key: "case_person",
|
||||
label: "Primer",
|
||||
sortable: true,
|
||||
formatter: (c) => c.client_case?.person?.full_name || "-",
|
||||
},
|
||||
{
|
||||
key: "address",
|
||||
label: "Naslov",
|
||||
sortable: true,
|
||||
formatter: (c) => primaryCaseAddress(c),
|
||||
},
|
||||
{
|
||||
key: "client_person",
|
||||
label: "Stranka",
|
||||
sortable: true,
|
||||
formatter: (c) => c.client?.person?.full_name || "-",
|
||||
},
|
||||
{
|
||||
key: "start_date",
|
||||
label: "Začetek",
|
||||
sortable: true,
|
||||
formatter: (c) => formatDate(c.start_date),
|
||||
},
|
||||
{
|
||||
key: "balance_amount",
|
||||
label: "Stanje",
|
||||
align: "right",
|
||||
sortable: true,
|
||||
formatter: (c) => formatCurrencyEUR(c.account?.balance_amount),
|
||||
},
|
||||
{ key: "_actions", label: "Dejanje", class: "w-32" },
|
||||
];
|
||||
|
||||
const assignedTotal = computed(() => assignedContractsFiltered.value.length);
|
||||
const assignedTotalPages = computed(() =>
|
||||
Math.max(1, Math.ceil(assignedTotal.value / assignedPerPage.value))
|
||||
const assignedColumns = [
|
||||
{ key: "reference", label: "Pogodba", sortable: true, class: "w-32" },
|
||||
{
|
||||
key: "case_person",
|
||||
label: "Primer",
|
||||
sortable: true,
|
||||
formatter: (c) => c.client_case?.person?.full_name || "-",
|
||||
},
|
||||
{
|
||||
key: "address",
|
||||
label: "Naslov",
|
||||
sortable: true,
|
||||
formatter: (c) => primaryCaseAddress(c),
|
||||
},
|
||||
{
|
||||
key: "client_person",
|
||||
label: "Stranka",
|
||||
sortable: true,
|
||||
formatter: (c) => c.client?.person?.full_name || "-",
|
||||
},
|
||||
{
|
||||
key: "assigned_at",
|
||||
label: "Dodeljeno dne",
|
||||
sortable: true,
|
||||
formatter: (c) => formatDate(props.assignments?.[c.uuid]?.assigned_at),
|
||||
},
|
||||
{
|
||||
key: "assigned_to",
|
||||
label: "Dodeljeno komu",
|
||||
sortable: true,
|
||||
formatter: (c) => assignedTo(c) || "-",
|
||||
},
|
||||
{
|
||||
key: "balance_amount",
|
||||
label: "Stanje",
|
||||
align: "right",
|
||||
sortable: true,
|
||||
formatter: (c) => formatCurrencyEUR(c.account?.balance_amount),
|
||||
},
|
||||
{ key: "_actions", label: "Dejanje", class: "w-32" },
|
||||
];
|
||||
|
||||
// Provide derived row arrays for DataTable (already filtered)
|
||||
// Add a flat numeric property `balance_amount` so the generic table sorter can sort by value
|
||||
// (original data nests it under account.balance_amount which the sorter cannot reach).
|
||||
const unassignedRows = computed(() =>
|
||||
unassignedFiltered.value.map((c) => ({
|
||||
...c,
|
||||
// Ensure numeric so sorter treats it as number (server often returns string)
|
||||
balance_amount:
|
||||
c?.account?.balance_amount === null || c?.account?.balance_amount === undefined
|
||||
? null
|
||||
: Number(c.account.balance_amount),
|
||||
// Flatten derived text fields so DataTable sorting/searching works
|
||||
case_person: c.client_case?.person?.full_name || null,
|
||||
client_person: c.client?.person?.full_name || null,
|
||||
address: primaryCaseAddress(c) || null,
|
||||
assigned_to: null, // not assigned yet
|
||||
}))
|
||||
);
|
||||
const assignedRows = computed(() =>
|
||||
assignedContractsFiltered.value.map((c) => ({
|
||||
...c,
|
||||
balance_amount:
|
||||
c?.account?.balance_amount === null || c?.account?.balance_amount === undefined
|
||||
? null
|
||||
: Number(c.account.balance_amount),
|
||||
case_person: c.client_case?.person?.full_name || null,
|
||||
client_person: c.client?.person?.full_name || null,
|
||||
address: primaryCaseAddress(c) || null,
|
||||
assigned_to: assignedTo(c) || null,
|
||||
}))
|
||||
);
|
||||
const assignedPageItems = computed(() => {
|
||||
const start = (assignedPage.value - 1) * assignedPerPage.value;
|
||||
return assignedContractsFiltered.value.slice(start, start + assignedPerPage.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -197,7 +288,7 @@ const assignedPageItems = computed(() => {
|
||||
class="border rounded px-3 py-2 w-full max-w-xl"
|
||||
/>
|
||||
</div>
|
||||
<!-- Unassigned (Assignable) Contracts -->
|
||||
<!-- Unassigned (Assignable) Contracts via DataTableClient -->
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6 mb-8">
|
||||
<h2 class="text-xl font-semibold mb-4">Pogodbe (nedodeljene)</h2>
|
||||
<div class="mb-4">
|
||||
@@ -217,98 +308,42 @@ const assignedPageItems = computed(() => {
|
||||
{{ form.errors.assigned_user_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-left text-sm">
|
||||
<thead>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 pr-4">Pogodba</th>
|
||||
<th class="py-2 pr-4">Primer</th>
|
||||
<th class="py-2 pr-4">Naslov</th>
|
||||
<th class="py-2 pr-4">Stranka</th>
|
||||
<th class="py-2 pr-4">Začetek</th>
|
||||
<th class="py-2 pr-4">Stanje</th>
|
||||
<th class="py-2 pr-4">Dejanje</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="c in unassignedPageItems"
|
||||
:key="c.uuid"
|
||||
class="border-b last:border-0"
|
||||
>
|
||||
<td class="py-2 pr-4">{{ c.reference }}</td>
|
||||
<td class="py-2 pr-4">
|
||||
<Link
|
||||
v-if="c.client_case?.uuid"
|
||||
:href="
|
||||
route('clientCase.show', { client_case: c.client_case.uuid })
|
||||
"
|
||||
class="text-indigo-600 hover:underline"
|
||||
>
|
||||
{{ c.client_case?.person?.full_name || "Primer stranke" }}
|
||||
</Link>
|
||||
<span v-else>{{ c.client_case?.person?.full_name || "-" }}</span>
|
||||
</td>
|
||||
<td class="py-2 pr-4">{{ primaryCaseAddress(c) }}</td>
|
||||
<td class="py-2 pr-4">
|
||||
{{ c.client?.person?.full_name || "-" }}
|
||||
</td>
|
||||
<td class="py-2 pr-4">{{ formatDate(c.start_date) }}</td>
|
||||
<td class="py-2 pr-4">
|
||||
{{ formatCurrencyEUR(c.account?.balance_amount) }}
|
||||
</td>
|
||||
<td class="py-2 pr-4 flex items-center gap-2">
|
||||
<button
|
||||
class="px-3 py-1 text-sm rounded bg-indigo-600 text-white"
|
||||
@click="assign(c)"
|
||||
>
|
||||
Dodeli
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="unassignedPageItems.length === 0">
|
||||
<td colspan="9" class="py-4 text-gray-500">Ni najdenih pogodb.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Unassigned pagination -->
|
||||
<div class="flex items-center justify-between mt-4 text-sm text-gray-700">
|
||||
<div>
|
||||
Prikazano
|
||||
{{
|
||||
Math.min((unassignedPage - 1) * unassignedPerPage + 1, unassignedTotal)
|
||||
}}–{{ Math.min(unassignedPage * unassignedPerPage, unassignedTotal) }} od
|
||||
{{ unassignedTotal }}
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<select v-model.number="unassignedPerPage" class="border rounded px-2 py-1">
|
||||
<option :value="10">10</option>
|
||||
<option :value="25">25</option>
|
||||
<option :value="50">50</option>
|
||||
</select>
|
||||
<button
|
||||
class="px-2 py-1 border rounded disabled:opacity-50"
|
||||
:disabled="unassignedPage <= 1"
|
||||
@click="unassignedPage = Math.max(1, unassignedPage - 1)"
|
||||
<DataTableClient
|
||||
:columns="unassignedColumns"
|
||||
:rows="unassignedRows"
|
||||
:search-keys="['reference', 'case_person', 'client_person', 'address']"
|
||||
v-model:sort="unassignedSort"
|
||||
v-model:search="search"
|
||||
v-model:page="unassignedPage"
|
||||
v-model:pageSize="unassignedPageSize"
|
||||
>
|
||||
<template #cell-case_person="{ row }">
|
||||
<Link
|
||||
v-if="row.client_case?.uuid"
|
||||
:href="route('clientCase.show', { client_case: row.client_case.uuid })"
|
||||
class="text-indigo-600 hover:underline"
|
||||
>
|
||||
Prejšnja
|
||||
</button>
|
||||
<span>Stran {{ unassignedPage }} / {{ unassignedTotalPages }}</span>
|
||||
{{ row.client_case?.person?.full_name || "Primer stranke" }}
|
||||
</Link>
|
||||
<span v-else>{{ row.client_case?.person?.full_name || "-" }}</span>
|
||||
</template>
|
||||
<template #cell-_actions="{ row }">
|
||||
<button
|
||||
class="px-2 py-1 border rounded disabled:opacity-50"
|
||||
:disabled="unassignedPage >= unassignedTotalPages"
|
||||
@click="
|
||||
unassignedPage = Math.min(unassignedTotalPages, unassignedPage + 1)
|
||||
"
|
||||
class="px-3 py-1 text-xs rounded bg-indigo-600 text-white"
|
||||
@click="assign(row)"
|
||||
>
|
||||
Naslednja
|
||||
Dodeli
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="text-sm text-gray-500 py-4 text-center">
|
||||
Ni najdenih pogodb.
|
||||
</div>
|
||||
</template>
|
||||
</DataTableClient>
|
||||
</div>
|
||||
|
||||
<!-- Assigned Contracts -->
|
||||
<!-- Assigned Contracts via DataTableClient -->
|
||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold">Dodeljene pogodbe</h2>
|
||||
@@ -322,99 +357,45 @@ const assignedPageItems = computed(() => {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full text-left text-sm">
|
||||
<thead>
|
||||
<tr class="border-b">
|
||||
<th class="py-2 pr-4">Pogodba</th>
|
||||
<th class="py-2 pr-4">Primer</th>
|
||||
<th class="py-2 pr-4">Naslov</th>
|
||||
<th class="py-2 pr-4">Stranka</th>
|
||||
<th class="py-2 pr-4">Dodeljeno dne</th>
|
||||
<th class="py-2 pr-4">Dodeljeno komu</th>
|
||||
<th class="py-2 pr-4">Stanje</th>
|
||||
<th class="py-2 pr-4">Dejanje</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="c in assignedPageItems"
|
||||
:key="c.uuid"
|
||||
class="border-b last:border-0"
|
||||
>
|
||||
<td class="py-2 pr-4">{{ c.reference }}</td>
|
||||
<td class="py-2 pr-4">
|
||||
<Link
|
||||
v-if="c.client_case?.uuid"
|
||||
:href="
|
||||
route('clientCase.show', { client_case: c.client_case.uuid })
|
||||
"
|
||||
class="text-indigo-600 hover:underline"
|
||||
>
|
||||
{{ c.client_case?.person?.full_name || "Primer stranke" }}
|
||||
</Link>
|
||||
<span v-else>{{ c.client_case?.person?.full_name || "-" }}</span>
|
||||
</td>
|
||||
<td class="py-2 pr-4">{{ primaryCaseAddress(c) }}</td>
|
||||
<td class="py-2 pr-4">
|
||||
{{ c.client?.person?.full_name || "-" }}
|
||||
</td>
|
||||
<td class="py-2 pr-4">
|
||||
{{ formatDate(props.assignments?.[c.uuid]?.assigned_at) }}
|
||||
</td>
|
||||
<td class="py-2 pr-4">{{ assignedTo(c) || "-" }}</td>
|
||||
<td class="py-2 pr-4">
|
||||
{{ formatCurrencyEUR(c.account?.balance_amount) }}
|
||||
</td>
|
||||
<td class="py-2 pr-4">
|
||||
<button
|
||||
class="px-3 py-1 text-sm rounded bg-red-600 text-white"
|
||||
@click="cancelAssignment(c)"
|
||||
>
|
||||
Prekliči
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="assignedPageItems.length === 0">
|
||||
<td colspan="8" class="py-4 text-gray-500">
|
||||
Ni dodeljenih pogodb za izbran filter.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Assigned pagination -->
|
||||
<div class="flex items-center justify-between mt-4 text-sm text-gray-700">
|
||||
<div>
|
||||
Prikazano
|
||||
{{ Math.min((assignedPage - 1) * assignedPerPage + 1, assignedTotal) }}–{{
|
||||
Math.min(assignedPage * assignedPerPage, assignedTotal)
|
||||
}}
|
||||
od {{ assignedTotal }}
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<select v-model.number="assignedPerPage" class="border rounded px-2 py-1">
|
||||
<option :value="10">10</option>
|
||||
<option :value="25">25</option>
|
||||
<option :value="50">50</option>
|
||||
</select>
|
||||
<button
|
||||
class="px-2 py-1 border rounded disabled:opacity-50"
|
||||
:disabled="assignedPage <= 1"
|
||||
@click="assignedPage = Math.max(1, assignedPage - 1)"
|
||||
<DataTableClient
|
||||
:columns="assignedColumns"
|
||||
:rows="assignedRows"
|
||||
:search-keys="[
|
||||
'reference',
|
||||
'case_person',
|
||||
'client_person',
|
||||
'address',
|
||||
'assigned_to',
|
||||
]"
|
||||
v-model:sort="assignedSort"
|
||||
v-model:search="search"
|
||||
v-model:page="assignedPage"
|
||||
v-model:pageSize="assignedPageSize"
|
||||
>
|
||||
<template #cell-case_person="{ row }">
|
||||
<Link
|
||||
v-if="row.client_case?.uuid"
|
||||
:href="route('clientCase.show', { client_case: row.client_case.uuid })"
|
||||
class="text-indigo-600 hover:underline"
|
||||
>
|
||||
Prejšnja
|
||||
</button>
|
||||
<span>Stran {{ assignedPage }} / {{ assignedTotalPages }}</span>
|
||||
{{ row.client_case?.person?.full_name || "Primer stranke" }}
|
||||
</Link>
|
||||
<span v-else>{{ row.client_case?.person?.full_name || "-" }}</span>
|
||||
</template>
|
||||
<template #cell-_actions="{ row }">
|
||||
<button
|
||||
class="px-2 py-1 border rounded disabled:opacity-50"
|
||||
:disabled="assignedPage >= assignedTotalPages"
|
||||
@click="assignedPage = Math.min(assignedTotalPages, assignedPage + 1)"
|
||||
class="px-3 py-1 text-xs rounded bg-red-600 text-white"
|
||||
@click="cancelAssignment(row)"
|
||||
>
|
||||
Naslednja
|
||||
Prekliči
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div class="text-sm text-gray-500 py-4 text-center">
|
||||
Ni dodeljenih pogodb za izbran filter.
|
||||
</div>
|
||||
</template>
|
||||
</DataTableClient>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user