changes to sms packages and option to create user

This commit is contained in:
Simon Pocrnjič
2025-11-06 21:54:07 +01:00
parent ad8e0d5cee
commit 1395b72ae8
102 changed files with 1386 additions and 319 deletions
+70 -11
View File
@@ -35,6 +35,15 @@ const filteredSenders = computed(() => {
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
@@ -78,6 +87,8 @@ const contracts = ref({ data: [], meta: { current_page: 1, last_page: 1, per_pag
const segmentId = ref(null)
const search = ref('')
const clientId = ref(null)
const startDateFrom = ref('')
const startDateTo = ref('')
const onlyMobile = ref(false)
const onlyValidated = ref(false)
const loadingContracts = ref(false)
@@ -90,7 +101,7 @@ async function loadContracts(url = null) {
}
loadingContracts.value = true
try {
const target = url || `${route('admin.packages.contracts')}?segment_id=${encodeURIComponent(segmentId.value)}${search.value ? `&q=${encodeURIComponent(search.value)}` : ''}${clientId.value ? `&client_id=${encodeURIComponent(clientId.value)}` : ''}${onlyMobile.value ? `&only_mobile=1` : ''}${onlyValidated.value ? `&only_validated=1` : ''}`
const target = url || `${route('admin.packages.contracts')}?segment_id=${encodeURIComponent(segmentId.value)}${search.value ? `&q=${encodeURIComponent(search.value)}` : ''}${clientId.value ? `&client_id=${encodeURIComponent(clientId.value)}` : ''}${startDateFrom.value ? `&start_date_from=${encodeURIComponent(startDateFrom.value)}` : ''}${startDateTo.value ? `&start_date_to=${encodeURIComponent(startDateTo.value)}` : ''}${onlyMobile.value ? `&only_mobile=1` : ''}${onlyValidated.value ? `&only_validated=1` : ''}`
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 } }
@@ -110,11 +121,37 @@ function clearSelection() {
selectedContractIds.value = new Set()
}
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 base = `${route('admin.packages.contracts')}?segment_id=${encodeURIComponent(segmentId.value)}${search.value ? `&q=${encodeURIComponent(search.value)}` : ''}${clientId.value ? `&client_id=${encodeURIComponent(clientId.value)}` : ''}${onlyMobile.value ? `&only_mobile=1` : ''}${onlyValidated.value ? `&only_validated=1` : ''}&page=${nextPage}`
const base = `${route('admin.packages.contracts')}?segment_id=${encodeURIComponent(segmentId.value)}${search.value ? `&q=${encodeURIComponent(search.value)}` : ''}${clientId.value ? `&client_id=${encodeURIComponent(clientId.value)}` : ''}${startDateFrom.value ? `&start_date_from=${encodeURIComponent(startDateFrom.value)}` : ''}${startDateTo.value ? `&start_date_to=${encodeURIComponent(startDateTo.value)}` : ''}${onlyMobile.value ? `&only_mobile=1` : ''}${onlyValidated.value ? `&only_validated=1` : ''}&page=${nextPage}`
loadContracts(base)
}
@@ -179,7 +216,7 @@ function submitCreateFromContracts() {
</div>
<div>
<label class="block text-xs text-gray-500 mb-1">Predloga</label>
<select v-model.number="form.template_id" class="w-full rounded border-gray-300 text-sm">
<select v-model.number="form.template_id" @change="onTemplateChange" class="w-full rounded border-gray-300 text-sm">
<option :value="null"></option>
<option v-for="t in templates" :key="t.id" :value="t.id">{{ t.name }}</option>
</select>
@@ -220,12 +257,20 @@ function submitCreateFromContracts() {
<option v-for="c in clients" :key="c.id" :value="c.id">{{ c.name }}</option>
</select>
</div>
<div class="sm:col-span-2">
<div>
<label class="block text-xs text-gray-500 mb-1">Iskanje</label>
<div class="flex gap-2">
<input v-model="search" @keyup.enter="loadContracts()" type="text" class="w-full rounded border-gray-300 text-sm" placeholder="referenca...">
<button @click="loadContracts()" class="px-3 py-1.5 rounded border text-sm">Išči</button>
</div>
<input v-model="search" @keyup.enter="loadContracts()" type="text" class="w-full rounded border-gray-300 text-sm" placeholder="referenca...">
</div>
<div>
<label class="block text-xs text-gray-500 mb-1">Datum začetka od</label>
<input v-model="startDateFrom" @change="loadContracts()" type="date" class="w-full rounded border-gray-300 text-sm">
</div>
<div>
<label class="block text-xs text-gray-500 mb-1">Datum začetka do</label>
<input v-model="startDateTo" @change="loadContracts()" type="date" class="w-full rounded border-gray-300 text-sm">
</div>
<div class="flex items-end">
<button @click="loadContracts()" class="px-3 py-1.5 rounded border text-sm h-fit">Išči</button>
</div>
<div class="sm:col-span-3 flex items-center gap-6 text-sm text-gray-700">
<label class="inline-flex items-center gap-2">
@@ -240,10 +285,21 @@ function submitCreateFromContracts() {
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr class="text-xs text-gray-500">
<th class="px-3 py-2"></th>
<th class="px-3 py-2">
<input
type="checkbox"
:checked="allCurrentPageSelected"
:indeterminate="someCurrentPageSelected"
@change="toggleSelectAll"
:disabled="!contracts.data.length"
class="rounded"
title="Izberi vse na tej strani"
>
</th>
<th class="px-3 py-2 text-left">Pogodba</th>
<th class="px-3 py-2 text-left">Primer</th>
<th class="px-3 py-2 text-left">Stranka</th>
<th class="px-3 py-2 text-left">Datum začetka</th>
<th class="px-3 py-2 text-left">Izbrana številka</th>
<th class="px-3 py-2 text-left">Opomba</th>
</tr>
@@ -263,6 +319,9 @@ function submitCreateFromContracts() {
<td class="px-3 py-2">
<div class="text-xs text-gray-800">{{ c.client?.name || '—' }}</div>
</td>
<td class="px-3 py-2">
<div class="text-xs text-gray-700">{{ c.start_date ? new Date(c.start_date).toLocaleDateString('sl-SI') : '—' }}</div>
</td>
<td class="px-3 py-2">
<div v-if="c.selected_phone" class="text-xs">
{{ c.selected_phone.number }}
@@ -273,11 +332,11 @@ function submitCreateFromContracts() {
<td class="px-3 py-2 text-xs text-gray-500">{{ c.no_phone_reason || '—' }}</td>
</tr>
<tr v-if="!contracts.data?.length">
<td colspan="6" class="px-3 py-8 text-center text-sm text-gray-500">Ni rezultatov.</td>
<td colspan="7" class="px-3 py-8 text-center text-sm text-gray-500">Ni rezultatov.</td>
</tr>
</tbody>
<tbody v-else>
<tr><td colspan="6" class="px-3 py-6 text-center text-sm text-gray-500">Nalaganje...</td></tr>
<tr><td colspan="7" class="px-3 py-6 text-center text-sm text-gray-500">Nalaganje...</td></tr>
</tbody>
</table>
</div>