Spaces:
Running
Running
File size: 6,496 Bytes
63c7991 57ffdaf 63c7991 57ffdaf 63c7991 57ffdaf 63c7991 57ffdaf 63c7991 57ffdaf 63c7991 57ffdaf 63c7991 9d1a465 63c7991 9d1a465 63c7991 9d1a465 63c7991 9d1a465 63c7991 9d1a465 63c7991 |
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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
"use client";
import CodeViewer from "@/components/code-viewer";
import { useScrollTo } from "@/hooks/use-scroll-to";
import { CheckIcon } from "@heroicons/react/16/solid";
import { ArrowLongRightIcon, ChevronDownIcon } from "@heroicons/react/20/solid";
import { ArrowUpOnSquareIcon } from "@heroicons/react/24/outline";
import * as Select from "@radix-ui/react-select";
import * as Switch from "@radix-ui/react-switch";
import { AnimatePresence, motion } from "framer-motion";
import { FormEvent, useEffect, useState } from "react";
import LoadingDots from "../../components/loading-dots";
function removeCodeFormatting(code: string): string {
return code.replace(/```(?:typescript|javascript|tsx)?\n([\s\S]*?)```/g, '$1').trim();
}
export default function Home() {
let [status, setStatus] = useState<
"initial" | "creating" | "created" | "updating" | "updated"
>("initial");
let [prompt, setPrompt] = useState("");
let models = [
{
label: "gemini-2.0-flash-exp",
value: "gemini-2.0-flash-exp",
},
{
label: "gemini-1.5-pro",
value: "gemini-1.5-pro",
},
{
label: "gemini-1.5-flash",
value: "gemini-1.5-flash",
}
];
let [model, setModel] = useState(models[0].value);
let [modification, setModification] = useState("");
let [generatedCode, setGeneratedCode] = useState("");
let [initialAppConfig, setInitialAppConfig] = useState({
model: "",
});
let [ref, scrollTo] = useScrollTo();
let [messages, setMessages] = useState<{ role: string; content: string }[]>([]);
let loading = status === "creating" || status === "updating";
async function createApp(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
if (status !== "initial") {
scrollTo({ delay: 0.5 });
}
setStatus("creating");
setGeneratedCode("");
try {
let res = await fetch("/api/generateCode", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: prompt }],
}),
});
if (!res.ok) {
throw new Error(res.statusText || `HTTP error: ${res.status}`);
}
if (!res.body) {
throw new Error("No response body");
}
const reader = res.body.getReader();
let receivedData = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
receivedData += new TextDecoder().decode(value);
const cleanedData = removeCodeFormatting(receivedData);
setGeneratedCode(cleanedData);
}
setMessages([{ role: "user", content: prompt }]);
setInitialAppConfig({ model });
setStatus("created");
} catch (error) {
console.error("Error al generar la aplicación:", error);
setStatus("initial");
}
}
useEffect(() => {
let el = document.querySelector(".cm-scroller");
if (el && loading) {
let end = el.scrollHeight - el.clientHeight;
el.scrollTo({ top: end });
}
}, [loading, generatedCode]);
return (
<main className="mt-12 flex w-full flex-1 flex-col items-center px-4 text-center sm:mt-1">
<a
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)] dark:bg-[rgba(30,41,59,0.5)] dark:border-gray-700 px-7 py-5 shadow-[0px_1px_1px_0px_rgba(0,0,0,0.25)]"
href="https://ai.google.dev/gemini-api/docs"
target="_blank"
>
<span className="text-center">
Powered by <span className="font-medium">Gemini API</span>
</span>
</a>
<h1 className="my-6 max-w-3xl text-4xl font-bold text-gray-800 dark:text-white sm:text-6xl">
Turn your <span className="text-blue-600">idea</span>
<br /> into an <span className="text-blue-600">app</span>
</h1>
<form className="w-full max-w-xl" onSubmit={createApp}>
<fieldset disabled={loading} className="disabled:opacity-75">
<div className="relative mt-5">
<div className="absolute -inset-2 rounded-[32px] bg-gray-300/50 dark:bg-gray-800/50" />
<div className="relative flex rounded-3xl bg-white dark:bg-[#1E293B] shadow-sm">
<div className="relative flex flex-grow items-stretch focus-within:z-10">
<textarea
rows={3}
required
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
name="prompt"
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 dark:text-gray-100 dark:placeholder-gray-400"
placeholder="Build me a calculator app..."
/>
</div>
<button
type="submit"
disabled={loading}
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 dark:disabled:text-gray-400"
>
{status === "creating" ? (
<LoadingDots color="black" style="large" />
) : (
<ArrowLongRightIcon className="-ml-0.5 size-6" />
)}
</button>
</div>
</div>
</fieldset>
</form>
{status !== "initial" && (
<motion.div
initial={{ height: 0 }}
animate={{
height: "auto",
overflow: "hidden",
transitionEnd: { overflow: "visible" },
}}
transition={{ type: "spring", bounce: 0, duration: 0.5 }}
className="w-full pb-[25vh] pt-1"
onAnimationComplete={() => scrollTo()}
ref={ref}
>
<div className="relative mt-8 w-full overflow-hidden">
<div className="isolate">
<CodeViewer code={generatedCode} showEditor />
</div>
</div>
</motion.div>
)}
</main>
);
}
async function minDelay<T>(promise: Promise<T>, ms: number) {
let delay = new Promise((resolve) => setTimeout(resolve, ms));
let [p] = await Promise.all([promise, delay]);
return p;
}
|