feat: i18n, language switcher fix, DataTable improvements, blade translations
- Translation system: lang/es/ PHP files (auth, validation, pagination, passwords)
- Rappasoft vendor translations published (lang/vendor/livewire-tables/es/)
- JSON files synced to 391 keys (EN + ES, full parity)
- APP_LOCALE changed to 'es', users.locale column default changed to 'es'
- Language switcher fixed: JS event + window.location.reload() avoids /livewire/update redirect
- SetLocale middleware fallback uses config('app.locale') instead of hardcoded 'en'
- setSortingPillsEnabled(false) on ProjectTable, CompanyTable, UserTable
- Translated 17 blade views: project-map, template-manager, layer-manager,
company-management, phase-list, media-manager, reports-dashboard,
client-projects, layer-upload, project-form, project-map-editor-tab,
admin/users, projects/media, projects/templates, layouts/client
- Navigation 'Empresas' link uses __('Companies')
- Fixed typo key 'Fases and layers' -> 'Phases and layers'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
<div>
|
||||
<x-slot name="header">
|
||||
<div class="flex items-center gap-3">
|
||||
<a href="{{ route('companies.manage') }}" class="btn btn-ghost btn-sm px-2" wire:navigate>
|
||||
<x-heroicon-o-arrow-left class="w-4 h-4" />
|
||||
</a>
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ $company ? 'Editar empresa: ' . $company->name : 'Nueva empresa' }}
|
||||
</h2>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-8">
|
||||
<div class="max-w-3xl mx-auto sm:px-6 lg:px-8">
|
||||
|
||||
@if(session('notify'))
|
||||
<div class="alert alert-success mb-4">{{ session('notify') }}</div>
|
||||
@endif
|
||||
|
||||
<div class="card bg-base-100 shadow">
|
||||
<div class="card-body p-8">
|
||||
|
||||
<form wire:submit.prevent="save" class="space-y-0">
|
||||
|
||||
@if($errors->any())
|
||||
<div class="alert alert-error text-sm mb-6">
|
||||
<x-heroicon-o-exclamation-circle class="w-5 h-5 shrink-0" />
|
||||
<ul class="list-disc pl-3 space-y-0.5">
|
||||
@foreach($errors->all() as $e) <li>{{ $e }}</li> @endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- ── Macro para fila de formulario horizontal ──────────── --}}
|
||||
{{-- Patrón: flex row, label w-48 shrink-0, campo flex-1 --}}
|
||||
|
||||
{{-- ── Sección: Identificación ──────────────────────────── --}}
|
||||
<div class="pb-6 mb-6 border-b border-base-200">
|
||||
<h3 class="text-xs font-semibold text-gray-400 uppercase tracking-widest mb-4">
|
||||
Identificación
|
||||
</h3>
|
||||
<div class="space-y-4">
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Nombre registrado <span class="text-error">*</span>
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<input type="text" wire:model="name"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Constructora Ejemplo, S.L." />
|
||||
@error('name') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Apodo / comercial
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<input type="text" wire:model="apodo"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Ejemplo Constr." />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
NIF / CIF / Tax ID
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<input type="text" wire:model="tax_id"
|
||||
class="input input-bordered w-full"
|
||||
placeholder="B12345678" />
|
||||
@error('tax_id') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Tipo de empresa <span class="text-error">*</span>
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<select wire:model="type" class="select select-bordered w-full">
|
||||
<option value="owner">Promotor / Propietario</option>
|
||||
<option value="constructor">Constructor principal</option>
|
||||
<option value="subcontractor">Subcontratista</option>
|
||||
<option value="consultant">Consultor / Ingeniería</option>
|
||||
<option value="supplier">Proveedor</option>
|
||||
<option value="other">Otro</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Estado <span class="text-error">*</span>
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<select wire:model="estado" class="select select-bordered w-full max-w-xs">
|
||||
<option value="activo">Activo</option>
|
||||
<option value="inactivo">Inactivo</option>
|
||||
<option value="suspendido">Suspendido</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ── Sección: Contacto ─────────────────────────────────── --}}
|
||||
<div class="pb-6 mb-6 border-b border-base-200">
|
||||
<h3 class="text-xs font-semibold text-gray-400 uppercase tracking-widest mb-4">
|
||||
Contacto
|
||||
</h3>
|
||||
<div class="space-y-4">
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Dirección
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<textarea wire:model="address" rows="2"
|
||||
class="textarea textarea-bordered w-full"
|
||||
placeholder="Calle, número, ciudad, CP, país"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Teléfono
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<x-heroicon-o-phone class="w-4 h-4 opacity-40 shrink-0" />
|
||||
<input type="tel" wire:model="phone" class="grow"
|
||||
placeholder="+34 600 123 456" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Email
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<x-heroicon-o-envelope class="w-4 h-4 opacity-40 shrink-0" />
|
||||
<input type="email" wire:model="email" class="grow"
|
||||
placeholder="contacto@empresa.com" />
|
||||
</label>
|
||||
@error('email') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Sitio web
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<label class="input input-bordered flex items-center gap-2">
|
||||
<x-heroicon-o-globe-alt class="w-4 h-4 opacity-40 shrink-0" />
|
||||
<input type="url" wire:model="website" class="grow"
|
||||
placeholder="https://www.empresa.com" />
|
||||
</label>
|
||||
@error('website') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ── Sección: Logo ─────────────────────────────────────── --}}
|
||||
<div class="pb-6 mb-6 border-b border-base-200">
|
||||
<h3 class="text-xs font-semibold text-gray-400 uppercase tracking-widest mb-4">
|
||||
Logo
|
||||
</h3>
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
{{ $company?->logo_path ? 'Reemplazar logo' : 'Subir logo' }}
|
||||
<p class="text-xs text-gray-400 font-normal mt-0.5">PNG / JPG, máx. 2 MB</p>
|
||||
</label>
|
||||
<div class="flex-1 flex items-start gap-4">
|
||||
{{-- Preview --}}
|
||||
@if($logo)
|
||||
<img src="{{ $logo->temporaryUrl() }}" alt="Preview"
|
||||
class="w-16 h-16 object-contain border border-base-300 rounded-lg shrink-0" />
|
||||
@elseif($company?->logo_path && \Illuminate\Support\Facades\Storage::disk('public')->exists($company->logo_path))
|
||||
<img src="{{ \Illuminate\Support\Facades\Storage::disk('public')->url($company->logo_path) }}"
|
||||
alt="Logo actual"
|
||||
class="w-16 h-16 object-contain border border-base-300 rounded-lg shrink-0" />
|
||||
@else
|
||||
<div class="w-16 h-16 bg-base-200 rounded-lg flex items-center justify-center shrink-0">
|
||||
<x-heroicon-o-building-office class="w-7 h-7 opacity-30" />
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex-1">
|
||||
<input type="file" wire:model="logo" accept="image/*"
|
||||
class="file-input file-input-bordered w-full" />
|
||||
<div wire:loading wire:target="logo" class="text-xs text-info mt-1">Subiendo…</div>
|
||||
@error('logo') <p class="text-error text-xs mt-1">{{ $message }}</p> @enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ── Sección: Notas ────────────────────────────────────── --}}
|
||||
<div class="pb-6 mb-6 border-b border-base-200">
|
||||
<h3 class="text-xs font-semibold text-gray-400 uppercase tracking-widest mb-4">
|
||||
Notas internas
|
||||
</h3>
|
||||
<div class="flex items-start gap-4">
|
||||
<label class="w-48 shrink-0 pt-2 text-sm font-medium text-gray-700">
|
||||
Observaciones
|
||||
<p class="text-xs text-gray-400 font-normal mt-0.5">Información interna</p>
|
||||
</label>
|
||||
<div class="flex-1">
|
||||
<textarea wire:model="notes" rows="3"
|
||||
class="textarea textarea-bordered w-full"
|
||||
placeholder="Condiciones especiales, observaciones…"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ── Botones ───────────────────────────────────────────── --}}
|
||||
<div class="flex items-center justify-between pt-2">
|
||||
<a href="{{ route('companies.manage') }}" class="btn btn-outline gap-1" wire:navigate>
|
||||
<x-heroicon-o-x-mark class="w-4 h-4" />
|
||||
Cancelar
|
||||
</a>
|
||||
<button type="submit" class="btn btn-primary gap-2"
|
||||
wire:loading.attr="disabled" wire:target="save">
|
||||
<span wire:loading wire:target="save" class="loading loading-spinner loading-sm"></span>
|
||||
<x-heroicon-o-check class="w-4 h-4" />
|
||||
{{ $company ? 'Guardar cambios' : 'Crear empresa' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user