forked from OpenNeo/impress-2020
Okay so one of the trickiest parts of login is done! 🤞 and now we need to make it actually show up in the UI. (and also pressure-test the security a bit, I've only really checked the happy path!)
187 lines
4.8 KiB
JavaScript
187 lines
4.8 KiB
JavaScript
import { gql, useMutation } from "@apollo/client";
|
|
import {
|
|
Box,
|
|
Button,
|
|
FormControl,
|
|
FormHelperText,
|
|
FormLabel,
|
|
Input,
|
|
Modal,
|
|
ModalBody,
|
|
ModalCloseButton,
|
|
ModalContent,
|
|
ModalHeader,
|
|
ModalOverlay,
|
|
Tab,
|
|
TabList,
|
|
TabPanel,
|
|
TabPanels,
|
|
Tabs,
|
|
} from "@chakra-ui/react";
|
|
import React from "react";
|
|
import { ErrorMessage, getGraphQLErrorMessage } from "../util";
|
|
|
|
export default function LoginModal({ isOpen, onClose }) {
|
|
return (
|
|
<Modal isOpen={isOpen} onClose={onClose}>
|
|
<ModalOverlay />
|
|
<ModalContent>
|
|
<ModalHeader>Welcome back to Dress to Impress! ✨</ModalHeader>
|
|
<ModalCloseButton />
|
|
<Tabs>
|
|
<TabList>
|
|
<Tab>Log in</Tab>
|
|
<Tab>Create account</Tab>
|
|
</TabList>
|
|
<TabPanels>
|
|
<TabPanel>
|
|
<ModalBody>
|
|
<LoginForm onSuccess={() => onClose()} />
|
|
</ModalBody>
|
|
</TabPanel>
|
|
<TabPanel>
|
|
<ModalBody>
|
|
<CreateAccountForm />
|
|
</ModalBody>
|
|
</TabPanel>
|
|
</TabPanels>
|
|
</Tabs>
|
|
</ModalContent>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
function LoginForm({ onSuccess }) {
|
|
const [username, setUsername] = React.useState("");
|
|
const [password, setPassword] = React.useState("");
|
|
|
|
const [
|
|
sendLoginMutation,
|
|
{ loading, error, data, called, reset },
|
|
] = useMutation(gql`
|
|
mutation LoginForm_Login($username: String!, $password: String!) {
|
|
login(username: $username, password: $password) {
|
|
id
|
|
username
|
|
}
|
|
}
|
|
`);
|
|
|
|
return (
|
|
<form
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
sendLoginMutation({
|
|
variables: { username, password },
|
|
})
|
|
.then(({ data }) => {
|
|
if (data?.login != null) {
|
|
onSuccess();
|
|
}
|
|
})
|
|
.catch((e) => {}); // handled in error UI
|
|
}}
|
|
>
|
|
<FormControl>
|
|
<FormLabel>DTI Username</FormLabel>
|
|
<Input
|
|
type="text"
|
|
value={username}
|
|
onChange={(e) => {
|
|
setUsername(e.target.value);
|
|
reset();
|
|
}}
|
|
/>
|
|
<FormHelperText>
|
|
This is separate from your Neopets.com account.
|
|
</FormHelperText>
|
|
</FormControl>
|
|
<Box height="4" />
|
|
<FormControl>
|
|
<FormLabel>DTI Password</FormLabel>
|
|
<Input
|
|
type="password"
|
|
value={password}
|
|
onChange={(e) => {
|
|
setPassword(e.target.value);
|
|
reset();
|
|
}}
|
|
/>
|
|
<FormHelperText>
|
|
Careful, never enter your Neopets password on another site!
|
|
</FormHelperText>
|
|
</FormControl>
|
|
|
|
{error && (
|
|
<ErrorMessage marginTop="4">
|
|
Oops, login failed: "{getGraphQLErrorMessage(error)}". Try again?
|
|
</ErrorMessage>
|
|
)}
|
|
|
|
{called && !loading && !error && data?.login == null && (
|
|
<ErrorMessage marginTop="4">
|
|
We couldn't find a match for that username and password. Try again?
|
|
</ErrorMessage>
|
|
)}
|
|
|
|
<Box marginTop="6" display="flex" alignItems="center">
|
|
<Button size="sm" onClick={() => alert("TODO: Forgot password")}>
|
|
Forgot password?
|
|
</Button>
|
|
<Box flex="1 0 auto" width="4" />
|
|
<Button type="submit" colorScheme="green" isLoading={loading}>
|
|
Log in
|
|
</Button>
|
|
</Box>
|
|
</form>
|
|
);
|
|
}
|
|
|
|
function CreateAccountForm() {
|
|
const onSubmit = (e) => {
|
|
e.preventDefault();
|
|
alert("TODO: Create account!");
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={onSubmit}>
|
|
<FormControl>
|
|
<FormLabel>DTI Username</FormLabel>
|
|
<Input type="text" />
|
|
<FormHelperText>
|
|
This will be separate from your Neopets.com account.
|
|
</FormHelperText>
|
|
</FormControl>
|
|
<Box height="4" />
|
|
<FormControl>
|
|
<FormLabel>DTI Password</FormLabel>
|
|
<Input type="password" />
|
|
<FormHelperText>
|
|
Careful, never use your Neopets password for another site!
|
|
</FormHelperText>
|
|
</FormControl>
|
|
<Box height="4" />
|
|
<FormControl>
|
|
<FormLabel>Confirm DTI Password</FormLabel>
|
|
<Input type="password" />
|
|
<FormHelperText>One more time, to make sure!</FormHelperText>
|
|
</FormControl>
|
|
<Box height="4" />
|
|
<FormControl>
|
|
<FormLabel>Email address</FormLabel>
|
|
<Input type="password" />
|
|
<FormHelperText>
|
|
We'll use this in the future if you need to reset your password, or
|
|
for us to contact you about your account. We won't sell this address,
|
|
and we won't send marketing-y emails.
|
|
</FormHelperText>
|
|
</FormControl>
|
|
<Box height="6" />
|
|
<Box display="flex" justifyContent="flex-end">
|
|
<Button type="submit" colorScheme="green">
|
|
Create account
|
|
</Button>
|
|
</Box>
|
|
</form>
|
|
);
|
|
}
|