+
{uploadHistory.map((item) => (
-
-
-

+ {/* Column 1: Image Card */}
+
+
+
setZoomedImageUrl(item.url)}
+ role="button"
+ tabIndex={0}
+ aria-label="View full size image"
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ setZoomedImageUrl(item.url);
+ }
+ }}
+ >
+

+
+
+
+
+ {item.originalName}
+
+
+
+ {formatFileSize(item.size)}
+
+
+ {formatDuration(item.durationMs)}
+
+
+
+ {item.timestamp.toLocaleString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ })}
+
+
+
+
+
+
+ {/* Columns 2-3: API Code Examples Widget */}
+
+
-
-
- {item.originalName}
-
-
- {formatFileSize(item.size)}
- {formatDuration(item.durationMs)}
-
-
- {item.timestamp.toLocaleString('en-US', {
- month: 'short',
- day: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
- })}
-
-
-
- View Full Image
-
))}
)}
+
+ {/* Image Zoom Modal */}
+
setZoomedImageUrl(null)} />
);
}
diff --git a/apps/landing/src/components/demo/CodeExamplesWidget.tsx b/apps/landing/src/components/demo/CodeExamplesWidget.tsx
new file mode 100644
index 0000000..4461a32
--- /dev/null
+++ b/apps/landing/src/components/demo/CodeExamplesWidget.tsx
@@ -0,0 +1,95 @@
+'use client';
+
+import { useState } from 'react';
+
+type CodeTab = 'curl' | 'fetch' | 'rest';
+
+interface CodeExamplesWidgetProps {
+ codeExamples: {
+ curl: string;
+ fetch: string;
+ rest: string;
+ };
+ onCopy: (text: string) => void;
+ defaultTab?: CodeTab;
+}
+
+export const CodeExamplesWidget = ({
+ codeExamples,
+ onCopy,
+ defaultTab = 'curl',
+}: CodeExamplesWidgetProps) => {
+ const [activeTab, setActiveTab] = useState
(defaultTab);
+
+ const getCodeForTab = () => {
+ switch (activeTab) {
+ case 'curl':
+ return codeExamples.curl;
+ case 'fetch':
+ return codeExamples.fetch;
+ case 'rest':
+ return codeExamples.rest;
+ }
+ };
+
+ return (
+
+
+
+
+ setActiveTab('curl')}
+ label="cURL"
+ />
+ setActiveTab('fetch')}
+ label="JS Fetch"
+ />
+ setActiveTab('rest')}
+ label="REST"
+ />
+
+
+
+
+ {getCodeForTab()}
+
+
+ );
+};
+
+const TabButton = ({
+ active,
+ onClick,
+ label,
+}: {
+ active: boolean;
+ onClick: () => void;
+ label: string;
+}) => {
+ return (
+
+ );
+};
diff --git a/apps/landing/src/components/demo/ImageZoomModal.tsx b/apps/landing/src/components/demo/ImageZoomModal.tsx
new file mode 100644
index 0000000..791bd7f
--- /dev/null
+++ b/apps/landing/src/components/demo/ImageZoomModal.tsx
@@ -0,0 +1,52 @@
+'use client';
+
+import { useEffect } from 'react';
+
+interface ImageZoomModalProps {
+ imageUrl: string | null;
+ onClose: () => void;
+}
+
+export const ImageZoomModal = ({ imageUrl, onClose }: ImageZoomModalProps) => {
+ useEffect(() => {
+ const handleEscape = (e: KeyboardEvent) => {
+ if (e.key === 'Escape') {
+ onClose();
+ }
+ };
+
+ if (imageUrl) {
+ document.addEventListener('keydown', handleEscape);
+ }
+
+ return () => {
+ document.removeEventListener('keydown', handleEscape);
+ };
+ }, [imageUrl, onClose]);
+
+ if (!imageUrl) return null;
+
+ return (
+
+
+

e.stopPropagation()}
+ />
+
+ );
+};
diff --git a/apps/landing/src/components/demo/ResultCard.tsx b/apps/landing/src/components/demo/ResultCard.tsx
index 646b00d..7d6f059 100644
--- a/apps/landing/src/components/demo/ResultCard.tsx
+++ b/apps/landing/src/components/demo/ResultCard.tsx
@@ -4,6 +4,7 @@ import { useState } from 'react';
import { InspectMode } from './InspectMode';
import { PromptReuseButton } from './PromptReuseButton';
import { CompletedTimerBadge } from './GenerationTimer';
+import { CodeExamplesWidget } from './CodeExamplesWidget';
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
@@ -57,7 +58,6 @@ interface ResultCardProps {
}
type ViewMode = 'preview' | 'inspect';
-type CodeTab = 'curl' | 'fetch' | 'rest';
export function ResultCard({
result,
@@ -68,7 +68,6 @@ export function ResultCard({
onReusePrompt,
}: ResultCardProps) {
const [viewMode, setViewMode] = useState('preview');
- const [activeTab, setActiveTab] = useState('curl');
// Build enhancement options JSON for code examples
const buildEnhancementOptionsJson = () => {
@@ -165,15 +164,10 @@ X-API-Key: ${apiKey}
"filename": "generated_image"
}`;
- const getCodeForTab = () => {
- switch (activeTab) {
- case 'curl':
- return curlCode;
- case 'fetch':
- return fetchCode;
- case 'rest':
- return restCode;
- }
+ const codeExamples = {
+ curl: curlCode,
+ fetch: fetchCode,
+ rest: restCode,
};
return (
@@ -240,12 +234,7 @@ X-API-Key: ${apiKey}
{/* API Code Examples */}
-