Skip to content

Commit 65b9b81

Browse files
committed
new generate page
1 parent 7c8a28c commit 65b9b81

2 files changed

Lines changed: 63 additions & 40 deletions

File tree

.dockerignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
.git
2+
.github
3+
.vscode
4+
.mypy_cache
5+
.pytest_cache
6+
.ruff_cache
7+
.venv
8+
node_modules
9+
frontend/node_modules
10+
frontend/dist
11+
frontend/playwright-report
12+
frontend/test-results
13+
frontend/blob-report
14+
backend/.venv
15+
backend/__pycache__
16+
backend/.pytest_cache
17+
backend/.mypy_cache
18+
backend/.ruff_cache
19+
*.log
20+
*.pyc
21+
.env

frontend/src/routes/_layout/generate.tsx

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
22
import { createFileRoute } from "@tanstack/react-router"
3+
import { Check, Copy } from "lucide-react"
34
import { useEffect, useMemo, useState } from "react"
4-
55
import { Button } from "@/components/ui/button"
66
import {
77
Card,
@@ -11,6 +11,7 @@ import {
1111
CardTitle,
1212
} from "@/components/ui/card"
1313
import { Input } from "@/components/ui/input"
14+
import { useCopyToClipboard } from "@/hooks/useCopyToClipboard"
1415
import useCustomToast from "@/hooks/useCustomToast"
1516
import {
1617
createGeneration,
@@ -19,12 +20,11 @@ import {
1920
getTemplate,
2021
listTemplates,
2122
listTemplateVersions,
22-
renderTemplate,
2323
type Template,
2424
type TemplateVariableConfig,
2525
type TemplateVersion,
2626
} from "@/lib/templateMvpApi"
27-
import { errorToMessage } from "@/lib/templateVariables"
27+
import { errorToMessage, renderTemplateText } from "@/lib/templateVariables"
2828

2929
function listToInput(value: unknown): string {
3030
if (!Array.isArray(value)) {
@@ -103,6 +103,7 @@ export const Route = createFileRoute("/_layout/generate")({
103103
function GeneratePage() {
104104
const queryClient = useQueryClient()
105105
const { showErrorToast, showSuccessToast } = useCustomToast()
106+
const [copiedText, copy] = useCopyToClipboard()
106107

107108
const [selectedTemplateId, setSelectedTemplateId] = useState<string>("")
108109
const [selectedVersionId, setSelectedVersionId] = useState<string>("")
@@ -168,10 +169,6 @@ function GeneratePage() {
168169
mutationFn: extractVariables,
169170
})
170171

171-
const renderMutation = useMutation({
172-
mutationFn: renderTemplate,
173-
})
174-
175172
const saveGenerationMutation = useMutation({
176173
mutationFn: createGeneration,
177174
})
@@ -192,6 +189,7 @@ function GeneratePage() {
192189
if (!currentVersion) {
193190
setValues({})
194191
setMissingRequired([])
192+
setOutputText("")
195193
return
196194
}
197195

@@ -208,8 +206,14 @@ function GeneratePage() {
208206
}
209207
setValues(initialValues)
210208
setMissingRequired([])
211-
setOutputText("")
212-
}, [currentVersion?.id, currentVersion])
209+
}, [currentVersion])
210+
211+
useEffect(() => {
212+
if (!currentVersion) {
213+
return
214+
}
215+
setOutputText(renderTemplateText(currentVersion.content, values))
216+
}, [currentVersion, values])
213217

214218
const handleExtract = async () => {
215219
if (!selectedVersionId) {
@@ -235,28 +239,6 @@ function GeneratePage() {
235239
}
236240
}
237241

238-
const handleRender = async () => {
239-
if (!selectedVersionId) {
240-
showErrorToast("Select a template version first")
241-
return
242-
}
243-
244-
try {
245-
const result = await renderMutation.mutateAsync({
246-
template_version_id: selectedVersionId,
247-
values,
248-
style: {
249-
tone: "professional",
250-
length: "medium",
251-
},
252-
})
253-
setOutputText(result.output_text)
254-
showSuccessToast("Draft generated")
255-
} catch (error) {
256-
showErrorToast(errorToMessage(error))
257-
}
258-
}
259-
260242
const handleSaveGeneration = async () => {
261243
if (!selectedTemplateId || !selectedVersionId || !outputText.trim()) {
262244
showErrorToast("Generate content before saving")
@@ -319,6 +301,19 @@ function GeneratePage() {
319301
setMissingRequired((current) => current.filter((item) => item !== variable))
320302
}
321303

304+
const handleCopyOutput = async () => {
305+
const text = outputText.trim()
306+
if (!text) {
307+
showErrorToast("Nothing to copy")
308+
return
309+
}
310+
311+
const ok = await copy(outputText)
312+
if (!ok) {
313+
showErrorToast("Copy failed")
314+
}
315+
}
316+
322317
return (
323318
<div className="space-y-6">
324319
<div>
@@ -392,7 +387,7 @@ function GeneratePage() {
392387
<CardHeader>
393388
<CardTitle>Step C: Confirm Variables</CardTitle>
394389
<CardDescription>
395-
Fill missing required fields before generating.
390+
Fill missing required fields. Output updates in real time.
396391
</CardDescription>
397392
</CardHeader>
398393
<CardContent className="space-y-4">
@@ -440,19 +435,26 @@ function GeneratePage() {
440435
Select a template version to load variables.
441436
</p>
442437
)}
443-
444-
<Button
445-
onClick={handleRender}
446-
disabled={renderMutation.isPending || !currentVersion}
447-
>
448-
Generate Draft
449-
</Button>
450438
</CardContent>
451439
</Card>
452440

453441
<Card>
454-
<CardHeader>
442+
<CardHeader className="flex flex-row items-center justify-between">
455443
<CardTitle>Step D: Output</CardTitle>
444+
<Button
445+
variant="outline"
446+
size="sm"
447+
className="gap-2"
448+
onClick={handleCopyOutput}
449+
disabled={!outputText.trim()}
450+
>
451+
{copiedText === outputText ? (
452+
<Check className="size-4 text-green-500" />
453+
) : (
454+
<Copy className="size-4" />
455+
)}
456+
{copiedText === outputText ? "Copied" : "test"}
457+
</Button>
456458
</CardHeader>
457459
<CardContent className="space-y-3">
458460
<textarea

0 commit comments

Comments
 (0)