diff --git a/src/App.tsx b/src/App.tsx index 836ab45..5123b80 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -103,6 +103,7 @@ function AppContent() { const baseSettings = settings || { enabledCategories: prev, itemsPerPage: 20, + gridItemSize: 5, defaultView: 'grid', showAdultContent: false, autoPlayTrailers: false, @@ -172,6 +173,28 @@ function AppContent() { } }; + const handleGridItemSizeChange = async (size: number) => { + const baseSettings = settings || { + enabledCategories: enabledCategories, + itemsPerPage: 20, + gridItemSize: 5, + defaultView: 'grid', + showAdultContent: false, + autoPlayTrailers: false, + language: 'en', + theme: 'system', + }; + const updatedSettings: UserSettings = { + ...baseSettings, + gridItemSize: size, + }; + updateSettings(updatedSettings).then(saved => { + if (saved) { + setSettings(saved); + } + }); + }; + const allStaff = useMemo(() => { const staff: Staff[] = []; // Use API data if available, otherwise fall back to mock data @@ -295,6 +318,8 @@ function AppContent() { onMediaClick={handleMediaClick} activeCategory={activeCategory} itemsPerPage={settings?.itemsPerPage} + gridItemSize={settings?.gridItemSize} + onGridItemSizeChange={handleGridItemSizeChange} /> } /> { export async function createSettings(settings: UserSettings): Promise { try { const apiSettings = convertSettingsToApi(settings); - console.log('Creating settings:', apiSettings); const response = await fetch(`${BASE_URL}/api/settings`, { method: 'POST', headers: { @@ -713,14 +716,12 @@ export async function createSettings(settings: UserSettings): Promise = await response.json(); - console.log('Create settings response:', data); if (data.success && data.data) { return convertApiToSettings(data.data); @@ -735,7 +736,6 @@ export async function createSettings(settings: UserSettings): Promise { try { const apiSettings = convertSettingsToApi(settings); - console.log('Updating settings:', apiSettings); const response = await fetch(`${BASE_URL}/api/settings`, { method: 'PUT', headers: { @@ -743,11 +743,9 @@ export async function updateSettings(settings: UserSettings): Promise = await response.json(); - console.log('Update settings response:', data); if (data.success && data.data) { return convertApiToSettings(data.data); diff --git a/src/components/BrowseView.tsx b/src/components/BrowseView.tsx index f3afab6..dfaf4f2 100644 --- a/src/components/BrowseView.tsx +++ b/src/components/BrowseView.tsx @@ -18,14 +18,31 @@ interface BrowseViewProps { onMediaClick: (media: Media) => void; activeCategory: MediaCategory; itemsPerPage?: number; + gridItemSize?: number; + onGridItemSizeChange?: (size: number) => void; } -export default function BrowseView({ mediaList, onMediaClick, activeCategory, itemsPerPage: initialItemsPerPage = 12 }: BrowseViewProps) { +export default function BrowseView({ mediaList, onMediaClick, activeCategory, itemsPerPage: initialItemsPerPage = 12, gridItemSize: initialGridItemSize = 5, onGridItemSizeChange }: BrowseViewProps) { const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid'); const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(initialItemsPerPage); const [sortBy, setSortBy] = useState('default'); - + const [gridItemSize, setGridItemSize] = useState(initialGridItemSize); + + // Sync itemsPerPage with prop when API settings are loaded + useEffect(() => { + if (initialItemsPerPage) { + setItemsPerPage(initialItemsPerPage); + } + }, [initialItemsPerPage]); + + // Sync gridItemSize with prop when API settings are loaded + useEffect(() => { + if (initialGridItemSize !== undefined) { + setGridItemSize(initialGridItemSize); + } + }, [initialGridItemSize]); + // Filter states const [selectedGenre, setSelectedGenre] = useState(null); const [selectedStudio, setSelectedStudio] = useState(null); @@ -67,6 +84,23 @@ export default function BrowseView({ mediaList, onMediaClick, activeCategory, it return list; }, [filteredMedia, sortBy]); + const gridColsClass = useMemo(() => { + // Map slider value (1-10) to grid columns + const colsMap: Record = { + 1: 'grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', + 2: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', + 3: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5', + 4: 'grid-cols-2 sm:grid-cols-3 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6', + 5: 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8', + 6: 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8', + 7: 'grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-7 xl:grid-cols-9', + 8: 'grid-cols-3 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10', + 9: 'grid-cols-4 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10', + 10: 'grid-cols-4 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-12', + }; + return `grid ${colsMap[gridItemSize] || colsMap[5]}`; + }, [gridItemSize]); + const totalPages = Math.ceil(sortedMedia.length / itemsPerPage); const paginatedMedia = useMemo(() => { @@ -193,6 +227,24 @@ export default function BrowseView({ mediaList, onMediaClick, activeCategory, it
+ {/* Grid item size slider */} +
+ Size + { + const newSize = Number(e.target.value); + setGridItemSize(newSize); + onGridItemSizeChange?.(newSize); + }} + className="w-24 h-2 bg-background rounded-lg appearance-none cursor-pointer accent-[#6d28d9]" + /> + {gridItemSize} +
+
) : (
diff --git a/src/components/CastView.tsx b/src/components/CastView.tsx index 7acded7..6c1062f 100644 --- a/src/components/CastView.tsx +++ b/src/components/CastView.tsx @@ -38,6 +38,13 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag const [itemsPerPage, setItemsPerPage] = useState(initialItemsPerPage); const [showFilters, setShowFilters] = useState(false); + // Sync itemsPerPage with prop when API settings are loaded + useEffect(() => { + if (initialItemsPerPage) { + setItemsPerPage(initialItemsPerPage); + } + }, [initialItemsPerPage]); + // Persist filters and sorts useEffect(() => { localStorage.setItem('castSearchQuery', searchQuery); diff --git a/src/components/SettingsView.tsx b/src/components/SettingsView.tsx index 119a508..03463a4 100644 --- a/src/components/SettingsView.tsx +++ b/src/components/SettingsView.tsx @@ -36,6 +36,7 @@ export default function SettingsView({ onSettingsSaved }: SettingsViewProps) { const [settings, setSettings] = useState({ enabledCategories: ['Anime', 'Movies', 'TV Series', 'Music', 'Books', 'Consoles', 'Games', 'Adult'], itemsPerPage: 20, + gridItemSize: 5, defaultView: 'grid', showAdultContent: false, autoPlayTrailers: false, @@ -233,6 +234,24 @@ export default function SettingsView({ onSettingsSaved }: SettingsViewProps) {
+ {/* Grid item size */} +
+ +
+ Small + setSettings(prev => ({ ...prev, gridItemSize: Number(e.target.value) }))} + className="flex-1 h-2 bg-muted rounded-lg appearance-none cursor-pointer accent-[#6d28d9]" + /> + Large + {settings.gridItemSize} +
+
+ {/* Theme */}
diff --git a/src/types.ts b/src/types.ts index 7a7b646..f33257a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -100,6 +100,7 @@ export interface UserSettings { id?: number; enabledCategories: MediaCategory[]; itemsPerPage: number; + gridItemSize: number; // 1-10 scale defaultView: 'grid' | 'list'; showAdultContent: boolean; autoPlayTrailers: boolean;