Files
next-go-blog/app/(auth)/login/page.tsx
Beyhan Oğur 6d95e27114 first commit
2026-04-26 22:16:43 +03:00

136 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useState } from "react";
import { useAppDispatch, useAppSelector } from "@/lib/hooks";
import { login } from "@/lib/features/auth/authSlice";
import { useRouter } from "next/navigation";
import { Turnstile } from "nextjs-turnstile";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { AlertCircle, Loader2 } from "lucide-react";
import Link from "next/link";
import Swal from 'sweetalert2'
import { loginSchema } from "@/lib/schemas/login";
export default function LoginPage() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [formErrors, setFormErrors] = useState<Record<string, string>>({});
const [turnstileToken, setTurnstileToken] = useState<string | null>(null);
const dispatch = useAppDispatch();
const { isLoading, error } = useAppSelector((state) => state.auth);
const router = useRouter();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setFormErrors({});
// Zod Validation
const result = loginSchema.safeParse({
email,
password
});
if (!result.success) {
const errors: Record<string, string> = {};
result.error.issues.forEach((issue) => {
const path = issue.path[0];
if (typeof path === 'string') {
errors[path] = issue.message;
}
});
setFormErrors(errors);
return;
}
if (!turnstileToken) {
Swal.fire({
icon: 'error',
title: 'Hata',
text: 'Lütfen doğrulamayı tamamlayın (Turnstile).',
})
return;
}
const dispatchResult = await dispatch(login({ email, password }));
if (login.fulfilled.match(dispatchResult)) {
Swal.fire({
position: "center",
icon: "success",
title: "Giriş Başarılı",
showConfirmButton: false,
timer: 1500
});
router.push("/admin");
}
};
return (
<Card className="w-full shadow-lg dark:shadow-slate-800/20">
<CardHeader>
<CardTitle className="text-2xl font-bold text-center">Giriş Yap</CardTitle>
<CardDescription className="text-center">
Admin paneline erişmek için giriş yapın
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="admin@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
// required override by Zod
/>
{formErrors.email && <p className="text-destructive text-sm">{formErrors.email}</p>}
</div>
<div className="space-y-2">
<Label htmlFor="password">Şifre</Label>
<Input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
// required override by Zod
/>
{formErrors.password && <p className="text-destructive text-sm">{formErrors.password}</p>}
</div>
<div className="flex justify-center py-2">
<Turnstile
siteKey={process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY || "0x4AAAAAACHzHKvlEwMamxCM"}
onSuccess={(token) => setTurnstileToken(token)}
/>
</div>
{error && (
<div className="flex items-center gap-2 text-sm text-destructive bg-destructive/10 p-3 rounded-md">
<AlertCircle className="h-4 w-4" />
<span>{error}</span>
</div>
)}
<Button type="submit" className="w-full" disabled={isLoading || !turnstileToken}>
{isLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : "Giriş Yap"}
</Button>
</form>
</CardContent>
<CardFooter className="flex justify-center">
<p className="text-sm text-muted-foreground">
Hesabınız yok mu?{" "}
<Link href="/register" className="text-primary hover:underline">
Kayıt Ol
</Link>
</p>
</CardFooter>
</Card>
);
}