ui / src /webzero /preview.tsx
ZuhairAhmed's picture
dynamic renderer fix
312ace9
Raw
History Blame Contribute Delete
3.06 kB
import React, { Suspense, useState, useEffect } from "react";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
interface DynamicFileProps {
id: string;
}
const DynamicFileRenderer: React.FC<DynamicFileProps> = ({ id }) => {
const [DynamicComponent, setDynamicComponent] =
useState<React.ComponentType | null>(null);
const [error, setError] = useState(false);
const [loadingText, setLoadingText] = useState("Loading");
useEffect(() => {
let failed = false;
const loadComponent = async (canSetError: boolean) => {
try {
const Component = await import(`@/components/generated/${id}`);
setDynamicComponent(() => Component.default || Component);
setError(false);
} catch (error) {
failed = true;
if (canSetError) {
setDynamicComponent(() => null);
setError(true);
}
}
};
loadComponent(false);
setTimeout(() => {
failed && loadComponent(true);
}, 2000);
}, [id]);
useEffect(() => {
const interval = setInterval(() => {
setLoadingText((prev) => (prev.endsWith("...") ? "Loading" : prev + "."));
}, 500);
return () => clearInterval(interval);
}, []);
if (error) {
return (
<div className="flex flex-col items-center justify-center min-h-screen p-6 bg-background text-foreground">
<div className="max-w-md rounded-lg border p-4 bg-card text-card-foreground border-border">
<Alert variant="destructive">
<AlertTitle className="text-destructive-foreground">
Error Loading Component
</AlertTitle>
<AlertDescription className="text-muted-foreground">
We encountered an issue while loading the component. Please try
the following steps:
<ul className="list-disc list-inside mt-2 text-sm">
<li>Switch between the "Preview" and "Code" tabs.</li>
<li>If the issue persists, refresh the page.</li>
</ul>
</AlertDescription>
</Alert>
<div className="flex justify-center mt-4">
<Button
onClick={() => window.location.reload()}
variant="default"
style={{
backgroundColor: "hsl(var(--primary))",
color: "hsl(var(--primary-foreground))",
}}
>
Refresh Page
</Button>
</div>
</div>
</div>
);
}
if (!DynamicComponent) {
return (
<div className="flex items-center justify-center min-h-screen bg-background text-muted-foreground">
{loadingText}
</div>
);
}
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-screen bg-background text-muted-foreground">
{loadingText}
</div>
}
>
<DynamicComponent />
</Suspense>
);
};
export default DynamicFileRenderer;