Add filmography sorting and role-count UI
Introduce filmography sorting controls and role-count indicators across cast list and detail views. In CastDetailView: add sort state (sortBy/sortOrder), compute sortedFilmography, add UI for choosing sort key and toggling order, and show a filmography count badge; import new icons and useState. In CastView: add a new 'roleCount' sort option (default sort is now roleCount desc), persist/restore it from localStorage, adjust reset/default filter logic and hasActiveFilters check, render role-count badges for each person, and tweak layout (flex-1) for better truncation. These changes make it easier to surface prolific cast members and sort filmography entries by year, title, or role.
This commit is contained in:
@@ -22,11 +22,11 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag
|
||||
const [searchQuery, setSearchQuery] = useState(() => {
|
||||
return localStorage.getItem('castSearchQuery') || '';
|
||||
});
|
||||
const [sortBy, setSortBy] = useState<'name' | 'role' | 'birthDate' | 'height'>(() => {
|
||||
return (localStorage.getItem('castSortBy') as 'name' | 'role' | 'birthDate' | 'height') || 'name';
|
||||
const [sortBy, setSortBy] = useState<'name' | 'role' | 'birthDate' | 'height' | 'roleCount'>(() => {
|
||||
return (localStorage.getItem('castSortBy') as 'name' | 'role' | 'birthDate' | 'height' | 'roleCount') || 'roleCount';
|
||||
});
|
||||
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>(() => {
|
||||
return (localStorage.getItem('castSortOrder') as 'asc' | 'desc') || 'asc';
|
||||
return (localStorage.getItem('castSortOrder') as 'asc' | 'desc') || 'desc';
|
||||
});
|
||||
const [filterOccupation, setFilterOccupation] = useState<string>(() => {
|
||||
return localStorage.getItem('castFilterOccupation') || '';
|
||||
@@ -68,13 +68,13 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag
|
||||
|
||||
const handleResetFilters = () => {
|
||||
setSearchQuery('');
|
||||
setSortBy('name');
|
||||
setSortOrder('asc');
|
||||
setSortBy('roleCount');
|
||||
setSortOrder('desc');
|
||||
setFilterOccupation('');
|
||||
setFilterMediaType('');
|
||||
};
|
||||
|
||||
const hasActiveFilters = searchQuery || filterOccupation || filterMediaType || sortBy !== 'name' || sortOrder !== 'asc';
|
||||
const hasActiveFilters = searchQuery || filterOccupation || filterMediaType || sortBy !== 'roleCount' || sortOrder !== 'desc';
|
||||
|
||||
useEffect(() => {
|
||||
const loadCast = async () => {
|
||||
@@ -137,6 +137,10 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag
|
||||
const heightA = a.height || 0;
|
||||
const heightB = b.height || 0;
|
||||
comparison = heightA - heightB;
|
||||
} else if (sortBy === 'roleCount') {
|
||||
const roleCountA = a.filmography?.length || 0;
|
||||
const roleCountB = b.filmography?.length || 0;
|
||||
comparison = roleCountA - roleCountB;
|
||||
}
|
||||
|
||||
return sortOrder === 'desc' ? -comparison : comparison;
|
||||
@@ -247,6 +251,7 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag
|
||||
<option value="role">Role</option>
|
||||
<option value="birthDate">Birth Date</option>
|
||||
<option value="height">Height</option>
|
||||
<option value="roleCount">Role Count</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
@@ -345,7 +350,7 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag
|
||||
referrerPolicy="no-referrer"
|
||||
/>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="min-w-0 flex-1">
|
||||
<h3 className="font-black text-foreground truncate group-hover:text-[#6d28d9] transition-colors">
|
||||
{person.name}
|
||||
</h3>
|
||||
@@ -353,6 +358,11 @@ export default function CastView({ onPersonClick, enabledCategories, itemsPerPag
|
||||
{person.role}
|
||||
</p>
|
||||
</div>
|
||||
{person.filmography && person.filmography.length > 0 && (
|
||||
<Badge variant="outline" className="border-[#6d28d9]/30 text-[#6d28d9] font-bold text-[10px] px-2 py-0.5 shrink-0">
|
||||
{person.filmography.length}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{person.filmography && person.filmography.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user