Public
HTTP
andreterron-genval.web.val.run
September 4, 2024
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { generateValCode } from "https://esm.town/v/andreterron/generateValCode";
import { html as htmlRes } from "https://esm.town/v/stevekrouse/html";
import process from "node:process";
export let genval = async (req: Request): Promise<Response> => {
const { default: htm } = await import("npm:htm");
const { default: vhtml } = await import("npm:vhtml");
const cookies = await import("https://deno.land/std@0.193.0/http/cookie.ts");
const html = htm.bind(vhtml);
const head = html`<head>
<title>Gen Val</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.org@1.9.2"></script>
</head>`;
const formClass = "p-2 pt-16 group min-h-screen animate-all bg-emerald-50 w-full max-w-2xl mx-auto";
const inputClass = "p-2 border rounded w-full";
const labelClass = "w-full text-sm font-bold uppercase text-emerald-800 [&>span]:pl-0.5 flex flex-col gap-2";
function parseCookies(cookie: string) {
const out: Record<string, string> = {};
const c = cookie.split(";");
for (const kv of c) {
const [cookieKey, ...cookieVal] = kv.split("=");
const key = cookieKey.trim();
out[key] = cookieVal.join("=");
}
return out;
}
switch (req.method) {
case "POST": {
const value = await req.json();
if (
!("description" in value)
|| !value.description
) {
return new Response("Bad input", { status: 400 });
}
const code = await generateValCode(
process.env.VT_OPENAI_KEY,
value.description,
);
const query = new URLSearchParams({ code });
const url = `https://www.val.town/embed/new?${query.toString()}`;
return htmlRes(html`<html>
${head}
<body class="bg-emerald-50">
<div class="w-full max-w-2xl mx-auto flex flex-col gap-4 p-6 ">
<h1 class="text-3xl text-center font-bold text-emerald-800">
Generated Val:
</h1>
<iframe class="w-full h-[480px]" src=${url} />
<a class="p-2 bg-emerald-500 text-white rounded" href="/">Generate another</a>
</div>
</body>
</html>`);
}
default: {
return htmlRes(html`<html>
${head}
<body class="bg-emerald-50">
<form hx-post="/" class=${formClass}>
<div class='flex justify-between items-center'>
<div class='group-[&.htmx-request]:block hidden uppercase text-emerald-500 text-sm'>
Loading…
</div>
</div>
<h1 class="text-3xl text-center font-bold text-emerald-800">
Generate a Val!
</h1>
<div class="flex flex-col gap-6 items-start p-4 max-w-2xl">
<label class=${labelClass} for="description">
<span>Description</span>
<input required class=${inputClass} id="description" name="description" type="text" placeholder="Function to return a random number" autocomplete="off" />
</label>
<button class="p-2 bg-emerald-500 text-white rounded" type="submit">Generate!</button>
</div>
</form>
<script>
</script>
</body>
</html>`);
}
}
};
// Forked from @tmcw.poll
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
September 4, 2024