Files
recommender/packages/frontend/src/components/Sidebar.tsx
T
ivanch c319dea2bf
Recommender Build and Deploy (internal) / Build Recommender Image (push) Successful in 3m22s
Recommender Build and Deploy (internal) / Deploy Recommender (internal) (push) Successful in 48s
new design
2026-04-18 21:19:24 -03:00

83 lines
2.2 KiB
TypeScript

import './Sidebar.css';
import { route } from 'preact-router';
import type { RecommendationSummary } from '../types/index.js';
interface SidebarProps {
list: RecommendationSummary[];
selectedId: string | null;
onSelect: (id: string) => void;
onNewClick: () => void;
}
function statusIcon(status: RecommendationSummary['status']): string {
switch (status) {
case 'done': return '✓';
case 'error': return '✗';
case 'running': return '⟳';
default: return '…';
}
}
function statusClass(status: RecommendationSummary['status']): string {
switch (status) {
case 'done': return 'status-done';
case 'error': return 'status-error';
case 'running': return 'status-running';
default: return 'status-pending';
}
}
export function Sidebar({ list, selectedId, onSelect, onNewClick }: SidebarProps) {
return (
<aside class="sidebar">
<div class="sidebar-header">
<a
href="/"
class="sidebar-title"
onClick={(event) => {
event.preventDefault();
route('/');
}}
>
Recommender
</a>
</div>
<button
type="button"
class="btn-new"
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
onNewClick();
}}
>
+ New Recommendation
</button>
<div class="sidebar-section-label">History</div>
<ul class="sidebar-list">
{list.length === 0 && (
<li class="sidebar-empty">No recommendations yet</li>
)}
{list.map((item) => (
<li
key={item.id}
class={`sidebar-item${selectedId === item.id ? ' selected' : ''}`}
onClick={() => onSelect(item.id)}
>
<span class={`sidebar-icon ${statusClass(item.status)}`}>
{statusIcon(item.status)}
</span>
<span class="sidebar-item-title">{item.title}</span>
<span class={`sidebar-type-badge sidebar-type-${item.media_type}`}>
{item.media_type === 'movie' ? 'Film' : 'TV'}
</span>
</li>
))}
</ul>
</aside>
);
}