Files
igny8/frontend/src/pages/AuthPages/SignUp.tsx
IGNY8 VPS (Salman) 839260a7db singup for, styling
2026-01-17 05:55:52 +00:00

131 lines
4.6 KiB
TypeScript

import { useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import PageMeta from "../../components/common/PageMeta";
import SignUpFormUnified from "../../components/auth/SignUpFormUnified";
interface Plan {
id: number;
name: string;
slug: string;
price: string | number;
billing_cycle: string;
is_active: boolean;
max_users: number;
max_sites: number;
max_keywords: number;
max_ahrefs_queries: number;
included_credits: number;
features: string[];
}
export default function SignUp() {
const planSlug = useMemo(() => {
const params = new URLSearchParams(window.location.search);
return params.get("plan") || "";
}, []);
const [plans, setPlans] = useState<Plan[]>([]);
const [plansLoading, setPlansLoading] = useState(true);
const [selectedPlan, setSelectedPlan] = useState<Plan | null>(null);
// NOTE: Geo detection removed per payment system refactor
// Country is now selected via dropdown in the signup form
// Payment method selection happens on /account/plans after registration
useEffect(() => {
const fetchPlans = async () => {
setPlansLoading(true);
try {
const API_BASE_URL = import.meta.env.VITE_BACKEND_URL || "https://api.igny8.com/api";
const res = await fetch(`${API_BASE_URL}/v1/auth/plans/`);
const data = await res.json();
const allPlans = data?.results || [];
// Show all active plans (including free plan)
const publicPlans = allPlans
.filter((p: Plan) => p.is_active)
.sort((a: Plan, b: Plan) => {
const priceA = typeof a.price === 'number' ? a.price : parseFloat(String(a.price || 0));
const priceB = typeof b.price === 'number' ? b.price : parseFloat(String(b.price || 0));
return priceA - priceB;
});
setPlans(publicPlans);
// Auto-select plan from URL or default to first plan
if (planSlug) {
const plan = publicPlans.find((p: Plan) => p.slug === planSlug);
if (plan) {
setSelectedPlan(plan);
} else {
setSelectedPlan(publicPlans[0] || null);
}
} else {
setSelectedPlan(publicPlans[0] || null);
}
} catch (e) {
console.error('Failed to load plans:', e);
} finally {
setPlansLoading(false);
}
};
fetchPlans();
}, [planSlug]);
return (
<>
<PageMeta
title="Sign Up - IGNY8"
description="Create your IGNY8 account and start building topical authority with AI-powered content"
/>
<div className="min-h-screen bg-white dark:bg-gray-900">
<div className="flex h-screen overflow-hidden">
{/* Left Side - Signup Form */}
<SignUpFormUnified
plans={plans}
selectedPlan={selectedPlan}
onPlanSelect={setSelectedPlan}
plansLoading={plansLoading}
/>
{/* Right Side - Pricing Plans */}
<div className="hidden lg:flex lg:w-1/2 bg-brand-950 dark:bg-white/5 p-8 xl:p-12 items-center justify-center relative">
{/* GridShape Background */}
<div className="absolute inset-0 flex items-center justify-center">
<div className="relative flex items-center justify-center z-1 w-full h-full">
<div className="absolute inset-0">
<svg className="w-full h-full opacity-40" viewBox="0 0 100 100" preserveAspectRatio="none">
<defs>
<pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(255,255,255,0.1)" strokeWidth="0.5"/>
</pattern>
</defs>
<rect width="100" height="100" fill="url(#grid)" />
</svg>
</div>
</div>
</div>
{/* Logo - Top Right - Smaller */}
<Link to="/" className="absolute top-6 right-6 z-10">
<img
src="/images/logo/IGNY8_DARK_LOGO.png"
alt="IGNY8"
className="h-8 w-auto"
/>
</Link>
<div className="w-full max-w-[840px] relative z-10">
{/* Pricing Plans Component Will Load Here */}
<div id="signup-pricing-plans" className="w-full">
{/* Plans will be rendered by SignUpFormUnified */}
</div>
</div>
</div>
</div>
</div>
</>
);
}