237 lines
6.4 KiB
TypeScript
237 lines
6.4 KiB
TypeScript
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
import type { ReactNode } from 'react';
|
|
import TagsPanel from '../tags/TagsPanel';
|
|
import CorrespondentsPanel, { CorrespondentsPanelProps } from '../correspondents/CorrespondentsPanel';
|
|
import PanelHeader from '../ui/PanelHeader';
|
|
|
|
const TAGS_MODAL = 'tags';
|
|
const CORRESPONDENTS_MODAL = 'correspondents';
|
|
|
|
interface TagRecord {
|
|
id?: string | number;
|
|
label?: string;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
interface CorrespondentRecord {
|
|
id?: string | number;
|
|
name?: string;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
interface UseManagementModalsArgs {
|
|
locationPathname?: string;
|
|
tags?: TagRecord[];
|
|
refreshTags?: () => void | Promise<void>;
|
|
onTagCreate?: (...args: any[]) => void | Promise<void>;
|
|
onTagUpdate?: (...args: any[]) => void | Promise<void>;
|
|
onTagDelete?: (...args: any[]) => void | Promise<void>;
|
|
correspondents?: CorrespondentRecord[];
|
|
refreshCorrespondents?: () => void | Promise<void>;
|
|
onCorrespondentCreate?: (...args: any[]) => void | Promise<void>;
|
|
onCorrespondentUpdate?: (...args: any[]) => void | Promise<void>;
|
|
onCorrespondentDelete?: (...args: any[]) => void | Promise<void>;
|
|
setStatusMessage?: (message: string, variant?: string) => void;
|
|
}
|
|
|
|
interface UseManagementModalsResult {
|
|
managementModals: ReactNode;
|
|
openTagsModal: () => void;
|
|
openCorrespondentsModal: () => void;
|
|
closeActiveModal: () => void;
|
|
activeModal: string | null;
|
|
}
|
|
|
|
export const useManagementModals = ({
|
|
locationPathname,
|
|
tags = [],
|
|
refreshTags,
|
|
onTagCreate,
|
|
onTagUpdate,
|
|
onTagDelete,
|
|
correspondents = [],
|
|
refreshCorrespondents,
|
|
onCorrespondentCreate,
|
|
onCorrespondentUpdate,
|
|
onCorrespondentDelete,
|
|
setStatusMessage,
|
|
}: UseManagementModalsArgs): UseManagementModalsResult => {
|
|
const [activeModal, setActiveModal] = useState<string | null>(null);
|
|
|
|
const openTagsModal = useCallback(() => setActiveModal(TAGS_MODAL), []);
|
|
const openCorrespondentsModal = useCallback(
|
|
() => setActiveModal(CORRESPONDENTS_MODAL),
|
|
[],
|
|
);
|
|
const closeActiveModal = useCallback(() => setActiveModal(null), []);
|
|
|
|
useEffect(() => {
|
|
setActiveModal(null);
|
|
}, [locationPathname]);
|
|
|
|
useEffect(() => {
|
|
if (!activeModal) {
|
|
return undefined;
|
|
}
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
if (event.key === 'Escape') {
|
|
event.preventDefault();
|
|
setActiveModal(null);
|
|
}
|
|
};
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [activeModal]);
|
|
|
|
const tagModal = useMemo(() => {
|
|
if (activeModal !== TAGS_MODAL) {
|
|
return null;
|
|
}
|
|
return (
|
|
<div
|
|
className="modal-backdrop"
|
|
role="presentation"
|
|
onClick={closeActiveModal}
|
|
>
|
|
<div
|
|
className="modal modal--panel"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="tags-modal-title"
|
|
onClick={(event) => event.stopPropagation()}
|
|
>
|
|
<PanelHeader
|
|
className="panel-modal__header"
|
|
title="Manage Tags"
|
|
titleTag="h3"
|
|
titleProps={{ id: 'tags-modal-title' }}
|
|
actions={(
|
|
<button type="button" className="secondary" onClick={closeActiveModal}>
|
|
Close
|
|
</button>
|
|
)}
|
|
/>
|
|
<div className="panel-modal__body">
|
|
<TagsPanel
|
|
tags={tags}
|
|
onRefresh={refreshTags}
|
|
onCreateTag={onTagCreate}
|
|
onUpdateTag={onTagUpdate}
|
|
onDeleteTag={onTagDelete}
|
|
onNotify={setStatusMessage}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}, [
|
|
activeModal,
|
|
closeActiveModal,
|
|
onTagCreate,
|
|
onTagDelete,
|
|
onTagUpdate,
|
|
refreshTags,
|
|
setStatusMessage,
|
|
tags,
|
|
]);
|
|
|
|
const handleCorrespondentCreateSafe = useCallback<CorrespondentsPanelProps['onCreate']>(
|
|
async (payload) => {
|
|
if (typeof onCorrespondentCreate !== 'function') {
|
|
return undefined;
|
|
}
|
|
return onCorrespondentCreate(payload) ?? undefined;
|
|
},
|
|
[onCorrespondentCreate],
|
|
);
|
|
|
|
const handleCorrespondentUpdateSafe = useCallback<CorrespondentsPanelProps['onUpdate']>(
|
|
async (id, payload) => {
|
|
if (typeof onCorrespondentUpdate !== 'function') {
|
|
return;
|
|
}
|
|
await onCorrespondentUpdate(id, payload);
|
|
},
|
|
[onCorrespondentUpdate],
|
|
);
|
|
|
|
const handleCorrespondentDeleteSafe = useCallback<CorrespondentsPanelProps['onDelete']>(
|
|
async (id) => {
|
|
if (typeof onCorrespondentDelete !== 'function') {
|
|
return;
|
|
}
|
|
await onCorrespondentDelete(id);
|
|
},
|
|
[onCorrespondentDelete],
|
|
);
|
|
|
|
const correspondentsModal = useMemo(() => {
|
|
if (activeModal !== CORRESPONDENTS_MODAL) {
|
|
return null;
|
|
}
|
|
return (
|
|
<div
|
|
className="modal-backdrop"
|
|
role="presentation"
|
|
onClick={closeActiveModal}
|
|
>
|
|
<div
|
|
className="modal modal--panel"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="correspondents-modal-title"
|
|
onClick={(event) => event.stopPropagation()}
|
|
>
|
|
<PanelHeader
|
|
className="panel-modal__header"
|
|
title="Manage Correspondents"
|
|
titleTag="h3"
|
|
titleProps={{ id: 'correspondents-modal-title' }}
|
|
actions={(
|
|
<button type="button" className="secondary" onClick={closeActiveModal}>
|
|
Close
|
|
</button>
|
|
)}
|
|
/>
|
|
<div className="panel-modal__body">
|
|
<CorrespondentsPanel
|
|
correspondents={correspondents}
|
|
onRefresh={refreshCorrespondents}
|
|
onCreate={handleCorrespondentCreateSafe}
|
|
onUpdate={handleCorrespondentUpdateSafe}
|
|
onDelete={handleCorrespondentDeleteSafe}
|
|
onNotify={setStatusMessage}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}, [
|
|
activeModal,
|
|
closeActiveModal,
|
|
correspondents,
|
|
handleCorrespondentCreateSafe,
|
|
handleCorrespondentDeleteSafe,
|
|
handleCorrespondentUpdateSafe,
|
|
refreshCorrespondents,
|
|
setStatusMessage,
|
|
]);
|
|
|
|
const managementModals = (
|
|
<>
|
|
{tagModal}
|
|
{correspondentsModal}
|
|
</>
|
|
);
|
|
|
|
return {
|
|
managementModals,
|
|
openTagsModal,
|
|
openCorrespondentsModal,
|
|
closeActiveModal,
|
|
activeModal,
|
|
};
|
|
};
|
|
|
|
export default useManagementModals;
|