151 lines
3.4 KiB
TypeScript
151 lines
3.4 KiB
TypeScript
import React from "react";
|
|
import { cn } from "~/lib/utils";
|
|
|
|
interface LoginLayoutProps {
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
}
|
|
|
|
export function LoginLayout({ children, className }: LoginLayoutProps) {
|
|
return (
|
|
<div className={cn("min-h-screen flex", className)} dir="ltr">
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface LoginContentProps {
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
}
|
|
|
|
export function LoginContent({ children, className }: LoginContentProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"flex-1 flex items-center justify-center p-4 sm:p-8",
|
|
className,
|
|
)}
|
|
style={{
|
|
background:
|
|
"linear-gradient(135deg, var(--color-login-dark-start) 0%, var(--color-login-dark-end) 100%)",
|
|
}}
|
|
>
|
|
<div className="w-full max-w-md space-y-8">{children}</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface LoginSidebarProps {
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
}
|
|
|
|
export function LoginSidebar({ children, className }: LoginSidebarProps) {
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"hidden lg:flex lg:w-2/5 relative overflow-hidden",
|
|
className,
|
|
)}
|
|
style={{
|
|
backgroundColor: "var(--color-login-primary)",
|
|
}}
|
|
>
|
|
<div className="absolute inset-0 flex flex-col justify-between p-8">
|
|
{children}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface LoginHeaderProps {
|
|
title: string;
|
|
subtitle: string;
|
|
description?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function LoginHeader({
|
|
title,
|
|
subtitle,
|
|
description,
|
|
className,
|
|
}: LoginHeaderProps) {
|
|
return (
|
|
<div className={cn(" space-y-4 flex text-right flex-col", className)}>
|
|
<div className="space-y-2">
|
|
<h1 className="text-white text-lg font-medium font-persian">{title}</h1>
|
|
<h2 className="text-white text-2xl sm:text-3xl font-bold font-persian leading-relaxed">
|
|
{subtitle}
|
|
</h2>
|
|
{description && (
|
|
<p className="text-slate-300 text-sm font-persian leading-relaxed mx-auto">
|
|
{description}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface LoginBrandingProps {
|
|
brandName: string;
|
|
companyName: string;
|
|
logo?: React.ReactNode;
|
|
className?: string;
|
|
}
|
|
|
|
export function LoginBranding({
|
|
brandName,
|
|
companyName,
|
|
logo,
|
|
className,
|
|
}: LoginBrandingProps) {
|
|
return (
|
|
<>
|
|
{/* Top Logo */}
|
|
<div className="flex justify-end">
|
|
<div className="text-slate-800 font-persian">
|
|
<div className="text-lg font-bold leading-tight">
|
|
{brandName.split("\n").map((line, index) => (
|
|
<React.Fragment key={index}>
|
|
{line}
|
|
{index === 0 && <br />}
|
|
</React.Fragment>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bottom Section */}
|
|
<div className="flex items-end justify-between">
|
|
<div className="text-slate-800 text-sm font-persian leading-relaxed max-w-xs">
|
|
{companyName}
|
|
</div>
|
|
|
|
{/* Logo */}
|
|
{logo && <div className="flex items-center">{logo}</div>}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
interface LoginFormContainerProps {
|
|
children: React.ReactNode;
|
|
onSubmit: (e: React.FormEvent) => void;
|
|
className?: string;
|
|
}
|
|
|
|
export function LoginFormContainer({
|
|
children,
|
|
onSubmit,
|
|
className,
|
|
}: LoginFormContainerProps) {
|
|
return (
|
|
<form onSubmit={onSubmit} className={cn("space-y-6", className)}>
|
|
{children}
|
|
</form>
|
|
);
|
|
}
|