diff --git a/.DS_Store b/.DS_Store index 18829a8..6468cc9 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/App.tsx b/App.tsx index d423735..cb815dc 100644 --- a/App.tsx +++ b/App.tsx @@ -7,10 +7,31 @@ import StepEventType from './components/StepEventType'; import StepToneGoal from './components/StepToneGoal'; import StepDetails from './components/StepDetails'; import StepResult from './components/StepResult'; -import { ChevronLeft, ExternalLink, Sparkles, User } from 'lucide-react'; +import { ChevronLeft, ExternalLink, Sparkles, User, Lock, ArrowRight, AlertCircle, Bug } from 'lucide-react'; import { generateStoryContent } from './services/geminiService'; const STORAGE_KEY = 'gpx-storyteller-state-v6'; // Incremented version for structure change +const AUTH_KEY = 'promptstory-auth-token'; + +// --- PASSWORD CONFIGURATION --- + +// 1. Try fetching from Vite standard (import.meta.env) +// @ts-ignore +const VITE_ENV_PASS = import.meta.env && import.meta.env.VITE_APP_PASSWORD ? import.meta.env.VITE_APP_PASSWORD : ''; + +// 2. Try fetching from Process env (sometimes used in other build tools) +// @ts-ignore +const PROCESS_ENV_PASS = (typeof process !== 'undefined' && process.env && process.env.VITE_APP_PASSWORD) ? process.env.VITE_APP_PASSWORD : ''; + +// 3. Fallback (Hardcoded safety net) +// W tym środowisku (AI Studio/Web Preview) restart serwera jest trudny. +// Ustawiamy hasło "na sztywno" jako zapas, żeby działało od razu. +const FALLBACK_PASS = 'Prometeusz'; + +// Decision Logic +const ENV_PASSWORD = VITE_ENV_PASS || PROCESS_ENV_PASS; +const APP_PASSWORD = ENV_PASSWORD || FALLBACK_PASS; +const IS_USING_FALLBACK = !ENV_PASSWORD; const INITIAL_STATE: WizardState = { step: Step.CONTEXT, @@ -38,7 +59,131 @@ const INITIAL_STATE: WizardState = { } }; +// --- LOGIN SCREEN COMPONENT --- +const LoginScreen: React.FC<{ onLogin: (success: boolean) => void }> = ({ onLogin }) => { + const [input, setInput] = useState(''); + const [error, setError] = useState(false); + const [showDebug, setShowDebug] = useState(false); + + // DEBUGGING: Log to console on mount + useEffect(() => { + console.group("--- DEBUG PASSWORD SYSTEM ---"); + console.log("1. Detected VITE_ENV:", VITE_ENV_PASS ? "****" : "(empty)"); + console.log("2. Detected PROCESS_ENV:", PROCESS_ENV_PASS ? "****" : "(empty)"); + console.log("3. Final Password Source:", IS_USING_FALLBACK ? "FALLBACK (Hardcoded)" : ".ENV FILE"); + console.log("4. Active Password Length:", APP_PASSWORD.length); + console.groupEnd(); + }, []); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + // Trim input to avoid accidental spaces from copy-paste + if (input.trim() === APP_PASSWORD) { + onLogin(true); + } else { + console.log(`Failed Login. Input: "${input}" vs Expected: "${APP_PASSWORD}"`); + setError(true); + setInput(''); + } + }; + + return ( +
+
+ + {/* Debug Toggle (Hidden in corner) */} + + +
+
+ +
+
+ +
+

Dostęp Chroniony

+

Wprowadź hasło, aby uzyskać dostęp do kreatora PromptStory.

+
+ +
+
+ { + setInput(e.target.value); + setError(false); + }} + placeholder="Hasło..." + className={`w-full p-4 border rounded-lg outline-none transition-all font-medium text-center tracking-widest ${ + error + ? 'border-red-300 bg-red-50 focus:border-red-500' + : 'border-gray-200 focus:border-[#EA4420] focus:ring-1 focus:ring-[#EA4420]' + }`} + autoFocus + /> +
+ + {error && ( +
+ + Nieprawidłowe hasło +
+ )} + + +
+ + {/* DEBUG PANEL */} + {showDebug && ( +
+

DEBUG STATUS:

+ +
+ SOURCE: + + {IS_USING_FALLBACK ? "FALLBACK (Code)" : ".ENV FILE"} + + + ACTIVE PASS: + {APP_PASSWORD.substring(0, 4)}... (len: {APP_PASSWORD.length}) +
+ + {IS_USING_FALLBACK && ( +
+

System używa hasła awaryjnego zdefiniowanego w kodzie, ponieważ nie może odświeżyć pliku .env bez restartu.

+

Twoje hasło powinno teraz działać.

+
+ )} +
+ )} + +

+ PromptStory v1.0 • Private Instance +

+
+
+ ); +}; + const App: React.FC = () => { + // Auth State + const [isAuthenticated, setIsAuthenticated] = useState(false); + const [isAuthChecking, setIsAuthChecking] = useState(true); + + // App State const [data, setData] = useState(INITIAL_STATE); const [generatedContent, setGeneratedContent] = useState(null); const [isGenerating, setIsGenerating] = useState(false); @@ -49,7 +194,29 @@ const App: React.FC = () => { const [logoError, setLogoError] = useState(false); const [avatarError, setAvatarError] = useState(false); - // Persistence Logic + // 1. Check Auth on Mount + useEffect(() => { + const storedAuth = localStorage.getItem(AUTH_KEY); + if (storedAuth === 'true') { + setIsAuthenticated(true); + } + setIsAuthChecking(false); + }, []); + + const handleLogin = (success: boolean) => { + if (success) { + localStorage.setItem(AUTH_KEY, 'true'); + setIsAuthenticated(true); + } + }; + + const handleLogout = () => { + localStorage.removeItem(AUTH_KEY); + setIsAuthenticated(false); + resetApp(); + }; + + // 2. Load Data Persistence Logic useEffect(() => { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { @@ -154,7 +321,13 @@ const App: React.FC = () => { window.location.reload(); }; - if (!isLoaded) return null; + // --- RENDER LOGIC --- + + if (isAuthChecking || !isLoaded) return null; // Loading state + + if (!isAuthenticated) { + return ; + } // Step Labels for Progress Bar (Order Changed) const stepsLabels = ['Kontekst', 'Typ', 'Platforma', 'Vibe & Cel', 'Szczegóły']; @@ -179,9 +352,15 @@ const App: React.FC = () => { )}

PromptStory

- + +
+ + +
diff --git a/index.tsx b/index.tsx index 6ca5361..39e1012 100644 --- a/index.tsx +++ b/index.tsx @@ -12,4 +12,4 @@ root.render( -); \ No newline at end of file +);