Files
MediaCollectorLibaryFrontend/src/pages/Movies.tsx

152 lines
5.7 KiB
TypeScript

import React, { useState, useContext } from 'react'
import { motion } from 'framer-motion'
import MovieCard from '../components/MovieCard'
import { MovieCardSkeleton } from '../components/LoadingSkeleton'
import { useMovies } from '../hooks/useApi'
import { ViewContext } from '../components/Layout'
import { FilmIcon } from '@heroicons/react/24/outline'
// Import from components
import { MediaListView } from '../components/MediaListView'
import { MediaDetailView } from '../components/MediaDetailView'
export default function Movies() {
const viewContext = useContext(ViewContext)
const viewMode = viewContext?.viewMode || 'grid'
const gridColumns = viewContext?.gridColumns || 5
const coverSize = viewContext?.coverSize || 200
const PaginationComp = viewContext?.PaginationComponent
const getGridClass = (columns: number) => {
const columnClasses = {
2: 'grid-cols-1 md:grid-cols-2',
3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
5: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5',
6: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6',
7: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-7',
8: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-8'
}
return columnClasses[columns as keyof typeof columnClasses] || columnClasses[5]
}
const [currentPage, setCurrentPage] = useState(1)
const [pageSize, setPageSize] = useState(24)
const { data: moviesData, isLoading } = useMovies({
page: currentPage,
per_page: pageSize
})
const movies = moviesData?.items || []
const pagination = moviesData?.pagination
// Convert movies to MediaItem format for MediaListView
const mediaItems = movies.map(movie => ({
id: movie.id.toString(),
title: movie.title || 'Untitled Movie',
type: 'movie' as const,
coverUrl: movie.poster_url || movie.cover_url || '',
rating: Number(movie.rating) || 0,
status: 'completed' as const, // Default status
releaseYear: movie.release_year || movie.year || new Date().getFullYear(),
addedAt: movie.created_at || new Date().toISOString(),
favorite: movie.favorite || false,
platform: movie.source_name || 'Unknown',
description: movie.description || '',
genres: movie.genres || []
}))
// State for MediaListView
const [selectedId, setSelectedId] = useState<string | null>(null)
const [multiSelectedIds, setMultiSelectedIds] = useState<Set<string>>(new Set())
const [detailItem, setDetailItem] = useState<any>(null)
const handleSelect = (item: any) => {
setSelectedId(item.id)
setDetailItem(item)
}
const handleToggleSelect = (id: string) => {
const newSelected = new Set(multiSelectedIds)
if (newSelected.has(id)) {
newSelected.delete(id)
} else {
newSelected.add(id)
}
setMultiSelectedIds(newSelected)
}
return (
<>
<div className="mx-auto">
{isLoading ? (
<div className={`grid gap-6 ${getGridClass(gridColumns)}`}>
{Array.from({ length: pageSize }, (_, i) => (
<MovieCardSkeleton key={i} />
))}
</div>
) : viewMode === 'list' ? (
// Use MediaListView for list mode with sideview
<div className="flex w-full h-full">
<div className={`${detailItem ? 'w-1/2 hidden md:flex' : 'w-full'} h-full flex flex-col transition-all duration-500`}>
<div className="h-[600px] border border-slate-200 dark:border-slate-700 rounded-lg overflow-hidden">
<MediaListView
items={mediaItems}
onSelect={handleSelect}
selectedId={selectedId}
onToggleSelect={handleToggleSelect}
multiSelectedIds={multiSelectedIds}
/>
</div>
</div>
{detailItem && (
<div className="w-full md:w-1/2 h-full border-l border-white/5 relative overflow-hidden animate-in slide-in-from-right duration-300">
<MediaDetailView
item={detailItem}
allMedia={mediaItems}
onBack={() => setDetailItem(null)}
onEdit={(item) => console.log('Edit item:', item)}
onToggleFavorite={(id, isFav) => console.log('Toggle favorite:', id, isFav)}
onSelectRelated={(item) => setDetailItem(item)}
onSelectPerson={(name, id) => console.log('Select person:', name, id)}
onViewAll={(type, id) => console.log('View all:', type, id)}
/>
</div>
)}
</div>
) : (
// Grid view with MovieCard
<motion.div
className={`grid gap-6 ${getGridClass(gridColumns)}`}
>
{movies.map((movie, index) => (
<motion.div
key={movie.id}
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: index * 0.03 }}
>
<MovieCard movie={movie} viewMode={viewMode} coverSize={coverSize} />
</motion.div>
))}
</motion.div>
)}
{!isLoading && pagination && pagination.last_page > 1 && PaginationComp && (
<div className="mt-8">
<PaginationComp
currentPage={currentPage}
lastPage={pagination.last_page}
total={pagination.total}
onPageChange={setCurrentPage}
itemsPerPage={pageSize}
onItemsPerPageChange={setPageSize}
/>
</div>
)}
</div>
</>
)
}