Files
service-finder/frontend_admin/components/garages/GarageGeneralTab.vue
2026-07-08 08:03:57 +00:00

203 lines
9.5 KiB
Vue

<template>
<div class="space-y-6">
<!-- Company Info -->
<div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden">
<div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3">
<div class="p-2 rounded-lg bg-indigo-500/10 text-indigo-400">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</div>
<h3 class="text-base font-semibold text-white">{{ $t('garages.details.company_info') }}</h3>
</div>
<div class="px-6 py-5">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-4">
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.company_name') }}</p>
<p class="text-sm text-white mt-1">{{ garage.full_name }}</p>
</div>
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.display_name') }}</p>
<p class="text-sm text-white mt-1">{{ garage.display_name || '—' }}</p>
</div>
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.org_type') }}</p>
<p class="text-sm text-white mt-1">{{ orgTypeLabel(garage.org_type) }}</p>
</div>
</div>
<div class="space-y-4">
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.tax_number') }}</p>
<p class="text-sm text-white mt-1">{{ garage.tax_number || '—' }}</p>
</div>
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.reg_number') }}</p>
<p class="text-sm text-white mt-1">{{ garage.reg_number || '—' }}</p>
</div>
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.created_at') }}</p>
<p class="text-sm text-white mt-1">{{ formatDate(garage.created_at) }}</p>
</div>
</div>
</div>
<div class="mt-6 pt-6 border-t border-slate-700/50">
<p class="text-xs text-slate-500 uppercase tracking-wider mb-3">{{ $t('garages.details.address') }}</p>
<p class="text-sm text-white">{{ formattedAddress }}</p>
</div>
<!-- Billing Address -->
<div v-if="formattedBillingAddress" class="mt-4 pt-4 border-t border-slate-700/50">
<p class="text-xs text-slate-500 uppercase tracking-wider mb-3">{{ $t('garages.details.billing_address') }}</p>
<p class="text-sm text-white">{{ formattedBillingAddress }}</p>
</div>
<!-- Notification Address -->
<div v-if="formattedNotificationAddress" class="mt-4 pt-4 border-t border-slate-700/50">
<p class="text-xs text-slate-500 uppercase tracking-wider mb-3">{{ $t('garages.details.notification_address') }}</p>
<p class="text-sm text-white">{{ formattedNotificationAddress }}</p>
</div>
<!-- System IDs Footer -->
<div class="mt-6 pt-4 border-t border-slate-700/50">
<p class="text-xs text-slate-500 uppercase tracking-wider mb-3">Rendszer Azonosítók</p>
<div class="flex gap-6 text-xs font-mono text-slate-500">
<span>Garázs ID: <span class="text-slate-400">{{ garage.id }}</span></span>
<span>User ID: <span class="text-slate-400">{{ garage.owner_user_id ?? 'N/A' }}</span></span>
<span>Person ID: <span class="text-slate-400">{{ garage.owner_person_id ?? 'N/A' }}</span></span>
</div>
</div>
</div>
</div>
<!-- Contact Info -->
<div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden">
<div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3">
<div class="p-2 rounded-lg bg-emerald-500/10 text-emerald-400">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<h3 class="text-base font-semibold text-white">{{ $t('garages.details.contact_info') }}</h3>
</div>
<div class="px-6 py-5">
<!-- Show block if ANY contact data exists (top-level fields or primary_contact) -->
<div v-if="garage.contact_person_name || garage.contact_email || garage.contact_phone || garage.primary_contact" class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-4">
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.contact_name') }}</p>
<p class="text-sm text-white mt-1 font-medium">{{ garage.contact_person_name || garage.primary_contact?.full_name || '—' }}</p>
</div>
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.contact_email') }}</p>
<p class="text-sm text-white mt-1 flex items-center gap-1.5">
<svg class="w-4 h-4 text-slate-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span>{{ garage.contact_email || garage.primary_contact?.email || '—' }}</span>
</p>
</div>
</div>
<div class="space-y-4">
<div>
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.contact_phone') }}</p>
<p class="text-sm text-white mt-1 flex items-center gap-1.5">
<svg class="w-4 h-4 text-slate-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
</svg>
<span>{{ garage.contact_phone || garage.primary_contact?.phone || '—' }}</span>
</p>
</div>
<!-- Extra metadata from primary_contact if available -->
<div v-if="garage.primary_contact?.role || garage.primary_contact?.department">
<p class="text-xs text-slate-500 uppercase tracking-wider">{{ $t('garages.details.contact_role') }}</p>
<p class="text-sm text-white mt-1">{{ garage.primary_contact.role || '—' }}<span v-if="garage.primary_contact?.department"> · {{ garage.primary_contact.department }}</span></p>
</div>
</div>
</div>
<div v-else class="text-center py-4">
<p class="text-sm text-slate-400">{{ $t('garages.details.no_contact') }}</p>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps<{
garage: any
}>()
function orgTypeLabel(type: string): string {
const map: Record<string, string> = {
dealership: 'Dealership',
service: 'Service Center',
rental: 'Rental Agency',
fleet: 'Fleet Operator',
individual: 'Individual',
workshop: 'Workshop',
garage: 'Garage',
other: 'Other',
}
return map[type?.toLowerCase()] || type || '-'
}
function formatDate(dateStr: string | null | undefined): string {
if (!dateStr) return '-'
try {
return new Intl.DateTimeFormat('hu-HU', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}).format(new Date(dateStr))
} catch {
return dateStr
}
}
/**
* Format an address object (address_detail) into a display string.
* Falls back to flat fields (address_zip, address_city, etc.) if address_detail is not available.
*/
function formatAddress(addr: Record<string, any> | null | undefined, flatPrefix: string = 'address'): string {
if (!props.garage) return '-'
// Try address_detail first
if (addr && typeof addr === 'object') {
const parts = [
addr.zip,
addr.city,
addr.street_name,
addr.street_type,
addr.house_number,
].filter(Boolean)
if (parts.length > 0) return parts.join(' ')
if (addr.full_address_text) return addr.full_address_text
}
// Fallback to flat fields
const flatParts = [
props.garage[`${flatPrefix}_zip`],
props.garage[`${flatPrefix}_city`],
props.garage[`${flatPrefix}_street_name`],
props.garage[`${flatPrefix}_street_type`],
props.garage[`${flatPrefix}_house_number`],
].filter(Boolean)
return flatParts.join(' ') || '-'
}
const formattedAddress = computed(() => {
return formatAddress(props.garage?.address_detail, 'address')
})
const formattedBillingAddress = computed(() => {
return formatAddress(props.garage?.billing_address_detail, 'billing')
})
const formattedNotificationAddress = computed(() => {
return formatAddress(props.garage?.notification_address_detail, 'notification')
})
</script>