Files
memito/frontend/src/components/auth/LoginPage.tsx
wisecolt 05bbe307e0 feat: not uygulaması ve altyapısını ekle
- iOS Memos benzeri PWA ön yüz eklendi (React, Tailwind)
- Express tabanlı arka uç, AnythingLLM API entegrasyonu ve senkronizasyon kuyruğu oluşturuldu
- Docker, TypeScript ve proje konfigürasyonları tanımlandı
2025-12-28 23:37:38 +03:00

80 lines
2.8 KiB
TypeScript

import { useState } from "react";
import { clearAuthHeader, getAuthHeader, setAuthHeader } from "../../auth/authStore";
import Button from "../ui/Button";
type LoginPageProps = {
onSuccess: () => void;
};
export default function LoginPage({ onSuccess }: LoginPageProps) {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
if (!username.trim()) {
setError("Kullanici adi gerekli.");
return;
}
setAuthHeader(username.trim(), password);
try {
const base = import.meta.env.VITE_API_BASE ?? "/api";
const authHeader = getAuthHeader();
const response = await fetch(`${base}/health`, {
headers: {
Authorization: authHeader ?? ""
}
});
if (!response.ok) {
throw new Error("Yetkisiz");
}
setError(null);
onSuccess();
} catch (error) {
clearAuthHeader();
setError("Giris basarisiz. Kullanici adi veya sifre hatali.");
}
};
return (
<div className="min-h-screen bg-[var(--paper)] px-4 py-10">
<div className="mx-auto w-full max-w-md rounded-3xl bg-white/80 p-8 shadow-xl">
<h1 className="font-display text-3xl text-[var(--ink)]">Memos</h1>
<p className="mt-2 text-sm text-[var(--muted)]">Notlarina erismek icin giris yap.</p>
<form className="mt-6 space-y-4" onSubmit={handleSubmit}>
<label className="block text-xs font-semibold uppercase text-[var(--muted)]">
Kullanici adi
<input
value={username}
onChange={(event) => setUsername(event.target.value)}
className="mt-2 w-full rounded-2xl border border-slate-200 bg-white px-4 py-3 text-sm outline-none focus:border-[var(--accent)]"
placeholder="admin"
autoComplete="username"
/>
</label>
<label className="block text-xs font-semibold uppercase text-[var(--muted)]">
Sifre
<input
value={password}
onChange={(event) => setPassword(event.target.value)}
type="password"
className="mt-2 w-full rounded-2xl border border-slate-200 bg-white px-4 py-3 text-sm outline-none focus:border-[var(--accent)]"
placeholder="••••••"
autoComplete="current-password"
/>
</label>
{error && <p className="text-xs text-red-600">{error}</p>}
<Button
type="submit"
radius="2xl"
className="w-full bg-[var(--accent)] py-3 text-sm font-semibold text-white"
>
Giris Yap
</Button>
</form>
</div>
</div>
);
}