157 lines
7.9 KiB
TypeScript
157 lines
7.9 KiB
TypeScript
"use client";
|
|
|
|
import React from 'react';
|
|
import { useStore } from '@/lib/store';
|
|
import { Save, Sparkles, Zap, Brain } from 'lucide-react';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
type Provider = 'whisk' | 'grok' | 'meta';
|
|
|
|
const providers: { id: Provider; name: string; icon: any; description: string }[] = [
|
|
{ id: 'whisk', name: 'Google Whisk', icon: Sparkles, description: 'ImageFX / Imagen 3' },
|
|
{ id: 'grok', name: 'Grok (xAI)', icon: Zap, description: 'FLUX.1 model' },
|
|
{ id: 'meta', name: 'Meta AI', icon: Brain, description: 'Imagine / Emu' },
|
|
];
|
|
|
|
export function Settings() {
|
|
const { settings, setSettings } = useStore();
|
|
|
|
// Local state for form fields
|
|
const [provider, setProvider] = React.useState<Provider>(settings.provider || 'whisk');
|
|
const [whiskCookies, setWhiskCookies] = React.useState(settings.whiskCookies || '');
|
|
const [grokApiKey, setGrokApiKey] = React.useState(settings.grokApiKey || '');
|
|
const [grokCookies, setGrokCookies] = React.useState(settings.grokCookies || '');
|
|
const [metaCookies, setMetaCookies] = React.useState(settings.metaCookies || '');
|
|
const [saved, setSaved] = React.useState(false);
|
|
|
|
const handleSave = () => {
|
|
setSettings({
|
|
provider,
|
|
whiskCookies,
|
|
grokApiKey,
|
|
grokCookies,
|
|
metaCookies
|
|
});
|
|
setSaved(true);
|
|
setTimeout(() => setSaved(false), 2000);
|
|
};
|
|
|
|
return (
|
|
<div className="max-w-2xl mx-auto space-y-8 p-4 md:p-8">
|
|
<div>
|
|
<h2 className="text-2xl font-bold mb-2">Settings</h2>
|
|
<p className="text-muted-foreground">Configure your AI image generation provider.</p>
|
|
</div>
|
|
|
|
{/* Provider Selection */}
|
|
<div className="space-y-3">
|
|
<label className="text-sm font-medium">Image Generation Provider</label>
|
|
<div className="grid grid-cols-3 gap-3">
|
|
{providers.map((p) => (
|
|
<button
|
|
key={p.id}
|
|
onClick={() => setProvider(p.id)}
|
|
className={cn(
|
|
"flex flex-col items-center gap-2 p-4 rounded-xl border-2 transition-all",
|
|
provider === p.id
|
|
? "border-primary bg-primary/10"
|
|
: "border-border hover:border-primary/50 bg-card"
|
|
)}
|
|
>
|
|
<p.icon className={cn(
|
|
"h-6 w-6",
|
|
provider === p.id ? "text-primary" : "text-muted-foreground"
|
|
)} />
|
|
<span className={cn(
|
|
"font-medium text-sm",
|
|
provider === p.id ? "text-primary" : ""
|
|
)}>{p.name}</span>
|
|
<span className="text-xs text-muted-foreground">{p.description}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Provider-specific settings */}
|
|
<div className="space-y-4 p-4 rounded-xl bg-card border">
|
|
{provider === 'whisk' && (
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium">Google Whisk Cookies</label>
|
|
<textarea
|
|
value={whiskCookies}
|
|
onChange={(e) => setWhiskCookies(e.target.value)}
|
|
placeholder="Paste your cookies here..."
|
|
className="w-full h-32 p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-xs"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
Get these from <a href="https://labs.google/fx/tools/image-fx" target="_blank" className="underline hover:text-primary">ImageFX</a> DevTools (Application > Cookies).
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{provider === 'grok' && (
|
|
<div className="space-y-4">
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium">Grok API Key (Recommended)</label>
|
|
<input
|
|
type="password"
|
|
value={grokApiKey}
|
|
onChange={(e) => setGrokApiKey(e.target.value)}
|
|
placeholder="xai-..."
|
|
className="w-full p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-sm"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
Get your API key from <a href="https://console.x.ai" target="_blank" className="underline hover:text-primary">console.x.ai</a>
|
|
</p>
|
|
</div>
|
|
<div className="relative">
|
|
<div className="absolute inset-0 flex items-center">
|
|
<div className="w-full border-t border-border"></div>
|
|
</div>
|
|
<div className="relative flex justify-center text-xs">
|
|
<span className="bg-card px-2 text-muted-foreground">or use cookies</span>
|
|
</div>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium text-muted-foreground">Grok Cookies (Alternative)</label>
|
|
<textarea
|
|
value={grokCookies}
|
|
onChange={(e) => setGrokCookies(e.target.value)}
|
|
placeholder="Paste cookies from grok.com..."
|
|
className="w-full h-24 p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-xs"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
Get from logged-in <a href="https://grok.com" target="_blank" className="underline hover:text-primary">grok.com</a> session.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{provider === 'meta' && (
|
|
<div className="space-y-2">
|
|
<label className="text-sm font-medium">Meta AI Cookies</label>
|
|
<textarea
|
|
value={metaCookies}
|
|
onChange={(e) => setMetaCookies(e.target.value)}
|
|
placeholder="Paste cookies from meta.ai..."
|
|
className="w-full h-32 p-3 rounded-lg bg-secondary/50 border border-border focus:ring-2 focus:ring-primary/50 outline-none font-mono text-xs"
|
|
/>
|
|
<p className="text-xs text-muted-foreground">
|
|
Get from logged-in <a href="https://www.meta.ai" target="_blank" className="underline hover:text-primary">meta.ai</a> session (requires Facebook login).
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="pt-4">
|
|
<button
|
|
onClick={handleSave}
|
|
className="flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors"
|
|
>
|
|
<Save className="h-4 w-4" />
|
|
{saved ? "Saved!" : "Save Settings"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|