feat(amazon): enhance playground with Amazon-specific field options and hints

This commit is contained in:
Anish Sarkar 2026-07-15 15:46:43 +05:30
parent 4abf95427b
commit aa3c62b754
3 changed files with 91 additions and 1 deletions

View file

@ -14,6 +14,11 @@ import { AppError } from "@/lib/error";
import { findVerb } from "@/lib/playground/catalog";
import { formatCost, formatDuration, formatPricing } from "@/lib/playground/format";
import { buildPayload, initialFormValues, parseSchemaFields } from "@/lib/playground/json-schema";
import {
AmazonMarketplaceHint,
getAmazonFieldOptions,
hasAmazonFranceValue,
} from "@/lib/playground/platform-overrides/amazon";
import { ApiReference } from "./api-reference";
import { OutputViewer } from "./output-viewer";
import { RunProgressPanel } from "./run-progress-panel";
@ -171,6 +176,8 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn
[run.detail]
);
const endpoint = `POST /workspaces/${workspaceId}/scrapers/${platform}/${verb}`;
const isAmazonScrape = platform === "amazon" && verb === "scrape";
const hasAmazonFranceUrl = useMemo(() => hasAmazonFranceValue(values), [values]);
useEffect(() => {
const previousStatus = previousStatusRef.current;
@ -260,7 +267,9 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn
values={values}
onChange={handleChange}
disabled={isRunning}
getFieldOptions={isAmazonScrape ? getAmazonFieldOptions : undefined}
/>
{isAmazonScrape ? <AmazonMarketplaceHint showFranceWarning={hasAmazonFranceUrl} /> : null}
<div className="flex items-center gap-2">
<Button type="button" onClick={handleRun} disabled={isRunning} className="relative">

View file

@ -17,11 +17,19 @@ import { Textarea } from "@/components/ui/textarea";
import type { FormField } from "@/lib/playground/json-schema";
import { cn } from "@/lib/utils";
export interface FieldOption {
label: string;
value: string;
}
type FieldOptionsResolver = (field: FormField) => FieldOption[] | undefined;
interface SchemaFormProps {
fields: FormField[];
values: Record<string, unknown>;
onChange: (name: string, value: unknown) => void;
disabled?: boolean;
getFieldOptions?: FieldOptionsResolver;
/** Field names flagged by a 422 response, shown with error styling. */
fieldErrors?: Record<string, string>;
}
@ -32,12 +40,14 @@ function FieldControl({
onChange,
disabled,
invalid,
options,
}: {
field: FormField;
value: unknown;
onChange: (value: unknown) => void;
disabled?: boolean;
invalid?: boolean;
options?: FieldOption[];
}) {
const id = `field-${field.name}`;
@ -68,6 +78,27 @@ function FieldControl({
);
}
if (options) {
return (
<Select
value={value ? String(value) : options[0]?.value}
onValueChange={onChange}
disabled={disabled}
>
<SelectTrigger id={id} className={cn("w-full", invalid && "border-destructive")}>
<SelectValue placeholder="Select…" />
</SelectTrigger>
<SelectContent>
{options.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label} ({option.value})
</SelectItem>
))}
</SelectContent>
</Select>
);
}
if (field.kind === "string_array") {
return (
<Textarea
@ -116,12 +147,14 @@ function FieldRow({
onChange,
disabled,
error,
options,
}: {
field: FormField;
value: unknown;
onChange: (value: unknown) => void;
disabled?: boolean;
error?: string;
options?: FieldOption[];
}) {
return (
<div className="space-y-1.5">
@ -143,13 +176,21 @@ function FieldRow({
onChange={onChange}
disabled={disabled}
invalid={!!error}
options={options}
/>
{error && <p className="text-xs text-destructive">{error}</p>}
</div>
);
}
export function SchemaForm({ fields, values, onChange, disabled, fieldErrors }: SchemaFormProps) {
export function SchemaForm({
fields,
values,
onChange,
disabled,
getFieldOptions,
fieldErrors,
}: SchemaFormProps) {
const [showAdvanced, setShowAdvanced] = useState(false);
const { primary, advanced } = useMemo(() => {
@ -168,6 +209,7 @@ export function SchemaForm({ fields, values, onChange, disabled, fieldErrors }:
onChange={(value) => onChange(field.name, value)}
disabled={disabled}
error={fieldErrors?.[field.name]}
options={getFieldOptions?.(field)}
/>
))}
@ -197,6 +239,7 @@ export function SchemaForm({ fields, values, onChange, disabled, fieldErrors }:
onChange={(value) => onChange(field.name, value)}
disabled={disabled}
error={fieldErrors?.[field.name]}
options={getFieldOptions?.(field)}
/>
))}
</div>

View file

@ -0,0 +1,38 @@
import { Info } from "lucide-react";
import type { FieldOption } from "@/app/dashboard/[workspace_id]/playground/components/schema-form";
import { Alert, AlertDescription } from "@/components/ui/alert";
import type { FormField } from "@/lib/playground/json-schema";
export const AMAZON_DOMAIN_OPTIONS: FieldOption[] = [
{ label: "US", value: "www.amazon.com" },
{ label: "UK", value: "www.amazon.co.uk" },
{ label: "Germany", value: "www.amazon.de" },
{ label: "Italy", value: "www.amazon.it" },
{ label: "Spain", value: "www.amazon.es" },
{ label: "France, best effort", value: "www.amazon.fr" },
];
const AMAZON_SUPPORTED_COUNTRIES = "US, UK, Germany, Italy, Spain, France";
export function getAmazonFieldOptions(field: FormField): FieldOption[] | undefined {
return field.name === "domain" ? AMAZON_DOMAIN_OPTIONS : undefined;
}
export function hasAmazonFranceValue(values: Record<string, unknown>): boolean {
return JSON.stringify(values).toLowerCase().includes("amazon.fr");
}
export function AmazonMarketplaceHint({ showFranceWarning }: { showFranceWarning: boolean }) {
return (
<Alert>
<Info />
<AlertDescription className="flex flex-wrap items-baseline gap-x-1">
<span className="font-medium text-foreground">Supported countries: </span>
<span>{AMAZON_SUPPORTED_COUNTRIES}</span>
{showFranceWarning
? " France is more WAF-sensitive. If this run returns no results, retry later or use another marketplace."
: null}
</AlertDescription>
</Alert>
);
}