Compare commits

...

2 Commits

3 changed files with 127 additions and 42 deletions

View File

@ -86,30 +86,30 @@ export interface MangaListDTO {
export interface PageMangaListDTO { export interface PageMangaListDTO {
totalPages?: number; totalPages?: number;
totalElements?: number; totalElements?: number;
pageable?: PageableObject;
size?: number; size?: number;
content?: MangaListDTO[]; content?: MangaListDTO[];
number?: number; number?: number;
pageable?: PageableObject; sort?: SortObject;
first?: boolean; first?: boolean;
last?: boolean; last?: boolean;
sort?: SortObject;
numberOfElements?: number; numberOfElements?: number;
empty?: boolean; empty?: boolean;
} }
export interface PageableObject { export interface PageableObject {
offset?: number;
pageNumber?: number; pageNumber?: number;
pageSize?: number; pageSize?: number;
paged?: boolean; paged?: boolean;
sort?: SortObject;
unpaged?: boolean; unpaged?: boolean;
offset?: number;
sort?: SortObject;
} }
export interface SortObject { export interface SortObject {
empty?: boolean;
sorted?: boolean; sorted?: boolean;
unsorted?: boolean; unsorted?: boolean;
empty?: boolean;
} }
export interface DefaultResponseDTOListMangaChapterDTO { export interface DefaultResponseDTOListMangaChapterDTO {
@ -152,10 +152,20 @@ export interface MangaDTO {
following: boolean; following: boolean;
} }
export type MangaProviderDTOProviderStatus = typeof MangaProviderDTOProviderStatus[keyof typeof MangaProviderDTOProviderStatus];
// eslint-disable-next-line @typescript-eslint/no-redeclare
export const MangaProviderDTOProviderStatus = {
ACTIVE: 'ACTIVE',
INACTIVE: 'INACTIVE',
} as const;
export interface MangaProviderDTO { export interface MangaProviderDTO {
id: number; id: number;
/** @minLength 1 */ /** @minLength 1 */
providerName: string; providerName: string;
providerStatus: MangaProviderDTOProviderStatus;
chaptersAvailable: number; chaptersAvailable: number;
chaptersDownloaded: number; chaptersDownloaded: number;
supportsChapterFetch: boolean; supportsChapterFetch: boolean;
@ -231,6 +241,10 @@ importReviewId: number;
malId: string; malId: string;
}; };
export type UpdateProviderMangaListParams = {
providerId: number;
};
export type GetMangasParams = { export type GetMangasParams = {
searchQuery?: string; searchQuery?: string;
genreIds?: number[]; genreIds?: number[];

View File

@ -15,7 +15,8 @@ import type {
} from '@tanstack/react-query'; } from '@tanstack/react-query';
import type { import type {
DefaultResponseDTOVoid DefaultResponseDTOVoid,
UpdateProviderMangaListParams
} from '../api.schemas'; } from '../api.schemas';
import { customInstance } from '../../api'; import { customInstance } from '../../api';
@ -89,6 +90,70 @@ export const useUserFollowUpdate = <TError = unknown,
return useMutation(mutationOptions, queryClient); return useMutation(mutationOptions, queryClient);
} }
/** /**
* Queue the retrieval of the manga list for a specific provider
* @summary Queue update provider manga list
*/
export const updateProviderMangaList = (
params: UpdateProviderMangaListParams,
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
) => {
return customInstance<DefaultResponseDTOVoid>(
{url: `/management/update-provider-manga-list`, method: 'POST',
params, signal
},
options);
}
export const getUpdateProviderMangaListMutationOptions = <TError = unknown,
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof updateProviderMangaList>>, TError,{params: UpdateProviderMangaListParams}, TContext>, request?: SecondParameter<typeof customInstance>}
): UseMutationOptions<Awaited<ReturnType<typeof updateProviderMangaList>>, TError,{params: UpdateProviderMangaListParams}, TContext> => {
const mutationKey = ['updateProviderMangaList'];
const {mutation: mutationOptions, request: requestOptions} = options ?
options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ?
options
: {...options, mutation: {...options.mutation, mutationKey}}
: {mutation: { mutationKey, }, request: undefined};
const mutationFn: MutationFunction<Awaited<ReturnType<typeof updateProviderMangaList>>, {params: UpdateProviderMangaListParams}> = (props) => {
const {params} = props ?? {};
return updateProviderMangaList(params,requestOptions)
}
return { mutationFn, ...mutationOptions }}
export type UpdateProviderMangaListMutationResult = NonNullable<Awaited<ReturnType<typeof updateProviderMangaList>>>
export type UpdateProviderMangaListMutationError = unknown
/**
* @summary Queue update provider manga list
*/
export const useUpdateProviderMangaList = <TError = unknown,
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof updateProviderMangaList>>, TError,{params: UpdateProviderMangaListParams}, TContext>, request?: SecondParameter<typeof customInstance>}
, queryClient?: QueryClient): UseMutationResult<
Awaited<ReturnType<typeof updateProviderMangaList>>,
TError,
{params: UpdateProviderMangaListParams},
TContext
> => {
const mutationOptions = getUpdateProviderMangaListMutationOptions(options);
return useMutation(mutationOptions, queryClient);
}
/**
* Queue the retrieval of the manga lists from the content providers * Queue the retrieval of the manga lists from the content providers
* @summary Queue update manga list * @summary Queue update manga list
*/ */

