forked from Goutam/lynkeduppro-crm
Add LynkedUp roofing portal: full login + registration auth UI
- Split-screen dark/orange auth shell with animated scan showcase - Login state machine: social/email, passkey, password, OTP (email/SMS/WhatsApp), TOTP, push, try-another-way, forgot-password, terms gate, success - 4-step registration wizard: Account, Property, Verify, Address - US-default phone + address with /api/geo lookup (PIN auto-fill / search) - Roofing-themed content, Inter font, logo from public/image Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import type { Metadata } from "next";
|
||||
import "@/components/portal/portal.css";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Lynkedup Pro Portal",
|
||||
description:
|
||||
"Official Lynkedup Pro portal — manage your workspace, payments and documents.",
|
||||
};
|
||||
|
||||
export default function PortalLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<div className="portal-root">{children}</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
import { PortalAside, PanelBrand } from "@/components/portal/parts";
|
||||
import { LoginFlow } from "@/components/portal/login-flow";
|
||||
import { CookieBanner } from "@/components/portal/bits";
|
||||
|
||||
export default function LoginPage() {
|
||||
return (
|
||||
<main className="portal-main">
|
||||
<span className="portal-grid" />
|
||||
<div className="portal-split anim-in">
|
||||
<PortalAside />
|
||||
<section className="portal-panel">
|
||||
<div style={{ width: "100%", maxWidth: 420 }}>
|
||||
<PanelBrand />
|
||||
<LoginFlow />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<CookieBanner />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
import { PortalAside, PanelBrand } from "@/components/portal/parts";
|
||||
import { RegisterFlow } from "@/components/portal/register-flow";
|
||||
import { CookieBanner } from "@/components/portal/bits";
|
||||
|
||||
export default function RegisterPage() {
|
||||
return (
|
||||
<main className="portal-main">
|
||||
<span className="portal-grid" />
|
||||
<div className="portal-split anim-in">
|
||||
<PortalAside />
|
||||
<section className="portal-panel">
|
||||
<div style={{ width: "100%", maxWidth: 420 }}>
|
||||
<PanelBrand />
|
||||
<RegisterFlow />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<CookieBanner />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user