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:
2026-06-16 18:05:53 +02:00
parent 052e1397df
commit 7d854ffb0a
85 changed files with 8499 additions and 1339 deletions
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('features', function (Blueprint $table) {
$table->enum('status', ['planned', 'started', 'in_progress', 'completed', 'verified'])
->default('planned')
->after('progress');
$table->foreignId('responsible_user_id')
->nullable()
->constrained('users')
->nullOnDelete()
->after('responsible');
});
}
public function down(): void
{
Schema::table('features', function (Blueprint $table) {
$table->dropForeign(['responsible_user_id']);
$table->dropColumn(['status', 'responsible_user_id']);
});
}
};
@@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('inspections', function (Blueprint $table) {
$table->enum('status', ['pending', 'in_progress', 'completed', 'approved', 'rejected'])
->default('pending')
->after('data');
$table->foreignId('inspector_user_id')
->nullable()
->constrained('users')
->nullOnDelete()
->after('status');
$table->timestamp('completed_at')
->nullable()
->after('inspector_user_id');
$table->enum('result', ['pass', 'fail', 'conditional'])
->nullable()
->after('completed_at');
$table->text('notes')
->nullable()
->after('result');
});
}
public function down(): void
{
Schema::table('inspections', function (Blueprint $table) {
$table->dropForeign(['inspector_user_id']);
$table->dropColumn(['status', 'inspector_user_id', 'completed_at', 'result', 'notes']);
});
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('phases', function (Blueprint $table) {
$table->date('planned_start')->nullable()->after('progress_percent');
$table->date('planned_end')->nullable()->after('planned_start');
$table->date('actual_start')->nullable()->after('planned_end');
$table->date('actual_end')->nullable()->after('actual_start');
});
}
public function down(): void
{
Schema::table('phases', function (Blueprint $table) {
$table->dropColumn(['planned_start', 'planned_end', 'actual_start', 'actual_end']);
});
}
};
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
$tables = ['projects', 'phases', 'layers', 'features', 'inspections'];
foreach ($tables as $table) {
if (!Schema::hasColumn($table, 'deleted_at')) {
Schema::table($table, function (Blueprint $t) {
$t->softDeletes();
});
}
}
}
public function down(): void
{
$tables = ['projects', 'phases', 'layers', 'features', 'inspections'];
foreach ($tables as $table) {
if (Schema::hasColumn($table, 'deleted_at')) {
Schema::table($table, function (Blueprint $t) {
$t->dropSoftDeletes();
});
}
}
}
};
@@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('issues', function (Blueprint $table) {
$table->id();
$table->foreignId('project_id')
->constrained('projects')
->cascadeOnDelete();
$table->foreignId('feature_id')
->nullable()
->constrained('features')
->nullOnDelete();
$table->foreignId('inspection_id')
->nullable()
->constrained('inspections')
->nullOnDelete();
$table->string('title');
$table->text('description')->nullable();
$table->enum('status', ['open', 'in_review', 'resolved', 'closed'])
->default('open');
$table->enum('priority', ['low', 'medium', 'high', 'critical'])
->default('medium');
$table->foreignId('reported_by')
->constrained('users');
$table->foreignId('assigned_to')
->nullable()
->constrained('users')
->nullOnDelete();
$table->timestamp('resolved_at')->nullable();
$table->text('resolution_notes')->nullable();
$table->timestamps();
$table->softDeletes();
});
}
public function down(): void
{
Schema::dropIfExists('issues');
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('notifications', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('type');
$table->morphs('notifiable');
$table->text('data');
$table->timestamp('read_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('notifications');
}
};
@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('activity_logs', function (Blueprint $table) {
$table->id();
$table->string('action');
$table->string('model_type');
$table->unsignedBigInteger('model_id');
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->json('changes')->nullable();
$table->timestamps();
$table->index(['model_type', 'model_id']);
});
}
public function down(): void
{
Schema::dropIfExists('activity_logs');
}
};
@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('title', 20)->nullable()->after('id');
$table->string('first_name')->nullable()->after('title');
$table->string('last_name')->nullable()->after('first_name');
$table->string('status', 20)->default('active')->after('name');
$table->date('valid_from')->nullable()->after('status');
$table->date('valid_until')->nullable()->after('valid_from');
$table->foreignId('company_id')->nullable()->constrained('companies')->nullOnDelete()->after('valid_until');
$table->string('phone', 30)->nullable()->after('company_id');
$table->text('address')->nullable()->after('phone');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropForeign(['company_id']);
$table->dropColumn([
'title', 'first_name', 'last_name', 'status',
'valid_from', 'valid_until', 'company_id', 'phone', 'address',
]);
});
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->text('notes')->nullable()->after('address');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('notes');
});
}
};
@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('projects', function (Blueprint $table) {
$table->char('country', 2)->nullable()->after('address');
});
}
public function down(): void
{
Schema::table('projects', function (Blueprint $table) {
$table->dropColumn('country');
});
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('locale', 5)->default('es')->change();
});
// Reset all users still on the old default so they load in Spanish.
// Users that explicitly chose 'en' keep their preference.
DB::table('users')->where('locale', 'en')->update(['locale' => 'es']);
}
public function down(): void
{
DB::table('users')->where('locale', 'es')->update(['locale' => 'en']);
Schema::table('users', function (Blueprint $table) {
$table->string('locale', 5)->default('en')->change();
});
}
};