File size: 4,337 Bytes
198828b
 
652b4c9
 
 
507f3f7
198828b
652b4c9
198828b
652b4c9
 
 
198828b
652b4c9
 
198828b
507f3f7
 
198828b
507f3f7
652b4c9
507f3f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652b4c9
 
198828b
 
652b4c9
 
 
 
 
 
 
 
 
 
 
 
198828b
652b4c9
198828b
 
652b4c9
507f3f7
652b4c9
 
 
 
 
 
 
 
 
 
 
 
507f3f7
652b4c9
 
507f3f7
652b4c9
507f3f7
652b4c9
507f3f7
 
 
 
 
652b4c9
 
507f3f7
652b4c9
 
507f3f7
652b4c9
507f3f7
 
652b4c9
 
 
 
 
507f3f7
652b4c9
 
 
 
507f3f7
 
 
 
652b4c9
 
198828b
652b4c9
198828b
 
 
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import React, { useState } from 'react';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Card } from './ui/card';
import { toast } from 'sonner';
import clareAvatar from '../assets/dfe44dab3ad8cd93953eac4a3e68bd1a5f999653.png';
import type { User } from '../App';

interface LoginScreenProps {
  onLogin: (user: User) => void;
}

export function LoginScreen({ onLogin }: LoginScreenProps) {
  const [showForm, setShowForm] = useState(false);
  const [name, setName] = useState('');
  const [emailOrId, setEmailOrId] = useState('');
  const [submitting, setSubmitting] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const n = name.trim();
    const uid = emailOrId.trim();

    if (!n || !uid) return;

    setSubmitting(true);
    try {
      // HF Space: same-origin call is correct (your FastAPI serves the SPA)
      const resp = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: n, user_id: uid }),
      });

      const data = await resp.json().catch(() => ({}));

      if (!resp.ok || !data?.ok) {
        const msg = data?.error || `Login failed (HTTP ${resp.status})`;
        throw new Error(msg);
      }

      // Keep your existing App flow: user = { name, email }
      onLogin({ name: data.user?.name ?? n, email: data.user?.user_id ?? uid });
      toast.success('Signed in');
    } catch (err: any) {
      toast.error(err?.message || 'Login failed');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="min-h-screen bg-background flex items-center justify-center p-4">
      <Card className="w-full max-w-md p-8">
        <div className="flex flex-col items-center space-y-6">
          {/* Clare Avatar */}
          <div className="w-24 h-24 rounded-full overflow-hidden bg-white flex items-center justify-center">
            <img src={clareAvatar} alt="Clare AI" className="w-full h-full object-cover" />
          </div>

          {/* Welcome Text */}
          <div className="text-center space-y-2">
            <h1 className="text-2xl">Welcome to Clare</h1>
            <p className="text-sm text-muted-foreground">
              Your AI teaching assistant for personalized learning
            </p>
          </div>

          {!showForm ? (
            <Button onClick={() => setShowForm(true)} className="w-full" size="lg">
              Sign In
            </Button>
          ) : (
            <form onSubmit={handleSubmit} className="w-full space-y-4">
              <div className="space-y-2">
                <Label htmlFor="login-name">Name</Label>
                <Input
                  id="login-name"
                  value={name}
                  onChange={(e) => setName(e.target.value)}
                  placeholder="Enter your name"
                  required
                  disabled={submitting}
                />
              </div>

              <div className="space-y-2">
                <Label htmlFor="login-userid">Email / Student ID</Label>
                <Input
                  id="login-userid"
                  // IMPORTANT: allow non-email IDs
                  type="text"
                  value={emailOrId}
                  onChange={(e) => setEmailOrId(e.target.value)}
                  placeholder="Enter your email or ID"
                  required
                  disabled={submitting}
                />
              </div>

              <div className="flex gap-2">
                <Button type="submit" className="flex-1" disabled={submitting}>
                  {submitting ? 'Signing in…' : 'Enter'}
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => setShowForm(false)}
                  disabled={submitting}
                >
                  Cancel
                </Button>
              </div>

              <div className="text-xs text-muted-foreground">
                This sign-in is for session identification only (name + ID), used to personalize tutoring and log events.
              </div>
            </form>
          )}
        </div>
      </Card>
    </div>
  );
}