diff --git a/kittyurl-frontend/src/components/Generator.tsx b/kittyurl-frontend/src/components/Generator.tsx index ad4f235..66abfb7 100644 --- a/kittyurl-frontend/src/components/Generator.tsx +++ b/kittyurl-frontend/src/components/Generator.tsx @@ -8,11 +8,18 @@ import { // Pobieramy adres API const API_BASE = import.meta.env.VITE_API_TARGET; -// Nazwa klucza w localStorage, gdzie trzymasz token +// Nazwa klucza w localStorage const TOKEN_KEY = 'jwt_token'; type CaseType = 'upper' | 'lower' | 'mixed'; +// 1. Definicja propsów, które przychodzą z App.tsx +interface GeneratorProps { + url: string; + setUrl: (url: string) => void; + onGenerate: () => void; +} + interface GeneratorSettings { length: number; alphanum: boolean; @@ -20,8 +27,8 @@ interface GeneratorSettings { withSubdomain: boolean; } +// Usunęliśmy 'remoteUrl' stąd, bo teraz przychodzi z propsów (url) interface LinkFormData { - remoteUrl: string; uri: string; subdomain: string; privacy: boolean; @@ -39,23 +46,22 @@ interface LinkPayload { interface User { id: string; - username: string; + username: string; email?: string; } -export const Generator: React.FC = () => { +// 2. Dodajemy propsy do argumentów funkcji +export const Generator: React.FC = ({ url, setUrl, onGenerate }) => { const [user, setUser] = useState(null); - // Stan formularza głównego + // Stan formularza (bez remoteUrl, bo to jest teraz w 'url') const [formData, setFormData] = useState({ - remoteUrl: '', uri: '', subdomain: '', privacy: true, expiryDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0] }); - // Stan ustawień generatora (GET) const [genSettings, setGenSettings] = useState({ length: 6, alphanum: true, @@ -63,14 +69,12 @@ export const Generator: React.FC = () => { withSubdomain: false }); - // Stany UI const [loading, setLoading] = useState(false); const [generatingUri, setGeneratingUri] = useState(false); const [errorMsg, setErrorMsg] = useState(null); const [result, setResult] = useState(null); const [copied, setCopied] = useState(false); - // Helper do pobierania nagłówków z tokenem const getAuthHeaders = () => { const token = localStorage.getItem(TOKEN_KEY); return { @@ -79,13 +83,10 @@ export const Generator: React.FC = () => { }; }; - // 1. Sprawdzenie sesji użytkownika przy starcie (używając JWT) - // 1. Sprawdzenie sesji użytkownika przy starcie + // Sprawdzenie sesji użytkownika useEffect(() => { const checkUser = async () => { const token = localStorage.getItem(TOKEN_KEY); - - // Jeśli brak tokena, przerywamy (tryb gościa) if (!token) return; try { @@ -95,30 +96,23 @@ export const Generator: React.FC = () => { if (res.ok) { const data = await res.json(); - - // Naprawa "Logged in as undefined": - // API może zwracać 'name', 'username' lub tylko 'email' setUser({ id: data.id || data._id || data.userId, username: data.username || data.name || data.email || "User", email: data.email }); } else { - // Jeśli token jest nieważny (401), czyścimy go console.log("Session expired. Logging out."); localStorage.removeItem(TOKEN_KEY); setUser(null); } } catch { - // POPRAWKA: Usunęliśmy '(err)', teraz jest samo 'catch' - // Dzięki temu linter nie krzyczy o nieużywaną zmienną console.log("API unreachable"); } }; checkUser(); }, []); - // 2. Generowanie URI (GET) - tutaj auth zazwyczaj nie jest wymagany, ale można dodać const handleGenerateUri = async (type: 'random' | 'wordlist') => { setGeneratingUri(true); setErrorMsg(null); @@ -140,8 +134,6 @@ export const Generator: React.FC = () => { endpoint = '/api/v1/link/fromWordlist'; } - // GET zazwyczaj jest publiczny, więc nie musimy dodawać Bearera, - // ale jeśli API tego wymaga, dodaj: headers: getAuthHeaders() const response = await fetch(`${API_BASE}${endpoint}?${params.toString()}`); const data = await response.json(); @@ -157,9 +149,9 @@ export const Generator: React.FC = () => { } }; - // 3. Zapis do bazy (POST) - WYMAGA AUTH (JWT) const handleSubmitToDb = async () => { - if (!formData.remoteUrl) { + // Używamy propsa 'url' zamiast formData.remoteUrl + if (!url) { setErrorMsg("Meow! I need a destination URL first! 🐾"); return; } @@ -174,7 +166,7 @@ export const Generator: React.FC = () => { try { const payload: LinkPayload = { - remoteUrl: formData.remoteUrl, + remoteUrl: url, // <-- Tutaj wstawiamy wartość z propsa uri: formData.uri, subdomain: formData.subdomain || undefined, privacy: formData.privacy, @@ -187,7 +179,7 @@ export const Generator: React.FC = () => { const response = await fetch(`${API_BASE}/api/v1/link/new`, { method: 'POST', - headers: getAuthHeaders(), // Tu wstrzykujemy JWT + headers: getAuthHeaders(), body: JSON.stringify(payload) }); @@ -200,6 +192,9 @@ export const Generator: React.FC = () => { const finalLink = data.url || `${API_BASE.replace('api.', '')}/${formData.uri}`; setResult(finalLink); + // Wywołujemy callback z App.tsx (np. żeby pokazać powiadomienie) + onGenerate(); + } catch (err: unknown) { if (err instanceof Error) setErrorMsg(err.message); else setErrorMsg("Something went wrong saving to DB!"); @@ -227,7 +222,6 @@ export const Generator: React.FC = () => { KittyURL

Shorten your links with a purr!

- {/* Error Display */} @@ -277,8 +271,8 @@ export const Generator: React.FC = () => { type="url" placeholder="https://very-long-link.com/..." className="w-full p-4 bg-pink-50/30 border-2 border-pink-100 rounded-2xl outline-none focus:border-pink-400 focus:bg-white transition-all text-pink-600 font-medium pr-12" - value={formData.remoteUrl} - onChange={(e) => setFormData({ ...formData, remoteUrl: e.target.value })} + value={url} // Używamy propsa + onChange={(e) => setUrl(e.target.value)} // Używamy propsa />