web / frontend /src /pages /MyListPage.tsx
Chandima Prabhath
Track bun.lockb with Git LFS
cc2caf9
raw
history blame
5.88 kB
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import PageHeader from '../components/PageHeader';
import ContentGrid, { ContentItem } from '../components/ContentGrid';
import { getAllFromMyList, removeFromMyList } from '../lib/storage';
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Plus, TrashIcon } from 'lucide-react';
import { useToast } from '@/hooks/use-toast';
interface MyListItem {
type: 'movie' | 'tvshow';
title: string;
addedAt: string;
}
const MyListPage = () => {
const [myListItems, setMyListItems] = useState<MyListItem[]>([]);
const [showRemoveButtons, setShowRemoveButtons] = useState(false);
const [activeTab, setActiveTab] = useState('all');
const [isLoading, setIsLoading] = useState(true);
const navigate = useNavigate();
const { toast } = useToast();
useEffect(() => {
const fetchMyList = async () => {
try {
setIsLoading(true);
const items = await getAllFromMyList();
// Sort by most recently added
items.sort((a, b) => new Date(b.addedAt).getTime() - new Date(a.addedAt).getTime());
setMyListItems(items);
} catch (error) {
console.error("Error loading My List:", error);
} finally {
setIsLoading(false);
}
};
fetchMyList();
}, []);
const handleRemoveItem = async (title: string, type: 'movie' | 'tvshow') => {
try {
await removeFromMyList(title, type);
setMyListItems(prev => prev.filter(item => !(item.title === title && item.type === type)));
toast({
title: "Removed from My List",
description: `"${title}" has been removed from your list`,
});
} catch (error) {
console.error("Error removing item from My List:", error);
toast({
title: "Error",
description: "Failed to remove item from your list",
variant: "destructive"
});
}
};
const toggleRemoveButtons = () => {
setShowRemoveButtons(!showRemoveButtons);
};
const getFilteredItems = (filter: string): ContentItem[] => {
let filtered = myListItems;
if (filter === 'movies') {
filtered = myListItems.filter(item => item.type === 'movie');
} else if (filter === 'tvshows') {
filtered = myListItems.filter(item => item.type === 'tvshow');
}
// Convert to ContentItem format
return filtered.map(item => ({
type: item.type,
title: item.title,
image: undefined // ContentCard will fetch the image if not provided
}));
};
const allItems = getFilteredItems('all');
const movieItems = getFilteredItems('movies');
const tvShowItems = getFilteredItems('tvshows');
if (isLoading) {
return (
<div className="container mx-auto px-4 py-8 animate-pulse">
<div className="h-8 w-1/3 bg-gray-700 rounded mb-8"></div>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6">
{[...Array(10)].map((_, i) => (
<div key={i} className="h-32 rounded bg-gray-800"></div>
))}
</div>
</div>
);
}
return (
<div className="container mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-6">
<PageHeader
title="My List"
subtitle={`${myListItems.length} ${myListItems.length === 1 ? 'title' : 'titles'}`}
/>
<div className="flex gap-4 items-center">
{myListItems.length > 0 && (
<button
onClick={toggleRemoveButtons}
className="px-4 py-2 rounded-full bg-theme-card hover:bg-theme-card-hover text-sm flex items-center gap-2"
>
{showRemoveButtons ? 'Done' : (
<>
<TrashIcon size={16} />
<span className="hidden sm:inline">Edit List</span>
</>
)}
</button>
)}
<button
onClick={() => navigate('/browse')}
className="px-4 py-2 rounded-full bg-theme-primary hover:bg-theme-primary-hover text-white text-sm flex items-center gap-2"
>
<Plus size={16} />
<span className="hidden sm:inline">Add Titles</span>
</button>
</div>
</div>
{myListItems.length === 0 ? (
<div className="flex flex-col items-center justify-center py-16 text-center">
<div className="text-5xl mb-4">🎬</div>
<h3 className="text-xl font-bold mb-2">Your list is empty</h3>
<p className="text-gray-400 mb-6">Start adding movies and shows to create your watchlist.</p>
<button
onClick={() => navigate('/browse')}
className="px-6 py-2 rounded bg-theme-primary hover:bg-theme-primary-hover text-white text-sm font-medium"
>
Browse Content
</button>
</div>
) : (
<Tabs defaultValue={activeTab} onValueChange={setActiveTab}>
<TabsList className="mb-8">
<TabsTrigger value="all">All ({allItems.length})</TabsTrigger>
<TabsTrigger value="movies">Movies ({movieItems.length})</TabsTrigger>
<TabsTrigger value="tvshows">TV Shows ({tvShowItems.length})</TabsTrigger>
</TabsList>
<TabsContent value="all">
<ContentGrid items={allItems} emptyMessage="No items in your list" />
</TabsContent>
<TabsContent value="movies">
<ContentGrid items={movieItems} emptyMessage="No movies in your list" />
</TabsContent>
<TabsContent value="tvshows">
<ContentGrid items={tvShowItems} emptyMessage="No TV shows in your list" />
</TabsContent>
</Tabs>
)}
</div>
);
};
export default MyListPage;