- Updated Mini App design guidelines to include detailed instructions on UI changes, accessibility rules, and verification processes. - Refactored multiple components to utilize `MiniAppScreen` and `MiniAppScreenContent` for consistent layout structure across the application. - Improved error handling in `GlobalError` and `NotFound` components by integrating new layout components for better user experience. - Introduced new hooks for admin functionality, streamlining access checks and data loading processes. - Enhanced documentation to reflect changes in design policies and component usage, ensuring clarity for future development.
117 lines
3.6 KiB
TypeScript
117 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import { useCallback, useEffect, useState, type Dispatch, type SetStateAction } from "react";
|
|
import { AccessDeniedError, patchAdminDuty, type UserForAdmin } from "@/lib/api";
|
|
import { triggerHapticLight } from "@/lib/telegram-haptic";
|
|
import type { DutyWithUser } from "@/types";
|
|
|
|
export interface UseAdminReassignOptions {
|
|
initDataRaw: string | undefined;
|
|
lang: "ru" | "en";
|
|
users: UserForAdmin[];
|
|
setDuties: Dispatch<SetStateAction<DutyWithUser[]>>;
|
|
t: (key: string, params?: Record<string, string>) => string;
|
|
}
|
|
|
|
export function useAdminReassign({
|
|
initDataRaw,
|
|
lang,
|
|
users,
|
|
setDuties,
|
|
t,
|
|
}: UseAdminReassignOptions) {
|
|
const [selectedDuty, setSelectedDuty] = useState<DutyWithUser | null>(null);
|
|
const [selectedUserId, setSelectedUserId] = useState<number | "">("");
|
|
const [saving, setSaving] = useState(false);
|
|
const [reassignErrorKey, setReassignErrorKey] = useState<string | null>(null);
|
|
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
|
const [sheetExiting, setSheetExiting] = useState(false);
|
|
|
|
const closeReassign = useCallback(() => {
|
|
setSelectedDuty(null);
|
|
setSelectedUserId("");
|
|
setReassignErrorKey(null);
|
|
setSheetExiting(false);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (!sheetExiting) return;
|
|
const fallback = window.setTimeout(() => {
|
|
closeReassign();
|
|
}, 320);
|
|
return () => window.clearTimeout(fallback);
|
|
}, [sheetExiting, closeReassign]);
|
|
|
|
const openReassign = useCallback((duty: DutyWithUser) => {
|
|
setSelectedDuty(duty);
|
|
setSelectedUserId(duty.user_id);
|
|
setReassignErrorKey(null);
|
|
}, []);
|
|
|
|
const requestCloseSheet = useCallback(() => {
|
|
setSheetExiting(true);
|
|
}, []);
|
|
|
|
const handleReassign = useCallback(() => {
|
|
if (!selectedDuty || selectedUserId === "" || !initDataRaw) return;
|
|
if (selectedUserId === selectedDuty.user_id) {
|
|
closeReassign();
|
|
return;
|
|
}
|
|
setSaving(true);
|
|
setReassignErrorKey(null);
|
|
patchAdminDuty(selectedDuty.id, selectedUserId, initDataRaw, lang)
|
|
.then((updated) => {
|
|
setDuties((prev) =>
|
|
prev.map((d) =>
|
|
d.id === updated.id
|
|
? {
|
|
...d,
|
|
user_id: updated.user_id,
|
|
full_name:
|
|
users.find((u) => u.id === updated.user_id)?.full_name ?? d.full_name,
|
|
}
|
|
: d
|
|
)
|
|
);
|
|
setSuccessMessage(t("admin.reassign_success"));
|
|
try {
|
|
triggerHapticLight();
|
|
} catch {
|
|
// Haptic not available (e.g. non-Telegram).
|
|
}
|
|
requestCloseSheet();
|
|
setTimeout(() => setSuccessMessage(null), 3000);
|
|
})
|
|
.catch((e) => {
|
|
if (e instanceof AccessDeniedError) {
|
|
setReassignErrorKey("admin.reassign_error_denied");
|
|
} else if (e instanceof Error && /not found|не найден/i.test(e.message)) {
|
|
setReassignErrorKey("admin.reassign_error_not_found");
|
|
} else if (
|
|
e instanceof TypeError ||
|
|
(e instanceof Error && (e.message === "Failed to fetch" || e.message === "Load failed"))
|
|
) {
|
|
setReassignErrorKey("admin.reassign_error_network");
|
|
} else {
|
|
setReassignErrorKey("admin.reassign_error_generic");
|
|
}
|
|
})
|
|
.finally(() => setSaving(false));
|
|
}, [selectedDuty, selectedUserId, initDataRaw, lang, users, closeReassign, requestCloseSheet, t, setDuties]);
|
|
|
|
return {
|
|
selectedDuty,
|
|
selectedUserId,
|
|
setSelectedUserId,
|
|
saving,
|
|
reassignErrorKey,
|
|
successMessage,
|
|
sheetExiting,
|
|
openReassign,
|
|
requestCloseSheet,
|
|
handleReassign,
|
|
closeReassign,
|
|
};
|
|
}
|