diff --git a/frontend/src/api/syntheses.ts b/frontend/src/api/syntheses.ts
index caba9f3..e8fb545 100644
--- a/frontend/src/api/syntheses.ts
+++ b/frontend/src/api/syntheses.ts
@@ -74,8 +74,8 @@ export const synthesesApi = {
api.delete(`/syntheses/${id}`),
/** POST /syntheses/generate -- kick off an async generation job, returns a job ID. */
- generate: (): Promise =>
- api.post('/syntheses/generate'),
+ generate: (themeId: string): Promise =>
+ api.post('/syntheses/generate', { theme_id: themeId }),
/** Build the SSE endpoint URL for streaming generation progress. */
progressUrl: (jobId: string): string =>
diff --git a/frontend/src/i18n/fr.ts b/frontend/src/i18n/fr.ts
index 0ceb468..e8d1a19 100644
--- a/frontend/src/i18n/fr.ts
+++ b/frontend/src/i18n/fr.ts
@@ -83,6 +83,9 @@ const fr = {
'generate.model': 'Modele',
'generate.noWebSearchWarning':
'Le fournisseur selectionne ne supporte pas la recherche web. Les resultats seront bases uniquement sur les connaissances du modele.',
+ 'generate.selectTheme': 'Theme a generer',
+ 'generate.noThemes': 'Aucun theme configure. Creez un theme pour pouvoir generer une synthese.',
+ 'generate.createThemeLink': 'Creer un theme',
// Synthesis Detail
'synthesis.title': 'Synthese de la Semaine {week}',
diff --git a/frontend/src/pages/GenerateSynthesis.tsx b/frontend/src/pages/GenerateSynthesis.tsx
index 7781869..7a28776 100644
--- a/frontend/src/pages/GenerateSynthesis.tsx
+++ b/frontend/src/pages/GenerateSynthesis.tsx
@@ -7,12 +7,13 @@ import {
Show,
For,
} from 'solid-js';
-import { useNavigate } from '@solidjs/router';
+import { useNavigate, A } from '@solidjs/router';
import { AlertCircle, AlertTriangle, CheckCircle, Circle, Loader2 } from 'lucide-solid';
import { useI18n } from '~/i18n';
import { synthesesApi } from '~/api/syntheses';
import { settingsApi } from '~/api/settings';
import { configApi } from '~/api/config';
+import { themesApi, type ThemeResponse } from '~/api/themes';
import { isApiError, DEFAULT_SETTINGS } from '~/types';
import type { UserSettings, ProviderConfig, ProgressEvent } from '~/types';
import { createSSEConnection, type SSEConnection, type SSEStatus } from '~/utils/sse';
@@ -52,6 +53,8 @@ const GenerateSynthesis: Component = () => {
const [settings, setSettings] = createSignal({ ...DEFAULT_SETTINGS });
const [providers, setProviders] = createSignal([]);
+ const [themes, setThemes] = createSignal([]);
+ const [selectedThemeId, setSelectedThemeId] = createSignal('');
const [loadingSettings, setLoadingSettings] = createSignal(true);
const [generating, setGenerating] = createSignal(false);
const [error, setError] = createSignal(null);
@@ -60,15 +63,20 @@ const GenerateSynthesis: Component = () => {
onMount(async () => {
try {
- const [data, providerList] = await Promise.all([
+ const [data, providerList, themeList] = await Promise.all([
settingsApi.get().catch((err) => {
if (isApiError(err) && err.status === 404) return null;
throw err;
}),
configApi.listProviders().catch(() => [] as ProviderConfig[]),
+ themesApi.list().catch(() => [] as ThemeResponse[]),
]);
if (data) setSettings(data);
setProviders(providerList);
+ setThemes(themeList);
+ if (themeList.length > 0) {
+ setSelectedThemeId(themeList[0].id);
+ }
} catch {
// Non-404 settings error — use defaults silently
} finally {
@@ -210,7 +218,7 @@ const GenerateSynthesis: Component = () => {
setSuccess(false);
try {
- const response = await synthesesApi.generate();
+ const response = await synthesesApi.generate(selectedThemeId());
const url = synthesesApi.progressUrl(response.job_id);
const conn = createSSEConnection(url);
setSSEConnection(conn);
@@ -264,6 +272,39 @@ const GenerateSynthesis: Component = () => {
+ {/* Theme selection */}
+ 0}
+ fallback={
+
+ }
+ >
+
+
+
+
+
+
{/* No web search warning */}
@@ -382,7 +423,7 @@ const GenerateSynthesis: Component = () => {