typescript
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
export interface DetailDocument {
|
||||
id?: string | number;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface UseDetailPanelOptions {
|
||||
documentLookup: Map<string | number, DetailDocument>;
|
||||
orderedSelectedDocuments: DetailDocument[];
|
||||
}
|
||||
|
||||
interface OpenDetailPanelArgs {
|
||||
documentId?: string | number;
|
||||
document?: DetailDocument | null;
|
||||
documentIds?: Array<string | number>;
|
||||
documents?: DetailDocument[];
|
||||
}
|
||||
|
||||
export const useDetailPanel = ({
|
||||
documentLookup,
|
||||
orderedSelectedDocuments,
|
||||
}: UseDetailPanelOptions) => {
|
||||
const [detailPanelOpen, setDetailPanelOpen] = useState(false);
|
||||
const [detailPanelDocId, setDetailPanelDocId] = useState<string | number | null>(null);
|
||||
const [detailPanelDocument, setDetailPanelDocument] = useState<DetailDocument | null>(null);
|
||||
const latestOrderedDocsRef = useRef<DetailDocument[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
latestOrderedDocsRef.current = orderedSelectedDocuments;
|
||||
if (detailPanelOpen && orderedSelectedDocuments.length) {
|
||||
const nextDoc = orderedSelectedDocuments[orderedSelectedDocuments.length - 1];
|
||||
if (nextDoc?.id) {
|
||||
setDetailPanelDocId(nextDoc.id);
|
||||
setDetailPanelDocument(nextDoc);
|
||||
}
|
||||
}
|
||||
}, [orderedSelectedDocuments, detailPanelOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!detailPanelDocId) {
|
||||
if (!detailPanelOpen) {
|
||||
setDetailPanelDocument(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const resolved = documentLookup.get(detailPanelDocId);
|
||||
if (resolved && resolved !== detailPanelDocument) {
|
||||
setDetailPanelDocument(resolved);
|
||||
}
|
||||
}, [detailPanelDocId, documentLookup, detailPanelDocument, detailPanelOpen]);
|
||||
|
||||
const openDetailPanel = useCallback(
|
||||
({ documentId, document, documentIds, documents }: OpenDetailPanelArgs = {}) => {
|
||||
let targetDoc = document || null;
|
||||
let targetId = documentId ?? document?.id ?? null;
|
||||
|
||||
if (!targetDoc && Array.isArray(documents) && documents.length) {
|
||||
targetDoc = documents[documents.length - 1];
|
||||
targetId = targetDoc?.id ?? targetId;
|
||||
}
|
||||
|
||||
if (!targetDoc && Array.isArray(documentIds) && documentIds.length) {
|
||||
targetId = documentIds[documentIds.length - 1];
|
||||
}
|
||||
|
||||
if (!targetDoc && targetId != null) {
|
||||
targetDoc = documentLookup.get(String(targetId)) || null;
|
||||
}
|
||||
|
||||
if (!targetDoc) {
|
||||
const fallbackDocs = latestOrderedDocsRef.current;
|
||||
const fallbackDoc = Array.isArray(fallbackDocs) && fallbackDocs.length
|
||||
? fallbackDocs[fallbackDocs.length - 1]
|
||||
: null;
|
||||
if (fallbackDoc) {
|
||||
targetDoc = fallbackDoc;
|
||||
targetId = fallbackDoc.id;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetDoc && targetId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDetailPanelDocId(targetDoc?.id ?? targetId ?? null);
|
||||
setDetailPanelDocument(targetDoc || null);
|
||||
setDetailPanelOpen(Boolean(targetDoc || targetId));
|
||||
},
|
||||
[documentLookup],
|
||||
);
|
||||
|
||||
const closeDetailPanel = useCallback(() => {
|
||||
setDetailPanelOpen(false);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
detailPanelOpen,
|
||||
detailPanelDocument,
|
||||
openDetailPanel,
|
||||
closeDetailPanel,
|
||||
setDetailPanelOpen,
|
||||
};
|
||||
};
|
||||
|
||||
export default useDetailPanel;
|
||||
Reference in New Issue
Block a user