diff --git a/src/components/Collection/CollectionView.tsx b/src/components/Collection/CollectionView.tsx index f56126d77..ed3be2bd0 100644 --- a/src/components/Collection/CollectionView.tsx +++ b/src/components/Collection/CollectionView.tsx @@ -25,6 +25,7 @@ type Props = { items: CollectionGroupType[] | SeriesType[]; mode: string; total: number; + setEditSeriesModalId: (seriesId: number) => void; }; const CollectionView = (props: Props) => { @@ -37,6 +38,7 @@ const CollectionView = (props: Props) => { isSidebarOpen, items, mode, + setEditSeriesModalId, total, } = props; @@ -146,7 +148,12 @@ const CollectionView = (props: Props) => { ); } else if (mode === 'poster') { children.push( - , + , ); } else { children.push( @@ -158,6 +165,7 @@ const CollectionView = (props: Props) => { key={`group-${item.IDs.ID}`} isSeries={isSeries} isSidebarOpen={isSidebarOpen} + setEditSeriesModalId={setEditSeriesModalId} />, ); } diff --git a/src/components/Collection/ListViewItem.tsx b/src/components/Collection/ListViewItem.tsx index 55dc2b25b..6c0db7c32 100644 --- a/src/components/Collection/ListViewItem.tsx +++ b/src/components/Collection/ListViewItem.tsx @@ -19,6 +19,7 @@ import { listItemSize } from '@/components/Collection/constants'; import { useSeriesTagsQuery } from '@/core/react-query/series/queries'; import { useSettingsQuery } from '@/core/react-query/settings/queries'; import { dayjs, formatThousand } from '@/core/util'; +import useEventCallback from '@/hooks/useEventCallback'; import useMainPoster from '@/hooks/useMainPoster'; import AnidbDescription from './AnidbDescription'; @@ -58,9 +59,10 @@ type Props = { isSeries?: boolean; groupExtras?: WebuiGroupExtra; isSidebarOpen: boolean; + setEditSeriesModalId: (seriesId: number) => void; }; -const ListViewItem = ({ groupExtras, isSeries, isSidebarOpen, item }: Props) => { +const ListViewItem = ({ groupExtras, isSeries, isSidebarOpen, item, setEditSeriesModalId }: Props) => { const settings = useSettingsQuery().data; const { showCustomTags, showGroupIndicator, showItemType, showTopTags } = settings.WebUI_Settings.collection.list; @@ -120,6 +122,12 @@ const ListViewItem = ({ groupExtras, isSeries, isSidebarOpen, item }: Props) => [isSeries, groupExtras?.Tags, tagsQuery.data, showCustomTags, showTopTags], ); + const editSeriesModalCallback = useEventCallback((event: React.MouseEvent) => { + event.stopPropagation(); + event.preventDefault(); + setEditSeriesModalId(('MainSeries' in item.IDs) ? item.IDs.MainSeries : item.IDs.ID); + }); + return (
zoomOnHover >
- - - + {(isSeries || item.Size === 1) && ( +
+ +
+ )}
{showGroupIndicator && groupCount > 1 && (
diff --git a/src/components/Collection/PosterViewItem.tsx b/src/components/Collection/PosterViewItem.tsx index c2db73d24..9487fcd12 100644 --- a/src/components/Collection/PosterViewItem.tsx +++ b/src/components/Collection/PosterViewItem.tsx @@ -6,6 +6,7 @@ import { reduce } from 'lodash'; import BackgroundImagePlaceholderDiv from '@/components/BackgroundImagePlaceholderDiv'; import { useSettingsQuery } from '@/core/react-query/settings/queries'; +import useEventCallback from '@/hooks/useEventCallback'; import useMainPoster from '@/hooks/useMainPoster'; import type { CollectionGroupType } from '@/core/types/api/collection'; @@ -14,9 +15,10 @@ import type { SeriesType } from '@/core/types/api/series'; type Props = { item: CollectionGroupType | SeriesType; isSeries?: boolean; + setEditSeriesModalId: (seriesId: number) => void; }; -const PosterViewItem = ({ isSeries = false, item }: Props) => { +const PosterViewItem = ({ isSeries = false, item, setEditSeriesModalId }: Props) => { const settings = useSettingsQuery().data; const { showEpisodeCount, showGroupIndicator, showUnwatchedCount } = settings.WebUI_Settings.collection.poster; @@ -43,6 +45,12 @@ const PosterViewItem = ({ isSeries = false, item }: Props) => { return link; }; + const editSeriesModalCallback = useEventCallback((event: React.MouseEvent) => { + event.stopPropagation(); + event.preventDefault(); + setEditSeriesModalId(('MainSeries' in item.IDs) ? item.IDs.MainSeries : item.IDs.ID); + }); + return (
{ )}
)} -
- {/* FIXME: This can't be a otherwise Warning: validateDOMNesting(...): cannot appear as a descendant of happens, BackgroundImagePlaceholderDiv wraps everything in a internally */} - - - +
+ {(isSeries || item.Size === 1) && ( +
+ +
+ )}
{showGroupIndicator && !isSeries && groupCount > 1 && (
diff --git a/src/components/Collection/Series/EditSeriesModal.tsx b/src/components/Collection/Series/EditSeriesModal.tsx index 2d16c6cfe..199f67257 100644 --- a/src/components/Collection/Series/EditSeriesModal.tsx +++ b/src/components/Collection/Series/EditSeriesModal.tsx @@ -15,7 +15,7 @@ import ModalPanel from '@/components/Panels/ModalPanel'; type Props = { show: boolean; onClose: () => void; - seriesId: number; + seriesId?: number; }; const tabs = { @@ -50,33 +50,35 @@ const EditSeriesModal = (props: Props) => { const [activeTab, setActiveTab] = useState('update_actions'); - return ( - -
-
-
- {map(tabs, (value, key) => ( -
setActiveTab(key)} - > - {value} -
- ))} + return (!seriesId) + ? null + : ( + +
+
+
+ {map(tabs, (value, key) => ( +
setActiveTab(key)} + > + {value} +
+ ))} +
+
+
+
+ {renderTab(activeTab, seriesId)}
-
-
- {renderTab(activeTab, seriesId)} -
-
- - ); + + ); }; export default EditSeriesModal; diff --git a/src/components/Collection/Series/EditSeriesTabs/NameTab.tsx b/src/components/Collection/Series/EditSeriesTabs/NameTab.tsx index de3a71cef..36c02558b 100644 --- a/src/components/Collection/Series/EditSeriesTabs/NameTab.tsx +++ b/src/components/Collection/Series/EditSeriesTabs/NameTab.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useMemo, useState } from 'react'; import { mdiCheckUnderlineCircleOutline, mdiCloseCircleOutline, mdiPencilCircleOutline } from '@mdi/js'; import cx from 'classnames'; -import { map } from 'lodash'; import { useToggle } from 'usehooks-ts'; import Input from '@/components/Input/Input'; @@ -9,8 +8,6 @@ import toast from '@/components/Toast'; import { useOverrideSeriesTitleMutation } from '@/core/react-query/series/mutations'; import { useSeriesQuery } from '@/core/react-query/series/queries'; -import type { SeriesType } from '@/core/types/api/series'; - type Props = { seriesId: number; }; @@ -19,17 +16,16 @@ const NameTab = ({ seriesId }: Props) => { const [name, setName] = useState(''); const [nameEditable, toggleNameEditable] = useToggle(false); - const seriesQuery = useSeriesQuery(seriesId, { includeDataFrom: ['AniDB'] }); - const series = useMemo(() => seriesQuery?.data ?? {} as SeriesType, [seriesQuery.data]); + const { data: seriesData, isError, isFetching, isSuccess } = useSeriesQuery(seriesId, { includeDataFrom: ['AniDB'] }); const { mutate: overrideTitle } = useOverrideSeriesTitleMutation(); useEffect(() => { - setName(series.Name ?? ''); - }, [series.Name]); + setName(seriesData?.Name ?? ''); + }, [seriesData?.Name]); const nameInputIcons = useMemo(() => { - if (!nameEditable || seriesQuery.isFetching) { + if (!nameEditable || isFetching) { return [{ icon: mdiPencilCircleOutline, className: 'text-panel-text-primary', @@ -37,12 +33,14 @@ const NameTab = ({ seriesId }: Props) => { }]; } + if (!isSuccess) return []; + return [ { icon: mdiCloseCircleOutline, className: 'text-panel-text-danger', onClick: () => { - setName(series.Name); + setName(seriesData.Name ?? ''); toggleNameEditable(); }, }, @@ -50,7 +48,7 @@ const NameTab = ({ seriesId }: Props) => { icon: mdiCheckUnderlineCircleOutline, className: 'text-panel-text-primary', onClick: () => - overrideTitle({ seriesId: series.IDs.ID, Title: name }, { + overrideTitle({ seriesId: seriesData.IDs.ID, Title: name }, { onSuccess: () => { toast.success('Name updated successfully!'); toggleNameEditable(); @@ -59,11 +57,20 @@ const NameTab = ({ seriesId }: Props) => { }), }, ]; - }, [name, nameEditable, overrideTitle, series.IDs.ID, series.Name, seriesQuery.isFetching, toggleNameEditable]); + }, [ + isFetching, + isSuccess, + name, + nameEditable, + overrideTitle, + seriesData?.IDs.ID, + seriesData?.Name, + toggleNameEditable, + ]); return (
- {seriesQuery.isError && ( + {isError && (
Series data could not be loaded!
@@ -74,6 +81,7 @@ const NameTab = ({ seriesId }: Props) => { type="text" onChange={e => setName(e.target.value)} value={name} + placeholder="Loading..." label="Name" className="mb-4" inputClassName={cx(nameInputIcons.length > 1 ? 'pr-[4.5rem]' : 'pr-10', 'truncate')} @@ -83,7 +91,7 @@ const NameTab = ({ seriesId }: Props) => { {nameEditable && (
- {map(series.AniDB?.Titles, title => ( + {seriesData?.AniDB?.Titles.map(title => (
(); + const openEditModalWithSeriesId = useEventCallback((seriesId: number) => { + setEditSeriesModalId(() => { + toggleEditSeriesModal(); + return seriesId; + }); + }); + const { mutate: patchSettings } = usePatchSettingsMutation(); useEffect(() => { @@ -230,6 +240,7 @@ function Collection() { items={items} mode={mode} total={total} + setEditSeriesModalId={openEditModalWithSeriesId} />
{isSeries && }
+
); }