[dyad] Improved form UX - wrote 1 file(s)
This commit is contained in:
@@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Globe, Edit, Check } from "lucide-react";
|
||||
import { Globe, Edit, Check, Loader2, X, ImageOff } from "lucide-react";
|
||||
import { extractMetaData } from "@/app/actions";
|
||||
import { LengthIndicator } from "./length-indicator";
|
||||
import { CopyButton } from "./copy-button";
|
||||
@@ -17,6 +17,7 @@ interface MetaData {
|
||||
}
|
||||
|
||||
export function MetaForm() {
|
||||
const [url, setUrl] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [metaData, setMetaData] = useState<MetaData | null>(null);
|
||||
@@ -26,11 +27,13 @@ export function MetaForm() {
|
||||
|
||||
const [editableTitle, setEditableTitle] = useState("");
|
||||
const [editableDescription, setEditableDescription] = useState("");
|
||||
const [imageError, setImageError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (metaData) {
|
||||
setEditableTitle(metaData.title);
|
||||
setEditableDescription(metaData.description);
|
||||
setImageError(false);
|
||||
}
|
||||
}, [metaData]);
|
||||
|
||||
@@ -41,9 +44,7 @@ export function MetaForm() {
|
||||
setMetaData(null);
|
||||
setIsEditingTitle(false);
|
||||
setIsEditingDescription(false);
|
||||
|
||||
const formData = new FormData(event.currentTarget);
|
||||
const url = formData.get("url") as string;
|
||||
setImageError(false);
|
||||
|
||||
const result = await extractMetaData(url);
|
||||
|
||||
@@ -56,6 +57,13 @@ export function MetaForm() {
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
setUrl("");
|
||||
setLoading(false);
|
||||
setError(null);
|
||||
setMetaData(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-6">
|
||||
<form
|
||||
@@ -70,15 +78,30 @@ export function MetaForm() {
|
||||
placeholder="https://example.com"
|
||||
required
|
||||
className="pl-10 h-12 text-base rounded-lg shadow-sm"
|
||||
value={url}
|
||||
onChange={(e) => setUrl(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="w-full sm:w-auto h-12 px-8 rounded-lg font-semibold transition-all"
|
||||
className="w-full sm:w-auto h-12 px-8 rounded-lg font-semibold transition-all flex items-center gap-2"
|
||||
>
|
||||
{loading && <Loader2 className="h-5 w-5 animate-spin" />}
|
||||
{loading ? "Extracting..." : "Extract"}
|
||||
</Button>
|
||||
{(url || metaData || error) && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleClear}
|
||||
className="h-12 w-12"
|
||||
>
|
||||
<X className="h-5 w-5" />
|
||||
<span className="sr-only">Clear</span>
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
|
||||
{error && (
|
||||
@@ -102,12 +125,20 @@ export function MetaForm() {
|
||||
<h3 className="font-semibold text-card-foreground mb-2">
|
||||
Preview Image
|
||||
</h3>
|
||||
<div className="aspect-video bg-muted rounded-md overflow-hidden relative">
|
||||
<img
|
||||
src={metaData.image}
|
||||
alt="Meta preview image"
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="aspect-video bg-muted rounded-md overflow-hidden relative flex items-center justify-center">
|
||||
{!imageError ? (
|
||||
<img
|
||||
src={metaData.image}
|
||||
alt="Meta preview image"
|
||||
className="w-full h-full object-cover"
|
||||
onError={() => setImageError(true)}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-2 text-muted-foreground">
|
||||
<ImageOff className="h-8 w-8" />
|
||||
<span>Image not available</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user