Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to select multiple needs for the Add / Edit Student Modal #503

Closed
wants to merge 12 commits into from
Closed
29 changes: 12 additions & 17 deletions frontend/src/components/Modal/RiderModalInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import cn from 'classnames';
import { Button, Input, Label } from '../FormElements/FormElements';
import styles from './ridermodal.module.css';
import { ObjectType, Accessibility, Rider } from '../../types/index';
import { useState } from 'react';
import MultiselectBox from '../MultiselectBox/MultiselectBox';

type ModalFormProps = {
onSubmit: (data: ObjectType) => void;
Expand Down Expand Up @@ -63,7 +65,6 @@ const RiderModalInfo = ({
const localUserType = localStorage.getItem('userType');
const isEditing = rider !== undefined;
const isStudentEditing = isEditing && localUserType === 'Rider';

return (
<form onSubmit={handleSubmit(beforeSubmit)} className={styles.form}>
<div className={cn(styles.inputContainer, styles.rideTime)}>
Expand Down Expand Up @@ -131,22 +132,16 @@ const RiderModalInfo = ({
)}
</div>
<div className={cn(styles.gridR2, styles.gridCBig1)}>
<Label className={styles.label} htmlFor="needs">
Needs:{' '}
</Label>
<select
name="needs"
aria-required="true"
ref={register({ required: true })}
>
{Object.values(Accessibility).map((value, index) => {
return (
<option key={index} value={value}>
{value}
</option>
);
})}
</select>
<Label className={styles.label}>Needs:</Label>
<MultiselectBox
placeHolderText="Select Your Needs"
dataSource={Object.values(Accessibility).map((value, _) =>
value.toString()
)}
isOpen={false}
optionWithTextInputBox={'Other'}
placeHolderTextInputBox="Specify Your Other Needs"
/>
{errors.needs?.type === 'validate' && (
<p className={styles.error}>
Invalid needs. You can enter 'Assistant', 'Crutches', or
Expand Down
96 changes: 96 additions & 0 deletions frontend/src/components/MultiselectBox/MultiselectBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useState } from 'react';
import './Multiselectbox.css';
import { upArrow, downArrow } from '../../icons/other';

type MultiselectBoxProps = {
placeHolderText: string;
dataSource: Array<string>;
isOpen: boolean;
optionWithTextInputBox?: string;
placeHolderTextInputBox?: string;
};

const MultiselectBox = ({
placeHolderText,
dataSource,
isOpen,
optionWithTextInputBox,
placeHolderTextInputBox,
}: MultiselectBoxProps) => {
const [isDropdownBoxOpen, setIsDropdownBoxOpen] = useState(isOpen);
const [selectedItems, setSelectedItems] = useState(new Set<string>());
const [inputValue, setInputValue] = useState('');
const toggleDropdownBox = () => {
setIsDropdownBoxOpen(!isDropdownBoxOpen);
};

const toggleSelectItem = (itemName: string) => {
const newSelectedItems = new Set(selectedItems);
if (newSelectedItems.has(itemName)) {
newSelectedItems.delete(itemName);
} else {
newSelectedItems.add(itemName);
}
setSelectedItems(newSelectedItems);
};

return (
<div className="dropdown-wrapper">
<button
type="button"
className="dropdown-header"
onClick={toggleDropdownBox}
>
<div className="dropdown-header-contents">
<span>
{placeHolderText} &nbsp;&nbsp;&nbsp;&nbsp;{' '}
{isDropdownBoxOpen ? (
<img src={upArrow} alt="Up Arrow" />
) : (
<img src={downArrow} alt="Down Arrow" />
)}
</span>
</div>
</button>

{isDropdownBoxOpen && (
<>
<div className="dropdown-list">
{dataSource.map((itemName) => (
<div key={itemName}>
<input
type="checkbox"
className={'item-checkbox'}
id={itemName}
name={itemName}
onChange={() => toggleSelectItem(itemName)}
checked={selectedItems.has(itemName)}
></input>
<label htmlFor={itemName} className={'item-name'}>
{itemName}
</label>
</div>
))}
{(optionWithTextInputBox
? selectedItems.has(optionWithTextInputBox)
: false) && (
<input
type="text"
className="dropdown-text-input"
value={inputValue}
onChange={(newInputValue) => {
setInputValue(newInputValue.target.value);
}}
placeholder={
placeHolderTextInputBox ? placeHolderTextInputBox : ''
}
/>
)}
</div>
</>
)}
</div>
);
};

export default MultiselectBox;
48 changes: 48 additions & 0 deletions frontend/src/components/MultiselectBox/Multiselectbox.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.dropdown-wrapper {
position: relative;
}

.dropdown-header {
background-color: rgb(255, 255, 255);
border: 1px solid #000000;
padding: 0.5rem;
cursor: pointer;
max-width: 20rem; /* Adjust width as needed */
height: 1.938rem;
border-radius: 0.25rem;
}

.dropdown-list {
position: absolute;
top: calc(100% + 5px);
left: 0;
background-color: rgba(234, 233, 233); /* Grey color with 30% opacity */
border: 1px solid #ccc;
padding: 0.75rem;
max-height: 25rem; /* Adjust max-height as needed */
overflow-y: auto;
z-index: 1000;
border-radius: 0.75rem;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Adding drop shadow */
}

.item-checkbox {
width: 0.75rem;
height: 0.75rem;
border: 0.094rem solid #ccc;
margin-right: 0.313rem;
border-radius: 0.188rem;
background-color: white;
}

.item-name {
font-size: small;
}

.dropdown-text-input {
position: relative;
margin-left: 0.2rem;
border-radius: 6px;
height: 1.75rem;
border: 1px #808080 solid;
}
3 changes: 3 additions & 0 deletions frontend/src/icons/other/downArrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions frontend/src/icons/other/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export { default as chevronLeft } from './chevron-left.svg';
export { default as block } from './blocked.svg';
export { default as red_trash } from './red-trash.svg';
export { default as search_icon } from './search.svg';
export { default as upArrow } from './upArrow.svg';
export { default as downArrow } from './downArrow.svg';
3 changes: 3 additions & 0 deletions frontend/src/icons/other/upArrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion frontend/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { VehicleType } from '../../../server/src/models/vehicle';
export type Rider = RiderType;

export enum Accessibility {
NONE = '',
ASSISTANT = 'Assistant',
CRUTCHES = 'Crutches',
WHEELCHAIR = 'Wheelchair',
Expand Down
Loading