CoolFace
Apppublic

DataScope26/WEB

sourceHugging Faceupdated 7d agoView on Hugging Face
0likes
WaitlistAdmin.jsx125 linesDownload Raw Back to pages
1import { useEffect, useState } from "react";2import axiosClient from "../services/axiosClient.js";3import { getCookie } from "../utils/cookieUtils.js";4import "./WaitlistAdmin.css";5 6const getToken = () =>7  sessionStorage.getItem("token") ||8  localStorage.getItem("token") ||9  getCookie("datascope_token");10 11export default function WaitlistAdmin() {12  const [entries, setEntries] = useState([]);13  const [loading, setLoading] = useState(true);14  const [error, setError] = useState("");15  const [busyEmail, setBusyEmail] = useState("");16 17  const fetchWaitlist = async () => {18    const token = getToken();19 20    if (!token) {21      setError("No hay sesión activa.");22      setLoading(false);23      return;24    }25 26    try {27      setLoading(true);28      const response = await axiosClient.get("/admin/waitlist", {29        headers: { Authorization: token },30      });31 32      setEntries(Array.isArray(response.data) ? response.data : []);33      setError("");34    } catch (err) {35      setError(err?.response?.data?.error || "No se pudo cargar la waitlist.");36    } finally {37      setLoading(false);38    }39  };40 41  useEffect(() => {42    fetchWaitlist();43  }, []);44 45  const updateEntry = async (type, email) => {46    const token = getToken();47 48    if (!token || !email) return;49 50    setBusyEmail(email);51 52    try {53      await axiosClient.post(54        `/admin/waitlist/${type}`,55        { email },56        { headers: { Authorization: token } }57      );58 59      await fetchWaitlist();60    } catch (err) {61      setError(62        err?.response?.data?.error ||63          `No se pudo ${type === "approve" ? "aprobar" : "rechazar"} la solicitud.`64      );65    } finally {66      setBusyEmail("");67    }68  };69 70  return (71    <div className="waitlist-admin">72      <div className="waitlist-admin__header">73        <div>74          <p className="waitlist-admin__eyebrow">Developer</p>75          <h1>Waitlist</h1>76        </div>77        <span className="waitlist-admin__count">{entries.length} pendientes</span>78      </div>79 80      {loading ? (81        <div className="waitlist-admin__state">Cargando solicitudes...</div>82      ) : error ? (83        <div className="waitlist-admin__state waitlist-admin__state--error">{error}</div>84      ) : entries.length === 0 ? (85        <div className="waitlist-admin__empty">No hay solicitudes pendientes.</div>86      ) : (87        <div className="waitlist-admin__list">88          {entries.map((entry) => (89            <article key={entry.id ?? entry.email} className="waitlist-admin__card">90              <div className="waitlist-admin__meta">91                <h2>{entry.name || "Sin nombre"}</h2>92                <p>{entry.email}</p>93                {entry.linkedin && (94                  <a href={entry.linkedin} target="_blank" rel="noreferrer">95                    LinkedIn96                  </a>97                )}98              </div>99 100              <div className="waitlist-admin__actions">101                <button102                  type="button"103                  className="waitlist-admin__button waitlist-admin__button--approve"104                  onClick={() => updateEntry("approve", entry.email)}105                  disabled={busyEmail === entry.email}106                >107                  {busyEmail === entry.email ? "Procesando..." : "Aprobar"}108                </button>109                <button110                  type="button"111                  className="waitlist-admin__button waitlist-admin__button--reject"112                  onClick={() => updateEntry("reject", entry.email)}113                  disabled={busyEmail === entry.email}114                >115                  Rechazar116                </button>117              </div>118            </article>119          ))}120        </div>121      )}122    </div>123  );124}125