Package and individual mail sender, new report, and other changes
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -1,176 +1,45 @@
|
||||
<script setup>
|
||||
import AppLayout from "@/Layouts/AppLayout.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";
|
||||
import { fmtDateTime } from "@/Utilities/functions";
|
||||
|
||||
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: "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("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("packages.destroy", packageToDelete.value.id), {
|
||||
onSuccess: () => {
|
||||
router.reload({ only: ["packages"] });
|
||||
},
|
||||
onFinish: () => {
|
||||
deletingId.value = null;
|
||||
showDeleteDialog.value = false;
|
||||
packageToDelete.value = null;
|
||||
},
|
||||
});
|
||||
}
|
||||
import { Link } from "@inertiajs/vue3";
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/Components/ui/card";
|
||||
import { MessageSquareIcon, MailIcon } from "lucide-vue-next";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout 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" />
|
||||
<AppLayout title="Paketi">
|
||||
<div class="mb-6">
|
||||
<h1 class="text-2xl font-bold tracking-tight">Paketi</h1>
|
||||
<p class="text-sm text-muted-foreground">Izberite vrsto paketa za pošiljanje</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 sm:grid-cols-2 max-w-2xl">
|
||||
<Link :href="route('packages.sms.index')">
|
||||
<Card class="cursor-pointer hover:border-primary transition-colors h-full">
|
||||
<CardHeader>
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
|
||||
<MessageSquareIcon class="h-5 w-5 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<CardTitle>SMS paketi</CardTitle>
|
||||
</div>
|
||||
<Link :href="route('packages.create')">
|
||||
<Button>
|
||||
<PlusIcon class="h-4 w-4" />
|
||||
Nov paket
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<CardDescription>Pošlji SMS sporočila v paketu prejemnikom iz pogodb ali ročno vnesenih številk</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</Link>
|
||||
|
||||
<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="packages.index"
|
||||
>
|
||||
<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">{{
|
||||
fmtDateTime(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>
|
||||
<Link :href="route('packages.email.index')">
|
||||
<Card class="cursor-pointer hover:border-primary transition-colors h-full">
|
||||
<CardHeader>
|
||||
<div class="flex items-center gap-3 mb-2">
|
||||
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
|
||||
<MailIcon class="h-5 w-5 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<CardTitle>E-mail paketi</CardTitle>
|
||||
<CardDescription>Pošlji e-mail sporočila v paketu prejemnikom iz pogodb z e-mail predlogami</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</Link>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user