diff --git a/app/Http/Controllers/Admin/DepartmentController.php b/app/Http/Controllers/Admin/DepartmentController.php index 933df53..bb9aaab 100644 --- a/app/Http/Controllers/Admin/DepartmentController.php +++ b/app/Http/Controllers/Admin/DepartmentController.php @@ -33,7 +33,6 @@ public function index() return $this->vuew('index', [ 'departments' => department::where('name', 'LIKE', "%{$q}%") - ->orWhere('description', 'LIKE', "%{$q}%") ->select([ 'id', 'name', diff --git a/app/Http/Controllers/Admin/MainRoleSkillsController.php b/app/Http/Controllers/Admin/MainRoleSkillsController.php new file mode 100644 index 0000000..9e3634d --- /dev/null +++ b/app/Http/Controllers/Admin/MainRoleSkillsController.php @@ -0,0 +1,98 @@ + + * + * @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,description', + 'skill:id,name,department_id', + 'score:id,alias' + ]) + ->paginate(config('app.pagination')); + + return $this->vuew('index', [ + 'mainRoleSkills' => $mainRoleSkills + ]); + } + + public function create() + { + $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 + ]); + } + + 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 update(UpdateMainRoleSkills $request, MainRoleSkills $mainRoleSkills) + { + $mainRoleSkills->update($request->all()); + } + + public function destroy($id) + { + $mainRoleSkill = MainRoleSkills::findOrFail($id); + $mainRoleSkill->delete(); + } + +} diff --git a/app/Http/Controllers/Admin/SkillController.php b/app/Http/Controllers/Admin/SkillController.php new file mode 100644 index 0000000..a33c24a --- /dev/null +++ b/app/Http/Controllers/Admin/SkillController.php @@ -0,0 +1,65 @@ + + * + * @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(); + } +} diff --git a/app/Http/Requests/StoreMainRoleSkills.php b/app/Http/Requests/StoreMainRoleSkills.php new file mode 100644 index 0000000..d859494 --- /dev/null +++ b/app/Http/Requests/StoreMainRoleSkills.php @@ -0,0 +1,41 @@ + + * + * @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 + */ + public function rules() + { + return [ + 'main_role_id' => ['required', 'integer'], + 'skills' => ['required', 'array', 'min:1'], + 'skills.*.skill_id' => ['required', 'integer'], + 'skills.*.scored_id' => ['required', 'integer'], + ]; + } +} diff --git a/app/Http/Requests/StoreSkill.php b/app/Http/Requests/StoreSkill.php new file mode 100644 index 0000000..7af14b8 --- /dev/null +++ b/app/Http/Requests/StoreSkill.php @@ -0,0 +1,40 @@ + + * + * @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 + */ + public function rules() + { + return [ + 'name' => ['required', 'string'], + 'description' => ['nullable', 'string'], + 'department_id' => ['required', 'integer'], + ]; + } +} diff --git a/app/Http/Requests/UpdateMainRoleSkills.php b/app/Http/Requests/UpdateMainRoleSkills.php new file mode 100644 index 0000000..eeac835 --- /dev/null +++ b/app/Http/Requests/UpdateMainRoleSkills.php @@ -0,0 +1,40 @@ + + * + * @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 + */ + public function rules() + { + return [ + 'main_role_id' => ['required', 'integer'], + 'skill_id' => ['required', 'integer'], + 'scored_id' => ['required', 'integer'], + ]; + } +} diff --git a/app/Http/Requests/UpdateSkill.php b/app/Http/Requests/UpdateSkill.php new file mode 100644 index 0000000..3613e72 --- /dev/null +++ b/app/Http/Requests/UpdateSkill.php @@ -0,0 +1,40 @@ + + * + * @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 + */ + public function rules() + { + return [ + 'name' => ['required', 'string'], + 'description' => ['nullable', 'string'], + 'department_id' => ['required', 'integer','exists:departments,id'], + ]; + } +} diff --git a/app/Models/MainRoleSkills.php b/app/Models/MainRoleSkills.php new file mode 100644 index 0000000..e357e71 --- /dev/null +++ b/app/Models/MainRoleSkills.php @@ -0,0 +1,45 @@ + + * + * @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'); + } +} diff --git a/app/Models/Score.php b/app/Models/Score.php index cad93f4..ac55e72 100644 --- a/app/Models/Score.php +++ b/app/Models/Score.php @@ -27,4 +27,9 @@ class Score extends Model 'value', 'description', ]; + + public function mainRoleSkills() + { + return $this->hasMany(MainRoleSkills::class); + } } diff --git a/app/Models/Skill.php b/app/Models/Skill.php new file mode 100644 index 0000000..6307b7d --- /dev/null +++ b/app/Models/Skill.php @@ -0,0 +1,46 @@ + + * + * @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); + } +} diff --git a/app/Models/department.php b/app/Models/department.php index 5de561b..2417780 100644 --- a/app/Models/department.php +++ b/app/Models/department.php @@ -24,7 +24,7 @@ class department extends Model */ protected $fillable = [ 'name', - 'description' + 'description', ]; /** @@ -34,4 +34,9 @@ public function mainRoles() { return $this->hasMany(MainRole::class); } + + public function skills() + { + return $this->hasMany(Skill::class); + } } diff --git a/app/Models/mainRole.php b/app/Models/mainRole.php index 9ef8cc2..8878701 100644 --- a/app/Models/mainRole.php +++ b/app/Models/mainRole.php @@ -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); + } } diff --git a/database/migrations/2025_07_01_151840_create_main_role_table.php b/database/migrations/2025_07_01_151840_create_main_role_table.php index 4992c6c..8319c36 100644 --- a/database/migrations/2025_07_01_151840_create_main_role_table.php +++ b/database/migrations/2025_07_01_151840_create_main_role_table.php @@ -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'); } }; diff --git a/database/migrations/2025_07_02_131157_create_skills_table.php b/database/migrations/2025_07_02_131157_create_skills_table.php new file mode 100644 index 0000000..e135060 --- /dev/null +++ b/database/migrations/2025_07_02_131157_create_skills_table.php @@ -0,0 +1,30 @@ +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'); + } +}; diff --git a/database/migrations/2025_07_02_162405_create_main_role_skills_table.php b/database/migrations/2025_07_02_162405_create_main_role_skills_table.php new file mode 100644 index 0000000..8216eb7 --- /dev/null +++ b/database/migrations/2025_07_02_162405_create_main_role_skills_table.php @@ -0,0 +1,30 @@ +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(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('main_role_skills'); + } +}; diff --git a/resources/js/Components/App/DepartmentSelector.vue b/resources/js/Components/App/DepartmentSelector.vue new file mode 100644 index 0000000..f5ac7b3 --- /dev/null +++ b/resources/js/Components/App/DepartmentSelector.vue @@ -0,0 +1,34 @@ + + + diff --git a/resources/js/Components/App/MainRoleSelector.vue b/resources/js/Components/App/MainRoleSelector.vue new file mode 100644 index 0000000..6a746c9 --- /dev/null +++ b/resources/js/Components/App/MainRoleSelector.vue @@ -0,0 +1,53 @@ + + + diff --git a/resources/js/Components/App/SkillAssignment.vue b/resources/js/Components/App/SkillAssignment.vue new file mode 100644 index 0000000..d5163ce --- /dev/null +++ b/resources/js/Components/App/SkillAssignment.vue @@ -0,0 +1,191 @@ + + + diff --git a/resources/js/Components/App/StepIndicator.vue b/resources/js/Components/App/StepIndicator.vue new file mode 100644 index 0000000..65adf05 --- /dev/null +++ b/resources/js/Components/App/StepIndicator.vue @@ -0,0 +1,38 @@ + + + diff --git a/resources/js/Lang/es.js b/resources/js/Lang/es.js index 644b7a2..6321028 100644 --- a/resources/js/Lang/es.js +++ b/resources/js/Lang/es.js @@ -1,257 +1,317 @@ 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: { + 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", +}; diff --git a/resources/js/Layouts/DashboardLayout.vue b/resources/js/Layouts/DashboardLayout.vue index dc1bf11..cfc77e3 100644 --- a/resources/js/Layouts/DashboardLayout.vue +++ b/resources/js/Layouts/DashboardLayout.vue @@ -85,11 +85,21 @@ onMounted(()=> { name="Rol Principal" to="admin.mainRoles.index" /> + + -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"); + }, }); -} - - +}; diff --git a/resources/js/Pages/Admin/Departments/Index.vue b/resources/js/Pages/Admin/Departments/Index.vue index a400033..37e712c 100644 --- a/resources/js/Pages/Admin/Departments/Index.vue +++ b/resources/js/Pages/Admin/Departments/Index.vue @@ -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')); diff --git a/resources/js/Pages/Admin/MainRoleSkills/Component.js b/resources/js/Pages/Admin/MainRoleSkills/Component.js new file mode 100644 index 0000000..e8adf24 --- /dev/null +++ b/resources/js/Pages/Admin/MainRoleSkills/Component.js @@ -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 +} diff --git a/resources/js/Pages/Admin/MainRoleSkills/Create.vue b/resources/js/Pages/Admin/MainRoleSkills/Create.vue new file mode 100644 index 0000000..7c1662e --- /dev/null +++ b/resources/js/Pages/Admin/MainRoleSkills/Create.vue @@ -0,0 +1,163 @@ + + + diff --git a/resources/js/Pages/Admin/MainRoleSkills/Destroy.vue b/resources/js/Pages/Admin/MainRoleSkills/Destroy.vue new file mode 100644 index 0000000..698d010 --- /dev/null +++ b/resources/js/Pages/Admin/MainRoleSkills/Destroy.vue @@ -0,0 +1,43 @@ + + + diff --git a/resources/js/Pages/Admin/MainRoleSkills/Edit.vue b/resources/js/Pages/Admin/MainRoleSkills/Edit.vue new file mode 100644 index 0000000..76a4df2 --- /dev/null +++ b/resources/js/Pages/Admin/MainRoleSkills/Edit.vue @@ -0,0 +1,67 @@ + + diff --git a/resources/js/Pages/Admin/MainRoleSkills/Index.vue b/resources/js/Pages/Admin/MainRoleSkills/Index.vue new file mode 100644 index 0000000..5ca1816 --- /dev/null +++ b/resources/js/Pages/Admin/MainRoleSkills/Index.vue @@ -0,0 +1,146 @@ + + + diff --git a/resources/js/Pages/Admin/Skills/Component.js b/resources/js/Pages/Admin/Skills/Component.js new file mode 100644 index 0000000..a3596a9 --- /dev/null +++ b/resources/js/Pages/Admin/Skills/Component.js @@ -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 +} diff --git a/resources/js/Pages/Admin/Skills/Create.vue b/resources/js/Pages/Admin/Skills/Create.vue new file mode 100644 index 0000000..8c02a53 --- /dev/null +++ b/resources/js/Pages/Admin/Skills/Create.vue @@ -0,0 +1,89 @@ + + + diff --git a/resources/js/Pages/Admin/Skills/Destroy.vue b/resources/js/Pages/Admin/Skills/Destroy.vue new file mode 100644 index 0000000..698d010 --- /dev/null +++ b/resources/js/Pages/Admin/Skills/Destroy.vue @@ -0,0 +1,43 @@ + + + diff --git a/resources/js/Pages/Admin/Skills/Edit.vue b/resources/js/Pages/Admin/Skills/Edit.vue new file mode 100644 index 0000000..76a4df2 --- /dev/null +++ b/resources/js/Pages/Admin/Skills/Edit.vue @@ -0,0 +1,67 @@ + + diff --git a/resources/js/Pages/Admin/Skills/Index.vue b/resources/js/Pages/Admin/Skills/Index.vue new file mode 100644 index 0000000..5eedd84 --- /dev/null +++ b/resources/js/Pages/Admin/Skills/Index.vue @@ -0,0 +1,149 @@ + + + diff --git a/routes/web.php b/routes/web.php index 92074ed..d62e826 100644 --- a/routes/web.php +++ b/routes/web.php @@ -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() {