CoolFace
Apppublic

DataScope26/WEB

sourceHugging Faceupdated 7d agoView on Hugging Face
0likes
RegisterModal.jsx239 linesDownload Raw Back to components
1import "./RegisterModal.css";2import { Eye, EyeOff, AtSign, Loader, CheckCircle } from "lucide-react";3import { useState, useEffect } from "react";4import { useAuth } from "../context/AuthContext.jsx";5import ButtonPrimary from "./ButtonPrimary.jsx";6import ButtonClose from "./ButtonClose.jsx";7 8export default function RegisterModal({ onClose, onOpenLogin }) {9  const [username, setUsername] = useState("");10  const [password, setPassword] = useState("");11  const [email, setEmail] = useState("");12  const [rememberMe, setRememberMe] = useState(false);13  const [showPassword, setShowPassword] = useState(false);14  const [isLoading, setIsLoading] = useState(false);15  const [isSuccess, setIsSuccess] = useState(false); // Nuevo estado para la lista de espera16 17  const [message, setMessage] = useState("");18  const [messageKey, setMessageKey] = useState(0);19 20  const [passwordChecklist, setPasswordChecklist] = useState({21    length: false,22    special: false,23    uppercaseLowercase: false24  });25 26  const { signup } = useAuth();27 28  useEffect(() => {29    const currentPassword = password || "";30    setPasswordChecklist({31      length: currentPassword.length >= 8,32      special: /[$&+,:;=?@#|'<>.-^*()%!]/.test(currentPassword),33      uppercaseLowercase:34        currentPassword !== currentPassword.toUpperCase() &&35        currentPassword !== currentPassword.toLowerCase()36    });37  }, [password]);38 39  const checkEmail = () => {40    setMessage("");41    if (email.length < 5) {42      setMessage("El correo debe tener al menos 5 caracteres");43      return false;44    }45    const parts = email.split("@");46    if (parts.length !== 2) {47      setMessage("Falta el símbolo @");48      return false;49    }50    const [localPart, domain] = parts;51    const localPartRegex = /^[A-Za-z0-9](?:[A-Za-z0-9._%+-]*[A-Za-z0-9])?$/;52    if (!localPartRegex.test(localPart)) {53      setMessage("Parte del correo antes del @ inválida");54      return false;55    }56    const domainRegex = /^[a-zA-Z]{2,10}\.[A-Za-z]{2,5}(\.[A-Za-z]{2,3})?$/;57    if (!domainRegex.test(domain)) {58      setMessage("Dominio del correo inválido");59      return false;60    }61    return true;62  };63 64  const checkPassword = () => {65    const currentPassword = password || "";66    if (currentPassword.length < 8) return false;67    if (!/[$&+,:;=?@#|'<>.-^*()%!]/.test(currentPassword)) return false;68    if (currentPassword === currentPassword.toUpperCase() || currentPassword === currentPassword.toLowerCase()) return false;69    return true;70  };71 72  const handleSubmit = async () => {73    setIsLoading(true);74 75    if (username.length < 3) {76      setMessage("El nombre de usuario debe tener al menos 3 caracteres");77      setMessageKey((prev) => prev + 1);78      setIsLoading(false);79      return;80    }81 82    try {83      if (checkEmail() && checkPassword()) {84        setMessage("");85 86        const result = await signup(username, email, password, rememberMe);87 88        if (result === true) {89          setIsSuccess(true);90        } else if (result?.status === 409) {91          setMessage("Ya estás registrado o en la lista de espera");92          setMessageKey((prev) => prev + 1);93        } else {94          setMessage("Hubo un error al procesar tu solicitud");95          setMessageKey((prev) => prev + 1);96        }97      } else {98        setMessageKey((prev) => prev + 1);99      }100    } catch (error) {101      console.error("Error durante el registro:", error);102      setMessage("Ocurrió un error al intentar registrarte");103      setMessageKey((prev) => prev + 1);104    } finally {105      setIsLoading(false);106    }107  };108 109  const getChecklistColor = (isValid) => {110    if (!password) return "#808080";111    return isValid ? "#22c55e" : "#ef4444";112  };113 114  return (115    <>116      <div className="modal-backdrop" onClick={onClose} />117      <div118        className="register-modal"119        onKeyDown={(e) => {120          if (e.key === "Enter" && !isSuccess) {121            handleSubmit();122          }123        }}124      >125        <ButtonClose onClick={onClose} />126 127        <div className="register-modal__layout">128          <aside className="register-modal__story">129            <p className="register-modal__eyebrow">Cupos limitados</p>130            <h1>Acceso Anticipado</h1>131            <p className="register-modal__copy">132              Datascope se lanza primero para un grupo reducido. Vas a poder usar el producto, opinar sobre lo que construimos y moldear la versión final antes que nadie más.133            </p>134            <ul className="register-modal__benefits">135              <li>Creá una compañía con el tier especial de <strong>Acceso Anticipado</strong>.</li>136              <li>Invitá hasta <strong>4 empleados adicionales</strong> a tu empresa.</li>137              <li>Accedé a todas las herramientas de nuestra <strong>extensión</strong>.</li>138            </ul>139          </aside>140 141          <div className="register-modal__form">142            {isSuccess ? (143              <div className="success-state" style={{ textAlign: "center", padding: "2rem 1rem" }}>144                <CheckCircle size={48} color="#22c55e" style={{ margin: "0 auto 1rem" }} />145                <h2>¡Solicitud enviada!</h2>146                <p>Estamos revisando tu pedido.</p>147              </div>148            ) : (149              <>150                <div className="input-group">151                  <label>NOMBRE COMPLETO</label>152                  <input153                    type="text"154                    placeholder="Ingresa tu nombre"155                    value={username}156                    onChange={(e) => setUsername(e.target.value)}157                    maxLength={50}158                  />159                </div>160 161                <div className="input-group">162                  <label>EMAIL CORPORATIVO</label>163                  <div className="input-icon">164                    <input165                      type="email"166                      placeholder="nombre@compania.com"167                      value={email}168                      onChange={(e) => setEmail(e.target.value)}169                      maxLength={50}170                    />171                    <AtSign size={18} className="icon" />172                  </div>173                </div>174 175                <div className="input-group">176                  <label>CONTRASEÑA</label>177                  <div className="input-icon">178                    <input179                      type={showPassword ? "text" : "password"}180                      placeholder="••••••••"181                      value={password}182                      onChange={(e) => setPassword(e.target.value)}183                      maxLength={50}184                    />185                    {showPassword ? (186                      <EyeOff size={18} className="icon" style={{ cursor: "pointer" }} onClick={() => setShowPassword(!showPassword)} />187                    ) : (188                      <Eye size={18} className="icon" style={{ cursor: "pointer" }} onClick={() => setShowPassword(!showPassword)} />189                    )}190                  </div>191                  <div className="password-checklist">192                    <div style={{ color: getChecklistColor(passwordChecklist.length) }}>193                      {passwordChecklist.length ? "☑" : "☐"} Contraseña tiene al menos 8 caracteres194                    </div>195                    <div style={{ color: getChecklistColor(passwordChecklist.special) }}>196                      {passwordChecklist.special ? "☑" : "☐"} Contraseña contiene al menos 1 caracter especial197                    </div>198                    <div style={{ color: getChecklistColor(passwordChecklist.uppercaseLowercase) }}>199                      {passwordChecklist.uppercaseLowercase ? "☑" : "☐"} Contraseña tiene al menos 1 mayuscula y 1 minuscula200                    </div>201                  </div>202                </div>203 204                {message && (205                  <p key={messageKey} className="error-text error-text--animated">206                    {message}207                  </p>208                )}209 210                {isLoading ? (211                  <ButtonPrimary className="register-btn" type="button" style={{ cursor: "default" }}>212                    <Loader size={18} className="loader-icon-animation" />213                  </ButtonPrimary>214                ) : (215                  <ButtonPrimary className="register-btn" onClick={() => handleSubmit()}>216                    Quiero mi lugar217                  </ButtonPrimary>218                )}219 220                <p className="bottom-text">221                  ¿Ya tenes una cuenta?{" "}222                  <span223                    onClick={() => {224                      onOpenLogin();225                      onClose();226                    }}227                  >228                    Inicia sesion229                  </span>230                </p>231                <p className="copyright">© 2026 DataScope</p>232              </>233            )}234          </div>235        </div>236      </div>237    </>238  );239}