123 lines
4.6 KiB
Vue
123 lines
4.6 KiB
Vue
<!-- nuxt4-app/app/components/clientes/ClienteCard.vue -->
|
|
<template>
|
|
<div class="relative overflow-hidden rounded-lg border border-gray-400/30 bg-gradient-to-br from-gray-100/10 to-gray-300/5 backdrop-blur-sm p-5 shadow-lg transition-all duration-300 hover:border-gray-300/50 hover:shadow-xl">
|
|
<!-- Header with Avatar and Name -->
|
|
<div class="flex items-start gap-4 mb-4">
|
|
<div class="flex-shrink-0">
|
|
<div class="h-14 w-14 rounded-full bg-gradient-to-br from-gray-300/40 to-gray-500/20 flex items-center justify-center text-xl font-bold text-gray-200 border border-gray-400/30">
|
|
{{ clienteInitials }}
|
|
</div>
|
|
</div>
|
|
<div class="flex-1 min-w-0">
|
|
<h3 class="text-lg font-bold text-gray-100 truncate mb-1">{{ cliente.name }}</h3>
|
|
<div class="flex flex-wrap gap-2 text-xs">
|
|
<span v-if="cliente.cedula" class="inline-flex items-center gap-1 px-2 py-0.5 rounded bg-gray-500/20 text-gray-300 border border-gray-400/20">
|
|
<UIcon name="i-lucide-credit-card" class="w-3 h-3" />
|
|
{{ cliente.cedula }}
|
|
</span>
|
|
<span v-if="cliente.empleado" class="inline-flex items-center gap-1 px-2 py-0.5 rounded bg-blue-500/20 text-blue-300 border border-blue-400/30">
|
|
<UIcon name="i-lucide-briefcase" class="w-3 h-3" />
|
|
Empleado
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<!-- Remove Button -->
|
|
<button
|
|
@click="$emit('remove')"
|
|
class="flex-shrink-0 p-1.5 rounded-full hover:bg-red-500/20 text-gray-400 hover:text-red-400 transition-colors"
|
|
title="Quitar cliente"
|
|
>
|
|
<UIcon name="i-lucide-x" class="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Details Grid -->
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div v-if="cliente.ubicacion" class="flex items-start gap-2">
|
|
<UIcon name="i-lucide-map-pin" class="w-4 h-4 text-gray-400 mt-0.5 flex-shrink-0" />
|
|
<div class="min-w-0 flex-1">
|
|
<div class="text-xs text-gray-500 uppercase tracking-wide">Ubicación</div>
|
|
<div class="text-sm text-gray-200 truncate">{{ cliente.ubicacion }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="cliente.telefono" class="flex items-start gap-2">
|
|
<UIcon name="i-lucide-phone" class="w-4 h-4 text-gray-400 mt-0.5 flex-shrink-0" />
|
|
<div class="min-w-0 flex-1">
|
|
<div class="text-xs text-gray-500 uppercase tracking-wide">Teléfono</div>
|
|
<div class="text-sm text-gray-200 truncate">{{ cliente.telefono }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="cliente.grupo_estudio" class="flex items-start gap-2">
|
|
<UIcon name="i-lucide-users" class="w-4 h-4 text-gray-400 mt-0.5 flex-shrink-0" />
|
|
<div class="min-w-0 flex-1">
|
|
<div class="text-xs text-gray-500 uppercase tracking-wide">Grupo</div>
|
|
<div class="text-sm text-gray-200 truncate">{{ cliente.grupo_estudio }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="cliente.idciat" class="flex items-start gap-2">
|
|
<UIcon name="i-lucide-hash" class="w-4 h-4 text-gray-400 mt-0.5 flex-shrink-0" />
|
|
<div class="min-w-0 flex-1">
|
|
<div class="text-xs text-gray-500 uppercase tracking-wide">ID CIAT</div>
|
|
<div class="text-sm text-gray-200">{{ cliente.idciat }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer with metadata -->
|
|
<div class="mt-4 pt-3 border-t border-gray-400/20 flex items-center justify-between text-xs text-gray-500">
|
|
<span>ID: {{ cliente.id }}</span>
|
|
<span v-if="cliente.created_at">Desde {{ formatDate(cliente.created_at) }}</span>
|
|
</div>
|
|
|
|
<!-- Decorative gradient overlay -->
|
|
<div class="absolute inset-0 bg-gradient-to-tr from-transparent via-transparent to-white/5 pointer-events-none rounded-lg"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
interface ClienteRecord {
|
|
id: number
|
|
created_at: string
|
|
updated_at: string
|
|
name: string
|
|
cedula?: number
|
|
ubicacion?: string
|
|
grupo_estudio?: string
|
|
empleado?: boolean
|
|
avatar_url?: string
|
|
telefono?: string
|
|
idciat?: number
|
|
}
|
|
|
|
interface Props {
|
|
cliente: ClienteRecord
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
|
|
defineEmits<{
|
|
remove: []
|
|
}>()
|
|
|
|
// Compute initials from name
|
|
const clienteInitials = computed(() => {
|
|
const names = props.cliente.name.trim().split(' ')
|
|
if (names.length >= 2 && names[0] && names[1]) {
|
|
return (names[0][0] + names[1][0]).toUpperCase()
|
|
}
|
|
return names[0]?.substring(0, 2).toUpperCase() || 'XX'
|
|
})
|
|
|
|
// Format date helper
|
|
const formatDate = (dateStr: string) => {
|
|
const date = new Date(dateStr)
|
|
return date.toLocaleDateString('es-ES', {
|
|
year: 'numeric',
|
|
month: 'short'
|
|
})
|
|
}
|
|
</script>
|