"use client" import type React from "react" import { useState, useEffect } from "react" import { Card, CardContent, CardHeader, CardFooter, CardTitle, CardDescription } from "@/components/ui/card" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Button } from "@/components/ui/button" import { Switch } from "@/components/ui/switch" import Link from "next/link" import { motion, AnimatePresence } from "framer-motion" import { UserPlus, UserCog, Heart, AlertCircle, CheckCircle2, Mail, Lock, User } from "lucide-react" import { useRouter } from "next/navigation" import validator from "validator" import PasswordValidator from "password-validator" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" export default function Signup() { const router = useRouter() const [formType, setFormType] = useState<"initial" | "create" | "migrate">("initial") const [formData, setFormData] = useState({ name: "", emailUsername: "", emailDomain: "librecloud.cc", password: "", terms: false, migratePassword: "", migrateTerms: false, migrateName: "", }) const [isValid, setIsValid] = useState(false) const [validationMessage, setValidationMessage] = useState("") const [isSubmitting, setIsSubmitting] = useState(false) const fadeInOut = { initial: { opacity: 0, y: 20 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -20 }, transition: { duration: 0.3 }, } const handleInputChange = (e: React.ChangeEvent) => { const { name, value, type, checked } = e.target setFormData((prev) => ({ ...prev, [name]: type === "checkbox" ? checked : value, })) } useEffect(() => { if (formType === "create") { const { name, emailUsername, emailDomain, password, terms } = formData const isNameValid = name.length >= 2 const isEmailValid = validateEmail(emailUsername, emailDomain) const isPasswordValid = validatePassword(password) setIsValid(isNameValid && isEmailValid && isPasswordValid && terms) if (!isNameValid) setValidationMessage("Enter your name") else if (!isEmailValid) setValidationMessage("Enter a valid email address") else if (!isPasswordValid) setValidationMessage("Weak Password") else if (!terms) setValidationMessage("Accept the terms") else setValidationMessage("Create Account") } else if (formType === "migrate") { const { emailUsername, emailDomain, migratePassword, migrateTerms, migrateName } = formData const isEmailValid = validateEmail(emailUsername, emailDomain) const isPasswordValid = validatePassword(migratePassword) const isNameValid = migrateName.length >= 2 setIsValid(isEmailValid && isPasswordValid && migrateTerms && isNameValid) if (!isNameValid) setValidationMessage("Enter your name") else if (!isEmailValid) setValidationMessage("Enter a valid email address") else if (!isPasswordValid) setValidationMessage("Weak Password") else if (!migrateTerms) setValidationMessage("Accept the terms") else setValidationMessage("Migrate Account") } }, [formData, formType]) const getButtonIcon = () => { if (isValid) return if (validationMessage.includes("name")) return if (validationMessage.includes("email")) return if (validationMessage.includes("Password")) return if (validationMessage.includes("terms")) return return null } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setIsSubmitting(true) try { const email = `${formData.emailUsername}@${formData.emailDomain}` const response = await fetch("/api/users/create", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ name: formType === "create" ? formData.name : formData.migrateName, email: email, password: formType === "create" ? formData.password : formData.migratePassword, migrate: formType === "migrate", }), }) const data = await response.json() if (data.success) { router.push("/account/signup/success") } else { setValidationMessage(data.message || "Failed to create account. Please try again.") } } catch (error) { console.log("[!] " + error) setValidationMessage("An error occurred. Please contact us (see the sidebar)") } finally { setIsSubmitting(false) } } function validateEmail(username: string, domain: string) { return username.length > 0 && domain.length > 0 && validator.isEmail(`${username}@${domain}`) } function validatePassword(password: string) { const passwordSchema = new PasswordValidator() passwordSchema.is().min(8).is().max(128).has().letters().has().digits().has().not().spaces() return passwordSchema.validate(password) } return (
Account Setup Create a new account or migrate an existing one. {formType === "initial" && ( )} {formType === "create" && (
@

Password must be 8-64 characters long, include letters and digits, and not contain spaces.

setFormData((prev) => ({ ...prev, terms: checked }))} />
)} {formType === "migrate" && (
@

A username for Authentik will be generated based on your email. Contact support if a username isn't available.

Password must be 8-64 characters long, include letters and digits, and not contain spaces.

setFormData((prev) => ({ ...prev, migrateTerms: checked }))} />
)}
{formType !== "initial" ? ( ) : ( Welcome to the LibreCloud family! )}
) }