Habilidades duplicadas

This commit is contained in:
Juan Felipe Zapata Moreno 2025-07-13 17:14:47 -06:00
parent 776ef80b93
commit 24a1e18dc3
5 changed files with 52 additions and 22 deletions

View File

@ -0,0 +1,4 @@
{
"tabWidth": 2,
"useTabs": false
}

View File

@ -0,0 +1,4 @@
{
"tabWidth": 2,
"useTabs": false
}

View File

@ -95,20 +95,29 @@ public function create()
public function store(StoreMainRoleSkills $request) public function store(StoreMainRoleSkills $request)
{ {
$create = []; try {
foreach ($request['skills'] as $skill) { $create = [];
$create[] = [ foreach ($request['skills'] as $skill) {
'main_role_id' => $request['main_role_id'], $create[] = [
'skill_id' => $skill['skill_id'], 'main_role_id' => $request['main_role_id'],
'scored_id' => $skill['scored_id'], 'skill_id' => $skill['skill_id'],
'created_at' => now(), 'scored_id' => $skill['scored_id'],
'updated_at' => now(), 'created_at' => now(),
]; 'updated_at' => now(),
} ];
}
MainRoleSkills::insert($create); MainRoleSkills::insert($create);
return $this->index(); return $this->index();
} catch (\Illuminate\Database\QueryException $e) {
// Si hay error de restricción única
if ($e->getCode() === '23000') {
return back()->withErrors(['skills' => 'Una o más habilidades ya están asignadas a este rol.']);
}
throw $e;
}
} }
public function update(UpdateMainRoleSkills $request, MainRoleSkills $mainRoleSkills) public function update(UpdateMainRoleSkills $request, MainRoleSkills $mainRoleSkills)

View File

@ -17,6 +17,8 @@ public function up(): void
$table->foreignId('skill_id')->constrained('skills')->onDelete('cascade'); $table->foreignId('skill_id')->constrained('skills')->onDelete('cascade');
$table->foreignId('scored_id')->constrained('scores')->onDelete('cascade'); $table->foreignId('scored_id')->constrained('scores')->onDelete('cascade');
$table->timestamps(); $table->timestamps();
$table->unique(['main_role_id', 'skill_id']);
}); });
} }

View File

@ -11,7 +11,7 @@ const props = defineProps({
required: true, required: true,
}, },
skills: { skills: {
type: Array, // Ya filtradas por departamento type: Array,
required: true, required: true,
}, },
scores: { scores: {
@ -35,16 +35,16 @@ const todos = ref([]);
function addTodo() { function addTodo() {
if (skillId.value && scoredId.value) { if (skillId.value && scoredId.value) {
const selectedSkill = props.skills.find( const selectedSkill = props.skills.find(
skill => skill.id === (skillId.value.id || skillId.value) (skill) => skill.id === (skillId.value.id || skillId.value)
); );
const selectedScore = props.scores.find( const selectedScore = props.scores.find(
score => score.id === (scoredId.value.id || scoredId.value) (score) => score.id === (scoredId.value.id || scoredId.value)
); );
if (selectedSkill && selectedScore) { if (selectedSkill && selectedScore) {
// Verificar que no esté duplicada // Verificar que no esté duplicada
const isDuplicate = todos.value.some( const isDuplicate = todos.value.some(
todo => todo.skill_id === selectedSkill.id (todo) => todo.skill_id === selectedSkill.id
); );
if (!isDuplicate) { if (!isDuplicate) {
@ -86,9 +86,13 @@ const submitForm = () => {
<h2 class="text-xl font-semibold mb-2"> <h2 class="text-xl font-semibold mb-2">
Asignar Habilidades al Rol: {{ selectedMainRole.name }} Asignar Habilidades al Rol: {{ selectedMainRole.name }}
</h2> </h2>
<p class="text-gray-600"> <p class="text-gray-600">Departamento: {{ selectedDepartment.name }}</p>
Departamento: {{ selectedDepartment.name }} </div>
</p> <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> </div>
<!-- Formulario para agregar habilidades --> <!-- Formulario para agregar habilidades -->
@ -132,10 +136,14 @@ const submitForm = () => {
<!-- Lista de habilidades agregadas --> <!-- Lista de habilidades agregadas -->
<div class="space-y-3 mb-6"> <div class="space-y-3 mb-6">
<template v-for="(todo, index) in todos" :key="index"> <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 bg-white items-center justify-between rounded-lg px-4 py-3 border shadow-sm"
>
<div class="flex-1"> <div class="flex-1">
<div class="font-bold text-black">{{ todo.skill_name }}</div> <div class="font-bold text-black">{{ todo.skill_name }}</div>
<div class="text-sm text-gray-600">Puntuación: {{ todo.score_alias }}</div> <div class="text-sm text-gray-600">
Puntuación: {{ todo.score_alias }}
</div>
</div> </div>
<button <button
@click="removeTodo(index)" @click="removeTodo(index)"
@ -146,7 +154,10 @@ const submitForm = () => {
</div> </div>
</template> </template>
<div v-if="todos.length === 0" class="text-gray-500 text-center py-8 bg-gray-50 rounded-lg"> <div
v-if="todos.length === 0"
class="text-gray-500 text-center py-8 bg-gray-50 rounded-lg"
>
No hay habilidades agregadas No hay habilidades agregadas
</div> </div>
</div> </div>