1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-30 19:52:20 +01:00

filter machines by status

This commit is contained in:
Sylvain 2021-06-17 10:25:13 +02:00
parent 80d206fc99
commit 4aa3fdff0e
7 changed files with 131 additions and 13 deletions

View File

@ -16,6 +16,21 @@ interface MachineCardProps {
const MachineCardComponent: React.FC<MachineCardProps> = ({ machine, onShowMachine, onReserveMachine }) => {
const { t } = useTranslation('public');
/**
* Callback triggered when the user clicks on the 'reserve' button.
* We handle the training verification process here, before redirecting the user to the reservation calendar.
*/
const handleReserveMachine = (): void => {
onReserveMachine(machine);
}
/**
* Callback triggered when the user clicks on the 'view' button
*/
const handleShowMachine = (): void => {
onShowMachine(machine);
}
const machinePicture = (): ReactNode => {
if (!machine.machine_image) {
return (
@ -33,13 +48,6 @@ const MachineCardComponent: React.FC<MachineCardProps> = ({ machine, onShowMachi
)
}
const handleReserveMachine = (): void => {
onReserveMachine(machine);
}
const handleShowMachine = (): void => {
onShowMachine(machine);
}
return (
<div className="machine-card">
{machinePicture()}

View File

@ -0,0 +1,50 @@
import React from 'react';
import Select from 'react-select';
import { useTranslation } from 'react-i18next';
interface MachinesFiltersProps {
onStatusSelected: (enabled: boolean) => void,
}
/**
* Option format, expected by react-select
* @see https://github.com/JedWatson/react-select
*/
type selectOption = { value: boolean, label: string };
export const MachinesFilters: React.FC<MachinesFiltersProps> = ({ onStatusSelected }) => {
const { t } = useTranslation('public');
const defaultValue = { value: true, label: t('app.public.machines_filters.status_enabled') };
/**
* Provides boolean options in the react-select format (yes/no/all)
*/
const buildBooleanOptions = (): Array<selectOption> => {
return [
defaultValue,
{ value: false, label: t('app.public.machines_filters.status_disabled') },
{ value: null, label: t('app.public.machines_filters.status_all') },
]
}
/**
* Callback triggered when the user selects a machine status in the dropdown list
*/
const handleStatusSelected = (option: selectOption): void => {
onStatusSelected(option.value);
}
return (
<div className="machines-filters">
<div className="status-filter">
<label htmlFor="status">{t('app.public.machines_filters.show_machines')}</label>
<Select defaultValue={defaultValue}
id="status"
className="status-select"
onChange={handleStatusSelected}
options={buildBooleanOptions()}/>
</div>
</div>
)
}

View File

@ -5,6 +5,7 @@ import { react2angular } from 'react2angular';
import { Loader } from '../base/loader';
import MachineAPI from '../../api/machine';
import { MachineCard } from './machine-card';
import { MachinesFilters } from './machines-filters';
declare var Application: IApplication;
@ -18,20 +19,43 @@ interface MachinesListProps {
* This component shows a list of all machines and allows filtering on that list.
*/
const MachinesList: React.FC<MachinesListProps> = ({ onError, onShowMachine, onReserveMachine }) => {
// shown machines
const [machines, setMachines] = useState<Array<Machine>>(null);
// we keep the full list of machines, for filtering
const [allMachines, setAllMachines] = useState<Array<Machine>>(null);
// retrieve the full list of machines on component mount
useEffect(() => {
MachineAPI.index()
.then(data => setMachines(data))
.then(data => setAllMachines(data))
.catch(e => onError(e));
}, []);
// filter the machines shown when the full list was retrieved
useEffect(() => {
handleFilterByStatus(true);
}, [allMachines])
/**
* Callback triggered when the user changes the status filter.
* Set the 'machines' state to a filtered list, depending on the provided parameter.
*/
const handleFilterByStatus = (status: boolean): void => {
if (!allMachines) return;
if (status === null) return setMachines(allMachines);
setMachines(allMachines.filter(m => m.disabled === !status));
}
return (
<div className="machines-list">
<MachinesFilters onStatusSelected={handleFilterByStatus} />
<div className="all-machines">
{machines && machines.map(machine => {
return <MachineCard key={machine.id} machine={machine} onShowMachine={onShowMachine} onReserveMachine={onReserveMachine} />
})}
</div>
</div>
);
}

View File

@ -52,5 +52,6 @@
@import "modules/plan-categories/delete-plan-category";
@import "modules/machines/machine-card";
@import "modules/machines/machines-list";
@import "modules/machines/machines-filters";
@import "app.responsive";

View File

@ -0,0 +1,31 @@
.machines-filters {
margin: 1.5em;
.status-filter {
& {
display: inline-flex;
width: 50%;
}
& > label {
white-space: nowrap;
line-height: 2em;
}
& > * {
display: inline-block;
}
.status-select {
width: 100%;
margin-left: 10px;
}
}
}
@media screen and (max-width: 720px){
.machines-filters {
.status-filter {
padding-right: 0;
display: inline-block;
width: 100%;
}
}
}

View File

@ -1,4 +1,6 @@
.machines-list {
.all-machines {
display: flex;
flex-wrap: wrap;
}
}

View File

@ -210,6 +210,8 @@ en:
new_availability: "Open reservations"
book: "Book"
_or_the_: " or the "
machines_filters:
show_machines: "Show machines"
status_enabled: "Enabled"
status_disabled: "Disabled"
status_all: "All"