Skip to content

Commit d180d14

Browse files
gildesmaraisclaude
andcommitted
fix(frontend): expose strategy selection reliably in member view
- useStrategies: init isLoading as !!token to prevent empty-select flash on first render - Strategy select always rendered (disabled + Loading… placeholder while fetching), no layout jump - Improved hint copy: "Direct fetch — works for most sites. Fast and safe." / "Headless browser — use for JavaScript-rendered pages (React, Angular, SPAs)." Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9e6955b commit d180d14

3 files changed

Lines changed: 27 additions & 36 deletions

File tree

frontend/src/components/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ export function App() {
6262
};
6363

6464
const strategyHint = (strategy: Strategy) => {
65-
if (strategy.id === 'ssrf_filter') return 'Recommended - safe and secure';
66-
if (strategy.id === 'browserless') return 'Great for pages that rely on JavaScript';
67-
return `Strategy: ${strategy.name}`;
65+
if (strategy.id === 'ssrf_filter') return 'Direct fetch — works for most sites. Fast and safe.';
66+
if (strategy.id === 'browserless') return 'Headless browser — use for JavaScript-rendered pages (React, Angular, SPAs).';
67+
return strategy.name;
6868
};
6969

7070
const handleAuthSubmit = async (event: Event) => {

frontend/src/components/AppPanels.tsx

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -260,30 +260,28 @@ export function MemberConvertPanel({
260260

261261
<div class="field">
262262
<label for="strategy" class="label">Strategy</label>
263-
{strategiesError && (
264-
<div class="notice notice--error" role="alert">
265-
<p>Failed to load strategies: {strategiesError}</p>
266-
</div>
267-
)}
268-
{strategiesLoading ? (
269-
<p>Loading strategies...</p>
270-
) : (
271-
<>
272-
<select
273-
id="strategy"
274-
name="strategy"
275-
class="input"
276-
value={feedFormData.strategy}
277-
onChange={(e) => onFeedFieldChange('strategy', (e.target as HTMLSelectElement).value)}
278-
>
279-
{strategies.map((strategy) => (
263+
<select
264+
id="strategy"
265+
name="strategy"
266+
class="input"
267+
value={feedFormData.strategy}
268+
disabled={strategiesLoading}
269+
onChange={(e) => onFeedFieldChange('strategy', (e.target as HTMLSelectElement).value)}
270+
>
271+
{strategiesLoading
272+
? <option value="">Loading…</option>
273+
: strategies.map((strategy) => (
280274
<option key={strategy.id} value={strategy.id}>
281275
{strategy.display_name}
282276
</option>
283-
))}
284-
</select>
285-
{selectedStrategy && <p class="field-help">{strategyHint(selectedStrategy)}</p>}
286-
</>
277+
))
278+
}
279+
</select>
280+
{strategiesError && (
281+
<p class="field-error">{strategiesError}</p>
282+
)}
283+
{selectedStrategy && !strategiesLoading && (
284+
<p class="field-help">{strategyHint(selectedStrategy)}</p>
287285
)}
288286
</div>
289287

frontend/src/hooks/useStrategies.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,18 @@
11
import { useState, useEffect } from 'preact/hooks';
22
import { listStrategies } from '../api/generated';
33
import { apiClient, bearerHeaders } from '../api/client';
4-
5-
interface Strategy {
6-
id: string;
7-
name: string;
8-
display_name: string;
9-
}
4+
import type { StrategyRecord } from '../api/contracts';
105

116
interface StrategiesState {
12-
strategies: Strategy[];
7+
strategies: StrategyRecord[];
138
isLoading: boolean;
149
error: string | null;
1510
}
1611

1712
export function useStrategies(token: string | null) {
1813
const [state, setState] = useState<StrategiesState>({
1914
strategies: [],
20-
isLoading: false,
15+
isLoading: !!token,
2116
error: null,
2217
});
2318

@@ -39,11 +34,9 @@ export function useStrategies(token: string | null) {
3934
responseStyle: 'data',
4035
});
4136

42-
const data = response as { success?: boolean; data?: { strategies?: Strategy[] } };
43-
44-
if (data.success && data.data?.strategies) {
37+
if (response?.success && response.data?.strategies) {
4538
setState({
46-
strategies: data.data.strategies,
39+
strategies: response.data.strategies,
4740
isLoading: false,
4841
error: null,
4942
});

0 commit comments

Comments
 (0)