Teren-app/resources/js/Components/PersonDetailPhone.vue
2025-09-28 22:36:47 +02:00

144 lines
7.3 KiB
Vue

<script setup>
import { computed, ref, watch } from 'vue'
const props = defineProps({
person: { type: Object, required: true },
types: { type: Object, default: () => ({}) },
// Allow overriding the default active tab: 'addresses' | 'phones' | 'emails' | 'bank'
defaultTab: { type: String, default: 'addresses' },
})
const phoneTypes = computed(() => {
const arr = props.types?.phone_types || []
const map = {}
for (const t of arr) { map[t.id] = t.name }
return map
})
const displayName = computed(() => {
const p = props.person || {}
const full = p.full_name?.trim()
if (full) { return full }
const first = p.first_name?.trim() || ''
const last = p.last_name?.trim() || ''
return `${first} ${last}`.trim()
})
const primaryAddress = computed(() => props.person?.addresses?.[0] || null)
const primaryEmail = computed(() => props.person?.emails?.[0]?.value || null)
// Backend phone model uses `nu` as the number
const allPhones = computed(() => props.person?.phones || [])
const allAddresses = computed(() => props.person?.addresses || [])
const allEmails = computed(() => props.person?.emails || [])
// Laravel serializes relation names to snake_case, so prefer bank_accounts, fallback to bankAccounts
const allBankAccounts = computed(() => props.person?.bank_accounts || props.person?.bankAccounts || [])
const bankIban = computed(() => allBankAccounts.value?.[0]?.iban || null)
const taxNumber = computed(() => props.person?.tax_number || null)
const ssn = computed(() => props.person?.social_security_number || null)
// Summary sizing
const showMore = ref(false)
const summaryPhones = computed(() => allPhones.value.slice(0, showMore.value ? 2 : 1))
// Tabs
const activeTab = ref(props.defaultTab || 'addresses')
watch(() => props.defaultTab, (val) => { if (val) activeTab.value = val })
function maskIban(iban) {
if (!iban || typeof iban !== 'string') return null
const clean = iban.replace(/\s+/g, '')
if (clean.length <= 8) return clean
return `${clean.slice(0, 4)} **** **** ${clean.slice(-4)}`
}
</script>
<template>
<div class="text-sm">
<div v-if="displayName" class="font-medium text-gray-900">{{ displayName }}</div>
<div v-if="primaryAddress" class="mt-1 text-gray-700">
<span>{{ primaryAddress.address }}</span>
<span v-if="primaryAddress.country" class="text-gray-500 text-xs ml-1">({{ primaryAddress.country }})</span>
</div>
<div v-if="summaryPhones?.length" class="mt-1 space-y-0.5">
<div v-for="p in summaryPhones" :key="p.id" class="text-gray-700">
<span>{{ p.nu }}</span>
<span v-if="(p.type_id && phoneTypes[p.type_id]) || p.type?.name" class="text-gray-500 text-xs ml-1">({{ p.type?.name || phoneTypes[p.type_id] }})</span>
</div>
</div>
<div v-if="showMore && primaryEmail" class="mt-1 text-gray-700">{{ primaryEmail }}</div>
<div v-if="showMore && bankIban" class="mt-1 text-gray-700">TRR: <span class="font-mono">{{ maskIban(bankIban) }}</span></div>
<div v-if="showMore && taxNumber" class="mt-1 text-gray-700">Davčna: <span class="font-mono">{{ taxNumber }}</span></div>
<div v-if="showMore && ssn" class="mt-1 text-gray-700">EMŠO: <span class="font-mono">{{ ssn }}</span></div>
<button type="button" class="mt-2 text-xs text-blue-600 hover:underline" @click="showMore = !showMore">
{{ showMore ? 'Skrij' : 'Prikaži več' }}
</button>
</div>
<!-- Tabs -->
<div class="mt-3">
<div class="flex gap-2 overflow-x-auto">
<button type="button" @click="activeTab = 'addresses'" :class="['px-3 py-1 rounded text-xs inline-flex items-center gap-1', activeTab==='addresses' ? 'bg-gray-200 text-gray-900' : 'bg-white text-gray-700 border']">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"><path d="M10 2a1 1 0 0 1 .832.445l6 8.5a1 1 0 0 1 .168.555V17a1 1 0 0 1-1 1h-4v-4H8v4H4a1 1 0 0 1-1-1v-5.5a1 1 0 0 1 .168-.555l6-8.5A1 1 0 0 1 10 2Z"/></svg>
Naslovi ({{ allAddresses.length }})
</button>
<button type="button" @click="activeTab = 'phones'" :class="['px-3 py-1 rounded text-xs inline-flex items-center gap-1', activeTab==='phones' ? 'bg-gray-200 text-gray-900' : 'bg-white text-gray-700 border']">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"><path d="M2.3 3.3c.6-1 1.9-1.3 2.9-.7l1.7 1a2 2 0 0 1 .9 2.5l-.5 1.2a2 2 0 0 0 .4 2.2l2.8 2.8a2 2 0 0 0 2.2.4l1.2-.5a2 2 0 0 1 2.5.9l1 1.7c.6 1 .3 2.3-.7 2.9-2 1.1-4.5 1.1-6.5 0-2.5-1.3-4.8-3.6-6.1-6.1-1.1-2-1.1-4.5 0-6.5Z"/></svg>
Telefoni ({{ allPhones.length }})
</button>
<button type="button" @click="activeTab = 'emails'" :class="['px-3 py-1 rounded text-xs inline-flex items-center gap-1', activeTab==='emails' ? 'bg-gray-200 text-gray-900' : 'bg-white text-gray-700 border']">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"><path d="M2.5 5A1.5 1.5 0 0 1 4 3.5h12A1.5 1.5 0 0 1 17.5 5v10A1.5 1.5 0 0 1 16 16.5H4A1.5 1.5 0 0 1 2.5 15V5Zm2.1.5 5.4 3.6a1 1 0 0 0 1.1 0l5.4-3.6V5H4.6Z"/></svg>
E-pošta ({{ allEmails.length }})
</button>
<button type="button" @click="activeTab = 'bank'" :class="['px-3 py-1 rounded text-xs inline-flex items-center gap-1', activeTab==='bank' ? 'bg-gray-200 text-gray-900' : 'bg-white text-gray-700 border']">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"><path d="M10 2 2 6v2h16V6l-8-4Zm-6 7h12v7H4V9Zm-1 8h14v1H3v-1Z"/></svg>
TRR ({{ allBankAccounts.length }})
</button>
</div>
<div class="mt-2">
<!-- Addresses -->
<div v-if="activeTab==='addresses'">
<div v-if="!allAddresses.length" class="text-gray-500 text-xs">Ni naslovov.</div>
<div v-for="(a,idx) in allAddresses" :key="a.id || idx" class="py-1">
<div class="text-gray-800">{{ a.address }}</div>
<div v-if="a.country" class="text-gray-600 text-xs">{{ a.country }}</div>
</div>
</div>
<!-- Phones -->
<div v-else-if="activeTab==='phones'">
<div v-if="!allPhones.length" class="text-gray-500 text-xs">Ni telefonov.</div>
<div v-for="(p,idx) in allPhones" :key="p.id || idx" class="py-1">
<div class="text-gray-800">{{ p.nu }} <span v-if="(p.type_id && phoneTypes[p.type_id]) || p.type?.name" class="text-gray-500 text-xs">({{ p.type?.name || phoneTypes[p.type_id] }})</span></div>
</div>
</div>
<!-- Emails -->
<div v-else-if="activeTab==='emails'">
<div v-if="!allEmails.length" class="text-gray-500 text-xs">Ni e-poštnih naslovov.</div>
<div v-for="(e,idx) in allEmails" :key="e.id || idx" class="py-1">
<div class="text-gray-800">{{ e.value }}<span v-if="e.label" class="text-gray-500 text-xs ml-1">({{ e.label }})</span></div>
</div>
</div>
<!-- Bank accounts -->
<div v-else>
<div v-if="!allBankAccounts.length" class="text-gray-500 text-xs">Ni TRR računov.</div>
<div v-for="(b,idx) in allBankAccounts" :key="b.id || idx" class="py-1">
<div class="text-gray-800">{{ maskIban(b.iban) }}</div>
<div v-if="b.bank_name" class="text-gray-600 text-xs">{{ b.bank_name }}</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
</style>