Spaces:
Build error
Build error
File size: 5,835 Bytes
75fefa7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
"use client";
import { useState } from "react";
import Link from "next/link";
import { appConfig } from "@/config/app.config";
interface SidebarInputProps {
onSubmit: (url: string, style: string, model: string, instructions?: string) => void;
disabled?: boolean;
}
export default function SidebarInput({ onSubmit, disabled = false }: SidebarInputProps) {
const [url, setUrl] = useState<string>("");
const [selectedStyle, setSelectedStyle] = useState<string>("1");
const [selectedModel, setSelectedModel] = useState<string>(appConfig.ai.defaultModel);
const [additionalInstructions, setAdditionalInstructions] = useState<string>("");
const [isValidUrl, setIsValidUrl] = useState<boolean>(false);
// Simple URL validation - currently unused but keeping for future use
// const validateUrl = (urlString: string) => {
// if (!urlString) return false;
// const urlPattern = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
// return urlPattern.test(urlString.toLowerCase());
// };
const styles = [
{ id: "1", name: "Glassmorphism", description: "Frosted glass effect" },
{ id: "2", name: "Neumorphism", description: "Soft 3D shadows" },
{ id: "3", name: "Brutalism", description: "Bold and raw" },
{ id: "4", name: "Minimalist", description: "Clean and simple" },
{ id: "5", name: "Dark Mode", description: "Dark theme design" },
{ id: "6", name: "Gradient Rich", description: "Vibrant gradients" },
{ id: "7", name: "3D Depth", description: "Dimensional layers" },
{ id: "8", name: "Retro Wave", description: "80s inspired" },
];
const models = appConfig.ai.availableModels.map(model => ({
id: model,
name: appConfig.ai.modelDisplayNames[model] || model,
}));
const handleSubmit = (e?: React.FormEvent) => {
if (e) e.preventDefault();
if (!url.trim() || disabled) return;
onSubmit(url.trim(), selectedStyle, selectedModel, additionalInstructions || undefined);
// Reset form
setUrl("");
setAdditionalInstructions("");
setIsValidUrl(false);
};
return (
<div className="w-full">
<div >
<div className="p-4 border-b border-gray-100">
{/* link to home page with button */}
<Link href="/">
<button className="w-full px-3 py-2 text-xs font-medium text-gray-700 bg-white rounded border border-gray-200 focus:border-orange-500 focus:outline-none focus:ring-1 focus:ring-orange-500">
Generate a new website
</button>
</Link>
</div>
{/* Options Section - Show when valid URL */}
{isValidUrl && (
<div className="p-4 space-y-4">
{/* Style Selector */}
<div>
<label className="block text-xs font-medium text-gray-700 mb-2">Style</label>
<div className="grid grid-cols-2 gap-1.5">
{styles.map((style) => (
<button
key={style.id}
onClick={() => setSelectedStyle(style.id)}
disabled={disabled}
className={`
py-2 px-2 rounded text-xs font-medium border transition-all text-center
${selectedStyle === style.id
? 'border-orange-500 bg-orange-50 text-orange-900'
: 'border-gray-200 hover:border-gray-300 bg-white text-gray-700'
}
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
`}
>
{style.name}
</button>
))}
</div>
</div>
{/* Model Selector */}
<div>
<label className="block text-xs font-medium text-gray-700 mb-2">AI Model</label>
<select
value={selectedModel}
onChange={(e) => setSelectedModel(e.target.value)}
disabled={disabled}
className="w-full px-3 py-2 text-xs font-medium text-gray-700 bg-white rounded border border-gray-200 focus:border-orange-500 focus:outline-none focus:ring-1 focus:ring-orange-500"
>
{models.map((model) => (
<option key={model.id} value={model.id}>
{model.name}
</option>
))}
</select>
</div>
{/* Additional Instructions */}
<div>
<label className="block text-xs font-medium text-gray-700 mb-2">Additional Instructions (optional)</label>
<input
type="text"
value={additionalInstructions}
onChange={(e) => setAdditionalInstructions(e.target.value)}
disabled={disabled}
className="w-full px-3 py-2 text-xs text-gray-700 bg-gray-50 rounded border border-gray-200 focus:border-orange-500 focus:outline-none focus:ring-1 focus:ring-orange-500 placeholder:text-gray-400"
placeholder="e.g., make it more colorful, add animations..."
/>
</div>
{/* Submit Button */}
<div className="pt-2">
<button
onClick={handleSubmit}
disabled={!isValidUrl || disabled}
className={`
w-full py-2.5 px-4 rounded-lg text-sm font-medium transition-all
${isValidUrl && !disabled
? 'bg-orange-500 hover:bg-orange-600 text-white'
: 'bg-gray-200 text-gray-400 cursor-not-allowed'
}
`}
>
{disabled ? 'Scraping...' : 'Scrape Site'}
</button>
</div>
</div>
)}
</div>
</div>
);
} |