177 lines
5.5 KiB
Vue
177 lines
5.5 KiB
Vue
<script setup>
|
|
import AdminLayout from "@/Layouts/AdminLayout.vue";
|
|
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 { Badge } from "@/Components/ui/badge";
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
} from "@/Components/ui/alert-dialog";
|
|
import DataTableNew2 from "@/Components/DataTable/DataTableNew2.vue";
|
|
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 },
|
|
});
|
|
|
|
const deletingId = ref(null);
|
|
const packageToDelete = ref(null);
|
|
const showDeleteDialog = ref(false);
|
|
|
|
const columns = [
|
|
{ accessorKey: "id", header: "ID" },
|
|
{ accessorKey: "uuid", header: "UUID" },
|
|
{ accessorKey: "name", header: "Ime" },
|
|
{ accessorKey: "type", header: "Tip" },
|
|
{ accessorKey: "status", header: "Status" },
|
|
{ accessorKey: "total_items", header: "Skupaj" },
|
|
{ accessorKey: "sent_count", header: "Poslano" },
|
|
{ accessorKey: "failed_count", header: "Neuspešno" },
|
|
{ accessorKey: "finished_at", header: "Zaključeno" },
|
|
{ accessorKey: "actions", header: "", enableSorting: false },
|
|
];
|
|
|
|
function getStatusVariant(status) {
|
|
if (["queued", "running"].includes(status)) return "secondary";
|
|
if (status === "completed") return "default";
|
|
if (status === "failed") return "destructive";
|
|
return "outline";
|
|
}
|
|
|
|
function goShow(id) {
|
|
router.visit(route("admin.packages.show", id));
|
|
}
|
|
|
|
function openDeleteDialog(pkg) {
|
|
if (!pkg || pkg.status !== "draft") return;
|
|
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;
|
|
showDeleteDialog.value = false;
|
|
packageToDelete.value = null;
|
|
},
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<AdminLayout title="SMS paketi">
|
|
<Card class="mb-4">
|
|
<CardHeader>
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex items-center gap-2">
|
|
<PackageIcon class="h-5 w-5 text-muted-foreground" />
|
|
<CardTitle>SMS paketi</CardTitle>
|
|
</div>
|
|
<Link :href="route('admin.packages.create')">
|
|
<Button>
|
|
<PlusIcon class="h-4 w-4 mr-2" />
|
|
Nov paket
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</CardHeader>
|
|
</Card>
|
|
|
|
<AppCard
|
|
title=""
|
|
padding="none"
|
|
class="p-0! gap-0"
|
|
header-class="py-3! px-4 gap-0 text-muted-foreground"
|
|
body-class=""
|
|
>
|
|
<template #header>
|
|
<div class="flex items-center gap-2">
|
|
<PackageIcon size="18" />
|
|
<CardTitle class="uppercase">Paketi</CardTitle>
|
|
</div>
|
|
</template>
|
|
<DataTableNew2
|
|
:columns="columns"
|
|
:data="packages.data"
|
|
:meta="packages"
|
|
route-name="admin.packages.index"
|
|
>
|
|
<template #cell-uuid="{ row }">
|
|
<span class="font-mono text-xs text-muted-foreground">{{ row.uuid }}</span>
|
|
</template>
|
|
|
|
<template #cell-name="{ row }">
|
|
<span class="text-sm">{{ row.name ?? "—" }}</span>
|
|
</template>
|
|
|
|
<template #cell-type="{ row }">
|
|
<Badge variant="outline" class="uppercase">{{ row.type }}</Badge>
|
|
</template>
|
|
|
|
<template #cell-status="{ row }">
|
|
<Badge :variant="getStatusVariant(row.status)">{{ row.status }}</Badge>
|
|
</template>
|
|
|
|
<template #cell-finished_at="{ row }">
|
|
<span class="text-xs text-muted-foreground">{{ row.finished_at ?? "—" }}</span>
|
|
</template>
|
|
|
|
<template #cell-actions="{ row }">
|
|
<div class="flex justify-end gap-2">
|
|
<Button @click="goShow(row.id)" variant="ghost" size="sm">
|
|
<EyeIcon class="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
v-if="row.status === 'draft'"
|
|
@click="openDeleteDialog(row)"
|
|
:disabled="deletingId === row.id"
|
|
variant="ghost"
|
|
size="sm"
|
|
>
|
|
<Trash2Icon class="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</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>
|