feat: build local optimizer interface
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
"use client";
|
||||
|
||||
import type { FormEvent } from "react";
|
||||
|
||||
import type { PublishPlatform } from "../lib/domain/types";
|
||||
|
||||
export interface ArticleInputPayload {
|
||||
title: string;
|
||||
body: string;
|
||||
image_lines: string;
|
||||
platform: PublishPlatform;
|
||||
user_instructions: string;
|
||||
}
|
||||
|
||||
interface ArticleInputFormProps {
|
||||
value: ArticleInputPayload;
|
||||
isSubmitting: boolean;
|
||||
onChange: (value: ArticleInputPayload) => void;
|
||||
onSubmit: () => void;
|
||||
}
|
||||
|
||||
const platforms: { value: PublishPlatform; label: string }[] = [
|
||||
{ value: "official_site", label: "Official site" },
|
||||
{ value: "media_article", label: "Media article" },
|
||||
{ value: "comparison_review", label: "Comparison review" },
|
||||
{ value: "recommendation_list", label: "Recommendation list" },
|
||||
];
|
||||
|
||||
export function ArticleInputForm({
|
||||
value,
|
||||
isSubmitting,
|
||||
onChange,
|
||||
onSubmit,
|
||||
}: ArticleInputFormProps) {
|
||||
function update<K extends keyof ArticleInputPayload>(
|
||||
key: K,
|
||||
nextValue: ArticleInputPayload[K],
|
||||
) {
|
||||
onChange({ ...value, [key]: nextValue });
|
||||
}
|
||||
|
||||
function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
onSubmit();
|
||||
}
|
||||
|
||||
return (
|
||||
<form className="panel stack" onSubmit={handleSubmit}>
|
||||
<div className="panel-heading">
|
||||
<span>Article Input</span>
|
||||
<button disabled={isSubmitting} type="submit">
|
||||
{isSubmitting ? "Analyzing..." : "Analyze"}
|
||||
</button>
|
||||
</div>
|
||||
<label>
|
||||
<span>Title</span>
|
||||
<input
|
||||
required
|
||||
value={value.title}
|
||||
onChange={(event) => update("title", event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span>Body</span>
|
||||
<textarea
|
||||
required
|
||||
className="body-input"
|
||||
value={value.body}
|
||||
onChange={(event) => update("body", event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span>Images</span>
|
||||
<textarea
|
||||
value={value.image_lines}
|
||||
onChange={(event) => update("image_lines", event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<span>Target platform</span>
|
||||
<select
|
||||
value={value.platform}
|
||||
onChange={(event) =>
|
||||
update("platform", event.target.value as PublishPlatform)
|
||||
}
|
||||
>
|
||||
{platforms.map((platform) => (
|
||||
<option key={platform.value} value={platform.value}>
|
||||
{platform.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>User instructions</span>
|
||||
<textarea
|
||||
value={value.user_instructions}
|
||||
onChange={(event) => update("user_instructions", event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user