235 lines
8.9 KiB
TypeScript
235 lines
8.9 KiB
TypeScript
import type {Route} from "../../../.react-router/types/app/pages/dashboard_sub/+types/DashboardRegister";
|
|
import {flexLeftWeight, iconMStyle, marginRound, maxWidth} from "~/styles";
|
|
import {
|
|
Button,
|
|
Flex,
|
|
Group,
|
|
Image,
|
|
Input,
|
|
Divider,
|
|
PasswordInput,
|
|
Select,
|
|
Stack,
|
|
Text,
|
|
TextInput, Space
|
|
} from "@mantine/core";
|
|
import {useForm} from "@mantine/form";
|
|
import {useState} from "react";
|
|
import AccountIcon from "mdi-react/AccountIcon";
|
|
import LockIcon from "mdi-react/LockIcon";
|
|
import { useNavigate } from "react-router";
|
|
import {apiRegisterPatient} from "~/utils/hms_api";
|
|
import {dateToTimestamp, showErrorMessage, showInfoMessage} from "~/utils/utils";
|
|
import {DateInput} from "@mantine/dates";
|
|
import {DashboardPageType} from "~/utils/hms_enums.ts";
|
|
import CalendarRangeIcon from "mdi-react/CalendarRangeIcon";
|
|
import GenderMaleFemaleIcon from "mdi-react/GenderMaleFemaleIcon";
|
|
import CellphoneIcon from "mdi-react/CellphoneIcon";
|
|
import EmailIcon from "mdi-react/EmailIcon";
|
|
import HomeIcon from "mdi-react/HomeIcon";
|
|
|
|
|
|
|
|
export function meta({}: Route.MetaArgs) {
|
|
return [
|
|
{ title: "Patient Registration" },
|
|
{ name: "description", content: "Patient registration page." },
|
|
];
|
|
}
|
|
|
|
export default function Component() {
|
|
const form = useForm({
|
|
initialValues: {
|
|
userName: '',
|
|
password: '',
|
|
password2: '',
|
|
|
|
name: '',
|
|
title: '',
|
|
birth_date: new Date(2000, 1, 1),
|
|
gender: '',
|
|
phone: '+44 ',
|
|
email: '',
|
|
address: '',
|
|
postcode: ''
|
|
},
|
|
|
|
validate: {
|
|
userName: (value) => {
|
|
if (value.length < 6) return "Username must be at least 6 characters long.";
|
|
if (/^\d+$/.test(value)) return "The username cannot be a pure number";
|
|
return null;
|
|
},
|
|
password: (value) => (/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(value) ? null :
|
|
"The password must be at least 8 characters long and contain both letters and numbers."),
|
|
password2: (value, others) => (value !== others.password ? "The two passwords do not match" : null),
|
|
name: (value) => (value.length < 2 ? "Name is too short" : null),
|
|
title: (value) => (value.length < 2 ? "Title is too short" : null),
|
|
birth_date: (value) => (value > new Date() ? "Date of birth cannot be in the future" : null),
|
|
gender: (value) => (value.length <= 0 ? "Please select your biological sex" : null),
|
|
phone: (value) => (/^\+\d{1,3} \d{7,}$/.test(value) ? null : "Invalid phone number format"),
|
|
email: (value) => (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? null : "Invalid email format"),
|
|
address: (value) => (value.length < 5 ? "Address is too short" : null),
|
|
postcode: (value) => (/^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$/.test(value) ? null : "Invalid postcode format"),
|
|
},
|
|
});
|
|
|
|
const [isLoggingIn, setIsLoggingIn] = useState(false);
|
|
|
|
const navigate = useNavigate();
|
|
|
|
const onClickRegister = (values: {
|
|
userName: string,
|
|
password: string,
|
|
password2: string,
|
|
name: string,
|
|
title: string,
|
|
birth_date: Date,
|
|
gender: string,
|
|
phone: string,
|
|
email: string,
|
|
address: string,
|
|
postcode: string,
|
|
}) => {
|
|
setIsLoggingIn(true)
|
|
const regData = {
|
|
username: values.userName,
|
|
password: values.password,
|
|
name: values.name,
|
|
title: values.title.endsWith(".") ? values.title : values.title + ".",
|
|
birth_date: dateToTimestamp(values.birth_date),
|
|
gender: values.gender,
|
|
phone: values.phone,
|
|
email: values.email,
|
|
address: values.address,
|
|
postcode: values.postcode,
|
|
}
|
|
// console.log(regData)
|
|
|
|
apiRegisterPatient(regData)
|
|
.then((res) => {
|
|
if (!res.success) {
|
|
showErrorMessage(res.message, "Registration failed")
|
|
return
|
|
}
|
|
showInfoMessage("", "Registration successful", 3000)
|
|
navigate(DashboardPageType.LoginPage)
|
|
})
|
|
.catch((e) => showErrorMessage(e.toString(), "Registration error"))
|
|
.finally(() => setIsLoggingIn(false))
|
|
}
|
|
|
|
return (
|
|
<Stack align="stretch" justify="center" gap="md" style={{...flexLeftWeight, "maxWidth": "400px"}}>
|
|
<Text size="1.5em" fw={700}>Patient Register</Text>
|
|
|
|
<form onSubmit={form.onSubmit((values) => onClickRegister(values))}>
|
|
<Divider my="0px" label="Account Info" labelPosition="center" />
|
|
<Stack gap="xs">
|
|
<TextInput
|
|
withAsterisk
|
|
label="Username"
|
|
placeholder="Username"
|
|
leftSection={<AccountIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('userName')}
|
|
/>
|
|
|
|
<PasswordInput
|
|
withAsterisk
|
|
label="Password"
|
|
placeholder="At least 8 characters long and contain both letters and numbers."
|
|
leftSection={<LockIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('password')}
|
|
/>
|
|
|
|
<PasswordInput
|
|
withAsterisk
|
|
label="Input Your Password Again"
|
|
placeholder="Input your password again"
|
|
leftSection={<LockIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('password2')}
|
|
/>
|
|
</Stack>
|
|
|
|
<Space h="xs" />
|
|
<Divider my="0px" label="Patient Info" labelPosition="center" />
|
|
<Stack gap="xs">
|
|
<TextInput
|
|
withAsterisk
|
|
label="Name"
|
|
placeholder="Your full name"
|
|
leftSection={<AccountIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('name')}
|
|
/>
|
|
|
|
<TextInput
|
|
withAsterisk
|
|
label="Title"
|
|
placeholder="eg. Mr./Mrs./Ms./Dr."
|
|
leftSection={<AccountIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('title')}
|
|
/>
|
|
|
|
<DateInput
|
|
withAsterisk
|
|
label="Date of Birth"
|
|
placeholder="Date of Birth"
|
|
valueFormat="DD/MM/YYYY"
|
|
leftSection={<CalendarRangeIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('birth_date')}
|
|
/>
|
|
|
|
<Select
|
|
withAsterisk
|
|
label="Biological Sex"
|
|
data={["M", "F", "Intersex"]}
|
|
defaultValue="F"
|
|
placeholder="Your biological sex"
|
|
leftSection={<GenderMaleFemaleIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('gender')}
|
|
/>
|
|
|
|
<TextInput
|
|
withAsterisk
|
|
label="Phone number"
|
|
placeholder="+44 01234567"
|
|
leftSection={<CellphoneIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('phone')}
|
|
/>
|
|
|
|
<TextInput
|
|
withAsterisk
|
|
label="Email"
|
|
placeholder="abc@example.com"
|
|
leftSection={<EmailIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('email')}
|
|
/>
|
|
|
|
<TextInput
|
|
withAsterisk
|
|
label="Address"
|
|
placeholder="Your home address"
|
|
leftSection={<HomeIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('address')}
|
|
/>
|
|
|
|
<TextInput
|
|
withAsterisk
|
|
label="Postcode"
|
|
placeholder="Your postcode. eg. BS16 1QY"
|
|
leftSection={<HomeIcon style={iconMStyle}/>}
|
|
{...form.getInputProps('postcode')}
|
|
/>
|
|
|
|
<Space h="0px" />
|
|
<Group justify="space-between">
|
|
<Button onClick={() => navigate(DashboardPageType.LoginPage)}>Back to Login</Button>
|
|
<Button type="submit" disabled={isLoggingIn}>Register</Button>
|
|
</Group>
|
|
</Stack>
|
|
</form>
|
|
|
|
</Stack>
|
|
)
|
|
}
|