mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 13:23:17 +00:00
60 lines
3.1 KiB
Vue
60 lines
3.1 KiB
Vue
<template>
|
|
<div class="detail-section">
|
|
<div class="section-title">Asignaciones a proyectos</div>
|
|
<div class="muted">Una persona puede trabajar en varios proyectos activos al mismo tiempo.</div>
|
|
<div v-if="!readonly" class="assignment-create mt-3">
|
|
<Select v-model="projectId" :options="availableProjects" option-label="name" option-value="id" placeholder="Proyecto activo" class="w-full" />
|
|
<Button label="Asignar" icon="pi pi-plus" :disabled="!projectId" @click="assignProject" />
|
|
</div>
|
|
|
|
<DataTable :value="assignments" size="small" class="mt-3" empty-message="Sin historial de asignaciones">
|
|
<Column header="Proyecto">
|
|
<template #body="{ data }">
|
|
<div><span class="identifier">{{ data.project_code }}</span><div>{{ data.project_name }}</div></div>
|
|
</template>
|
|
</Column>
|
|
<Column field="start_date" header="Inicio" />
|
|
<Column header="Estado">
|
|
<template #body="{ data }"><Tag :value="data.active ? 'Activa' : 'Finalizada'" :severity="data.active ? 'success' : 'secondary'" /></template>
|
|
</Column>
|
|
<Column v-if="!readonly" header="">
|
|
<template #body="{ data }">
|
|
<Button v-if="data.active" icon="pi pi-times" text rounded severity="danger" size="small" aria-label="Finalizar asignación" @click="deactivate(data)" />
|
|
<Button v-else icon="pi pi-refresh" text rounded size="small" aria-label="Reactivar asignación" @click="reactivate(data)" />
|
|
</template>
|
|
</Column>
|
|
</DataTable>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { ProjectOption } from "~/types/padron";
|
|
|
|
type Assignment = { id: number; project_id: number; project_name: string; project_code: string; active: number; start_date: string; end_date?: string | null };
|
|
const props = defineProps<{ workerId: number; assignments: Assignment[]; projects: ProjectOption[]; readonly?: boolean }>();
|
|
const emit = defineEmits<{ changed: [] }>();
|
|
const { api } = useApi();
|
|
const confirm = useConfirm();
|
|
const toast = useToast();
|
|
const projectId = ref<number | null>(null);
|
|
const availableProjects = computed(() => props.projects.filter((project) => !props.assignments.some((assignment) => assignment.project_id === project.id && assignment.active)));
|
|
|
|
async function setAssignment(id: number, active: boolean) {
|
|
await api(`/v1/workers/${props.workerId}/assign`, { method: "POST", json: { project_id: id, active } });
|
|
toast.add({ severity: "success", summary: active ? "Asignación activa" : "Asignación finalizada", life: 1800 });
|
|
projectId.value = null;
|
|
emit("changed");
|
|
}
|
|
function assignProject() { if (projectId.value) setAssignment(projectId.value, true); }
|
|
function reactivate(assignment: Assignment) { setAssignment(assignment.project_id, true); }
|
|
function deactivate(assignment: Assignment) {
|
|
confirm.require({
|
|
header: "Finalizar asignación",
|
|
message: `¿Quitar a esta persona de ${assignment.project_name}? Se conservará la fecha en el historial.`,
|
|
icon: "pi pi-exclamation-triangle",
|
|
acceptLabel: "Finalizar",
|
|
rejectLabel: "Cancelar",
|
|
accept: () => setAssignment(assignment.project_id, false),
|
|
});
|
|
}
|
|
</script>
|