Files
neta/components/auth/auth-page-shell.tsx
T
Poyraz 24fcdf9a77 feat: add new UI components and improve existing ones
- Introduced `Field` and `Label` components for better form handling.
- Refactored `Input` and `Textarea` components to use forward refs and improved styling.
- Updated `PendingSubmitButton` to use the new `Button` component.
- Enhanced `Skeleton` component for better layout handling.
- Revamped `Toast` component to support live regions and improved accessibility.
- Updated sidebar configuration to use typed icons.
- Added phase 3 UI boundary checks to prevent usage of deprecated imports.
- Implemented new authentication action handler for better cookie management.
- Improved setup logic for freelancer accounts with repair functionality.
2026-07-10 22:47:02 +03:00

167 lines
5.7 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 type { ReactNode } from "react";
import Image from "next/image";
import Link from "next/link";
import { motion, useReducedMotion } from "framer-motion";
import {
ArrowUpRight,
BarChart3,
CalendarDays,
Kanban,
Wallet,
} from "lucide-react";
type AuthPageShellProps = {
title: string;
description: string;
imageSrc?: string;
imageAlt?: string;
imageSide?: "left" | "right";
form: ReactNode;
secondaryAction?: ReactNode;
footer: ReactNode;
};
const highlights = [
{ label: "Müşteriler", icon: Kanban },
{ label: "Takvim", icon: CalendarDays },
{ label: "Finans", icon: Wallet },
{ label: "Raporlar", icon: BarChart3 },
];
export function AuthPageShell({
title,
description,
form,
secondaryAction,
footer,
}: AuthPageShellProps) {
const reducedMotion = useReducedMotion();
const fadeUp = {
initial: reducedMotion ? false : { opacity: 0, y: 18 },
animate: { opacity: 1, y: 0 },
transition: {
duration: reducedMotion ? 0 : 0.55,
ease: [0.22, 1, 0.36, 1] as const,
},
};
return (
<main className="min-h-screen bg-background text-foreground">
<div className="grid min-h-screen grid-cols-1 lg:grid-cols-[minmax(0,1fr)_480px]">
<motion.section
initial={reducedMotion ? false : { opacity: 0, x: -28 }}
animate={{ opacity: 1, x: 0 }}
transition={{
duration: reducedMotion ? 0 : 0.75,
ease: [0.22, 1, 0.36, 1],
}}
className="relative hidden overflow-hidden bg-primary text-primary-foreground lg:flex lg:flex-col lg:justify-between"
>
<div className="absolute inset-0 opacity-20 bg-[linear-gradient(rgba(255,255,255,.18)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,.18)_1px,transparent_1px)] bg-size-[32px_32px]" />
<div className="relative z-10 flex items-center gap-4 p-10">
<Image
src="/logo/lightLogoLong.png"
alt="Neta"
width={240}
height={64}
className="h-16 w-auto object-contain"
style={{ width: "auto" }}
priority
/>
</div>
<div className="relative z-10 px-10">
<motion.div {...fadeUp}>
<h1 className="max-w-2xl text-5xl font-semibold leading-[1.02] text-primary-foreground">
Freelancer işlerini, müşterilerini ve finansını tek yerde yönet.
</h1>
<p className="mt-6 max-w-xl text-lg leading-8 text-primary-foreground/78">
Neta, günlük operasyonunu, projelerini, side projectlerini ve
temel finans durumunu sade raporlarla takip etmen için
tasarlanır.
</p>
</motion.div>
<motion.div
initial={reducedMotion ? false : { opacity: 0, y: 18 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: reducedMotion ? 0 : 0.55, delay: 0.16 }}
className="mt-10 grid max-w-xl grid-cols-2 gap-3"
>
{highlights.map((item) => {
const Icon = item.icon;
return (
<div
key={item.label}
className="flex items-center gap-3 rounded-sm border border-white/18 bg-white/10 px-4 py-3 text-sm font-medium backdrop-blur"
>
<Icon className="h-4 w-4" />
{item.label}
</div>
);
})}
</motion.div>
</div>
<div className="w-full relative z-10 p-10 text-sm text-primary-foreground/78">
<span>Açık kaynak ve self-host edilebilir.</span>{" "}
<Link
href="https://github.com/poyrazavsever/neta"
className="font-semibold text-primary-foreground underline-offset-4 hover:underline"
target="_blank"
>
GitHub <ArrowUpRight className="h-3.5 w-3.5 inline" />
</Link>
<span> üzerinden ulaşabilirsin. </span>
<Link
href="https://poyrazavsever.com"
className="inline-flex items-center gap-1 font-semibold text-primary-foreground underline-offset-4 hover:underline"
target="_blank"
>
Poyraz Avsever <ArrowUpRight className="h-3.5 w-3.5 inline" />
</Link>
<span> tarafından kodlandı.</span>
</div>
</motion.section>
<section className="flex min-h-screen items-center justify-center px-6 py-8 lg:px-12">
<motion.div
initial={reducedMotion ? false : { opacity: 0, y: 18 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: reducedMotion ? 0 : 0.6, delay: 0.08 }}
className="w-full max-w-sm"
>
<div className="mb-8 flex justify-center lg:hidden">
<Image
src="/logo/blackLogoLong.png"
alt="Neta logo"
width={180}
height={56}
className="h-14 w-auto object-contain"
style={{ width: "auto" }}
priority
/>
</div>
<div className="space-y-2 text-center lg:text-left">
<h2 className="text-3xl font-semibold tracking-normal text-foreground">
{title}
</h2>
<p className="text-sm leading-6 text-muted-foreground">{description}</p>
</div>
<div className="mt-8 space-y-6">
{form}
{secondaryAction}
{footer}
</div>
</motion.div>
</section>
</div>
</main>
);
}