diff --git a/src/app/libraries/[libraryId]/page.tsx b/src/app/libraries/[libraryId]/page.tsx
index a3787eb..c346a51 100644
--- a/src/app/libraries/[libraryId]/page.tsx
+++ b/src/app/libraries/[libraryId]/page.tsx
@@ -1,5 +1,6 @@
import { PaginatedSeriesGrid } from "@/components/library/PaginatedSeriesGrid";
import { LibraryService } from "@/lib/services/library.service";
+import { PreferencesService } from "@/lib/services/preferences.service";
interface PageProps {
params: { libraryId: string };
@@ -28,7 +29,11 @@ async function getLibrarySeries(libraryId: string, page: number = 1, unreadOnly:
export default async function LibraryPage({ params, searchParams }: PageProps) {
const currentPage = searchParams.page ? parseInt(searchParams.page) : 1;
- const unreadOnly = searchParams.unread === "true";
+ const preferences = await PreferencesService.getPreferences();
+
+ // Utiliser le paramètre d'URL s'il existe, sinon utiliser la préférence utilisateur
+ const unreadOnly =
+ searchParams.unread !== undefined ? searchParams.unread === "true" : preferences.showOnlyUnread;
try {
const { data: series, library } = await getLibrarySeries(
@@ -53,6 +58,8 @@ export default async function LibraryPage({ params, searchParams }: PageProps) {
totalPages={series.totalPages}
totalElements={series.totalElements}
pageSize={PAGE_SIZE}
+ defaultShowOnlyUnread={preferences.showOnlyUnread}
+ showOnlyUnread={unreadOnly}
/>
);
diff --git a/src/app/series/[seriesId]/page.tsx b/src/app/series/[seriesId]/page.tsx
index e82f597..8ff71a4 100644
--- a/src/app/series/[seriesId]/page.tsx
+++ b/src/app/series/[seriesId]/page.tsx
@@ -1,6 +1,7 @@
import { PaginatedBookGrid } from "@/components/series/PaginatedBookGrid";
import { SeriesHeader } from "@/components/series/SeriesHeader";
import { SeriesService } from "@/lib/services/series.service";
+import { PreferencesService } from "@/lib/services/preferences.service";
interface PageProps {
params: { seriesId: string };
@@ -9,18 +10,29 @@ interface PageProps {
const PAGE_SIZE = 24;
+async function getSeriesBooks(seriesId: string, page: number = 1, unreadOnly: boolean = false) {
+ try {
+ const pageIndex = page - 1;
+
+ const books = await SeriesService.getSeriesBooks(seriesId, pageIndex, PAGE_SIZE, unreadOnly);
+ const series = await SeriesService.getSeries(seriesId);
+
+ return { data: books, series };
+ } catch (error) {
+ throw error instanceof Error ? error : new Error("Erreur lors de la récupération des tomes");
+ }
+}
+
export default async function SeriesPage({ params, searchParams }: PageProps) {
const currentPage = searchParams.page ? parseInt(searchParams.page) : 1;
- const unreadOnly = searchParams.unread === "true";
+ const preferences = await PreferencesService.getPreferences();
+
+ // Utiliser le paramètre d'URL s'il existe, sinon utiliser la préférence utilisateur
+ const unreadOnly =
+ searchParams.unread !== undefined ? searchParams.unread === "true" : preferences.showOnlyUnread;
try {
- const pageIndex = currentPage - 1;
-
- // Appels API parallèles pour les détails de la série et les tomes
- const [series, books] = await Promise.all([
- SeriesService.getSeries(params.seriesId),
- SeriesService.getSeriesBooks(params.seriesId, pageIndex, PAGE_SIZE, unreadOnly),
- ]);
+ const { data: books, series } = await getSeriesBooks(params.seriesId, currentPage, unreadOnly);
return (
@@ -31,6 +43,8 @@ export default async function SeriesPage({ params, searchParams }: PageProps) {
totalPages={books.totalPages}
totalElements={books.totalElements}
pageSize={PAGE_SIZE}
+ defaultShowOnlyUnread={preferences.showOnlyUnread}
+ showOnlyUnread={unreadOnly}
/>
);
diff --git a/src/components/library/PaginatedSeriesGrid.tsx b/src/components/library/PaginatedSeriesGrid.tsx
index 6b807cd..77e6c6f 100644
--- a/src/components/library/PaginatedSeriesGrid.tsx
+++ b/src/components/library/PaginatedSeriesGrid.tsx
@@ -14,6 +14,8 @@ interface PaginatedSeriesGridProps {
totalPages: number;
totalElements: number;
pageSize: number;
+ defaultShowOnlyUnread: boolean;
+ showOnlyUnread: boolean;
}
export function PaginatedSeriesGrid({
@@ -22,26 +24,43 @@ export function PaginatedSeriesGrid({
totalPages,
totalElements,
pageSize,
+ defaultShowOnlyUnread,
+ showOnlyUnread: initialShowOnlyUnread,
}: PaginatedSeriesGridProps) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const [isChangingPage, setIsChangingPage] = useState(false);
- const [showOnlyUnread, setShowOnlyUnread] = useState(searchParams.get("unread") === "true");
+ const [showOnlyUnread, setShowOnlyUnread] = useState(initialShowOnlyUnread);
// Réinitialiser l'état de chargement quand les séries changent
useEffect(() => {
setIsChangingPage(false);
}, [series]);
+ // Mettre à jour l'état local quand la prop change
+ useEffect(() => {
+ setShowOnlyUnread(initialShowOnlyUnread);
+ }, [initialShowOnlyUnread]);
+
+ // Appliquer le filtre par défaut au chargement initial
+ useEffect(() => {
+ if (defaultShowOnlyUnread && !searchParams.has("unread")) {
+ const params = new URLSearchParams(searchParams.toString());
+ params.set("page", "1");
+ params.set("unread", "true");
+ router.push(`${pathname}?${params.toString()}`);
+ }
+ }, [defaultShowOnlyUnread, pathname, router, searchParams]);
+
const handlePageChange = async (page: number) => {
setIsChangingPage(true);
// Créer un nouvel objet URLSearchParams pour manipuler les paramètres
const params = new URLSearchParams(searchParams.toString());
params.set("page", page.toString());
- if (showOnlyUnread) {
- params.set("unread", "true");
- }
+
+ // Conserver l'état du filtre unread
+ params.set("unread", showOnlyUnread.toString());
// Rediriger vers la nouvelle URL avec les paramètres mis à jour
await router.push(`${pathname}?${params.toString()}`);
@@ -52,13 +71,12 @@ export function PaginatedSeriesGrid({
const params = new URLSearchParams(searchParams.toString());
params.set("page", "1"); // Retourner à la première page lors du changement de filtre
- if (!showOnlyUnread) {
- params.set("unread", "true");
- } else {
- params.delete("unread");
- }
+ const newUnreadState = !showOnlyUnread;
+ setShowOnlyUnread(newUnreadState);
+
+ // Toujours définir explicitement le paramètre unread
+ params.set("unread", newUnreadState.toString());
- setShowOnlyUnread(!showOnlyUnread);
await router.push(`${pathname}?${params.toString()}`);
};
diff --git a/src/components/series/PaginatedBookGrid.tsx b/src/components/series/PaginatedBookGrid.tsx
index 048dd72..778c2f6 100644
--- a/src/components/series/PaginatedBookGrid.tsx
+++ b/src/components/series/PaginatedBookGrid.tsx
@@ -14,6 +14,8 @@ interface PaginatedBookGridProps {
totalPages: number;
totalElements: number;
pageSize: number;
+ defaultShowOnlyUnread: boolean;
+ showOnlyUnread: boolean;
}
export function PaginatedBookGrid({
@@ -22,26 +24,43 @@ export function PaginatedBookGrid({
totalPages,
totalElements,
pageSize,
+ defaultShowOnlyUnread,
+ showOnlyUnread: initialShowOnlyUnread,
}: PaginatedBookGridProps) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const [isChangingPage, setIsChangingPage] = useState(false);
- const [showOnlyUnread, setShowOnlyUnread] = useState(searchParams.get("unread") === "true");
+ const [showOnlyUnread, setShowOnlyUnread] = useState(initialShowOnlyUnread);
// Réinitialiser l'état de chargement quand les tomes changent
useEffect(() => {
setIsChangingPage(false);
}, [books]);
+ // Mettre à jour l'état local quand la prop change
+ useEffect(() => {
+ setShowOnlyUnread(initialShowOnlyUnread);
+ }, [initialShowOnlyUnread]);
+
+ // Appliquer le filtre par défaut au chargement initial
+ useEffect(() => {
+ if (defaultShowOnlyUnread && !searchParams.has("unread")) {
+ const params = new URLSearchParams(searchParams.toString());
+ params.set("page", "1");
+ params.set("unread", "true");
+ router.push(`${pathname}?${params.toString()}`);
+ }
+ }, [defaultShowOnlyUnread, pathname, router, searchParams]);
+
const handlePageChange = async (page: number) => {
setIsChangingPage(true);
// Créer un nouvel objet URLSearchParams pour manipuler les paramètres
const params = new URLSearchParams(searchParams.toString());
params.set("page", page.toString());
- if (showOnlyUnread) {
- params.set("unread", "true");
- }
+
+ // Conserver l'état du filtre unread
+ params.set("unread", showOnlyUnread.toString());
// Rediriger vers la nouvelle URL avec les paramètres mis à jour
await router.push(`${pathname}?${params.toString()}`);
@@ -52,13 +71,12 @@ export function PaginatedBookGrid({
const params = new URLSearchParams(searchParams.toString());
params.set("page", "1"); // Retourner à la première page lors du changement de filtre
- if (!showOnlyUnread) {
- params.set("unread", "true");
- } else {
- params.delete("unread");
- }
+ const newUnreadState = !showOnlyUnread;
+ setShowOnlyUnread(newUnreadState);
+
+ // Toujours définir explicitement le paramètre unread
+ params.set("unread", newUnreadState.toString());
- setShowOnlyUnread(!showOnlyUnread);
await router.push(`${pathname}?${params.toString()}`);
};
diff --git a/src/components/settings/ClientSettings.tsx b/src/components/settings/ClientSettings.tsx
index 5da6692..dfe2aa1 100644
--- a/src/components/settings/ClientSettings.tsx
+++ b/src/components/settings/ClientSettings.tsx
@@ -306,6 +306,39 @@ export function ClientSettings({ initialConfig, initialTTLConfig }: ClientSettin
onCheckedChange={handleToggleThumbnails}
/>
+
+
+
+
+ Afficher uniquement les séries non lues par défaut
+
+
+
{
+ try {
+ await updatePreferences({ showOnlyUnread: checked });
+ toast({
+ title: "Préférences sauvegardées",
+ description: `Le filtre "À lire" par défaut est maintenant ${
+ checked ? "activé" : "désactivé"
+ }`,
+ });
+ } catch (error) {
+ console.error("Erreur détaillée:", error);
+ toast({
+ variant: "destructive",
+ title: "Erreur",
+ description:
+ error instanceof Error
+ ? error.message
+ : "Une erreur est survenue lors de la mise à jour des préférences",
+ });
+ }
+ }}
+ />
+
diff --git a/src/contexts/PreferencesContext.tsx b/src/contexts/PreferencesContext.tsx
index 747756b..ed7a401 100644
--- a/src/contexts/PreferencesContext.tsx
+++ b/src/contexts/PreferencesContext.tsx
@@ -5,11 +5,13 @@ import React, { createContext, useContext, useEffect, useState } from "react";
export interface UserPreferences {
showThumbnails: boolean;
cacheMode: "memory" | "file";
+ showOnlyUnread: boolean;
}
const defaultPreferences: UserPreferences = {
showThumbnails: true,
cacheMode: "memory",
+ showOnlyUnread: false,
};
interface PreferencesContextType {
@@ -30,7 +32,10 @@ export function PreferencesProvider({ children }: { children: React.ReactNode })
const response = await fetch("/api/preferences");
if (!response.ok) throw new Error("Erreur lors de la récupération des préférences");
const data = await response.json();
- setPreferences(data);
+ setPreferences({
+ ...defaultPreferences,
+ ...data,
+ });
} catch (error) {
console.error("Erreur lors de la récupération des préférences:", error);
// En cas d'erreur, on garde les préférences par défaut
@@ -56,7 +61,15 @@ export function PreferencesProvider({ children }: { children: React.ReactNode })
if (!response.ok) throw new Error("Erreur lors de la mise à jour des préférences");
const updatedPreferences = await response.json();
- setPreferences(updatedPreferences);
+
+ setPreferences((prev) => {
+ const newState = {
+ ...prev,
+ ...updatedPreferences,
+ };
+ console.log("Nouvel état des préférences:", newState);
+ return newState;
+ });
} catch (error) {
console.error("Erreur lors de la mise à jour des préférences:", error);
throw error;
diff --git a/src/lib/models/preferences.model.ts b/src/lib/models/preferences.model.ts
index bba84ab..d367ad1 100644
--- a/src/lib/models/preferences.model.ts
+++ b/src/lib/models/preferences.model.ts
@@ -16,11 +16,47 @@ const preferencesSchema = new mongoose.Schema(
enum: ["memory", "file"],
default: "memory",
},
+ showOnlyUnread: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
},
{
timestamps: true,
+ strict: true,
+ toObject: {
+ transform: function (doc, ret) {
+ // Assurez-vous que showOnlyUnread est toujours un booléen
+ ret.showOnlyUnread = ret.showOnlyUnread === true;
+ return ret;
+ },
+ },
}
);
+// Middleware pour s'assurer que showOnlyUnread est toujours un booléen
+preferencesSchema.pre("save", function (next) {
+ if (this.showOnlyUnread === undefined) {
+ this.showOnlyUnread = false;
+ }
+ this.showOnlyUnread = this.showOnlyUnread === true;
+ next();
+});
+
+preferencesSchema.pre("findOneAndUpdate", function (next) {
+ const update = this.getUpdate() as mongoose.UpdateQuery;
+ if (
+ update &&
+ "$set" in update &&
+ update.$set &&
+ typeof update.$set === "object" &&
+ "showOnlyUnread" in update.$set
+ ) {
+ update.$set.showOnlyUnread = update.$set.showOnlyUnread === true;
+ }
+ next();
+});
+
export const PreferencesModel =
mongoose.models.Preferences || mongoose.model("Preferences", preferencesSchema);
diff --git a/src/lib/services/preferences.service.ts b/src/lib/services/preferences.service.ts
index 574780d..46af9f9 100644
--- a/src/lib/services/preferences.service.ts
+++ b/src/lib/services/preferences.service.ts
@@ -9,8 +9,15 @@ interface User {
export interface UserPreferences {
showThumbnails: boolean;
cacheMode: "memory" | "file";
+ showOnlyUnread: boolean;
}
+const defaultPreferences: UserPreferences = {
+ showThumbnails: true,
+ cacheMode: "memory",
+ showOnlyUnread: false,
+};
+
export class PreferencesService {
static async getCurrentUser(): Promise {
const userCookie = cookies().get("stripUser");
@@ -32,26 +39,21 @@ export class PreferencesService {
const user = await this.getCurrentUser();
const preferences = await PreferencesModel.findOne({ userId: user.id });
if (!preferences) {
- return {
- showThumbnails: true,
- cacheMode: "memory",
- };
+ return defaultPreferences;
}
return {
- showThumbnails: preferences.showThumbnails,
- cacheMode: preferences.cacheMode || "memory",
+ ...defaultPreferences,
+ ...preferences.toObject(),
};
} catch (error) {
console.error("Error getting preferences:", error);
- return {
- showThumbnails: true,
- cacheMode: "memory",
- };
+ return defaultPreferences;
}
}
static async updatePreferences(preferences: Partial): Promise {
try {
+ console.log("Service - Préférences reçues pour mise à jour:", preferences);
const user = await this.getCurrentUser();
const updatedPreferences = await PreferencesModel.findOneAndUpdate(
{ userId: user.id },
@@ -59,10 +61,13 @@ export class PreferencesService {
{ new: true, upsert: true }
);
- return {
- showThumbnails: updatedPreferences.showThumbnails,
- cacheMode: updatedPreferences.cacheMode || "memory",
+ console.log("Service - Document MongoDB après mise à jour:", updatedPreferences);
+ const result = {
+ ...defaultPreferences,
+ ...updatedPreferences.toObject(),
};
+ console.log("Service - Résultat final:", result);
+ return result;
} catch (error) {
console.error("Error updating preferences:", error);
throw error;