diff --git a/.replit b/.replit index c806144..63699fb 100644 --- a/.replit +++ b/.replit @@ -40,3 +40,4 @@ args = "npm run dev" waitForPort = 5000 [agent] +integrations = ["javascript_openai==1.0.0"] diff --git a/client/src/pages/admin.tsx b/client/src/pages/admin.tsx index 5d34dd7..33a1564 100644 --- a/client/src/pages/admin.tsx +++ b/client/src/pages/admin.tsx @@ -13,7 +13,7 @@ import { useToast } from "@/hooks/use-toast"; import { LoadingSpinner } from "@/components/loading-spinner"; import { apiRequest } from "@/lib/queryClient"; import type { Video } from "@shared/schema"; -import { Shield, Edit, Upload, Search, Filter, Save, X } from "lucide-react"; +import { Shield, Edit, Upload, Search, Filter, Save, X, Sparkles, Loader2 } from "lucide-react"; export default function AdminPage() { const { user, isLoading: authLoading, isAuthenticated, isAdmin } = useAuth(); @@ -216,6 +216,7 @@ function EditVideoDialog({ genre: video.genre, customThumbnailUrl: video.customThumbnailUrl || "", }); + const [isGeneratingAI, setIsGeneratingAI] = useState(false); const updateMutation = useMutation({ mutationFn: (data: any) => apiRequest("PATCH", `/api/admin/videos/${video.id}`, data), @@ -240,6 +241,42 @@ function EditVideoDialog({ updateMutation.mutate(formData); }; + const generateAIDescription = async () => { + if (!formData.title.trim()) { + toast({ + title: "Error", + description: "Please enter a title first", + variant: "destructive", + }); + return; + } + + setIsGeneratingAI(true); + try { + const response = await apiRequest("POST", `/api/admin/videos/${video.id}/generate-description`, { + maxCharacters: 500, + includeArtistInfo: true, + includeLabelInfo: true + }); + + if (response.description) { + setFormData(prev => ({ ...prev, description: response.description })); + toast({ + title: "Success", + description: `AI description generated (${response.characterCount}/${response.maxCharacters} characters)`, + }); + } + } catch (error: any) { + toast({ + title: "Error", + description: error.message || "Failed to generate AI description", + variant: "destructive", + }); + } finally { + setIsGeneratingAI(false); + } + }; + return ( @@ -263,13 +300,34 @@ function EditVideoDialog({
- +
+ + +