Refactor code structure for improved readability and maintainability
This commit is contained in:
+42
-68
@@ -1,61 +1,31 @@
|
|||||||
import { login } from './actions'
|
import { login } from '@/app/login/actions'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import { Label } from '@/components/ui/label'
|
import { Label } from '@/components/ui/label'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { ErrorToaster } from '@/components/error-toaster'
|
import { ErrorToaster } from '@/components/error-toaster'
|
||||||
import Image from 'next/image'
|
|
||||||
import { Icon } from '@/components/ui/icon'
|
import { Icon } from '@/components/ui/icon'
|
||||||
|
import { AuthPageShell } from '@/components/auth/auth-page-shell'
|
||||||
|
|
||||||
export default async function LoginPage({
|
export default async function LoginPage({
|
||||||
searchParams,
|
searchParams,
|
||||||
}: {
|
}: {
|
||||||
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
|
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
|
||||||
}) {
|
}) {
|
||||||
const resolvedParams = await searchParams;
|
const resolvedParams = await searchParams
|
||||||
const error = resolvedParams?.error;
|
const error = resolvedParams?.error
|
||||||
const message = resolvedParams?.message;
|
const message = resolvedParams?.message
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen bg-background">
|
<>
|
||||||
{error && message && <ErrorToaster message={String(message)} />}
|
{error && message && <ErrorToaster message={String(message)} />}
|
||||||
|
<AuthPageShell
|
||||||
{/* Sol Taraf - Resim Alanı */}
|
title="Tekrar Hoş Geldiniz"
|
||||||
<div className="hidden lg:flex lg:w-1/2 p-4 relative">
|
description="Kişisel alanınıza ulaşmak için giriş yapın"
|
||||||
<div className="relative w-full h-full overflow-hidden rounded-2xl">
|
imageSrc="/images/1830857_Image.png"
|
||||||
<Image
|
imageAlt="MindSpace Background"
|
||||||
src="/images/1830857_Image.png"
|
imageSide="left"
|
||||||
alt="MindSpace Background"
|
form={
|
||||||
fill
|
|
||||||
className="object-cover"
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-background via-transparent to-background/30 opacity-90" />
|
|
||||||
{/* Logo */}
|
|
||||||
<div className="absolute bottom-0 flex items-center justify-center pointer-events-none z-10">
|
|
||||||
<div className="relative drop-shadow-2xl flex items-center gap-4">
|
|
||||||
<img
|
|
||||||
src="/logo/logo.png"
|
|
||||||
alt="MindSpace Logo"
|
|
||||||
className="object-contain w-64 h-auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Sağ Taraf - Form Alanı */}
|
|
||||||
<div className="flex flex-1 items-center justify-center p-8 w-full lg:w-1/2">
|
|
||||||
<div className="w-full max-w-sm space-y-8">
|
|
||||||
<div className="text-center lg:text-left">
|
|
||||||
<h1 className="text-3xl font-bold tracking-tight text-foreground">
|
|
||||||
Tekrar Hoş Geldiniz
|
|
||||||
</h1>
|
|
||||||
<p className="text-sm text-muted-foreground mt-2">
|
|
||||||
Kişisel alanınıza ulaşmak için giriş yapın
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form className="space-y-6">
|
<form className="space-y-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -96,29 +66,33 @@ export default async function LoginPage({
|
|||||||
Giriş Yap
|
Giriş Yap
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
|
secondaryAction={
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute inset-0 flex items-center">
|
||||||
|
<span className="w-full border-t border-border" />
|
||||||
|
</div>
|
||||||
|
<div className="relative flex justify-center text-xs uppercase">
|
||||||
|
<span className="bg-background px-2 text-muted-foreground">
|
||||||
|
veya
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="relative">
|
<Button
|
||||||
<div className="absolute inset-0 flex items-center">
|
type="button"
|
||||||
<span className="w-full border-t border-border" />
|
variant="outline"
|
||||||
</div>
|
className="w-full h-11 text-base font-medium bg-card border-border hover:bg-secondary transition-colors"
|
||||||
<div className="relative flex justify-center text-xs uppercase">
|
>
|
||||||
<span className="bg-background px-2 text-muted-foreground">
|
<Icon icon="flat-color-icons:google" className="w-5 h-5 mr-2" />
|
||||||
veya
|
Google ile Devam Et
|
||||||
</span>
|
</Button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
<Button
|
footer={
|
||||||
type="button"
|
<div className="text-center text-sm">
|
||||||
variant="outline"
|
Hesabınız yok mu?{' '}
|
||||||
className="w-full h-11 text-base font-medium bg-card border-border hover:bg-secondary transition-colors"
|
|
||||||
>
|
|
||||||
<Icon icon="flat-color-icons:google" className="w-5 h-5 mr-2" />
|
|
||||||
Google ile Devam Et
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<div className="text-center text-sm mt-6">
|
|
||||||
Hesabınız yok mu?{" "}
|
|
||||||
<Link
|
<Link
|
||||||
href="/register"
|
href="/register"
|
||||||
className="font-medium text-primary hover:text-primary-hover transition-colors"
|
className="font-medium text-primary hover:text-primary-hover transition-colors"
|
||||||
@@ -126,8 +100,8 @@ export default async function LoginPage({
|
|||||||
Kayıt Ol
|
Kayıt Ol
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
</div>
|
/>
|
||||||
</div>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-57
@@ -4,8 +4,8 @@ import { Input } from '@/components/ui/input'
|
|||||||
import { Label } from '@/components/ui/label'
|
import { Label } from '@/components/ui/label'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { ErrorToaster } from '@/components/error-toaster'
|
import { ErrorToaster } from '@/components/error-toaster'
|
||||||
import Image from 'next/image'
|
|
||||||
import { Icon } from '@/components/ui/icon'
|
import { Icon } from '@/components/ui/icon'
|
||||||
|
import { AuthPageShell } from '@/components/auth/auth-page-shell'
|
||||||
|
|
||||||
export default async function RegisterPage({
|
export default async function RegisterPage({
|
||||||
searchParams,
|
searchParams,
|
||||||
@@ -17,20 +17,15 @@ export default async function RegisterPage({
|
|||||||
const message = resolvedParams?.message
|
const message = resolvedParams?.message
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen bg-background">
|
<>
|
||||||
{error && message && <ErrorToaster message={String(message)} />}
|
{error && message && <ErrorToaster message={String(message)} />}
|
||||||
|
<AuthPageShell
|
||||||
<div className="flex flex-1 items-center justify-center p-8 w-full lg:w-1/2">
|
title="Aramıza Katılın"
|
||||||
<div className="w-full max-w-sm space-y-8">
|
description="Kişisel yaşam alanınızı oluşturmak için kayıt olun"
|
||||||
<div className="text-center lg:text-left">
|
imageSrc="/images/1830837_Image.png"
|
||||||
<h1 className="text-3xl font-bold tracking-tight text-foreground">
|
imageAlt="MindSpace Background"
|
||||||
Aramıza Katılın
|
imageSide="right"
|
||||||
</h1>
|
form={
|
||||||
<p className="text-sm text-muted-foreground mt-2">
|
|
||||||
Kişisel yaşam alanınızı oluşturmak için kayıt olun
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form className="space-y-6">
|
<form className="space-y-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -63,28 +58,32 @@ export default async function RegisterPage({
|
|||||||
Kayıt Ol
|
Kayıt Ol
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
|
secondaryAction={
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute inset-0 flex items-center">
|
||||||
|
<span className="w-full border-t border-border" />
|
||||||
|
</div>
|
||||||
|
<div className="relative flex justify-center text-xs uppercase">
|
||||||
|
<span className="bg-background px-2 text-muted-foreground">
|
||||||
|
veya
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="relative">
|
<Button
|
||||||
<div className="absolute inset-0 flex items-center">
|
type="button"
|
||||||
<span className="w-full border-t border-border" />
|
variant="outline"
|
||||||
</div>
|
className="w-full h-11 text-base font-medium bg-card border-border hover:bg-secondary transition-colors"
|
||||||
<div className="relative flex justify-center text-xs uppercase">
|
>
|
||||||
<span className="bg-background px-2 text-muted-foreground">
|
<Icon icon="flat-color-icons:google" className="w-5 h-5 mr-2" />
|
||||||
veya
|
Google ile Devam Et
|
||||||
</span>
|
</Button>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
<Button
|
footer={
|
||||||
type="button"
|
<div className="text-center text-sm">
|
||||||
variant="outline"
|
|
||||||
className="w-full h-11 text-base font-medium bg-card border-border hover:bg-secondary transition-colors"
|
|
||||||
>
|
|
||||||
<Icon icon="flat-color-icons:google" className="w-5 h-5 mr-2" />
|
|
||||||
Google ile Devam Et
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<div className="text-center text-sm mt-6">
|
|
||||||
Zaten hesabınız var mı?{' '}
|
Zaten hesabınız var mı?{' '}
|
||||||
<Link
|
<Link
|
||||||
href="/login"
|
href="/login"
|
||||||
@@ -93,28 +92,8 @@ export default async function RegisterPage({
|
|||||||
Giriş Yap
|
Giriş Yap
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
</div>
|
/>
|
||||||
|
</>
|
||||||
<div className="hidden lg:flex lg:w-1/2 p-4 relative">
|
|
||||||
<div className="relative w-full h-full overflow-hidden rounded-2xl">
|
|
||||||
<img
|
|
||||||
src="/images/1830837_Image.png"
|
|
||||||
alt="MindSpace Background"
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
/>
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-t from-background via-transparent to-background/30 opacity-90" />
|
|
||||||
<div className="absolute bottom-0 flex items-center justify-center pointer-events-none z-10">
|
|
||||||
<div className="relative drop-shadow-2xl flex items-center gap-4">
|
|
||||||
<img
|
|
||||||
src="/logo/logo.png"
|
|
||||||
alt="MindSpace Logo"
|
|
||||||
className="object-contain w-64 h-auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,191 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import type { ReactNode } from "react"
|
||||||
|
import Image from "next/image"
|
||||||
|
import { motion, useReducedMotion } from "framer-motion"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
type AuthPageShellProps = {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
imageSrc: string
|
||||||
|
imageAlt: string
|
||||||
|
imageSide: "left" | "right"
|
||||||
|
form: ReactNode
|
||||||
|
secondaryAction?: ReactNode
|
||||||
|
footer: ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AuthPageShell({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
imageSrc,
|
||||||
|
imageAlt,
|
||||||
|
imageSide,
|
||||||
|
form,
|
||||||
|
secondaryAction,
|
||||||
|
footer,
|
||||||
|
}: AuthPageShellProps) {
|
||||||
|
const reducedMotion = useReducedMotion()
|
||||||
|
|
||||||
|
const stackVariants = {
|
||||||
|
hidden: {},
|
||||||
|
show: {
|
||||||
|
transition: reducedMotion
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
staggerChildren: 0.1,
|
||||||
|
delayChildren: 0.15,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemVariants = {
|
||||||
|
hidden: reducedMotion ? { opacity: 1 } : { opacity: 0, y: 24 },
|
||||||
|
show: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
duration: reducedMotion ? 0 : 0.65,
|
||||||
|
ease: [0.22, 1, 0.36, 1] as const,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const formPanel = (
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { opacity: 0, x: imageSide === "left" ? 36 : -36 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{
|
||||||
|
duration: reducedMotion ? 0 : 0.8,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
}}
|
||||||
|
className="flex flex-1 items-center justify-center p-8 w-full lg:w-1/2"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
variants={stackVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate="show"
|
||||||
|
className="w-full max-w-sm space-y-8"
|
||||||
|
>
|
||||||
|
<motion.div variants={itemVariants} className="text-center lg:text-left">
|
||||||
|
<h1 className="text-3xl font-bold tracking-tight text-foreground">
|
||||||
|
{title}
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm text-muted-foreground mt-2">{description}</p>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div variants={itemVariants}>{form}</motion.div>
|
||||||
|
|
||||||
|
{secondaryAction ? (
|
||||||
|
<motion.div variants={itemVariants}>{secondaryAction}</motion.div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<motion.div variants={itemVariants}>{footer}</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const imagePanel = (
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { opacity: 0, x: imageSide === "left" ? -42 : 42 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{
|
||||||
|
duration: reducedMotion ? 0 : 0.95,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
}}
|
||||||
|
className="hidden lg:flex lg:w-1/2 p-4 relative"
|
||||||
|
>
|
||||||
|
<div className="relative w-full h-full overflow-hidden rounded-2xl">
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { scale: 1.08, filter: "blur(6px)" }}
|
||||||
|
animate={{ scale: 1, filter: "blur(0px)" }}
|
||||||
|
transition={{
|
||||||
|
duration: reducedMotion ? 0 : 1.2,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
}}
|
||||||
|
className="absolute inset-0"
|
||||||
|
>
|
||||||
|
<Image src={imageSrc} alt={imageAlt} fill className="object-cover" priority />
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { opacity: 0 }}
|
||||||
|
animate={{ opacity: 0.9 }}
|
||||||
|
transition={{ duration: reducedMotion ? 0 : 0.9, delay: reducedMotion ? 0 : 0.1 }}
|
||||||
|
className="absolute inset-0 bg-gradient-to-t from-background via-transparent to-background/30"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { opacity: 0, scale: 0.92 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
transition={{
|
||||||
|
duration: reducedMotion ? 0 : 1.1,
|
||||||
|
delay: reducedMotion ? 0 : 0.2,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
}}
|
||||||
|
className="absolute inset-0 bg-[radial-gradient(circle_at_50%_18%,rgba(255,255,255,0.18),transparent_46%)]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { opacity: 0, y: 26 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{
|
||||||
|
duration: reducedMotion ? 0 : 0.85,
|
||||||
|
delay: reducedMotion ? 0 : 0.32,
|
||||||
|
ease: [0.22, 1, 0.36, 1],
|
||||||
|
}}
|
||||||
|
className="absolute bottom-0 left-0 right-0 flex items-center justify-center pointer-events-none z-10"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
animate={
|
||||||
|
reducedMotion
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
y: [0, -8, 0],
|
||||||
|
scale: [1, 1.02, 1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
transition={
|
||||||
|
reducedMotion
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
duration: 8,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
className="relative drop-shadow-2xl flex items-center gap-4"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src="/logo/logo.png"
|
||||||
|
alt="MindSpace Logo"
|
||||||
|
width={256}
|
||||||
|
height={128}
|
||||||
|
className="object-contain w-64 h-auto"
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative isolate flex min-h-screen overflow-hidden bg-background">
|
||||||
|
{imageSide === "left" ? imagePanel : null}
|
||||||
|
{formPanel}
|
||||||
|
{imageSide === "right" ? imagePanel : null}
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={reducedMotion ? false : { opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: reducedMotion ? 0 : 1.4 }}
|
||||||
|
className={cn(
|
||||||
|
"pointer-events-none absolute inset-0 -z-10",
|
||||||
|
"bg-[radial-gradient(circle_at_top,rgba(108,91,176,0.12),transparent_42%)]",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user