Trudy commited on
Commit
36c87c6
·
1 Parent(s): e3e9445

added error modal

Browse files
Files changed (2) hide show
  1. components/ErrorModal.js +74 -0
  2. pages/index.js +36 -16
components/ErrorModal.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { X } from 'lucide-react';
3
+ import { Github } from 'lucide-react';
4
+
5
+ const ErrorModal = ({ isOpen, onClose }) => {
6
+ if (!isOpen) return null;
7
+
8
+ return (
9
+ <div className="fixed inset-0 z-50 flex items-center justify-center">
10
+ {/* Semi-opaque blur background */}
11
+ <div
12
+ className="absolute inset-0 bg-gray-800/30 backdrop-blur-sm"
13
+ onClick={onClose}
14
+ onKeyDown={(e) => e.key === 'Escape' && onClose()}
15
+ role="button"
16
+ tabIndex={0}
17
+ />
18
+
19
+ {/* Modal card */}
20
+ <div className="relative bg-white rounded-2xl p-8 shadow-lg border border-gray-200 max-w-lg mx-4 z-10">
21
+ <button
22
+ type="button"
23
+ onClick={onClose}
24
+ className="absolute top-4 right-4 text-gray-400 hover:text-gray-600 transition-colors"
25
+ >
26
+ <X size={24} />
27
+ </button>
28
+
29
+ <h2 className="text-xl font-bold text-gray-900 mb-4">
30
+ This space is very popular right now...
31
+ </h2>
32
+
33
+ <p className="text-gray-600 mb-4">
34
+ Due to high demand, we're not able to process requests right now. Want to run this locally? Get the code and host it yourself!
35
+ </p>
36
+
37
+ <p className="text-gray-600 mb-8">
38
+ You can get your own API key from{' '}
39
+ <a
40
+ href="https://ai.google.dev"
41
+ target="_blank"
42
+ rel="noopener noreferrer"
43
+ className="text-blue-600 hover:text-blue-800 underline"
44
+ >
45
+ ai.google.dev
46
+ </a>
47
+ {' '}to start using this right away.
48
+ </p>
49
+
50
+ <div className="flex gap-4 justify-center">
51
+ <a
52
+ href="https://github.com/googlecreativelab/gemini-demos/tree/main/image-to-code"
53
+ target="_blank"
54
+ rel="noopener noreferrer"
55
+ className="flex items-center gap-2 px-4 py-2 bg-gray-900 text-white rounded-lg hover:bg-gray-800 transition-colors"
56
+ >
57
+ <Github size={20} />
58
+ <span>Get the code on GitHub</span>
59
+ </a>
60
+
61
+ <button
62
+ type="button"
63
+ onClick={onClose}
64
+ className="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors"
65
+ >
66
+ Close
67
+ </button>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ );
72
+ };
73
+
74
+ export default ErrorModal;
pages/index.js CHANGED
@@ -20,6 +20,7 @@ import { ChevronDown, Image, Upload, Settings, Send, History, ArrowRight, Pen, L
20
  import Head from "next/head";
21
  import CodePreview from "../components/CodePreview";
22
  import Header from '../components/Header';
 
23
 
24
  const SAMPLE_IMAGES = [
25
  'beeripple.jpeg',
@@ -36,23 +37,28 @@ const SAMPLE_IMAGES = [
36
 
37
  // Helper function to generate code from image
38
  async function generateCodeFromImage(imageBase64, prompt, userInput) {
39
- const response = await fetch('/api/hello', {
40
- method: 'POST',
41
- headers: {
42
- 'Content-Type': 'application/json',
43
- },
44
- body: JSON.stringify({
45
- imageBase64,
46
- prompt,
47
- userInput
48
- })
49
- });
 
 
 
 
 
50
 
51
- if (!response.ok) {
52
- throw new Error('Failed to generate code');
 
 
53
  }
54
-
55
- return response.json();
56
  }
57
 
58
  export default function Home() {
@@ -64,6 +70,7 @@ export default function Home() {
64
  const [concurrentRequests, setConcurrentRequests] = useState(5);
65
  const [showPrompt, setShowPrompt] = useState(false);
66
  const [prompt, setPrompt] = useState("");
 
67
 
68
  // Load prompt from localStorage on initial render
69
  useEffect(() => {
@@ -181,12 +188,20 @@ export default function Home() {
181
  setLoading(true);
182
  setHasStartedGenerating(true);
183
  setOutputs([]);
 
184
  try {
185
  const requests = Array(concurrentRequests)
186
  .fill()
187
  .map(() => generateCodeFromImage(imageBase64, prompt, userInput));
188
 
189
  const results = await Promise.all(requests);
 
 
 
 
 
 
 
190
  setOutputs(results.map((result, index) => ({
191
  id: index + 1,
192
  code: result.code,
@@ -194,6 +209,7 @@ export default function Home() {
194
  })));
195
  } catch (error) {
196
  console.error("Error generating code:", error);
 
197
  } finally {
198
  setLoading(false);
199
  }
@@ -277,6 +293,10 @@ export default function Home() {
277
  </Head>
278
  <div className="h-screen max-h-screen bg-white flex items-center justify-center overflow-y-hidden tracking-[-0.005em]">
279
  <Header />
 
 
 
 
280
 
281
  <div className="w-full h-full max-h-full overflow-hidden bg-white">
282
  <div className={`flex flex-col md:flex-row gap-0 max-w-6xl mx-auto py-0 h-full transition-all duration-500 ${!hasStartedGenerating ? 'justify-center' : ''}`}>
@@ -410,7 +430,7 @@ export default function Home() {
410
  {loading ? (
411
  // Loading skeletons for code previews
412
  Array(concurrentRequests).fill().map((_, index) => (
413
- <div key={`skeleton-${index}`} className="mb-4 p-6 rounded-3xl bg-gray-100 animate-pulse">
414
  <div className="w-full h-[500px] bg-gray-200 rounded-lg mb-4" />
415
  <div className="flex justify-between items-center">
416
  <div className="h-10 w-32 bg-gray-200 rounded-full" />
 
20
  import Head from "next/head";
21
  import CodePreview from "../components/CodePreview";
22
  import Header from '../components/Header';
23
+ import ErrorModal from '../components/ErrorModal';
24
 
25
  const SAMPLE_IMAGES = [
26
  'beeripple.jpeg',
 
37
 
38
  // Helper function to generate code from image
39
  async function generateCodeFromImage(imageBase64, prompt, userInput) {
40
+ try {
41
+ const response = await fetch('/api/hello', {
42
+ method: 'POST',
43
+ headers: {
44
+ 'Content-Type': 'application/json',
45
+ },
46
+ body: JSON.stringify({
47
+ imageBase64,
48
+ prompt,
49
+ userInput
50
+ })
51
+ });
52
+
53
+ if (!response.ok) {
54
+ return { error: true, message: 'Failed to generate code' };
55
+ }
56
 
57
+ const data = await response.json();
58
+ return { error: false, ...data };
59
+ } catch (error) {
60
+ return { error: true, message: error.message || 'Failed to generate code' };
61
  }
 
 
62
  }
63
 
64
  export default function Home() {
 
70
  const [concurrentRequests, setConcurrentRequests] = useState(5);
71
  const [showPrompt, setShowPrompt] = useState(false);
72
  const [prompt, setPrompt] = useState("");
73
+ const [showErrorModal, setShowErrorModal] = useState(false);
74
 
75
  // Load prompt from localStorage on initial render
76
  useEffect(() => {
 
188
  setLoading(true);
189
  setHasStartedGenerating(true);
190
  setOutputs([]);
191
+
192
  try {
193
  const requests = Array(concurrentRequests)
194
  .fill()
195
  .map(() => generateCodeFromImage(imageBase64, prompt, userInput));
196
 
197
  const results = await Promise.all(requests);
198
+
199
+ // Check if any requests resulted in an error
200
+ if (results.some(result => result.error)) {
201
+ setShowErrorModal(true);
202
+ return;
203
+ }
204
+
205
  setOutputs(results.map((result, index) => ({
206
  id: index + 1,
207
  code: result.code,
 
209
  })));
210
  } catch (error) {
211
  console.error("Error generating code:", error);
212
+ setShowErrorModal(true);
213
  } finally {
214
  setLoading(false);
215
  }
 
293
  </Head>
294
  <div className="h-screen max-h-screen bg-white flex items-center justify-center overflow-y-hidden tracking-[-0.005em]">
295
  <Header />
296
+ <ErrorModal
297
+ isOpen={showErrorModal}
298
+ onClose={() => setShowErrorModal(false)}
299
+ />
300
 
301
  <div className="w-full h-full max-h-full overflow-hidden bg-white">
302
  <div className={`flex flex-col md:flex-row gap-0 max-w-6xl mx-auto py-0 h-full transition-all duration-500 ${!hasStartedGenerating ? 'justify-center' : ''}`}>
 
430
  {loading ? (
431
  // Loading skeletons for code previews
432
  Array(concurrentRequests).fill().map((_, index) => (
433
+ <div key={`skeleton-preview-${Date.now()}-${index}`} className="mb-4 p-6 rounded-3xl bg-gray-100 animate-pulse">
434
  <div className="w-full h-[500px] bg-gray-200 rounded-lg mb-4" />
435
  <div className="flex justify-between items-center">
436
  <div className="h-10 w-32 bg-gray-200 rounded-full" />