Changes to field job view and controller
This commit is contained in:
parent
dea7432deb
commit
84b75143df
|
|
@ -26,10 +26,13 @@ public function index(Request $request)
|
||||||
])->filter()->unique()->values();
|
])->filter()->unique()->values();
|
||||||
|
|
||||||
$search = $request->input('search');
|
$search = $request->input('search');
|
||||||
|
$searchAssigned = $request->input('search_assigned');
|
||||||
$assignedUserId = $request->input('assigned_user_id');
|
$assignedUserId = $request->input('assigned_user_id');
|
||||||
|
$unassignedClientUuids = $request->input('unassigned_client_uuids');
|
||||||
|
$assignedClientUuids = $request->input('assigned_client_uuids');
|
||||||
|
|
||||||
$unassignedContracts = Contract::query()
|
$unassignedContracts = Contract::query()
|
||||||
->with(['clientCase.person.addresses', 'clientCase.client.person', 'type', 'account'])
|
->with(['clientCase.person.addresses', 'clientCase.client.person:id,uuid,full_name', 'type', 'account'])
|
||||||
->when($segmentIds->isNotEmpty(), fn($q) =>
|
->when($segmentIds->isNotEmpty(), fn($q) =>
|
||||||
$q->whereHas('segments', fn($rq) => $rq->whereIn('segments.id', $segmentIds)),
|
$q->whereHas('segments', fn($rq) => $rq->whereIn('segments.id', $segmentIds)),
|
||||||
fn($q) => $q->whereRaw('1 = 0')
|
fn($q) => $q->whereRaw('1 = 0')
|
||||||
|
|
@ -45,50 +48,83 @@ public function index(Request $request)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
->when(!empty($unassignedClientUuids) && is_array($unassignedClientUuids), fn ($q) =>
|
||||||
|
$q->whereHas('clientCase.client', fn($cq) =>
|
||||||
|
$cq->whereIn('uuid', $unassignedClientUuids)
|
||||||
|
)
|
||||||
|
)
|
||||||
->whereDoesntHave('fieldJobs', fn ($q) =>
|
->whereDoesntHave('fieldJobs', fn ($q) =>
|
||||||
$q->whereNull('completed_at')
|
$q->whereNull('completed_at')
|
||||||
->whereNull('cancelled_at')
|
->whereNull('cancelled_at')
|
||||||
)
|
)
|
||||||
->latest('id')
|
->latest('id');
|
||||||
->paginate(
|
|
||||||
$request->input('per_page_contracts', 10),
|
|
||||||
['*'],
|
|
||||||
'page_contracts',
|
|
||||||
$request->input('page_contracts', 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
$unassignedClients = $unassignedContracts->get()
|
||||||
|
->pluck('clientCase.client')
|
||||||
|
->filter()
|
||||||
|
->unique('id');
|
||||||
|
|
||||||
|
|
||||||
$assignedContracts = Contract::query()
|
$assignedContracts = Contract::query()
|
||||||
->with(['clientCase.person.addresses', 'clientCase.client.person', 'type', 'account', 'lastFieldJobs', 'lastFieldJobs.assignedUser', 'lastFieldJobs.user'])
|
->with(['clientCase.person.addresses', 'clientCase.client.person:id,uuid,full_name', 'type', 'account', 'lastFieldJobs', 'lastFieldJobs.assignedUser', 'lastFieldJobs.user'])
|
||||||
->when($segmentIds->isNotEmpty(), fn($q) =>
|
->when($segmentIds->isNotEmpty(), fn($q) =>
|
||||||
$q->whereHas('segments', fn($rq) => $rq->whereIn('segments.id', $segmentIds)),
|
$q->whereHas('segments', fn($rq) => $rq->whereIn('segments.id', $segmentIds)),
|
||||||
fn($q) => $q->whereRaw('1 = 0')
|
fn($q) => $q->whereRaw('1 = 0')
|
||||||
)
|
)
|
||||||
|
->when( !empty($searchAssigned), fn ($q) =>
|
||||||
|
$q->where(fn($sq) =>
|
||||||
|
$sq->where('reference', 'like', "%{$searchAssigned}%")
|
||||||
|
->orWhereHas('clientCase.person', fn($psq) =>
|
||||||
|
$psq->where('full_name', 'ilike', "%{$searchAssigned}%")
|
||||||
|
)
|
||||||
|
->orWhereHas('clientCase.person.addresses', fn ($ccpaq) =>
|
||||||
|
$ccpaq->where('address', 'ilike', "%{$searchAssigned}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->when(!empty($assignedClientUuids) && is_array($assignedClientUuids), fn ($q) =>
|
||||||
|
$q->whereHas('clientCase.client', fn($cq) =>
|
||||||
|
$cq->whereIn('uuid', $assignedClientUuids)
|
||||||
|
)
|
||||||
|
)
|
||||||
->whereHas('lastFieldJobs', fn ($q) =>
|
->whereHas('lastFieldJobs', fn ($q) =>
|
||||||
$q->whereNull('completed_at')
|
$q->whereNull('completed_at')
|
||||||
->whereNull('cancelled_at')
|
->whereNull('cancelled_at')
|
||||||
->when($assignedUserId && $assignedUserId !== 'all', fn ($jq) =>
|
->when($assignedUserId && $assignedUserId !== 'all', fn ($jq) =>
|
||||||
$jq->where('assigned_user_id', $assignedUserId))
|
$jq->where('assigned_user_id', $assignedUserId))
|
||||||
)
|
)
|
||||||
->latest('id')
|
->latest('id');
|
||||||
->paginate(
|
|
||||||
$request->input('per_page_assignments', 10),
|
$assignedClients = $assignedContracts->get()
|
||||||
['*'],
|
->pluck('clientCase.client')
|
||||||
'page_assignments',
|
->filter()
|
||||||
$request->input('page_assignments', 1)
|
->unique('id');
|
||||||
);
|
|
||||||
|
|
||||||
$users = User::query()->orderBy('name')->get(['id', 'name']);
|
$users = User::query()->orderBy('name')->get(['id', 'name']);
|
||||||
|
|
||||||
return Inertia::render('FieldJob/Index', [
|
return Inertia::render('FieldJob/Index', [
|
||||||
'setting' => $setting,
|
'setting' => $setting,
|
||||||
'unassignedContracts' => $unassignedContracts,
|
'unassignedContracts' => $unassignedContracts->paginate(
|
||||||
'assignedContracts' => $assignedContracts,
|
$request->input('per_page_contracts', 10),
|
||||||
|
['*'],
|
||||||
|
'page_contracts',
|
||||||
|
$request->input('page_contracts', 1)
|
||||||
|
),
|
||||||
|
'assignedContracts' => $assignedContracts->paginate(
|
||||||
|
$request->input('per_page_assignments', 10),
|
||||||
|
['*'],
|
||||||
|
'page_assignments',
|
||||||
|
$request->input('page_assignments', 1)
|
||||||
|
),
|
||||||
|
'unassignedClients' => $unassignedClients,
|
||||||
|
'assignedClients' => $assignedClients,
|
||||||
'users' => $users,
|
'users' => $users,
|
||||||
'filters' => [
|
'filters' => [
|
||||||
'search' => $search,
|
'search' => $search,
|
||||||
|
'search_assigned' => $searchAssigned,
|
||||||
'assigned_user_id' => $assignedUserId,
|
'assigned_user_id' => $assignedUserId,
|
||||||
|
'unassigned_client_uuids' => $unassignedClientUuids,
|
||||||
|
'assigned_client_uuids' => $assignedClientUuids,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import AppLayout from "@/Layouts/AppLayout.vue";
|
||||||
import { Link, useForm, router } from "@inertiajs/vue3";
|
import { Link, useForm, router } from "@inertiajs/vue3";
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref, watch } from "vue";
|
||||||
import DataTable from "@/Components/DataTable/DataTableNew2.vue";
|
import DataTable from "@/Components/DataTable/DataTableNew2.vue";
|
||||||
import { Card } from "@/Components/ui/card";
|
import { Card, CardTitle } from "@/Components/ui/card";
|
||||||
import { Input } from "@/Components/ui/input";
|
import { Input } from "@/Components/ui/input";
|
||||||
import { Button } from "@/Components/ui/button";
|
import { Button } from "@/Components/ui/button";
|
||||||
import { Label } from "@/Components/ui/label";
|
import { Label } from "@/Components/ui/label";
|
||||||
|
|
@ -15,19 +15,45 @@ import {
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/Components/ui/select";
|
} from "@/Components/ui/select";
|
||||||
import { AlertCircle } from "lucide-vue-next";
|
import { AlertCircle, FileCheckCornerIcon, FilesIcon, Filter } from "lucide-vue-next";
|
||||||
import Checkbox from "@/Components/ui/checkbox/Checkbox.vue";
|
import Checkbox from "@/Components/ui/checkbox/Checkbox.vue";
|
||||||
import Pagination from "@/Components/Pagination.vue";
|
import Pagination from "@/Components/Pagination.vue";
|
||||||
import { watchDebounced } from "@vueuse/core";
|
import { watchDebounced } from "@vueuse/core";
|
||||||
|
import Dropdown from "@/Components/Dropdown.vue";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/Components/ui/dropdown-menu";
|
||||||
|
import AppPopover from "@/Components/app/ui/AppPopover.vue";
|
||||||
|
import InputLabel from "@/Components/InputLabel.vue";
|
||||||
|
import AppMultiSelect from "@/Components/app/ui/AppMultiSelect.vue";
|
||||||
|
import AppCard from "@/Components/app/ui/card/AppCard.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
setting: Object,
|
setting: Object,
|
||||||
unassignedContracts: Object,
|
unassignedContracts: Object,
|
||||||
assignedContracts: Object,
|
assignedContracts: Object,
|
||||||
users: Array,
|
users: Array,
|
||||||
|
unassignedClients: Array,
|
||||||
|
assignedClients: Array,
|
||||||
filters: Object,
|
filters: Object,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filterUnassignedContracts = ref(false);
|
||||||
|
const filterAssignedContracts = ref(false);
|
||||||
|
const filterUnassignedSelectedClient = ref(
|
||||||
|
Array.isArray(props.filters?.unassigned_client_uuids)
|
||||||
|
? props.filters.unassigned_client_uuids
|
||||||
|
: []
|
||||||
|
);
|
||||||
|
const filterAssignedSelectedClient = ref(
|
||||||
|
Array.isArray(props.filters?.assigned_client_uuids)
|
||||||
|
? props.filters.assigned_client_uuids
|
||||||
|
: []
|
||||||
|
);
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
contract_uuid: null,
|
contract_uuid: null,
|
||||||
assigned_user_id: null,
|
assigned_user_id: null,
|
||||||
|
|
@ -85,6 +111,7 @@ function toggleContractSelection(uuid, checked) {
|
||||||
|
|
||||||
// Initialize search and filter from URL params
|
// Initialize search and filter from URL params
|
||||||
const search = ref(props.filters?.search || "");
|
const search = ref(props.filters?.search || "");
|
||||||
|
const searchAssigned = ref(props.filters?.search_assigned || "");
|
||||||
const assignedFilterUserId = ref(props.filters?.assigned_user_id || "all");
|
const assignedFilterUserId = ref(props.filters?.assigned_user_id || "all");
|
||||||
|
|
||||||
// Navigation helpers
|
// Navigation helpers
|
||||||
|
|
@ -128,6 +155,37 @@ watchDebounced(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const applySearchAssigned = async function () {
|
||||||
|
const params = Object.fromEntries(
|
||||||
|
new URLSearchParams(window.location.search).entries()
|
||||||
|
);
|
||||||
|
|
||||||
|
const term = (searchAssigned.value || "").trim();
|
||||||
|
if (term) {
|
||||||
|
params.search_assigned = term;
|
||||||
|
} else {
|
||||||
|
delete params.search_assigned;
|
||||||
|
}
|
||||||
|
delete params.page_assignments;
|
||||||
|
router.get(route("fieldjobs.index"), params, {
|
||||||
|
preserveState: true,
|
||||||
|
replace: true,
|
||||||
|
preserveScroll: true,
|
||||||
|
only: ["assignedContracts", "filters"],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
watchDebounced(
|
||||||
|
() => searchAssigned.value,
|
||||||
|
(val) => {
|
||||||
|
applySearchAssigned();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
debounce: 200,
|
||||||
|
maxWait: 1000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Watch search and filter changes
|
// Watch search and filter changes
|
||||||
/*watch(search, (value) => {
|
/*watch(search, (value) => {
|
||||||
navigateWithParams({
|
navigateWithParams({
|
||||||
|
|
@ -143,6 +201,44 @@ watch(assignedFilterUserId, (value) => {
|
||||||
navigateWithParams({
|
navigateWithParams({
|
||||||
search: search.value || undefined,
|
search: search.value || undefined,
|
||||||
assigned_user_id: value !== "all" ? value : undefined,
|
assigned_user_id: value !== "all" ? value : undefined,
|
||||||
|
unassigned_client_uuids:
|
||||||
|
filterUnassignedSelectedClient.value?.length > 0
|
||||||
|
? filterUnassignedSelectedClient.value
|
||||||
|
: undefined,
|
||||||
|
assigned_client_uuids:
|
||||||
|
filterAssignedSelectedClient.value?.length > 0
|
||||||
|
? filterAssignedSelectedClient.value
|
||||||
|
: undefined,
|
||||||
|
page_contracts: props.unassignedContracts?.current_page,
|
||||||
|
page_assignments: 1, // Reset to first page on filter change
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(filterUnassignedSelectedClient, (value) => {
|
||||||
|
navigateWithParams({
|
||||||
|
search: search.value || undefined,
|
||||||
|
assigned_user_id:
|
||||||
|
assignedFilterUserId.value !== "all" ? assignedFilterUserId.value : undefined,
|
||||||
|
unassigned_client_uuids: value?.length > 0 ? value : undefined,
|
||||||
|
assigned_client_uuids:
|
||||||
|
filterAssignedSelectedClient.value?.length > 0
|
||||||
|
? filterAssignedSelectedClient.value
|
||||||
|
: undefined,
|
||||||
|
page_contracts: 1, // Reset to first page on filter change
|
||||||
|
page_assignments: props.assignedContracts?.current_page,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(filterAssignedSelectedClient, (value) => {
|
||||||
|
navigateWithParams({
|
||||||
|
search: search.value || undefined,
|
||||||
|
assigned_user_id:
|
||||||
|
assignedFilterUserId.value !== "all" ? assignedFilterUserId.value : undefined,
|
||||||
|
unassigned_client_uuids:
|
||||||
|
filterUnassignedSelectedClient.value?.length > 0
|
||||||
|
? filterUnassignedSelectedClient.value
|
||||||
|
: undefined,
|
||||||
|
assigned_client_uuids: value?.length > 0 ? value : undefined,
|
||||||
page_contracts: props.unassignedContracts?.current_page,
|
page_contracts: props.unassignedContracts?.current_page,
|
||||||
page_assignments: 1, // Reset to first page on filter change
|
page_assignments: 1, // Reset to first page on filter change
|
||||||
});
|
});
|
||||||
|
|
@ -248,7 +344,7 @@ const unassignedRows = computed(() =>
|
||||||
? null
|
? null
|
||||||
: Number(c.account.balance_amount),
|
: Number(c.account.balance_amount),
|
||||||
case_person: c.client_case?.person?.full_name || null,
|
case_person: c.client_case?.person?.full_name || null,
|
||||||
client_person: c.client?.person?.full_name || null,
|
client_person: c.client_case?.client?.person?.full_name || null,
|
||||||
address: primaryCaseAddress(c) || null,
|
address: primaryCaseAddress(c) || null,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
@ -261,7 +357,7 @@ const assignedRows = computed(() =>
|
||||||
? null
|
? null
|
||||||
: Number(c.account.balance_amount),
|
: Number(c.account.balance_amount),
|
||||||
case_person: c.client_case?.person?.full_name || null,
|
case_person: c.client_case?.person?.full_name || null,
|
||||||
client_person: c.client?.person?.full_name || null,
|
client_person: c.client_case?.client?.person?.full_name || null,
|
||||||
address: primaryCaseAddress(c) || null,
|
address: primaryCaseAddress(c) || null,
|
||||||
assigned_to: c.last_field_jobs.assigned_user.name || null,
|
assigned_to: c.last_field_jobs.assigned_user.name || null,
|
||||||
assigned_at_formatted: formatDate(c.last_field_jobs.assigned_at),
|
assigned_at_formatted: formatDate(c.last_field_jobs.assigned_at),
|
||||||
|
|
@ -272,32 +368,42 @@ const assignedRows = computed(() =>
|
||||||
<template>
|
<template>
|
||||||
<AppLayout title="Dodeljevanje terenskih opravil">
|
<AppLayout title="Dodeljevanje terenskih opravil">
|
||||||
<template #header></template>
|
<template #header></template>
|
||||||
<div class="pt-12">
|
<div class="pt-6">
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||||
|
<AppCard
|
||||||
|
title=""
|
||||||
|
padding="none"
|
||||||
|
class="p-0! gap-0"
|
||||||
|
header-class="p-3! px-4 gap-0 text-muted-foreground"
|
||||||
|
body-class=""
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<FilesIcon size="18" />
|
||||||
|
<CardTitle class="uppercase">Pogodbe (nedodeljene)</CardTitle>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<div
|
<div
|
||||||
v-if="!setting"
|
v-if="!setting"
|
||||||
class="mb-6 flex items-start gap-3 rounded-lg border border-yellow-200 bg-yellow-50 p-4"
|
class="mb-6 flex items-start gap-3 rounded-lg border border-yellow-200 bg-yellow-50 p-4"
|
||||||
>
|
>
|
||||||
<AlertCircle class="h-5 w-5 text-yellow-600 shrink-0 mt-0.5" />
|
<AlertCircle class="h-5 w-5 text-yellow-600 shrink-0 mt-0.5" />
|
||||||
<p class="text-sm text-yellow-800">
|
<p class="text-sm text-yellow-800">
|
||||||
Nastavitev za terenska opravila ni najdena. Najprej jo ustvarite v Nastavitve
|
Nastavitev za terenska opravila ni najdena. Najprej jo ustvarite v
|
||||||
→ Nastavitve terenskih opravil.
|
Nastavitve → Nastavitve terenskih opravil.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Unassigned (Assignable) Contracts -->
|
<!-- Unassigned (Assignable) Contracts -->
|
||||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg mb-8">
|
<div class="overflow-hidden mb-8 border-t">
|
||||||
<div class="p-4 border-b">
|
<div class="p-4 flex flex-row gap-2 items-end">
|
||||||
<h2 class="text-xl font-semibold">Pogodbe (nedodeljene)</h2>
|
|
||||||
</div>
|
|
||||||
<div class="p-4 border-b space-y-4">
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label for="assign-user">Dodeli uporabniku</Label>
|
<Label for="assign-user">Dodeli uporabniku</Label>
|
||||||
<Select v-model="form.assigned_user_id">
|
<Select v-model="form.assigned_user_id">
|
||||||
<SelectTrigger id="assign-user" class="max-w-xs">
|
<SelectTrigger id="assign-user" class="max-w-xs min-w-60">
|
||||||
<SelectValue placeholder="Izberite uporabnika" />
|
<SelectValue placeholder="Izberite uporabnika" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent class="min-w-60">
|
||||||
<SelectItem v-for="u in users || []" :key="u.id" :value="u.id">
|
<SelectItem v-for="u in users || []" :key="u.id" :value="u.id">
|
||||||
{{ u.name }}
|
{{ u.name }}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
|
|
@ -352,12 +458,44 @@ const assignedRows = computed(() =>
|
||||||
>
|
>
|
||||||
<template #toolbar-filters>
|
<template #toolbar-filters>
|
||||||
<div class="flex items-center gap-2 w-full">
|
<div class="flex items-center gap-2 w-full">
|
||||||
|
<AppPopover
|
||||||
|
v-model:open="filterUnassignedContracts"
|
||||||
|
align="start"
|
||||||
|
content-class="w-[350px]"
|
||||||
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<Button variant="outline"
|
||||||
|
><Filter class="h-4 w-4" /> Filtri
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<InputLabel>Iskanje</InputLabel>
|
||||||
<Input
|
<Input
|
||||||
v-model="search"
|
v-model="search"
|
||||||
placeholder="Išči po pogodbi, primeru, stranki, naslovu..."
|
placeholder="Išči po pogodbi, primeru, stranki, naslovu..."
|
||||||
class="w-[320px]"
|
class="w-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<InputLabel>Stranke</InputLabel>
|
||||||
|
<AppMultiSelect
|
||||||
|
v-model="filterUnassignedSelectedClient"
|
||||||
|
:items="
|
||||||
|
(props.unassignedClients || []).map((client) => ({
|
||||||
|
value: client.uuid,
|
||||||
|
label: client.person.full_name,
|
||||||
|
}))
|
||||||
|
"
|
||||||
|
placeholder="Vse stranke"
|
||||||
|
search-placeholder="Išči stranko..."
|
||||||
|
empty-text="Ni strank"
|
||||||
|
chip-variant="secondary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AppPopover>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #cell-_select="{ row }">
|
<template #cell-_select="{ row }">
|
||||||
|
|
@ -390,12 +528,21 @@ const assignedRows = computed(() =>
|
||||||
</template>
|
</template>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
</div>
|
</div>
|
||||||
|
</AppCard>
|
||||||
<!-- Assigned Contracts -->
|
<!-- Assigned Contracts -->
|
||||||
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
<AppCard
|
||||||
<div class="p-4 border-b">
|
title=""
|
||||||
<h2 class="text-xl font-semibold">Dodeljene pogodbe</h2>
|
padding="none"
|
||||||
|
class="p-0! gap-0"
|
||||||
|
header-class="p-3! px-4 gap-0 text-muted-foreground"
|
||||||
|
body-class=""
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<FileCheckCornerIcon size="18" />
|
||||||
|
<CardTitle class="uppercase">Dodeljene pogodbe</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
<DataTable
|
<DataTable
|
||||||
:columns="assignedColumns"
|
:columns="assignedColumns"
|
||||||
:data="assignedRows"
|
:data="assignedRows"
|
||||||
|
|
@ -418,17 +565,27 @@ const assignedRows = computed(() =>
|
||||||
>
|
>
|
||||||
<template #toolbar-filters>
|
<template #toolbar-filters>
|
||||||
<div class="flex items-center gap-2 w-full">
|
<div class="flex items-center gap-2 w-full">
|
||||||
<Input
|
<AppPopover
|
||||||
v-model="search_contract"
|
v-model:open="filterAssignedContracts"
|
||||||
placeholder="Išči po pogodbi, primeru, stranki..."
|
align="start"
|
||||||
class="w-[320px]"
|
content-class="w-[350px]"
|
||||||
/>
|
|
||||||
<div class="flex items-center gap-2 ml-4">
|
|
||||||
<Label for="filter-user" class="text-sm whitespace-nowrap"
|
|
||||||
>Filter po uporabniku</Label
|
|
||||||
>
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<Button variant="outline"><Filter class="h-4 w-4" /> Filtri </Button>
|
||||||
|
</template>
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<InputLabel>Iskanje</InputLabel>
|
||||||
|
<Input
|
||||||
|
v-model="searchAssigned"
|
||||||
|
placeholder="Išči po pogodbi, primeru, stranki, naslovu..."
|
||||||
|
class="w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<InputLabel>Filter po uporabniku</InputLabel>
|
||||||
<Select v-model="assignedFilterUserId">
|
<Select v-model="assignedFilterUserId">
|
||||||
<SelectTrigger id="filter-user" class="w-48">
|
<SelectTrigger id="filter-user">
|
||||||
<SelectValue placeholder="Vsi" />
|
<SelectValue placeholder="Vsi" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
|
@ -443,6 +600,24 @@ const assignedRows = computed(() =>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
<InputLabel>Stranke</InputLabel>
|
||||||
|
<AppMultiSelect
|
||||||
|
v-model="filterAssignedSelectedClient"
|
||||||
|
:items="
|
||||||
|
(props.assignedClients || []).map((client) => ({
|
||||||
|
value: client.uuid,
|
||||||
|
label: client.person.full_name,
|
||||||
|
}))
|
||||||
|
"
|
||||||
|
placeholder="Vse stranke"
|
||||||
|
search-placeholder="Išči stranko..."
|
||||||
|
empty-text="Ni strank"
|
||||||
|
chip-variant="secondary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AppPopover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #cell-case_person="{ row }">
|
<template #cell-case_person="{ row }">
|
||||||
|
|
@ -469,7 +644,7 @@ const assignedRows = computed(() =>
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
</div>
|
</AppCard>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,9 @@ const filteredTemplates = computed(() => {
|
||||||
if (!form.client_uuid) {
|
if (!form.client_uuid) {
|
||||||
return props.templates.filter((t) => !t.client_id);
|
return props.templates.filter((t) => !t.client_id);
|
||||||
}
|
}
|
||||||
return props.templates.filter((t) => t.client_uuid === form.client_uuid || !t.client_id);
|
return props.templates.filter(
|
||||||
|
(t) => t.client_uuid === form.client_uuid || !t.client_id
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const uploading = ref(false);
|
const uploading = ref(false);
|
||||||
|
|
@ -153,7 +155,30 @@ async function startImport() {
|
||||||
<Label>Predloga</Label>
|
<Label>Predloga</Label>
|
||||||
<Select v-model="form.import_template_id">
|
<Select v-model="form.import_template_id">
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Izberite predlogo..." />
|
<SelectValue placeholder="Izberite predlogo...">
|
||||||
|
<template v-if="form.import_template_id">
|
||||||
|
<div class="flex w-full items-center justify-between">
|
||||||
|
<span class="truncate">
|
||||||
|
{{
|
||||||
|
filteredTemplates.find(
|
||||||
|
(t) => t.id === form.import_template_id
|
||||||
|
)?.name
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="ml-2 rounded bg-gray-100 px-1.5 py-0.5 text-[10px] text-gray-600 dark:bg-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
filteredTemplates.find(
|
||||||
|
(t) => t.id === form.import_template_id
|
||||||
|
)?.client_id
|
||||||
|
? "Client"
|
||||||
|
: "Global"
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
|
|
@ -209,7 +234,9 @@ async function startImport() {
|
||||||
<span class="text-xs text-gray-500">
|
<span class="text-xs text-gray-500">
|
||||||
{{ (form.file.size / 1024).toFixed(1) }} kB
|
{{ (form.file.size / 1024).toFixed(1) }} kB
|
||||||
</span>
|
</span>
|
||||||
<span class="inline-block rounded bg-gray-100 px-1.5 py-0.5 text-[10px]">
|
<span
|
||||||
|
class="inline-block rounded bg-gray-100 px-1.5 py-0.5 text-[10px]"
|
||||||
|
>
|
||||||
Zamenjaj
|
Zamenjaj
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user