fix(frontend): surface department employee loading errors
This commit is contained in:
parent
d1a7eedcee
commit
edc770dc83
@ -398,6 +398,7 @@ function DepartmentMembersEmptyState() {
|
||||
|
||||
function AddMemberModal({
|
||||
canAssignRoles,
|
||||
directoryError,
|
||||
isOpen,
|
||||
items,
|
||||
loading,
|
||||
@ -405,6 +406,7 @@ function AddMemberModal({
|
||||
optionsLoading,
|
||||
onClose,
|
||||
onCreateRole,
|
||||
onRetryEmployees,
|
||||
onSave,
|
||||
onSelect,
|
||||
onSelectRole,
|
||||
@ -413,6 +415,7 @@ function AddMemberModal({
|
||||
selectedRoleId,
|
||||
}: {
|
||||
canAssignRoles: boolean;
|
||||
directoryError: string | null;
|
||||
isOpen: boolean;
|
||||
items: Array<{ id: number; name: string }>;
|
||||
loading: boolean;
|
||||
@ -420,6 +423,7 @@ function AddMemberModal({
|
||||
optionsLoading: boolean;
|
||||
onClose: () => void;
|
||||
onCreateRole: () => void;
|
||||
onRetryEmployees: () => Promise<void>;
|
||||
onSave: () => Promise<void>;
|
||||
onSelect: (id: number | null) => void;
|
||||
onSelectRole: (id: number | null) => void;
|
||||
@ -432,7 +436,7 @@ function AddMemberModal({
|
||||
optionsLoading,
|
||||
items.length,
|
||||
);
|
||||
const selectDisabled = optionsLoading || items.length === 0;
|
||||
const selectDisabled = optionsLoading || !!directoryError || items.length === 0;
|
||||
const submitDisabled = isDepartmentMemberModalSubmitDisabled({
|
||||
loading,
|
||||
mode,
|
||||
@ -477,7 +481,20 @@ function AddMemberModal({
|
||||
disabled={selectDisabled}
|
||||
/>
|
||||
|
||||
{canAssignRoles ? (
|
||||
{directoryError ? (
|
||||
<div className="app-feedback-danger rounded-xl p-3 text-sm">
|
||||
<p>{directoryError}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void onRetryEmployees()}
|
||||
className="app-action-secondary mt-3 inline-flex rounded-lg px-3 py-2 text-sm"
|
||||
>
|
||||
Повторить загрузку
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{canAssignRoles && !directoryError ? (
|
||||
<div className="space-y-3">
|
||||
<SearchableSelectSingle
|
||||
label={mode === "assignRole" ? "Роль *" : "Роль"}
|
||||
@ -509,7 +526,7 @@ function AddMemberModal({
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{helperText ? (
|
||||
{!directoryError && helperText ? (
|
||||
<p className="app-text-muted mt-3 text-sm">
|
||||
{helperText}
|
||||
</p>
|
||||
@ -855,6 +872,7 @@ export default function DepartmentDetailPage() {
|
||||
|
||||
<AddMemberModal
|
||||
canAssignRoles={h.userPerms.can_assign_roles}
|
||||
directoryError={h.employeesDirectoryError}
|
||||
isOpen={h.addMemberOpen}
|
||||
items={getDepartmentMemberModalItems(
|
||||
h.memberModalMode,
|
||||
@ -869,6 +887,7 @@ export default function DepartmentDetailPage() {
|
||||
h.closeAddMember();
|
||||
h.openCreateRole();
|
||||
}}
|
||||
onRetryEmployees={h.reloadEmployeesDirectory}
|
||||
onSave={h.submitAddMember}
|
||||
onSelect={h.setSelectedMemberId}
|
||||
onSelectRole={h.setSelectedRoleId}
|
||||
|
||||
@ -41,6 +41,7 @@ export type DepartmentPageController = {
|
||||
departmentDraft: { name: string; description: string };
|
||||
departmentId: number;
|
||||
editDepartmentOpen: boolean;
|
||||
employeesDirectoryError: string | null;
|
||||
error: string | null;
|
||||
filteredMembers: DepartmentMemberLink[];
|
||||
headCandidates: Array<{ id: number; name: string }>;
|
||||
@ -66,6 +67,7 @@ export type DepartmentPageController = {
|
||||
openCreateRole: () => void;
|
||||
openDepartmentEditor: () => void;
|
||||
openEditRole: (role: DepartmentRole) => void;
|
||||
reloadEmployeesDirectory: () => Promise<void>;
|
||||
refreshPage: () => Promise<void>;
|
||||
saveDepartment: () => Promise<void>;
|
||||
saveRole: () => Promise<void>;
|
||||
@ -136,6 +138,7 @@ export function useDepartmentPage(departmentId: number): DepartmentPageControlle
|
||||
const [userPerms, setUserPerms] = useState<DepartmentUserPermissions | null>(null);
|
||||
const [allEmployees, setAllEmployees] = useState<User[]>([]);
|
||||
const [employeesDirectoryLoading, setEmployeesDirectoryLoading] = useState(false);
|
||||
const [employeesDirectoryError, setEmployeesDirectoryError] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [pendingKey, setPendingKey] = useState<SavingKey | null>(null);
|
||||
@ -166,9 +169,14 @@ export function useDepartmentPage(departmentId: number): DepartmentPageControlle
|
||||
|
||||
const loadEmployeesDirectory = useCallback(async () => {
|
||||
setEmployeesDirectoryLoading(true);
|
||||
setEmployeesDirectoryError(null);
|
||||
try {
|
||||
const employees = await loadAllPages<User>((params) => apiClient.getEmployees(params));
|
||||
setAllEmployees(sortEmployeesByName(employees.filter((employee) => employee.is_active)));
|
||||
} catch (loadError) {
|
||||
const message = getErrorMessage(loadError, "Не удалось загрузить сотрудников");
|
||||
setEmployeesDirectoryError(message);
|
||||
throw loadError;
|
||||
} finally {
|
||||
setEmployeesDirectoryLoading(false);
|
||||
}
|
||||
@ -232,7 +240,12 @@ export function useDepartmentPage(departmentId: number): DepartmentPageControlle
|
||||
}, [loadCore]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!userPerms || (!userPerms.can_manage && !userPerms.can_change_head)) {
|
||||
if (
|
||||
!userPerms ||
|
||||
(!userPerms.can_manage &&
|
||||
!userPerms.can_change_head &&
|
||||
!userPerms.can_assign_roles)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (allEmployees.length > 0) {
|
||||
@ -292,6 +305,10 @@ export function useDepartmentPage(departmentId: number): DepartmentPageControlle
|
||||
await loadCore();
|
||||
}, [loadCore]);
|
||||
|
||||
const reloadEmployeesDirectory = useCallback(async () => {
|
||||
await loadEmployeesDirectory();
|
||||
}, [loadEmployeesDirectory]);
|
||||
|
||||
const updateDepartmentDraft = useCallback((patch: Partial<{ name: string; description: string }>) => {
|
||||
setDepartmentDraft((current) => ({ ...current, ...patch }));
|
||||
}, []);
|
||||
@ -606,6 +623,7 @@ export function useDepartmentPage(departmentId: number): DepartmentPageControlle
|
||||
departmentDraft,
|
||||
departmentId,
|
||||
editDepartmentOpen,
|
||||
employeesDirectoryError,
|
||||
employeesDirectoryLoading,
|
||||
error,
|
||||
filteredMembers,
|
||||
@ -631,6 +649,7 @@ export function useDepartmentPage(departmentId: number): DepartmentPageControlle
|
||||
openCreateRole,
|
||||
openDepartmentEditor,
|
||||
openEditRole,
|
||||
reloadEmployeesDirectory,
|
||||
refreshPage,
|
||||
saveDepartment,
|
||||
saveRole,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user