Skip to content

Commit

Permalink
Edit meal request form (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
sophie-wjyang authored Aug 6, 2023
1 parent 06505c3 commit a9a48f4
Show file tree
Hide file tree
Showing 4 changed files with 337 additions and 0 deletions.
1 change: 1 addition & 0 deletions frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = {
"react/no-array-index-key": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off",
"@typescript-eslint/no-unused-vars": "off",
"react/function-component-definition": [
"warn",
{
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Button as ChakraButton, Wrap } from "@chakra-ui/react";
import React, { useContext } from "react";
import { useNavigate } from "react-router-dom";

import EditMealRequestForm from "./EditMealRequestForm";

import BackgroundImage from "../../assets/background.png";
import * as Routes from "../../constants/Routes";
import SampleContext from "../../contexts/SampleContext";
Expand Down Expand Up @@ -67,6 +69,7 @@ const Default = (): React.ReactElement => {
/>
<Button text="Edit Team" path={Routes.EDIT_TEAM_PAGE} />
<Button text="Hooks Demo" path={Routes.HOOKS_PAGE} />
<EditMealRequestForm />
</Wrap>
<div style={{ height: "2rem" }} />

Expand Down
315 changes: 315 additions & 0 deletions frontend/src/components/pages/EditMealRequestForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
import {
Button,
Divider,
Flex,
FormControl,
FormLabel,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalOverlay,
Text,
useDisclosure,
} from "@chakra-ui/react";
import React, { useState } from "react";

import { Contact } from "../../types/UserTypes";
import { isValidEmail } from "../../utils/ValidationUtils";
import useIsWebView from "../../utils/useIsWebView";
import OnsiteStaffSection from "../common/OnsiteStaffSection";

const PLACEHOLDER_WEB_EXAMPLE_FULL_NAME = "Jane Doe";
const PLACEHOLDER_WEB_EXAMPLE_PHONE_NUMBER = "111-222-3333";
const PLACEHOLDER_WEB_EXAMPLE_EMAIL = "[email protected]";

const PLACEHOLDER_MOBILE_EXAMPLE_FULL_NAME = "Full Name (Jane Doe)";
const PLACEHOLDER_MOBILE_EXAMPLE_EMAIL = "Email ([email protected])";
const PLACEHOLDER_MOBILE_EXAMPLE_PHONE_NUMBER = "Phone Number (111-222-3333)";

const EditMealRequestForm = () => {
const [primaryContact, setPrimaryContact] = useState<Contact>({
name: "",
phone: "",
email: "",
});
const [onsiteInfo, setOnsiteInfo] = useState<Array<Contact>>([
{
name: "",
phone: "",
email: "",
},
]);

const [attemptedSubmit, setAttemptedSubmit] = useState(false);
const isWebView = useIsWebView();
const { isOpen, onOpen, onClose } = useDisclosure();

const initialFocusRef = React.useRef(null);

const getMobileContactSection = (): React.ReactElement => {
return (
<Flex flexDir="column" gap="8px">
<FormControl isRequired mb={6}>
<FormLabel variant="mobile-form-label-bold">
Primary Contact
</FormLabel>
<Flex flexDir="column" gap="8px">
<FormControl
isRequired
isInvalid={attemptedSubmit && primaryContact.name === ""}
>
<Input
variant="mobile-outline"
value={primaryContact.name}
onChange={(e) =>
setPrimaryContact({ ...primaryContact, name: e.target.value })
}
placeholder={PLACEHOLDER_MOBILE_EXAMPLE_FULL_NAME}
/>
</FormControl>
<FormControl
isRequired
isInvalid={attemptedSubmit && primaryContact.phone === ""}
>
<Input
variant="mobile-outline"
type="tel"
value={primaryContact.phone}
onChange={(e) =>
setPrimaryContact({
...primaryContact,
phone: e.target.value,
})
}
placeholder={PLACEHOLDER_MOBILE_EXAMPLE_PHONE_NUMBER}
/>
</FormControl>
<FormControl
isRequired
isInvalid={attemptedSubmit && !isValidEmail(primaryContact.email)}
>
<Input
variant="mobile-outline"
type="email"
value={primaryContact.email}
onChange={(e) =>
setPrimaryContact({
...primaryContact,
email: e.target.value,
})
}
placeholder={PLACEHOLDER_MOBILE_EXAMPLE_EMAIL}
/>
</FormControl>
</Flex>
</FormControl>
</Flex>
);
};

const getWebContactSection = (): React.ReactElement => {
return (
<>
<Text variant="desktop-heading" pt={4} pb={3}>
Contact Information
</Text>

<Flex flexDir="column" gap="24px">
<Flex flexDir="column">
<FormControl
isRequired
isInvalid={attemptedSubmit && primaryContact.name === ""}
>
<FormLabel
variant={{
base: "mobile-form-label-bold",
md: "form-label-bold",
}}
>
Primary contact name
</FormLabel>
<Input
value={primaryContact.name}
placeholder={PLACEHOLDER_WEB_EXAMPLE_FULL_NAME}
onChange={(e) =>
setPrimaryContact({ ...primaryContact, name: e.target.value })
}
/>
</FormControl>
</Flex>

<Flex flexDir="row" gap="24px">
<Flex flexDir="column" w="240px">
<FormControl
isRequired
isInvalid={attemptedSubmit && primaryContact.phone === ""}
mb={6}
>
<FormLabel
variant={{
base: "mobile-form-label-bold",
md: "form-label-bold",
}}
>
Phone number
</FormLabel>
<Input
type="tel"
value={primaryContact.phone}
placeholder={PLACEHOLDER_WEB_EXAMPLE_PHONE_NUMBER}
onChange={(e) =>
setPrimaryContact({
...primaryContact,
phone: e.target.value,
})
}
/>
</FormControl>
</Flex>

<Flex flexDir="column" w="519px">
<FormControl
isRequired
isInvalid={
attemptedSubmit && !isValidEmail(primaryContact.email)
}
>
<FormLabel
variant={{
base: "mobile-form-label-bold",
md: "form-label-bold",
}}
>
Email address
</FormLabel>
<Input
type="email"
value={primaryContact.email}
placeholder={PLACEHOLDER_WEB_EXAMPLE_EMAIL}
onChange={(e) =>
setPrimaryContact({
...primaryContact,
email: e.target.value,
})
}
/>
</FormControl>
</Flex>
</Flex>
</Flex>
</>
);
};

return (
<>
<Button onClick={onOpen}>Edit Meal Request</Button>
<Modal
initialFocusRef={initialFocusRef}
isOpen={isOpen}
onClose={onClose}
>
<ModalOverlay />
<ModalContent
maxWidth={{ base: "100%", md: "900px" }}
padding={{ base: "10px", md: "40px" }}
>
<Text
pb={{ base: 1, md: 5 }}
pl={{ base: 6, md: 6 }}
pt={{ base: 5, md: 8 }}
variant={{ base: "mobile-display-xl", md: "desktop-display-xl" }}
>
Edit Meal Request
</Text>
<ModalCloseButton />
<ModalBody pb={6}>
<Text
variant={{
base: "mobile-heading",
md: "desktop-heading",
}}
>
Meal Information
</Text>

<FormControl mt={3} mb={6} isRequired>
<FormLabel
variant={{
base: "mobile-form-label-bold",
md: "form-label-bold",
}}

// TODO: Hook this up to a state variable
// TODO: Setup correct validation for this
// isInvalid={attemptedSubmit && }
>
Number of meals
</FormLabel>
<Input ref={initialFocusRef} w="200px" placeholder="Ex. 100" />
</FormControl>

<FormControl mt={3} mb={6} isRequired>
<FormLabel
variant={{
base: "mobile-form-label-bold",
md: "form-label-bold",
}}

// TODO: Hook this up to a state variable
// TODO: Setup correct validation for this
// isInvalid={attemptedSubmit && }
>
Dietary restrictions
</FormLabel>
<Input placeholder="Ex. Nut allergy, gluten free" />
</FormControl>

<FormControl mt={3} mb={6} isRequired>
<FormLabel
variant={{
base: "mobile-form-label-bold",
md: "form-label-bold",
}}
// TODO: Hook this up to a state variable
// TODO: Setup correct validation for this
// isInvalid={attemptedSubmit && }
>
Delivery Notes
</FormLabel>
<Input placeholder="Ex. Nut allergy, gluten free" />
<br />
</FormControl>
{isWebView && <Divider />}
{isWebView ? getWebContactSection() : getMobileContactSection()}

<OnsiteStaffSection
onsiteInfo={onsiteInfo}
setOnsiteInfo={setOnsiteInfo}
attemptedSubmit={attemptedSubmit}
/>
</ModalBody>

<ModalFooter>
<Button onClick={onClose} mr={3} variant="outline">
Cancel
</Button>
<Button
colorScheme="blue"
onClick={() => {
setAttemptedSubmit(true);
}}
>
Save
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
);
};

export default EditMealRequestForm;
18 changes: 18 additions & 0 deletions frontend/src/setupTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,21 @@
// "normal .ts file."
// eslint-disable-next-line import/no-extraneous-dependencies
import "@testing-library/jest-dom";

// To fix issue in some tests with not finding "matchMedia"
// https://stackoverflow.com/questions/39830580/jest-test-fails-typeerror-window-matchmedia-is-not-a-function
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
// https://github.com/facebook/create-react-app/issues/10126
Object.defineProperty(window, "matchMedia", {
writable: true,
value: (query: any) => ({

Check warning on line 17 in frontend/src/setupTests.ts

View workflow job for this annotation

GitHub Actions / run-lint

Unexpected any. Specify a different type
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // Deprecated
removeListener: jest.fn(), // Deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
}),
});

0 comments on commit a9a48f4

Please sign in to comment.