fix(i18n): Fix syntax errors and add missing translation keys - Restored broken useStore destructuring in PromptEnhancer, UXDesignerPrompt, ActionPlanGenerator, SlidesGenerator - Fixed GoogleAdsGenerator scope issue with renderMagicWandSectionContent - Added missing inputLabel keys to promptEnhancer for all languages - Fixed t.resultTitle to t.enhancedTitle in PromptEnhancer
This commit is contained in:
@@ -11,7 +11,16 @@ import { cn } from "@/lib/utils";
|
|||||||
import { translations } from "@/lib/i18n/translations";
|
import { translations } from "@/lib/i18n/translations";
|
||||||
|
|
||||||
export default function ActionPlanGenerator() {
|
export default function ActionPlanGenerator() {
|
||||||
|
const {
|
||||||
language,
|
language,
|
||||||
|
currentPrompt,
|
||||||
|
actionPlan,
|
||||||
|
selectedProvider,
|
||||||
|
selectedModels,
|
||||||
|
availableModels,
|
||||||
|
apiKeys,
|
||||||
|
isProcessing,
|
||||||
|
error,
|
||||||
setCurrentPrompt,
|
setCurrentPrompt,
|
||||||
setSelectedProvider,
|
setSelectedProvider,
|
||||||
setActionPlan,
|
setActionPlan,
|
||||||
@@ -21,15 +30,15 @@ export default function ActionPlanGenerator() {
|
|||||||
setSelectedModel,
|
setSelectedModel,
|
||||||
} = useStore();
|
} = useStore();
|
||||||
|
|
||||||
const t = translations[language].actionPlan;
|
const t = translations[language].actionPlan;
|
||||||
const common = translations[language].common;
|
const common = translations[language].common;
|
||||||
|
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
const selectedModel = selectedModels[selectedProvider];
|
const selectedModel = selectedModels[selectedProvider];
|
||||||
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
loadAvailableModels();
|
loadAvailableModels();
|
||||||
const saved = localStorage.getItem("promptarch-api-keys");
|
const saved = localStorage.getItem("promptarch-api-keys");
|
||||||
@@ -44,9 +53,9 @@ useEffect(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedProvider]);
|
}, [selectedProvider]);
|
||||||
|
|
||||||
const loadAvailableModels = async () => {
|
const loadAvailableModels = async () => {
|
||||||
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
||||||
setAvailableModels(selectedProvider, fallbackModels);
|
setAvailableModels(selectedProvider, fallbackModels);
|
||||||
|
|
||||||
@@ -58,9 +67,9 @@ const loadAvailableModels = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load models:", error);
|
console.error("Failed to load models:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGenerate = async () => {
|
const handleGenerate = async () => {
|
||||||
if (!currentPrompt.trim()) {
|
if (!currentPrompt.trim()) {
|
||||||
setError("Please enter PRD or project requirements");
|
setError("Please enter PRD or project requirements");
|
||||||
return;
|
return;
|
||||||
@@ -111,17 +120,17 @@ const handleGenerate = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
if (actionPlan?.rawContent) {
|
if (actionPlan?.rawContent) {
|
||||||
await navigator.clipboard.writeText(actionPlan.rawContent);
|
await navigator.clipboard.writeText(actionPlan.rawContent);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setTimeout(() => setCopied(false), 2000);
|
setTimeout(() => setCopied(false), 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2 text-start">
|
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2 text-start">
|
||||||
<Card className="h-fit">
|
<Card className="h-fit">
|
||||||
<CardHeader className="p-4 lg:p-6 text-start">
|
<CardHeader className="p-4 lg:p-6 text-start">
|
||||||
@@ -257,5 +266,5 @@ return (
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,10 +394,9 @@ export default function GoogleAdsGenerator() {
|
|||||||
default:
|
default:
|
||||||
return <pre className="whitespace-pre-wrap text-xs">{googleAdsResult.rawContent}</pre>;
|
return <pre className="whitespace-pre-wrap text-xs">{googleAdsResult.rawContent}</pre>;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const renderMagicWandSectionContent = (sectionId: string) => {
|
const renderMagicWandSectionContent = (sectionId: string) => {
|
||||||
if (!magicWandResult) return null;
|
if (!magicWandResult) return null;
|
||||||
|
|
||||||
switch (sectionId) {
|
switch (sectionId) {
|
||||||
@@ -546,10 +545,10 @@ const renderMagicWandSectionContent = (sectionId: string) => {
|
|||||||
default:
|
default:
|
||||||
return <pre className="whitespace-pre-wrap text-xs">{magicWandResult.rawContent}</pre>;
|
return <pre className="whitespace-pre-wrap text-xs">{magicWandResult.rawContent}</pre>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2">
|
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2">
|
||||||
<Card className="h-fit">
|
<Card className="h-fit">
|
||||||
<CardHeader className="p-4 lg:p-6 text-start">
|
<CardHeader className="p-4 lg:p-6 text-start">
|
||||||
@@ -797,5 +796,5 @@ return (
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,16 @@ import { cn } from "@/lib/utils";
|
|||||||
import { translations } from "@/lib/i18n/translations";
|
import { translations } from "@/lib/i18n/translations";
|
||||||
|
|
||||||
export default function PromptEnhancer() {
|
export default function PromptEnhancer() {
|
||||||
|
const {
|
||||||
language,
|
language,
|
||||||
|
currentPrompt,
|
||||||
|
enhancedPrompt,
|
||||||
|
selectedProvider,
|
||||||
|
selectedModels,
|
||||||
|
availableModels,
|
||||||
|
apiKeys,
|
||||||
|
isProcessing,
|
||||||
|
error,
|
||||||
setSelectedProvider,
|
setSelectedProvider,
|
||||||
setCurrentPrompt,
|
setCurrentPrompt,
|
||||||
setEnhancedPrompt,
|
setEnhancedPrompt,
|
||||||
@@ -21,15 +30,15 @@ export default function PromptEnhancer() {
|
|||||||
setSelectedModel,
|
setSelectedModel,
|
||||||
} = useStore();
|
} = useStore();
|
||||||
|
|
||||||
const t = translations[language].promptEnhancer;
|
const t = translations[language].promptEnhancer;
|
||||||
const common = translations[language].common;
|
const common = translations[language].common;
|
||||||
|
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
const selectedModel = selectedModels[selectedProvider];
|
const selectedModel = selectedModels[selectedProvider];
|
||||||
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
loadAvailableModels();
|
loadAvailableModels();
|
||||||
const saved = localStorage.getItem("promptarch-api-keys");
|
const saved = localStorage.getItem("promptarch-api-keys");
|
||||||
@@ -44,9 +53,9 @@ useEffect(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedProvider]);
|
}, [selectedProvider]);
|
||||||
|
|
||||||
const loadAvailableModels = async () => {
|
const loadAvailableModels = async () => {
|
||||||
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
||||||
setAvailableModels(selectedProvider, fallbackModels);
|
setAvailableModels(selectedProvider, fallbackModels);
|
||||||
|
|
||||||
@@ -58,9 +67,9 @@ const loadAvailableModels = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load models:", error);
|
console.error("Failed to load models:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEnhance = async () => {
|
const handleEnhance = async () => {
|
||||||
if (!currentPrompt.trim()) {
|
if (!currentPrompt.trim()) {
|
||||||
setError("Please enter a prompt to enhance");
|
setError("Please enter a prompt to enhance");
|
||||||
return;
|
return;
|
||||||
@@ -96,23 +105,23 @@ const handleEnhance = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
if (enhancedPrompt) {
|
if (enhancedPrompt) {
|
||||||
await navigator.clipboard.writeText(enhancedPrompt);
|
await navigator.clipboard.writeText(enhancedPrompt);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setTimeout(() => setCopied(false), 2000);
|
setTimeout(() => setCopied(false), 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
setCurrentPrompt("");
|
setCurrentPrompt("");
|
||||||
setEnhancedPrompt(null);
|
setEnhancedPrompt(null);
|
||||||
setError(null);
|
setError(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2 text-start">
|
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2 text-start">
|
||||||
<Card className="h-fit">
|
<Card className="h-fit">
|
||||||
<CardHeader className="p-4 lg:p-6 text-start">
|
<CardHeader className="p-4 lg:p-6 text-start">
|
||||||
@@ -209,7 +218,7 @@ return (
|
|||||||
<CardTitle className="flex items-center justify-between text-base lg:text-lg">
|
<CardTitle className="flex items-center justify-between text-base lg:text-lg">
|
||||||
<span className="flex items-center gap-2">
|
<span className="flex items-center gap-2">
|
||||||
<CheckCircle2 className="h-4 w-4 lg:h-5 lg:w-5 text-green-500" />
|
<CheckCircle2 className="h-4 w-4 lg:h-5 lg:w-5 text-green-500" />
|
||||||
{t.resultTitle}
|
{t.enhancedTitle}
|
||||||
</span>
|
</span>
|
||||||
{enhancedPrompt && (
|
{enhancedPrompt && (
|
||||||
<Button variant="ghost" size="icon" onClick={handleCopy} className="h-8 w-8 lg:h-9 lg:w-9">
|
<Button variant="ghost" size="icon" onClick={handleCopy} className="h-8 w-8 lg:h-9 lg:w-9">
|
||||||
@@ -238,5 +247,5 @@ return (
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,36 +108,49 @@ const ACCEPTED_FILE_TYPES = {
|
|||||||
const ALL_ACCEPTED = Object.values(ACCEPTED_FILE_TYPES).flat().join(",");
|
const ALL_ACCEPTED = Object.values(ACCEPTED_FILE_TYPES).flat().join(",");
|
||||||
|
|
||||||
export default function SlidesGenerator() {
|
export default function SlidesGenerator() {
|
||||||
|
const {
|
||||||
|
selectedProvider,
|
||||||
|
selectedModels,
|
||||||
|
availableModels,
|
||||||
|
apiKeys,
|
||||||
|
isProcessing,
|
||||||
|
error,
|
||||||
|
slidesPresentation,
|
||||||
|
setSelectedProvider,
|
||||||
|
setSlidesPresentation,
|
||||||
|
setProcessing,
|
||||||
|
setError,
|
||||||
|
setAvailableModels,
|
||||||
setSelectedModel,
|
setSelectedModel,
|
||||||
language: uiLanguage,
|
language: uiLanguage,
|
||||||
} = useStore();
|
} = useStore();
|
||||||
|
|
||||||
const t = translations[uiLanguage].slidesGen;
|
const t = translations[uiLanguage].slidesGen;
|
||||||
const common = translations[uiLanguage].common;
|
const common = translations[uiLanguage].common;
|
||||||
|
|
||||||
const [topic, setTopic] = useState("");
|
const [topic, setTopic] = useState("");
|
||||||
const [language, setLanguage] = useState("en");
|
const [language, setLanguage] = useState("en");
|
||||||
const [theme, setTheme] = useState("executive-dark");
|
const [theme, setTheme] = useState("executive-dark");
|
||||||
const [audience, setAudience] = useState("executives");
|
const [audience, setAudience] = useState("executives");
|
||||||
const [organization, setOrganization] = useState("");
|
const [organization, setOrganization] = useState("");
|
||||||
const [slideCount, setSlideCount] = useState(10);
|
const [slideCount, setSlideCount] = useState(10);
|
||||||
const [animationStyle, setAnimationStyle] = useState("professional");
|
const [animationStyle, setAnimationStyle] = useState("professional");
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const [currentSlide, setCurrentSlide] = useState(0);
|
const [currentSlide, setCurrentSlide] = useState(0);
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
const [isAutoPlaying, setIsAutoPlaying] = useState(false);
|
const [isAutoPlaying, setIsAutoPlaying] = useState(false);
|
||||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||||
const [attachedFiles, setAttachedFiles] = useState<AttachedFile[]>([]);
|
const [attachedFiles, setAttachedFiles] = useState<AttachedFile[]>([]);
|
||||||
const [isDragOver, setIsDragOver] = useState(false);
|
const [isDragOver, setIsDragOver] = useState(false);
|
||||||
const [uploadProgress, setUploadProgress] = useState<string | null>(null);
|
const [uploadProgress, setUploadProgress] = useState<string | null>(null);
|
||||||
const slideContainerRef = useRef<HTMLDivElement>(null);
|
const slideContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const autoPlayRef = useRef<NodeJS.Timeout | null>(null);
|
const autoPlayRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const selectedModel = selectedModels[selectedProvider];
|
const selectedModel = selectedModels[selectedProvider];
|
||||||
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
loadAvailableModels();
|
loadAvailableModels();
|
||||||
const saved = localStorage.getItem("promptarch-api-keys");
|
const saved = localStorage.getItem("promptarch-api-keys");
|
||||||
@@ -152,9 +165,9 @@ useEffect(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedProvider]);
|
}, [selectedProvider]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAutoPlaying && slidesPresentation?.slides) {
|
if (isAutoPlaying && slidesPresentation?.slides) {
|
||||||
autoPlayRef.current = setInterval(() => {
|
autoPlayRef.current = setInterval(() => {
|
||||||
setCurrentSlide((prev) =>
|
setCurrentSlide((prev) =>
|
||||||
@@ -167,9 +180,9 @@ useEffect(() => {
|
|||||||
clearInterval(autoPlayRef.current);
|
clearInterval(autoPlayRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [isAutoPlaying, slidesPresentation?.slides?.length]);
|
}, [isAutoPlaying, slidesPresentation?.slides?.length]);
|
||||||
|
|
||||||
const loadAvailableModels = async () => {
|
const loadAvailableModels = async () => {
|
||||||
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
||||||
setAvailableModels(selectedProvider, fallbackModels);
|
setAvailableModels(selectedProvider, fallbackModels);
|
||||||
|
|
||||||
@@ -181,10 +194,10 @@ const loadAvailableModels = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load models:", error);
|
console.error("Failed to load models:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract colors from image
|
// Extract colors from image
|
||||||
const extractColorsFromImage = (file: File): Promise<string[]> => {
|
const extractColorsFromImage = (file: File): Promise<string[]> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const img = document.createElement("img");
|
const img = document.createElement("img");
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
@@ -221,10 +234,10 @@ const extractColorsFromImage = (file: File): Promise<string[]> => {
|
|||||||
|
|
||||||
img.src = URL.createObjectURL(file);
|
img.src = URL.createObjectURL(file);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Process uploaded file
|
// Process uploaded file
|
||||||
const processFile = async (file: File): Promise<AttachedFile | null> => {
|
const processFile = async (file: File): Promise<AttachedFile | null> => {
|
||||||
const id = Math.random().toString(36).substr(2, 9);
|
const id = Math.random().toString(36).substr(2, 9);
|
||||||
const ext = file.name.split(".").pop()?.toLowerCase() || "";
|
const ext = file.name.split(".").pop()?.toLowerCase() || "";
|
||||||
|
|
||||||
@@ -276,17 +289,17 @@ const processFile = async (file: File): Promise<AttachedFile | null> => {
|
|||||||
console.error("Error processing file:", err);
|
console.error("Error processing file:", err);
|
||||||
return attachedFile;
|
return attachedFile;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileDrop = useCallback(async (e: React.DragEvent) => {
|
const handleFileDrop = useCallback(async (e: React.DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsDragOver(false);
|
setIsDragOver(false);
|
||||||
|
|
||||||
const files = Array.from(e.dataTransfer.files);
|
const files = Array.from(e.dataTransfer.files);
|
||||||
await handleFileUpload(files);
|
await handleFileUpload(files);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleFileUpload = async (files: File[]) => {
|
const handleFileUpload = async (files: File[]) => {
|
||||||
setUploadProgress("Processing files...");
|
setUploadProgress("Processing files...");
|
||||||
|
|
||||||
const newFiles: AttachedFile[] = [];
|
const newFiles: AttachedFile[] = [];
|
||||||
@@ -300,9 +313,9 @@ const handleFileUpload = async (files: File[]) => {
|
|||||||
|
|
||||||
setAttachedFiles(prev => [...prev, ...newFiles]);
|
setAttachedFiles(prev => [...prev, ...newFiles]);
|
||||||
setUploadProgress(null);
|
setUploadProgress(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeFile = (id: string) => {
|
const removeFile = (id: string) => {
|
||||||
setAttachedFiles(prev => {
|
setAttachedFiles(prev => {
|
||||||
const file = prev.find(f => f.id === id);
|
const file = prev.find(f => f.id === id);
|
||||||
if (file?.preview) {
|
if (file?.preview) {
|
||||||
@@ -310,16 +323,16 @@ const removeFile = (id: string) => {
|
|||||||
}
|
}
|
||||||
return prev.filter(f => f.id !== id);
|
return prev.filter(f => f.id !== id);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFileIcon = (type: string, name: string) => {
|
const getFileIcon = (type: string, name: string) => {
|
||||||
if (name.match(/\.(png|jpg|jpeg|svg|webp|gif)$/i)) return <ImageIcon className="h-4 w-4" />;
|
if (name.match(/\.(png|jpg|jpeg|svg|webp|gif)$/i)) return <ImageIcon className="h-4 w-4" />;
|
||||||
if (name.match(/\.(pdf|doc|docx|txt|md)$/i)) return <FileText className="h-4 w-4" />;
|
if (name.match(/\.(pdf|doc|docx|txt|md)$/i)) return <FileText className="h-4 w-4" />;
|
||||||
if (name.match(/\.(pptx|ppt|key)$/i)) return <Presentation className="h-4 w-4" />;
|
if (name.match(/\.(pptx|ppt|key)$/i)) return <Presentation className="h-4 w-4" />;
|
||||||
return <File className="h-4 w-4" />;
|
return <File className="h-4 w-4" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildFileContext = (): string => {
|
const buildFileContext = (): string => {
|
||||||
if (attachedFiles.length === 0) return "";
|
if (attachedFiles.length === 0) return "";
|
||||||
|
|
||||||
let context = "\n\n## ATTACHED FILES CONTEXT:\n";
|
let context = "\n\n## ATTACHED FILES CONTEXT:\n";
|
||||||
@@ -342,9 +355,9 @@ const buildFileContext = (): string => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseSlides = (content: string): SlidesPresentation | null => {
|
const parseSlides = (content: string): SlidesPresentation | null => {
|
||||||
try {
|
try {
|
||||||
const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
|
const jsonMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
|
||||||
const jsonStr = jsonMatch ? jsonMatch[1].trim() : content.trim();
|
const jsonStr = jsonMatch ? jsonMatch[1].trim() : content.trim();
|
||||||
@@ -377,9 +390,9 @@ const parseSlides = (content: string): SlidesPresentation | null => {
|
|||||||
console.error("Failed to parse slides:", e);
|
console.error("Failed to parse slides:", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateAnimatedHtml = (slide: any, index: number): string => {
|
const generateAnimatedHtml = (slide: any, index: number): string => {
|
||||||
const themeConfig = THEMES.find(t => t.id === theme) || THEMES[1];
|
const themeConfig = THEMES.find(t => t.id === theme) || THEMES[1];
|
||||||
const [bg, accent, secondary, text] = themeConfig.colors;
|
const [bg, accent, secondary, text] = themeConfig.colors;
|
||||||
const gradient = themeConfig.gradient;
|
const gradient = themeConfig.gradient;
|
||||||
@@ -476,9 +489,9 @@ const generateAnimatedHtml = (slide: any, index: number): string => {
|
|||||||
</style>
|
</style>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGenerate = async () => {
|
const handleGenerate = async () => {
|
||||||
if (!topic.trim()) {
|
if (!topic.trim()) {
|
||||||
setError("Please enter a topic for your presentation");
|
setError("Please enter a topic for your presentation");
|
||||||
return;
|
return;
|
||||||
@@ -574,17 +587,17 @@ const handleGenerate = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
if (slidesPresentation?.rawContent) {
|
if (slidesPresentation?.rawContent) {
|
||||||
await navigator.clipboard.writeText(slidesPresentation.rawContent);
|
await navigator.clipboard.writeText(slidesPresentation.rawContent);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setTimeout(() => setCopied(false), 2000);
|
setTimeout(() => setCopied(false), 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDownloadHtml = () => {
|
const handleDownloadHtml = () => {
|
||||||
if (!slidesPresentation) return;
|
if (!slidesPresentation) return;
|
||||||
|
|
||||||
const themeConfig = THEMES.find(t => t.id === slidesPresentation.theme) || THEMES[1];
|
const themeConfig = THEMES.find(t => t.id === slidesPresentation.theme) || THEMES[1];
|
||||||
@@ -786,9 +799,9 @@ const handleDownloadHtml = () => {
|
|||||||
a.download = `${slidesPresentation.title.replace(/[^a-z0-9]/gi, '_')}_animated_presentation.html`;
|
a.download = `${slidesPresentation.title.replace(/[^a-z0-9]/gi, '_')}_animated_presentation.html`;
|
||||||
a.click();
|
a.click();
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleFullscreen = () => {
|
const toggleFullscreen = () => {
|
||||||
if (!slideContainerRef.current) return;
|
if (!slideContainerRef.current) return;
|
||||||
|
|
||||||
if (!document.fullscreenElement) {
|
if (!document.fullscreenElement) {
|
||||||
@@ -798,21 +811,21 @@ const toggleFullscreen = () => {
|
|||||||
document.exitFullscreen();
|
document.exitFullscreen();
|
||||||
setIsFullscreen(false);
|
setIsFullscreen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToSlide = (index: number) => {
|
const goToSlide = (index: number) => {
|
||||||
if (slidesPresentation?.slides) {
|
if (slidesPresentation?.slides) {
|
||||||
setCurrentSlide(Math.max(0, Math.min(index, slidesPresentation.slides.length - 1)));
|
setCurrentSlide(Math.max(0, Math.min(index, slidesPresentation.slides.length - 1)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatFileSize = (bytes: number) => {
|
const formatFileSize = (bytes: number) => {
|
||||||
if (bytes < 1024) return bytes + " B";
|
if (bytes < 1024) return bytes + " B";
|
||||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
||||||
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 xl:grid-cols-2 text-start">
|
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 xl:grid-cols-2 text-start">
|
||||||
{/* Input Panel */}
|
{/* Input Panel */}
|
||||||
<Card className="h-fit">
|
<Card className="h-fit">
|
||||||
@@ -1279,5 +1292,5 @@ return (
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,16 @@ import { cn } from "@/lib/utils";
|
|||||||
import { translations } from "@/lib/i18n/translations";
|
import { translations } from "@/lib/i18n/translations";
|
||||||
|
|
||||||
export default function UXDesignerPrompt() {
|
export default function UXDesignerPrompt() {
|
||||||
|
const {
|
||||||
language,
|
language,
|
||||||
|
currentPrompt,
|
||||||
|
enhancedPrompt,
|
||||||
|
selectedProvider,
|
||||||
|
selectedModels,
|
||||||
|
availableModels,
|
||||||
|
apiKeys,
|
||||||
|
isProcessing,
|
||||||
|
error,
|
||||||
setSelectedProvider,
|
setSelectedProvider,
|
||||||
setCurrentPrompt,
|
setCurrentPrompt,
|
||||||
setEnhancedPrompt,
|
setEnhancedPrompt,
|
||||||
@@ -21,16 +30,16 @@ export default function UXDesignerPrompt() {
|
|||||||
setSelectedModel,
|
setSelectedModel,
|
||||||
} = useStore();
|
} = useStore();
|
||||||
|
|
||||||
const t = translations[language].uxDesigner;
|
const t = translations[language].uxDesigner;
|
||||||
const common = translations[language].common;
|
const common = translations[language].common;
|
||||||
|
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const [generatedPrompt, setGeneratedPrompt] = useState<string | null>(null);
|
const [generatedPrompt, setGeneratedPrompt] = useState<string | null>(null);
|
||||||
|
|
||||||
const selectedModel = selectedModels[selectedProvider];
|
const selectedModel = selectedModels[selectedProvider];
|
||||||
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
const models = availableModels[selectedProvider] || modelAdapter.getAvailableModels(selectedProvider);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
loadAvailableModels();
|
loadAvailableModels();
|
||||||
const saved = localStorage.getItem("promptarch-api-keys");
|
const saved = localStorage.getItem("promptarch-api-keys");
|
||||||
@@ -44,9 +53,9 @@ useEffect(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectedProvider]);
|
}, [selectedProvider]);
|
||||||
|
|
||||||
const loadAvailableModels = async () => {
|
const loadAvailableModels = async () => {
|
||||||
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
const fallbackModels = modelAdapter.getAvailableModels(selectedProvider);
|
||||||
setAvailableModels(selectedProvider, fallbackModels);
|
setAvailableModels(selectedProvider, fallbackModels);
|
||||||
|
|
||||||
@@ -58,9 +67,9 @@ const loadAvailableModels = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load models:", error);
|
console.error("Failed to load models:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGenerate = async () => {
|
const handleGenerate = async () => {
|
||||||
if (!currentPrompt.trim()) {
|
if (!currentPrompt.trim()) {
|
||||||
setError("Please enter an app description");
|
setError("Please enter an app description");
|
||||||
return;
|
return;
|
||||||
@@ -98,24 +107,24 @@ const handleGenerate = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
if (generatedPrompt) {
|
if (generatedPrompt) {
|
||||||
await navigator.clipboard.writeText(generatedPrompt);
|
await navigator.clipboard.writeText(generatedPrompt);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
setTimeout(() => setCopied(false), 2000);
|
setTimeout(() => setCopied(false), 2000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClear = () => {
|
const handleClear = () => {
|
||||||
setCurrentPrompt("");
|
setCurrentPrompt("");
|
||||||
setGeneratedPrompt(null);
|
setGeneratedPrompt(null);
|
||||||
setEnhancedPrompt(null);
|
setEnhancedPrompt(null);
|
||||||
setError(null);
|
setError(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2 text-start">
|
<div className="mx-auto grid max-w-7xl gap-4 lg:gap-6 grid-cols-1 lg:grid-cols-2 text-start">
|
||||||
<Card className="h-fit">
|
<Card className="h-fit">
|
||||||
<CardHeader className="p-4 lg:p-6 text-start">
|
<CardHeader className="p-4 lg:p-6 text-start">
|
||||||
@@ -245,5 +254,5 @@ return (
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const translations = {
|
|||||||
title: "Prompt Enhancer",
|
title: "Prompt Enhancer",
|
||||||
description: "Transform your simple ideas into professional, high-quality prompts",
|
description: "Transform your simple ideas into professional, high-quality prompts",
|
||||||
placeholder: "Enter your prompt here...",
|
placeholder: "Enter your prompt here...",
|
||||||
|
inputLabel: "Your Prompt",
|
||||||
enhancedTitle: "Enhanced Prompt",
|
enhancedTitle: "Enhanced Prompt",
|
||||||
enhancedDesc: "Your prompt has been optimized for better AI performance",
|
enhancedDesc: "Your prompt has been optimized for better AI performance",
|
||||||
},
|
},
|
||||||
@@ -150,6 +151,7 @@ export const translations = {
|
|||||||
title: "Улучшение промптов",
|
title: "Улучшение промптов",
|
||||||
description: "Превратите ваши простые идеи в профессиональные, качественные промпты",
|
description: "Превратите ваши простые идеи в профессиональные, качественные промпты",
|
||||||
placeholder: "Введите ваш промпт здесь...",
|
placeholder: "Введите ваш промпт здесь...",
|
||||||
|
inputLabel: "Ваш промпт",
|
||||||
enhancedTitle: "Улучшенный промпт",
|
enhancedTitle: "Улучшенный промпт",
|
||||||
enhancedDesc: "Ваш промпт оптимизирован для лучшей работы ИИ",
|
enhancedDesc: "Ваш промпт оптимизирован для лучшей работы ИИ",
|
||||||
},
|
},
|
||||||
@@ -271,6 +273,7 @@ export const translations = {
|
|||||||
title: "משפר פרומפטים",
|
title: "משפר פרומפטים",
|
||||||
description: "הפוך רעיונות פשוטים לפרומפטים מקצועיים באיכות גבוהה",
|
description: "הפוך רעיונות פשוטים לפרומפטים מקצועיים באיכות גבוהה",
|
||||||
placeholder: "הזן את הפרומפט שלך כאן...",
|
placeholder: "הזן את הפרומפט שלך כאן...",
|
||||||
|
inputLabel: "הפרומפט שלך",
|
||||||
enhancedTitle: "פרומפט משופר",
|
enhancedTitle: "פרומפט משופר",
|
||||||
enhancedDesc: "הפרומפט שלך הותאם לביצועי בינה מלאכותית טובים יותר",
|
enhancedDesc: "הפרומפט שלך הותאם לביצועי בינה מלאכותית טובים יותר",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user