Files
cloudlense/website-monitoring-frontend/src/app/auth/page.tsx
T
Dennis 14a32bdc0d feat: initialize monorepo with full dev team best practices
- Unified monorepo with backend (Express), frontend (Next.js), and devops
- Backend: ESLint, Prettier, Jest tests (3 passing), health endpoint, .env.example
- Frontend: Fixed build errors, fixed all lint errors (0 remaining), tests passing
- DevOps: Docker Compose with PostgreSQL, backend, frontend + healthchecks
- CI/CD: 3 GitHub Actions workflows (backend, frontend, docker integration)
- DX: Husky pre-commit hooks with smart change detection
- Docs: Root README with architecture, CONTRIBUTING.md, PR template

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-06 00:05:50 +01:00

149 lines
5.4 KiB
TypeScript

"use client";
import { AuthForm } from "@/components/auth/AuthForm";
import { Shield, ArrowLeft } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/contexts/AuthContext";
export default function AuthPage() {
const searchParams = useSearchParams();
const source = searchParams.get("source");
const email = searchParams.get("email");
const [mounted, setMounted] = useState(false);
const router = useRouter();
const { user } = useAuth();
useEffect(() => {
setMounted(true);
if (user) {
router.push("/dashboard");
}
}, [user, router]);
return (
<div className="relative min-h-screen flex items-center justify-center overflow-hidden bg-gradient-to-br from-gray-50 to-white p-4">
{/* Animated background elements */}
<div className="absolute inset-0 overflow-hidden">
<div className="absolute inset-0 bg-grid-pattern opacity-[0.02]" />
{mounted && (
<>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 0.5 }}
transition={{ duration: 1 }}
className="absolute top-0 -left-4 w-[500px] h-[500px] bg-gradient-to-br from-blue-400/20 to-indigo-400/20 rounded-full blur-3xl"
style={{ filter: "blur(120px)" }}
/>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 0.5 }}
transition={{ duration: 1, delay: 0.2 }}
className="absolute bottom-0 -right-4 w-[500px] h-[500px] bg-gradient-to-br from-purple-400/20 to-pink-400/20 rounded-full blur-3xl"
style={{ filter: "blur(120px)" }}
/>
</>
)}
</div>
{/* Main content container */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.1 }}
className="relative w-full max-w-lg mx-auto"
>
{/* Logo and name above the card */}
<div className="absolute top-[-40px] left-1/2 transform -translate-x-1/2 flex items-center space-x-2">
<Shield className="h-8 w-8 text-blue-600" />
<span className="text-2xl font-semibold bg-clip-text text-transparent bg-gradient-to-r from-blue-600 to-indigo-600">
CloudLense
</span>
</div>
{/* Glass card effect */}
<div className="relative backdrop-blur-xl bg-white/80 rounded-2xl shadow-xl border border-white/20 overflow-hidden">
{/* Card header */}
<div className="px-8 pt-8">
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
className="flex items-center justify-between"
>
<div
className="flex items-center space-x-4 cursor-pointer transition-transform transform hover:scale-110"
onClick={() => router.push("/")}
>
<div className="flex items-center space-x-2">
<ArrowLeft className="h-4 w-4 text-blue-600" />
<span className="text-sm font-medium text-blue-600">
Back to Home
</span>
</div>
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.3 }}
className="mt-6 mb-4"
>
<h1 className="text-2xl font-bold text-gray-900">
{source === "hero" ? "Get Started" : "Welcome"}
</h1>
<p className="mt-2 text-gray-600">
{source === "hero"
? "Set up your account in seconds"
: "Sign in to continue to your dashboard"}
</p>
</motion.div>
</div>
{/* Form section */}
<div className="p-8">
<AuthForm initialEmail={email} />
</div>
{/* Footer */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.4 }}
className="px-8 pb-8 text-center"
>
<p className="text-sm text-gray-500">
By continuing, you agree to our{" "}
<a href="#" className="text-blue-600 hover:underline">
Terms
</a>{" "}
and{" "}
<a href="#" className="text-blue-600 hover:underline">
Privacy Policy
</a>
</p>
</motion.div>
</div>
{/* Decorative elements */}
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, delay: 0.5 }}
className="absolute -z-10 inset-0 border border-blue-100 rounded-2xl -m-2"
/>
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5, delay: 0.6 }}
className="absolute -z-10 inset-0 border border-blue-50 rounded-2xl -m-4"
/>
</motion.div>
</div>
);
}