Delete project logic
This commit is contained in:
@@ -50,6 +50,8 @@ export default function UsersPage() {
|
|||||||
const emptyUser: UserForm = { name: "", email: "", roleId: "", projectId: "", password: "", status: "ACTIVE", createdAt: new Date().toISOString().slice(0,10) };
|
const emptyUser: UserForm = { name: "", email: "", roleId: "", projectId: "", password: "", status: "ACTIVE", createdAt: new Date().toISOString().slice(0,10) };
|
||||||
const [form, setForm] = useState<UserForm>(emptyUser);
|
const [form, setForm] = useState<UserForm>(emptyUser);
|
||||||
|
|
||||||
|
const activeProjects = projects.filter(p => p.status === 'ACTIVE');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
}, []);
|
}, []);
|
||||||
@@ -382,7 +384,7 @@ export default function UsersPage() {
|
|||||||
disabled={loadingProjects || saving}
|
disabled={loadingProjects || saving}
|
||||||
>
|
>
|
||||||
<option value="">{loadingProjects ? "Loading projects..." : "Select Project *"}</option>
|
<option value="">{loadingProjects ? "Loading projects..." : "Select Project *"}</option>
|
||||||
{projects.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
|
{activeProjects.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
|
||||||
</select>
|
</select>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
fetchProjects,
|
fetchProjects,
|
||||||
createProject as apiCreateProject,
|
createProject as apiCreateProject,
|
||||||
updateProject as apiUpdateProject,
|
updateProject as apiUpdateProject,
|
||||||
deleteProject as apiDeleteProject,
|
|
||||||
deactivateProject as apiDeactivateProject,
|
deactivateProject as apiDeactivateProject,
|
||||||
} from "../../api/projects";
|
} from "../../api/projects";
|
||||||
import { fetchMeterTypes, type MeterType } from "../../api/meterTypes";
|
import { fetchMeterTypes, type MeterType } from "../../api/meterTypes";
|
||||||
@@ -28,10 +27,6 @@ export default function ProjectsPage() {
|
|||||||
|
|
||||||
const [meterTypes, setMeterTypes] = useState<MeterType[]>([]);
|
const [meterTypes, setMeterTypes] = useState<MeterType[]>([]);
|
||||||
|
|
||||||
const [showDeactivateModal, setShowDeactivateModal] = useState(false);
|
|
||||||
const [projectToDeactivate, setProjectToDeactivate] = useState<Project | null>(null);
|
|
||||||
const [usersAssignedCount, setUsersAssignedCount] = useState(0);
|
|
||||||
|
|
||||||
const emptyForm: ProjectInput = {
|
const emptyForm: ProjectInput = {
|
||||||
name: "",
|
name: "",
|
||||||
description: "",
|
description: "",
|
||||||
@@ -113,44 +108,27 @@ export default function ProjectsPage() {
|
|||||||
if (!activeProject) return;
|
if (!activeProject) return;
|
||||||
|
|
||||||
const confirmDelete = window.confirm(
|
const confirmDelete = window.confirm(
|
||||||
`¿Estás seguro que quieres eliminar el proyecto "${activeProject.name}"?`
|
`¿Estás seguro que quieres desactivar el proyecto "${activeProject.name}"?\n\nEl proyecto será desactivado (no eliminado) y cualquier usuario asignado será desvinculado.`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!confirmDelete) return;
|
if (!confirmDelete) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await apiDeleteProject(activeProject.id);
|
const deactivatedProject = await apiDeactivateProject(activeProject.id);
|
||||||
setProjects((prev) => prev.filter((p) => p.id !== activeProject.id));
|
|
||||||
setActiveProject(null);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deleting project:", error);
|
|
||||||
|
|
||||||
// Get error message - ApiError extends Error
|
setProjects((prev) =>
|
||||||
let errorMessage = "";
|
prev.map((p) => (p.id === deactivatedProject.id ? deactivatedProject : p))
|
||||||
if (error instanceof Error) {
|
);
|
||||||
errorMessage = error.message;
|
|
||||||
} else if (typeof error === 'string') {
|
setActiveProject(null);
|
||||||
errorMessage = error;
|
alert(`Proyecto "${activeProject.name}" ha sido desactivado exitosamente.`);
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error("Error deactivating project:", error);
|
||||||
console.log("Error message:", errorMessage); // Debug log
|
alert(
|
||||||
|
`Error al desactivar el proyecto: ${
|
||||||
// Check if error is about users assigned to the project
|
error instanceof Error ? error.message : "Por favor intenta de nuevo."
|
||||||
if (errorMessage.includes("user(s) are assigned to this project")) {
|
}`
|
||||||
// Extract number of users from error message
|
|
||||||
const match = errorMessage.match(/(\d+) user\(s\)/);
|
|
||||||
const userCount = match ? parseInt(match[1]) : 1;
|
|
||||||
|
|
||||||
console.log("Users assigned:", userCount); // Debug log
|
|
||||||
|
|
||||||
setUsersAssignedCount(userCount);
|
|
||||||
setProjectToDeactivate(activeProject);
|
|
||||||
setShowDeactivateModal(true);
|
|
||||||
} else {
|
|
||||||
alert(
|
|
||||||
`Error deleting project: ${errorMessage || "Please try again."}`
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,31 +152,6 @@ export default function ProjectsPage() {
|
|||||||
setShowModal(true);
|
setShowModal(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConfirmDeactivate = async () => {
|
|
||||||
if (!projectToDeactivate) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const deactivatedProject = await apiDeactivateProject(projectToDeactivate.id);
|
|
||||||
|
|
||||||
setProjects((prev) =>
|
|
||||||
prev.map((p) => (p.id === deactivatedProject.id ? deactivatedProject : p))
|
|
||||||
);
|
|
||||||
|
|
||||||
setShowDeactivateModal(false);
|
|
||||||
setProjectToDeactivate(null);
|
|
||||||
setActiveProject(null);
|
|
||||||
|
|
||||||
alert(`Proyecto "${projectToDeactivate.name}" ha sido desactivado y los usuarios han sido desasignados.`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deactivating project:", error);
|
|
||||||
alert(
|
|
||||||
`Error deactivating project: ${
|
|
||||||
error instanceof Error ? error.message : "Please try again."
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const filtered = visibleProjects.filter((p) =>
|
const filtered = visibleProjects.filter((p) =>
|
||||||
`${p.name} ${p.areaName} ${p.description ?? ""}`
|
`${p.name} ${p.areaName} ${p.description ?? ""}`
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
@@ -435,60 +388,6 @@ export default function ProjectsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{showDeactivateModal && projectToDeactivate && (
|
|
||||||
<div className="fixed inset-0 bg-black/40 flex items-center justify-center z-50">
|
|
||||||
<div className="bg-white rounded-xl p-6 w-[500px] space-y-4">
|
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
|
||||||
Proyecto con Usuarios Asignados
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="space-y-3">
|
|
||||||
<p className="text-sm text-gray-700">
|
|
||||||
El proyecto <span className="font-semibold">"{projectToDeactivate.name}"</span> tiene{" "}
|
|
||||||
<span className="font-semibold text-blue-600">{usersAssignedCount} usuario(s)</span> asignado(s).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="text-sm text-gray-700">
|
|
||||||
No se puede eliminar directamente. ¿Deseas continuar con las siguientes acciones?
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul className="text-sm text-gray-700 space-y-2 bg-amber-50 border border-amber-200 rounded-lg p-4">
|
|
||||||
<li className="flex items-start gap-2">
|
|
||||||
<span className="text-amber-600 font-bold">•</span>
|
|
||||||
<span>El proyecto será <span className="font-semibold">desactivado</span> (status = INACTIVE)</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start gap-2">
|
|
||||||
<span className="text-amber-600 font-bold">•</span>
|
|
||||||
<span>Los <span className="font-semibold">{usersAssignedCount} usuario(s)</span> serán desasignados (project_id = null)</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p className="text-xs text-gray-500">
|
|
||||||
Nota: El proyecto no será eliminado de la base de datos, solo desactivado.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex justify-end gap-2 pt-3 border-t">
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
setShowDeactivateModal(false);
|
|
||||||
setProjectToDeactivate(null);
|
|
||||||
}}
|
|
||||||
className="px-4 py-2 rounded hover:bg-gray-100"
|
|
||||||
>
|
|
||||||
Cancelar
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={handleConfirmDeactivate}
|
|
||||||
className="bg-amber-600 text-white px-4 py-2 rounded hover:bg-amber-700"
|
|
||||||
>
|
|
||||||
Sí, Desactivar Proyecto
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user