Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 10x 428x 428x 428x 428x 428x 202x 202x 428x 15x 14x 428x 15x 15x 428x | import { useState, useEffect } from "react";
import { useStores } from "~/hooks/useStores";
import { CodeInput } from "./CodeInput";
import { IoLogInOutline } from "react-icons/io5";
import { TbLockPassword } from "react-icons/tb";
import { useMutation } from "@tanstack/react-query";
import { Logo } from "./Logo";
export const PairingForm = () => {
const { hub } = useStores();
const [code, setCode] = useState<string[]>(["", "", "", ""]);
const [isInputValid, setIsInputValid] = useState<boolean>(true);
const token = code.join("");
useEffect(() => {
const inputRegex = /^[A-Za-z0-9]{4}$/;
setIsInputValid(token.length === 4 ? inputRegex.test(token) : true);
}, [token]);
const { mutate, isError, isPending, error } = useMutation({
mutationFn: async (pairingCode: string) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
return hub.service.pair(pairingCode);
},
mutationKey: ["PAIR_HUB"],
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
mutate(token);
};
return (
<form
className="max-w-md md:min-w-md bg-base-100 border border-base-300 p-8 rounded-4xl shadow-sm"
onSubmit={handleSubmit}
aria-labelledby="form-title"
>
<Logo />
<fieldset className="fieldset flex flex-col items-stretch gap-4 mt-6">
<legend
id="form-title"
className="fieldset-legend md:text-xl text-lg flex items-center gap-2 mb-4"
>
<TbLockPassword aria-hidden="true" />
<span>Sign in to control devices</span>
</legend>
{isError && (
<p className="text-error text-base" role="alert">
{error.message}
</p>
)}
<label
htmlFor="access-code"
className="fieldset-label text-xl text-base-content"
>
Access Code
</label>
{isPending ? (
<p className="text-accent text-xl font-medium flex gap-2">
<span className="loading loading-spinner loading-lg"></span>{" "}
One moment
</p>
) : (
<CodeInput onCodeChange={setCode} />
)}
<button
type="submit"
className="btn btn-primary btn-xl w-full mt-4 py-7"
disabled={token.length !== 4 || !isInputValid || isPending}
aria-disabled={token.length !== 4 || !isInputValid}
>
<IoLogInOutline aria-hidden="true" />
<span>Connect Hub</span>
</button>
</fieldset>
</form>
);
};
|