feat: integrate display preferences for pagination and compact view in series grid
This commit is contained in:
@@ -9,6 +9,7 @@ import { cn } from "@/lib/utils";
|
||||
import type { KomgaSeries } from "@/types/komga";
|
||||
import { SearchInput } from "./SearchInput";
|
||||
import { useTranslate } from "@/hooks/useTranslate";
|
||||
import { useDisplayPreferences } from "@/hooks/useDisplayPreferences";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -22,7 +23,6 @@ interface PaginatedSeriesGridProps {
|
||||
currentPage: number;
|
||||
totalPages: number;
|
||||
totalElements: number;
|
||||
pageSize: number;
|
||||
defaultShowOnlyUnread: boolean;
|
||||
showOnlyUnread: boolean;
|
||||
}
|
||||
@@ -32,7 +32,6 @@ export function PaginatedSeriesGrid({
|
||||
currentPage,
|
||||
totalPages,
|
||||
totalElements,
|
||||
pageSize,
|
||||
defaultShowOnlyUnread,
|
||||
showOnlyUnread: initialShowOnlyUnread,
|
||||
}: PaginatedSeriesGridProps) {
|
||||
@@ -41,7 +40,8 @@ export function PaginatedSeriesGrid({
|
||||
const searchParams = useSearchParams();
|
||||
const [isChangingPage, setIsChangingPage] = useState(false);
|
||||
const [showOnlyUnread, setShowOnlyUnread] = useState(initialShowOnlyUnread);
|
||||
const [isCompact, setIsCompact] = useState(searchParams.get("compact") === "true");
|
||||
const { isCompact, itemsPerPage, handleCompactToggle, handlePageSizeChange } =
|
||||
useDisplayPreferences();
|
||||
const { t } = useTranslate();
|
||||
|
||||
const updateUrlParams = async (updates: Record<string, string | null>) => {
|
||||
@@ -78,7 +78,7 @@ export function PaginatedSeriesGrid({
|
||||
}, [defaultShowOnlyUnread, pathname, router, searchParams]);
|
||||
|
||||
const handlePageChange = async (page: number) => {
|
||||
await updateUrlParams({ page: page.toString(), compact: isCompact.toString() });
|
||||
await updateUrlParams({ page: page.toString() });
|
||||
};
|
||||
|
||||
const handleUnreadFilter = async () => {
|
||||
@@ -87,30 +87,30 @@ export function PaginatedSeriesGrid({
|
||||
await updateUrlParams({
|
||||
page: "1",
|
||||
unread: newUnreadState ? "true" : "false",
|
||||
compact: isCompact.toString(),
|
||||
});
|
||||
};
|
||||
|
||||
const handleCompactToggle = async () => {
|
||||
const handleCompactToggleClick = async () => {
|
||||
const newCompactState = !isCompact;
|
||||
setIsCompact(newCompactState);
|
||||
await handleCompactToggle(newCompactState);
|
||||
await updateUrlParams({
|
||||
page: "1",
|
||||
compact: newCompactState.toString(),
|
||||
});
|
||||
};
|
||||
|
||||
const handlePageSizeChange = async (value: string) => {
|
||||
const handlePageSizeChangeClick = async (value: string) => {
|
||||
const size = parseInt(value);
|
||||
await handlePageSizeChange(size);
|
||||
await updateUrlParams({
|
||||
page: "1",
|
||||
size: value,
|
||||
compact: isCompact.toString(),
|
||||
});
|
||||
};
|
||||
|
||||
// Calculate start and end indices for display
|
||||
const startIndex = (currentPage - 1) * pageSize + 1;
|
||||
const endIndex = Math.min(currentPage * pageSize, totalElements);
|
||||
const startIndex = (currentPage - 1) * itemsPerPage + 1;
|
||||
const endIndex = Math.min(currentPage * itemsPerPage, totalElements);
|
||||
|
||||
const getShowingText = () => {
|
||||
if (!totalElements) return t("series.empty");
|
||||
@@ -130,7 +130,7 @@ export function PaginatedSeriesGrid({
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-sm text-muted-foreground">{getShowingText()}</p>
|
||||
<Select value={pageSize.toString()} onValueChange={handlePageSizeChange}>
|
||||
<Select value={itemsPerPage.toString()} onValueChange={handlePageSizeChangeClick}>
|
||||
<SelectTrigger className="w-[80px]">
|
||||
<LayoutList className="h-4 w-4 mr-2" />
|
||||
<SelectValue />
|
||||
@@ -142,7 +142,7 @@ export function PaginatedSeriesGrid({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<button
|
||||
onClick={handleCompactToggle}
|
||||
onClick={handleCompactToggleClick}
|
||||
className="inline-flex items-center gap-2 px-2 py-1.5 text-sm font-medium rounded-lg hover:bg-accent hover:text-accent-foreground whitespace-nowrap"
|
||||
>
|
||||
{isCompact ? (
|
||||
|
||||
60
src/hooks/useDisplayPreferences.ts
Normal file
60
src/hooks/useDisplayPreferences.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { usePreferences } from "@/contexts/PreferencesContext";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { useTranslate } from "@/hooks/useTranslate";
|
||||
|
||||
export function useDisplayPreferences() {
|
||||
const { preferences, updatePreferences } = usePreferences();
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslate();
|
||||
|
||||
const handleCompactToggle = async (checked: boolean) => {
|
||||
try {
|
||||
await updatePreferences({
|
||||
displayMode: {
|
||||
...preferences.displayMode,
|
||||
compact: checked,
|
||||
},
|
||||
});
|
||||
toast({
|
||||
title: t("settings.title"),
|
||||
description: t("settings.komga.messages.configSaved"),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la mise à jour du mode compact:", error);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t("settings.error.title"),
|
||||
description: t("settings.error.message"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageSizeChange = async (size: number) => {
|
||||
try {
|
||||
await updatePreferences({
|
||||
displayMode: {
|
||||
...preferences.displayMode,
|
||||
itemsPerPage: size,
|
||||
},
|
||||
});
|
||||
toast({
|
||||
title: t("settings.title"),
|
||||
description: t("settings.komga.messages.configSaved"),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la mise à jour de la taille de page:", error);
|
||||
toast({
|
||||
variant: "destructive",
|
||||
title: t("settings.error.title"),
|
||||
description: t("settings.error.message"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
isCompact: preferences.displayMode.compact,
|
||||
itemsPerPage: preferences.displayMode.itemsPerPage,
|
||||
handleCompactToggle,
|
||||
handlePageSizeChange,
|
||||
};
|
||||
}
|
||||
@@ -26,6 +26,17 @@ const preferencesSchema = new mongoose.Schema(
|
||||
default: false,
|
||||
required: false,
|
||||
},
|
||||
displayMode: {
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
itemsPerPage: {
|
||||
type: Number,
|
||||
default: 20,
|
||||
enum: [20, 50, 100],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
@@ -35,6 +46,8 @@ const preferencesSchema = new mongoose.Schema(
|
||||
// Force la conversion en booléen
|
||||
ret.showOnlyUnread = Boolean(ret.showOnlyUnread);
|
||||
ret.debug = Boolean(ret.debug);
|
||||
ret.displayMode = ret.displayMode || { compact: false, itemsPerPage: 20 };
|
||||
ret.displayMode.compact = Boolean(ret.displayMode.compact);
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
@@ -49,8 +62,12 @@ preferencesSchema.pre("save", function (next) {
|
||||
if (this.debug === undefined) {
|
||||
this.debug = false;
|
||||
}
|
||||
if (!this.displayMode) {
|
||||
this.displayMode = { compact: false, itemsPerPage: 20 };
|
||||
}
|
||||
this.showOnlyUnread = Boolean(this.showOnlyUnread);
|
||||
this.debug = Boolean(this.debug);
|
||||
this.displayMode.compact = Boolean(this.displayMode.compact);
|
||||
next();
|
||||
});
|
||||
|
||||
@@ -63,6 +80,12 @@ preferencesSchema.pre("findOneAndUpdate", function (next) {
|
||||
if ("debug" in update.$set) {
|
||||
update.$set.debug = Boolean(update.$set.debug);
|
||||
}
|
||||
if ("displayMode" in update.$set) {
|
||||
update.$set.displayMode = {
|
||||
compact: Boolean(update.$set.displayMode?.compact),
|
||||
itemsPerPage: update.$set.displayMode?.itemsPerPage || 20,
|
||||
};
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
@@ -3,6 +3,10 @@ export interface UserPreferences {
|
||||
cacheMode: "memory" | "file";
|
||||
showOnlyUnread: boolean;
|
||||
debug: boolean;
|
||||
displayMode: {
|
||||
compact: boolean;
|
||||
itemsPerPage: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const defaultPreferences: UserPreferences = {
|
||||
@@ -10,4 +14,8 @@ export const defaultPreferences: UserPreferences = {
|
||||
cacheMode: "memory",
|
||||
showOnlyUnread: false,
|
||||
debug: false,
|
||||
displayMode: {
|
||||
compact: false,
|
||||
itemsPerPage: 20,
|
||||
},
|
||||
} as const;
|
||||
|
||||
Reference in New Issue
Block a user