DEV Community

Rahul
Rahul

Posted on

Testcraft Studio frontend 30: src/pages/Login.jsx

import React, { useState } from 'react';
import Icon from '../Icon.jsx';
import { teamNames } from '../seed.js';
import { authenticateTeam } from '../access.js';
import { useStudio, log, visibleWorkspaces } from '../store.jsx';
import { Button, Field } from '../ui.jsx';

export default function Login({ navigate }) {
  const { state: s, mutate } = useStudio();
  const [team, setTeam] = useState(s.session.team);
  const [password, setPassword] = useState(''), [show, setShow] = useState(false);
  const [busy, setBusy] = useState(false), [error, setError] = useState('');
  async function login(event) {
    event.preventDefault(); if (busy) return;
    setBusy(true); setError('');
    try {
      const session = await authenticateTeam(s, team, password);
      mutate(d => { d.session = session; d.activeWorkspaceId = visibleWorkspaces(d)[0]?.id || ''; log(d, `Signed in to ${team} as ${session.role === 'administrator' ? 'Administrator' : 'User'}`); });
      setPassword(''); navigate('overview');
    } catch (failure) { setError(failure.message); } finally { setBusy(false); }
  }
  return <div className="login-page">
    <section className="login-story"><div className="login-brand"><span className="brand-symbol"><Icon name="layers" size={29}/></span><span>Testcraft Studio</span></div>
      <div className="login-story-body"><span className="eyebrow">EVIDENCE. CLARITY. CONFIDENCE.</span><h1>Clear evidence.<br/>Confident testing.</h1><p>Bring your system knowledge and change requests together to create traceable test cases.</p>
      </div><div className="login-story-footer">Built for clear decisions at every step.</div>
    </section>
    <section className="login-form-area"><form onSubmit={login}>
      <span className="eyebrow login-eyebrow">TESTCRAFT STUDIO</span><h2>Welcome back</h2><p>Sign in to your workspace.</p>
      <Field label="Team"><div className="login-select-field"><Icon name="users" size={18}/><select value={team} title={teamNames[team] || team} onChange={e => { setTeam(e.target.value); setPassword(''); setError(''); }}>{s.teams.map(t => <option key={t} value={t}>{t}</option>)}</select></div></Field>
      <Field label="System password"><div className="password-field"><Icon name="lock" size={18}/><input type={show ? 'text' : 'password'} required autoComplete="current-password" aria-label="System password" value={password} onChange={e => setPassword(e.target.value)} placeholder="Enter your system password"/><button type="button" onClick={() => setShow(value => !value)} aria-label={show ? 'Hide password' : 'Show password'} title={show ? 'Hide password' : 'Show password'}><Icon name={show ? 'eyeOff' : 'eye'} size={18}/></button></div></Field>
      {error && <p className="form-error" role="alert">{error}</p>}
      <Button type="submit" variant="primary" className="full-width" disabled={busy || !password}>{busy ? 'Signing in…' : 'Sign in'} <Icon name="arrow" size={16}/></Button>
    </form><div className="login-footer">Testcraft Studio</div></section>
  </div>;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)