Skip to content

Commit a32e723

Browse files
author
Juan Castaño
committed
add download button
1 parent 6d048f2 commit a32e723

File tree

4 files changed

+195
-5
lines changed

4 files changed

+195
-5
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
import { Download, Loader2 } from 'lucide-react';
5+
import { Button } from '@/components/ui/button';
6+
import { benchifyFileSchema } from '@/lib/schemas';
7+
import { z } from 'zod';
8+
import JSZip from 'jszip';
9+
10+
interface DownloadButtonProps {
11+
files: z.infer<typeof benchifyFileSchema>;
12+
disabled?: boolean;
13+
className?: string;
14+
}
15+
16+
export function DownloadButton({ files, disabled = false, className }: DownloadButtonProps) {
17+
const [isDownloading, setIsDownloading] = useState(false);
18+
19+
const handleDownload = async () => {
20+
if (!files.length) return;
21+
22+
setIsDownloading(true);
23+
try {
24+
const zip = new JSZip();
25+
26+
// Add each file to the ZIP
27+
files.forEach(file => {
28+
zip.file(file.path, file.content);
29+
});
30+
31+
// Generate the ZIP file
32+
const content = await zip.generateAsync({ type: 'blob' });
33+
34+
// Create download link
35+
const url = URL.createObjectURL(content);
36+
const link = document.createElement('a');
37+
link.href = url;
38+
link.download = 'generated-ui-project.zip';
39+
document.body.appendChild(link);
40+
link.click();
41+
42+
// Cleanup
43+
document.body.removeChild(link);
44+
URL.revokeObjectURL(url);
45+
} catch (error) {
46+
console.error('Error creating download:', error);
47+
} finally {
48+
setIsDownloading(false);
49+
}
50+
};
51+
52+
if (!files.length) return null;
53+
54+
return (
55+
<Button
56+
onClick={handleDownload}
57+
disabled={disabled || isDownloading}
58+
variant="outline"
59+
size="sm"
60+
className={`flex items-center gap-2 ${className}`}
61+
>
62+
{isDownloading ? (
63+
<Loader2 className="h-4 w-4 animate-spin" />
64+
) : (
65+
<Download className="h-4 w-4" />
66+
)}
67+
{isDownloading ? 'Downloading...' : 'Download Project'}
68+
</Button>
69+
);
70+
}

components/ui-builder/preview-card.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
55
import { benchifyFileSchema } from "@/lib/schemas";
66
import { z } from "zod";
77
import { CodeEditor } from "./code-editor";
8+
import { DownloadButton } from "./download-button";
89

910
interface Step {
1011
id: string;
@@ -69,10 +70,17 @@ export function PreviewCard({ previewUrl, code, isGenerating = false, prompt }:
6970
return (
7071
<div className="h-full">
7172
<Tabs defaultValue="preview" className="w-full h-full flex flex-col">
72-
<TabsList className="mb-4 self-start">
73-
<TabsTrigger value="preview">Preview</TabsTrigger>
74-
<TabsTrigger value="code">Code</TabsTrigger>
75-
</TabsList>
73+
<div className="flex items-center justify-between mb-4">
74+
<TabsList>
75+
<TabsTrigger value="preview">Preview</TabsTrigger>
76+
<TabsTrigger value="code">Code</TabsTrigger>
77+
</TabsList>
78+
79+
<DownloadButton
80+
files={files}
81+
disabled={isGenerating}
82+
/>
83+
</div>
7684

7785
<TabsContent value="preview" className="flex-1 m-0">
7886
{isGenerating && prompt ? (

package-lock.json

Lines changed: 111 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"clsx": "^2.1.1",
2626
"diff": "^8.0.1",
2727
"e2b": "^1.5.0",
28+
"jszip": "^3.10.1",
2829
"lucide-react": "^0.510.0",
2930
"next": "15.3.2",
3031
"openai": "^4.98.0",
@@ -38,6 +39,7 @@
3839
"devDependencies": {
3940
"@eslint/eslintrc": "^3",
4041
"@tailwindcss/postcss": "^4",
42+
"@types/jszip": "^3.4.0",
4143
"@types/node": "^20",
4244
"@types/react": "^19",
4345
"@types/react-dom": "^19",

0 commit comments

Comments
 (0)