385 lines
17 KiB
PHP
385 lines
17 KiB
PHP
|
|
<x-layouts.app title="{{ (isset($user) && $user->id) ? __('Edit User') : __('Create User') }}" :showSidebar={{ $showSidebar }}>
|
|
|
|
<!-- Header -->
|
|
<div class="mb-8">
|
|
<div class="flex items-center gap-4 mb-4">
|
|
<flux:icon.user class="size-10" variant="solid"/>
|
|
<h1 class="text-3xl font-bold text-gray-800">
|
|
{{ (isset($user) && $user->id) ? 'Editar Usuario' : 'Nuevo Usuario' }}
|
|
</h1>
|
|
</div>
|
|
<p class="text-gray-600 text-sm">
|
|
@if(isset($user) && $user->id)
|
|
Modifique los campos necesarios para actualizar la información del usuario.
|
|
@else
|
|
Complete todos los campos obligatorios para registrar un nuevo usuario en el sistema.
|
|
@endisset
|
|
</p>
|
|
</div>
|
|
|
|
|
|
@if(session('error'))
|
|
<div id="error-message" class="mb-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded">
|
|
{{ session('error') }}
|
|
</div>
|
|
@endif
|
|
|
|
@if($errors->any())
|
|
<div class="mb-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded">
|
|
<ul>
|
|
@foreach($errors->all() as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
|
|
<form method="POST" action="{{ (isset($user) && $user->id) ? route('users.update', $user) : route('users.store') }}">
|
|
@csrf
|
|
@if(isset($user) && $user->id)
|
|
@method('PUT')
|
|
@endif
|
|
|
|
<!-- Separador -->
|
|
<div class="relative">
|
|
<div class="absolute inset-0 flex items-center">
|
|
<div class="w-full border-t border-gray-300"></div>
|
|
</div>
|
|
<div class="relative flex justify-center">
|
|
<span class="px-4 bg-white text-sm text-gray-500">Datos Personales</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Datos Personales -->
|
|
<div class="bg-white py-6">
|
|
<table class="w-full">
|
|
<tbody class="space-y-4">
|
|
<!-- Título de cortesía -->
|
|
<tr>
|
|
<td class="py-2 pr-4 w-1/3">
|
|
<label class="block text-sm font-medium text-gray-700">
|
|
Título de cortesía
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<select name="title" class="w-[150px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
<option value="">Seleccionar...</option>
|
|
<option value="Sr.">Sr.</option>
|
|
<option value="Sra.">Sra.</option>
|
|
<option value="Dr.">Dr.</option>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Nombre -->
|
|
<tr>
|
|
<td class="py-2 pr-4">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Nombre
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<input type="text" name="first_name" required
|
|
value="{{ old('first_name', $user->first_name ?? '') }}"
|
|
class="w-[250px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none"
|
|
autofocus>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Apellidos -->
|
|
<tr>
|
|
<td class="py-2 pr-4">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Apellidos
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<input type="text" name="last_name" required
|
|
value="{{ old('last_name', $user->last_name ?? '') }}"
|
|
class="w-[250px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Nombre de Login -->
|
|
<tr>
|
|
<td class="py-2 pr-4">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Nombre de Login
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<input type="text" name="username" required
|
|
value="{{ old('username', $user->username ?? '') }}"
|
|
class="w-[250px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Separador -->
|
|
<div class="relative">
|
|
<div class="absolute inset-0 flex items-center">
|
|
<div class="w-full border-t border-gray-300"></div>
|
|
</div>
|
|
<div class="relative flex justify-center">
|
|
<span class="px-4 bg-white text-sm text-gray-500">Configuración de acceso</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Configuración de Acceso -->
|
|
<div class="bg-white py-6">
|
|
<table class="w-full">
|
|
<tbody>
|
|
<!-- Intervalo de fechas -->
|
|
<tr>
|
|
<td class="py-2 pr-4 w-1/3">
|
|
<label class="block text-sm font-medium text-gray-700">
|
|
Validez de acceso
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex gap-4">
|
|
de
|
|
<input type="date" name="start_date"
|
|
value="{{ old('start_date', isset($user->access_start) ? $user->access_start->format('Y-m-d') : '') }}"
|
|
class="w-[150px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
a
|
|
<input type="date" name="end_date"
|
|
value="{{ old('end_date', isset($user->access_end) ? $user->access_end->format('Y-m-d') : '') }}"
|
|
class="w-[150px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Contraseña -->
|
|
<tr>
|
|
<td class="py-2 pr-4">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Contraseña
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex gap-2">
|
|
<input type="text" name="password" id="password"
|
|
{{ !isset($user) ? 'required' : '' }}
|
|
class="w-[250px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
<button type="button" onclick="generatePassword()"
|
|
class="px-2 py-1 bg-blue-100 text-blue-700 rounded-md hover:bg-blue-200 flex items-center gap-2">
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
|
<path fill-rule="evenodd" d="M18 8a6 6 0 01-7.743 5.743L10 14l-1 1-1 1H6v2H2v-4l4.257-4.257A6 6 0 1118 8zm-6-4a1 1 0 100 2 2 2 0 012 2 1 1 0 102 0 4 4 0 00-4-4z" clip-rule="evenodd" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Separador -->
|
|
<div class="relative">
|
|
<div class="absolute inset-0 flex items-center">
|
|
<div class="w-full border-t border-gray-300"></div>
|
|
</div>
|
|
<div class="relative flex justify-center">
|
|
<span class="px-4 bg-white text-sm text-gray-500">Datos de contacto</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Datos de Contacto -->
|
|
<div class="bg-white py-6">
|
|
<table class="w-full">
|
|
<tbody>
|
|
<tr>
|
|
<td class="py-2 pr-4 w-1/3">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Email
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex items-center gap-2">
|
|
<flux:icon.envelope class="w-5 h-5"/>
|
|
<input type="email" name="email" required
|
|
value="{{ old('email', $user->email ?? '') }}"
|
|
class="w-[300px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="py-2 pr-4">
|
|
<label class="block text-sm font-medium text-gray-700">
|
|
Teléfono
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex items-center gap-2">
|
|
<flux:icon.phone class="w-5 h-5"/>
|
|
<input type="tel" name="phone"
|
|
value="{{ old('phone', $user->phone ?? '') }}"
|
|
class="w-[250px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="py-2 pr-4 align-top">
|
|
<label class="block text-sm font-medium text-gray-700">
|
|
Dirección
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex items-start gap-2">
|
|
<flux:icon.map-pin class="w-5 h-5"/>
|
|
<textarea name="address" rows="3"
|
|
class="w-full border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">{{ old('address', $user->address ?? '') }}</textarea>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Separador -->
|
|
<div class="relative">
|
|
<div class="absolute inset-0 flex items-center">
|
|
<div class="w-full border-t border-gray-300"></div>
|
|
</div>
|
|
<div class="relative flex justify-center">
|
|
<span class="px-4 bg-white text-sm text-gray-500">Otros datos</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Datos de Contacto -->
|
|
<div class="bg-white py-6">
|
|
<table class="w-full">
|
|
<tbody>
|
|
<!-- tipo de usuario -->
|
|
<tr>
|
|
<td class="py-2 pr-4 w-1/3">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Tipo de usuario
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex items-center gap-2">
|
|
<select name="user_type" class="w-[200px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
<option value="0">Interno</option>
|
|
<option value="1">Externo</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Estado -->
|
|
<tr>
|
|
<td class="py-2 pr-4 w-1/3">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Estado
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="flex items-center gap-2">
|
|
<select name="is_active" class="w-[200px] border-b-1 border-gray-300 focus:border-blue-500 focus:outline-none">
|
|
<option value="Activo">Activo</option>
|
|
<option value="Inactivo">Inactivo</option>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- Foto -->
|
|
<tr>
|
|
<td class="py-2 pr-4">
|
|
<label class="block text-sm font-bold text-gray-700">
|
|
Foto
|
|
</label>
|
|
</td>
|
|
<td class="py-2">
|
|
<div class="mb-6">
|
|
@livewire('image-uploader', [
|
|
'fieldName' => 'image_path', // Nombre del campo en la BD
|
|
'label' => 'Imagen principal' // Etiqueta personalizada
|
|
])
|
|
<!-- Campo oculto para la ruta de la imagen -->
|
|
<input type="hidden" name="profile_photo_path" id="profilePhotoPathInput" value="{{ old('profile_photo_path', optional($user)->profile_photo_path ?? '') }}">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Botón de envío -->
|
|
<div class="text-right">
|
|
<button type="submit"
|
|
class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors">
|
|
{{ (isset($user) && $user->id) ? 'Actualizar Usuario' : 'Crear Usuario' }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
|
|
<script>
|
|
// Escuchar el evento de Livewire y actualizar el campo oculto
|
|
document.addEventListener('imageUploaded', (event) => {
|
|
document.getElementById('profilePhotoPathInput').value = event.detail.path;
|
|
});
|
|
|
|
document.addEventListener('imageRemoved', (event) => {
|
|
document.getElementById('profilePhotoPathInput').value = '';
|
|
});
|
|
|
|
function generatePassword() {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';
|
|
let password = '';
|
|
for (let i = 0; i < 12; i++) {
|
|
password += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
document.getElementById('password').value = password;
|
|
}
|
|
|
|
/*
|
|
<div class="mt-2 flex items-center gap-2">
|
|
<input type="checkbox" onclick="togglePasswordVisibility()">
|
|
<span class="text-sm text-gray-500">Mostrar contraseña</span>
|
|
</div>
|
|
|
|
function togglePasswordVisibility() {
|
|
const passwordField = document.getElementById('password');
|
|
passwordField.type = passwordField.type === 'password' ? 'text' : 'password';
|
|
}
|
|
*/
|
|
</script>
|
|
|
|
<!-- Sidebar menu -->
|
|
@push('sidebar-menu')
|
|
<flux:navlist variant="outline">
|
|
<!-- Sección de Usuarios -->
|
|
<flux:navlist.group :heading="__('User')">
|
|
<flux:navlist.item
|
|
icon="users"
|
|
:href="route('users.index')"
|
|
wire:navigate
|
|
>
|
|
{{ __('List Users') }}
|
|
</flux:navlist.item>
|
|
|
|
<flux:navlist.item
|
|
icon="user-plus"
|
|
:href="route('users.create')"
|
|
wire:navigate
|
|
>
|
|
{{ __('Create User') }}
|
|
</flux:navlist.item>
|
|
</flux:navlist.group>
|
|
|
|
<flux:separator />
|
|
</flux:navlist>
|
|
|
|
@endpush
|
|
|
|
</x-layouts.app> |