| 1 | "use client"; |
| 2 | |
| 3 | import { Clapperboard, Image, Wand2 } from "lucide-react"; |
| 4 | import { useSession } from "next-auth/react"; |
| 5 | |
| 6 | import { Label } from "@/components/ui/label"; |
| 7 | import { |
| 8 | Select, |
| 9 | SelectContent, |
| 10 | SelectGroup, |
| 11 | SelectItem, |
| 12 | SelectLabel, |
| 13 | SelectTrigger, |
| 14 | SelectValue, |
| 15 | } from "@/components/ui/select"; |
| 16 | import { |
| 17 | DEFAULT_IMAGE_MODEL, |
| 18 | getAvailableImageModels, |
| 19 | type ImageModelList, |
| 20 | } from "@/constants/image-models"; |
| 21 | import { type PresentationStockImageProvider } from "@/states/presentation-state"; |
| 22 | |
| 23 | interface ImageSourceSelectorProps { |
| 24 | imageSource: "automatic" | "ai" | "stock" | "gif"; |
| 25 | imageModel: ImageModelList; |
| 26 | stockImageProvider: PresentationStockImageProvider; |
| 27 | onImageSourceChange: (source: "automatic" | "ai" | "stock" | "gif") => void; |
| 28 | onImageModelChange: (model: ImageModelList) => void; |
| 29 | onStockImageProviderChange: ( |
| 30 | provider: PresentationStockImageProvider, |
| 31 | ) => void; |
| 32 | className?: string; |
| 33 | showLabel?: boolean; |
| 34 | } |
| 35 | |
| 36 | export function ImageSourceSelector({ |
| 37 | imageSource, |
| 38 | imageModel, |
| 39 | stockImageProvider, |
| 40 | onImageSourceChange, |
| 41 | onImageModelChange, |
| 42 | onStockImageProviderChange, |
| 43 | className, |
| 44 | showLabel = true, |
| 45 | }: ImageSourceSelectorProps) { |
| 46 | const { data: session } = useSession(); |
| 47 | const imageModels = getAvailableImageModels(session?.user?.isAdmin === true); |
| 48 | |
| 49 | return ( |
| 50 | <div className={className}> |
| 51 | {showLabel && ( |
| 52 | <Label className="mb-2 block text-sm font-medium">Image Source</Label> |
| 53 | )} |
| 54 | <Select |
| 55 | value={ |
| 56 | imageSource === "ai" |
| 57 | ? imageModel || DEFAULT_IMAGE_MODEL |
| 58 | : imageSource === "stock" |
| 59 | ? `stock-${stockImageProvider}` |
| 60 | : imageSource === "gif" |
| 61 | ? "gif" |
| 62 | : "automatic" |
| 63 | } |
| 64 | onValueChange={(value) => { |
| 65 | if (value === "automatic") { |
| 66 | onImageSourceChange("automatic"); |
| 67 | } else if (value === "gif") { |
| 68 | onImageSourceChange("gif"); |
| 69 | } else if (value.startsWith("stock-")) { |
| 70 | // Handle stock image selection |
| 71 | const provider = value.replace( |
| 72 | "stock-", |
| 73 | "", |
| 74 | ) as PresentationStockImageProvider; |
| 75 | onImageSourceChange("stock"); |
| 76 | onStockImageProviderChange(provider); |
| 77 | } else { |
| 78 | // Handle AI model selection |
| 79 | onImageSourceChange("ai"); |
| 80 | onImageModelChange(value as ImageModelList); |
| 81 | } |
| 82 | }} |
| 83 | > |
| 84 | <SelectTrigger> |
| 85 | <SelectValue placeholder="Select image generation method" /> |
| 86 | </SelectTrigger> |
| 87 | <SelectContent> |
| 88 | <SelectGroup> |
| 89 | <SelectItem value="automatic" className="font-medium"> |
| 90 | Automatic |
| 91 | </SelectItem> |
| 92 | </SelectGroup> |
| 93 | <SelectGroup> |
| 94 | <SelectLabel className="flex items-center gap-1 text-primary/80"> |
| 95 | <Wand2 size={10} /> |
| 96 | AI Generation |
| 97 | </SelectLabel> |
| 98 | {imageModels.map((model) => ( |
| 99 | <SelectItem key={model.value} value={model.value}> |
| 100 | {model.label} |
| 101 | </SelectItem> |
| 102 | ))} |
| 103 | </SelectGroup> |
| 104 | <SelectGroup> |
| 105 | <SelectLabel className="flex items-center gap-1 text-primary/80"> |
| 106 | <Image size={10} /> |
| 107 | Stock & Web Images |
| 108 | </SelectLabel> |
| 109 | <SelectItem value="stock-unsplash">Unsplash</SelectItem> |
| 110 | <SelectItem value="stock-pixabay">Pixabay</SelectItem> |
| 111 | <SelectItem value="stock-google">Web Search</SelectItem> |
| 112 | </SelectGroup> |
| 113 | <SelectGroup> |
| 114 | <SelectLabel className="flex items-center gap-1 text-primary/80"> |
| 115 | <Clapperboard size={10} /> |
| 116 | Animated |
| 117 | </SelectLabel> |
| 118 | <SelectItem value="gif">GIFs from Giphy</SelectItem> |
| 119 | </SelectGroup> |
| 120 | </SelectContent> |
| 121 | </Select> |
| 122 | </div> |
| 123 | ); |
| 124 | } |
| 125 |