+61
-3
src/pages/Login.tsx
+61
-3
src/pages/Login.tsx
···
1
1
import { useState, useRef, useEffect } from "react";
2
2
import "actor-typeahead";
3
-
import { Heart, Upload, Search, ArrowRight, AlertCircle } from "lucide-react";
3
+
import {
4
+
Heart,
5
+
Upload,
6
+
Search,
7
+
ArrowRight,
8
+
AlertCircle,
9
+
Info,
10
+
} from "lucide-react";
4
11
import FireflyLogo from "../assets/at-firefly-logo.svg?react";
5
12
import { useFormValidation } from "../hooks/useFormValidation";
6
13
import { validateHandle } from "../lib/validation";
···
20
27
}: LoginPageProps) {
21
28
const inputRef = useRef<HTMLInputElement>(null);
22
29
const [isSubmitting, setIsSubmitting] = useState(false);
30
+
const [strippedAtMessage, setStrippedAtMessage] = useState(false);
23
31
24
32
const { fields, setValue, validate, getFieldProps } = useFormValidation({
25
33
handle: "",
26
34
});
27
35
36
+
// Sync typeahead selection with form state
37
+
useEffect(() => {
38
+
const input = inputRef.current;
39
+
if (!input) return;
40
+
41
+
const handleInputChange = () => {
42
+
let value = input.value.trim();
43
+
44
+
// Strip leading @ if present
45
+
if (value.startsWith("@")) {
46
+
value = value.substring(1);
47
+
input.value = value;
48
+
49
+
// Show message once
50
+
if (!strippedAtMessage) {
51
+
setStrippedAtMessage(true);
52
+
setTimeout(() => setStrippedAtMessage(false), 3000);
53
+
}
54
+
}
55
+
56
+
// Update form state
57
+
setValue("handle", value);
58
+
};
59
+
60
+
// Listen for input, change, and blur events to catch typeahead selections
61
+
input.addEventListener("input", handleInputChange);
62
+
input.addEventListener("change", handleInputChange);
63
+
input.addEventListener("blur", handleInputChange);
64
+
65
+
return () => {
66
+
input.removeEventListener("input", handleInputChange);
67
+
input.removeEventListener("change", handleInputChange);
68
+
input.removeEventListener("blur", handleInputChange);
69
+
};
70
+
}, [setValue, strippedAtMessage]);
71
+
28
72
const handleSubmit = async (e: React.FormEvent) => {
29
73
e.preventDefault();
30
74
31
-
// Get the value directly from the input
32
-
const currentHandle = inputRef.current?.value || fields.handle.value;
75
+
// Get the value directly from the input (in case form state is stale)
76
+
let currentHandle = (inputRef.current?.value || fields.handle.value).trim();
77
+
78
+
// Strip leading @ one more time to be sure
79
+
if (currentHandle.startsWith("@")) {
80
+
currentHandle = currentHandle.substring(1);
81
+
}
82
+
33
83
setValue("handle", currentHandle);
34
84
35
85
// Validate
···
158
208
disabled={isSubmitting}
159
209
/>
160
210
</actor-typeahead>
211
+
{strippedAtMessage && (
212
+
<div className="mt-2 flex items-center gap-2 text-sm text-cyan-700 dark:text-cyan-300">
213
+
<Info className="w-4 h-4 flex-shrink-0" />
214
+
<span>
215
+
No need for the @ symbol - we've removed it for you!
216
+
</span>
217
+
</div>
218
+
)}
161
219
{fields.handle.touched && fields.handle.error && (
162
220
<div
163
221
id="handle-error"