Teren-app/resources/js/Pages/Admin/SmsLogs/Index.vue
Simon Pocrnjič 930ac83604 SMS service
2025-10-24 21:39:10 +02:00

165 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import AdminLayout from "@/Layouts/AdminLayout.vue";
import { Head, Link, router } from "@inertiajs/vue3";
import { ref, watch } from "vue";
const props = defineProps({
logs: { type: Object, required: true },
profiles: { type: Array, default: () => [] },
templates: { type: Array, default: () => [] },
filters: { type: Object, default: () => ({}) },
});
const f = ref({
status: props.filters.status ?? "",
profile_id: props.filters.profile_id ?? "",
template_id: props.filters.template_id ?? "",
search: props.filters.search ?? "",
from: props.filters.from ?? "",
to: props.filters.to ?? "",
});
function reload() {
const query = Object.fromEntries(
Object.entries(f.value).filter(([_, v]) => v !== null && v !== undefined && v !== "")
);
router.get(route("admin.sms-logs.index"), query, { preserveScroll: true, preserveState: true });
}
watch(
() => [f.value.status, f.value.profile_id, f.value.template_id, f.value.from, f.value.to],
() => reload()
);
function clearFilters() {
f.value = { status: "", profile_id: "", template_id: "", search: "", from: "", to: "" };
reload();
}
</script>
<template>
<AdminLayout title="SMS dnevniki">
<Head title="SMS dnevniki" />
<div class="flex items-center justify-between mb-6">
<h1 class="text-xl font-semibold text-gray-800">SMS dnevniki</h1>
</div>
<div class="rounded-lg border bg-white p-4 shadow-sm mb-4">
<div class="grid grid-cols-1 md:grid-cols-6 gap-3">
<div>
<label class="label">Status</label>
<select v-model="f.status" class="input">
<option value="">Vsi</option>
<option value="queued">queued</option>
<option value="sent">sent</option>
<option value="delivered">delivered</option>
<option value="failed">failed</option>
</select>
</div>
<div>
<label class="label">Profil</label>
<select v-model="f.profile_id" class="input">
<option value="">Vsi</option>
<option v-for="p in profiles" :key="p.id" :value="p.id">{{ p.name }}</option>
</select>
</div>
<div>
<label class="label">Predloga</label>
<select v-model="f.template_id" class="input">
<option value="">Vse</option>
<option v-for="t in templates" :key="t.id" :value="t.id">{{ t.name }}</option>
</select>
</div>
<div>
<label class="label">Od</label>
<input type="date" v-model="f.from" class="input" />
</div>
<div>
<label class="label">Do</label>
<input type="date" v-model="f.to" class="input" />
</div>
<div>
<label class="label">Iskanje</label>
<input
type="text"
v-model="f.search"
class="input"
placeholder="to, sender, provider id, message"
@keyup.enter="reload"
/>
</div>
</div>
<div class="mt-3 flex items-center gap-2">
<button type="button" class="px-3 py-1.5 rounded border text-sm bg-gray-50 hover:bg-gray-100" @click="reload">Filtriraj</button>
<button type="button" class="px-3 py-1.5 rounded border text-sm bg-white hover:bg-gray-50" @click="clearFilters">Počisti</button>
</div>
</div>
<div class="rounded-lg border bg-white overflow-hidden shadow-sm">
<table class="w-full text-sm">
<thead class="bg-gray-50 text-gray-600 text-xs uppercase tracking-wider">
<tr>
<th class="px-3 py-2 text-left">Čas</th>
<th class="px-3 py-2 text-left">Prejemnik</th>
<th class="px-3 py-2 text-left">Sender</th>
<th class="px-3 py-2 text-left">Profil</th>
<th class="px-3 py-2 text-left">Predloga</th>
<th class="px-3 py-2 text-left">Status</th>
<th class="px-3 py-2 text-left">Cena</th>
<th class="px-3 py-2 text-left">Provider ID</th>
<th class="px-3 py-2">&nbsp;</th>
</tr>
</thead>
<tbody>
<tr v-for="log in logs.data" :key="log.id" class="border-t last:border-b hover:bg-gray-50">
<td class="px-3 py-2">{{ new Date(log.created_at).toLocaleString() }}</td>
<td class="px-3 py-2">{{ log.to_number }}</td>
<td class="px-3 py-2">{{ log.sender || '—' }}</td>
<td class="px-3 py-2">{{ log.profile?.name || '—' }}</td>
<td class="px-3 py-2">{{ log.template?.slug || log.template?.name || '—' }}</td>
<td class="px-3 py-2">
<span :class="{
'text-amber-600': log.status === 'queued',
'text-sky-700': log.status === 'sent',
'text-emerald-700': log.status === 'delivered',
'text-rose-700': log.status === 'failed',
}">{{ log.status }}</span>
</td>
<td class="px-3 py-2">{{ log.cost != null ? (Number(log.cost).toFixed(2) + ' ' + (log.currency || '')) : '—' }}</td>
<td class="px-3 py-2">{{ log.provider_message_id || '—' }}</td>
<td class="px-3 py-2 text-right">
<Link :href="route('admin.sms-logs.show', log.id)" class="text-xs px-2 py-1 rounded border text-gray-700 bg-gray-50 hover:bg-gray-100">Ogled</Link>
</td>
</tr>
<tr v-if="!logs.data || logs.data.length === 0">
<td colspan="9" class="px-3 py-6 text-center text-sm text-gray-500">Ni vnosov.</td>
</tr>
</tbody>
</table>
<div class="px-3 py-2 border-t flex items-center justify-between text-xs text-gray-600">
<div>
Prikaz {{ logs.from || 0 }}{{ logs.to || 0 }} od {{ logs.total || 0 }}
</div>
<div class="flex items-center gap-1">
<Link
v-for="l in logs.links"
:key="l.label + l.url"
:href="l.url || '#'"
v-html="l.label"
class="px-2 py-1 rounded border"
:class="[l.active ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white hover:bg-gray-50']"
preserve-scroll
preserve-state
/>
</div>
</div>
</div>
</AdminLayout>
</template>
<style scoped>
.input { width: 100%; border-radius: 0.375rem; border: 1px solid #d1d5db; padding: 0.5rem 0.75rem; font-size: 0.875rem; line-height: 1.25rem; }
.input:focus { outline: 2px solid transparent; outline-offset: 2px; border-color: #6366f1; box-shadow: 0 0 0 1px #6366f1; }
.label { display: block; font-size: 0.65rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: #6b7280; margin-bottom: 0.25rem; }
</style>