2025-04-30 17:28:58 +01:00

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>
)
}