diff --git a/frontend/src/app/vsr/page.module.css b/frontend/src/app/vsr/page.module.css index c520a45..99248b7 100644 --- a/frontend/src/app/vsr/page.module.css +++ b/frontend/src/app/vsr/page.module.css @@ -15,6 +15,10 @@ line-height: normal; } +.title { + font-size: 40px; +} + .description { color: #000; /* Desktop/Body 1 */ @@ -25,18 +29,9 @@ line-height: normal; } -.personalInfo { - color: var(--Accent-Blue-1, #102d5f); - /* Desktop/H2 */ - font-family: Lora; - font-size: 24px; - font-style: normal; - font-weight: 700; - line-height: normal; -} - .fieldsMarked { color: #000; + font-family: "Open Sans"; font-size: 16px; font-style: normal; font-weight: 400; @@ -70,6 +65,16 @@ align-self: flex-start; } +.sectionTitle { + color: var(--Accent-Blue-1, #102d5f); + /* Desktop/H2 */ + font-family: Lora; + font-size: 24px; + font-style: normal; + font-weight: 700; + line-height: normal; +} + .formRow { width: 100%; display: flex; @@ -78,68 +83,23 @@ align-items: start; } +.desktopRowTabletColumn { + flex-direction: row; +} + .numChildren { display: flex; flex-direction: column; gap: 20px; align-items: center; flex: 1; + width: 100%; } .asterisk { color: var(--Secondary-2, #be2d46); } -.buttonContainer { - display: flex; - justify-content: space-between; -} - -.submitButton { - align-self: end; -} - -.submit { - width: 306px; - height: 64px; - background-color: #102d5f; - color: white; - cursor: pointer; - font-family: Lora; - font-size: 24px; - font-style: normal; - font-weight: 700; - line-height: normal; - border: none; - border-radius: 4px; -} -.enabled { - background-color: #102d5f; -} - -.disabled { - background-color: grey; -} - -.backButton { - align-self: start; -} - -.back { - width: 306px; - height: 64px; - background-color: white; - color: #102d5f; - cursor: pointer; - font-family: Lora; - font-size: 24px; - font-style: normal; - font-weight: 700; - line-height: normal; - border: #102d5f; - border-radius: 4px; -} - .sectionHeader { gap: 4px; font-size: 16px; @@ -153,17 +113,13 @@ .longText { flex: 1; + width: 100%; } .childInputWrapper { width: 100%; } -.page { - margin: 0; - box-sizing: border-box; - background-color: var(--color-tse-primary-light); -} .canvas { border-radius: 20px; background-color: #fff; @@ -172,6 +128,7 @@ margin-top: 128px; padding: 64px; } + .title { color: var(--Accent-Blue-1, #102d5f); font-family: "Lora"; @@ -180,9 +137,7 @@ font-weight: 700; line-height: normal; } -.sections { - padding-top: 32px; -} + .section:not(:last-child) { padding-bottom: 64px; } @@ -204,6 +159,7 @@ .furnitureItemsSectionLabel { padding-bottom: 16px; + font-size: 16px; /* Capitalize names of furniture categories */ text-transform: capitalize; } @@ -215,43 +171,141 @@ gap: 16px; } -.actions { +.bottomRow { display: flex; flex-direction: row; justify-content: space-between; - width: calc(100vw * 5 / 6); - margin: auto; - align-items: baseline; - padding-top: 64px; + align-items: center; + width: 100%; + gap: 64px; + padding-top: 32px; padding-bottom: 128px; } -.submit { +.bottomRowMobile { + display: flex; + flex-direction: row; + width: 100%; + gap: 32px; +} + +.bottomButton { width: 306px; height: 64px; - color: white; cursor: pointer; font-family: "Lora"; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; - border: none; border-radius: 4px; } +.submit { + color: white; + border: none; +} + +.enabled { + background-color: #102d5f; +} + +.disabled { + background-color: grey; +} + .back { - width: 306px; - height: 64px; background-color: var(--color-tse-primary-light); color: #102d5f; - cursor: pointer; - font-family: "Lora"; - font-size: 24px; - font-style: normal; - font-weight: 700; - line-height: normal; - border-radius: 4px; border: 1px solid var(--Secondary-1, #102d5f); background: rgba(255, 255, 255, 0); } + +/* tablet version */ +@media screen and (max-width: 850px) { + .main { + padding: 48px; + padding-top: 64px; + } + + .title { + font-size: 36px; + } + + .description { + font-size: 18px; + } + + .fieldsMarked { + font-size: 14px; + } + + .formContainer { + padding: 48px 32px; + } + + .sectionTitle { + font-size: 28px; + } + + .formRow { + gap: 32px; + } + + .desktopRowTabletColumn { + flex-direction: column; + } + + .bottomRow { + padding-bottom: 64px; + } + + .bottomButton { + width: 100%; + } + + .furnitureItemsSectionLabel { + font-size: 14px; + } +} + +/* mobile version */ +@media screen and (max-width: 550px) { + .main { + padding: 24px; + padding-top: 35px; + } + + .title { + font-size: 28px; + } + + .description { + font-size: 14px; + } + + .fieldsMarked { + font-size: 12px; + } + + .formContainer { + padding: 32px 16px; + } + + .sectionTitle { + font-size: 20px; + } + + .formRow { + flex-direction: column; + } + + .bottomRow { + gap: 32px; + flex-direction: column; + } + + .furnitureItemsSectionLabel { + font-size: 12px; + } +} diff --git a/frontend/src/app/vsr/page.tsx b/frontend/src/app/vsr/page.tsx index d1d724f..9ac0e0b 100644 --- a/frontend/src/app/vsr/page.tsx +++ b/frontend/src/app/vsr/page.tsx @@ -8,6 +8,7 @@ import Dropdown from "@/components/shared/input/Dropdown"; import HeaderBar from "@/components/shared/HeaderBar"; import PageNumber from "@/components/VSRForm/PageNumber"; import { createVSR, CreateVSRRequest, FurnitureInput } from "@/api/VSRs"; +import { useMediaQuery } from "@mui/material"; import { FurnitureItem, getFurnitureItems } from "@/api/FurnitureItems"; import BinaryChoice from "@/components/shared/input/BinaryChoice"; import { FurnitureItemSelection } from "@/components/VeteranForm/FurnitureItemSelection"; @@ -252,6 +253,8 @@ const VeteranServiceRequest: React.FC = () => { })); }; + const isMobile = useMediaQuery("@media screen and (max-width: 550px)"); + // Execute when submit button is pressed const onSubmit: SubmitHandler = async (data) => { // Construct the request object @@ -326,7 +329,7 @@ const VeteranServiceRequest: React.FC = () => { <>
{ />
-
- {/* Cap it at 99 children per gender to avoid freezing web browser */} - {Array.from({ length: Math.min(numChildrenThisGender, 99) }, (_, index) => ( -
- -
- ))} -
+ {numChildrenThisGender > 0 ? ( +
+ {/* Cap it at 99 children per gender to avoid freezing web browser */} + {Array.from({ length: Math.min(numChildrenThisGender, 99) }, (_, index) => ( +
+ +
+ ))} +
+ ) : null} ); }; + const renderPageNumber = () => { + return ; + }; + + const renderBackButton = () => { + return pageNumber === 1 ? ( +
+ ) : ( + + ); + }; + + const renderNextButton = () => { + return ( + + ); + }; + + const renderBottomRow = () => { + if (isMobile) { + return ( +
+ +
+ {pageNumber === 1 ? null : renderBackButton()} + {renderNextButton()} +
+
+ ); + } else { + return ( +
+ {renderBackButton()} + {renderPageNumber()} + {renderNextButton()} +
+ ); + } + }; + if (pageNumber == 1) { return (
-

Veteran Service Request Form

+

Veteran Service Request Form

Welcome, Veterans, Active Duty, Reservists, and Families. If you're in need of furnishings, we're here to assist you. Please complete and submit the form below @@ -405,7 +459,7 @@ const VeteranServiceRequest: React.FC = () => {

-

Personal Information

+

Personal Information

@@ -419,8 +473,8 @@ const VeteranServiceRequest: React.FC = () => { helperText={errors.name?.message} />
- {/* Add an empty div here with flex: 1 to take up the right half of the row */} -
+ {/* Add an empty div here with flex: 1 to take up the right half of the row, on non-mobile */} + {isMobile ? null :
}
@@ -505,9 +559,9 @@ const VeteranServiceRequest: React.FC = () => {

Children (under 18)

-
- {renderChildInput("boy")} - {renderChildInput("girl")} +
+
{renderChildInput("boy")}
+
{renderChildInput("girl")}
@@ -607,15 +661,7 @@ const VeteranServiceRequest: React.FC = () => { />
-
- -
- + {renderBottomRow()}
@@ -629,72 +675,75 @@ const VeteranServiceRequest: React.FC = () => {
-

Contact Information

- -
-
- -
+

Contact Information

-
- -
+
+
+
+ +
-
- ( - field.onChange(e)} - required - error={!!errors.state} - helperText={errors.state?.message} - placeholder="Select a state" - /> - )} - /> +
+ +
+
+
+ ( + field.onChange(e)} + required + error={!!errors.state} + helperText={errors.state?.message} + placeholder="Select a state" + /> + )} + /> +
-
- +
+ +
@@ -740,7 +789,7 @@ const VeteranServiceRequest: React.FC = () => {
-

Military Background

+

Military Background

{
-

Additional Information

- +

Additional Information

{
-
-
- -
- -
- -
-
+ {renderBottomRow()}
); } else { return ( -
+
-
-
Furnishings
-
- {Object.entries(furnitureCategoriesToItems ?? {}).map(([category, items]) => ( -
-

{category}

-
- {(items ?? []).map((furnitureItem) => ( - handleSelectionChange(newSelection)} - /> +
+
+
+
+
Furnishings
+
+ {Object.entries(furnitureCategoriesToItems ?? {}).map(([category, items]) => ( +
+

{category}

+
+ {(items ?? []).map((furnitureItem) => ( + + handleSelectionChange(newSelection) + } + /> + ))} +
+
))} +
+ setAdditionalItems(e.target.value)} + > +
- ))} -
- setAdditionalItems(e.target.value)} - >
-
-
-
- -
- -
- -
+ {renderBottomRow()}
diff --git a/frontend/src/components/VSRForm/PageNumber/styles.module.css b/frontend/src/components/VSRForm/PageNumber/styles.module.css index baa68f8..d4ccce6 100644 --- a/frontend/src/components/VSRForm/PageNumber/styles.module.css +++ b/frontend/src/components/VSRForm/PageNumber/styles.module.css @@ -7,4 +7,19 @@ font-style: normal; font-weight: 400; line-height: normal; + white-space: nowrap; +} + +/* tablet version */ +@media screen and (max-width: 850px) { + .pageNumber { + font-size: 14px; + } +} + +/* mobile version */ +@media screen and (max-width: 550px) { + .pageNumber { + font-size: 12px; + } } diff --git a/frontend/src/components/VeteranForm/FurnitureItemSelection/styles.module.css b/frontend/src/components/VeteranForm/FurnitureItemSelection/styles.module.css index c7f73be..318b0f2 100644 --- a/frontend/src/components/VeteranForm/FurnitureItemSelection/styles.module.css +++ b/frontend/src/components/VeteranForm/FurnitureItemSelection/styles.module.css @@ -1,7 +1,5 @@ .chip { white-space: nowrap; - border-width: 1px; - border-style: solid; text-align: center; font-family: "OpenSans"; font-size: 16px; @@ -15,6 +13,7 @@ .chipContent { display: flex; flex-direction: row; + align-items: center; padding: 9px 16px; align-content: baseline; } @@ -84,3 +83,17 @@ filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(0%) hue-rotate(36deg) brightness(103%) contrast(103%); } + +/* tablet version */ +@media screen and (max-width: 850px) { + .chip { + font-size: 14px; + } +} + +/* mobile version */ +@media screen and (max-width: 550px) { + .chip { + font-size: 12px; + } +} diff --git a/frontend/src/components/shared/input/BinaryChoice/index.tsx b/frontend/src/components/shared/input/BinaryChoice/index.tsx index a459430..69a4110 100644 --- a/frontend/src/components/shared/input/BinaryChoice/index.tsx +++ b/frontend/src/components/shared/input/BinaryChoice/index.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import Chip from "@mui/material/Chip"; import styles from "@/components/shared/input/BinaryChoice/styles.module.css"; +import { FormField } from "../FormField"; export interface BinaryChoiceProps { label: string; @@ -11,7 +12,14 @@ export interface BinaryChoiceProps { helperText?: string; } -const BinaryChoice = ({ label, value, onChange, required, helperText }: BinaryChoiceProps) => { +const BinaryChoice = ({ + label, + value, + onChange, + required, + error, + helperText, +}: BinaryChoiceProps) => { const [selectedOption, setSelectedOption] = useState(value); const handleOptionClick = (newOption: boolean | null) => { @@ -20,11 +28,7 @@ const BinaryChoice = ({ label, value, onChange, required, helperText }: BinaryCh }; return ( -
-

- {required ? * : null} - {label} -

+
- {helperText ?
{helperText}
: null} -
+ ); }; diff --git a/frontend/src/components/shared/input/BinaryChoice/styles.module.css b/frontend/src/components/shared/input/BinaryChoice/styles.module.css index 2f69852..c40c320 100644 --- a/frontend/src/components/shared/input/BinaryChoice/styles.module.css +++ b/frontend/src/components/shared/input/BinaryChoice/styles.module.css @@ -1,19 +1,5 @@ /* BinaryChoice.module.css */ -.wrapperClass { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 16px; - flex: 1 0 0; - font-size: 16px; - color: var(--Light-Gray, #818181); - font-family: "Open Sans"; - font-style: normal; - font-weight: 400; - line-height: normal; -} - .chip { border-width: 1px; border-style: solid; @@ -52,13 +38,3 @@ .chipUnselected:hover { background: rgb(213, 232, 239); } - -.requiredAsterisk { - color: var(--Secondary-2, #be2d46); - text-align: left; -} - -.helperText { - color: var(--Secondary-2, #be2d46); - font-size: 12px; -} diff --git a/frontend/src/components/shared/input/Dropdown/index.tsx b/frontend/src/components/shared/input/Dropdown/index.tsx index be8f073..ccec258 100644 --- a/frontend/src/components/shared/input/Dropdown/index.tsx +++ b/frontend/src/components/shared/input/Dropdown/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import styles from "@/components/shared/input/Dropdown/styles.module.css"; -import { FormControl, Select, MenuItem, SelectChangeEvent } from "@mui/material"; +import { FormControl, Select, MenuItem, SelectChangeEvent, useMediaQuery } from "@mui/material"; +import { FormField } from "../FormField"; export interface DropDownProps { label: string; @@ -23,15 +24,14 @@ const Dropdown = ({ helperText, placeholder, }: DropDownProps) => { + const isMobile = useMediaQuery("@media screen and (max-width: 550px)"); + const isTablet = useMediaQuery("@media screen and (max-width: 850px)"); + return ( -
-

- {required ? * : null} - {label} -

+ - {helperText ?
{helperText}
: null} -
+ ); }; diff --git a/frontend/src/components/shared/input/Dropdown/styles.module.css b/frontend/src/components/shared/input/Dropdown/styles.module.css index dfd998b..0a9c1b5 100644 --- a/frontend/src/components/shared/input/Dropdown/styles.module.css +++ b/frontend/src/components/shared/input/Dropdown/styles.module.css @@ -1,25 +1,9 @@ -.wrapperClass { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 4px; - flex: 1 0 0; - font-size: 16px; - color: var(--Light-Gray, #818181); - font-family: "Open Sans"; - font-style: normal; - font-weight: 400; - line-height: normal; -} - .dropDown { color: var(--Dark-Gray, #484848); font-family: "Open Sans"; font-size: 16px; - font-style: italic; font-weight: 300; line-height: normal; - align-items: flex-start; gap: 10px; align-self: stretch; } @@ -29,16 +13,6 @@ height: 100%; } -.requiredAsterisk { - color: var(--Secondary-2, #be2d46); - text-align: left; -} - -.helperText { - color: var(--Secondary-2, #be2d46); - font-size: 12px; -} - .placeholder { font-size: 16px; font-style: italic; diff --git a/frontend/src/components/shared/input/FormField/index.tsx b/frontend/src/components/shared/input/FormField/index.tsx new file mode 100644 index 0000000..4ef3b50 --- /dev/null +++ b/frontend/src/components/shared/input/FormField/index.tsx @@ -0,0 +1,25 @@ +import styles from "@/components/shared/input/FormField/styles.module.css"; +import { ReactNode } from "react"; + +export interface FormFieldProps { + label: string; + required: boolean; + error?: boolean; + helperText?: string; + children: ReactNode; +} + +export const FormField = ({ label, required, error, helperText, children }: FormFieldProps) => { + return ( +
+

+ {required ? * : null} + {label} +

+ {children} + {helperText ? ( +
{helperText}
+ ) : null} +
+ ); +}; diff --git a/frontend/src/components/shared/input/FormField/styles.module.css b/frontend/src/components/shared/input/FormField/styles.module.css new file mode 100644 index 0000000..82b9ab1 --- /dev/null +++ b/frontend/src/components/shared/input/FormField/styles.module.css @@ -0,0 +1,41 @@ +.wrapperClass { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + flex: 1 0 0; + font-size: 16px; + color: var(--Light-Gray, #818181); + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + line-height: normal; +} + +.requiredAsterisk { + color: var(--Secondary-2, #be2d46); + text-align: left; +} + +.helperText { + color: var(--Neutral-Gray6, #484848); + font-size: 12px; +} + +.errorText { + color: var(--Secondary-2, #be2d46); +} + +/* tablet version */ +@media screen and (max-width: 850px) { + .wrapperClass { + font-size: 14px; + } +} + +/* mobile version */ +@media screen and (max-width: 550px) { + .wrapperClass { + font-size: 12px; + } +} diff --git a/frontend/src/components/shared/input/MultipleChoice/index.tsx b/frontend/src/components/shared/input/MultipleChoice/index.tsx index c4b9132..23b2566 100644 --- a/frontend/src/components/shared/input/MultipleChoice/index.tsx +++ b/frontend/src/components/shared/input/MultipleChoice/index.tsx @@ -1,5 +1,6 @@ import Chip from "@mui/material/Chip"; import styles from "@/components/shared/input/MultipleChoice/styles.module.css"; +import { FormField } from "../FormField"; export interface MultipleChoiceProps { label: string; @@ -19,14 +20,11 @@ const MultipleChoice = ({ onChange, required, allowMultiple = false, + error, helperText, }: MultipleChoiceProps) => { return ( -
-

- {required ? * : null} - {label} -

+
{options.map((option) => { const optionIsSelected = allowMultiple ? value?.includes(option) : value === option; @@ -58,12 +56,16 @@ const MultipleChoice = ({ optionIsSelected ? styles.chipSelected : styles.chipUnselected }`} clickable + sx={{ + ".MuiChip-label": { + padding: "0 !important", + }, + }} /> ); })}
- {helperText ?
{helperText}
: null} -
+ ); }; diff --git a/frontend/src/components/shared/input/MultipleChoice/styles.module.css b/frontend/src/components/shared/input/MultipleChoice/styles.module.css index b3a1f93..1076148 100644 --- a/frontend/src/components/shared/input/MultipleChoice/styles.module.css +++ b/frontend/src/components/shared/input/MultipleChoice/styles.module.css @@ -1,22 +1,7 @@ /* MultipleChoice.module.css */ -.wrapperClass { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 16px; - flex: 1 0 0; - font-size: 16px; - color: var(--Light-Gray, #818181); - font-family: "Open Sans"; - font-style: normal; - font-weight: 400; - line-height: normal; -} - .chip { border-width: 1px; - border-style: solid; text-align: center; font-family: "Open Sans"; font-size: 16px; @@ -25,6 +10,8 @@ line-height: normal; border-radius: 64px; border: 1px solid var(--Secondary-1, #102d5f); + padding: 8px 16px; + height: 40px; } .chipSelected { @@ -50,15 +37,21 @@ /*Need exact color for this*/ .chipUnselected:hover { - background: rgb(213, 232, 239); + background: rgb(142, 166, 175); } -.requiredAsterisk { - color: var(--Secondary-2, #be2d46); - text-align: left; +/* tablet version */ +@media screen and (max-width: 850px) { + .chip { + font-size: 14px; + height: 36px; + } } -.helperText { - color: var(--Secondary-2, #be2d46); - font-size: 12px; +/* mobile version */ +@media screen and (max-width: 550px) { + .chip { + font-size: 12px; + height: 30px; + } } diff --git a/frontend/src/components/shared/input/TextField/index.tsx b/frontend/src/components/shared/input/TextField/index.tsx index 2dc9e10..0e71772 100644 --- a/frontend/src/components/shared/input/TextField/index.tsx +++ b/frontend/src/components/shared/input/TextField/index.tsx @@ -1,6 +1,7 @@ import styles from "@/components/shared/input/TextField/styles.module.css"; import MUITextField, { TextFieldProps as MUITextFieldProps } from "@mui/material/TextField"; import { ForwardedRef, forwardRef } from "react"; +import { FormField } from "../FormField"; export interface TextFieldProps extends MUITextFieldProps<"outlined"> { label: string; @@ -15,11 +16,7 @@ const TextField = forwardRef( ref: ForwardedRef, ) => { return ( -
-

- {required ? * : null} - {label} -

+ - {helperText ? ( -
- {helperText} -
- ) : null} -
+ ); }, ); diff --git a/frontend/src/components/shared/input/TextField/styles.module.css b/frontend/src/components/shared/input/TextField/styles.module.css index 40565fa..0aebaae 100644 --- a/frontend/src/components/shared/input/TextField/styles.module.css +++ b/frontend/src/components/shared/input/TextField/styles.module.css @@ -1,22 +1,3 @@ -.wrapperClass { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: 4px; - flex: 1 0 0; - font-size: 16px; - color: var(--Light-Gray, #818181); - font-family: "Open Sans"; - font-style: normal; - font-weight: 400; - line-height: normal; -} - -.requiredAsterisk { - color: var(--Secondary-2, #be2d46); - text-align: left; -} - .inputClass { display: flex; align-items: flex-start; @@ -28,13 +9,9 @@ line-height: normal; } -.helperText { - color: var(--Neutral-Gray6, #484848); - font-size: 12px; -} - -.errorText { - color: var(--Secondary-2, #be2d46); +.input { + height: 22px; + padding: 6px 12px; } .input::placeholder { @@ -43,3 +20,17 @@ font-weight: 300; color: var(--Dark-Gray, #484848); } + +/* tablet version */ +@media screen and (max-width: 850px) { + .input { + height: 19px; + } +} + +/* mobile version */ +@media screen and (max-width: 550px) { + .input { + height: 16px; + } +}