task-runtime-ai / app /page.tsx
harshlocham's picture
Refactor code structure for improved readability and maintainability
f0f2f77
Raw
History Blame Contribute Delete
5.99 kB
"use client";
import { FormEvent, useState } from "react";
type RunTaskResponse = {
providerUsed: string;
goal: string;
successDefinition: string;
executionTrace: string[];
finalResult: string;
planNotes?: string | null;
error?: string;
};
const DEFAULT_PROMPT = "Plan and summarize a concise hackathon demo for a task runner UI.";
export default function Home() {
const [prompt, setPrompt] = useState(DEFAULT_PROMPT);
const [result, setResult] = useState<RunTaskResponse | null>(null);
const [error, setError] = useState<string | null>(null);
const [isRunning, setIsRunning] = useState(false);
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const trimmed = prompt.trim();
if (!trimmed) {
setError("Enter a prompt before running the task.");
return;
}
setIsRunning(true);
setError(null);
try {
const response = await fetch("/api/run-task", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prompt: trimmed }),
});
const payload = (await response.json()) as RunTaskResponse;
if (!response.ok) {
throw new Error(payload.error || "Task run failed.");
}
setResult(payload);
} catch (requestError) {
setResult(null);
setError(requestError instanceof Error ? requestError.message : "Task run failed.");
} finally {
setIsRunning(false);
}
}
return (
<main className="app-shell">
<div className="ambient ambient-one" />
<div className="ambient ambient-two" />
<section className="hero panel">
<p className="eyebrow">Hackathon demo</p>
<h1>Shared planner, shared provider, minimal surface.</h1>
<p className="hero-copy">
Run the same task planning path used by the worker services, but render it in a single Next.js page that is easy to ship to Hugging Face Spaces.
</p>
</section>
<section className="workspace">
<form className="panel form-panel" onSubmit={handleSubmit}>
<label className="label" htmlFor="prompt">
Prompt
</label>
<textarea
id="prompt"
className="prompt-input"
value={prompt}
onChange={(event) => setPrompt(event.target.value)}
spellCheck={false}
placeholder="Describe the task you want planned and summarized."
/>
<div className="actions">
<button className="run-button" type="submit" disabled={isRunning}>
{isRunning ? "Running..." : "Run task"}
</button>
<span className="hint">POST /api/run-task</span>
</div>
{error ? <p className="error-text">{error}</p> : null}
</form>
<div className="results-column">
<section className="panel result-panel">
<div className="panel-header">
<div>
<p className="panel-kicker">Provider used</p>
<h2>{result?.providerUsed ?? "Waiting for a run"}</h2>
</div>
{result ? <span className="status-pill">Ready</span> : <span className="status-pill muted">Idle</span>}
</div>
<dl className="meta-grid">
<div>
<dt>Goal</dt>
<dd>{result?.goal ?? "No task has been executed yet."}</dd>
</div>
<div>
<dt>Success definition</dt>
<dd>{result?.successDefinition ?? "Run a prompt to see the planner output."}</dd>
</div>
</dl>
</section>
<section className="panel trace-panel">
<div className="panel-header">
<div>
<p className="panel-kicker">Execution trace</p>
<h2>Planner steps</h2>
</div>
</div>
{result?.executionTrace?.length ? (
<ol className="trace-list">
{result.executionTrace.map((entry) => (
<li key={entry}>{entry}</li>
))}
</ol>
) : (
<p className="empty-state">The execution trace will appear here after the first run.</p>
)}
{result?.planNotes ? <p className="plan-notes">{result.planNotes}</p> : null}
</section>
<section className="panel output-panel">
<div className="panel-header">
<div>
<p className="panel-kicker">Final result</p>
<h2>Provider output</h2>
</div>
</div>
<pre className="output-box">{result?.finalResult ?? "Run a task to see the final result."}</pre>
</section>
</div>
</section>
</main>
);
}