From 5bcc8330c268424e2d693cb64b6d24c96a6ea92a Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 12 Jul 2025 22:03:59 +0000 Subject: [PATCH 1/2] Enhance AI content generation with advanced tuning and history features Co-authored-by: pavanello.emanuele --- src/components/create-post-form.tsx | 377 ++++++++++++++++++++++++---- src/functions/ai.ts | 24 +- src/lib/server/ai-service.ts | 65 ++++- 3 files changed, 403 insertions(+), 63 deletions(-) diff --git a/src/components/create-post-form.tsx b/src/components/create-post-form.tsx index a0fbe9d..8a9b641 100644 --- a/src/components/create-post-form.tsx +++ b/src/components/create-post-form.tsx @@ -4,9 +4,11 @@ import { Label } from "@/components/ui/label" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Textarea } from "@/components/ui/textarea" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" +import { Checkbox } from "@/components/ui/checkbox" import { checkAiAccess, generateAiContent } from "@/functions/ai" import { useMutation, useQuery } from "@tanstack/react-query" -import { CalendarClock, Loader2, Lock, Rocket, Sparkles, X } from "lucide-react" +import { CalendarClock, Loader2, Lock, Rocket, Sparkles, X, RotateCcw, ChevronDown, ChevronUp } from "lucide-react" import { useState } from "react" import { toast } from "sonner" @@ -23,6 +25,25 @@ interface CreatePostFormProps { onValidationError: (message: string) => void } +interface GenerationHistory { + id: string + content: string + prompt: string + parameters: AiTuningParameters + timestamp: Date +} + +interface AiTuningParameters { + temperature?: number + maxTokens?: number + styleOverride?: string + toneOverride?: string + lengthOverride?: string + useEmojisOverride?: boolean + useHashtagsOverride?: boolean + customInstructionsOverride?: string +} + export function CreatePostForm({ selectedIntegrationId, currentIntegrationName, @@ -37,6 +58,17 @@ export function CreatePostForm({ const [isSchedulePopoverOpen, setIsSchedulePopoverOpen] = useState(false) const [aiPrompt, setAiPrompt] = useState("") const [showAiInput, setShowAiInput] = useState(false) + const [showAdvancedSettings, setShowAdvancedSettings] = useState(false) + const [showGenerationHistory, setShowGenerationHistory] = useState(false) + + // AI tuning parameters + const [aiParameters, setAiParameters] = useState({ + temperature: 0.7, + maxTokens: 150, + }) + + // Generation history + const [generationHistory, setGenerationHistory] = useState([]) // Always check AI access (for displaying appropriate messages) const { data: aiAccess, isLoading: isCheckingAiAccess } = useQuery({ @@ -51,9 +83,17 @@ export function CreatePostForm({ mutationFn: generateAiContent, onSuccess: (result) => { if (result.content) { + // Add to history + const historyEntry: GenerationHistory = { + id: Date.now().toString(), + content: result.content, + prompt: aiPrompt, + parameters: { ...aiParameters }, + timestamp: new Date() + } + setGenerationHistory(prev => [historyEntry, ...prev.slice(0, 9)]) // Keep last 10 + setContent(result.content) - setAiPrompt("") - setShowAiInput(false) toast.success("Content generated successfully!") } }, @@ -62,7 +102,7 @@ export function CreatePostForm({ } }) - const handleGenerateAiContent = () => { + const handleGenerateAiContent = (iterationInstruction?: string, previousContent?: string) => { if (!isAiAvailable) { onValidationError(aiUnavailableReason || "AI features are not available") return @@ -72,19 +112,51 @@ export function CreatePostForm({ onValidationError("Please select a platform first.") return } - if (!aiPrompt.trim()) { + if (!aiPrompt.trim() && !iterationInstruction) { onValidationError("Please enter a prompt for AI generation.") return } generateContent({ data: { - prompt: aiPrompt, - integrationId: selectedIntegrationId + prompt: iterationInstruction || aiPrompt, + integrationId: selectedIntegrationId, + temperature: aiParameters.temperature, + maxTokens: aiParameters.maxTokens, + styleOverride: aiParameters.styleOverride as "casual" | "formal" | "humorous" | "professional" | "conversational" | undefined, + toneOverride: aiParameters.toneOverride as "friendly" | "professional" | "authoritative" | "inspirational" | "educational" | undefined, + lengthOverride: aiParameters.lengthOverride as "short" | "medium" | "long" | undefined, + useEmojisOverride: aiParameters.useEmojisOverride, + useHashtagsOverride: aiParameters.useHashtagsOverride, + customInstructionsOverride: aiParameters.customInstructionsOverride, + previousContent, + iterationInstruction: iterationInstruction || undefined } }) } + const handleQuickAdjustment = (adjustment: string) => { + const adjustmentPrompts: Record = { + shorter: "Make this shorter and more concise", + longer: "Expand this with more details and examples", + formal: "Make this more formal and professional", + casual: "Make this more casual and conversational", + humor: "Add some humor and personality to this", + engaging: "Make this more engaging and attention-grabbing" + } + + if (content && adjustmentPrompts[adjustment]) { + handleGenerateAiContent(adjustmentPrompts[adjustment], content) + } + } + + const handleUseHistoryItem = (historyItem: GenerationHistory) => { + setContent(historyItem.content) + setAiPrompt(historyItem.prompt) + setAiParameters(historyItem.parameters) + setShowGenerationHistory(false) + } + const handlePublishNow = () => { if (!selectedIntegrationId) { onValidationError("Please select a platform.") @@ -132,15 +204,11 @@ export function CreatePostForm({ const handleClear = () => { setContent("") - setScheduledDateTime("") setAiPrompt("") - setShowAiInput(false) - setIsPublishPopoverOpen(false) - setIsSchedulePopoverOpen(false) + setScheduledDateTime("") onClear() } - // Calculate minimum datetime (current time + 5 minutes) const getMinDateTime = () => { const now = new Date() now.setMinutes(now.getMinutes() + 5) @@ -190,6 +258,141 @@ export function CreatePostForm({ ) } + const renderAdvancedSettings = () => ( +
+
+ + +
+ + {showAdvancedSettings && ( +
+
+
+ + setAiParameters(prev => ({ ...prev, temperature: Number(e.target.value) }))} + className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer" + /> +
+ Conservative + Creative +
+
+ +
+ + setAiParameters(prev => ({ ...prev, maxTokens: Number(e.target.value) }))} + className="w-full" + /> +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+ + +
+ +
+
+ setAiParameters(prev => ({ ...prev, useEmojisOverride: checked === true ? true : undefined }))} + /> + +
+ +
+ setAiParameters(prev => ({ ...prev, useHashtagsOverride: checked === true ? true : undefined }))} + /> + +
+
+ +
+ +