Habilidades Puntuadas (#2)
Co-authored-by: Juan Felipe Zapata Moreno <zapata_pipe@hotmail.com> Reviewed-on: #2 Co-authored-by: Juan Felipe Zapata Moreno <juan.zapata@golsystems.com.mx> Co-committed-by: Juan Felipe Zapata Moreno <juan.zapata@golsystems.com.mx>
This commit is contained in:
parent
0a526df665
commit
023fd8d2f8
4
app/Http/Controllers/.prettierrc
Normal file
4
app/Http/Controllers/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false
|
||||
}
|
||||
151
app/Http/Controllers/Admin/MainRoleSkillsController.php
Normal file
151
app/Http/Controllers/Admin/MainRoleSkillsController.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use App\Http\Requests\StoreMainRoleSkills;
|
||||
use App\Http\Requests\UpdateMainRoleSkills;
|
||||
use App\Models\department;
|
||||
use App\Models\mainRole;
|
||||
use App\Models\MainRoleSkills;
|
||||
use App\Models\Score;
|
||||
use App\Models\Skill;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Notsoweb\Core\Http\Controllers\VueController;
|
||||
|
||||
/**
|
||||
* Descripción
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class MainRoleSkillsController extends VueController
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
return $this->vueRoot('admin.mainRoleSkills');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$q = request()->get('q');
|
||||
|
||||
$mainRole = mainRole::where('name', 'LIKE', "%{$q}%")->pluck('id');
|
||||
$skills = Skill::where('name', 'LIKE', "%{$q}%")->pluck('id');
|
||||
$scores = Score::where('alias', 'LIKE', "%{$q}%")->pluck('id');
|
||||
|
||||
$mainRoleSkills = MainRoleSkills::whereIn('main_role_id', $mainRole)
|
||||
->orWhereIn('skill_id', $skills)
|
||||
->orWhereIn('scored_id', $scores)
|
||||
->with([
|
||||
'mainRole:id,name,department_id',
|
||||
'mainRole.department:id,name',
|
||||
'skill:id,name',
|
||||
'score:id,alias'
|
||||
])
|
||||
->paginate(config('app.pagination'));
|
||||
|
||||
$departments = department::select(['id', 'name', 'description'])->orderBy('name', 'ASC')->get();
|
||||
$mainRoles = mainRole::with(['department:id,name'])->orderBy('name', 'ASC')->get();
|
||||
$skills = Skill::with(['department:id,name'])->orderBy('name', 'ASC')->get();
|
||||
$scores = Score::orderBy('alias', 'ASC')->get();
|
||||
|
||||
|
||||
return $this->vuew('index', [
|
||||
'mainRoleSkills' => $mainRoleSkills,
|
||||
'departments' => $departments,
|
||||
'mainRoles' => $mainRoles,
|
||||
'skills' => $skills,
|
||||
'scores' => $scores,
|
||||
]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$roleId = request()->get('role_id');
|
||||
$departmentId = request()->get('department_id');
|
||||
|
||||
// Obtener el rol seleccionado y su departamento
|
||||
$selectedRole = null;
|
||||
$selectedDepartment = null;
|
||||
|
||||
if ($roleId) {
|
||||
$selectedRole = mainRole::with('department:id,name')->find($roleId);
|
||||
if ($selectedRole && $selectedRole->department) {
|
||||
$selectedDepartment = $selectedRole->department;
|
||||
}
|
||||
} elseif ($departmentId) {
|
||||
$selectedDepartment = department::find($departmentId);
|
||||
}
|
||||
$mainRoles = mainRole::with('department:id,name')->orderBy('name', 'ASC')->get();
|
||||
$skills = Skill::with('department:id,name')->orderBy('name', 'ASC')->get();
|
||||
$scores = Score::orderBy('alias', 'ASC')->get();
|
||||
|
||||
return $this->vuew('create', [
|
||||
'mainRoles' => $mainRoles,
|
||||
'skills' => $skills,
|
||||
'scores' => $scores,
|
||||
'selectedRole' => $selectedRole,
|
||||
'selectedDepartment' => $selectedDepartment
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(StoreMainRoleSkills $request)
|
||||
{
|
||||
$create = [];
|
||||
foreach ($request['skills'] as $skill) {
|
||||
$create[] = [
|
||||
'main_role_id' => $request['main_role_id'],
|
||||
'skill_id' => $skill['skill_id'],
|
||||
'scored_id' => $skill['scored_id'],
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
];
|
||||
}
|
||||
|
||||
MainRoleSkills::insert($create);
|
||||
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
public function edit(MainRoleSkills $mainRoleSkills)
|
||||
{
|
||||
$mainRoleSkills->load(['mainRole.department', 'skill.department', 'score']);
|
||||
$scores = Score::orderBy('alias', 'ASC')->get();
|
||||
|
||||
return $this->vuew('edit', [
|
||||
'mainRoleSkills' => $mainRoleSkills,
|
||||
'scores' => $scores,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function update(UpdateMainRoleSkills $request, $id)
|
||||
{
|
||||
$mainRoleSkills = MainRoleSkills::findOrFail($id);
|
||||
|
||||
$mainRoleSkills->update([
|
||||
'scored_id' => $request->scored_id,
|
||||
]);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
try {
|
||||
$mainRoleSkills = MainRoleSkills::findOrFail($id);
|
||||
|
||||
$mainRoleSkills->delete();
|
||||
|
||||
return $this->index();
|
||||
} catch (\Throwable $th) {
|
||||
Log::error($th->getMessage());
|
||||
return response()->json(['error' => 'Error al eliminar las habilidades']);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
app/Http/Controllers/Admin/SkillController.php
Normal file
65
app/Http/Controllers/Admin/SkillController.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php namespace App\Http\Controllers\Admin;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use App\Http\Requests\StoreSkill;
|
||||
use App\Http\Requests\UpdateSkill;
|
||||
use App\Models\department;
|
||||
use App\Models\Skill;
|
||||
use Notsoweb\Core\Http\Controllers\VueController;
|
||||
|
||||
/**
|
||||
* Descripción
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class SkillController extends VueController
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
return $this->vueRoot('admin.skills');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$q = request()->get('q');
|
||||
|
||||
$skills = Skill::orderBy('name', 'ASC')
|
||||
->where('name', 'LIKE', "%{$q}%")
|
||||
->with('department:id,name')
|
||||
->paginate(config('app.pagination'));
|
||||
|
||||
return $this->vuew('index', [
|
||||
'skills' => $skills,
|
||||
]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$department = department::orderBy('name', 'ASC')->get();
|
||||
|
||||
return $this->vuew('create', [
|
||||
'departments' => $department,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(StoreSkill $request)
|
||||
{
|
||||
Skill::create($request->all());
|
||||
|
||||
return $this->index();
|
||||
}
|
||||
|
||||
public function update(UpdateSkill $request, Skill $skill)
|
||||
{
|
||||
$skill->update($request->all());
|
||||
}
|
||||
|
||||
public function destroy (Skill $skill)
|
||||
{
|
||||
$skill->delete();
|
||||
}
|
||||
}
|
||||
41
app/Http/Requests/StoreMainRoleSkills.php
Normal file
41
app/Http/Requests/StoreMainRoleSkills.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Valida el almacenamiento de un usuario
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class StoreMainRoleSkills extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determinar si el usuario esta autorizado
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reglas de validación
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'main_role_id' => ['required', 'integer'],
|
||||
'skills' => ['required', 'array', 'min:1'],
|
||||
'skills.*.skill_id' => ['required', 'integer'],
|
||||
'skills.*.scored_id' => ['required', 'integer'],
|
||||
];
|
||||
}
|
||||
}
|
||||
40
app/Http/Requests/StoreSkill.php
Normal file
40
app/Http/Requests/StoreSkill.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Valida el almacenamiento de un usuario
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class StoreSkill extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determinar si el usuario esta autorizado
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reglas de validación
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string'],
|
||||
'description' => ['nullable', 'string'],
|
||||
'department_id' => ['required', 'integer'],
|
||||
];
|
||||
}
|
||||
}
|
||||
38
app/Http/Requests/UpdateMainRoleSkills.php
Normal file
38
app/Http/Requests/UpdateMainRoleSkills.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Valida el almacenamiento de un usuario
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class UpdateMainRoleSkills extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determinar si el usuario esta autorizado
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reglas de validación
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'scored_id' => ['required', 'integer'],
|
||||
];
|
||||
}
|
||||
}
|
||||
40
app/Http/Requests/UpdateSkill.php
Normal file
40
app/Http/Requests/UpdateSkill.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php namespace App\Http\Requests;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
/**
|
||||
* Valida el almacenamiento de un usuario
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class UpdateSkill extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determinar si el usuario esta autorizado
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reglas de validación
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string'],
|
||||
'description' => ['nullable', 'string'],
|
||||
'department_id' => ['required', 'integer','exists:departments,id'],
|
||||
];
|
||||
}
|
||||
}
|
||||
45
app/Models/MainRoleSkills.php
Normal file
45
app/Models/MainRoleSkills.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php namespace App\Models;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use App\Http\Traits\ModelExtend;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Descripción
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class MainRoleSkills extends Model
|
||||
{
|
||||
use HasFactory,
|
||||
ModelExtend;
|
||||
|
||||
/**
|
||||
* Atributos llenables masivamente
|
||||
*/
|
||||
protected $fillable = [
|
||||
'main_role_id',
|
||||
'skill_id',
|
||||
'scored_id',
|
||||
];
|
||||
|
||||
public function mainRole()
|
||||
{
|
||||
return $this->belongsTo(mainRole::class, 'main_role_id');
|
||||
}
|
||||
|
||||
public function skill()
|
||||
{
|
||||
return $this->belongsTo(Skill::class, 'skill_id');
|
||||
}
|
||||
|
||||
public function score()
|
||||
{
|
||||
return $this->belongsTo(Score::class, 'scored_id');
|
||||
}
|
||||
}
|
||||
@ -27,4 +27,9 @@ class Score extends Model
|
||||
'value',
|
||||
'description',
|
||||
];
|
||||
|
||||
public function mainRoleSkills()
|
||||
{
|
||||
return $this->hasMany(MainRoleSkills::class);
|
||||
}
|
||||
}
|
||||
|
||||
46
app/Models/Skill.php
Normal file
46
app/Models/Skill.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php namespace App\Models;
|
||||
/**
|
||||
* @copyright Copyright (c) 2023 Notsoweb (https://notsoweb.com) - All rights reserved.
|
||||
*/
|
||||
|
||||
use App\Http\Traits\ModelExtend;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Descripción
|
||||
*
|
||||
* @author Moisés de Jesús Cortés Castellanos <ing.moisesdejesuscortesc@notsoweb.com>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
class Skill extends Model
|
||||
{
|
||||
use HasFactory,
|
||||
ModelExtend;
|
||||
|
||||
/**
|
||||
* Atributos llenables masivamente
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'department_id',
|
||||
];
|
||||
|
||||
|
||||
public function department()
|
||||
{
|
||||
return $this->belongsTo(department::class);
|
||||
}
|
||||
|
||||
public function mainRoles()
|
||||
{
|
||||
return $this->belongsTo(MainRole::class);
|
||||
}
|
||||
|
||||
public function mainRoleSkills()
|
||||
{
|
||||
return $this->hasMany(MainRoleSkills::class);
|
||||
}
|
||||
}
|
||||
@ -34,4 +34,9 @@ public function mainRoles()
|
||||
{
|
||||
return $this->hasMany(MainRole::class);
|
||||
}
|
||||
|
||||
public function skills()
|
||||
{
|
||||
return $this->hasMany(Skill::class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ class MainRole extends Model
|
||||
/**
|
||||
* Nombre de la tabla
|
||||
*/
|
||||
protected $table = 'main_role';
|
||||
protected $table = 'main_roles';
|
||||
|
||||
/**
|
||||
* Atributos llenables masivamente
|
||||
@ -40,4 +40,14 @@ public function department()
|
||||
{
|
||||
return $this->belongsTo(department::class);
|
||||
}
|
||||
|
||||
public function skills()
|
||||
{
|
||||
return $this->hasMany(Skill::class);
|
||||
}
|
||||
|
||||
public function mainRoleSkills()
|
||||
{
|
||||
return $this->hasMany(MainRoleSkills::class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('main_role', function (Blueprint $table) {
|
||||
Schema::create('main_roles', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('description')->nullable();
|
||||
@ -25,6 +25,6 @@ public function up(): void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('main_role');
|
||||
Schema::dropIfExists('main_roles');
|
||||
}
|
||||
};
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
<?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::create('skills', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('description');
|
||||
$table->foreignId('department_id')->constrained('departments')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('skills');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,32 @@
|
||||
<?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::create('main_role_skills', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('main_role_id')->constrained('main_roles')->onDelete('cascade');
|
||||
$table->foreignId('skill_id')->constrained('skills')->onDelete('cascade');
|
||||
$table->foreignId('scored_id')->constrained('scores')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['main_role_id', 'skill_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('main_role_skills');
|
||||
}
|
||||
};
|
||||
32
resources/js/Components/App/DepartmentSelector.vue
Normal file
32
resources/js/Components/App/DepartmentSelector.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<script setup>
|
||||
defineEmits(['select']);
|
||||
|
||||
const props = defineProps({
|
||||
departments: Object,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="mb-6 mt-12">
|
||||
<h2 class="text-xl font-semibold mb-2">{{ $t('department.select.title') }}</h2>
|
||||
<p class="text-gray-600">{{ $t('department.select.description') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<button
|
||||
v-for="department in departments"
|
||||
:key="department.id"
|
||||
@click="$emit('select', department)"
|
||||
class="group p-6 border-2 border-gray-200 rounded-lg hover:border-primary hover:bg-primary/5 transition-all duration-200 text-left focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
|
||||
>
|
||||
<h3 class="font-semibold text-lg mb-2 group-hover:text-primary transition-colors">
|
||||
{{ department.name }}
|
||||
</h3>
|
||||
<p class="text-gray-600 text-sm">
|
||||
{{ department.description }}
|
||||
</p>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
47
resources/js/Components/App/MainRoleSelector.vue
Normal file
47
resources/js/Components/App/MainRoleSelector.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const emit = defineEmits(['select']);
|
||||
|
||||
const props = defineProps({
|
||||
mainRoles: Object,
|
||||
selectedDepartment: Object,
|
||||
});
|
||||
|
||||
const departmentMainRoles = computed(() => {
|
||||
return props.mainRoles.filter(role =>
|
||||
role.department && role.department.id === props.selectedDepartment.id
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="mb-6 mt-12">
|
||||
<h2 class="text-xl font-semibold mb-2">
|
||||
{{ $t('mainRole.inDepartment') }}
|
||||
</h2>
|
||||
<p class="text-gray-600">{{ $t('mainRole.select.description') }}</p>
|
||||
</div>
|
||||
|
||||
<div v-if="departmentMainRoles.length > 0" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<button
|
||||
v-for="mainRole in departmentMainRoles"
|
||||
:key="mainRole.id"
|
||||
@click="$emit('select', mainRole)"
|
||||
class="group p-6 border-2 border-gray-200 rounded-lg hover:border-primary hover:bg-primary/5 transition-all duration-200 text-left focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
|
||||
>
|
||||
<h3 class="font-semibold text-lg mb-2 group-hover:text-primary transition-colors">
|
||||
{{ mainRole.name }}
|
||||
</h3>
|
||||
<p class="text-gray-600 text-sm">
|
||||
{{ mainRole.description}}
|
||||
</p>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-center py-12">
|
||||
<p class="text-gray-500 text-lg">{{ $t('mainRole.noRolesInDepartment') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
177
resources/js/Components/App/SkillAssignment.vue
Normal file
177
resources/js/Components/App/SkillAssignment.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<script setup>
|
||||
import { ref, computed } from "vue";
|
||||
import PrimaryButton from "@/Components/Dashboard/Button/Primary.vue";
|
||||
import Selectable from "@/Components/Dashboard/Form/Selectable.vue";
|
||||
|
||||
const emit = defineEmits(["submit"]);
|
||||
|
||||
const props = defineProps({
|
||||
form: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
skills: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
scores: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
selectedDepartment: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
selectedMainRole: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const skillId = ref("");
|
||||
const scoredId = ref("");
|
||||
const todos = ref([]);
|
||||
|
||||
function addTodo() {
|
||||
if (skillId.value && scoredId.value) {
|
||||
const selectedSkill = props.skills.find(
|
||||
(skill) => skill.id === (skillId.value.id || skillId.value)
|
||||
);
|
||||
const selectedScore = props.scores.find(
|
||||
(score) => score.id === (scoredId.value.id || scoredId.value)
|
||||
);
|
||||
|
||||
if (selectedSkill && selectedScore) {
|
||||
// Verificar que no esté duplicada
|
||||
const isDuplicate = todos.value.some(
|
||||
(todo) => todo.skill_id === selectedSkill.id
|
||||
);
|
||||
|
||||
if (!isDuplicate) {
|
||||
const newItem = {
|
||||
skill_id: selectedSkill.id,
|
||||
scored_id: selectedScore.id,
|
||||
skill_name: selectedSkill.name,
|
||||
score_alias: selectedScore.alias,
|
||||
};
|
||||
|
||||
todos.value.push(newItem);
|
||||
|
||||
// Limpiar campos
|
||||
skillId.value = "";
|
||||
scoredId.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeTodo(index) {
|
||||
todos.value.splice(index, 1);
|
||||
}
|
||||
|
||||
const isFormValid = computed(() => {
|
||||
return todos.value.length > 0;
|
||||
});
|
||||
|
||||
const submitForm = () => {
|
||||
if (isFormValid.value) {
|
||||
emit("submit", todos.value);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="mb-6">
|
||||
<h2 class="text-xl font-semibold mb-2">
|
||||
Asignar Habilidades al Rol: {{ selectedMainRole.name }}
|
||||
</h2>
|
||||
<p class="text-gray-600">Departamento: {{ selectedDepartment.name }}</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="form.errors.skills"
|
||||
class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4 mt-4"
|
||||
>
|
||||
{{ form.errors.skills }}
|
||||
</div>
|
||||
|
||||
<!-- Formulario para agregar habilidades -->
|
||||
<div class="bg-white rounded-lg shadow-sm border p-6 mb-6">
|
||||
<div class="grid gap-6 grid-cols-1 md:grid-cols-2">
|
||||
<Selectable
|
||||
id="skill_id"
|
||||
v-model="skillId"
|
||||
:options="skills"
|
||||
:title="$t('skill.title')"
|
||||
placeholder="Selecciona una habilidad..."
|
||||
label="name"
|
||||
track-by="id"
|
||||
required
|
||||
/>
|
||||
|
||||
<Selectable
|
||||
id="scored_id"
|
||||
v-model="scoredId"
|
||||
:options="scores"
|
||||
:title="$t('scores.title')"
|
||||
placeholder="Selecciona una puntuación..."
|
||||
label="alias"
|
||||
track-by="id"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center mt-6">
|
||||
<button
|
||||
@click="addTodo"
|
||||
type="button"
|
||||
:disabled="!skillId || !scoredId"
|
||||
class="rounded-lg px-4 py-2 bg-primary text-white border disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Agregar Habilidad
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lista de habilidades agregadas -->
|
||||
<div class="space-y-3 mb-6">
|
||||
<template v-for="(todo, index) in todos" :key="index">
|
||||
<div
|
||||
class="flex bg-white items-center justify-between rounded-lg px-4 py-3 border shadow-sm"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="font-bold text-black">{{ todo.skill_name }}</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
Puntuación: {{ todo.score_alias }}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
@click="removeTodo(index)"
|
||||
class="rounded-lg px-4 py-2 bg-red-600 text-white hover:bg-red-700 transition-colors"
|
||||
>
|
||||
Quitar
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-if="todos.length === 0"
|
||||
class="text-gray-500 text-center py-8 bg-gray-50 rounded-lg"
|
||||
>
|
||||
No hay habilidades agregadas
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Botón de envío -->
|
||||
<div class="flex justify-center">
|
||||
<PrimaryButton
|
||||
:class="{ 'opacity-25': form.processing }"
|
||||
:disabled="form.processing || !isFormValid"
|
||||
type="button"
|
||||
@click="submitForm"
|
||||
>
|
||||
<span>Crear Asignación</span>
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
135
resources/js/Components/App/SkillsRole.vue
Normal file
135
resources/js/Components/App/SkillsRole.vue
Normal file
@ -0,0 +1,135 @@
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { Link } from "@inertiajs/vue3";
|
||||
import { can, goTo } from "@/Pages/Admin/MainRoleSkills/Component";
|
||||
|
||||
import GoogleIcon from "@/Components/Shared/GoogleIcon.vue";
|
||||
import ModalController from "@/Controllers/ModalController.js";
|
||||
import DestroyView from "@/Pages/Admin/MainRoleSkills/Destroy.vue";
|
||||
import EditView from '@/Pages/Admin/MainRoleSkills/Edit.vue';
|
||||
|
||||
const emit = defineEmits(["select"]);
|
||||
|
||||
const props = defineProps({
|
||||
mainRoleSkills: Array,
|
||||
selectedRole: Object,
|
||||
scores: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
// Controlador de modal
|
||||
const Modal = new ModalController();
|
||||
const destroyModal = ref(Modal.destroyModal);
|
||||
const editModal = ref(Modal.editModal);
|
||||
const modelModal = ref(Modal.modelModal);
|
||||
|
||||
const roleSkills = computed(() => {
|
||||
if (!props.mainRoleSkills || !props.selectedRole) {
|
||||
return [];
|
||||
}
|
||||
return props.mainRoleSkills.filter(
|
||||
(roleSkill) => roleSkill.main_role_id === props.selectedRole.id
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="mb-6 mt-12">
|
||||
<div class="flex gap-6">
|
||||
<h2 class="text-xl font-semibold mb-2">
|
||||
{{ $t("skill.assignment.title") }}
|
||||
</h2>
|
||||
<Link
|
||||
v-if="can('create')"
|
||||
:href="
|
||||
route(goTo('create'), {
|
||||
role_id: selectedRole.id,
|
||||
department_id:
|
||||
selectedRole.department?.id || selectedRole.department_id,
|
||||
})
|
||||
"
|
||||
>
|
||||
<GoogleIcon
|
||||
:title="$t('crud.create')"
|
||||
class="btn-icon-primary"
|
||||
name="add"
|
||||
outline
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
<p class="text-gray-600">
|
||||
Habilidades asignadas al rol: {{ selectedRole.name }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="roleSkills.length > 0"
|
||||
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"
|
||||
>
|
||||
<div
|
||||
v-for="roleSkill in roleSkills"
|
||||
:key="roleSkill.id"
|
||||
class="bg-white p-4 rounded-lg shadow hover:shadow-lg transition-shadow duration-200 cursor-pointer border"
|
||||
@click="emit('select', roleSkill)"
|
||||
>
|
||||
<h3 class="text-lg font-medium mb-2 text-blue-600">
|
||||
{{ roleSkill.skill.name }}
|
||||
</h3>
|
||||
|
||||
<div class="text-sm text-gray-600">
|
||||
<span class="font-semibold">Puntuación:</span>
|
||||
{{ roleSkill.score.alias }}
|
||||
</div>
|
||||
|
||||
<p
|
||||
v-if="roleSkill.skill.description"
|
||||
class="text-xs text-gray-500 mt-2"
|
||||
>
|
||||
{{ roleSkill.skill.description }}
|
||||
</p>
|
||||
<div class="flex items-center justify-end mt-4 gap-2">
|
||||
<GoogleIcon
|
||||
v-if="can('edit')"
|
||||
:title="$t('crud.edit')"
|
||||
class="btn-icon-danger w-6 h-6 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
name="edit"
|
||||
@click.stop="Modal.switchEditModal(roleSkill)"
|
||||
/>
|
||||
<GoogleIcon
|
||||
v-if="can('destroy')"
|
||||
:title="$t('crud.destroy')"
|
||||
class="btn-icon-danger w-6 h-6 bg-red-500 text-white rounded hover:bg-red-600"
|
||||
name="delete"
|
||||
@click.stop="Modal.switchDestroyModal(roleSkill)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-center py-12">
|
||||
<p class="text-gray-500 text-lg">
|
||||
No hay habilidades asignadas a este rol
|
||||
</p>
|
||||
<p class="text-gray-400 text-sm mt-2">
|
||||
Las habilidades se pueden asignar desde la sección de creación
|
||||
</p>
|
||||
</div>
|
||||
<EditView
|
||||
v-if="can('edit')"
|
||||
:show="editModal"
|
||||
:model="modelModal"
|
||||
:scores="scores"
|
||||
@close="Modal.switchEditModal"
|
||||
@switchModal="Modal.switchEditModal"
|
||||
/>
|
||||
<DestroyView
|
||||
v-if="can('destroy')"
|
||||
:show="destroyModal"
|
||||
:model="modelModal"
|
||||
@close="Modal.switchDestroyModal"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
38
resources/js/Components/App/StepIndicator.vue
Normal file
38
resources/js/Components/App/StepIndicator.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
currentStep: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const steps = [
|
||||
{ number: 1, name: 'department.title' },
|
||||
{ number: 2, name: 'mainRole.title' },
|
||||
{ number: 3, name: 'skill.title' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full pb-4">
|
||||
<div class="flex items-center justify-center space-x-4 mb-6">
|
||||
<template v-for="(step, index) in steps" :key="step.number">
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class="w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium transition-colors"
|
||||
:class="currentStep >= step.number ? 'bg-primary text-primary-on' : 'bg-gray-300 text-gray-600'"
|
||||
>
|
||||
{{ step.number }}
|
||||
</div>
|
||||
<span class="ml-2 text-sm font-medium">{{ $t(step.name) }}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="index < steps.length - 1"
|
||||
class="w-8 h-1 bg-gray-300 transition-colors"
|
||||
:class="currentStep > step.number ? 'bg-primary' : ''"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -46,34 +46,34 @@ const onRemove = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col relative">
|
||||
<label v-if="title" class="block mb-2 text-sm font-medium text-gray-900">
|
||||
{{title}} <span class="text-red-500" v-if="required">*</span> <slot name="label-icon" />
|
||||
</label>
|
||||
<VueMultiselect
|
||||
v-model="value"
|
||||
ref="multiselect"
|
||||
:options="options"
|
||||
:mode="mode"
|
||||
:close-on-select="true"
|
||||
:clear-on-select="false"
|
||||
:preserve-search="true"
|
||||
selectedLabel="Seleccionado"
|
||||
selectLabel="Seleccionar"
|
||||
deselectLabel="Remover"
|
||||
:placeholder="placeholder"
|
||||
:label="label"
|
||||
:track-by="trackBy"
|
||||
:required="required"
|
||||
@select="onChange"
|
||||
@remove="onRemove"
|
||||
>
|
||||
<template #noOptions>
|
||||
{{ $t('noRecords') }}
|
||||
</template>
|
||||
<VueMultiselect
|
||||
v-model="value"
|
||||
ref="multiselect"
|
||||
:options="options"
|
||||
:mode="mode"
|
||||
:close-on-select="true"
|
||||
:clear-on-select="false"
|
||||
:preserve-search="true"
|
||||
selectedLabel="Seleccionado"
|
||||
selectLabel="Seleccionar"
|
||||
deselectLabel="Remover"
|
||||
:placeholder="placeholder"
|
||||
:label="label"
|
||||
:track-by="trackBy"
|
||||
:required="required"
|
||||
@select="onChange"
|
||||
@remove="onRemove"
|
||||
>
|
||||
<template #noOptions>
|
||||
{{ $t('noRecords') }}
|
||||
</template>
|
||||
</VueMultiselect>
|
||||
<p v-show="onError" class="text-sm text-red-600">
|
||||
{{ onError }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<script setup>
|
||||
import DialogModal from '@/Components/Dashboard/DialogModal.vue';
|
||||
import SecondaryButton from '@/Components/Dashboard/Button/Secondary.vue';
|
||||
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'update'
|
||||
'update'
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
@ -26,7 +26,7 @@ const props = defineProps({
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="w-full right-0 mt-2">
|
||||
<div class="rounded overflow-hidden">
|
||||
<div class="rounded">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
@ -34,15 +34,15 @@ const props = defineProps({
|
||||
<template #footer>
|
||||
<div class="space-x-2">
|
||||
<slot name="buttons" />
|
||||
<SecondaryButton
|
||||
<SecondaryButton
|
||||
@click="$emit('update')"
|
||||
v-text="$t('update')"
|
||||
/>
|
||||
<SecondaryButton
|
||||
@click="$emit('close')"
|
||||
@click="$emit('close')"
|
||||
v-text="$t('cancel')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</DialogModal>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import SecondaryButton from '@/Components/Dashboard/Button/Secondary.vue';
|
||||
import DialogModal from '@/Components/Dashboard/DialogModal.vue';
|
||||
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'edit'
|
||||
@ -35,16 +35,16 @@ const props = defineProps({
|
||||
<template #footer>
|
||||
<div class="space-x-2">
|
||||
<slot name="buttons" />
|
||||
<SecondaryButton
|
||||
<SecondaryButton
|
||||
v-if="editable"
|
||||
@click="$emit('edit')"
|
||||
v-text="$t('update')"
|
||||
/>
|
||||
<SecondaryButton
|
||||
@click="$emit('close')"
|
||||
@click="$emit('close')"
|
||||
v-text="$t('close')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</DialogModal>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -1,257 +1,318 @@
|
||||
export default {
|
||||
'&':'y',
|
||||
account: {
|
||||
delete: {
|
||||
confirm:'¿Está seguro de que quiere eliminar su cuenta? Una vez eliminada su cuenta, todos sus recursos y datos se borrarán permanentemente. Por favor, introduzca su contraseña para confirmar que desea eliminar permanentemente su cuenta.',
|
||||
description:'Eliminar permanentemente su cuenta.',
|
||||
onDelete:'Una vez eliminada su cuenta, todos sus recursos y datos se borrarán permanentemente. Antes de eliminar su cuenta, descargue los datos o la información que desee conservar.',
|
||||
title:'Eliminar cuenta',
|
||||
},
|
||||
email: {
|
||||
notifySendVerification:'Se ha enviado un nuevo enlace de verificación a su dirección de correo electrónico.',
|
||||
sendVerification:'Haga clic aquí para volver a enviar el correo electrónico de verificación.',
|
||||
unverify: 'Su dirección de correo electrónico no está verificada.',
|
||||
},
|
||||
manage:'Administrar cuenta',
|
||||
password: {
|
||||
description:'Asegúrese de que su cuenta utiliza una contraseña larga y aleatoria para estar seguro.',
|
||||
new:'Nueva contraseña',
|
||||
reset:'Restaurar contraseña',
|
||||
secure:'Esta es una zona segura de la aplicación. Confirme su contraseña antes de continuar.',
|
||||
update: 'Actualizar contraseña',
|
||||
verify:'Por su seguridad, confirme su contraseña para continuar.',
|
||||
},
|
||||
profile: {
|
||||
description:'Actualice la información del perfil de su cuenta y su dirección de correo electrónico.',
|
||||
title:'Información del perfil',
|
||||
},
|
||||
sessions: {
|
||||
confirm:'Por favor, introduzca su contraseña para confirmar que desea salir de sus otras sesiones de navegación en todos sus dispositivos.',
|
||||
description: 'Gestiona y cierra tus sesiones activas en otros navegadores y dispositivos.',
|
||||
last:'Último activo',
|
||||
logout:'Cerrar otras sesiones del navegador',
|
||||
onLogout:'Si es necesario, puede cerrar la sesión de todos sus otros navegadores en todos sus dispositivos. A continuación se enumeran algunas de sus sesiones recientes; sin embargo, esta lista puede no ser exhaustiva. Si crees que tu cuenta ha sido comprometida, también deberías actualizar tu contraseña.',
|
||||
this: 'Dispositivo actual',
|
||||
title: 'Sesiones del navegador',
|
||||
},
|
||||
twoFactor: {
|
||||
codes:{
|
||||
regenerate:'Regenerar los códigos de recuperación',
|
||||
show:'Mostrar códigos de recuperación',
|
||||
store:'Guarde estos códigos de recuperación en un gestor de contraseñas seguro. Pueden utilizarse para recuperar el acceso a su cuenta si se pierde su dispositivo de autenticación de dos factores.',
|
||||
},
|
||||
description:'Añada seguridad adicional a su cuenta mediante la autenticación de dos factores.',
|
||||
isEnable:'Ha activado la autenticación de dos factores.',
|
||||
isNotEnable:{
|
||||
title:'No ha activado la autenticación de dos factores.',
|
||||
description:'Cuando la autenticación de dos factores está activada, se le pedirá un token seguro y aleatorio durante la autenticación. Puedes recuperar este token desde la aplicación Google Authenticator de tu teléfono.',
|
||||
},
|
||||
key:'Llave de configuración',
|
||||
login: {
|
||||
onAuth: 'Por favor, confirme el acceso a su cuenta introduciendo el código de autentificación proporcionado por su aplicación de autentificación.',
|
||||
onRecovery: 'Confirme el acceso a su cuenta introduciendo uno de sus códigos de recuperación de emergencia.',
|
||||
},
|
||||
onFinish:'Termina de habilitar la autenticación de dos factores.',
|
||||
qr: {
|
||||
isConfirmed: 'La autenticación de dos factores ya está activada. Escanee el siguiente código QR con la aplicación de autenticación de su teléfono o introduzca la clave de configuración.',
|
||||
onConfirmed: 'Para terminar de habilitar la autenticación de dos factores, escanea el siguiente código QR utilizando la aplicación de autenticación de tu teléfono o introduce la clave de configuración y proporciona el código OTP generado.',
|
||||
},
|
||||
recovery: {
|
||||
code: 'Código de recuperación',
|
||||
useAuth: 'Utilizar un código de autentificación',
|
||||
useCode: 'Utiliza un código de recuperación',
|
||||
},
|
||||
title:'Autenticación de dos factores',
|
||||
},
|
||||
"&": "y",
|
||||
account: {
|
||||
delete: {
|
||||
confirm:
|
||||
"¿Está seguro de que quiere eliminar su cuenta? Una vez eliminada su cuenta, todos sus recursos y datos se borrarán permanentemente. Por favor, introduzca su contraseña para confirmar que desea eliminar permanentemente su cuenta.",
|
||||
description: "Eliminar permanentemente su cuenta.",
|
||||
onDelete:
|
||||
"Una vez eliminada su cuenta, todos sus recursos y datos se borrarán permanentemente. Antes de eliminar su cuenta, descargue los datos o la información que desee conservar.",
|
||||
title: "Eliminar cuenta",
|
||||
},
|
||||
actions:'Acciones',
|
||||
auth: {
|
||||
forgotPassword: {
|
||||
ask: '¿Olvidaste tu contraseña?',
|
||||
description: '¿Ha olvidado su contraseña? No hay problema. Sólo tienes que indicarnos tu dirección de correo electrónico y te enviaremos un enlace para restablecer la contraseña que te permitirá elegir una nueva.',
|
||||
sendLink: 'Enviar enlace de recuperación por correo',
|
||||
title: 'Contraseña olvidada',
|
||||
},
|
||||
login: 'Iniciar sesión',
|
||||
logout: 'Cerrar sesión',
|
||||
register: {
|
||||
already: '¿Ya estas registrado?',
|
||||
me: 'Registrarme',
|
||||
},
|
||||
remember: 'Recuerdame',
|
||||
email: {
|
||||
notifySendVerification:
|
||||
"Se ha enviado un nuevo enlace de verificación a su dirección de correo electrónico.",
|
||||
sendVerification:
|
||||
"Haga clic aquí para volver a enviar el correo electrónico de verificación.",
|
||||
unverify: "Su dirección de correo electrónico no está verificada.",
|
||||
},
|
||||
code:'Código',
|
||||
cancel:'Cancelar',
|
||||
changes:'Cambios',
|
||||
changelogs: {
|
||||
title:'Historial de cambios',
|
||||
description: 'Lista de los cambios realizados al sistema.',
|
||||
manage: "Administrar cuenta",
|
||||
password: {
|
||||
description:
|
||||
"Asegúrese de que su cuenta utiliza una contraseña larga y aleatoria para estar seguro.",
|
||||
new: "Nueva contraseña",
|
||||
reset: "Restaurar contraseña",
|
||||
secure:
|
||||
"Esta es una zona segura de la aplicación. Confirme su contraseña antes de continuar.",
|
||||
update: "Actualizar contraseña",
|
||||
verify: "Por su seguridad, confirme su contraseña para continuar.",
|
||||
},
|
||||
close:"Cerrar",
|
||||
confirm:'Confirmar',
|
||||
copyright:'Todos los derechos reservados.',
|
||||
contact:'Contacto',
|
||||
crud: {
|
||||
create: 'Nuevo registro',
|
||||
edit: 'Editar registro',
|
||||
destroy: 'Eliminar registro',
|
||||
show: 'Más detalles',
|
||||
profile: {
|
||||
description:
|
||||
"Actualice la información del perfil de su cuenta y su dirección de correo electrónico.",
|
||||
title: "Información del perfil",
|
||||
},
|
||||
date: 'Fecha',
|
||||
delete:{
|
||||
confirm: 'Al presionar ELIMINAR el registro se eliminará permanentemente y no podrá recuperarse.',
|
||||
title: 'Eliminar',
|
||||
sessions: {
|
||||
confirm:
|
||||
"Por favor, introduzca su contraseña para confirmar que desea salir de sus otras sesiones de navegación en todos sus dispositivos.",
|
||||
description:
|
||||
"Gestiona y cierra tus sesiones activas en otros navegadores y dispositivos.",
|
||||
last: "Último activo",
|
||||
logout: "Cerrar otras sesiones del navegador",
|
||||
onLogout:
|
||||
"Si es necesario, puede cerrar la sesión de todos sus otros navegadores en todos sus dispositivos. A continuación se enumeran algunas de sus sesiones recientes; sin embargo, esta lista puede no ser exhaustiva. Si crees que tu cuenta ha sido comprometida, también deberías actualizar tu contraseña.",
|
||||
this: "Dispositivo actual",
|
||||
title: "Sesiones del navegador",
|
||||
},
|
||||
deleted:'Eliminado',
|
||||
description:'Descripción',
|
||||
details:'Detalles',
|
||||
disable:'Deshabilitar',
|
||||
disabled:'Deshabilitado',
|
||||
done:'Hecho.',
|
||||
edit:'Editar',
|
||||
email:{
|
||||
title:'Correo',
|
||||
verification:'Verificar correo'
|
||||
},
|
||||
enable:'Habilitar',
|
||||
endDate:'Fecha Fin',
|
||||
event:'Evento',
|
||||
help: {
|
||||
description:'A continuación se lista la iconografía para entender el funcionamiento del sistema.',
|
||||
home: 'Volver a la pagina de inicio.',
|
||||
title:'Ayuda',
|
||||
},
|
||||
history: {
|
||||
title:'Historial de acciones',
|
||||
description:'Historial de acciones realizadas por los usuarios en orden cronológico.'
|
||||
},
|
||||
home:'Inicio',
|
||||
hour:'Hora',
|
||||
icon:'Icono',
|
||||
maternal:'Apellido materno',
|
||||
menu:'Menú',
|
||||
name:'Nombre',
|
||||
noRecords:'Sin registros',
|
||||
notifications: {
|
||||
readed:'Marcar como leído',
|
||||
deleted:'Notificación eliminada',
|
||||
description:'Notificaciones del usuario',
|
||||
notFound:'Notificación no encontrada',
|
||||
title:'Notificaciones',
|
||||
},
|
||||
password:'Contraseña',
|
||||
passwordConfirmation:'Confirmar contraseña',
|
||||
passwordCurrent:'Contraseña actual',
|
||||
passwordReset:'Restaurar contraseña',
|
||||
paternal:'Apellido paterno',
|
||||
phone:'Teléfono',
|
||||
photo: {
|
||||
new: 'Seleccionar una nueva foto',
|
||||
remove:'Remover foto',
|
||||
title:'Foto',
|
||||
},
|
||||
profile:'Perfil',
|
||||
readed:'Leído',
|
||||
register: {
|
||||
agree:'Estoy de acuerdo con los',
|
||||
privacy:'Política de Privacidad',
|
||||
signUp:'Registrarme',
|
||||
terms:'Términos de Servicio',
|
||||
},
|
||||
registers:{
|
||||
title:'Registros',
|
||||
empty:'Sin registros',
|
||||
},
|
||||
remove: 'Remover',
|
||||
return: 'Regresar',
|
||||
role:'Rol',
|
||||
roles:{
|
||||
create: {
|
||||
title: 'Crear rol',
|
||||
description: 'Estos roles serán usados para dar permisos en el sistema.',
|
||||
onSuccess: 'Rol creado exitosamente',
|
||||
onError: 'Error al crear el role',
|
||||
},
|
||||
deleted:'Rol eliminado',
|
||||
title: 'Roles',
|
||||
},
|
||||
save:'Guardar',
|
||||
saved:'¡Guardado!',
|
||||
search:'Buscar',
|
||||
selected: 'Seleccionado',
|
||||
select: 'Seleccionar',
|
||||
setting: 'Configuración',
|
||||
show: {
|
||||
all:'Mostrar todo',
|
||||
title:'Mostrar',
|
||||
},
|
||||
startDate:'Fecha de inicio',
|
||||
status:'Estado',
|
||||
terms: {
|
||||
agree:'Estoy de acuerdo con los',
|
||||
privacy:'Política de privacidad',
|
||||
service:'Términos de servicio',
|
||||
},
|
||||
unknown:'Desconocido',
|
||||
update:'Actualizar',
|
||||
updated:'Actualizado',
|
||||
updateFail:'Error al actualizar',
|
||||
unreaded:'No leído',
|
||||
user:'Usuario',
|
||||
users:{
|
||||
create:{
|
||||
title:'Crear usuario',
|
||||
description:'Permite crear nuevos usuarios. No olvides otorgarle roles para que pueda acceder a las partes del sistema deseados.',
|
||||
onSuccess:'Usuario creado',
|
||||
onError:'Ocurrió un error al crear el usuario'
|
||||
},
|
||||
deleted:'Usuario eliminado',
|
||||
notFount:'Usuario no encontrado',
|
||||
password: {
|
||||
description:'Permite actualizar las contraseñas de los usuarios sobreescribiendola.',
|
||||
title:'Actualizar contraseña',
|
||||
},
|
||||
roles: {
|
||||
description:'Actualiza los roles de los usuarios, permitiendo o denegando los accesos a determinadas áreas.',
|
||||
error:{
|
||||
min:'Seleccionar mínimo un role'
|
||||
},
|
||||
title:'Roles de usuario',
|
||||
},
|
||||
menu:'Menú de usuario',
|
||||
select:'Seleccionar un usuario',
|
||||
settings:'Ajustes del usuario',
|
||||
system:'Usuarios del sistema',
|
||||
title:'Usuarios',
|
||||
},
|
||||
|
||||
scores:{
|
||||
system: 'Sistema de puntuación',
|
||||
create:{
|
||||
title:'Crear puntuación',
|
||||
description:'Permite crear nuevas puntuaciones para los usuarios.',
|
||||
onSuccess:'Puntuación creada exitosamente',
|
||||
onError:'Error al crear la puntuación',
|
||||
}
|
||||
},
|
||||
department:{
|
||||
system: 'Sistema de departamentos',
|
||||
title: 'Departamentos',
|
||||
create:{
|
||||
title:'Crear departamento',
|
||||
description:'Permite crear nuevos departamentos para los usuarios.',
|
||||
onSuccess:'Departamento creado exitosamente',
|
||||
onError:'Error al crear el departamento',
|
||||
}
|
||||
},
|
||||
mainRole: {
|
||||
system: 'Sistema de roles principales',
|
||||
create:{
|
||||
title:'Crear rol principal',
|
||||
description:'Permite crear nuevos roles principales para los usuarios.',
|
||||
onSuccess:'Rol principal creado exitosamente',
|
||||
onError:'Error al crear el rol principal',
|
||||
twoFactor: {
|
||||
codes: {
|
||||
regenerate: "Regenerar los códigos de recuperación",
|
||||
show: "Mostrar códigos de recuperación",
|
||||
store:
|
||||
"Guarde estos códigos de recuperación en un gestor de contraseñas seguro. Pueden utilizarse para recuperar el acceso a su cuenta si se pierde su dispositivo de autenticación de dos factores.",
|
||||
},
|
||||
description:
|
||||
"Añada seguridad adicional a su cuenta mediante la autenticación de dos factores.",
|
||||
isEnable: "Ha activado la autenticación de dos factores.",
|
||||
isNotEnable: {
|
||||
title: "No ha activado la autenticación de dos factores.",
|
||||
description:
|
||||
"Cuando la autenticación de dos factores está activada, se le pedirá un token seguro y aleatorio durante la autenticación. Puedes recuperar este token desde la aplicación Google Authenticator de tu teléfono.",
|
||||
},
|
||||
key: "Llave de configuración",
|
||||
login: {
|
||||
onAuth:
|
||||
"Por favor, confirme el acceso a su cuenta introduciendo el código de autentificación proporcionado por su aplicación de autentificación.",
|
||||
onRecovery:
|
||||
"Confirme el acceso a su cuenta introduciendo uno de sus códigos de recuperación de emergencia.",
|
||||
},
|
||||
onFinish: "Termina de habilitar la autenticación de dos factores.",
|
||||
qr: {
|
||||
isConfirmed:
|
||||
"La autenticación de dos factores ya está activada. Escanee el siguiente código QR con la aplicación de autenticación de su teléfono o introduzca la clave de configuración.",
|
||||
onConfirmed:
|
||||
"Para terminar de habilitar la autenticación de dos factores, escanea el siguiente código QR utilizando la aplicación de autenticación de tu teléfono o introduce la clave de configuración y proporciona el código OTP generado.",
|
||||
},
|
||||
recovery: {
|
||||
code: "Código de recuperación",
|
||||
useAuth: "Utilizar un código de autentificación",
|
||||
useCode: "Utiliza un código de recuperación",
|
||||
},
|
||||
title: "Autenticación de dos factores",
|
||||
},
|
||||
version:'Versión',
|
||||
}
|
||||
},
|
||||
actions: "Acciones",
|
||||
auth: {
|
||||
forgotPassword: {
|
||||
ask: "¿Olvidaste tu contraseña?",
|
||||
description:
|
||||
"¿Ha olvidado su contraseña? No hay problema. Sólo tienes que indicarnos tu dirección de correo electrónico y te enviaremos un enlace para restablecer la contraseña que te permitirá elegir una nueva.",
|
||||
sendLink: "Enviar enlace de recuperación por correo",
|
||||
title: "Contraseña olvidada",
|
||||
},
|
||||
login: "Iniciar sesión",
|
||||
logout: "Cerrar sesión",
|
||||
register: {
|
||||
already: "¿Ya estas registrado?",
|
||||
me: "Registrarme",
|
||||
},
|
||||
remember: "Recuerdame",
|
||||
},
|
||||
code: "Código",
|
||||
cancel: "Cancelar",
|
||||
changes: "Cambios",
|
||||
changelogs: {
|
||||
title: "Historial de cambios",
|
||||
description: "Lista de los cambios realizados al sistema.",
|
||||
},
|
||||
close: "Cerrar",
|
||||
confirm: "Confirmar",
|
||||
copyright: "Todos los derechos reservados.",
|
||||
contact: "Contacto",
|
||||
crud: {
|
||||
create: "Nuevo registro",
|
||||
edit: "Editar registro",
|
||||
destroy: "Eliminar registro",
|
||||
show: "Más detalles",
|
||||
},
|
||||
date: "Fecha",
|
||||
delete: {
|
||||
confirm:
|
||||
"Al presionar ELIMINAR el registro se eliminará permanentemente y no podrá recuperarse.",
|
||||
title: "Eliminar",
|
||||
},
|
||||
deleted: "Eliminado",
|
||||
description: "Descripción",
|
||||
details: "Detalles",
|
||||
disable: "Deshabilitar",
|
||||
disabled: "Deshabilitado",
|
||||
done: "Hecho.",
|
||||
edit: "Editar",
|
||||
email: {
|
||||
title: "Correo",
|
||||
verification: "Verificar correo",
|
||||
},
|
||||
enable: "Habilitar",
|
||||
endDate: "Fecha Fin",
|
||||
event: "Evento",
|
||||
help: {
|
||||
description:
|
||||
"A continuación se lista la iconografía para entender el funcionamiento del sistema.",
|
||||
home: "Volver a la pagina de inicio.",
|
||||
title: "Ayuda",
|
||||
},
|
||||
history: {
|
||||
title: "Historial de acciones",
|
||||
description:
|
||||
"Historial de acciones realizadas por los usuarios en orden cronológico.",
|
||||
},
|
||||
home: "Inicio",
|
||||
hour: "Hora",
|
||||
icon: "Icono",
|
||||
maternal: "Apellido materno",
|
||||
menu: "Menú",
|
||||
name: "Nombre",
|
||||
noRecords: "Sin registros",
|
||||
notifications: {
|
||||
readed: "Marcar como leído",
|
||||
deleted: "Notificación eliminada",
|
||||
description: "Notificaciones del usuario",
|
||||
notFound: "Notificación no encontrada",
|
||||
title: "Notificaciones",
|
||||
},
|
||||
password: "Contraseña",
|
||||
passwordConfirmation: "Confirmar contraseña",
|
||||
passwordCurrent: "Contraseña actual",
|
||||
passwordReset: "Restaurar contraseña",
|
||||
paternal: "Apellido paterno",
|
||||
phone: "Teléfono",
|
||||
photo: {
|
||||
new: "Seleccionar una nueva foto",
|
||||
remove: "Remover foto",
|
||||
title: "Foto",
|
||||
},
|
||||
profile: "Perfil",
|
||||
readed: "Leído",
|
||||
register: {
|
||||
agree: "Estoy de acuerdo con los",
|
||||
privacy: "Política de Privacidad",
|
||||
signUp: "Registrarme",
|
||||
terms: "Términos de Servicio",
|
||||
},
|
||||
registers: {
|
||||
title: "Registros",
|
||||
empty: "Sin registros",
|
||||
},
|
||||
remove: "Remover",
|
||||
return: "Regresar",
|
||||
role: "Rol",
|
||||
roles: {
|
||||
create: {
|
||||
title: "Crear rol",
|
||||
description: "Estos roles serán usados para dar permisos en el sistema.",
|
||||
onSuccess: "Rol creado exitosamente",
|
||||
onError: "Error al crear el role",
|
||||
},
|
||||
deleted: "Rol eliminado",
|
||||
title: "Roles",
|
||||
},
|
||||
save: "Guardar",
|
||||
saved: "¡Guardado!",
|
||||
search: "Buscar",
|
||||
selected: "Seleccionado",
|
||||
select: "Seleccionar",
|
||||
setting: "Configuración",
|
||||
show: {
|
||||
all: "Mostrar todo",
|
||||
title: "Mostrar",
|
||||
},
|
||||
startDate: "Fecha de inicio",
|
||||
status: "Estado",
|
||||
terms: {
|
||||
agree: "Estoy de acuerdo con los",
|
||||
privacy: "Política de privacidad",
|
||||
service: "Términos de servicio",
|
||||
},
|
||||
unknown: "Desconocido",
|
||||
update: "Actualizar",
|
||||
updated: "Actualizado",
|
||||
updateFail: "Error al actualizar",
|
||||
unreaded: "No leído",
|
||||
user: "Usuario",
|
||||
users: {
|
||||
create: {
|
||||
title: "Crear usuario",
|
||||
description:
|
||||
"Permite crear nuevos usuarios. No olvides otorgarle roles para que pueda acceder a las partes del sistema deseados.",
|
||||
onSuccess: "Usuario creado",
|
||||
onError: "Ocurrió un error al crear el usuario",
|
||||
},
|
||||
deleted: "Usuario eliminado",
|
||||
notFount: "Usuario no encontrado",
|
||||
password: {
|
||||
description:
|
||||
"Permite actualizar las contraseñas de los usuarios sobreescribiendola.",
|
||||
title: "Actualizar contraseña",
|
||||
},
|
||||
roles: {
|
||||
description:
|
||||
"Actualiza los roles de los usuarios, permitiendo o denegando los accesos a determinadas áreas.",
|
||||
error: {
|
||||
min: "Seleccionar mínimo un role",
|
||||
},
|
||||
title: "Roles de usuario",
|
||||
},
|
||||
menu: "Menú de usuario",
|
||||
select: "Seleccionar un usuario",
|
||||
settings: "Ajustes del usuario",
|
||||
system: "Usuarios del sistema",
|
||||
title: "Usuarios",
|
||||
},
|
||||
|
||||
scores: {
|
||||
system: "Sistema de puntuación",
|
||||
title: "Puntuaciones",
|
||||
create: {
|
||||
title: "Crear puntuación",
|
||||
description: "Permite crear nuevas puntuaciones para los usuarios.",
|
||||
onSuccess: "Puntuación creada exitosamente",
|
||||
onError: "Error al crear la puntuación",
|
||||
},
|
||||
},
|
||||
department: {
|
||||
system: "Sistema de departamentos",
|
||||
title: "Departamentos",
|
||||
create: {
|
||||
title: "Crear departamento",
|
||||
description: "Permite crear nuevos departamentos para los usuarios.",
|
||||
onSuccess: "Departamento creado exitosamente",
|
||||
onError: "Error al crear el departamento",
|
||||
},
|
||||
select:{
|
||||
title: "Seleccionar un departamento",
|
||||
description: "Seleccione un departamento para filtrar los roles.",
|
||||
}
|
||||
},
|
||||
mainRole: {
|
||||
title: "Roles principales",
|
||||
inDepartment: "Roles principales en el departamento",
|
||||
system: "Sistema de roles principales",
|
||||
select:{
|
||||
description: "Seleccione un rol principal.",
|
||||
},
|
||||
create: {
|
||||
title: "Crear rol principal",
|
||||
description: "Permite crear nuevos roles principales para los usuarios.",
|
||||
onSuccess: "Rol principal creado exitosamente",
|
||||
onError: "Error al crear el rol principal",
|
||||
},
|
||||
},
|
||||
skill: {
|
||||
title: "Habilidades",
|
||||
assignTo: "Asignar a rol principal",
|
||||
system: "Sistema de habilidades",
|
||||
assignment: {
|
||||
title: "Habilidades del Rol",
|
||||
description: "Asigna una habilidad a un rol principal.",
|
||||
},
|
||||
create: {
|
||||
title: "Crear habilidad",
|
||||
description:
|
||||
"Permite crear nuevas habilidades para los roles principales.",
|
||||
onSuccess: "Habilidad creada exitosamente",
|
||||
onError: "Error al crear la habilidad",
|
||||
},
|
||||
deleted: "Habilidad eliminada",
|
||||
},
|
||||
mainRoleSkills: {
|
||||
system: "Sistema de habilidades de rol principal",
|
||||
create: {
|
||||
title: "Crear habilidad de rol principal",
|
||||
description:
|
||||
"Permite crear nuevas habilidades para los roles principales.",
|
||||
onSuccess: "Habilidad de rol principal creada exitosamente",
|
||||
onError: "Error al crear la habilidad de rol principal",
|
||||
},
|
||||
},
|
||||
version: "Versión",
|
||||
};
|
||||
|
||||
@ -85,11 +85,21 @@ onMounted(()=> {
|
||||
name="Rol Principal"
|
||||
to="admin.mainRoles.index"
|
||||
/>
|
||||
<Link
|
||||
icon="psychology"
|
||||
name="Habilidades"
|
||||
to="admin.skills.index"
|
||||
/>
|
||||
<Link
|
||||
icon="leaderboard"
|
||||
name="Scores"
|
||||
to="admin.scores.index"
|
||||
/>
|
||||
<Link
|
||||
icon="sports_handball"
|
||||
name="Roles Puntuados"
|
||||
to="admin.mainRoleSkills.index"
|
||||
/>
|
||||
<Link
|
||||
icon="history"
|
||||
name="changelogs.title"
|
||||
|
||||
@ -65,7 +65,7 @@ const submit = () => form.post(route(goTo('store')), {
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descrición"
|
||||
id="Descripción"
|
||||
class="col-span-2"
|
||||
v-model="form.description"
|
||||
:onError="form.errors.description"
|
||||
|
||||
@ -1,73 +1,64 @@
|
||||
<script setup>
|
||||
import { goTo } from './Component';
|
||||
import { useForm } from '@inertiajs/vue3';
|
||||
import { onUpdated } from 'vue';
|
||||
import { goTo } from "./Component";
|
||||
import { useForm } from "@inertiajs/vue3";
|
||||
import { onUpdated } from "vue";
|
||||
|
||||
import Input from '@/Components/Dashboard/Form/Input.vue';
|
||||
import EditModal from '@/Components/Dashboard/Modal/Edit.vue';
|
||||
import Header from '@/Components/Dashboard/Modal/Elements/Header.vue';
|
||||
import Input from "@/Components/Dashboard/Form/Input.vue";
|
||||
import EditModal from "@/Components/Dashboard/Modal/Edit.vue";
|
||||
import Header from "@/Components/Dashboard/Modal/Elements/Header.vue";
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'switchModal'
|
||||
]);
|
||||
const emit = defineEmits(["close", "switchModal"]);
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
model: Object
|
||||
show: Boolean,
|
||||
model: Object,
|
||||
});
|
||||
|
||||
const form = useForm({});
|
||||
|
||||
const update = (id) => {
|
||||
form.transform(data => ({
|
||||
...props.model
|
||||
})).put(route(goTo('update'), {id}),{
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
Notify.success(lang('updated'))
|
||||
emit('switchModal')
|
||||
}
|
||||
form
|
||||
.transform((data) => ({
|
||||
...props.model,
|
||||
}))
|
||||
.put(route(goTo("update"), { id }), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
Notify.success(lang("updated"));
|
||||
emit("switchModal");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<EditModal
|
||||
:show="show"
|
||||
@close="$emit('close')"
|
||||
@update="update(model.id)"
|
||||
>
|
||||
<Header
|
||||
:title="model.alias"
|
||||
/>
|
||||
<div class="py-2 border-b">
|
||||
<div class="p-4">
|
||||
<form>
|
||||
<div class="grid gap-6 mb-6 lg:grid-cols-2">
|
||||
<Input
|
||||
id="Alias"
|
||||
placeholder="Alias"
|
||||
v-model="model.alias"
|
||||
:onError="form.errors.alias"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Valor"
|
||||
v-model="model.value"
|
||||
:onError="form.errors.value"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descripción"
|
||||
v-model="model.description"
|
||||
:onError="form.errors.description"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</EditModal>
|
||||
<EditModal :show="show" @close="$emit('close')" @update="update(model.id)">
|
||||
<Header :title="model.alias" />
|
||||
<div class="py-2 border-b">
|
||||
<div class="p-4">
|
||||
<form>
|
||||
<div class="grid gap-6 mb-6 lg:grid-cols-2">
|
||||
<Input
|
||||
id="Alias"
|
||||
placeholder="Alias"
|
||||
v-model="model.alias"
|
||||
:onError="form.errors.alias"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Valor"
|
||||
v-model="model.value"
|
||||
:onError="form.errors.value"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descripción"
|
||||
v-model="model.description"
|
||||
:onError="form.errors.description"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</EditModal>
|
||||
</template>
|
||||
|
||||
@ -54,7 +54,7 @@ const submit = () => form.post(route(goTo('store')), {
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descrición"
|
||||
id="Descripción"
|
||||
class="col-span-2"
|
||||
v-model="form.description"
|
||||
:onError="form.errors.description"
|
||||
|
||||
@ -17,7 +17,6 @@ import ShowView from './Show.vue';
|
||||
const props = defineProps({
|
||||
departments: Object
|
||||
});
|
||||
|
||||
// Controladores
|
||||
const Modal = new ModalController();
|
||||
const Searcher = new SearcherController(goTo('index'));
|
||||
|
||||
@ -59,7 +59,7 @@ const submit = () =>
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descrición"
|
||||
id="Descripción"
|
||||
class="col-span-2"
|
||||
v-model="form.description"
|
||||
:onError="form.errors.description"
|
||||
|
||||
15
resources/js/Pages/Admin/MainRoleSkills/Component.js
Normal file
15
resources/js/Pages/Admin/MainRoleSkills/Component.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { t } from '@/Lang/i18n';
|
||||
import { hasPermission } from '@/rolePermission.js';
|
||||
|
||||
// Obtener ruta
|
||||
const goTo = (route) => `admin.mainRoleSkills.${route}`
|
||||
// Obtener traducción del componente
|
||||
const transl = (lang) => t(`mainRoleSkills.${lang}`)
|
||||
// Determina si un usuario puede hacer algo no en base a los permisos
|
||||
const can = (permission) => hasPermission(`users.${permission}`)
|
||||
|
||||
export{
|
||||
can,
|
||||
goTo,
|
||||
transl
|
||||
}
|
||||
169
resources/js/Pages/Admin/MainRoleSkills/Create.vue
Normal file
169
resources/js/Pages/Admin/MainRoleSkills/Create.vue
Normal file
@ -0,0 +1,169 @@
|
||||
<script setup>
|
||||
import { goTo, transl } from "./Component";
|
||||
import { Link, useForm } from "@inertiajs/vue3";
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
|
||||
import PageHeader from "@/Components/Dashboard/PageHeader.vue";
|
||||
import GoogleIcon from "@/Components/Shared/GoogleIcon.vue";
|
||||
import DashboardLayout from "@/Layouts/DashboardLayout.vue";
|
||||
import DepartmentSelector from "@/Components/App/DepartmentSelector.vue";
|
||||
import MainRoleSelector from "@/Components/App/MainRoleSelector.vue";
|
||||
import SkillAssignment from "@/Components/App/SkillAssignment.vue";
|
||||
|
||||
const props = defineProps({
|
||||
mainRoles: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
skills: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
scores: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
selectedRole: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
selectedDepartment: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
|
||||
const selectedDepartment = ref(props.selectedDepartment);
|
||||
const selectedMainRole = ref(props.selectedRole);
|
||||
|
||||
const form = useForm({
|
||||
main_role_id: props.selectedRole?.id || '',
|
||||
skills: []
|
||||
});
|
||||
|
||||
// Obtener departamentos únicos
|
||||
const departments = computed(() => {
|
||||
const uniqueDepartments = [];
|
||||
const seenIds = new Set();
|
||||
|
||||
props.mainRoles.forEach(role => {
|
||||
if (role.department && !seenIds.has(role.department.id)) {
|
||||
seenIds.add(role.department.id);
|
||||
uniqueDepartments.push(role.department);
|
||||
}
|
||||
});
|
||||
|
||||
return uniqueDepartments;
|
||||
});
|
||||
|
||||
// Filtrar habilidades por departamento seleccionado
|
||||
const departmentSkills = computed(() => {
|
||||
if (!selectedDepartment.value) return [];
|
||||
return props.skills.filter(skill =>
|
||||
skill.department_id === selectedDepartment.value.id
|
||||
);
|
||||
});
|
||||
|
||||
const handleDepartmentSelect = (department) => {
|
||||
selectedDepartment.value = department;
|
||||
selectedMainRole.value = null;
|
||||
form.main_role_id = '';
|
||||
};
|
||||
|
||||
const handleRoleSelect = (role) => {
|
||||
selectedMainRole.value = role;
|
||||
form.main_role_id = role.id;
|
||||
};
|
||||
|
||||
const submit = (skillsData) => {
|
||||
form.skills = skillsData;
|
||||
|
||||
form.post(route(goTo("store")), {
|
||||
onSuccess: () => {
|
||||
// Redireccionar al index
|
||||
},
|
||||
onError: () => {
|
||||
// Mostrar mensaje de error
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const goBack = () => {
|
||||
if (selectedMainRole.value) {
|
||||
selectedMainRole.value = null;
|
||||
form.main_role_id = '';
|
||||
} else if (selectedDepartment.value) {
|
||||
selectedDepartment.value = null;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// Si tenemos rol seleccionado, asegurar que el departamento también esté seleccionado
|
||||
if (props.selectedRole && props.selectedRole.department) {
|
||||
selectedDepartment.value = props.selectedRole.department;
|
||||
selectedMainRole.value = props.selectedRole;
|
||||
form.main_role_id = props.selectedRole.id;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardLayout :title="transl('create.title')">
|
||||
<PageHeader>
|
||||
<Link :href="route(goTo('index'))">
|
||||
<GoogleIcon
|
||||
:title="$t('return')"
|
||||
class="btn-icon-primary"
|
||||
name="arrow_back"
|
||||
outline
|
||||
/>
|
||||
</Link>
|
||||
</PageHeader>
|
||||
|
||||
<div class="w-full pb-8">
|
||||
<div class="mt-8">
|
||||
<p v-text="transl('create.description')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
<!-- Navegación hacia atrás -->
|
||||
<div v-if="selectedDepartment || selectedMainRole" class="mb-6">
|
||||
<button
|
||||
@click="goBack"
|
||||
class="text-primary hover:underline flex items-center gap-2"
|
||||
>
|
||||
<GoogleIcon name="arrow_back" class="w-4 h-4" />
|
||||
<span v-if="selectedMainRole">Cambiar rol principal</span>
|
||||
<span v-else-if="selectedDepartment">Cambiar departamento</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Paso 1: Selector de Departamento -->
|
||||
<DepartmentSelector
|
||||
v-if="!selectedDepartment"
|
||||
:departments="departments"
|
||||
@select="handleDepartmentSelect"
|
||||
/>
|
||||
|
||||
<!-- Paso 2: Selector de Rol Principal -->
|
||||
<MainRoleSelector
|
||||
v-else-if="selectedDepartment && !selectedMainRole"
|
||||
:selectedDepartment="selectedDepartment"
|
||||
:mainRoles="mainRoles"
|
||||
@select="handleRoleSelect"
|
||||
/>
|
||||
|
||||
<!-- Paso 3: Asignación de Habilidades -->
|
||||
<SkillAssignment
|
||||
v-else-if="selectedDepartment && selectedMainRole"
|
||||
:form="form"
|
||||
:skills="departmentSkills"
|
||||
:scores="scores"
|
||||
:selectedDepartment="selectedDepartment"
|
||||
:selectedMainRole="selectedMainRole"
|
||||
@submit="submit"
|
||||
/>
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
42
resources/js/Pages/Admin/MainRoleSkills/Destroy.vue
Normal file
42
resources/js/Pages/Admin/MainRoleSkills/Destroy.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<script setup>
|
||||
import { transl, goTo } from './Component'
|
||||
import { router } from '@inertiajs/vue3';
|
||||
|
||||
import DestroyModal from '@/Components/Dashboard/Modal/Destroy.vue';
|
||||
import Header from '@/Components/Dashboard/Modal/Elements/Header.vue';
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'switchModal'
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
model: Object
|
||||
});
|
||||
|
||||
const destroy = (id) => router.delete(route(goTo('destroy'), {id}), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
props.model.pop;
|
||||
Notify.success(transl('deleted'));
|
||||
emit('close');
|
||||
},
|
||||
onError: () => {
|
||||
Notify.info(transl('notFound'));
|
||||
emit('close');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DestroyModal
|
||||
:show="show"
|
||||
@close="$emit('close')"
|
||||
@destroy="destroy(model.id)"
|
||||
>
|
||||
<Header
|
||||
:title="model.skill.name"
|
||||
/>
|
||||
</DestroyModal>
|
||||
</template>
|
||||
87
resources/js/Pages/Admin/MainRoleSkills/Edit.vue
Normal file
87
resources/js/Pages/Admin/MainRoleSkills/Edit.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<script setup>
|
||||
import { goTo } from "./Component";
|
||||
import { router, useForm } from "@inertiajs/vue3";
|
||||
|
||||
import Selectable from "@/Components/Dashboard/Form/Selectable.vue";
|
||||
import EditModal from "@/Components/Dashboard/Modal/Edit.vue";
|
||||
import Header from "@/Components/Dashboard/Modal/Elements/Header.vue";
|
||||
|
||||
const emit = defineEmits(["close", "switchModal"]);
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
model: Object,
|
||||
scores: Array,
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
scored_id: "",
|
||||
});
|
||||
|
||||
const update = (id) => {
|
||||
form
|
||||
.transform((data) => ({
|
||||
scored_id:
|
||||
typeof data.scored_id === "object" ? data.scored_id.id : data.scored_id,
|
||||
}))
|
||||
.put(route(goTo("update"), { id }), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
Notify.success(lang("updated"));
|
||||
emit("switchModal");
|
||||
router.reload();
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<EditModal :show="show" @close="$emit('close')" @update="update(model.id)">
|
||||
<Header :title="model.main_role?.name" />
|
||||
<div class="py-2 border-b">
|
||||
<div class="p-4">
|
||||
<form>
|
||||
<div class="grid gap-6 mb-6 overflow-auto">
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<h4 class="bg-gray-50 text-gray-700 mb-2 font-medium">
|
||||
Información:
|
||||
</h4>
|
||||
<div class="text-sm text-gray-600 space-y-1">
|
||||
<p>
|
||||
<span class="font-medium">Rol: </span
|
||||
>{{ model.main_role?.name }}
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-medium">Departamento: </span>
|
||||
{{ model.main_role?.department?.name }}
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-medium">Habilidad: </span
|
||||
>{{ model.skill?.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Cambiar Puntuación
|
||||
</label>
|
||||
<Selectable
|
||||
id="scored_id"
|
||||
v-model="form.scored_id"
|
||||
:options="scores"
|
||||
:onError="form.errors.scored_id"
|
||||
label="alias"
|
||||
track-by="id"
|
||||
required
|
||||
/>
|
||||
<p class="text-xs text-gray-500 mt-1">
|
||||
Puntuación actual:
|
||||
<span class="font-medium"> {{ model.score?.alias }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</EditModal>
|
||||
</template>
|
||||
92
resources/js/Pages/Admin/MainRoleSkills/Index.vue
Normal file
92
resources/js/Pages/Admin/MainRoleSkills/Index.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<script setup>
|
||||
import { transl } from "./Component";
|
||||
import { ref, computed } from "vue";
|
||||
|
||||
import DashboardLayout from "@/Layouts/DashboardLayout.vue";
|
||||
import DepartmentSelector from "@/Components/App/DepartmentSelector.vue";
|
||||
import MainRoleSelector from "@/Components/App/MainRoleSelector.vue";
|
||||
import SkillRole from "@/Components/App/SkillsRole.vue";
|
||||
import PageHeader from "@/Components/Dashboard/PageHeader.vue";
|
||||
import GoogleIcon from "@/Components/Shared/GoogleIcon.vue";
|
||||
|
||||
defineEmits(["select"]);
|
||||
|
||||
const props = defineProps({
|
||||
mainRoleSkills: Object,
|
||||
departments: Object,
|
||||
mainRoles: Object,
|
||||
skills: Object,
|
||||
scores: Object,
|
||||
});
|
||||
|
||||
const selectedDepartment = ref(null);
|
||||
const selectedRole = ref(null);
|
||||
|
||||
const filteredMainRoleSkills = computed(() => {
|
||||
if (!props.mainRoleSkills?.data || !selectedRole.value) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return props.mainRoleSkills.data.filter(roleSkill =>
|
||||
roleSkill.main_role_id === selectedRole.value.id
|
||||
);
|
||||
});
|
||||
|
||||
const handleDepartmentSelect = (department) => {
|
||||
selectedDepartment.value = department;
|
||||
selectedRole.value= null;
|
||||
};
|
||||
const handleRoleSelect = (role) => {
|
||||
selectedRole.value = role;
|
||||
};
|
||||
|
||||
const handleSkillSelect = (roleSkill) => {
|
||||
console.log('Habilidad de rol seleccionada:', roleSkill);
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
if (selectedRole.value) {
|
||||
selectedRole.value = null;
|
||||
} else if (selectedDepartment.value) {
|
||||
selectedDepartment.value = null;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardLayout :title="transl('system')">
|
||||
<PageHeader>
|
||||
<button @click="goBack">
|
||||
<GoogleIcon
|
||||
:title="$t('return')"
|
||||
class="btn-icon-primary"
|
||||
name="arrow_back"
|
||||
outline
|
||||
/>
|
||||
</button>
|
||||
</PageHeader>
|
||||
|
||||
<!-- Selector de Departamento -->
|
||||
<DepartmentSelector
|
||||
v-if="!selectedDepartment"
|
||||
:departments="departments"
|
||||
@select="handleDepartmentSelect"
|
||||
/>
|
||||
|
||||
<!-- Selector de Roles Principales -->
|
||||
<MainRoleSelector
|
||||
v-if="selectedDepartment"
|
||||
:selectedDepartment="selectedDepartment"
|
||||
:mainRoles="mainRoles"
|
||||
@select="handleRoleSelect"
|
||||
/>
|
||||
|
||||
<SkillRole
|
||||
v-if="selectedRole"
|
||||
:mainRoleSkills="filteredMainRoleSkills"
|
||||
:selectedRole="selectedRole"
|
||||
:scores="scores"
|
||||
@select="handleSkillSelect"
|
||||
/>
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
15
resources/js/Pages/Admin/Skills/Component.js
Normal file
15
resources/js/Pages/Admin/Skills/Component.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { t } from '@/Lang/i18n';
|
||||
import { hasPermission } from '@/rolePermission.js';
|
||||
|
||||
// Obtener ruta
|
||||
const goTo = (route) => `admin.skills.${route}`
|
||||
// Obtener traducción del componente
|
||||
const transl = (lang) => t(`skill.${lang}`)
|
||||
// Determina si un usuario puede hacer algo no en base a los permisos
|
||||
const can = (permission) => hasPermission(`users.${permission}`)
|
||||
|
||||
export{
|
||||
can,
|
||||
goTo,
|
||||
transl
|
||||
}
|
||||
89
resources/js/Pages/Admin/Skills/Create.vue
Normal file
89
resources/js/Pages/Admin/Skills/Create.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<script setup>
|
||||
import { goTo, transl } from "./Component";
|
||||
import { Link, useForm } from "@inertiajs/vue3";
|
||||
|
||||
import PrimaryButton from "@/Components/Dashboard/Button/Primary.vue";
|
||||
import Input from "@/Components/Dashboard/Form/Input.vue";
|
||||
import PageHeader from "@/Components/Dashboard/PageHeader.vue";
|
||||
import GoogleIcon from "@/Components/Shared/GoogleIcon.vue";
|
||||
import DashboardLayout from "@/Layouts/DashboardLayout.vue";
|
||||
import Selectable from "@/Components/Dashboard/Form/Selectable.vue";
|
||||
|
||||
defineProps({
|
||||
departments: Object,
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
name: "",
|
||||
description: "",
|
||||
department_id: "",
|
||||
});
|
||||
|
||||
const submit = () =>
|
||||
form
|
||||
.transform((data) => ({
|
||||
...data,
|
||||
department_id: form.department_id?.id,
|
||||
}))
|
||||
.post(route(goTo("store")), {
|
||||
onSuccess: () => Notify.success(transl("create.onSuccess")),
|
||||
onError: () => Notify.error(transl("create.onError")),
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardLayout :title="transl('create.title')">
|
||||
<PageHeader>
|
||||
<Link :href="route(goTo('index'))">
|
||||
<GoogleIcon
|
||||
:title="$t('return')"
|
||||
class="btn-icon-primary"
|
||||
name="arrow_back"
|
||||
outline
|
||||
/>
|
||||
</Link>
|
||||
</PageHeader>
|
||||
<div class="w-full pb-8">
|
||||
<div class="mt-8">
|
||||
<p v-text="transl('create.description')" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<form @submit.prevent="submit" class="grid gap-4 grid-cols-6">
|
||||
<Input
|
||||
id="Nombre"
|
||||
class="col-span-2"
|
||||
v-model="form.name"
|
||||
:onError="form.errors.name"
|
||||
autofocus
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descripción"
|
||||
class="col-span-2"
|
||||
v-model="form.description"
|
||||
:onError="form.errors.description"
|
||||
autofocus
|
||||
/>
|
||||
<Selectable
|
||||
id="department_id"
|
||||
class="col-span-3"
|
||||
v-model="form.department_id"
|
||||
:options="departments"
|
||||
:onError="form.errors.department_id"
|
||||
:title="$t('department.title')"
|
||||
required
|
||||
/>
|
||||
<div
|
||||
class="col-span-6 flex flex-col items-center justify-end space-y-4 mt-4"
|
||||
>
|
||||
<PrimaryButton
|
||||
:class="{ 'opacity-25': form.processing }"
|
||||
:disabled="form.processing"
|
||||
v-text="transl('create.title')"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
43
resources/js/Pages/Admin/Skills/Destroy.vue
Normal file
43
resources/js/Pages/Admin/Skills/Destroy.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<script setup>
|
||||
import { transl, goTo } from './Component'
|
||||
import { router } from '@inertiajs/vue3';
|
||||
|
||||
import DestroyModal from '@/Components/Dashboard/Modal/Destroy.vue';
|
||||
import Header from '@/Components/Dashboard/Modal/Elements/Header.vue';
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'switchModal'
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
model: Object
|
||||
});
|
||||
|
||||
const destroy = (id) => router.delete(route(goTo('destroy'), {id}), {
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
props.model.pop;
|
||||
Notify.success(transl('deleted'));
|
||||
emit('close');
|
||||
},
|
||||
onError: () => {
|
||||
Notify.info(transl('notFound'));
|
||||
emit('close');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DestroyModal
|
||||
:show="show"
|
||||
@close="$emit('close')"
|
||||
@destroy="destroy(model.id)"
|
||||
>
|
||||
<Header
|
||||
:title="model.name"
|
||||
:subtitle="model.description"
|
||||
/>
|
||||
</DestroyModal>
|
||||
</template>
|
||||
67
resources/js/Pages/Admin/Skills/Edit.vue
Normal file
67
resources/js/Pages/Admin/Skills/Edit.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<script setup>
|
||||
import { goTo } from './Component';
|
||||
import { useForm } from '@inertiajs/vue3';
|
||||
import { onUpdated } from 'vue';
|
||||
|
||||
import Input from '@/Components/Dashboard/Form/Input.vue';
|
||||
import EditModal from '@/Components/Dashboard/Modal/Edit.vue';
|
||||
import Header from '@/Components/Dashboard/Modal/Elements/Header.vue';
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'switchModal'
|
||||
]);
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
model: Object
|
||||
});
|
||||
|
||||
const form = useForm({});
|
||||
|
||||
const update = (id) => {
|
||||
form.transform(data => ({
|
||||
...props.model
|
||||
})).put(route(goTo('update'), {id}),{
|
||||
preserveScroll: true,
|
||||
onSuccess: () => {
|
||||
Notify.success(lang('updated'))
|
||||
emit('switchModal')
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<EditModal
|
||||
:show="show"
|
||||
@close="$emit('close')"
|
||||
@update="update(model.id)"
|
||||
>
|
||||
<Header
|
||||
:title="model.name"
|
||||
/>
|
||||
<div class="py-2 border-b">
|
||||
<div class="p-4">
|
||||
<form>
|
||||
<div class="grid gap-6 mb-6 lg:grid-cols-2">
|
||||
<Input
|
||||
id="Nombre"
|
||||
placeholder="name"
|
||||
v-model="model.name"
|
||||
:onError="form.errors.name"
|
||||
required
|
||||
/>
|
||||
<Input
|
||||
id="Descripción"
|
||||
v-model="model.description"
|
||||
:onError="form.errors.description"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</EditModal>
|
||||
</template>
|
||||
149
resources/js/Pages/Admin/Skills/Index.vue
Normal file
149
resources/js/Pages/Admin/Skills/Index.vue
Normal file
@ -0,0 +1,149 @@
|
||||
<script setup>
|
||||
import { transl, can, goTo } from './Component'
|
||||
import { ref } from 'vue';
|
||||
import { Link } from '@inertiajs/vue3';
|
||||
|
||||
import ModalController from '@/Controllers/ModalController.js';
|
||||
import SearcherController from '@/Controllers/SearcherController.js';
|
||||
|
||||
import SearcherHead from '@/Components/Dashboard/Searcher.vue';
|
||||
import Table from '@/Components/Dashboard/Table.vue';
|
||||
import GoogleIcon from '@/Components/Shared/GoogleIcon.vue';
|
||||
import DashboardLayout from '@/Layouts/DashboardLayout.vue';
|
||||
import DestroyView from './Destroy.vue';
|
||||
import EditView from './Edit.vue';
|
||||
|
||||
const props = defineProps({
|
||||
skills: Object
|
||||
});
|
||||
|
||||
// Controladores
|
||||
const Modal = new ModalController();
|
||||
const Searcher = new SearcherController(goTo('index'));
|
||||
|
||||
// Variables de controladores
|
||||
const destroyModal = ref(Modal.destroyModal);
|
||||
const editModal = ref(Modal.editModal);
|
||||
const modelModal = ref(Modal.modelModal);
|
||||
const query = ref(Searcher.query);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DashboardLayout :title="transl('system')">
|
||||
<SearcherHead @search="Searcher.search">
|
||||
<Link
|
||||
v-if="can('create')"
|
||||
:href="route(goTo('create'))"
|
||||
>
|
||||
<GoogleIcon
|
||||
:title="$t('crud.create')"
|
||||
class="btn-icon-primary"
|
||||
name="add"
|
||||
outline
|
||||
/>
|
||||
</Link>
|
||||
</SearcherHead>
|
||||
<div class="pt-2 w-full">
|
||||
<Table
|
||||
:items="skills"
|
||||
@send-pagination="Searcher.searchWithPagination"
|
||||
>
|
||||
<template #head>
|
||||
<th
|
||||
class="table-item"
|
||||
v-text="$t('Nombre')"
|
||||
/>
|
||||
<th
|
||||
class="table-item"
|
||||
v-text="$t('Descripción')"
|
||||
/>
|
||||
<th
|
||||
class="table-item"
|
||||
v-text="$t('Departamento')"
|
||||
/>
|
||||
<th
|
||||
class="table-item w-44"
|
||||
v-text="$t('actions')"
|
||||
/>
|
||||
</template>
|
||||
<template #body="{items}">
|
||||
<tr v-for="model in items">
|
||||
<td class="table-item border">
|
||||
<div class="flex items-center text-sm">
|
||||
<div>
|
||||
<p class="font-semibold">
|
||||
{{ model.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="table-item border">
|
||||
<div class="flex items-center text-sm">
|
||||
<div>
|
||||
<p class="font-semibold">
|
||||
{{ model.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="table-item border">
|
||||
<div class="flex items-center text-sm">
|
||||
<div>
|
||||
<p class="font-semibold">
|
||||
{{ model.department?.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="table-item border">
|
||||
<div class="flex justify-center space-x-2">
|
||||
<GoogleIcon
|
||||
v-if="can('edit')"
|
||||
:title="$t('crud.edit')"
|
||||
class="btn-icon-primary"
|
||||
name="edit"
|
||||
outline
|
||||
@click="Modal.switchEditModal(model)"
|
||||
/>
|
||||
<GoogleIcon
|
||||
v-if="can('destroy')"
|
||||
:title="$t('crud.destroy')"
|
||||
class="btn-icon-primary"
|
||||
name="delete"
|
||||
outline
|
||||
@click="Modal.switchDestroyModal(model)"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template #empty>
|
||||
<td class="table-item border">
|
||||
<div class="flex items-center text-sm">
|
||||
<div>
|
||||
<p class="font-semibold">
|
||||
{{ $t('registers.empty') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="table-item border">-</td>
|
||||
<td class="table-item border">-</td>
|
||||
</template>
|
||||
</Table>
|
||||
</div>
|
||||
<EditView
|
||||
v-if="can('edit')"
|
||||
:show="editModal"
|
||||
:model="modelModal"
|
||||
@switchModal="Modal.switchShowEditModal"
|
||||
@close="Modal.switchEditModal"
|
||||
/>
|
||||
<DestroyView
|
||||
v-if="can('create')"
|
||||
:show="destroyModal"
|
||||
:model="modelModal"
|
||||
@close="Modal.switchDestroyModal"
|
||||
/>
|
||||
</DashboardLayout>
|
||||
</template>
|
||||
@ -7,8 +7,11 @@
|
||||
use App\Http\Controllers\Dashboard\NotificationController;
|
||||
use App\Http\Controllers\Admin\DepartmentController;
|
||||
use App\Http\Controllers\Admin\MainRoleController;
|
||||
use App\Http\Controllers\Admin\MainRoleSkillsController;
|
||||
use App\Http\Controllers\Admin\SkillController;
|
||||
use App\Http\Controllers\Developer\RoleController;
|
||||
use App\Http\Controllers\Example\IndexController as ExampleIndexController;
|
||||
use App\Models\MainRoleSkills;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
/**
|
||||
@ -17,7 +20,6 @@
|
||||
* Rutas accesibles por todos los usuarios y no usuarios
|
||||
*/
|
||||
Route::redirect('/', '/login');
|
||||
|
||||
/**
|
||||
* Rutas del Dashboard
|
||||
*
|
||||
@ -55,10 +57,12 @@
|
||||
'auth:sanctum',
|
||||
config('jetstream.auth_session')
|
||||
])->group(function () {
|
||||
Route::resource('users', UserController::class);
|
||||
Route::resource('scores', ScoreController::class);
|
||||
Route::resource('departments', DepartmentController::class);
|
||||
Route::resource('mainRoles', MainRoleController::class);
|
||||
Route::resource('users', UserController::class);
|
||||
Route::resource('scores', ScoreController::class);
|
||||
Route::resource('departments', DepartmentController::class);
|
||||
Route::resource('mainRoles', MainRoleController::class);
|
||||
Route::resource('skills', SkillController::class);
|
||||
Route::resource('mainRoleSkills', MainRoleSkillsController::class);
|
||||
|
||||
Route::prefix('/users')->name('users.')->group(function()
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user