osanseviero commited on
Commit
b176809
·
verified ·
1 Parent(s): 39ed31e

Delete page.tsx

Browse files
Files changed (1) hide show
  1. page.tsx +0 -251
page.tsx DELETED
@@ -1,251 +0,0 @@
1
- "use client";
2
-
3
- import CodeViewer from "@/components/code-viewer";
4
- import { useScrollTo } from "@/hooks/use-scroll-to";
5
- import { CheckIcon } from "@heroicons/react/16/solid";
6
- import { ArrowLongRightIcon, ChevronDownIcon } from "@heroicons/react/20/solid";
7
- import { ArrowUpOnSquareIcon } from "@heroicons/react/24/outline";
8
- import * as Select from "@radix-ui/react-select";
9
- import * as Switch from "@radix-ui/react-switch";
10
- import { AnimatePresence, motion } from "framer-motion";
11
- import { FormEvent, useEffect, useState } from "react";
12
- import LoadingDots from "../../components/loading-dots";
13
-
14
- function removeCodeFormatting(code: string): string {
15
- return code.replace(/```(?:typescript|javascript|tsx)?\n([\s\S]*?)```/g, '$1').trim();
16
- }
17
-
18
- export default function Home() {
19
- let [status, setStatus] = useState<
20
- "initial" | "creating" | "created" | "updating" | "updated"
21
- >("initial");
22
- let [prompt, setPrompt] = useState("");
23
- let models = [
24
- {
25
- label: "gemini-2.0-flash-exp",
26
- value: "gemini-2.0-flash-exp",
27
- },
28
- {
29
- label: "gemini-1.5-pro",
30
- value: "gemini-1.5-pro",
31
- },
32
- {
33
- label: "gemini-1.5-flash",
34
- value: "gemini-1.5-flash",
35
- }
36
- ];
37
- let [model, setModel] = useState(models[0].value);
38
- let [modification, setModification] = useState("");
39
- let [generatedCode, setGeneratedCode] = useState("");
40
- let [initialAppConfig, setInitialAppConfig] = useState({
41
- model: "",
42
- shadcn: true,
43
- });
44
- let [ref, scrollTo] = useScrollTo();
45
- let [messages, setMessages] = useState<{ role: string; content: string }[]>(
46
- [],
47
- );
48
-
49
- let loading = status === "creating" || status === "updating";
50
-
51
- async function createApp(e: FormEvent<HTMLFormElement>) {
52
- e.preventDefault();
53
-
54
- if (status !== "initial") {
55
- scrollTo({ delay: 0.5 });
56
- }
57
-
58
- setStatus("creating");
59
- setGeneratedCode("");
60
-
61
- let res = await fetch("/api/generateCode", {
62
- method: "POST",
63
- headers: {
64
- "Content-Type": "application/json",
65
- },
66
- body: JSON.stringify({
67
- model,
68
- messages: [{ role: "user", content: prompt }],
69
- }),
70
- });
71
-
72
- if (!res.ok) {
73
- throw new Error(res.statusText);
74
- }
75
-
76
- if (!res.body) {
77
- throw new Error("No response body");
78
- }
79
-
80
- const reader = res.body.getReader();
81
- let receivedData = "";
82
-
83
- while (true) {
84
- const { done, value } = await reader.read();
85
- if (done) {
86
- break;
87
- }
88
- receivedData += new TextDecoder().decode(value);
89
- const cleanedData = removeCodeFormatting(receivedData);
90
- setGeneratedCode(cleanedData);
91
- }
92
-
93
- setMessages([{ role: "user", content: prompt }]);
94
- setInitialAppConfig({ model });
95
- setStatus("created");
96
- }
97
-
98
- useEffect(() => {
99
- let el = document.querySelector(".cm-scroller");
100
- if (el && loading) {
101
- let end = el.scrollHeight - el.clientHeight;
102
- el.scrollTo({ top: end });
103
- }
104
- }, [loading, generatedCode]);
105
-
106
- return (
107
- <main className="mt-12 flex w-full flex-1 flex-col items-center px-4 text-center sm:mt-1">
108
- <a
109
- className="mb-4 inline-flex h-7 shrink-0 items-center gap-[9px] rounded-[50px] border-[0.5px] border-solid border-[#E6E6E6] bg-[rgba(234,238,255,0.65)] bg-gray-100 px-7 py-5 shadow-[0px_1px_1px_0px_rgba(0,0,0,0.25)]"
110
- href="https://ai.google.dev/gemini-api/docs"
111
- target="_blank"
112
- >
113
- <span className="text-center">
114
- Powered by <span className="font-medium">Gemini API</span>
115
- </span>
116
- </a>
117
- <h1 className="my-6 max-w-3xl text-4xl font-bold text-gray-800 sm:text-6xl">
118
- Turn your <span className="text-blue-600">idea</span>
119
- <br /> into an <span className="text-blue-600">app</span>
120
- </h1>
121
-
122
- <form className="w-full max-w-xl" onSubmit={createApp}>
123
- <fieldset disabled={loading} className="disabled:opacity-75">
124
- <div className="relative mt-5">
125
- <div className="absolute -inset-2 rounded-[32px] bg-gray-300/50" />
126
- <div className="relative flex rounded-3xl bg-white shadow-sm">
127
- <div className="relative flex flex-grow items-stretch focus-within:z-10">
128
- <textarea
129
- rows={3}
130
- required
131
- value={prompt}
132
- onChange={(e) => setPrompt(e.target.value)}
133
- name="prompt"
134
- className="w-full resize-none rounded-l-3xl bg-transparent px-6 py-5 text-lg focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-500"
135
- placeholder="Build me a calculator app..."
136
- />
137
- </div>
138
- <button
139
- type="submit"
140
- disabled={loading}
141
- className="relative -ml-px inline-flex items-center gap-x-1.5 rounded-r-3xl px-3 py-2 text-sm font-semibold text-blue-500 hover:text-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-500 disabled:text-gray-900"
142
- >
143
- {status === "creating" ? (
144
- <LoadingDots color="black" style="large" />
145
- ) : (
146
- <ArrowLongRightIcon className="-ml-0.5 size-6" />
147
- )}
148
- </button>
149
- </div>
150
- </div>
151
- <div className="mt-6 flex flex-col justify-center gap-4 sm:flex-row sm:items-center sm:gap-8">
152
- <div className="flex items-center justify-between gap-3 sm:justify-center">
153
- <p className="text-gray-500 sm:text-xs">Model:</p>
154
- <Select.Root
155
- name="model"
156
- disabled={loading}
157
- value={model}
158
- onValueChange={(value) => setModel(value)}
159
- >
160
- <Select.Trigger className="group flex w-60 max-w-xs items-center rounded-2xl border-[6px] border-gray-300 bg-white px-4 py-2 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-500">
161
- <Select.Value />
162
- <Select.Icon className="ml-auto">
163
- <ChevronDownIcon className="size-6 text-gray-300 group-focus-visible:text-gray-500 group-enabled:group-hover:text-gray-500" />
164
- </Select.Icon>
165
- </Select.Trigger>
166
- <Select.Portal>
167
- <Select.Content className="overflow-hidden rounded-md bg-white shadow-lg">
168
- <Select.Viewport className="p-2">
169
- {models.map((model) => (
170
- <Select.Item
171
- key={model.value}
172
- value={model.value}
173
- className="flex cursor-pointer items-center rounded-md px-3 py-2 text-sm data-[highlighted]:bg-gray-100 data-[highlighted]:outline-none"
174
- >
175
- <Select.ItemText asChild>
176
- <span className="inline-flex items-center gap-2 text-gray-500">
177
- <div className="size-2 rounded-full bg-green-500" />
178
- {model.label}
179
- </span>
180
- </Select.ItemText>
181
- <Select.ItemIndicator className="ml-auto">
182
- <CheckIcon className="size-5 text-blue-600" />
183
- </Select.ItemIndicator>
184
- </Select.Item>
185
- ))}
186
- </Select.Viewport>
187
- <Select.ScrollDownButton />
188
- <Select.Arrow />
189
- </Select.Content>
190
- </Select.Portal>
191
- </Select.Root>
192
- </div>
193
- </div>
194
- </fieldset>
195
- </form>
196
-
197
- <hr className="border-1 mb-20 h-px bg-gray-700 dark:bg-gray-700" />
198
-
199
- {status !== "initial" && (
200
- <motion.div
201
- initial={{ height: 0 }}
202
- animate={{
203
- height: "auto",
204
- overflow: "hidden",
205
- transitionEnd: { overflow: "visible" },
206
- }}
207
- transition={{ type: "spring", bounce: 0, duration: 0.5 }}
208
- className="w-full pb-[25vh] pt-1"
209
- onAnimationComplete={() => scrollTo()}
210
- ref={ref}
211
- >
212
- <div className="relative mt-8 w-full overflow-hidden">
213
- <div className="isolate">
214
- <CodeViewer code={generatedCode} showEditor />
215
- </div>
216
-
217
- <AnimatePresence>
218
- {loading && (
219
- <motion.div
220
- initial={status === "updating" ? { x: "100%" } : undefined}
221
- animate={status === "updating" ? { x: "0%" } : undefined}
222
- exit={{ x: "100%" }}
223
- transition={{
224
- type: "spring",
225
- bounce: 0,
226
- duration: 0.85,
227
- delay: 0.5,
228
- }}
229
- className="absolute inset-x-0 bottom-0 top-1/2 flex items-center justify-center rounded-r border border-gray-400 bg-gradient-to-br from-gray-100 to-gray-300 md:inset-y-0 md:left-1/2 md:right-0"
230
- >
231
- <p className="animate-pulse text-3xl font-bold">
232
- {status === "creating"
233
- ? "Building your app..."
234
- : "Updating your app..."}
235
- </p>
236
- </motion.div>
237
- )}
238
- </AnimatePresence>
239
- </div>
240
- </motion.div>
241
- )}
242
- </main>
243
- );
244
- }
245
-
246
- async function minDelay<T>(promise: Promise<T>, ms: number) {
247
- let delay = new Promise((resolve) => setTimeout(resolve, ms));
248
- let [p] = await Promise.all([promise, delay]);
249
-
250
- return p;
251
- }