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

TASK-387 Sort shifts in dropdown #282

Merged
merged 10 commits into from
Mar 18, 2021
63 changes: 39 additions & 24 deletions src/assets/styles/styles/custom/_autocomplete.scss
Original file line number Diff line number Diff line change
@@ -1,34 +1,51 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

/*
?Styling for shift autocomplete component
*/
.more-left-margin {
margin-left: -6px !important;
}

.autoSeparator {
flex: 1;
width: 90%;
background-color: $gray-400;
height: 1.25px;
display: flex;
align-self: center;
margin-top: 10px;
margin-bottom: 10px;
}
.listbox {
position: absolute;
padding: 10px 0;
margin: -5px 0 0 -2px;
z-index: 1;
list-style: none;
overflow: auto;
font-family: $font-family-primary;
font-size: $font-size-lg;
line-height: 175%;
text-align: left;
color: $primary;
background-color: $white;
font-weight: $font-weight-normal;
box-shadow: 0 4px 7px rgba(16, 32, 70, 0.2);
max-height: 500px;
border-radius: 7px;
min-width: 250px;
min-width: 260px;
z-index: 300;

& li {
clear: both;
min-height: 25px;
& > div {
display: flex;
margin-left: 0.6em;
flex: 1;
flex-direction: row;
flex-wrap: nowrap;
letter-spacing: 0.75px;
align-content: center;
justify-items: center;
justify-content: left;
&:hover {
font-style: italic;
font-weight: $font-weight-extra-bold;
Expand All @@ -37,23 +54,21 @@
&[data-focus="true"] {
cursor: pointer;
}

.container {
display: block;
margin-left: 15px;

.colorSample {
width: 9px;
height: 9px;
border-radius: 50%;
float: left;
margin: 8.5px 20px 0 10px;
}

.optionLabel {
float: left;
clear: both;
}
> .optionLabel {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin-right: 0.2em;
word-wrap: normal;
overflow-wrap: normal;
}
> .colorSamplee {
display: flex;
width: 9px;
height: 9px;
border-radius: 50%;
margin: 0 0;
align-self: center;
}
}
}

This file was deleted.

1 change: 0 additions & 1 deletion src/components/common-components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
export * from "./header/header.component";
export * from "./autocomplete/autocomplete.component";
export * from "./button-component/button.component";
export * from "./month-switch/month-switch.component";
export * from "./snackbar/snackbar.component";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,133 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import React from "react";
import { SHIFTS as shifts } from "../../../../../../common-models/shift-info.model";
import { AutocompleteComponent } from "../../../../../common-components";
import { useAutocomplete } from "@material-ui/lab";
import _ from "lodash";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { usePopper } from "react-popper";
import { useSelector } from "react-redux";
import { ShiftCode, SHIFTS as shifts } from "../../../../../../common-models/shift-info.model";
import { ApplicationStateModel } from "../../../../../../state/models/application-state.model";
import { BaseCellInputOptions } from "../base-cell/base-cell-input.component";
import classNames from "classnames/bind";

const ShiftCodeSelectItems = Object.values(shifts).map((shift) => {
return {
name: `${shift.name} ${shift.isWorkingShift ? `(${shift.from}-${shift.to})` : ""}`,
symbol: shift.code,
code: shift.code,
color: shift.color ? shift.color : "$white",
"data-cy": `autocomplete-${shift.code}`,
};
});

const ShiftCodeSelectItems = _.sortBy(
Object.values(shifts).map((shift) => {
return {
name: `${shift.name} ${shift.isWorkingShift ? `(${shift.from}-${shift.to})` : ""}`,
symbol: shift.code,
from: shift.from,
to: shift.to,
isWorkingShift: shift!.isWorkingShift,
code: shift.code,
color: shift.color ? shift.color : "$white",
"data-cy": `autocomplete-${shift.code}`,
};
}),
["from", "to", "name"]
);
type ShiftCodeSelectItem = typeof ShiftCodeSelectItems[0];
/**
* @description Input & MaterialAutocomplete component for rendering employees shifts
* @param inputOptions : BaseCellInputOptions
* @returns JSX.Element
*/
export function ShiftAutocompleteComponent(inputOptions: BaseCellInputOptions): JSX.Element {
const inputRef = useRef(null);
const tooltipRef = useRef(null);
const { styles } = usePopper(inputRef.current, tooltipRef.current, {
placement: "right-end",
});
const onValueChange = useCallback((option): void => inputOptions.onValueChange(option.code), [
inputOptions,
]);
const getOptionLabel = (option): string => option.name;
const getOptionColor = (option): string => option.color;
const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => inputOptions.onKeyDown(e);
const [value, setValue] = useState();
useEffect(() => {
if (value) {
onValueChange(value);
}
}, [value, onValueChange]);

const {
getRootProps,
getInputProps,
getListboxProps,
getOptionProps,
groupedOptions,
} = useAutocomplete({
options: ShiftCodeSelectItems,
getOptionLabel,
open: true,
});
const shiftTypes = useSelector(
(state: ApplicationStateModel) => state.actualState.persistentSchedule.present.shift_types
);

/**
* @description Small element for rendering shift info & shift color circle
* @returns JSX.Element
*/
const getNonWorkingShifts = (shift: ShiftCodeSelectItem): ShiftCodeSelectItem | undefined => {
if (shift.name.trim() !== shiftTypes[ShiftCode.W].name) {
if (!shift.isWorkingShift) return shift;
}
};
const nonWorkingShifts = groupedOptions.filter(getNonWorkingShifts);
const LabelComponent = ({ option, index }): JSX.Element => {
return (
<div
{...getOptionProps({ option, index })}
data-cy={option["data-cy"]}
onClick={(e: React.MouseEvent): void => {
e.stopPropagation();
setValue(option);
}}
>
<div className="optionLabel">{getOptionLabel(option)}</div>
<div className="colorSamplee" style={{ backgroundColor: `#${getOptionColor(option)}` }} />
</div>
);
};
return (
<AutocompleteComponent
className={inputOptions.className}
options={ShiftCodeSelectItems}
getOptionLabel={(option): string => option.name}
getOptionColor={(option): string => option.color}
onValueChange={(option): void => inputOptions.onValueChange(option.code)}
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>): void => inputOptions.onKeyDown(e)}
/>
<div ref={inputRef} data-cy="shiftDropdown">
<div {...getRootProps()}>
<input
className={inputOptions.className}
autoFocus={true}
value={value && getOptionLabel(value)}
{...getInputProps()}
onKeyDown={onKeyDown}
/>
</div>
{shiftTypes && groupedOptions.length > 0 && (
<div
ref={tooltipRef}
className={classNames("listbox")}
style={styles.popper}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onMouseDown={(getListboxProps() as any).onMouseDown}
>
{groupedOptions.map((option, index) => {
if (option.name.trim() === shiftTypes[ShiftCode.W].name) {
return <LabelComponent option={option} index={index} />;
}
return null;
})}
{groupedOptions.map((option, index) => {
if (option.isWorkingShift) {
return <LabelComponent option={option} index={index} />;
}
return null;
})}
{nonWorkingShifts.length > 0 && <div className="autoSeparator" />}
{nonWorkingShifts.map((option, index) => (
<LabelComponent option={option} index={index} />
))}
</div>
)}
</div>
);
}