front end updates
This commit is contained in:
parent
79b3e20b02
commit
ddfc79ffe8
|
|
@ -11,6 +11,10 @@ import {
|
||||||
faGears,
|
faGears,
|
||||||
faKey,
|
faKey,
|
||||||
faEnvelope,
|
faEnvelope,
|
||||||
|
faEnvelopeOpenText,
|
||||||
|
faAt,
|
||||||
|
faInbox,
|
||||||
|
faFileLines,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import Dropdown from "@/Components/Dropdown.vue";
|
import Dropdown from "@/Components/Dropdown.vue";
|
||||||
import DropdownLink from "@/Components/DropdownLink.vue";
|
import DropdownLink from "@/Components/DropdownLink.vue";
|
||||||
|
|
@ -44,7 +48,7 @@ function toggleSidebar() {
|
||||||
const logout = () => router.post(route("logout"));
|
const logout = () => router.post(route("logout"));
|
||||||
const page = usePage();
|
const page = usePage();
|
||||||
|
|
||||||
// Categorized admin navigation groups (removed global 'Nastavitve')
|
// Categorized admin navigation groups with distinct icons
|
||||||
const navGroups = computed(() => [
|
const navGroups = computed(() => [
|
||||||
{
|
{
|
||||||
key: "core",
|
key: "core",
|
||||||
|
|
@ -97,11 +101,17 @@ const navGroups = computed(() => [
|
||||||
icon: faFileWord,
|
icon: faFileWord,
|
||||||
active: ["admin.document-templates.index"],
|
active: ["admin.document-templates.index"],
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "email",
|
||||||
|
label: "Email",
|
||||||
|
items: [
|
||||||
{
|
{
|
||||||
key: "admin.email-templates.index",
|
key: "admin.email-templates.index",
|
||||||
label: "Email predloge",
|
label: "Email predloge",
|
||||||
route: "admin.email-templates.index",
|
route: "admin.email-templates.index",
|
||||||
icon: faEnvelope,
|
icon: faEnvelopeOpenText,
|
||||||
active: [
|
active: [
|
||||||
"admin.email-templates.index",
|
"admin.email-templates.index",
|
||||||
"admin.email-templates.create",
|
"admin.email-templates.create",
|
||||||
|
|
@ -112,14 +122,14 @@ const navGroups = computed(() => [
|
||||||
key: "admin.email-logs.index",
|
key: "admin.email-logs.index",
|
||||||
label: "Email dnevniki",
|
label: "Email dnevniki",
|
||||||
route: "admin.email-logs.index",
|
route: "admin.email-logs.index",
|
||||||
icon: faEnvelope,
|
icon: faInbox,
|
||||||
active: ["admin.email-logs.index", "admin.email-logs.show"],
|
active: ["admin.email-logs.index", "admin.email-logs.show"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "admin.mail-profiles.index",
|
key: "admin.mail-profiles.index",
|
||||||
label: "Mail profili",
|
label: "Mail profili",
|
||||||
route: "admin.mail-profiles.index",
|
route: "admin.mail-profiles.index",
|
||||||
icon: faGears,
|
icon: faAt,
|
||||||
active: ["admin.mail-profiles.index"],
|
active: ["admin.mail-profiles.index"],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import AdminLayout from '@/Layouts/AdminLayout.vue'
|
import AdminLayout from '@/Layouts/AdminLayout.vue'
|
||||||
import { Link } from '@inertiajs/vue3'
|
import { Link } from '@inertiajs/vue3'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
import { faUserGroup, faKey, faGears, faFileWord } from '@fortawesome/free-solid-svg-icons'
|
import { faUserGroup, faKey, faGears, faFileWord, faEnvelopeOpenText, faInbox, faAt } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
const cards = [
|
const cards = [
|
||||||
{
|
{
|
||||||
|
|
@ -39,6 +39,29 @@ const cards = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
category: 'Email',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
title: 'Email predloge',
|
||||||
|
description: 'Upravljanje HTML / tekst email predlog',
|
||||||
|
route: 'admin.email-templates.index',
|
||||||
|
icon: faEnvelopeOpenText,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Email dnevniki',
|
||||||
|
description: 'Pregled poslanih emailov in statusov',
|
||||||
|
route: 'admin.email-logs.index',
|
||||||
|
icon: faInbox,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mail profili',
|
||||||
|
description: 'SMTP profili, nastavitve in testiranje povezave',
|
||||||
|
route: 'admin.mail-profiles.index',
|
||||||
|
icon: faAt,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,9 @@ const props = defineProps({
|
||||||
profiles: { type: Array, default: () => [] },
|
profiles: { type: Array, default: () => [] },
|
||||||
});
|
});
|
||||||
|
|
||||||
const createOpen = ref(false);
|
const createOpen = ref(false); // create modal
|
||||||
const editTarget = ref(null);
|
const editOpen = ref(false); // edit modal
|
||||||
|
const editTarget = ref(null); // profile being edited
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
name: "",
|
name: "",
|
||||||
|
|
@ -39,6 +40,22 @@ function openCreate() {
|
||||||
editTarget.value = null;
|
editTarget.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openEdit(p) {
|
||||||
|
// populate form with existing profile data (exclude password which is write-only)
|
||||||
|
form.reset();
|
||||||
|
form.name = p.name || "";
|
||||||
|
form.host = p.host || "";
|
||||||
|
form.port = p.port || 587;
|
||||||
|
form.encryption = p.encryption || "";
|
||||||
|
form.username = p.username || "";
|
||||||
|
form.password = ""; // empty -> keep existing unless user fills
|
||||||
|
form.from_address = p.from_address || "";
|
||||||
|
form.from_name = p.from_name || "";
|
||||||
|
form.priority = p.priority ?? 10;
|
||||||
|
editTarget.value = p;
|
||||||
|
editOpen.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
function closeCreate() {
|
function closeCreate() {
|
||||||
if (form.processing) return;
|
if (form.processing) return;
|
||||||
createOpen.value = false;
|
createOpen.value = false;
|
||||||
|
|
@ -53,6 +70,37 @@ function submitCreate() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeEdit() {
|
||||||
|
if (form.processing) return;
|
||||||
|
editOpen.value = false;
|
||||||
|
editTarget.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitEdit() {
|
||||||
|
if (!editTarget.value) return;
|
||||||
|
// Build payload excluding empty password
|
||||||
|
const payload = {
|
||||||
|
name: form.name,
|
||||||
|
host: form.host,
|
||||||
|
port: form.port,
|
||||||
|
encryption: form.encryption || null,
|
||||||
|
username: form.username || null,
|
||||||
|
from_address: form.from_address,
|
||||||
|
from_name: form.from_name || null,
|
||||||
|
priority: form.priority,
|
||||||
|
};
|
||||||
|
if (form.password && form.password.trim() !== "") {
|
||||||
|
payload.password = form.password.trim();
|
||||||
|
}
|
||||||
|
form.transform(() => payload).put(route("admin.mail-profiles.update", editTarget.value.id), {
|
||||||
|
preserveScroll: true,
|
||||||
|
onSuccess: () => {
|
||||||
|
editOpen.value = false;
|
||||||
|
editTarget.value = null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function toggleActive(p) {
|
function toggleActive(p) {
|
||||||
window.axios
|
window.axios
|
||||||
.post(route("admin.mail-profiles.toggle", p.id))
|
.post(route("admin.mail-profiles.toggle", p.id))
|
||||||
|
|
@ -160,9 +208,11 @@ const statusClass = (p) => {
|
||||||
<FontAwesomeIcon :icon="faPaperPlane" class="w-3.5 h-3.5" /> Pošlji test
|
<FontAwesomeIcon :icon="faPaperPlane" class="w-3.5 h-3.5" /> Pošlji test
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@click="openEdit(p)"
|
||||||
class="inline-flex items-center gap-1 text-xs px-2 py-1 rounded border text-indigo-600 border-indigo-300 bg-indigo-50 hover:bg-indigo-100"
|
class="inline-flex items-center gap-1 text-xs px-2 py-1 rounded border text-indigo-600 border-indigo-300 bg-indigo-50 hover:bg-indigo-100"
|
||||||
|
title="Uredi profil"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon :icon="faArrowsRotate" class="w-3.5 h-3.5" /> Shrani
|
<FontAwesomeIcon :icon="faArrowsRotate" class="w-3.5 h-3.5" /> Uredi
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -241,6 +291,61 @@ const statusClass = (p) => {
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
</DialogModal>
|
</DialogModal>
|
||||||
|
<!-- Edit Modal -->
|
||||||
|
<DialogModal :show="editOpen" max-width="2xl" @close="closeEdit">
|
||||||
|
<template #title> Uredi Mail profil </template>
|
||||||
|
<template #content>
|
||||||
|
<form @submit.prevent="submitEdit" id="edit-mail-profile" class="space-y-5">
|
||||||
|
<div class="grid gap-4 grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<label class="label">Ime</label>
|
||||||
|
<input v-model="form.name" type="text" class="input" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">Host</label>
|
||||||
|
<input v-model="form.host" type="text" class="input" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">Port</label>
|
||||||
|
<input v-model="form.port" type="number" class="input" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">Encryption</label>
|
||||||
|
<select v-model="form.encryption" class="input">
|
||||||
|
<option value="">(None)</option>
|
||||||
|
<option value="tls">TLS</option>
|
||||||
|
<option value="ssl">SSL</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">Username</label>
|
||||||
|
<input v-model="form.username" type="text" class="input" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">Password (nova, če spreminjaš)</label>
|
||||||
|
<input v-model="form.password" type="password" class="input" autocomplete="new-password" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">From naslov</label>
|
||||||
|
<input v-model="form.from_address" type="email" class="input" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">From ime</label>
|
||||||
|
<input v-model="form.from_name" type="text" class="input" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label">Prioriteta</label>
|
||||||
|
<input v-model="form.priority" type="number" class="input" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-xs text-gray-500">Pusti geslo prazno, če želiš obdržati obstoječe.</p>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<button type="button" @click="closeEdit" class="px-4 py-2 text-sm rounded-md border bg-white hover:bg-gray-50">Prekliči</button>
|
||||||
|
<button form="edit-mail-profile" type="submit" :disabled="form.processing" class="px-4 py-2 text-sm rounded-md bg-indigo-600 text-white hover:bg-indigo-500 disabled:opacity-50">Shrani</button>
|
||||||
|
</template>
|
||||||
|
</DialogModal>
|
||||||
</AdminLayout>
|
</AdminLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,12 +112,7 @@ const confirmDeleteAction = () => {
|
||||||
{{ row.contract.reference }}
|
{{ row.contract.reference }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Link
|
<span class="text-gray-400">—</span>
|
||||||
:href="route('clientCase.show', { client_case: client_case.uuid })"
|
|
||||||
class="text-indigo-600 hover:underline"
|
|
||||||
>
|
|
||||||
{{ client_case?.person?.full_name || "—" }}
|
|
||||||
</Link>
|
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-2 pr-4 align-top">
|
<td class="py-2 pr-4 align-top">
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import AppLayout from "@/Layouts/AppLayout.vue";
|
import AppLayout from "@/Layouts/AppLayout.vue";
|
||||||
import { Link, useForm } from "@inertiajs/vue3";
|
import { Link, useForm } from "@inertiajs/vue3";
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref, watch } from "vue";
|
||||||
|
import DataTableClient from "@/Components/DataTable/DataTableClient.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
setting: Object,
|
setting: Object,
|
||||||
|
|
@ -138,39 +139,129 @@ const assignedContractsFiltered = computed(() => {
|
||||||
return list.filter(matchesSearch);
|
return list.filter(matchesSearch);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pagination state
|
// DataTableClient state per table
|
||||||
|
const unassignedSort = ref({ key: null, direction: null });
|
||||||
const unassignedPage = ref(1);
|
const unassignedPage = ref(1);
|
||||||
const unassignedPerPage = ref(10);
|
const unassignedPageSize = ref(10);
|
||||||
|
const assignedSort = ref({ key: null, direction: null });
|
||||||
const assignedPage = ref(1);
|
const assignedPage = ref(1);
|
||||||
const assignedPerPage = ref(10);
|
const assignedPageSize = ref(10);
|
||||||
|
|
||||||
// Reset pages when filters change
|
watch([search, assignedFilterUserId], () => {
|
||||||
watch([search], () => {
|
|
||||||
unassignedPage.value = 1;
|
unassignedPage.value = 1;
|
||||||
assignedPage.value = 1;
|
assignedPage.value = 1;
|
||||||
});
|
});
|
||||||
watch([assignedFilterUserId], () => {
|
|
||||||
assignedPage.value = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Paginated lists
|
// Column definitions for DataTableClient
|
||||||
const unassignedTotal = computed(() => unassignedFiltered.value.length);
|
const unassignedColumns = [
|
||||||
const unassignedTotalPages = computed(() =>
|
{ key: "reference", label: "Pogodba", sortable: true, class: "w-32" },
|
||||||
Math.max(1, Math.ceil(unassignedTotal.value / unassignedPerPage.value))
|
{
|
||||||
);
|
key: "case_person",
|
||||||
const unassignedPageItems = computed(() => {
|
label: "Primer",
|
||||||
const start = (unassignedPage.value - 1) * unassignedPerPage.value;
|
sortable: true,
|
||||||
return unassignedFiltered.value.slice(start, start + unassignedPerPage.value);
|
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 assignedColumns = [
|
||||||
const assignedTotalPages = computed(() =>
|
{ key: "reference", label: "Pogodba", sortable: true, class: "w-32" },
|
||||||
Math.max(1, Math.ceil(assignedTotal.value / assignedPerPage.value))
|
{
|
||||||
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -197,7 +288,7 @@ const assignedPageItems = computed(() => {
|
||||||
class="border rounded px-3 py-2 w-full max-w-xl"
|
class="border rounded px-3 py-2 w-full max-w-xl"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Unassigned (Assignable) Contracts -->
|
<!-- Unassigned (Assignable) Contracts via DataTableClient -->
|
||||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6 mb-8">
|
<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>
|
<h2 class="text-xl font-semibold mb-4">Pogodbe (nedodeljene)</h2>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
|
|
@ -217,98 +308,42 @@ const assignedPageItems = computed(() => {
|
||||||
{{ form.errors.assigned_user_id }}
|
{{ form.errors.assigned_user_id }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-x-auto">
|
<DataTableClient
|
||||||
<table class="min-w-full text-left text-sm">
|
:columns="unassignedColumns"
|
||||||
<thead>
|
:rows="unassignedRows"
|
||||||
<tr class="border-b">
|
:search-keys="['reference', 'case_person', 'client_person', 'address']"
|
||||||
<th class="py-2 pr-4">Pogodba</th>
|
v-model:sort="unassignedSort"
|
||||||
<th class="py-2 pr-4">Primer</th>
|
v-model:search="search"
|
||||||
<th class="py-2 pr-4">Naslov</th>
|
v-model:page="unassignedPage"
|
||||||
<th class="py-2 pr-4">Stranka</th>
|
v-model:pageSize="unassignedPageSize"
|
||||||
<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>
|
<template #cell-case_person="{ row }">
|
||||||
<td class="py-2 pr-4">
|
|
||||||
<Link
|
<Link
|
||||||
v-if="c.client_case?.uuid"
|
v-if="row.client_case?.uuid"
|
||||||
:href="
|
:href="route('clientCase.show', { client_case: row.client_case.uuid })"
|
||||||
route('clientCase.show', { client_case: c.client_case.uuid })
|
|
||||||
"
|
|
||||||
class="text-indigo-600 hover:underline"
|
class="text-indigo-600 hover:underline"
|
||||||
>
|
>
|
||||||
{{ c.client_case?.person?.full_name || "Primer stranke" }}
|
{{ row.client_case?.person?.full_name || "Primer stranke" }}
|
||||||
</Link>
|
</Link>
|
||||||
<span v-else>{{ c.client_case?.person?.full_name || "-" }}</span>
|
<span v-else>{{ row.client_case?.person?.full_name || "-" }}</span>
|
||||||
</td>
|
</template>
|
||||||
<td class="py-2 pr-4">{{ primaryCaseAddress(c) }}</td>
|
<template #cell-_actions="{ row }">
|
||||||
<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
|
<button
|
||||||
class="px-3 py-1 text-sm rounded bg-indigo-600 text-white"
|
class="px-3 py-1 text-xs rounded bg-indigo-600 text-white"
|
||||||
@click="assign(c)"
|
@click="assign(row)"
|
||||||
>
|
>
|
||||||
Dodeli
|
Dodeli
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</template>
|
||||||
</tr>
|
<template #empty>
|
||||||
<tr v-if="unassignedPageItems.length === 0">
|
<div class="text-sm text-gray-500 py-4 text-center">
|
||||||
<td colspan="9" class="py-4 text-gray-500">Ni najdenih pogodb.</td>
|
Ni najdenih pogodb.
|
||||||
</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)"
|
|
||||||
>
|
|
||||||
Prejšnja
|
|
||||||
</button>
|
|
||||||
<span>Stran {{ unassignedPage }} / {{ unassignedTotalPages }}</span>
|
|
||||||
<button
|
|
||||||
class="px-2 py-1 border rounded disabled:opacity-50"
|
|
||||||
:disabled="unassignedPage >= unassignedTotalPages"
|
|
||||||
@click="
|
|
||||||
unassignedPage = Math.min(unassignedTotalPages, unassignedPage + 1)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
Naslednja
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
</DataTableClient>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Assigned Contracts -->
|
<!-- Assigned Contracts via DataTableClient -->
|
||||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6">
|
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg p-6">
|
||||||
<div class="flex items-center justify-between mb-4">
|
<div class="flex items-center justify-between mb-4">
|
||||||
<h2 class="text-xl font-semibold">Dodeljene pogodbe</h2>
|
<h2 class="text-xl font-semibold">Dodeljene pogodbe</h2>
|
||||||
|
|
@ -322,99 +357,45 @@ const assignedPageItems = computed(() => {
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-x-auto">
|
<DataTableClient
|
||||||
<table class="min-w-full text-left text-sm">
|
:columns="assignedColumns"
|
||||||
<thead>
|
:rows="assignedRows"
|
||||||
<tr class="border-b">
|
:search-keys="[
|
||||||
<th class="py-2 pr-4">Pogodba</th>
|
'reference',
|
||||||
<th class="py-2 pr-4">Primer</th>
|
'case_person',
|
||||||
<th class="py-2 pr-4">Naslov</th>
|
'client_person',
|
||||||
<th class="py-2 pr-4">Stranka</th>
|
'address',
|
||||||
<th class="py-2 pr-4">Dodeljeno dne</th>
|
'assigned_to',
|
||||||
<th class="py-2 pr-4">Dodeljeno komu</th>
|
]"
|
||||||
<th class="py-2 pr-4">Stanje</th>
|
v-model:sort="assignedSort"
|
||||||
<th class="py-2 pr-4">Dejanje</th>
|
v-model:search="search"
|
||||||
</tr>
|
v-model:page="assignedPage"
|
||||||
</thead>
|
v-model:pageSize="assignedPageSize"
|
||||||
<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>
|
<template #cell-case_person="{ row }">
|
||||||
<td class="py-2 pr-4">
|
|
||||||
<Link
|
<Link
|
||||||
v-if="c.client_case?.uuid"
|
v-if="row.client_case?.uuid"
|
||||||
:href="
|
:href="route('clientCase.show', { client_case: row.client_case.uuid })"
|
||||||
route('clientCase.show', { client_case: c.client_case.uuid })
|
|
||||||
"
|
|
||||||
class="text-indigo-600 hover:underline"
|
class="text-indigo-600 hover:underline"
|
||||||
>
|
>
|
||||||
{{ c.client_case?.person?.full_name || "Primer stranke" }}
|
{{ row.client_case?.person?.full_name || "Primer stranke" }}
|
||||||
</Link>
|
</Link>
|
||||||
<span v-else>{{ c.client_case?.person?.full_name || "-" }}</span>
|
<span v-else>{{ row.client_case?.person?.full_name || "-" }}</span>
|
||||||
</td>
|
</template>
|
||||||
<td class="py-2 pr-4">{{ primaryCaseAddress(c) }}</td>
|
<template #cell-_actions="{ row }">
|
||||||
<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
|
<button
|
||||||
class="px-3 py-1 text-sm rounded bg-red-600 text-white"
|
class="px-3 py-1 text-xs rounded bg-red-600 text-white"
|
||||||
@click="cancelAssignment(c)"
|
@click="cancelAssignment(row)"
|
||||||
>
|
>
|
||||||
Prekliči
|
Prekliči
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</template>
|
||||||
</tr>
|
<template #empty>
|
||||||
<tr v-if="assignedPageItems.length === 0">
|
<div class="text-sm text-gray-500 py-4 text-center">
|
||||||
<td colspan="8" class="py-4 text-gray-500">
|
|
||||||
Ni dodeljenih pogodb za izbran filter.
|
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)"
|
|
||||||
>
|
|
||||||
Prejšnja
|
|
||||||
</button>
|
|
||||||
<span>Stran {{ assignedPage }} / {{ assignedTotalPages }}</span>
|
|
||||||
<button
|
|
||||||
class="px-2 py-1 border rounded disabled:opacity-50"
|
|
||||||
:disabled="assignedPage >= assignedTotalPages"
|
|
||||||
@click="assignedPage = Math.min(assignedTotalPages, assignedPage + 1)"
|
|
||||||
>
|
|
||||||
Naslednja
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
</DataTableClient>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user