"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>; t: (key: string, params?: Record) => string; } export function useAdminReassign({ initDataRaw, lang, users, setDuties, t, }: UseAdminReassignOptions) { const [selectedDuty, setSelectedDuty] = useState(null); const [selectedUserId, setSelectedUserId] = useState(""); const [saving, setSaving] = useState(false); const [reassignErrorKey, setReassignErrorKey] = useState(null); const [successMessage, setSuccessMessage] = useState(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, }; }