diff --git a/app/Livewire/ProjectCompanies.php b/app/Livewire/ProjectCompanies.php
new file mode 100644
index 0000000..68d2f76
--- /dev/null
+++ b/app/Livewire/ProjectCompanies.php
@@ -0,0 +1,81 @@
+project = $project;
+ $this->loadCompanies();
+ }
+
+ public function loadCompanies()
+ {
+ $this->assignedCompanies = $this->project->companies()->withPivot('role_in_project')->get();
+ $assignedIds = $this->assignedCompanies->pluck('id')->toArray();
+ $this->allCompanies = Company::whereNotIn('id', $assignedIds)->orderBy('name')->get();
+ }
+
+ public function assignCompany()
+ {
+ $user = Auth::user();
+ if (!$user->can('assign users') && !$user->hasRole('Admin')) {
+ session()->flash('error', 'No tienes permisos para asignar compañías.');
+ return;
+ }
+
+ $this->validate([
+ 'selectedCompanyId' => 'required|exists:companies,id',
+ 'selectedRole' => 'required|in:owner,constructor,subcontractor,consultant,supplier,other',
+ ]);
+
+ $this->project->companies()->attach($this->selectedCompanyId, [
+ 'role_in_project' => $this->selectedRole
+ ]);
+
+ $this->reset(['selectedCompanyId', 'selectedRole']);
+ $this->loadCompanies();
+ $this->dispatch('notify', 'Compañía asignada al proyecto.');
+ }
+
+ public function removeCompany($companyId)
+ {
+ $user = Auth::user();
+ if (!$user->can('assign users') && !$user->hasRole('Admin')) {
+ session()->flash('error', 'Sin permisos.');
+ return;
+ }
+
+ $this->project->companies()->detach($companyId);
+ $this->loadCompanies();
+ $this->dispatch('notify', 'Compañía eliminada del proyecto.');
+ }
+
+ public function changeRole($companyId, $role)
+ {
+ if (!in_array($role, ['owner', 'constructor', 'subcontractor', 'consultant', 'supplier', 'other'])) return;
+
+ $this->project->companies()->updateExistingPivot($companyId, [
+ 'role_in_project' => $role
+ ]);
+ $this->loadCompanies();
+ $this->dispatch('notify', 'Rol actualizado.');
+ }
+
+ public function render()
+ {
+ return view('livewire.project-companies');
+ }
+}
\ No newline at end of file
diff --git a/app/Livewire/ProjectTable.php.bak b/app/Livewire/ProjectTable.php.bak
new file mode 100644
index 0000000..a800e1a
--- /dev/null
+++ b/app/Livewire/ProjectTable.php.bak
@@ -0,0 +1,111 @@
+setPrimaryKey('id')
+ ->setDefaultSort('created_at', 'desc')
+ ->setTableAttributes(['class' => 'table-auto w-full'])
+ ->setThAttributes(['class' => 'px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider'])
+ ->setTdAttributes(['class' => 'px-4 py-2 whitespace-nowrap text-sm text-gray-900']);
+
+ $this->addColumn('name', __('Project Name'))
+ ->setSortable()
+ ->setSearchable();
+
+ $this->addColumn('address', __('Address'))
+ ->setSortable()
+ ->setSearchable();
+
+ $this->addColumn('status', __('Status'))
+ ->setSortable()
+ ->setFilterable([
+ 'planning' => __('Planning'),
+ 'in_progress' => __('In progress'),
+ 'paused' => __('Paused'),
+ 'completed' => __('Completed'),
+ ])
+ ->setLabel(fn ($value, $row, $column, $component) =>
+ match ($value) {
+ 'planning' => ''.__('Planning').' ',
+ 'in_progress' => ''.__('In progress').' ',
+ 'paused' => ''.__('Paused').' ',
+ 'completed' => ''.__('Completed').' ',
+ default => $value
+ }
+ );
+
+ $this->addColumn('start_date', __('Start Date'))
+ ->setSortable()
+ ->setFormat(fn ($value, $row, $column) => $value ? $value->format('Y-m-d') : '');
+
+ $this->addColumn('end_date_estimated', __('Estimated End Date'))
+ ->setSortable()
+ ->setFormat(fn ($value, $row, $column) => $value ? $value->format('Y-m-d') : '');
+
+ $this->addColumn('actions', __('Actions'))
+ ->setLabel(fn ($row) => '
')
+ ->setHtmlAttribute(['class' => 'text-right']);
+ }
+
+ public function columns(): array
+ {
+ return [
+ Column::make(__('Project Name'), 'name')
+ ->sortable()
+ ->searchable(),
+ Column::make(__('Address'), 'address')
+ ->sortable()
+ ->searchable(),
+ Column::make(__('Status'), 'status')
+ ->sortable()
+ ->filterable([
+ 'planning' => __('Planning'),
+ 'in_progress' => __('In progress'),
+ 'paused' => __('Paused'),
+ 'completed' => __('Completed'),
+ ])
+ ->label(fn ($value, $row, $column) =>
+ match ($value) {
+ 'planning' => ''.__('Planning').' ',
+ 'in_progress' => ''.__('In progress').' ',
+ 'paused' => ''.__('Paused').' ',
+ 'completed' => ''.__('Completed').' ',
+ default => $value
+ }
+ ),
+ Column::make(__('Start Date'), 'start_date')
+ ->sortable()
+ ->format(fn ($value, $row, $column) => $value ? $value->format('Y-m-d') : ''),
+ Column::make(__('Estimated End Date'), 'end_date_estimated')
+ ->sortable()
+ ->format(fn ($value, $row, $column) => $value ? $value->format('Y-m-d') : ''),
+ Column::make(__('Actions'))
+ ->label(fn ($row) => '')
+ ->htmlAttribute(['class' => 'text-right']),
+ ];
+ }
+}
diff --git a/app/Models/Company.php b/app/Models/Company.php
new file mode 100644
index 0000000..0d8ed7a
--- /dev/null
+++ b/app/Models/Company.php
@@ -0,0 +1,32 @@
+belongsToMany(Project::class, 'company_project')
+ ->withPivot('role_in_project')
+ ->withTimestamps();
+ }
+}
diff --git a/app/Models/Project.php b/app/Models/Project.php
index 35d782e..892c229 100644
--- a/app/Models/Project.php
+++ b/app/Models/Project.php
@@ -34,6 +34,13 @@ class Project extends Model
return $this->belongsToMany(User::class)->withPivot('role_in_project');
}
+ public function companies()
+ {
+ return $this->belongsToMany(Company::class, 'company_project')
+ ->withPivot('role_in_project')
+ ->withTimestamps();
+ }
+
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
diff --git a/database/migrations/2026_05_13_075321_create_companies_table.php b/database/migrations/2026_05_13_075321_create_companies_table.php
new file mode 100644
index 0000000..de80105
--- /dev/null
+++ b/database/migrations/2026_05_13_075321_create_companies_table.php
@@ -0,0 +1,36 @@
+id();
+ $table->string('name');
+ $table->string('tax_id')->nullable()->unique();
+ $table->string('address')->nullable();
+ $table->string('phone')->nullable();
+ $table->string('email')->nullable();
+ $table->string('website')->nullable();
+ $table->enum('type', ['owner', 'constructor', 'subcontractor', 'consultant', 'supplier', 'other'])->default('other');
+ $table->text('notes')->nullable();
+ $table->timestamps();
+ $table->softDeletes();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('companies');
+ }
+};
\ No newline at end of file
diff --git a/database/migrations/2026_05_13_075457_create_company_project_table.php b/database/migrations/2026_05_13_075457_create_company_project_table.php
new file mode 100644
index 0000000..91634bf
--- /dev/null
+++ b/database/migrations/2026_05_13_075457_create_company_project_table.php
@@ -0,0 +1,33 @@
+id();
+ $table->foreignId('company_id')->constrained()->onDelete('cascade');
+ $table->foreignId('project_id')->constrained()->onDelete('cascade');
+ $table->string('role_in_project');
+ $table->timestamps();
+
+ // Ensure a company is not linked more than once to the same project
+ $table->unique(['company_id', 'project_id']);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('company_project');
+ }
+};
\ No newline at end of file
diff --git a/database/schema/mysql-schema.sql b/database/schema/mysql-schema.sql
new file mode 100644
index 0000000..be317e3
--- /dev/null
+++ b/database/schema/mysql-schema.sql
@@ -0,0 +1,419 @@
+/*M!999999\- enable the sandbox mode */
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+DROP TABLE IF EXISTS `cache`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `cache` (
+ `key` varchar(255) NOT NULL,
+ `value` mediumtext NOT NULL,
+ `expiration` int(11) NOT NULL,
+ PRIMARY KEY (`key`),
+ KEY `cache_expiration_index` (`expiration`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `cache_locks`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `cache_locks` (
+ `key` varchar(255) NOT NULL,
+ `owner` varchar(255) NOT NULL,
+ `expiration` int(11) NOT NULL,
+ PRIMARY KEY (`key`),
+ KEY `cache_locks_expiration_index` (`expiration`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `failed_jobs`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `failed_jobs` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `uuid` varchar(255) NOT NULL,
+ `connection` text NOT NULL,
+ `queue` text NOT NULL,
+ `payload` longtext NOT NULL,
+ `exception` longtext NOT NULL,
+ `failed_at` timestamp NOT NULL DEFAULT current_timestamp(),
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `features`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `features` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `layer_id` bigint(20) unsigned NOT NULL,
+ `name` varchar(255) DEFAULT NULL,
+ `geometry` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`geometry`)),
+ `properties` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`properties`)),
+ `template_id` bigint(20) unsigned DEFAULT NULL,
+ `progress` int(11) NOT NULL DEFAULT 0,
+ `responsible` varchar(255) DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `features_layer_id_foreign` (`layer_id`),
+ KEY `features_template_id_foreign` (`template_id`),
+ CONSTRAINT `features_layer_id_foreign` FOREIGN KEY (`layer_id`) REFERENCES `layers` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `features_template_id_foreign` FOREIGN KEY (`template_id`) REFERENCES `inspection_templates` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `inspection_templates`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `inspection_templates` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `description` text DEFAULT NULL,
+ `project_id` bigint(20) unsigned DEFAULT NULL,
+ `fields` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`fields`)),
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ `phase_id` bigint(20) unsigned DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `inspection_templates_project_id_foreign` (`project_id`),
+ KEY `inspection_templates_phase_id_index` (`phase_id`),
+ CONSTRAINT `inspection_templates_phase_id_foreign` FOREIGN KEY (`phase_id`) REFERENCES `phases` (`id`) ON DELETE SET NULL,
+ CONSTRAINT `inspection_templates_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `inspections`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `inspections` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `project_id` bigint(20) unsigned NOT NULL,
+ `layer_id` bigint(20) unsigned NOT NULL,
+ `template_id` bigint(20) unsigned DEFAULT NULL,
+ `user_id` bigint(20) unsigned NOT NULL,
+ `data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`data`)),
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ `feature_id` bigint(20) unsigned NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `inspections_project_id_foreign` (`project_id`),
+ KEY `inspections_layer_id_foreign` (`layer_id`),
+ KEY `inspections_template_id_foreign` (`template_id`),
+ KEY `inspections_user_id_foreign` (`user_id`),
+ KEY `inspections_feature_id_foreign` (`feature_id`),
+ CONSTRAINT `inspections_feature_id_foreign` FOREIGN KEY (`feature_id`) REFERENCES `features` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `inspections_layer_id_foreign` FOREIGN KEY (`layer_id`) REFERENCES `layers` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `inspections_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `inspections_template_id_foreign` FOREIGN KEY (`template_id`) REFERENCES `inspection_templates` (`id`) ON DELETE SET NULL,
+ CONSTRAINT `inspections_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `job_batches`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `job_batches` (
+ `id` varchar(255) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `total_jobs` int(11) NOT NULL,
+ `pending_jobs` int(11) NOT NULL,
+ `failed_jobs` int(11) NOT NULL,
+ `failed_job_ids` longtext NOT NULL,
+ `options` mediumtext DEFAULT NULL,
+ `cancelled_at` int(11) DEFAULT NULL,
+ `created_at` int(11) NOT NULL,
+ `finished_at` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `jobs`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `jobs` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `queue` varchar(255) NOT NULL,
+ `payload` longtext NOT NULL,
+ `attempts` tinyint(3) unsigned NOT NULL,
+ `reserved_at` int(10) unsigned DEFAULT NULL,
+ `available_at` int(10) unsigned NOT NULL,
+ `created_at` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `jobs_queue_index` (`queue`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `layers`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `layers` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `project_id` bigint(20) unsigned NOT NULL,
+ `phase_id` bigint(20) unsigned DEFAULT NULL,
+ `name` varchar(255) NOT NULL,
+ `color` varchar(7) NOT NULL DEFAULT '#3b82f6',
+ `original_file` varchar(255) DEFAULT NULL,
+ `uploaded_by` bigint(20) unsigned NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `layers_project_id_foreign` (`project_id`),
+ KEY `layers_phase_id_foreign` (`phase_id`),
+ KEY `layers_uploaded_by_foreign` (`uploaded_by`),
+ CONSTRAINT `layers_phase_id_foreign` FOREIGN KEY (`phase_id`) REFERENCES `phases` (`id`) ON DELETE SET NULL,
+ CONSTRAINT `layers_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `layers_uploaded_by_foreign` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `media`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `media` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `mediable_type` varchar(255) NOT NULL,
+ `mediable_id` bigint(20) unsigned NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `file_path` varchar(255) NOT NULL,
+ `file_type` varchar(255) NOT NULL,
+ `file_extension` varchar(10) NOT NULL,
+ `file_size` int(10) unsigned NOT NULL,
+ `category` enum('image','document','other') NOT NULL DEFAULT 'image',
+ `description` text DEFAULT NULL,
+ `metadata` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`metadata`)),
+ `uploaded_by` bigint(20) unsigned NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `media_mediable_type_mediable_id_index` (`mediable_type`,`mediable_id`),
+ KEY `media_uploaded_by_foreign` (`uploaded_by`),
+ CONSTRAINT `media_uploaded_by_foreign` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `migrations`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `migrations` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `migration` varchar(255) NOT NULL,
+ `batch` int(11) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `model_has_permissions`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `model_has_permissions` (
+ `permission_id` bigint(20) unsigned NOT NULL,
+ `model_type` varchar(255) NOT NULL,
+ `model_id` bigint(20) unsigned NOT NULL,
+ PRIMARY KEY (`permission_id`,`model_id`,`model_type`),
+ KEY `model_has_permissions_model_id_model_type_index` (`model_id`,`model_type`),
+ CONSTRAINT `model_has_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `model_has_roles`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `model_has_roles` (
+ `role_id` bigint(20) unsigned NOT NULL,
+ `model_type` varchar(255) NOT NULL,
+ `model_id` bigint(20) unsigned NOT NULL,
+ PRIMARY KEY (`role_id`,`model_id`,`model_type`),
+ KEY `model_has_roles_model_id_model_type_index` (`model_id`,`model_type`),
+ CONSTRAINT `model_has_roles_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `password_reset_tokens`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `password_reset_tokens` (
+ `email` varchar(255) NOT NULL,
+ `token` varchar(255) NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`email`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `pending_syncs`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `pending_syncs` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `user_id` bigint(20) unsigned NOT NULL,
+ `action` varchar(255) NOT NULL,
+ `payload` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`payload`)),
+ `synced_at` timestamp NULL DEFAULT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `pending_syncs_user_id_foreign` (`user_id`),
+ CONSTRAINT `pending_syncs_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `permissions`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `permissions` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `guard_name` varchar(255) NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `permissions_name_guard_name_unique` (`name`,`guard_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `phases`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `phases` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `project_id` bigint(20) unsigned NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `description` text DEFAULT NULL,
+ `order` int(11) NOT NULL DEFAULT 0,
+ `color` varchar(7) NOT NULL DEFAULT '#3b82f6',
+ `progress_percent` int(11) NOT NULL DEFAULT 0,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `phases_project_id_foreign` (`project_id`),
+ CONSTRAINT `phases_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `progress_updates`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `progress_updates` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `phase_id` bigint(20) unsigned NOT NULL,
+ `user_id` bigint(20) unsigned NOT NULL,
+ `progress_percent` int(11) NOT NULL,
+ `comment` text DEFAULT NULL,
+ `location` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`location`)),
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `progress_updates_phase_id_foreign` (`phase_id`),
+ KEY `progress_updates_user_id_foreign` (`user_id`),
+ CONSTRAINT `progress_updates_phase_id_foreign` FOREIGN KEY (`phase_id`) REFERENCES `phases` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `progress_updates_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `project_user`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `project_user` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `project_id` bigint(20) unsigned NOT NULL,
+ `user_id` bigint(20) unsigned NOT NULL,
+ `role_in_project` varchar(255) NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `project_user_project_id_foreign` (`project_id`),
+ KEY `project_user_user_id_foreign` (`user_id`),
+ CONSTRAINT `project_user_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `project_user_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `projects`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `projects` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `address` text NOT NULL,
+ `lat` decimal(10,8) NOT NULL,
+ `lng` decimal(11,8) NOT NULL,
+ `start_date` date NOT NULL,
+ `end_date_estimated` date DEFAULT NULL,
+ `status` enum('planning','in_progress','paused','completed') NOT NULL DEFAULT 'planning',
+ `created_by` bigint(20) unsigned NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `projects_created_by_foreign` (`created_by`),
+ CONSTRAINT `projects_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `role_has_permissions`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `role_has_permissions` (
+ `permission_id` bigint(20) unsigned NOT NULL,
+ `role_id` bigint(20) unsigned NOT NULL,
+ PRIMARY KEY (`permission_id`,`role_id`),
+ KEY `role_has_permissions_role_id_foreign` (`role_id`),
+ CONSTRAINT `role_has_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `role_has_permissions_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `roles`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `roles` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `guard_name` varchar(255) NOT NULL,
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `roles_name_guard_name_unique` (`name`,`guard_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `sessions`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `sessions` (
+ `id` varchar(255) NOT NULL,
+ `user_id` bigint(20) unsigned DEFAULT NULL,
+ `ip_address` varchar(45) DEFAULT NULL,
+ `user_agent` text DEFAULT NULL,
+ `payload` longtext NOT NULL,
+ `last_activity` int(11) NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `sessions_user_id_index` (`user_id`),
+ KEY `sessions_last_activity_index` (`last_activity`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+DROP TABLE IF EXISTS `users`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8mb4 */;
+CREATE TABLE `users` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `email` varchar(255) NOT NULL,
+ `email_verified_at` timestamp NULL DEFAULT NULL,
+ `password` varchar(255) NOT NULL,
+ `remember_token` varchar(100) DEFAULT NULL,
+ `locale` varchar(5) NOT NULL DEFAULT 'en',
+ `created_at` timestamp NULL DEFAULT NULL,
+ `updated_at` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `users_email_unique` (`email`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+/*M!999999\- enable the sandbox mode */
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (1,'0001_01_01_000000_create_users_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (2,'0001_01_01_000001_create_cache_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (3,'0001_01_01_000002_create_jobs_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (4,'2026_04_27_095918_create_projects_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (5,'2026_04_27_095919_create_phases_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (6,'2026_04_27_095920_create_layers_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (7,'2026_04_27_095921_create_progress_updates_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (8,'2026_04_27_095925_create_pending_syncs_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (9,'2026_04_27_095925_create_project_user_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (10,'2026_04_27_095926_create_permission_tables',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (11,'2026_04_28_090208_create_inspection_templates_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (12,'2026_04_28_090218_create_inspections_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (13,'2026_05_06_122423_create_features_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (14,'2026_05_06_122711_update_inspections_feature_id_foreign',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (15,'2026_05_06_125429_drop_geojson_data_from_layers',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (16,'2026_05_06_172557_add_color_to_layers_table',1);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (17,'2026_05_09_210000_create_media_table',2);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (18,'2026_05_09_220000_add_locale_to_users_table',3);
+INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES (19,'2026_05_11_115552_add_phase_id_to_inspection_templates',4);
diff --git a/resources/views/livewire/project-companies.blade.php b/resources/views/livewire/project-companies.blade.php
new file mode 100644
index 0000000..9a581a0
--- /dev/null
+++ b/resources/views/livewire/project-companies.blade.php
@@ -0,0 +1,76 @@
+
+ @if(session()->has('message'))
+
{{ session('message') }}
+ @endif
+ @if(session()->has('error'))
+
{{ session('error') }}
+ @endif
+
+ {{-- Asignar compañía --}}
+ @can('assign users')
+
+ @endcan
+
+ {{-- Lista de compañías asignadas --}}
+ @if($assignedCompanies->isNotEmpty())
+
+ @foreach($assignedCompanies as $company)
+
+
+
+ {{ strtoupper(substr($company->name, 0, 1)) }}
+
+
+ {{ $company->name }}
+ @if($company->tax_id)
+ {{ $company->tax_id }}
+ @endif
+
+
+
+ @can('assign users')
+
+ pivot->role_in_project == 'owner')>{{ __('Owner') }}
+ pivot->role_in_project == 'constructor')>{{ __('Constructor') }}
+ pivot->role_in_project == 'subcontractor')>{{ __('Subcontractor') }}
+ pivot->role_in_project == 'consultant')>{{ __('Consultant') }}
+ pivot->role_in_project == 'supplier')>{{ __('Supplier') }}
+ pivot->role_in_project == 'other')>{{ __('Other') }}
+
+ ✕
+ @else
+ {{ ucfirst($company->pivot->role_in_project) }}
+ @endcan
+
+
+ @endforeach
+
+ @else
+
{{ __('No companies assigned yet') }}
+ @endif
+
\ No newline at end of file
diff --git a/resources/views/livewire/project-edit-tabs.blade.php b/resources/views/livewire/project-edit-tabs.blade.php
index c8d5926..ea2e578 100644
--- a/resources/views/livewire/project-edit-tabs.blade.php
+++ b/resources/views/livewire/project-edit-tabs.blade.php
@@ -18,6 +18,12 @@
{{ __('Users') }}
+
+
+
+ {{ __('Companies') }}
+
diff --git a/resources/views/livewire/project-table.blade.php.backup b/resources/views/livewire/project-table.blade.php.backup
new file mode 100644
index 0000000..fd5ed6b
--- /dev/null
+++ b/resources/views/livewire/project-table.blade.php.backup
@@ -0,0 +1,3 @@
+
+ {{-- Nothing in the world is as soft and yielding as water. --}}
+
diff --git a/resources/views/livewire/template-manager.blade.php.bak b/resources/views/livewire/template-manager.blade.php.bak
new file mode 100644
index 0000000..16f9fb1
--- /dev/null
+++ b/resources/views/livewire/template-manager.blade.php.bak
@@ -0,0 +1,160 @@
+
+
+
+
📋 Templates de inspección
+
+
+ Nuevo template
+
+
+
+
+ @if(session()->has('message'))
+
{{ session('message') }}
+ @endif
+
+ {{-- Formulario de creación/edición con diseño de dos columnas --}}
+ @if($showForm)
+
+ @endif
+
+ {{-- Tabla de templates existentes --}}
+
+
+
+
+ Nombre
+ Descripción
+ Fase
+ Campos
+ Acciones
+
+
+
+ @forelse($templates as $template)
+
+ {{ $template->name }}
+ {{ $template->description ?? '-' }}
+ {{ $template->phase ? $template->phase->name : 'Global' }}
+ {{ count($template->fields) }}
+
+
+ Editar
+
+ Eliminar
+
+
+ @empty
+
+ No hay templates creados. Presiona "Nuevo template" para comenzar.
+
+ @endforelse
+
+
+
+
+
\ No newline at end of file