View File

@ -81,11 +81,10 @@ const Manga = () => {
const isPendingFavoriteChange = isPendingFavorite || isPendingUnfavorite; const isPendingFavoriteChange = isPendingFavorite || isPendingUnfavorite;
const handleFavoriteClick = useCallback( const handleFavoriteClick = useCallback(
(isFavorite: boolean) => { (isFavorite: boolean) =>
isFavorite isFavorite
? mutateUnfavorite({ id: mangaData?.data?.id ?? -1 }) ? mutateUnfavorite({ id: mangaData?.data?.id ?? -1 })
: mutateFavorite({ id: mangaData?.data?.id ?? -1 }); : mutateFavorite({ id: mangaData?.data?.id ?? -1 }),
},
[mutateUnfavorite, mutateFavorite, mangaData?.data?.id], [mutateUnfavorite, mutateFavorite, mangaData?.data?.id],
); );
@ -115,11 +114,10 @@ const Manga = () => {
const isPendingFollowChange = isPendingFollow || isPendingUnfollow; const isPendingFollowChange = isPendingFollow || isPendingUnfollow;
const handleFollowClick = useCallback( const handleFollowClick = useCallback(
(isFollowing: boolean) => { (isFollowing: boolean) =>
isFollowing isFollowing
? mutateUnfollow({ mangaId: mangaData?.data?.id ?? -1 }) ? mutateUnfollow({ mangaId: mangaData?.data?.id ?? -1 })
: mutateFollow({ mangaId: mangaData?.data?.id ?? -1 }); : mutateFollow({ mangaId: mangaData?.data?.id ?? -1 }),
},
[mangaData?.data?.id, mutateUnfollow, mutateFollow], [mangaData?.data?.id, mutateUnfollow, mutateFollow],
); );
@ -347,6 +345,13 @@ const Manga = () => {
</h2> </h2>
<div className="space-y-4"> <div className="space-y-4">
{mangaData.data?.providers.length === 0 && (
<div className="flex justify-center">
<p className="text-foreground">
No providers available for this manga.
</p>
</div>
)}
{mangaData.data?.providers.map((provider) => ( {mangaData.data?.providers.map((provider) => (
<Card key={provider.id} className="border-border bg-card"> <Card key={provider.id} className="border-border bg-card">
<Collapsible <Collapsible
@ -368,7 +373,8 @@ const Manga = () => {
</p> </p>
</div> </div>
</div> </div>
{provider.supportsChapterFetch && ( {provider.supportsChapterFetch &&
provider.providerStatus === "ACTIVE" && (
<div className={"flex gap-4 pr-4"}> <div className={"flex gap-4 pr-4"}>
<Button <Button
size="sm" size="sm"