feature: new changes!
All checks were successful
Recommender Build and Deploy (internal) / Build Recommender Image (push) Successful in 3m59s
Recommender Build and Deploy (internal) / Deploy Recommender (internal) (push) Successful in 10s

This commit is contained in:
2026-03-25 20:09:32 -03:00
parent 26f61077b8
commit f9f3d95406
25 changed files with 964 additions and 696 deletions

View File

@@ -1,8 +1,11 @@
import { useState, useCallback, useEffect } from 'preact/hooks';
import './Recom.css';
import { route } from 'preact-router';
import { PipelineProgress } from '../components/PipelineProgress.js';
import { RecommendationCard } from '../components/RecommendationCard.js';
import { useRecommendations } from '../hooks/useRecommendations.js';
import { Sidebar } from '../components/Sidebar.js';
import { NewRecommendationModal } from '../components/NewRecommendationModal.js';
import { useRecommendationsContext } from '../context/RecommendationsContext.js';
import { useSSE } from '../hooks/useSSE.js';
import { getRecommendation } from '../api/client.js';
import type { Recommendation, SSEEvent, StageMap, PipelineStage } from '../types/index.js';
@@ -22,11 +25,12 @@ const DEFAULT_STAGES: StageMap = {
const STAGE_ORDER: (keyof StageMap)[] = ['interpreter', 'retrieval', 'ranking', 'curator'];
export function Recom({ id }: RecomProps) {
const { feedback, submitFeedback, rerank, updateStatus, refreshList } = useRecommendations();
const { list, feedback, submitFeedback, rerank, updateStatus, refreshList, createNew } = useRecommendationsContext();
const [rec, setRec] = useState<Recommendation | null>(null);
const [stages, setStages] = useState<StageMap>(DEFAULT_STAGES);
const [sseUrl, setSseUrl] = useState<string | null>(null);
const [showModal, setShowModal] = useState(false);
useEffect(() => {
setRec(null);
@@ -83,66 +87,83 @@ export function Recom({ id }: RecomProps) {
setRec((prev) => (prev ? { ...prev, status: 'pending' } : null));
};
const handleCreateNew = async (body: {
main_prompt: string;
liked_shows: string;
disliked_shows: string;
themes: string;
brainstorm_count?: number;
}) => {
const newId = await createNew(body);
route(`/recom/${newId}`);
};
const isRunning = rec?.status === 'running' || rec?.status === 'pending' || !!sseUrl;
const feedbackMap = new Map(feedback.map((f) => [f.tv_show_name, f]));
return (
<div class="recom-page">
<nav class="recom-nav">
<a
class="recom-back"
href="/"
onClick={(e) => { e.preventDefault(); route('/'); }}
>
Recommender
</a>
</nav>
<div class="layout">
<Sidebar
list={list}
selectedId={id}
onSelect={(sid) => route(`/recom/${sid}`)}
onNewClick={() => setShowModal(true)}
/>
<div class="recom-content">
{isRunning && (
<div class="content-area">
<PipelineProgress stages={stages} />
</div>
)}
{!isRunning && rec?.status === 'done' && rec.recommendations && (
<div class="content-area">
<h2 class="rec-title">{rec.title}</h2>
<div class="cards-grid">
{rec.recommendations.map((show) => (
<RecommendationCard
key={show.title}
show={show}
existingFeedback={feedbackMap.get(show.title)}
onFeedback={async (name, stars, comment) => {
await submitFeedback({ tv_show_name: name, stars, feedback: comment });
}}
/>
))}
<main class="main-content">
<div class="recom-content">
{isRunning && (
<div class="content-area">
<PipelineProgress stages={stages} />
</div>
<div class="rerank-section">
<button
class="btn-rerank"
onClick={handleRerank}
disabled={feedback.length === 0}
title={feedback.length === 0 ? 'Rate at least one show to enable re-ranking' : 'Re-rank based on your feedback'}
>
Re-rank with Feedback {feedback.length > 0 ? `(${feedback.length} rated)` : ''}
)}
{!isRunning && rec?.status === 'done' && rec.recommendations && (
<div class="content-area">
<h2 class="rec-title">{rec.title}</h2>
<div class="cards-grid">
{rec.recommendations.map((show) => (
<RecommendationCard
key={show.title}
show={show}
existingFeedback={feedbackMap.get(show.title)}
onFeedback={async (name, stars, comment) => {
await submitFeedback({ tv_show_name: name, stars, feedback: comment });
}}
/>
))}
</div>
<div class="rerank-section">
<button
class="btn-rerank"
onClick={handleRerank}
disabled={feedback.length === 0}
title={feedback.length === 0 ? 'Rate at least one show to enable re-ranking' : 'Re-rank based on your feedback'}
>
Re-rank with Feedback {feedback.length > 0 ? `(${feedback.length} rated)` : ''}
</button>
</div>
</div>
)}
{!isRunning && rec?.status === 'error' && (
<div class="content-area error-state">
<h2>Something went wrong</h2>
<p>The pipeline encountered an error. You can try again by clicking Re-rank.</p>
<button class="btn-primary" onClick={handleRerank}>
Try Again
</button>
</div>
</div>
)}
)}
</div>
</main>
{!isRunning && rec?.status === 'error' && (
<div class="content-area error-state">
<h2>Something went wrong</h2>
<p>The pipeline encountered an error. You can try again by clicking Re-rank.</p>
<button class="btn-primary" onClick={handleRerank}>
Try Again
</button>
</div>
)}
</div>
{showModal && (
<NewRecommendationModal
onClose={() => setShowModal(false)}
onSubmit={handleCreateNew}
/>
)}
</div>
);
}