import { useQueryClient } from "@tanstack/react-query";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { Link, matchPath, useLocation, useNavigate, useRoutes } from "react-router";
import { clearToken } from "../auth/token.ts";
import { CloseAbortContext } from "../issues/closeAbort.ts";
import { IssueModal } from "../issues/IssueModal.tsx";
import { cardState, LIST_BACKGROUND } from "../issues/modal.ts";
import { ErrorBoundary } from "./ErrorBoundary.tsx";
import { PAGE_ROUTES } from "./pages.tsx";
import "./shell.css";
export function Layout() {
const qc = useQueryClient();
const location = useLocation();
const navigate = useNavigate();
const issueKey = matchPath("/issues/:key", location.pathname)?.params.key ?? null;
const card = issueKey ? cardState(location.state) : null;
const bgPath = issueKey ? (card?.background ?? LIST_BACKGROUND).pathname : null;
const bgSearch = issueKey ? (card?.background ?? LIST_BACKGROUND).search : "";
// адрес страницы под окном; передаётся в useRoutes всегда (и без окна), чтобы дерево страницы не менялось при
// открытии окна и useSearchParams внутри неё видел её собственный адрес (design 10)
const bgLocation = useMemo(() => bgPath === null ? null : { pathname: bgPath, search: bgSearch, hash: "", state: null, key: "card-background" },
[bgPath, bgSearch]);
const pageLocation = bgLocation ?? location;
const page = useRoutes(PAGE_ROUTES, pageLocation);
// прямой адрес карточки: запись истории получает state окна поверх списка задач (design 11)
useEffect(() => {
if (issueKey && !card) {
void navigate(location.pathname + location.search, { replace: true, state: { background: LIST_BACKGROUND, depth: 0, direct: true } });
}
}, [issueKey, card, location.pathname, location.search, navigate]);
// закрытие (design 12): назад на depth записей; запись прямого адреса, на которую вернулись, заменяется списком
const closingDirect = useRef(false);
useEffect(() => {
if (closingDirect.current && card?.direct && card.depth === 0) {
closingDirect.current = false;
void navigate("/issues", { replace: true });
}
}, [card, navigate]);
const close = useCallback(() => {
if (!card || card.depth === 0) { void navigate("/issues", { replace: true }); return; }
closingDirect.current = card.direct;
void navigate(-card.depth);
}, [card, navigate]);
const abortClose = useCallback(() => { closingDirect.current = false; }, []);
const at = pageLocation.pathname;
const tab = (to: string, label: string) => {
const active = at === to || at.startsWith(to + "/");
return {label};
};
return (
<>
Хаб Jira
{page}
{issueKey && }
>
);
}