diff --git a/client/src/components/ai-chat.tsx b/client/src/components/ai-chat.tsx
index bb2d530..55320bd 100644
--- a/client/src/components/ai-chat.tsx
+++ b/client/src/components/ai-chat.tsx
@@ -6,7 +6,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { Bot, User, Lightbulb, History, Zap, Sparkles, Loader2 } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
+import { ModelCombobox } from "@/components/model-combobox";
interface Message {
role: "user" | "assistant";
@@ -114,32 +114,16 @@ export default function AiChat() {
-
+
diff --git a/client/src/components/model-combobox.tsx b/client/src/components/model-combobox.tsx
new file mode 100644
index 0000000..90f6de2
--- /dev/null
+++ b/client/src/components/model-combobox.tsx
@@ -0,0 +1,134 @@
+import { useState } from "react";
+import { Check, ChevronsUpDown, Loader2 } from "lucide-react";
+import { cn } from "@/lib/utils";
+import { Button } from "@/components/ui/button";
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@/components/ui/command";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+
+interface Model {
+ id: string;
+ name: string;
+ pricing?: {
+ prompt: string;
+ completion: string;
+ };
+}
+
+interface ModelComboboxProps {
+ models: Model[];
+ value: string;
+ onValueChange: (value: string) => void;
+ placeholder?: string;
+ isLoading?: boolean;
+ disabled?: boolean;
+ className?: string;
+ testId?: string;
+}
+
+export function ModelCombobox({
+ models,
+ value,
+ onValueChange,
+ placeholder = "Sélectionner un modèle",
+ isLoading = false,
+ disabled = false,
+ className,
+ testId,
+}: ModelComboboxProps) {
+ const [open, setOpen] = useState(false);
+ const [searchQuery, setSearchQuery] = useState("");
+
+ const selectedModel = models.find((model) => model.id === value);
+
+ const filteredModels = models.filter((model) =>
+ model.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ model.id.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+
+ return (
+
+
+
+
+
+
+
+
+ Aucun modèle trouvé.
+
+ {filteredModels.map((model) => (
+ {
+ onValueChange(currentValue);
+ setOpen(false);
+ setSearchQuery("");
+ }}
+ data-testid={`${testId}-option-${model.id}`}
+ >
+
+
+ {model.name}
+ {model.pricing && (
+
+ Prompt: ${model.pricing.prompt} | Completion: ${model.pricing.completion}
+
+ )}
+
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/client/src/pages/settings.tsx b/client/src/pages/settings.tsx
index 788aabb..e3bf3cb 100644
--- a/client/src/pages/settings.tsx
+++ b/client/src/pages/settings.tsx
@@ -8,10 +8,10 @@ import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { useToast } from "@/hooks/use-toast";
import { apiRequest, queryClient } from "@/lib/queryClient";
+import { ModelCombobox } from "@/components/model-combobox";
export default function Settings() {
const [sidebarOpen, setSidebarOpen] = useState(false);
@@ -33,7 +33,7 @@ export default function Settings() {
queryKey: ['/api/openrouter/config'],
});
- const { data: openrouterModels } = useQuery({
+ const { data: openrouterModels, isLoading: modelsLoading } = useQuery({
queryKey: ['/api/openrouter/models'],
});
@@ -227,18 +227,15 @@ export default function Settings() {
-
+
Choisissez le modèle d'IA pour générer vos publications