<commit_before>import { Alert, Button, Checkbox, Input } from "antd";
import { CSSProperties, useEffect, useRef, useState } from "react";
import SquareLogo from "components/logo-square";
import useCustomize from "lib/use-customize";
import A from "components/misc/A";
import {
  len,
  is_valid_email_address as isValidEmailAddress,
} from "@cocalc/util/misc";
import apiPost from "lib/api/post";
import SSO, { Strategy } from "./sso";
import { LOGIN_STYLE } from "./shared";
import Loading from "components/share/loading";

const LINE = { margin: "15px 0" } as CSSProperties;

interface Props {
  strategies?: Strategy[];
  minimal?: boolean; // use a minimal interface with less explanation and instructions (e.g., for embedding in other pages)
  requiresToken?: boolean; // will be determined by API call if not given.
  onSuccess?: () => void; // if given, call after sign up *succeeds*.
}

export default function SignUp({
  strategies,
  requiresToken,
  minimal,
  onSuccess,
}: Props) {
  const {
    anonymousSignup,
    siteName,
    emailSignup,
    accountCreationInstructions,
  } = useCustomize();
  const [terms, setTerms] = useState<boolean>(false);
  const [email, setEmail] = useState<string>("");
  const [registrationToken, setRegistrationToken] = useState<string>("");
  const [password, setPassword] = useState<string>("");
  const [firstName, setFirstName] = useState<string>("");
  const [lastName, setLastName] = useState<string>("");
  const [signingUp, setSigningUp] = useState<boolean>(false);
  const [issues, setIssues] = useState<{
    email?: string;
    password?: string;
    terms?: string;
    error?: string;
    registrationToken?: string;
  }>({});

  const submittable = useRef<boolean>(false);

  // Sometimes the user if this component knows requiresToken and sometimes they don't.
  // If they don't, we have to make an API call to figure it out.
  const [requiresToken2, setRequiresToken2] = useState<boolean | undefined>(
    requiresToken
  );
  useEffect(() => {
    if (requiresToken2 === undefined) {
      (async () => {
        try {
          setRequiresToken2(await apiPost("/auth/requires-token"));
        } catch (err) {}
      })();
    }
  }, []);

  const [strategies2, setStrategies2] = useState<Strategy[] | undefined>(
    strategies
  );
  useEffect(() => {
    if (strategies2 === undefined) {
      (async () => {
        try {
          setStrategies2(await apiPost("/auth/sso-strategies"));
        } catch (err) {}
      })();
    }
  }, []);

  if (requiresToken2 === undefined || strategies2 === undefined) {
    return <Loading />;
  }

  submittable.current = !!(
    terms &&
    (!requiresToken2 || registrationToken) &&
    email &&
    isValidEmailAddress(email) &&
    password &&
    firstName &&
    lastName
  );

  async function signUp() {
    if (!submittable.current) return;
    if (signingUp) return;
    setIssues({});
    try {
      setSigningUp(true);
      const result = await apiPost("/auth/sign-up", {
        terms,
        email,
        password,
        firstName,
        lastName,
        registrationToken,
      });
      if (result.issues && len(result.issues) > 0) {
        setIssues(result.issues);
      } else {
        onSuccess?.();
      }
    } catch (err) {
      setIssues({ error: `${err}` });
    } finally {
      setSigningUp(false);
    }
  }

  if (!emailSignup && strategies2.length == 0) {
    return (
      <Alert
        style={{ margin: "30px 15%" }}
        type="error"
        showIcon
        message={"No Account Creation Allowed"}
        description={
          <div style={{ fontSize: "14pt", marginTop: "20px" }}>
            <b>
              There is no method enabled for creating an account on this server.
            </b>
            {anonymousSignup && (
              <>
                <br />
                <br />
                However, you can still{" "}
                <A href="/auth/try">
                  try {siteName} without creating an account.
                </A>
              </>
            )}
          </div>
        }
      />
    );
  }

  return (
    <div style={{ padding: "0 15px" }}>
      {!minimal && (
        <div style={{ textAlign: "center", marginBottom: "15px" }}>
          <SquareLogo
            style={{ width: "100px", height: "100px", marginBottom: "15px" }}
          />
          <h1>Create a {siteName} Account</h1>
          {accountCreationInstructions}
        </div>
      )}

      <div style={LOGIN_STYLE}>
        <TermsCheckbox
          onChange={setTerms}
          style={{
            marginTop: "10px",
            marginBottom: terms ? "10px" : undefined,
            fontSize: "12pt",
            color: "#666",
          }}
        />
        <form>
          {issues.registrationToken && (
            <Alert
              style={LINE}
              type="error"
              showIcon
              message={issues.registrationToken}
              description={
                <>
                  You may have to contact the site administrator for a
                  registration token.
                </>
              }
            />
          )}<commit_msg>fix bug in terms checkbox<commit_after>import { Alert, Button, Checkbox, Input } from "antd";
import { CSSProperties, useEffect, useRef, useState } from "react";
import SquareLogo from "components/logo-square";
import useCustomize from "lib/use-customize";
import A from "components/misc/A";
import {
  len,
  is_valid_email_address as isValidEmailAddress,
} from "@cocalc/util/misc";
import apiPost from "lib/api/post";
import SSO, { Strategy } from "./sso";
import { LOGIN_STYLE } from "./shared";
import Loading from "components/share/loading";

const LINE = { margin: "15px 0" } as CSSProperties;

interface Props {
  strategies?: Strategy[];
  minimal?: boolean; // use a minimal interface with less explanation and instructions (e.g., for embedding in other pages)
  requiresToken?: boolean; // will be determined by API call if not given.
  onSuccess?: () => void; // if given, call after sign up *succeeds*.
}

export default function SignUp({
  strategies,
  requiresToken,
  minimal,
  onSuccess,
}: Props) {
  const {
    anonymousSignup,
    siteName,
    emailSignup,
    accountCreationInstructions,
  } = useCustomize();
  const [terms, setTerms] = useState<boolean>(false);
  const [email, setEmail] = useState<string>("");
  const [registrationToken, setRegistrationToken] = useState<string>("");
  const [password, setPassword] = useState<string>("");
  const [firstName, setFirstName] = useState<string>("");
  const [lastName, setLastName] = useState<string>("");
  const [signingUp, setSigningUp] = useState<boolean>(false);
  const [issues, setIssues] = useState<{
    email?: string;
    password?: string;
    terms?: string;
    error?: string;
    registrationToken?: string;
  }>({});

  const submittable = useRef<boolean>(false);

  // Sometimes the user if this component knows requiresToken and sometimes they don't.
  // If they don't, we have to make an API call to figure it out.
  const [requiresToken2, setRequiresToken2] = useState<boolean | undefined>(
    requiresToken
  );
  useEffect(() => {
    if (requiresToken2 === undefined) {
      (async () => {
        try {
          setRequiresToken2(await apiPost("/auth/requires-token"));
        } catch (err) {}
      })();
    }
  }, []);

  const [strategies2, setStrategies2] = useState<Strategy[] | undefined>(
    strategies
  );
  useEffect(() => {
    if (strategies2 === undefined) {
      (async () => {
        try {
          setStrategies2(await apiPost("/auth/sso-strategies"));
        } catch (err) {}
      })();
    }
  }, []);

  if (requiresToken2 === undefined || strategies2 === undefined) {
    return <Loading />;
  }

  submittable.current = !!(
    terms &&
    (!requiresToken2 || registrationToken) &&
    email &&
    isValidEmailAddress(email) &&
    password &&
    firstName &&
    lastName
  );

  async function signUp() {
    if (!submittable.current) return;
    if (signingUp) return;
    setIssues({});
    try {
      setSigningUp(true);
      const result = await apiPost("/auth/sign-up", {
        terms,
        email,
        password,
        firstName,
        lastName,
        registrationToken,
      });
      if (result.issues && len(result.issues) > 0) {
        setIssues(result.issues);
      } else {
        onSuccess?.();
      }
    } catch (err) {
      setIssues({ error: `${err}` });
    } finally {
      setSigningUp(false);
    }
  }

  if (!emailSignup && strategies2.length == 0) {
    return (
      <Alert
        style={{ margin: "30px 15%" }}
        type="error"
        showIcon
        message={"No Account Creation Allowed"}
        description={
          <div style={{ fontSize: "14pt", marginTop: "20px" }}>
            <b>
              There is no method enabled for creating an account on this server.
            </b>
            {anonymousSignup && (
              <>
                <br />
                <br />
                However, you can still{" "}
                <A href="/auth/try">
                  try {siteName} without creating an account.
                </A>
              </>
            )}
          </div>
        }
      />
    );
  }

  return (
    <div style={{ padding: "0 15px" }}>
      {!minimal && (
        <div style={{ textAlign: "center", marginBottom: "15px" }}>
          <SquareLogo
            style={{ width: "100px", height: "100px", marginBottom: "15px" }}
          />
          <h1>Create a {siteName} Account</h1>
          {accountCreationInstructions}
        </div>
      )}

      <div style={LOGIN_STYLE}>
        <TermsCheckbox
          onChange={setTerms}
          checked={terms}
          style={{
            marginTop: "10px",
            marginBottom: terms ? "10px" : undefined,
            fontSize: "12pt",
            color: "#666",
          }}
        />
        <form>
          {issues.registrationToken && (
            <Alert
              style={LINE}
              type="error"
              showIcon
              message={issues.registrationToken}
              description={
                <>
                  You may have to contact the site administrator for a
                  registration token.
                </>
              }
            />
          )}
{'fraction_non_alphanumeric': 0.13687150837988826, 'fraction_numerical': 0.009439414371026777, 'mean_word_length': 2.112410071942446, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3861672', 'n_tokens_mistral': 3087, 'n_tokens_neox': 3010, 'n_words': 773}