feat: add main features

Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
2026-06-06 01:27:01 +02:00
parent 55b3bee2c8
commit 307ae71857
273 changed files with 48740 additions and 0 deletions

View File

@ -0,0 +1,103 @@
/**
* `ProjectLauncher` — the empty-state screen shown when no project tab is open.
*
* Renders the project creation form and the known-projects list centred in the
* available space. All behaviour comes from the `vm` prop (a `useProjects`
* view-model slice); no hooks called here — presentation only.
*/
import type { Project } from "@/domain";
import { Button, Input, Panel } from "@/shared";
export interface ProjectLauncherProps {
/** Form field values */
name: string;
root: string;
onNameChange: (v: string) => void;
onRootChange: (v: string) => void;
onSubmit: (e: React.FormEvent) => void;
canCreate: boolean;
busy: boolean;
onRefresh: () => void;
projects: Project[];
onOpen: (id: string) => void;
error?: string | null;
}
export function ProjectLauncher({
name,
root,
onNameChange,
onRootChange,
onSubmit,
canCreate,
busy,
onRefresh,
projects,
onOpen,
error,
}: ProjectLauncherProps) {
return (
<div className="flex flex-1 items-start justify-center p-8">
<div className="flex w-full max-w-2xl flex-col gap-6">
{error && (
<p
role="alert"
className="rounded-md border border-danger/40 bg-danger/10 px-3 py-2 text-sm text-danger"
>
{error}
</p>
)}
<div className="flex flex-col gap-3">
<h2 className="text-base font-semibold text-content">New project</h2>
<form onSubmit={onSubmit} className="flex flex-wrap items-center gap-2">
<Input
aria-label="project name"
placeholder="Project name"
value={name}
onChange={(e) => onNameChange(e.target.value)}
className="w-48"
/>
<Input
aria-label="project root"
placeholder="/absolute/project/root"
value={root}
onChange={(e) => onRootChange(e.target.value)}
className="min-w-80 flex-1"
/>
<Button type="submit" variant="primary" disabled={!canCreate}>
Create project
</Button>
<Button type="button" onClick={onRefresh} disabled={busy}>
Refresh
</Button>
</form>
</div>
<Panel title="Known projects">
{projects.length === 0 ? (
<p className="text-sm text-muted">No projects yet.</p>
) : (
<ul className="flex flex-col divide-y divide-border">
{projects.map((p) => (
<li
key={p.id}
className="flex items-center justify-between gap-3 py-2 first:pt-0 last:pb-0"
>
<span className="flex min-w-0 items-baseline gap-2">
<span className="font-medium text-content">{p.name}</span>
<code className="truncate text-xs text-muted">{p.root}</code>
</span>
<Button size="sm" onClick={() => onOpen(p.id)}>
Open
</Button>
</li>
))}
</ul>
)}
</Panel>
</div>
</div>
);
}