Changes
This commit is contained in:
@@ -1,53 +1,31 @@
|
||||
<script setup>
|
||||
import AdminLayout from "@/Layouts/AdminLayout.vue";
|
||||
import { Link, router, useForm } from "@inertiajs/vue3";
|
||||
import { ref, computed } from "vue";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/Components/ui/card";
|
||||
import { Link, router } from "@inertiajs/vue3";
|
||||
import { ref } from "vue";
|
||||
import { Card, CardHeader, CardTitle } from "@/Components/ui/card";
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import { Input } from "@/Components/ui/input";
|
||||
import { Label } from "@/Components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/Components/ui/select";
|
||||
import { Textarea } from "@/Components/ui/textarea";
|
||||
import { Checkbox } from "@/Components/ui/checkbox";
|
||||
import { Badge } from "@/Components/ui/badge";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/Components/ui/table";
|
||||
import { Separator } from "@/Components/ui/separator";
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/Components/ui/alert-dialog";
|
||||
import DataTableNew2 from "@/Components/DataTable/DataTableNew2.vue";
|
||||
import Pagination from "@/Components/Pagination.vue";
|
||||
import {
|
||||
PackageIcon,
|
||||
PlusIcon,
|
||||
XIcon,
|
||||
SearchIcon,
|
||||
Trash2Icon,
|
||||
EyeIcon,
|
||||
} from "lucide-vue-next";
|
||||
import { PackageIcon, PlusIcon, Trash2Icon, EyeIcon } from "lucide-vue-next";
|
||||
import AppCard from "@/Components/app/ui/card/AppCard.vue";
|
||||
|
||||
const props = defineProps({
|
||||
packages: { type: Object, required: true },
|
||||
profiles: { type: Array, default: () => [] },
|
||||
senders: { type: Array, default: () => [] },
|
||||
templates: { type: Array, default: () => [] },
|
||||
segments: { type: Array, default: () => [] },
|
||||
clients: { type: Array, default: () => [] },
|
||||
});
|
||||
|
||||
const deletingId = ref(null);
|
||||
const creatingFromContracts = ref(false);
|
||||
const packageToDelete = ref(null);
|
||||
const showDeleteDialog = ref(false);
|
||||
|
||||
const columns = [
|
||||
{ accessorKey: "id", header: "ID" },
|
||||
@@ -73,242 +51,23 @@ function goShow(id) {
|
||||
router.visit(route("admin.packages.show", id));
|
||||
}
|
||||
|
||||
const showCreate = ref(false);
|
||||
const createMode = ref("numbers"); // 'numbers' | 'contracts'
|
||||
const form = useForm({
|
||||
type: "sms",
|
||||
name: "",
|
||||
description: "",
|
||||
profile_id: null,
|
||||
sender_id: null,
|
||||
template_id: null,
|
||||
delivery_report: false,
|
||||
body: "",
|
||||
numbers: "", // one per line
|
||||
});
|
||||
|
||||
const filteredSenders = computed(() => {
|
||||
if (!form.profile_id) return props.senders;
|
||||
return props.senders.filter((s) => s.profile_id === form.profile_id);
|
||||
});
|
||||
|
||||
function onTemplateChange() {
|
||||
const template = props.templates.find((t) => t.id === form.template_id);
|
||||
if (template?.content) {
|
||||
form.body = template.content;
|
||||
} else {
|
||||
form.body = "";
|
||||
}
|
||||
}
|
||||
|
||||
function submitCreate() {
|
||||
const lines = (form.numbers || "")
|
||||
.split(/\r?\n/)
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
if (!lines.length) return;
|
||||
if (!form.profile_id && !form.template_id) {
|
||||
// require profile if no template/default profile resolution available
|
||||
alert("Izberi SMS profil ali predlogo.");
|
||||
return;
|
||||
}
|
||||
if (!form.template_id && !form.body) {
|
||||
alert("Vnesi vsebino sporočila ali izberi predlogo.");
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
type: "sms",
|
||||
name: form.name || `SMS paket ${new Date().toLocaleString()}`,
|
||||
description: form.description || "",
|
||||
items: lines.map((number) => ({
|
||||
number,
|
||||
payload: {
|
||||
profile_id: form.profile_id,
|
||||
sender_id: form.sender_id,
|
||||
template_id: form.template_id,
|
||||
delivery_report: !!form.delivery_report,
|
||||
body: form.body && form.body.trim() ? form.body.trim() : null,
|
||||
},
|
||||
})),
|
||||
};
|
||||
|
||||
router.post(route("admin.packages.store"), payload, {
|
||||
onSuccess: () => {
|
||||
form.reset();
|
||||
showCreate.value = false;
|
||||
router.reload({ only: ["packages"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Contracts mode state & actions
|
||||
const contracts = ref({
|
||||
data: [],
|
||||
meta: { current_page: 1, last_page: 1, per_page: 25, total: 0 },
|
||||
});
|
||||
const segmentId = ref(null);
|
||||
const search = ref("");
|
||||
const clientId = ref(null);
|
||||
const startDateFrom = ref("");
|
||||
const startDateTo = ref("");
|
||||
const promiseDateFrom = ref("");
|
||||
const promiseDateTo = ref("");
|
||||
const onlyMobile = ref(false);
|
||||
const onlyValidated = ref(false);
|
||||
const loadingContracts = ref(false);
|
||||
const selectedContractIds = ref(new Set());
|
||||
const perPage = ref(25);
|
||||
|
||||
async function loadContracts(url = null) {
|
||||
loadingContracts.value = true;
|
||||
try {
|
||||
const params = new URLSearchParams();
|
||||
if (segmentId.value) params.append("segment_id", segmentId.value);
|
||||
if (search.value) params.append("q", search.value);
|
||||
if (clientId.value) params.append("client_id", clientId.value);
|
||||
if (startDateFrom.value) params.append("start_date_from", startDateFrom.value);
|
||||
if (startDateTo.value) params.append("start_date_to", startDateTo.value);
|
||||
if (promiseDateFrom.value) params.append("promise_date_from", promiseDateFrom.value);
|
||||
if (promiseDateTo.value) params.append("promise_date_to", promiseDateTo.value);
|
||||
if (onlyMobile.value) params.append("only_mobile", "1");
|
||||
if (onlyValidated.value) params.append("only_validated", "1");
|
||||
params.append("per_page", perPage.value);
|
||||
|
||||
const target = url || `${route("admin.packages.contracts")}?${params.toString()}`;
|
||||
const res = await fetch(target, {
|
||||
headers: { "X-Requested-With": "XMLHttpRequest" },
|
||||
});
|
||||
const json = await res.json();
|
||||
contracts.value = {
|
||||
data: json.data || [],
|
||||
meta: json.meta || { current_page: 1, last_page: 1, per_page: 25, total: 0 },
|
||||
};
|
||||
} finally {
|
||||
loadingContracts.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSelectContract(id) {
|
||||
const s = selectedContractIds.value;
|
||||
if (s.has(id)) {
|
||||
s.delete(id);
|
||||
} else {
|
||||
s.add(id);
|
||||
}
|
||||
// force reactivity
|
||||
selectedContractIds.value = new Set(Array.from(s));
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
selectedContractIds.value = new Set();
|
||||
}
|
||||
|
||||
function deletePackage(pkg) {
|
||||
function openDeleteDialog(pkg) {
|
||||
if (!pkg || pkg.status !== "draft") return;
|
||||
if (!confirm(`Izbrišem paket #${pkg.id}?`)) return;
|
||||
deletingId.value = pkg.id;
|
||||
router.delete(route("admin.packages.destroy", pkg.id), {
|
||||
packageToDelete.value = pkg;
|
||||
showDeleteDialog.value = true;
|
||||
}
|
||||
|
||||
function confirmDelete() {
|
||||
if (!packageToDelete.value) return;
|
||||
deletingId.value = packageToDelete.value.id;
|
||||
router.delete(route("admin.packages.destroy", packageToDelete.value.id), {
|
||||
onSuccess: () => {
|
||||
router.reload({ only: ["packages"] });
|
||||
},
|
||||
onFinish: () => {
|
||||
deletingId.value = null;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function toggleSelectAll() {
|
||||
const currentPageIds = contracts.value.data.map((c) => c.id);
|
||||
const allSelected = currentPageIds.every((id) => selectedContractIds.value.has(id));
|
||||
|
||||
if (allSelected) {
|
||||
// Deselect all on current page
|
||||
currentPageIds.forEach((id) => selectedContractIds.value.delete(id));
|
||||
} else {
|
||||
// Select all on current page
|
||||
currentPageIds.forEach((id) => selectedContractIds.value.add(id));
|
||||
}
|
||||
|
||||
// Force reactivity
|
||||
selectedContractIds.value = new Set(Array.from(selectedContractIds.value));
|
||||
}
|
||||
|
||||
const allCurrentPageSelected = computed(() => {
|
||||
if (!contracts.value.data.length) return false;
|
||||
return contracts.value.data.every((c) => selectedContractIds.value.has(c.id));
|
||||
});
|
||||
|
||||
const someCurrentPageSelected = computed(() => {
|
||||
if (!contracts.value.data.length) return false;
|
||||
return (
|
||||
contracts.value.data.some((c) => selectedContractIds.value.has(c.id)) &&
|
||||
!allCurrentPageSelected.value
|
||||
);
|
||||
});
|
||||
|
||||
function goContractsPage(delta) {
|
||||
const { current_page } = contracts.value.meta;
|
||||
const nextPage = current_page + delta;
|
||||
if (nextPage < 1 || nextPage > contracts.value.meta.last_page) return;
|
||||
|
||||
const params = new URLSearchParams();
|
||||
if (segmentId.value) params.append("segment_id", segmentId.value);
|
||||
if (search.value) params.append("q", search.value);
|
||||
if (clientId.value) params.append("client_id", clientId.value);
|
||||
if (startDateFrom.value) params.append("start_date_from", startDateFrom.value);
|
||||
if (startDateTo.value) params.append("start_date_to", startDateTo.value);
|
||||
if (promiseDateFrom.value) params.append("promise_date_from", promiseDateFrom.value);
|
||||
if (promiseDateTo.value) params.append("promise_date_to", promiseDateTo.value);
|
||||
if (onlyMobile.value) params.append("only_mobile", "1");
|
||||
if (onlyValidated.value) params.append("only_validated", "1");
|
||||
params.append("per_page", perPage.value);
|
||||
params.append("page", nextPage);
|
||||
|
||||
const base = `${route("admin.packages.contracts")}?${params.toString()}`;
|
||||
loadContracts(base);
|
||||
}
|
||||
|
||||
function submitCreateFromContracts() {
|
||||
const ids = Array.from(selectedContractIds.value);
|
||||
if (!ids.length) return;
|
||||
// Optional quick client-side sanity: if all selected are from current page and none have phones, warn early.
|
||||
const visibleById = new Map((contracts.value.data || []).map((c) => [c.id, c]));
|
||||
const selectedVisible = ids.map((id) => visibleById.get(id)).filter(Boolean);
|
||||
if (selectedVisible.length && selectedVisible.every((c) => !c?.selected_phone)) {
|
||||
alert("Za izbrane pogodbe ni mogoče najti prejemnikov (telefonov).");
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
type: "sms",
|
||||
name: form.name || `SMS paket (segment) ${new Date().toLocaleString()}`,
|
||||
description: form.description || "",
|
||||
payload: {
|
||||
profile_id: form.profile_id,
|
||||
sender_id: form.sender_id,
|
||||
template_id: form.template_id,
|
||||
delivery_report: !!form.delivery_report,
|
||||
body: form.body && form.body.trim() ? form.body.trim() : null,
|
||||
},
|
||||
contract_ids: ids,
|
||||
};
|
||||
|
||||
creatingFromContracts.value = true;
|
||||
router.post(route("admin.packages.store-from-contracts"), payload, {
|
||||
onSuccess: () => {
|
||||
clearSelection();
|
||||
showCreate.value = false;
|
||||
router.reload({ only: ["packages"] });
|
||||
},
|
||||
onError: (errors) => {
|
||||
// Show the first validation error if present
|
||||
const first = errors && Object.values(errors)[0];
|
||||
if (first) {
|
||||
alert(String(first));
|
||||
}
|
||||
},
|
||||
onFinish: () => {
|
||||
creatingFromContracts.value = false;
|
||||
showDeleteDialog.value = false;
|
||||
packageToDelete.value = null;
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -323,444 +82,16 @@ function submitCreateFromContracts() {
|
||||
<PackageIcon class="h-5 w-5 text-muted-foreground" />
|
||||
<CardTitle>SMS paketi</CardTitle>
|
||||
</div>
|
||||
<Button
|
||||
@click="showCreate = !showCreate"
|
||||
:variant="showCreate ? 'outline' : 'default'"
|
||||
>
|
||||
<component :is="showCreate ? XIcon : PlusIcon" class="h-4 w-4 mr-2" />
|
||||
{{ showCreate ? "Zapri" : "Nov paket" }}
|
||||
</Button>
|
||||
<Link :href="route('admin.packages.create')">
|
||||
<Button>
|
||||
<PlusIcon class="h-4 w-4 mr-2" />
|
||||
Nov paket
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
|
||||
<Card v-if="showCreate" class="mb-6">
|
||||
<CardContent class="pt-6">
|
||||
<div class="mb-4 flex items-center gap-4">
|
||||
<Label class="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
value="numbers"
|
||||
v-model="createMode"
|
||||
class="rounded-full"
|
||||
/>
|
||||
Vnos številk
|
||||
</Label>
|
||||
<Label class="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
value="contracts"
|
||||
v-model="createMode"
|
||||
class="rounded-full"
|
||||
/>
|
||||
Iz pogodb (segment)
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-3 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label>Profil</Label>
|
||||
<Select v-model="form.profile_id">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="—" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">—</SelectItem>
|
||||
<SelectItem v-for="p in profiles" :key="p.id" :value="p.id">{{
|
||||
p.name
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>Pošiljatelj</Label>
|
||||
<Select v-model="form.sender_id">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="—" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">—</SelectItem>
|
||||
<SelectItem v-for="s in filteredSenders" :key="s.id" :value="s.id">
|
||||
{{ s.sname }} <span v-if="s.phone_number">({{ s.phone_number }})</span>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>Predloga</Label>
|
||||
<Select v-model="form.template_id" @update:model-value="onTemplateChange">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="—" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">—</SelectItem>
|
||||
<SelectItem v-for="t in templates" :key="t.id" :value="t.id">{{
|
||||
t.name
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="sm:col-span-3 space-y-2">
|
||||
<Label>Vsebina (če ni predloge)</Label>
|
||||
<Textarea v-model="form.body" rows="3" placeholder="Sporočilo..." />
|
||||
<div class="flex items-center gap-2">
|
||||
<Checkbox
|
||||
:checked="form.delivery_report"
|
||||
@update:checked="(val) => (form.delivery_report = val)"
|
||||
id="delivery-report"
|
||||
/>
|
||||
<Label for="delivery-report" class="cursor-pointer"
|
||||
>Zahtevaj delivery report</Label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Numbers mode -->
|
||||
<template v-if="createMode === 'numbers'">
|
||||
<div class="sm:col-span-3 space-y-2">
|
||||
<Label>Telefonske številke (ena na vrstico)</Label>
|
||||
<Textarea
|
||||
v-model="form.numbers"
|
||||
rows="4"
|
||||
placeholder="+38640123456 +38640123457"
|
||||
/>
|
||||
</div>
|
||||
<div class="sm:col-span-3 flex items-center justify-end gap-2">
|
||||
<Button @click="submitCreate"> Ustvari paket </Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Contracts mode -->
|
||||
<template v-else>
|
||||
<div class="sm:col-span-3 space-y-4">
|
||||
<Separator />
|
||||
<!-- Basic filters -->
|
||||
<div class="grid sm:grid-cols-3 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label>Segment</Label>
|
||||
<Select v-model="segmentId" @update:model-value="loadContracts()">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Vsi segmenti" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">Vsi segmenti</SelectItem>
|
||||
<SelectItem v-for="s in segments" :key="s.id" :value="s.id">{{
|
||||
s.name
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>Stranka</Label>
|
||||
<Select v-model="clientId" @update:model-value="loadContracts()">
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Vse stranke" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="null">Vse stranke</SelectItem>
|
||||
<SelectItem v-for="c in clients" :key="c.id" :value="c.id">{{
|
||||
c.name
|
||||
}}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>Iskanje po referenci</Label>
|
||||
<Input
|
||||
v-model="search"
|
||||
@keyup.enter="loadContracts()"
|
||||
type="text"
|
||||
placeholder="Vnesi referenco..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Date range filters -->
|
||||
<Separator />
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold mb-3">Datumski filtri</h4>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<div class="text-sm font-medium text-muted-foreground mb-2">
|
||||
Datum začetka pogodbe
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div class="space-y-2">
|
||||
<Label>Od</Label>
|
||||
<Input
|
||||
v-model="startDateFrom"
|
||||
@change="loadContracts()"
|
||||
type="date"
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>Do</Label>
|
||||
<Input
|
||||
v-model="startDateTo"
|
||||
@change="loadContracts()"
|
||||
type="date"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-muted-foreground mb-2">
|
||||
Datum obljube plačila
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div class="space-y-2">
|
||||
<Label>Od</Label>
|
||||
<Input
|
||||
v-model="promiseDateFrom"
|
||||
@change="loadContracts()"
|
||||
type="date"
|
||||
/>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<Label>Do</Label>
|
||||
<Input
|
||||
v-model="promiseDateTo"
|
||||
@change="loadContracts()"
|
||||
type="date"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phone filters -->
|
||||
<Separator />
|
||||
<div>
|
||||
<h4 class="text-sm font-semibold mb-3">Telefonski filtri</h4>
|
||||
<div class="flex items-center gap-6">
|
||||
<div class="flex items-center gap-2">
|
||||
<Checkbox
|
||||
:checked="onlyMobile"
|
||||
@update:checked="
|
||||
(val) => {
|
||||
onlyMobile = val;
|
||||
loadContracts();
|
||||
}
|
||||
"
|
||||
id="only-mobile"
|
||||
/>
|
||||
<Label for="only-mobile" class="cursor-pointer"
|
||||
>Samo mobilne številke</Label
|
||||
>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Checkbox
|
||||
:checked="onlyValidated"
|
||||
@update:checked="
|
||||
(val) => {
|
||||
onlyValidated = val;
|
||||
loadContracts();
|
||||
}
|
||||
"
|
||||
id="only-validated"
|
||||
/>
|
||||
<Label for="only-validated" class="cursor-pointer"
|
||||
>Samo potrjene številke</Label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Action buttons -->
|
||||
<div class="flex items-center gap-2">
|
||||
<Button @click="loadContracts()">
|
||||
<SearchIcon class="h-4 w-4 mr-2" />
|
||||
Išči pogodbe
|
||||
</Button>
|
||||
<Button
|
||||
@click="
|
||||
segmentId = null;
|
||||
clientId = null;
|
||||
search = '';
|
||||
startDateFrom = '';
|
||||
startDateTo = '';
|
||||
promiseDateFrom = '';
|
||||
promiseDateTo = '';
|
||||
onlyMobile = false;
|
||||
onlyValidated = false;
|
||||
contracts.value = {
|
||||
data: [],
|
||||
meta: { current_page: 1, last_page: 1, per_page: 25, total: 0 },
|
||||
};
|
||||
"
|
||||
variant="outline"
|
||||
>
|
||||
Počisti filtre
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Results table -->
|
||||
<div class="sm:col-span-3">
|
||||
<Card>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="allCurrentPageSelected"
|
||||
:indeterminate="someCurrentPageSelected"
|
||||
@change="toggleSelectAll"
|
||||
:disabled="!contracts.data.length"
|
||||
class="rounded"
|
||||
title="Izberi vse na tej strani"
|
||||
/>
|
||||
</TableHead>
|
||||
<TableHead>Pogodba</TableHead>
|
||||
<TableHead>Primer</TableHead>
|
||||
<TableHead>Stranka</TableHead>
|
||||
<TableHead>Datum začetka</TableHead>
|
||||
<TableHead>Zadnja obljuba</TableHead>
|
||||
<TableHead>Izbrana številka</TableHead>
|
||||
<TableHead>Opomba</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody v-if="!loadingContracts">
|
||||
<TableRow v-for="c in contracts.data" :key="c.id">
|
||||
<TableCell>
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="selectedContractIds.has(c.id)"
|
||||
@change="toggleSelectContract(c.id)"
|
||||
class="rounded"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div class="font-mono text-xs text-muted-foreground">
|
||||
{{ c.uuid }}
|
||||
</div>
|
||||
<a
|
||||
v-if="c.case?.uuid"
|
||||
:href="route('clientCase.show', c.case.uuid)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-xs font-medium text-primary hover:underline"
|
||||
>
|
||||
{{ c.reference }}
|
||||
</a>
|
||||
<div v-else class="text-xs font-medium">{{ c.reference }}</div>
|
||||
</TableCell>
|
||||
<TableCell class="text-xs">
|
||||
{{ c.person?.full_name || "—" }}
|
||||
</TableCell>
|
||||
<TableCell class="text-xs">{{ c.client?.name || "—" }}</TableCell>
|
||||
<TableCell class="text-xs">{{
|
||||
c.start_date
|
||||
? new Date(c.start_date).toLocaleDateString("sl-SI")
|
||||
: "—"
|
||||
}}</TableCell>
|
||||
<TableCell class="text-xs">{{
|
||||
c.promise_date
|
||||
? new Date(c.promise_date).toLocaleDateString("sl-SI")
|
||||
: "—"
|
||||
}}</TableCell>
|
||||
<TableCell>
|
||||
<div v-if="c.selected_phone" class="text-xs">
|
||||
{{ c.selected_phone.number }}
|
||||
<Badge
|
||||
v-if="c.selected_phone.is_mobile"
|
||||
variant="secondary"
|
||||
class="ml-1"
|
||||
>mobitel</Badge
|
||||
>
|
||||
<Badge
|
||||
v-if="c.selected_phone.is_validated"
|
||||
variant="default"
|
||||
class="ml-1"
|
||||
>potrjen</Badge
|
||||
>
|
||||
</div>
|
||||
<div v-else class="text-xs text-muted-foreground">—</div>
|
||||
</TableCell>
|
||||
<TableCell class="text-xs text-muted-foreground">
|
||||
{{ c.no_phone_reason || "—" }}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow v-if="!contracts.data?.length">
|
||||
<TableCell colspan="8" class="text-center text-muted-foreground h-24">
|
||||
Ni rezultatov. Kliknite "Išči pogodbe" za prikaz.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
<TableBody v-else>
|
||||
<TableRow
|
||||
><TableCell colspan="8" class="text-center text-muted-foreground h-24"
|
||||
>Nalaganje...</TableCell
|
||||
></TableRow
|
||||
>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
<div class="mt-3 flex items-center justify-between">
|
||||
<div class="text-sm text-muted-foreground flex items-center gap-4">
|
||||
<span v-if="contracts.data.length">
|
||||
Prikazano stran {{ contracts.meta.current_page }} od
|
||||
{{ contracts.meta.last_page }} (skupaj {{ contracts.meta.total }})
|
||||
</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<Label class="text-xs">Na stran:</Label>
|
||||
<Select v-model="perPage" @update:model-value="loadContracts()">
|
||||
<SelectTrigger class="w-20 h-8">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem :value="10">10</SelectItem>
|
||||
<SelectItem :value="25">25</SelectItem>
|
||||
<SelectItem :value="50">50</SelectItem>
|
||||
<SelectItem :value="100">100</SelectItem>
|
||||
<SelectItem :value="200">200</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
@click="goContractsPage(-1)"
|
||||
:disabled="contracts.meta.current_page <= 1"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
>Nazaj</Button
|
||||
>
|
||||
<Button
|
||||
@click="goContractsPage(1)"
|
||||
:disabled="contracts.meta.current_page >= contracts.meta.last_page"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
>Naprej</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Separator class="sm:col-span-3" />
|
||||
<div class="sm:col-span-3 flex items-center justify-between gap-2">
|
||||
<div class="text-sm">
|
||||
<span class="font-medium">Izbrano: {{ selectedContractIds.size }}</span>
|
||||
<span v-if="selectedContractIds.size > 0" class="ml-2 text-muted-foreground"
|
||||
>({{
|
||||
selectedContractIds.size === 1
|
||||
? "1 pogodba"
|
||||
: `${selectedContractIds.size} pogodb`
|
||||
}})</span
|
||||
>
|
||||
</div>
|
||||
<Button
|
||||
@click="submitCreateFromContracts"
|
||||
:disabled="selectedContractIds.size === 0 || creatingFromContracts"
|
||||
>Ustvari paket</Button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<AppCard
|
||||
title=""
|
||||
padding="none"
|
||||
@@ -771,7 +102,7 @@ function submitCreateFromContracts() {
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2">
|
||||
<PackageIcon size="18" />
|
||||
<CardTitle class="uppercase">Uvozi</CardTitle>
|
||||
<CardTitle class="uppercase">Paketi</CardTitle>
|
||||
</div>
|
||||
</template>
|
||||
<DataTableNew2
|
||||
@@ -807,7 +138,7 @@ function submitCreateFromContracts() {
|
||||
</Button>
|
||||
<Button
|
||||
v-if="row.status === 'draft'"
|
||||
@click="deletePackage(row)"
|
||||
@click="openDeleteDialog(row)"
|
||||
:disabled="deletingId === row.id"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@@ -818,5 +149,28 @@ function submitCreateFromContracts() {
|
||||
</template>
|
||||
</DataTableNew2>
|
||||
</AppCard>
|
||||
|
||||
<!-- Delete Confirmation Dialog -->
|
||||
<AlertDialog v-model:open="showDeleteDialog">
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Izbriši paket?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Ali ste prepričani, da želite izbrisati paket
|
||||
<strong v-if="packageToDelete">#{{ packageToDelete.id }} - {{ packageToDelete.name || 'Brez imena' }}</strong>?
|
||||
Tega dejanja ni mogoče razveljaviti.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Prekliči</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
@click="confirmDelete"
|
||||
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||
>
|
||||
Izbriši
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</AdminLayout>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user