diff --git a/src/client/components/ComicDetail/ComicDetail.tsx b/src/client/components/ComicDetail/ComicDetail.tsx index 631a9c5..5aa7ae1 100644 --- a/src/client/components/ComicDetail/ComicDetail.tsx +++ b/src/client/components/ComicDetail/ComicDetail.tsx @@ -85,6 +85,8 @@ interface ComicDetailProps { updatedAt: string; }; userSettings?: any; + queryClient?: any; + comicObjectId?: string; } interface ComicVineSearchQuery { @@ -132,8 +134,10 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { updatedAt, }, userSettings, + queryClient, + comicObjectId: comicObjectIdProp, } = data; - const [page, setPage] = useState(1); + const [activeTab, setActiveTab] = useState(undefined); const [visible, setVisible] = useState(false); const [slidingPanelContentId, setSlidingPanelContentId] = useState(""); const [modalIsOpen, setIsOpen] = useState(false); @@ -188,6 +192,11 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { props={{ comicVineMatches, comicObjectId, + queryClient, + onMatchApplied: () => { + setVisible(false); + setActiveTab(1); // Switch to Volume Information tab (id: 1) + }, }} /> @@ -521,6 +530,8 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => { { const { comicObjectId } = useParams<{ comicObjectId: string }>(); + const queryClient = useQueryClient(); + const { data: comicBookDetailData, isLoading, isError, } = useQuery({ - queryKey: ["comicBookMetadata"], + queryKey: ["comicBookMetadata", comicObjectId], queryFn: async () => await axios({ url: `${LIBRARY_SERVICE_BASE_URI}/getComicBookById`, @@ -30,6 +32,12 @@ export const ComicDetailContainer = (): ReactElement | null => { isLoading && <>Loading...; } return ( - comicBookDetailData?.data && + comicBookDetailData?.data && ( + + ) ); }; diff --git a/src/client/components/ComicDetail/ComicVineMatchPanel.tsx b/src/client/components/ComicDetail/ComicVineMatchPanel.tsx index 9c858bf..192c4ff 100644 --- a/src/client/components/ComicDetail/ComicVineMatchPanel.tsx +++ b/src/client/components/ComicDetail/ComicVineMatchPanel.tsx @@ -6,7 +6,7 @@ import { useStore } from "../../store"; import { useShallow } from "zustand/react/shallow"; export const ComicVineMatchPanel = (comicVineData): ReactElement => { - const { comicObjectId, comicVineMatches } = comicVineData.props; + const { comicObjectId, comicVineMatches, queryClient, onMatchApplied } = comicVineData.props; const { comicvine } = useStore( useShallow((state) => ({ comicvine: state.comicvine, @@ -19,6 +19,8 @@ export const ComicVineMatchPanel = (comicVineData): ReactElement => { ) : ( <> diff --git a/src/client/components/ComicDetail/MatchResult.tsx b/src/client/components/ComicDetail/MatchResult.tsx index 8c3f689..70b1a7d 100644 --- a/src/client/components/ComicDetail/MatchResult.tsx +++ b/src/client/components/ComicDetail/MatchResult.tsx @@ -8,6 +8,8 @@ import axios from "axios"; interface MatchResultProps { matchData: any; comicObjectId: string; + queryClient?: any; + onMatchApplied?: () => void; } const handleBrokenImage = (e) => { @@ -16,14 +18,33 @@ const handleBrokenImage = (e) => { export const MatchResult = (props: MatchResultProps) => { const applyCVMatch = async (match, comicObjectId) => { - return await axios.request({ - url: `${LIBRARY_SERVICE_BASE_URI}/applyComicVineMetadata`, - method: "POST", - data: { - match, - comicObjectId, - }, - }); + try { + const response = await axios.request({ + url: `${LIBRARY_SERVICE_BASE_URI}/applyComicVineMetadata`, + method: "POST", + data: { + match, + comicObjectId, + }, + }); + + // Invalidate and refetch the comic book metadata + if (props.queryClient) { + await props.queryClient.invalidateQueries({ + queryKey: ["comicBookMetadata", comicObjectId], + }); + } + + // Call the callback to close panel and switch tabs + if (props.onMatchApplied) { + props.onMatchApplied(); + } + + return response; + } catch (error) { + console.error("Error applying ComicVine match:", error); + throw error; + } }; return ( <> diff --git a/src/client/components/ComicDetail/TabControls.tsx b/src/client/components/ComicDetail/TabControls.tsx index e3c5f15..ca1c1f9 100644 --- a/src/client/components/ComicDetail/TabControls.tsx +++ b/src/client/components/ComicDetail/TabControls.tsx @@ -2,8 +2,12 @@ import React, { ReactElement, useState } from "react"; import { isNil } from "lodash"; export const TabControls = (props): ReactElement => { - const { filteredTabs, downloadCount } = props; + const { filteredTabs, downloadCount, activeTab, setActiveTab } = props; const [active, setActive] = useState(filteredTabs[0].id); + + // Use controlled state if provided, otherwise use internal state + const currentActive = activeTab !== undefined ? activeTab : active; + const handleSetActive = activeTab !== undefined ? setActiveTab : setActive; return ( <> @@ -14,12 +18,12 @@ export const TabControls = (props): ReactElement => { setActive(id)} + onClick={() => handleSetActive(id)} > {/* Downloads tab and count badge */} <> @@ -44,7 +48,7 @@ export const TabControls = (props): ReactElement => { {filteredTabs.map(({ id, content }) => { - return active === id ? content : null; + return currentActive === id ? content : null; })} );