Catalyst / admin/Apex 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Apex

public

Bid Management and Orchestration Tool with AI Capability

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
Apex / Synapse-Apexv2 / frontend / src / pages / Login.tsx 3125 B · main
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { useState } from "react";
import { api, setToken } from "../lib/api";
import { useAuth } from "../lib/auth";

export default function Login({ forceChange = false }: { forceChange?: boolean }) {
  const { refresh } = useAuth();
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [otp, setOtp] = useState("");
  const [mfaStep, setMfaStep] = useState(false);
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);

  // forced password change (must_change_password)
  const [newPw, setNewPw] = useState("");
  const [curPw, setCurPw] = useState("");

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    setErr("");
    setBusy(true);
    try {
      const res = await api.post("/auth/login", { email, password, otp: otp || undefined });
      if (res.mfa_required) {
        setMfaStep(true);
        setBusy(false);
        return;
      }
      setToken(res.access_token);
      await refresh();
    } catch (e: any) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  }

  async function changePassword(e: React.FormEvent) {
    e.preventDefault();
    setErr("");
    try {
      await api.post("/auth/change-password", { current_password: curPw, new_password: newPw });
      await refresh();
    } catch (e: any) {
      setErr(e.message);
    }
  }

  if (forceChange) {
    return (
      <div className="login-wrap">
        <form className="card login-card" onSubmit={changePassword}>
          <h1>Set a new password</h1>
          <p className="muted">Your account requires a password change before continuing.</p>
          <label>Current password</label>
          <input type="password" value={curPw} onChange={(e) => setCurPw(e.target.value)} />
          <label>New password</label>
          <input type="password" value={newPw} onChange={(e) => setNewPw(e.target.value)} />
          {err && <div className="err">{err}</div>}
          <button style={{ marginTop: 14 }}>Update password</button>
        </form>
      </div>
    );
  }

  return (
    <div className="login-wrap">
      <form className="card login-card" onSubmit={submit}>
        <div className="row" style={{ marginBottom: 8 }}>
          <img src="/icon.svg" width={36} height={36} alt="" />
          <h1 style={{ margin: 0 }}>Synapse-Apex</h1>
        </div>
        <p className="muted">Sign in to the bid workspace.</p>
        <label>Email</label>
        <input value={email} onChange={(e) => setEmail(e.target.value)} autoFocus />
        <label>Password</label>
        <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
        {mfaStep && (
          <>
            <label>Authentication code</label>
            <input value={otp} onChange={(e) => setOtp(e.target.value)} placeholder="6-digit or recovery code" autoFocus />
          </>
        )}
        {err && <div className="err">{err}</div>}
        <button style={{ marginTop: 14, width: "100%" }} disabled={busy}>
          {mfaStep ? "Verify" : "Sign in"}
        </button>
      </form>
    </div>
  );
}