tv shows to tv series
This commit is contained in:
@@ -18,8 +18,8 @@ async function request<T>(path: string, options?: RequestInit): Promise<T> {
|
||||
|
||||
export function createRecommendation(body: {
|
||||
main_prompt: string;
|
||||
liked_shows: string;
|
||||
disliked_shows: string;
|
||||
liked_series: string;
|
||||
disliked_series: string;
|
||||
themes: string;
|
||||
brainstorm_count?: number;
|
||||
media_type: MediaType;
|
||||
@@ -68,8 +68,8 @@ export function deleteRecommendation(id: string): Promise<{ ok: boolean }> {
|
||||
}
|
||||
|
||||
export function createContinuousRecommendation(body: {
|
||||
liked_shows: string;
|
||||
disliked_shows?: string;
|
||||
liked_series: string;
|
||||
disliked_series?: string;
|
||||
themes?: string;
|
||||
requirements?: string;
|
||||
avoid?: string;
|
||||
|
||||
@@ -8,8 +8,8 @@ interface NewRecommendationModalProps {
|
||||
onClose: () => void;
|
||||
onSubmit: (body: {
|
||||
main_prompt: string;
|
||||
liked_shows: string;
|
||||
disliked_shows: string;
|
||||
liked_series: string;
|
||||
disliked_series: string;
|
||||
themes: string;
|
||||
requirements?: string;
|
||||
avoid?: string;
|
||||
@@ -33,19 +33,19 @@ const MEDIA_OPTIONS: Array<{
|
||||
label: string;
|
||||
description: string;
|
||||
}> = [
|
||||
{
|
||||
type: 'tv_show',
|
||||
icon: '📺',
|
||||
label: 'TV Shows',
|
||||
description: 'Serialized stories, limited series, and long-form comfort watches.',
|
||||
},
|
||||
{
|
||||
type: 'movie',
|
||||
icon: '🎬',
|
||||
label: 'Movies',
|
||||
description: 'Feature films, prestige cinema, and one-night picks.',
|
||||
},
|
||||
];
|
||||
{
|
||||
type: 'tv_show',
|
||||
icon: '📺',
|
||||
label: 'TV series',
|
||||
description: 'Serialized stories, limited series, and long-form comfort watches.',
|
||||
},
|
||||
{
|
||||
type: 'movie',
|
||||
icon: '🎬',
|
||||
label: 'Movies',
|
||||
description: 'Feature films, prestige cinema, and one-night picks.',
|
||||
},
|
||||
];
|
||||
|
||||
const MODE_OPTIONS: Array<{
|
||||
mode: GenerationMode;
|
||||
@@ -53,27 +53,27 @@ const MODE_OPTIONS: Array<{
|
||||
badge: string;
|
||||
description: string;
|
||||
}> = [
|
||||
{
|
||||
mode: 'brainstorm',
|
||||
label: 'Brainstorm',
|
||||
badge: 'Best for variety',
|
||||
description: 'Explore a broad pool of options, then rank and curate the strongest fits.',
|
||||
},
|
||||
{
|
||||
mode: 'continuous',
|
||||
label: 'Continuous',
|
||||
badge: 'Best for deep search',
|
||||
description: 'Generate recommendations in chained batches for a steadier, longer-running hunt.',
|
||||
},
|
||||
];
|
||||
{
|
||||
mode: 'brainstorm',
|
||||
label: 'Brainstorm',
|
||||
badge: 'Best for variety',
|
||||
description: 'Explore a broad pool of options, then rank and curate the strongest fits.',
|
||||
},
|
||||
{
|
||||
mode: 'continuous',
|
||||
label: 'Continuous',
|
||||
badge: 'Best for deep search',
|
||||
description: 'Generate recommendations in chained batches for a steadier, longer-running hunt.',
|
||||
},
|
||||
];
|
||||
|
||||
export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationModalProps) {
|
||||
const [step, setStep] = useState<'type' | 'mode' | 'form'>('type');
|
||||
const [mediaType, setMediaType] = useState<MediaType>('tv_show');
|
||||
const [generationMode, setGenerationMode] = useState<GenerationMode>('brainstorm');
|
||||
const [mainPrompt, setMainPrompt] = useState('');
|
||||
const [likedShows, setLikedShows] = useState('');
|
||||
const [dislikedShows, setDislikedShows] = useState('');
|
||||
const [likedSeries, setLikedSeries] = useState('');
|
||||
const [dislikedSeries, setDislikedSeries] = useState('');
|
||||
const [themes, setThemes] = useState('');
|
||||
const [requirements, setRequirements] = useState('');
|
||||
const [avoid, setAvoid] = useState('');
|
||||
@@ -100,7 +100,7 @@ export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationM
|
||||
}, [loading, onClose]);
|
||||
|
||||
const mediaLabel = mediaType === 'movie' ? 'Movie' : 'TV Show';
|
||||
const mediaPluralLabel = mediaType === 'movie' ? 'movies' : 'shows';
|
||||
const mediaPluralLabel = mediaType === 'movie' ? 'movies' : 'series';
|
||||
|
||||
const handleSelectType = (type: MediaType) => {
|
||||
setMediaType(type);
|
||||
@@ -119,15 +119,15 @@ export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationM
|
||||
const handleSubmit = async (e: Event) => {
|
||||
e.preventDefault();
|
||||
if (generationMode === 'brainstorm' && !mainPrompt.trim()) return;
|
||||
if (!likedShows.trim()) return;
|
||||
if (!likedSeries.trim()) return;
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
if (generationMode === 'brainstorm') {
|
||||
await onSubmit({
|
||||
main_prompt: mainPrompt.trim(),
|
||||
liked_shows: likedShows.trim(),
|
||||
disliked_shows: dislikedShows.trim(),
|
||||
liked_series: likedSeries.trim(),
|
||||
disliked_series: dislikedSeries.trim(),
|
||||
themes: themes.trim(),
|
||||
brainstorm_count: brainstormCount,
|
||||
media_type: mediaType,
|
||||
@@ -142,8 +142,8 @@ export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationM
|
||||
} else {
|
||||
await onSubmit({
|
||||
main_prompt: '',
|
||||
liked_shows: likedShows.trim(),
|
||||
disliked_shows: dislikedShows.trim(),
|
||||
liked_series: likedSeries.trim(),
|
||||
disliked_series: dislikedSeries.trim(),
|
||||
themes: themes.trim(),
|
||||
requirements: requirements.trim(),
|
||||
avoid: avoid.trim(),
|
||||
@@ -258,7 +258,7 @@ export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationM
|
||||
|
||||
<div class="modal-type-footer">
|
||||
<div class="modal-selection-summary">
|
||||
<span class="summary-pill">{mediaType === 'movie' ? 'Movies' : 'TV Shows'}</span>
|
||||
<span class="summary-pill">{mediaType === 'movie' ? 'Movies' : 'TV series'}</span>
|
||||
<span class="summary-pill">{selectedMode?.label}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -281,7 +281,7 @@ export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationM
|
||||
|
||||
<form class="modal-form" onSubmit={handleSubmit}>
|
||||
<div class="modal-summary-strip">
|
||||
<span class="summary-pill">{mediaType === 'movie' ? 'Movies' : 'TV Shows'}</span>
|
||||
<span class="summary-pill">{mediaType === 'movie' ? 'Movies' : 'TV series'}</span>
|
||||
<span class="summary-pill summary-pill--accent">{selectedMode?.label}</span>
|
||||
<span class="summary-caption">
|
||||
{generationMode === 'brainstorm'
|
||||
@@ -307,28 +307,28 @@ export function NewRecommendationModal({ onClose, onSubmit }: NewRecommendationM
|
||||
|
||||
<div class="modal-form-grid">
|
||||
<div class="form-group">
|
||||
<label for="liked-shows">{mediaLabel}s you liked</label>
|
||||
<label for="liked-series">{mediaLabel}s you liked</label>
|
||||
<input
|
||||
id="liked-shows"
|
||||
id="liked-series"
|
||||
type="text"
|
||||
class="form-input"
|
||||
placeholder={mediaType === 'movie' ? 'e.g. Inception, The Godfather' : 'e.g. Breaking Bad, The Wire'}
|
||||
value={likedShows}
|
||||
onInput={(e) => setLikedShows((e.target as HTMLInputElement).value)}
|
||||
value={likedSeries}
|
||||
onInput={(e) => setLikedSeries((e.target as HTMLInputElement).value)}
|
||||
required
|
||||
/>
|
||||
<span class="form-help">A few strong examples help the pipeline lock onto your taste.</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="disliked-shows">{mediaLabel}s you disliked</label>
|
||||
<label for="disliked-series">{mediaLabel}s you disliked</label>
|
||||
<input
|
||||
id="disliked-shows"
|
||||
id="disliked-series"
|
||||
type="text"
|
||||
class="form-input"
|
||||
placeholder={mediaType === 'movie' ? 'e.g. Transformers' : 'e.g. Game of Thrones'}
|
||||
value={dislikedShows}
|
||||
onInput={(e) => setDislikedShows((e.target as HTMLInputElement).value)}
|
||||
value={dislikedSeries}
|
||||
onInput={(e) => setDislikedSeries((e.target as HTMLInputElement).value)}
|
||||
/>
|
||||
<span class="form-help">Optional, but useful when you want to steer away from common misses.</span>
|
||||
</div>
|
||||
|
||||
@@ -14,8 +14,8 @@ type GenerationMode = 'brainstorm' | 'continuous';
|
||||
|
||||
interface CreateBody {
|
||||
main_prompt: string;
|
||||
liked_shows: string;
|
||||
disliked_shows: string;
|
||||
liked_series: string;
|
||||
disliked_series: string;
|
||||
themes: string;
|
||||
requirements?: string;
|
||||
avoid?: string;
|
||||
@@ -58,8 +58,8 @@ export function useRecommendations() {
|
||||
|
||||
if (body.generation_mode === 'continuous') {
|
||||
const result = await createContinuousRecommendation({
|
||||
liked_shows: body.liked_shows,
|
||||
disliked_shows: body.disliked_shows,
|
||||
liked_series: body.liked_series,
|
||||
disliked_series: body.disliked_series,
|
||||
themes: body.themes,
|
||||
requirements: body.requirements ?? '',
|
||||
avoid: body.avoid ?? '',
|
||||
@@ -73,7 +73,7 @@ export function useRecommendations() {
|
||||
const result = await createRecommendation(body);
|
||||
id = result.id;
|
||||
}
|
||||
|
||||
|
||||
await refreshList();
|
||||
setSelectedId(id);
|
||||
return id;
|
||||
|
||||
@@ -13,8 +13,8 @@ export function Home() {
|
||||
|
||||
const handleCreateNew = async (body: {
|
||||
main_prompt: string;
|
||||
liked_shows: string;
|
||||
disliked_shows: string;
|
||||
liked_series: string;
|
||||
disliked_series: string;
|
||||
themes: string;
|
||||
requirements?: string;
|
||||
avoid?: string;
|
||||
|
||||
@@ -183,8 +183,8 @@ export function Recom({ id }: RecomProps) {
|
||||
|
||||
const handleCreateNew = async (body: {
|
||||
main_prompt: string;
|
||||
liked_shows: string;
|
||||
disliked_shows: string;
|
||||
liked_series: string;
|
||||
disliked_series: string;
|
||||
themes: string;
|
||||
brainstorm_count?: number;
|
||||
media_type: import('../types/index.js').MediaType;
|
||||
@@ -234,16 +234,16 @@ export function Recom({ id }: RecomProps) {
|
||||
<span class="rec-info-value">{rec.main_prompt}</span>
|
||||
</div>
|
||||
)}
|
||||
{rec.liked_shows && (
|
||||
{rec.liked_series && (
|
||||
<div class="rec-info-row">
|
||||
<span class="rec-info-label">Liked</span>
|
||||
<span class="rec-info-value">{rec.liked_shows}</span>
|
||||
<span class="rec-info-value">{rec.liked_series}</span>
|
||||
</div>
|
||||
)}
|
||||
{rec.disliked_shows && (
|
||||
{rec.disliked_series && (
|
||||
<div class="rec-info-row">
|
||||
<span class="rec-info-label">Disliked</span>
|
||||
<span class="rec-info-value">{rec.disliked_shows}</span>
|
||||
<span class="rec-info-value">{rec.disliked_series}</span>
|
||||
</div>
|
||||
)}
|
||||
{rec.themes && (
|
||||
@@ -254,7 +254,7 @@ export function Recom({ id }: RecomProps) {
|
||||
)}
|
||||
<div class="rec-info-row">
|
||||
<span class="rec-info-label">Media</span>
|
||||
<span class="rec-info-value">{rec.media_type === 'tv_show' ? 'TV Shows' : 'Movies'}</span>
|
||||
<span class="rec-info-value">{rec.media_type === 'tv_show' ? 'TV series' : 'Movies'}</span>
|
||||
</div>
|
||||
{rec.use_web_search && (
|
||||
<div class="rec-info-row">
|
||||
|
||||
@@ -17,8 +17,8 @@ export interface Recommendation {
|
||||
id: string;
|
||||
title: string;
|
||||
main_prompt: string;
|
||||
liked_shows: string;
|
||||
disliked_shows: string;
|
||||
liked_series: string;
|
||||
disliked_series: string;
|
||||
themes: string;
|
||||
media_type: MediaType;
|
||||
use_web_search: boolean;
|
||||
|
||||
Reference in New Issue
Block a user