238 lines
6.7 KiB
Markdown
238 lines
6.7 KiB
Markdown
# Web Pages
|
||
|
||
- Web pages that are used in the project
|
||
|
||
## Directories:
|
||
|
||
```
|
||
-| PageName
|
||
-| hook.ts
|
||
-| language.ts
|
||
-| page.tsx
|
||
-| schemas.ts
|
||
-| types.ts
|
||
```
|
||
|
||
### hook.ts:
|
||
|
||
```typescript
|
||
export function loginHook(
|
||
startTransition: any,
|
||
data: any,
|
||
setError: any,
|
||
setJsonText: any,
|
||
Router: any,
|
||
lang: LanguageTypes
|
||
) {
|
||
try {
|
||
const sendData = { ...data };
|
||
startTransition(() => {
|
||
fetch("/api/login/email", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(sendData),
|
||
})
|
||
.then((response) => {
|
||
if (response.status === 200) {
|
||
response.json().then((data) => {
|
||
setTimeout(() => {
|
||
Router.push(`/panel/dashboard`);
|
||
}, 100);
|
||
});
|
||
} else {
|
||
response.json().then((data) => {
|
||
setError(data?.message);
|
||
});
|
||
}
|
||
})
|
||
.catch(() => {});
|
||
});
|
||
} catch (error) {
|
||
setError("An error occurred during login");
|
||
}
|
||
}
|
||
```
|
||
|
||
### language.ts:
|
||
|
||
```typescript
|
||
export const loginTranslation = {
|
||
tr: {
|
||
email: "E-Posta",
|
||
password: "Şifre",
|
||
rememberMe: "Beni Hatırla",
|
||
login: "Giriş Yap",
|
||
successMessage: "Giriş Yapıldı",
|
||
errorMessage: "Giriş Yapılmadı",
|
||
pendingMessage: "Giriş Yapılıyor...",
|
||
responseData: "Giriş Verileri",
|
||
},
|
||
en: {
|
||
email: "Email",
|
||
password: "Password",
|
||
rememberMe: "Remember Me",
|
||
login: "Login",
|
||
successMessage: "Login completed successfully",
|
||
errorMessage: "Login failed",
|
||
pendingMessage: "Logging in...",
|
||
responseData: "Response Data",
|
||
},
|
||
};
|
||
```
|
||
|
||
### page.tsx:
|
||
|
||
```typescript
|
||
"use client";
|
||
import { useState, useTransition } from "react";
|
||
import { useRouter } from "next/navigation";
|
||
import { useForm } from "react-hook-form";
|
||
import { zodResolver } from "@hookform/resolvers/zod";
|
||
import { LoginFormData } from "./types";
|
||
import { loginSchemaEmail } from "./schemas";
|
||
import { loginTranslation } from "./language";
|
||
import { loginHook } from "./hook";
|
||
import { AuthPageProps } from "@/validations/mutual/auth/props";
|
||
|
||
function Login({ language }: AuthPageProps) {
|
||
const Router = useRouter();
|
||
const translation = loginTranslation[language];
|
||
|
||
const [isPending, startTransition] = useTransition();
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [jsonText, setJsonText] = useState<string | null>(null);
|
||
|
||
const {
|
||
register,
|
||
formState: { errors },
|
||
handleSubmit,
|
||
} = useForm<LoginFormData>({ resolver: zodResolver(loginSchemaEmail) });
|
||
const onSubmit = async (data: LoginFormData) => {
|
||
loginHook(startTransition, data, setError, setJsonText, Router, language);
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<div className="flex h-full min-h-[inherit] flex-col items-center justify-center gap-4">
|
||
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
|
||
<h2 className="mb-6 text-center text-2xl font-bold text-gray-900">
|
||
{translation.login}
|
||
</h2>
|
||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
|
||
<div>
|
||
<label
|
||
htmlFor="email"
|
||
className="block text-sm font-medium text-gray-700"
|
||
>
|
||
{translation.email}
|
||
</label>
|
||
<input
|
||
{...register("email")}
|
||
type="email"
|
||
id="email"
|
||
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500"
|
||
/>
|
||
{errors.email && (
|
||
<p className="mt-1 text-sm text-red-600">
|
||
{errors.email.message}
|
||
</p>
|
||
)}
|
||
</div>
|
||
<div>
|
||
<label
|
||
htmlFor="password"
|
||
className="block text-sm font-medium text-gray-700"
|
||
>
|
||
{translation.password}
|
||
</label>
|
||
<input
|
||
{...register("password")}
|
||
type="password"
|
||
id="password"
|
||
className="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500"
|
||
/>
|
||
{errors.password && (
|
||
<p className="mt-1 text-sm text-red-600">
|
||
{errors.password.message}
|
||
</p>
|
||
)}
|
||
</div>
|
||
{error && (
|
||
<div className="rounded-md bg-red-50 p-4">
|
||
<p className="text-sm text-red-700">{error}</p>
|
||
</div>
|
||
)}
|
||
<button
|
||
type="submit"
|
||
disabled={isPending}
|
||
className="w-full rounded-md bg-indigo-600 px-4 py-2 text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-50"
|
||
>
|
||
{isPending ? translation.pendingMessage : translation.login}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
{jsonText && (
|
||
<div className="w-full max-w-md rounded-lg bg-white p-8 shadow-md">
|
||
<h2 className="mb-4 text-center text-xl font-bold text-gray-900">
|
||
{translation.responseData}
|
||
</h2>
|
||
<div className="space-y-2">
|
||
{Object.entries(JSON.parse(jsonText)).map(([key, value]) => (
|
||
<div key={key} className="flex items-start gap-2">
|
||
<strong className="text-gray-700">{key}:</strong>
|
||
<span className="text-gray-600">
|
||
{typeof value === "object"
|
||
? JSON.stringify(value)
|
||
: value?.toString() || "N/A"}
|
||
</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</>
|
||
);
|
||
}
|
||
|
||
export default Login;
|
||
```
|
||
|
||
### schemas.ts:
|
||
|
||
```typescript
|
||
import { z } from "zod";
|
||
|
||
const loginSchemaEmail = z.object({
|
||
email: z.string().email("Invalid email address"),
|
||
password: z.string().min(5, "Password must be at least 5 characters"),
|
||
rememberMe: z.boolean().optional().default(false),
|
||
});
|
||
|
||
const loginSchemaPhone = z.object({
|
||
phone: z.string().regex(/^[0-9]{10}$/, "Invalid phone number"),
|
||
password: z.string().min(5, "Password must be at least 5 characters"),
|
||
rememberMe: z.boolean().optional().default(false),
|
||
});
|
||
|
||
export { loginSchemaEmail, loginSchemaPhone };
|
||
```
|
||
|
||
### types.ts:
|
||
|
||
```typescript
|
||
type LoginFormData = {
|
||
email: string;
|
||
password: string;
|
||
rememberMe?: boolean;
|
||
};
|
||
|
||
type LoginFormDataPhone = {
|
||
phone: string;
|
||
password: string;
|
||
rememberMe?: boolean;
|
||
};
|
||
|
||
export type { LoginFormData, LoginFormDataPhone };
|
||
```
|