All checks were successful
Build And Deploy Main / build-and-deploy (push) Successful in 36s
305 lines
11 KiB
JavaScript
305 lines
11 KiB
JavaScript
import React, { useEffect, useMemo, useState } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { Button, Modal, Spinner } from "react-bootstrap";
|
|
import { AuthService, EmployeeService, EventsService } from "../../services";
|
|
import { EMPLOYEE_PERMISSION_GROUPS } from "../../shared";
|
|
|
|
const SYSTEM_ACCESS_PERMISSION = "System Access";
|
|
|
|
const ExternalEmployeesImport = () => {
|
|
const navigate = useNavigate();
|
|
const currentSite = EventsService.site || 3;
|
|
const [loading, setLoading] = useState(false);
|
|
const [saving, setSaving] = useState(false);
|
|
const [employees, setEmployees] = useState([]);
|
|
const [siteFilter, setSiteFilter] = useState(currentSite);
|
|
const [keyword, setKeyword] = useState("");
|
|
const [showPermissionModal, setShowPermissionModal] = useState(false);
|
|
const [selectedEmployee, setSelectedEmployee] = useState(undefined);
|
|
const [selectedPermissions, setSelectedPermissions] = useState([SYSTEM_ACCESS_PERMISSION]);
|
|
const [selectedAllowSite, setSelectedAllowSite] = useState(currentSite);
|
|
const [existingPermissionMap, setExistingPermissionMap] = useState({});
|
|
|
|
useEffect(() => {
|
|
if (!AuthService.canAddOrEditEmployees()) {
|
|
window.alert("You haven't login yet OR this user does not have access to this page. Please change an admin account to login.");
|
|
AuthService.logout();
|
|
navigate("/login");
|
|
return;
|
|
}
|
|
loadExternalEmployees();
|
|
loadExistingPermissions();
|
|
}, []);
|
|
|
|
const loadExistingPermissions = () => {
|
|
EmployeeService.getExternalUserPermissionsList(currentSite)
|
|
.then((response) => {
|
|
const records = Array.isArray(response?.data) ? response.data : [];
|
|
const nextMap = {};
|
|
records.forEach((item) => {
|
|
const key = item?.external_user_id;
|
|
if (!key) return;
|
|
nextMap[key] = item;
|
|
});
|
|
setExistingPermissionMap(nextMap);
|
|
})
|
|
.catch(() => {
|
|
setExistingPermissionMap({});
|
|
});
|
|
};
|
|
|
|
const loadExternalEmployees = () => {
|
|
setLoading(true);
|
|
EmployeeService.getExternalEmployeesList()
|
|
.then((response) => {
|
|
setEmployees(Array.isArray(response?.data) ? response.data : []);
|
|
})
|
|
.catch((error) => {
|
|
window.alert(error?.response?.data?.message || "Failed to load employees from HR system.");
|
|
})
|
|
.finally(() => {
|
|
setLoading(false);
|
|
});
|
|
};
|
|
|
|
const filteredEmployees = useMemo(() => {
|
|
return (employees || [])
|
|
.filter((item) => siteFilter === 'all' || Number(item?.site) === Number(siteFilter))
|
|
.filter((item) => {
|
|
if (!keyword) return true;
|
|
const key = keyword.toLowerCase();
|
|
return (
|
|
(item?.username || "").toLowerCase().includes(key) ||
|
|
(item?.name || "").toLowerCase().includes(key) ||
|
|
(item?.title || "").toLowerCase().includes(key)
|
|
);
|
|
});
|
|
}, [employees, siteFilter, keyword]);
|
|
|
|
const openPermissionModal = (employee) => {
|
|
const allowSite = Number(currentSite);
|
|
setSelectedEmployee(employee);
|
|
setSelectedAllowSite(allowSite);
|
|
setSelectedPermissions([SYSTEM_ACCESS_PERMISSION]);
|
|
setShowPermissionModal(true);
|
|
EmployeeService.getExternalUserPermission(employee?.employee_id, allowSite)
|
|
.then((response) => {
|
|
const existingPermissions = Array.isArray(response?.data?.permissions) ? response.data.permissions : [];
|
|
const nextPermissions = Array.from(new Set([SYSTEM_ACCESS_PERMISSION, ...existingPermissions]));
|
|
setSelectedPermissions(nextPermissions);
|
|
})
|
|
.catch(() => {
|
|
setSelectedPermissions([SYSTEM_ACCESS_PERMISSION]);
|
|
});
|
|
};
|
|
|
|
const closePermissionModal = () => {
|
|
if (saving) return;
|
|
setShowPermissionModal(false);
|
|
setSelectedEmployee(undefined);
|
|
setSelectedPermissions([SYSTEM_ACCESS_PERMISSION]);
|
|
setSelectedAllowSite(currentSite);
|
|
};
|
|
|
|
const togglePermission = (permissionKey) => {
|
|
if (permissionKey === SYSTEM_ACCESS_PERMISSION) return;
|
|
setSelectedPermissions((prev) => {
|
|
if (prev.includes(permissionKey)) {
|
|
return prev.filter((item) => item !== permissionKey);
|
|
}
|
|
return [...prev, permissionKey];
|
|
});
|
|
};
|
|
|
|
const isPermissionGroupFullySelected = (permissionItems = []) => {
|
|
return permissionItems.length > 0 && permissionItems.every((permissionKey) => selectedPermissions.includes(permissionKey));
|
|
};
|
|
|
|
const togglePermissionGroup = (permissionItems = [], checked) => {
|
|
if (!Array.isArray(permissionItems) || permissionItems.length === 0) return;
|
|
setSelectedPermissions((prev) => {
|
|
const nextSet = new Set(prev);
|
|
permissionItems.forEach((permissionKey) => {
|
|
if (permissionKey === SYSTEM_ACCESS_PERMISSION) {
|
|
nextSet.add(SYSTEM_ACCESS_PERMISSION);
|
|
return;
|
|
}
|
|
if (checked) {
|
|
nextSet.add(permissionKey);
|
|
} else {
|
|
nextSet.delete(permissionKey);
|
|
}
|
|
});
|
|
return Array.from(nextSet);
|
|
});
|
|
};
|
|
|
|
const savePermissions = () => {
|
|
if (!selectedEmployee?.employee_id) return;
|
|
setSaving(true);
|
|
EmployeeService.saveExternalUserPermission({
|
|
external_user_id: selectedEmployee.employee_id,
|
|
username: selectedEmployee.username || "",
|
|
name: selectedEmployee.name || "",
|
|
title: selectedEmployee.title || "",
|
|
email: selectedEmployee.email || "",
|
|
allow_site: Number(selectedAllowSite),
|
|
permissions: selectedPermissions
|
|
})
|
|
.then(() => {
|
|
loadExistingPermissions();
|
|
closePermissionModal();
|
|
})
|
|
.catch((error) => {
|
|
window.alert(error?.response?.data?.message || "Failed to save external user permissions.");
|
|
})
|
|
.finally(() => {
|
|
setSaving(false);
|
|
});
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className="list row mb-4">
|
|
<div className="col-md-12 text-primary">
|
|
<h5>
|
|
Add New Employee From HR System
|
|
<button className="btn btn-link btn-sm" onClick={() => navigate("/employees/list")}>Back</button>
|
|
</h5>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="list row mb-4">
|
|
<div className="col-md-12">
|
|
<div className="mb-3 d-flex align-items-center" style={{ gap: "12px", flexWrap: "wrap" }}>
|
|
<label>
|
|
Filter By Site:
|
|
<select
|
|
className="ms-2"
|
|
value={siteFilter}
|
|
onChange={(e) => setSiteFilter(e.currentTarget.value)}
|
|
>
|
|
<option value="all">All Sites</option>
|
|
<option value={1}>Site 1</option>
|
|
<option value={2}>Site 2</option>
|
|
<option value={3}>Site 3</option>
|
|
<option value={4}>Site 4</option>
|
|
<option value={5}>Site 5</option>
|
|
</select>
|
|
</label>
|
|
<label>
|
|
Filter By Username/Name:
|
|
<input
|
|
className="ms-2"
|
|
type="text"
|
|
value={keyword}
|
|
onChange={(e) => setKeyword(e.currentTarget.value)}
|
|
/>
|
|
</label>
|
|
<button className="btn btn-primary btn-sm" onClick={loadExternalEmployees} disabled={loading}>
|
|
{loading ? "Loading..." : "Refresh"}
|
|
</button>
|
|
</div>
|
|
|
|
{loading ? (
|
|
<div className="py-4"><Spinner size="sm" className="me-2" />Loading employees...</div>
|
|
) : (
|
|
<table className="personnel-info-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Username</th>
|
|
<th>Name</th>
|
|
<th>Title</th>
|
|
<th>Site</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{filteredEmployees.map((item) => (
|
|
<tr key={`${item?.employee_id}-${item?.site}`}>
|
|
<td>{item?.username}</td>
|
|
<td>{item?.name}</td>
|
|
<td>{item?.title}</td>
|
|
<td>{item?.site}</td>
|
|
<td>
|
|
{(() => {
|
|
const hasExistingPermission = !!existingPermissionMap?.[item?.employee_id];
|
|
return (
|
|
<button
|
|
className="btn btn-primary btn-sm"
|
|
onClick={() => openPermissionModal(item)}
|
|
>
|
|
{hasExistingPermission ? "Edit" : "Add"}
|
|
</button>
|
|
);
|
|
})()}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
{filteredEmployees.length === 0 && (
|
|
<tr>
|
|
<td colSpan={5} style={{ textAlign: "center" }}>No active employees found for selected site.</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<Modal show={showPermissionModal} onHide={closePermissionModal} size="lg">
|
|
<Modal.Header closeButton>
|
|
<Modal.Title>Set Permissions - {selectedEmployee?.username}</Modal.Title>
|
|
</Modal.Header>
|
|
<Modal.Body>
|
|
<div className="mb-3">
|
|
<strong>Allow Site:</strong> {selectedAllowSite}
|
|
</div>
|
|
{Object.entries(EMPLOYEE_PERMISSION_GROUPS).map(([groupName, permissionItems]) => (
|
|
<div key={groupName} className="mb-3">
|
|
<div className="d-flex align-items-center justify-content-between mb-1" style={{ gap: "16px" }}>
|
|
<div className="text-primary">{groupName}</div>
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
className="me-2"
|
|
checked={isPermissionGroupFullySelected(permissionItems)}
|
|
onChange={(e) => togglePermissionGroup(permissionItems, e.currentTarget.checked)}
|
|
disabled={groupName === "System"}
|
|
/>
|
|
Select All
|
|
</label>
|
|
</div>
|
|
<div style={{ display: "flex", flexWrap: "wrap", gap: "10px 18px" }}>
|
|
{permissionItems.map((permissionKey) => (
|
|
<label key={permissionKey} style={{ minWidth: "280px" }}>
|
|
<input
|
|
type="checkbox"
|
|
className="me-2"
|
|
checked={selectedPermissions.includes(permissionKey)}
|
|
onChange={() => togglePermission(permissionKey)}
|
|
disabled={permissionKey === SYSTEM_ACCESS_PERMISSION}
|
|
/>
|
|
{permissionKey}
|
|
{permissionKey === SYSTEM_ACCESS_PERMISSION ? " (required)" : ""}
|
|
</label>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</Modal.Body>
|
|
<Modal.Footer>
|
|
<Button variant="secondary" onClick={closePermissionModal} disabled={saving}>
|
|
Cancel
|
|
</Button>
|
|
<Button variant="primary" onClick={savePermissions} disabled={saving}>
|
|
{saving ? <><Spinner size="sm" className="me-2" />Saving...</> : "Done"}
|
|
</Button>
|
|
</Modal.Footer>
|
|
</Modal>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ExternalEmployeesImport;
|