feature: new changes!
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user