apix/components/Settings.tsx
Khoa.vo 8741e3b89f
Some checks are pending
CI / build (18.x) (push) Waiting to run
CI / build (20.x) (push) Waiting to run
feat: Initial commit with multi-provider image generation
2026-01-05 13:50:35 +07:00

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 &gt; 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>
);
}