feat(vcard-api): tabla VCards completa + modal edicion con redes y apariencia
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
+293
-97
@@ -126,30 +126,55 @@
|
|||||||
<table class="table-auto w-full text-sm" x-show="items.length > 0">
|
<table class="table-auto w-full text-sm" x-show="items.length > 0">
|
||||||
<thead class="border-b border-gray-200 text-left text-xs font-semibold text-gray-500 uppercase">
|
<thead class="border-b border-gray-200 text-left text-xs font-semibold text-gray-500 uppercase">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="py-2 px-3">Nombre</th>
|
<th class="py-2 px-3">Nombre / Cargo</th>
|
||||||
<th class="py-2 px-3">Usuario</th>
|
<th class="py-2 px-3">Usuario</th>
|
||||||
<th class="py-2 px-3">Empresa</th>
|
<th class="py-2 px-3">Empresa</th>
|
||||||
<th class="py-2 px-3">Email</th>
|
<th class="py-2 px-3">Email</th>
|
||||||
|
<th class="py-2 px-3">URL</th>
|
||||||
<th class="py-2 px-3">Estado</th>
|
<th class="py-2 px-3">Estado</th>
|
||||||
|
<th class="py-2 px-3">Borrador</th>
|
||||||
<th class="py-2 px-3">Privacidad</th>
|
<th class="py-2 px-3">Privacidad</th>
|
||||||
|
<th class="py-2 px-3">País / Ciudad</th>
|
||||||
|
<th class="py-2 px-3">Creada</th>
|
||||||
<th class="py-2 px-3 text-right">Acciones</th>
|
<th class="py-2 px-3 text-right">Acciones</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<template x-for="v in items" :key="v.id || v._id">
|
<template x-for="v in items" :key="v.id || v._id">
|
||||||
<tr class="hover:bg-gray-50 border-b border-gray-100">
|
<tr class="hover:bg-gray-50 border-b border-gray-100">
|
||||||
<td class="py-2 px-3 font-medium" x-text="v.nombre || '—'"></td>
|
<td class="py-2 px-3">
|
||||||
<td class="py-2 px-3 text-xs text-gray-500" x-text="(v.user && v.user.email) ? v.user.email : (v.user_id || '—')"></td>
|
<div class="font-medium" x-text="v.nombre || '—'"></div>
|
||||||
<td class="py-2 px-3 text-gray-500" x-text="v.empresa || '—'"></td>
|
<div class="text-xs text-gray-400" x-text="v.cargo || ''"></div>
|
||||||
<td class="py-2 px-3 text-gray-500" x-text="v.email || '—'"></td>
|
</td>
|
||||||
|
<td class="py-2 px-3 text-xs text-gray-500">
|
||||||
|
<div x-text="(v.user && v.user.name) ? v.user.name : '—'"></div>
|
||||||
|
<div class="text-gray-400" x-text="(v.user && v.user.email) ? v.user.email : (v.user_id || '')"></div>
|
||||||
|
</td>
|
||||||
|
<td class="py-2 px-3 text-gray-500 text-xs" x-text="v.empresa || '—'"></td>
|
||||||
|
<td class="py-2 px-3 text-gray-500 text-xs" x-text="v.email || '—'"></td>
|
||||||
|
<td class="py-2 px-3 text-xs">
|
||||||
|
<a :href="v.url || ('https://vcard.u-site.app/' + v.unico)" target="_blank"
|
||||||
|
x-show="v.unico || v.url"
|
||||||
|
class="text-blue-500 hover:underline font-mono" x-text="v.unico || '—'"></a>
|
||||||
|
<span x-show="!v.unico && !v.url" class="text-gray-400">—</span>
|
||||||
|
</td>
|
||||||
<td class="py-2 px-3">
|
<td class="py-2 px-3">
|
||||||
<span :class="v.estado ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'"
|
<span :class="v.estado ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'"
|
||||||
class="text-xs px-2 py-0.5 rounded-full" x-text="v.estado ? 'Activa' : 'Inactiva'"></span>
|
class="text-xs px-2 py-0.5 rounded-full" x-text="v.estado ? 'Activa' : 'Inactiva'"></span>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="py-2 px-3">
|
||||||
|
<span x-show="v.es_borrador" class="text-xs px-2 py-0.5 rounded-full bg-yellow-100 text-yellow-700">Borrador</span>
|
||||||
|
<span x-show="!v.es_borrador" class="text-xs text-gray-300">—</span>
|
||||||
|
</td>
|
||||||
<td class="py-2 px-3">
|
<td class="py-2 px-3">
|
||||||
<span :class="v.privacidad === 'publica' ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 text-gray-600'"
|
<span :class="v.privacidad === 'publica' ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 text-gray-600'"
|
||||||
class="text-xs px-2 py-0.5 rounded-full" x-text="v.privacidad || '—'"></span>
|
class="text-xs px-2 py-0.5 rounded-full" x-text="v.privacidad || '—'"></span>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="py-2 px-3 text-xs text-gray-500">
|
||||||
|
<div x-text="v.pais || '—'"></div>
|
||||||
|
<div class="text-gray-400" x-text="v.ciudad || ''"></div>
|
||||||
|
</td>
|
||||||
|
<td class="py-2 px-3 text-xs text-gray-400" x-text="v.created_at ? v.created_at.substring(0,10) : '—'"></td>
|
||||||
<td class="py-2 px-3 text-right">
|
<td class="py-2 px-3 text-right">
|
||||||
<button @click="openEditVcardModal(v)"
|
<button @click="openEditVcardModal(v)"
|
||||||
class="text-gray-600 hover:text-gray-800 text-xs px-2 py-1 border border-gray-300 rounded">Editar</button>
|
class="text-gray-600 hover:text-gray-800 text-xs px-2 py-1 border border-gray-300 rounded">Editar</button>
|
||||||
@@ -753,90 +778,217 @@
|
|||||||
|
|
||||||
<!-- ─── Modal: Editar VCard ───────────────────────────────────────────── -->
|
<!-- ─── Modal: Editar VCard ───────────────────────────────────────────── -->
|
||||||
<div x-show="editVcardModal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm" style="display:none">
|
<div x-show="editVcardModal" class="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm" style="display:none">
|
||||||
<div class="bg-white rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto">
|
<div class="bg-white rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] flex flex-col">
|
||||||
<div class="flex justify-between items-center p-5 border-b sticky top-0 bg-white z-10">
|
<div class="flex justify-between items-center p-5 border-b shrink-0">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-lg font-semibold">Editar VCard</h2>
|
<h2 class="text-lg font-semibold">Editar VCard</h2>
|
||||||
<p class="text-xs text-gray-500 mt-0.5" x-text="editVcardData ? (editVcardData.nombre || '') : ''"></p>
|
<p class="text-xs text-gray-500 mt-0.5" x-text="editVcardData ? (editVcardData.nombre || '') : ''"></p>
|
||||||
</div>
|
</div>
|
||||||
<button @click="editVcardModal = false" class="text-gray-400 hover:text-gray-600 text-xl">✕</button>
|
<button @click="editVcardModal = false" class="text-gray-400 hover:text-gray-600 text-xl">✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-5 grid grid-cols-1 sm:grid-cols-2 gap-4">
|
<!-- Tabs del modal -->
|
||||||
<div>
|
<div class="border-b px-5 flex gap-1 shrink-0 overflow-x-auto">
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Nombre</label>
|
<template x-for="vt in ['datos','redes','apariencia']" :key="vt">
|
||||||
<input x-model="editVcardForm.nombre" type="text"
|
<button @click="editVcardTab = vt"
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
:class="editVcardTab === vt ? 'border-b-2 border-[#8eb02f] text-[#6d8c24] font-semibold' : 'text-gray-500 hover:text-gray-700'"
|
||||||
</div>
|
class="text-xs py-2 px-3 whitespace-nowrap capitalize" x-text="vt.charAt(0).toUpperCase()+vt.slice(1)"></button>
|
||||||
<div>
|
</template>
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Cargo</label>
|
|
||||||
<input x-model="editVcardForm.cargo" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div class="sm:col-span-2">
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Descripción</label>
|
|
||||||
<textarea x-model="editVcardForm.descripcion" rows="2"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]"></textarea>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Teléfono</label>
|
|
||||||
<input x-model="editVcardForm.telefono" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">WhatsApp</label>
|
|
||||||
<input x-model="editVcardForm.whatsapp" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Email</label>
|
|
||||||
<input x-model="editVcardForm.email" type="email"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Empresa</label>
|
|
||||||
<input x-model="editVcardForm.empresa" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div class="sm:col-span-2">
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Dirección</label>
|
|
||||||
<input x-model="editVcardForm.direccion" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Website</label>
|
|
||||||
<input x-model="editVcardForm.website" type="url"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">País</label>
|
|
||||||
<input x-model="editVcardForm.pais" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Ciudad</label>
|
|
||||||
<input x-model="editVcardForm.ciudad" type="text"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Privacidad</label>
|
|
||||||
<select x-model="editVcardForm.privacidad"
|
|
||||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
|
||||||
<option value="publica">Pública</option>
|
|
||||||
<option value="privada">Privada</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-4 sm:col-span-2">
|
|
||||||
<label class="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
|
|
||||||
<input x-model="editVcardForm.estado" type="checkbox" class="rounded" /> Activa
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
|
|
||||||
<input x-model="editVcardForm.es_borrador" type="checkbox" class="rounded" /> Borrador
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div x-show="editVcardError" class="sm:col-span-2 p-3 bg-red-50 border border-red-200 rounded text-sm text-red-600" x-text="editVcardError"></div>
|
|
||||||
<div x-show="editVcardSuccess" class="sm:col-span-2 p-3 bg-green-50 border border-green-200 rounded text-sm text-green-700">✓ VCard actualizada correctamente.</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end gap-3 px-5 pb-5">
|
<div class="overflow-y-auto flex-1 p-5">
|
||||||
|
<!-- Tab Datos -->
|
||||||
|
<div x-show="editVcardTab === 'datos'" class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Nombre</label>
|
||||||
|
<input x-model="editVcardForm.nombre" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Cargo</label>
|
||||||
|
<input x-model="editVcardForm.cargo" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Descripción</label>
|
||||||
|
<textarea x-model="editVcardForm.descripcion" rows="2" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]"></textarea>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Teléfono</label>
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<input x-model="editVcardForm.consecutivo_telefono" type="text" placeholder="+57" class="w-16 border border-gray-300 rounded-lg px-2 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
<input x-model="editVcardForm.telefono" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">WhatsApp</label>
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<input x-model="editVcardForm.consecutivo_whatsapp" type="text" placeholder="+57" class="w-16 border border-gray-300 rounded-lg px-2 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
<input x-model="editVcardForm.whatsapp" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Email</label>
|
||||||
|
<input x-model="editVcardForm.email" type="email" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Empresa</label>
|
||||||
|
<input x-model="editVcardForm.empresa" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Dirección</label>
|
||||||
|
<input x-model="editVcardForm.direccion" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Website</label>
|
||||||
|
<input x-model="editVcardForm.website" type="url" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">País</label>
|
||||||
|
<input x-model="editVcardForm.pais" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Ciudad</label>
|
||||||
|
<input x-model="editVcardForm.ciudad" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Foto perfil (URL)</label>
|
||||||
|
<input x-model="editVcardForm.foto_perfil" type="url" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Logo (URL)</label>
|
||||||
|
<input x-model="editVcardForm.logo" type="url" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Privacidad</label>
|
||||||
|
<select x-model="editVcardForm.privacidad" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||||
|
<option value="publica">Pública</option>
|
||||||
|
<option value="privada">Privada</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Texto botón</label>
|
||||||
|
<input x-model="editVcardForm.boton" type="text" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4 sm:col-span-2 pt-1">
|
||||||
|
<label class="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
|
||||||
|
<input x-model="editVcardForm.estado" type="checkbox" class="rounded" /> Activa
|
||||||
|
</label>
|
||||||
|
<label class="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
|
||||||
|
<input x-model="editVcardForm.es_borrador" type="checkbox" class="rounded" /> Borrador
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab Redes Sociales -->
|
||||||
|
<div x-show="editVcardTab === 'redes'" class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
|
<template x-for="red in [
|
||||||
|
{key:'linkedin', label:'LinkedIn'},
|
||||||
|
{key:'twitter', label:'Twitter / X'},
|
||||||
|
{key:'facebook', label:'Facebook'},
|
||||||
|
{key:'instagram', label:'Instagram'},
|
||||||
|
{key:'tiktok', label:'TikTok'},
|
||||||
|
{key:'github', label:'GitHub'},
|
||||||
|
{key:'behance', label:'Behance'},
|
||||||
|
{key:'youtube', label:'YouTube'},
|
||||||
|
{key:'youtube_channel', label:'Canal YouTube'},
|
||||||
|
{key:'telegram', label:'Telegram'},
|
||||||
|
{key:'messenger', label:'Messenger'},
|
||||||
|
{key:'wechat', label:'WeChat'},
|
||||||
|
{key:'signal', label:'Signal'},
|
||||||
|
{key:'line', label:'Line'}
|
||||||
|
]" :key="red.key">
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1" x-text="red.label"></label>
|
||||||
|
<div class="flex gap-1" x-show="red.key === 'signal'">
|
||||||
|
<input x-model="editVcardForm.consecutivo_signal" type="text" placeholder="+57" class="w-16 border border-gray-300 rounded-lg px-2 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
<input x-model="editVcardForm[red.key]" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
<input x-show="red.key !== 'signal'" x-model="editVcardForm[red.key]" type="text"
|
||||||
|
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab Apariencia -->
|
||||||
|
<div x-show="editVcardTab === 'apariencia'" class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Color cabecera</label>
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<input x-model="editVcardForm.cabecera" type="color" class="h-9 w-12 border border-gray-300 rounded cursor-pointer" />
|
||||||
|
<input x-model="editVcardForm.cabecera" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Color fondo</label>
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<input x-model="editVcardForm.fondo" type="color" class="h-9 w-12 border border-gray-300 rounded cursor-pointer" />
|
||||||
|
<input x-model="editVcardForm.fondo" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Color cuerpo</label>
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<input x-model="editVcardForm.color_cuerpo" type="color" class="h-9 w-12 border border-gray-300 rounded cursor-pointer" />
|
||||||
|
<input x-model="editVcardForm.color_cuerpo" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Color iconos</label>
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<input x-model="editVcardForm.color_iconos" type="color" class="h-9 w-12 border border-gray-300 rounded cursor-pointer" />
|
||||||
|
<input x-model="editVcardForm.color_iconos" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Color info</label>
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
<input x-model="editVcardForm.color_info" type="color" class="h-9 w-12 border border-gray-300 rounded cursor-pointer" />
|
||||||
|
<input x-model="editVcardForm.color_info" type="text" class="flex-1 border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Fuente</label>
|
||||||
|
<select x-model="editVcardForm.fuente" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||||
|
<option value="Inter">Inter</option>
|
||||||
|
<option value="Roboto">Roboto</option>
|
||||||
|
<option value="Montserrat">Montserrat</option>
|
||||||
|
<option value="Poppins">Poppins</option>
|
||||||
|
<option value="Lato">Lato</option>
|
||||||
|
<option value="Open Sans">Open Sans</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Bordes</label>
|
||||||
|
<select x-model="editVcardForm.bordes" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||||
|
<option value="rounded-full">Circular</option>
|
||||||
|
<option value="rounded-lg">Redondeado</option>
|
||||||
|
<option value="rounded-none">Recto</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Estilo VCard</label>
|
||||||
|
<select x-model="editVcardForm.estilo_vcard" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||||
|
<option :value="1">Estilo 1</option>
|
||||||
|
<option :value="2">Estilo 2</option>
|
||||||
|
<option :value="3">Estilo 3</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Orden iconos</label>
|
||||||
|
<select x-model="editVcardForm.orden_iconos" class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||||
|
<option value="top">Arriba</option>
|
||||||
|
<option value="bottom">Abajo</option>
|
||||||
|
<option value="left">Izquierda</option>
|
||||||
|
<option value="right">Derecha</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Animación</label>
|
||||||
|
<input x-model="editVcardForm.animacion" type="text" placeholder="ej: fade, slide..." class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div x-show="editVcardError" class="mt-4 p-3 bg-red-50 border border-red-200 rounded text-sm text-red-600" x-text="editVcardError"></div>
|
||||||
|
<div x-show="editVcardSuccess" class="mt-4 p-3 bg-green-50 border border-green-200 rounded text-sm text-green-700">✓ VCard actualizada correctamente.</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end gap-3 px-5 py-4 border-t shrink-0">
|
||||||
<button @click="editVcardModal = false" class="px-4 py-2 text-sm border rounded-lg hover:bg-gray-50">Cancelar</button>
|
<button @click="editVcardModal = false" class="px-4 py-2 text-sm border rounded-lg hover:bg-gray-50">Cancelar</button>
|
||||||
<button @click="saveEditVcard()" :disabled="saving"
|
<button @click="saveEditVcard()" :disabled="saving"
|
||||||
class="px-4 py-2 text-sm text-white rounded-lg disabled:opacity-50"
|
class="px-4 py-2 text-sm text-white rounded-lg disabled:opacity-50"
|
||||||
@@ -959,8 +1111,21 @@ function vcardApiApp() {
|
|||||||
|
|
||||||
// Modal editar vcard
|
// Modal editar vcard
|
||||||
editVcardModal: false,
|
editVcardModal: false,
|
||||||
|
editVcardTab: 'datos',
|
||||||
editVcardData: null,
|
editVcardData: null,
|
||||||
editVcardForm: { nombre: '', cargo: '', descripcion: '', telefono: '', whatsapp: '', email: '', empresa: '', direccion: '', website: '', pais: '', ciudad: '', estado: true, privacidad: 'publica', es_borrador: false },
|
editVcardForm: {
|
||||||
|
nombre: '', cargo: '', descripcion: '', telefono: '', consecutivo_telefono: '',
|
||||||
|
whatsapp: '', consecutivo_whatsapp: '', email: '', empresa: '', direccion: '',
|
||||||
|
website: '', pais: '', ciudad: '', foto_perfil: '', logo: '',
|
||||||
|
privacidad: 'publica', boton: '', estado: true, es_borrador: false,
|
||||||
|
linkedin: '', twitter: '', facebook: '', instagram: '', tiktok: '',
|
||||||
|
github: '', behance: '', youtube: '', youtube_channel: '',
|
||||||
|
telegram: '', messenger: '', wechat: '', signal: '', consecutivo_signal: '', line: '',
|
||||||
|
cabecera: '#E8E8E8', fondo: '#2B2D35', color_cuerpo: '#FFFFFF',
|
||||||
|
color_iconos: '#2B2D35', color_info: '#2B2D35',
|
||||||
|
fuente: 'Inter', bordes: 'rounded-full', estilo_vcard: 1,
|
||||||
|
orden_iconos: 'top', animacion: '',
|
||||||
|
},
|
||||||
editVcardError: '',
|
editVcardError: '',
|
||||||
editVcardSuccess: false,
|
editVcardSuccess: false,
|
||||||
|
|
||||||
@@ -1213,21 +1378,52 @@ function vcardApiApp() {
|
|||||||
|
|
||||||
openEditVcardModal(v) {
|
openEditVcardModal(v) {
|
||||||
this.editVcardData = v;
|
this.editVcardData = v;
|
||||||
|
this.editVcardTab = 'datos';
|
||||||
this.editVcardForm = {
|
this.editVcardForm = {
|
||||||
nombre: v.nombre || '',
|
nombre: v.nombre || '',
|
||||||
cargo: v.cargo || '',
|
cargo: v.cargo || '',
|
||||||
descripcion: v.descripcion || '',
|
descripcion: v.descripcion || '',
|
||||||
telefono: v.telefono || '',
|
telefono: v.telefono || '',
|
||||||
whatsapp: v.whatsapp || '',
|
consecutivo_telefono: v.consecutivo_telefono || '',
|
||||||
email: v.email || '',
|
whatsapp: v.whatsapp || '',
|
||||||
empresa: v.empresa || '',
|
consecutivo_whatsapp: v.consecutivo_whatsapp || '',
|
||||||
direccion: v.direccion || '',
|
email: v.email || '',
|
||||||
website: v.website || '',
|
empresa: v.empresa || '',
|
||||||
pais: v.pais || '',
|
direccion: v.direccion || '',
|
||||||
ciudad: v.ciudad || '',
|
website: v.website || '',
|
||||||
estado: !!v.estado,
|
pais: v.pais || '',
|
||||||
privacidad: v.privacidad || 'publica',
|
ciudad: v.ciudad || '',
|
||||||
es_borrador: !!v.es_borrador,
|
foto_perfil: v.foto_perfil || '',
|
||||||
|
logo: v.logo || '',
|
||||||
|
privacidad: v.privacidad || 'publica',
|
||||||
|
boton: v.boton || '',
|
||||||
|
estado: !!v.estado,
|
||||||
|
es_borrador: !!v.es_borrador,
|
||||||
|
linkedin: v.linkedin || '',
|
||||||
|
twitter: v.twitter || '',
|
||||||
|
facebook: v.facebook || '',
|
||||||
|
instagram: v.instagram || '',
|
||||||
|
tiktok: v.tiktok || '',
|
||||||
|
github: v.github || '',
|
||||||
|
behance: v.behance || '',
|
||||||
|
youtube: v.youtube || '',
|
||||||
|
youtube_channel: v.youtube_channel || '',
|
||||||
|
telegram: v.telegram || '',
|
||||||
|
messenger: v.messenger || '',
|
||||||
|
wechat: v.wechat || '',
|
||||||
|
signal: v.signal || '',
|
||||||
|
consecutivo_signal: v.consecutivo_signal || '',
|
||||||
|
line: v.line || '',
|
||||||
|
cabecera: v.cabecera || '#E8E8E8',
|
||||||
|
fondo: v.fondo || '#2B2D35',
|
||||||
|
color_cuerpo: v.color_cuerpo || '#FFFFFF',
|
||||||
|
color_iconos: v.color_iconos || '#2B2D35',
|
||||||
|
color_info: v.color_info || '#2B2D35',
|
||||||
|
fuente: v.fuente || 'Inter',
|
||||||
|
bordes: v.bordes || 'rounded-full',
|
||||||
|
estilo_vcard: v.estilo_vcard || 1,
|
||||||
|
orden_iconos: v.orden_iconos || 'top',
|
||||||
|
animacion: v.animacion || '',
|
||||||
};
|
};
|
||||||
this.editVcardError = '';
|
this.editVcardError = '';
|
||||||
this.editVcardSuccess = false;
|
this.editVcardSuccess = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user