From b4503b7e3e45a0bba8d297ec718f76658a6e8282 Mon Sep 17 00:00:00 2001 From: Riccardo Giorato Date: Fri, 26 Dec 2025 21:16:23 +0100 Subject: [PATCH] Replace localStorage API key with reactive hook across app --- app/editor/[storySlug]/page.tsx | 13 ++--- components/api-key-modal.tsx | 38 ++++++------- components/landing/comic-creation-form.tsx | 28 +++++----- components/landing/navbar.tsx | 4 +- hooks/use-api-key.ts | 65 ++++++++++++++++++++++ 5 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 hooks/use-api-key.ts diff --git a/app/editor/[storySlug]/page.tsx b/app/editor/[storySlug]/page.tsx index e833f7e..57e3594 100644 --- a/app/editor/[storySlug]/page.tsx +++ b/app/editor/[storySlug]/page.tsx @@ -3,6 +3,7 @@ import { useState, useEffect } from "react"; import { useParams } from "next/navigation"; import { useToast } from "@/hooks/use-toast"; +import { useApiKey } from "@/hooks/use-api-key"; import { EditorToolbar } from "@/components/editor/editor-toolbar"; import { PageSidebar } from "@/components/editor/page-sidebar"; import { ComicCanvas } from "@/components/editor/comic-canvas"; @@ -48,6 +49,7 @@ export default function StoryEditorPage() { string[] >([]); const { toast } = useToast(); + const [apiKey, setApiKey] = useApiKey(); // Load story and pages from API useEffect(() => { @@ -123,8 +125,7 @@ export default function StoryEditorPage() { }, [pages.length]); const handleAddPage = () => { - const storedKey = localStorage.getItem("together_api_key"); - if (!storedKey && pages.length >= 1) { + if (!apiKey && pages.length >= 1) { setShowApiModal(true); return; } @@ -132,8 +133,7 @@ export default function StoryEditorPage() { }; const handleRedrawPage = async () => { - const storedKey = localStorage.getItem("together_api_key"); - if (!storedKey) { + if (!apiKey) { setShowApiModal(true); return; } @@ -148,7 +148,7 @@ export default function StoryEditorPage() { method: "POST", headers: { "Content-Type": "application/json", - "x-api-key": storedKey, + "x-api-key": apiKey, }, body: JSON.stringify({ storyId: story?.slug, @@ -196,7 +196,7 @@ export default function StoryEditorPage() { }; const handleApiKeySubmit = (key: string) => { - localStorage.setItem("together_api_key", key); + setApiKey(key); setShowApiModal(false); const wasGenerating = showGenerateModal; if (wasGenerating) { @@ -210,7 +210,6 @@ export default function StoryEditorPage() { characterUrls?: string[]; }) => { try { - const apiKey = localStorage.getItem("together_api_key"); if (!apiKey) { setShowApiModal(true); return; diff --git a/components/api-key-modal.tsx b/components/api-key-modal.tsx index b1f4d18..cb664c8 100644 --- a/components/api-key-modal.tsx +++ b/components/api-key-modal.tsx @@ -13,6 +13,7 @@ import { DialogDescription, } from "@/components/ui/dialog"; import { TOGETHER_LINK } from "@/lib/utils"; +import { useApiKey } from "@/hooks/use-api-key"; interface ApiKeyModalProps { isOpen: boolean; @@ -21,38 +22,35 @@ interface ApiKeyModalProps { } export function ApiKeyModal({ isOpen, onClose, onSubmit }: ApiKeyModalProps) { - const [apiKey, setApiKey] = useState(""); + const [apiKeyInput, setApiKeyInput] = useState(""); const [isLoading, setIsLoading] = useState(false); - const [existingKey, setExistingKey] = useState(null); + const [existingKey, setApiKey] = useApiKey(); useEffect(() => { - if (typeof window !== "undefined" && isOpen) { - const storedKey = localStorage.getItem("together_api_key"); - setExistingKey(storedKey); - setApiKey((current) => { - if (storedKey && current === "") { - return storedKey; + if (isOpen) { + setApiKeyInput((current) => { + if (existingKey && current === "") { + return existingKey; } return current; }); } - }, [isOpen]); + }, [isOpen, existingKey]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - if (!apiKey.trim()) return; + if (!apiKeyInput.trim()) return; setIsLoading(true); await new Promise((resolve) => setTimeout(resolve, 500)); setIsLoading(false); - onSubmit(apiKey.trim()); - setApiKey(""); + onSubmit(apiKeyInput.trim()); + setApiKeyInput(""); }; const handleDelete = () => { - localStorage.removeItem("together_api_key"); - setExistingKey(null); - setApiKey(""); + setApiKey(null); + setApiKeyInput(""); onClose(); }; @@ -83,15 +81,15 @@ export function ApiKeyModal({ isOpen, onClose, onSubmit }: ApiKeyModalProps) {
setApiKey(e.target.value)} + value={apiKeyInput} + onChange={(e) => setApiKeyInput(e.target.value)} placeholder={existingKey ? "Your current API key" : "Enter your API key..."} className="bg-secondary border-border/50 text-white placeholder-muted-foreground py-5 pr-10" /> - {apiKey && ( + {apiKeyInput && (