From a7058346a5481a5f370c21af5fd9718ef30b6bf6 Mon Sep 17 00:00:00 2001
From: Rodrigo Verdiani
Date: Fri, 10 Apr 2026 10:13:49 -0300
Subject: [PATCH 1/3] feat: add support for content fetch in provider manager
and display update button conditionally
---
src/api/generated/api.schemas.ts | 5 +-
.../admin/components/ProviderManager.tsx | 61 ++++++++++++-------
2 files changed, 42 insertions(+), 24 deletions(-)
diff --git a/src/api/generated/api.schemas.ts b/src/api/generated/api.schemas.ts
index 8ef277f..72312cc 100644
--- a/src/api/generated/api.schemas.ts
+++ b/src/api/generated/api.schemas.ts
@@ -117,6 +117,7 @@ export interface ContentProviderDTO {
name: string;
url?: string;
active?: boolean;
+ supportsContentFetch?: boolean;
}
export interface ContentProviderListDTO {
@@ -214,9 +215,9 @@ export interface PageMangaImportJobDTO {
number?: number;
pageable?: PageableObject;
numberOfElements?: number;
+ sort?: SortObject;
first?: boolean;
last?: boolean;
- sort?: SortObject;
empty?: boolean;
}
@@ -277,9 +278,9 @@ export interface PageMangaListDTO {
number?: number;
pageable?: PageableObject;
numberOfElements?: number;
+ sort?: SortObject;
first?: boolean;
last?: boolean;
- sort?: SortObject;
empty?: boolean;
}
diff --git a/src/features/admin/components/ProviderManager.tsx b/src/features/admin/components/ProviderManager.tsx
index 19fed53..d533001 100644
--- a/src/features/admin/components/ProviderManager.tsx
+++ b/src/features/admin/components/ProviderManager.tsx
@@ -7,6 +7,7 @@ import {
import { Badge } from "@/components/ui/badge.tsx";
import { Button } from "@/components/ui/button.tsx";
import { Card } from "@/components/ui/card.tsx";
+import {toast} from "sonner";
export const ProviderManager = () => {
const { data } = useGetContentProviders();
@@ -15,12 +16,26 @@ export const ProviderManager = () => {
const {
mutate: mutateFetchContentProviderMangas,
isPending: isPendingFetchContentProviderMangas,
- } = useFetchContentProviderMangas();
+ } = useFetchContentProviderMangas({
+ mutation: {
+ onSuccess: () => {
+ toast.success("Content Provider mangas update queued successfully!");
+ },
+ },
+ });
const {
mutate: mutateFetchAllContentProviderMangas,
isPending: isPendingFetchAllContentProviderMangas,
- } = useFetchAllContentProviderMangas();
+ } = useFetchAllContentProviderMangas(
+ {
+ mutation: {
+ onSuccess: () => {
+ toast.success("All Content Provider mangas update queued successfully!");
+ },
+ },
+ }
+ );
const activeCount = providers?.filter((p) => p.active).length;
@@ -104,26 +119,28 @@ export const ProviderManager = () => {
-
+ {provider.supportsContentFetch && (
+
+ )}
);
--
2.49.1
From 9f1dddb057b92cfb822177c139a138eb54253a92 Mon Sep 17 00:00:00 2001
From: Rodrigo Verdiani
Date: Fri, 10 Apr 2026 10:53:42 -0300
Subject: [PATCH 2/3] feat: add loading states with skeletons and spinners in
admin components
---
.../admin/components/FailedImportJobs.tsx | 56 +++++++++++++------
.../admin/components/IngestReview.tsx | 53 +++++++++++++++++-
src/pages/Admin.tsx | 48 ++++++++++++++++
src/pages/Manga.tsx | 26 +++++----
4 files changed, 152 insertions(+), 31 deletions(-)
diff --git a/src/features/admin/components/FailedImportJobs.tsx b/src/features/admin/components/FailedImportJobs.tsx
index d7714a3..ee0732b 100644
--- a/src/features/admin/components/FailedImportJobs.tsx
+++ b/src/features/admin/components/FailedImportJobs.tsx
@@ -18,6 +18,8 @@ import {
DialogTitle,
} from "@/components/ui/dialog.tsx";
import { Input } from "@/components/ui/input.tsx";
+import { Skeleton } from "@/components/ui/skeleton.tsx";
+import { Spinner } from "@/components/ui/spinner.tsx";
import {
Select,
SelectContent,
@@ -46,7 +48,7 @@ export const FailedImportJobs = () => {
const [errorDialogOpen, setErrorDialogOpen] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
- const { data } = useGetMangaImportJobs({
+ const { data, isPending } = useGetMangaImportJobs({
status: statusFilter,
searchQuery: searchQuery,
page: currentPage - 1,
@@ -54,6 +56,41 @@ export const FailedImportJobs = () => {
});
const importJobsData = data?.data;
+ if (isPending) {
+ return (
+
+
+
+
+
+
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleString("en-US", {
year: "numeric",
@@ -328,23 +365,6 @@ export const FailedImportJobs = () => {
>
Close
- {/**/}
)}
diff --git a/src/features/admin/components/IngestReview.tsx b/src/features/admin/components/IngestReview.tsx
index ad66fd4..197fef6 100644
--- a/src/features/admin/components/IngestReview.tsx
+++ b/src/features/admin/components/IngestReview.tsx
@@ -2,9 +2,60 @@ import {Card} from "@/components/ui/card.tsx";
import {AlertCircle} from "lucide-react";
import {useGetMangaIngestReviews} from "@/api/generated/manga-ingest-review/manga-ingest-review.ts";
import {ImportReviewCard} from "@/features/admin/components/ImportReviewCard.tsx";
+import {Skeleton} from "@/components/ui/skeleton.tsx";
+import {Spinner} from "@/components/ui/spinner.tsx";
export const IngestReview = () => {
- const { data: importReviewData, queryKey } = useGetMangaIngestReviews();
+ const { data: importReviewData, queryKey, isPending } = useGetMangaIngestReviews();
+
+ if (isPending) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {Array.from({ length: 2 }).map((_, i) => (
+
+
+
+ ))}
+
+ );
+ }
return (
diff --git a/src/pages/Admin.tsx b/src/pages/Admin.tsx
index 8b8f74e..d421e17 100644
--- a/src/pages/Admin.tsx
+++ b/src/pages/Admin.tsx
@@ -2,6 +2,8 @@ import {AlertCircle, ArrowLeft, Download, FileStack, Server, Shield} from "lucid
import { type ReactNode, useEffect, useState } from "react";
import { useNavigate } from "react-router";
import { Button } from "@/components/ui/button.tsx";
+import { Skeleton } from "@/components/ui/skeleton.tsx";
+import { Spinner } from "@/components/ui/spinner.tsx";
import { useAuth } from "@/contexts/AuthContext.tsx";
import { FailedImportJobs } from "@/features/admin/components/FailedImportJobs.tsx";
import { ProviderManager } from "@/features/admin/components/ProviderManager.tsx";
@@ -70,6 +72,52 @@ const Admin = () => {
// },
];
+ if (isLoading) {
+ return (
+
+
+
+
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/Manga.tsx b/src/pages/Manga.tsx
index 976b24c..ee154c7 100644
--- a/src/pages/Manga.tsx
+++ b/src/pages/Manga.tsx
@@ -249,18 +249,20 @@ const Manga = () => {
{/* Manga Info Section */}
{/* Cover */}
-
-

+
+
+

+
{/* Details */}
--
2.49.1
From 45705c62cf4dbb9c859d814cafcfdc08d88d340a Mon Sep 17 00:00:00 2001
From: Rodrigo Verdiani
Date: Fri, 10 Apr 2026 10:59:40 -0300
Subject: [PATCH 3/3] feat: enable HTML rendering for manga synopsis in Manga
component
---
src/pages/Manga.tsx | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/pages/Manga.tsx b/src/pages/Manga.tsx
index ee154c7..609622c 100644
--- a/src/pages/Manga.tsx
+++ b/src/pages/Manga.tsx
@@ -361,9 +361,10 @@ const Manga = () => {
)}
-
- {mangaData.data?.synopsis}
-
+