submit by hitting next
This commit is contained in:
parent
c956db367f
commit
672b62b3ef
@ -1,5 +1,5 @@
|
|||||||
import { Button, FormField, Input, SpaceBetween } from "@cloudscape-design/components";
|
import { Button, FormField, Icon, Input, SpaceBetween } from "@cloudscape-design/components";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
// COPIED FROM SERVER
|
// COPIED FROM SERVER
|
||||||
export enum IAuthMode {
|
export enum IAuthMode {
|
||||||
@ -13,31 +13,38 @@ export interface IAuthComponentProps {
|
|||||||
authMode: IAuthMode,
|
authMode: IAuthMode,
|
||||||
secret: string | null;
|
secret: string | null;
|
||||||
onUnlock: () => void;
|
onUnlock: () => void;
|
||||||
onError: (res: any) => void;
|
onError?: (res: any) => void;
|
||||||
|
runCheck?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AuthComponent = ({ door, secret, authMode, onError, onUnlock }: IAuthComponentProps) => {
|
export const AuthComponent = ({ door, secret, authMode, onError, onUnlock, runCheck }: IAuthComponentProps) => {
|
||||||
const [ key, setKey ] = useState(secret);
|
const [ key, setKey ] = useState(secret);
|
||||||
|
const [ error, setError ] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (runCheck) {
|
||||||
|
onSubmit();
|
||||||
|
}
|
||||||
|
}, [runCheck])
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
fetch(`/api/door/${door}/auth?key=${key}&rotatingKey=${key}`)
|
||||||
|
.then(async res => {
|
||||||
|
if (res.status !== 200) {
|
||||||
|
setError("Incorrect PIN");
|
||||||
|
onError && onError(await res.json());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onUnlock();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SpaceBetween size='l'>
|
<SpaceBetween size='l'>
|
||||||
<FormField label={"PIN"} constraintText={"Enter the PIN to unlock the door"}>
|
<FormField errorText={error} label={"PIN"} constraintText={"Enter the PIN to unlock the door"}>
|
||||||
<Input readOnly={secret !== null} value={key || ""} onChange={({ detail }) => setKey(detail.value)} />
|
<Input readOnly={secret !== null} value={key || ""} onChange={({ detail }) => setKey(detail.value)} />
|
||||||
</FormField>
|
</FormField>
|
||||||
<Button
|
|
||||||
onClick={() =>
|
|
||||||
fetch(`/api/door/${door}/auth?key=${key}&rotatingKey=${key}`)
|
|
||||||
.then(async res => {
|
|
||||||
if (res.status !== 200) {
|
|
||||||
onError(await res.json());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onUnlock();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Unlock the door
|
|
||||||
</Button>
|
|
||||||
</SpaceBetween>
|
</SpaceBetween>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,12 +35,16 @@ export function DoorPage() {
|
|||||||
const secret = searchParams.get('key') || searchParams.get('rotatingKey');
|
const secret = searchParams.get('key') || searchParams.get('rotatingKey');
|
||||||
const [ alerts, setAlerts ] = useState<FlashbarProps.MessageDefinition[]>([]);
|
const [ alerts, setAlerts ] = useState<FlashbarProps.MessageDefinition[]>([]);
|
||||||
const [ polling, setPolling ] = useState(false);
|
const [ polling, setPolling ] = useState(false);
|
||||||
const [ inProgressAlert, setInProgressAlert ] = useState("");
|
const [ submitPin, setSubmitPin ] = useState(0);
|
||||||
|
|
||||||
const dismissAlert = (id: string) => {
|
const dismissAlert = (id: string) => {
|
||||||
setAlerts(alerts => alerts.filter(alert => alert.id !== id));
|
setAlerts(alerts => alerts.filter(alert => alert.id !== id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dismissInProgressAlerts = () => {
|
||||||
|
setAlerts(alerts => alerts.filter(alert => alert.type !== 'in-progress'));
|
||||||
|
}
|
||||||
|
|
||||||
const createAlert = (type: FlashbarProps.Type, content: ReactNode): FlashbarProps.MessageDefinition => {
|
const createAlert = (type: FlashbarProps.Type, content: ReactNode): FlashbarProps.MessageDefinition => {
|
||||||
const id = `${Math.random()}`;
|
const id = `${Math.random()}`;
|
||||||
return {
|
return {
|
||||||
@ -54,7 +58,7 @@ export function DoorPage() {
|
|||||||
|
|
||||||
const addAlert = (type: FlashbarProps.Type, content: ReactNode): string => {
|
const addAlert = (type: FlashbarProps.Type, content: ReactNode): string => {
|
||||||
const newAlert = createAlert(type, content);
|
const newAlert = createAlert(type, content);
|
||||||
setAlerts([
|
setAlerts(alerts => [
|
||||||
newAlert,
|
newAlert,
|
||||||
...alerts,
|
...alerts,
|
||||||
]);
|
]);
|
||||||
@ -77,13 +81,16 @@ export function DoorPage() {
|
|||||||
setStep(3);
|
setStep(3);
|
||||||
setPolling(false);
|
setPolling(false);
|
||||||
setAlerts(alerts =>
|
setAlerts(alerts =>
|
||||||
[createAlert("success", "Buzzer successfully unlocked"), ...alerts.filter(alert => alert.id !== inProgressAlert)]
|
[createAlert("success", "Buzzer successfully unlocked"), ...alerts.filter(alert => alert.type !== 'in-progress')]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
return () => clearInterval(timer);
|
return () => {
|
||||||
|
clearInterval(timer);
|
||||||
|
dismissInProgressAlerts();
|
||||||
|
}
|
||||||
}, [polling]);
|
}, [polling]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -131,8 +138,15 @@ export function DoorPage() {
|
|||||||
}}
|
}}
|
||||||
activeStepIndex={step}
|
activeStepIndex={step}
|
||||||
onNavigate={({ detail }) => {
|
onNavigate={({ detail }) => {
|
||||||
|
if (detail.requestedStepIndex < step) {
|
||||||
|
dismissInProgressAlerts();
|
||||||
|
setSubmitPin(0);
|
||||||
|
setPolling(false);
|
||||||
|
setStep(detail.requestedStepIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (detail.requestedStepIndex === 2) {
|
if (detail.requestedStepIndex === 2) {
|
||||||
addAlert("error", "You must unlock the door to proceed");
|
setSubmitPin(submitPin + 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +158,8 @@ export function DoorPage() {
|
|||||||
}}
|
}}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setStep(0);
|
setStep(0);
|
||||||
|
dismissInProgressAlerts();
|
||||||
|
setSubmitPin(0);
|
||||||
}}
|
}}
|
||||||
steps={[
|
steps={[
|
||||||
{
|
{
|
||||||
@ -174,14 +190,13 @@ export function DoorPage() {
|
|||||||
>
|
>
|
||||||
<AuthComponent
|
<AuthComponent
|
||||||
authMode={IAuthMode.FIXED_PIN}
|
authMode={IAuthMode.FIXED_PIN}
|
||||||
|
runCheck={submitPin}
|
||||||
door={door}
|
door={door}
|
||||||
secret={secret}
|
secret={secret}
|
||||||
onError={(res) => {
|
|
||||||
addAlert("error", "Authentication failed, double check the credentials");
|
|
||||||
}}
|
|
||||||
onUnlock={() => {
|
onUnlock={() => {
|
||||||
setStep(2);
|
setStep(2);
|
||||||
const inprogAlert = addAlert("in-progress", (
|
dismissInProgressAlerts();
|
||||||
|
addAlert("in-progress", (
|
||||||
<CountdownBar
|
<CountdownBar
|
||||||
timeSeconds={doorResponse.timeout}
|
timeSeconds={doorResponse.timeout}
|
||||||
onExpiry={() => {
|
onExpiry={() => {
|
||||||
@ -192,7 +207,6 @@ export function DoorPage() {
|
|||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
setInProgressAlert(inprogAlert);
|
|
||||||
setPolling(true);
|
setPolling(true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user