92 lines
2.6 KiB
TypeScript

import { Button, Form, FormField, Icon, Input, SpaceBetween } from "@cloudscape-design/components";
import { useEffect, useState } from "react";
import { AuthRequest, AuthRequestSchema } from "../../../doorman-schema/src";
import { fetchUrlEncoded } from "../helpers/FetchHelper";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import CInput from "react-hook-form-cloudscape/components/input";
// COPIED FROM SERVER
export enum IAuthMode {
FIXED_PIN = "Fixed Pin",
RANDOM_ROTATING_KEY = "Random Rotating Key",
}
export interface IAuthComponentProps {
door: string,
authMode: IAuthMode,
secret: string | null;
onUnlock: () => void;
onError?: (res: any) => void;
runCheck?: number;
}
export const AuthComponent = ({ door, secret, authMode, onError, onUnlock, runCheck }: IAuthComponentProps) => {
const { control, setError, formState, handleSubmit, setValue, getValues } = useForm<AuthRequest>({
resolver: zodResolver(AuthRequestSchema),
defaultValues: {
key: secret || "",
door,
}
});
const [isLoading, setLoading] = useState(false);
const onSubmit = async (body: AuthRequest) => {
setLoading(true);
await fetchUrlEncoded('/api/door/auth', body)
.then(async res => {
if (res.status !== 200) {
setError("key", { type: "validate", message: "Incorrect PIN"});
onError && onError(await res.json());
return;
}
onUnlock();
});
setLoading(false);
};
useEffect(() => {
// don't allow us to submit while we are submitting
if (runCheck && !isLoading) {
handleSubmit(onSubmit)();
}
}, [runCheck]);
// try and submit on load if the pin is passed in by query params
useEffect(() => {
setLoading(true);
fetch('https://api.ipify.org?format=json')
.then(response => response.json())
.then(data => {
return data.ip;
})
.catch(error => {
console.log('Error:', error);
return "null";
})
.then(async ip => {
setValue("ip", ip);
// if the key is there, then try submitting right away
if (secret !== null) {
await handleSubmit(onSubmit)();
}
setLoading(false);
});
}, [secret]);
return (
<>
<SpaceBetween size='l'>
<FormField errorText={formState.errors.key?.message} label={"PIN"} constraintText={"Enter the PIN to unlock the door"}>
<CInput type="password" name="key" readOnly={secret !== null} control={control} />
</FormField>
</SpaceBetween>
</>
);
}