Flower / app.py
sadsawq's picture
.env
bff31ec verified
raw
history blame
4.8 kB
// FLOWER AI Uygulaması - Grok klonu
// Framework: React + Tailwind + Hugging Face API
// Kod tam sayfa layout, model seçimi ve konuşma sistemi ile hazırlandı
import React, { useState, useEffect, useRef } from "react";
import { InferenceClient } from "@huggingface/inference";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { Mic, Paperclip, Sparkles, Brain } from "lucide-react";
import Editor from "@monaco-editor/react";
const client = new InferenceClient(process.env.NEXT_PUBLIC_HF_TOKEN);
const models = {
"Flower Chat": "openai/gpt-oss-20b",
"Flower Coder": "Qwen/Qwen3-Coder-30B-A3B-Instruct",
"Flower MULTI": "moonshotai/Kimi-K2-Instruct"
};
export default function FlowerApp() {
const [model, setModel] = useState("Flower Chat");
const [input, setInput] = useState("");
const [messages, setMessages] = useState([]);
const [thinking, setThinking] = useState(false);
const [codeOutput, setCodeOutput] = useState("");
const chatEndRef = useRef(null);
const sendMessage = async () => {
if (!input.trim()) return;
const userMessage = { role: "user", content: input };
setMessages((prev) => [...prev, userMessage]);
setInput("");
setThinking(true);
try {
const response = await client.chatCompletion({
provider: "auto",
model: models[model],
messages: [...messages, userMessage]
});
const reply = response.choices[0].message;
setMessages((prev) => [...prev, reply]);
if (model === "Flower Coder") setCodeOutput(reply.content);
} catch (err) {
setMessages((prev) => [...prev, { role: "system", content: "❌ Hata: " + err.message }]);
}
setThinking(false);
};
useEffect(() => {
chatEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
return (
<div className="flex h-screen w-screen overflow-hidden">
{/* Sidebar */}
<div className="w-[280px] bg-white flex flex-col justify-between p-4 border-r">
<div>
<Button className="w-full mb-4">+ Yeni Sohbet</Button>
{/* Geçmiş Sohbetler */}
</div>
<div className="flex flex-col gap-2">
<Button variant="ghost">🖼 Resmi Düzenle</Button>
<Button variant="ghost">📰 Son Dakika Haberleri</Button>
<Button variant="ghost">🎭 Kişilikler</Button>
</div>
</div>
{/* Ana Alan */}
<div className="flex-1 flex flex-col relative bg-gradient-to-b from-[--flower11] to-[--flower14]">
{/* Üst Logo */}
<div className="text-center text-4xl font-bold py-6">Flower</div>
{/* Mesajlar */}
<div className="flex-1 overflow-y-auto p-6 space-y-4">
{messages.map((msg, i) => (
<Card key={i} className={`p-4 w-fit ${msg.role === "user" ? "ml-auto bg-flower3" : "mr-auto bg-white"}`}>
{msg.content}
</Card>
))}
{thinking && (
<Card className="mr-auto bg-white p-4 animate-pulse">🤔 Düşünüyor...</Card>
)}
<div ref={chatEndRef} />
</div>
{/* Alt Giriş Alanı */}
<div className="p-4 border-t flex items-center gap-2">
<Paperclip className="w-5 h-5" />
<Button variant="outline" className="text-sm">DeepSearch</Button>
<Button variant="outline" className="text-sm">Think</Button>
<Textarea
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Ne bilmek istiyorsun?"
className="flex-1 resize-none h-[56px] rounded-full border px-4 py-2 text-[16px]"
/>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">{model} ▼</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
{Object.keys(models).map((m) => (
<DropdownMenuItem key={m} onSelect={() => setModel(m)}>
{model === m ? "●" : "○"} {m}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
<Mic className="w-5 h-5" />
</div>
</div>
{/* Sağ Kod Paneli */}
{model === "Flower Coder" && (
<div className="w-[400px] bg-white border-l p-4 overflow-y-auto">
<Editor
height="100%"
defaultLanguage="javascript"
defaultValue={codeOutput || "// Kod burada görüntülenecek..."}
theme="vs-light"
/>
</div>
)}
</div>
);
}