mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-20 14:54:15 +01:00
allow user to filter plans by groups
This commit is contained in:
parent
854db568bf
commit
4580bfc7d7
@ -8,7 +8,7 @@ export const Loader: React.FC = ({children }) => {
|
||||
<div className="fa-3x">
|
||||
<i className="fas fa-circle-notch fa-spin" />
|
||||
</div>
|
||||
);// compile
|
||||
);
|
||||
return (
|
||||
<Suspense fallback={loading}>
|
||||
{children}
|
||||
|
@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Group } from '../../models/group';
|
||||
import { User } from '../../models/user';
|
||||
|
||||
interface PlansFilterProps {
|
||||
user?: User,
|
||||
groups: Array<Group>,
|
||||
onGroupSelected: (groupId: number) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
export const PlansFilter: React.FC<PlansFilterProps> = ({ user, groups, onGroupSelected }) => {
|
||||
const { t } = useTranslation('public');
|
||||
|
||||
/**
|
||||
* Convert all groups to the react-select format
|
||||
*/
|
||||
const buildGroupOptions = (): Array<selectOption> => {
|
||||
return groups.filter(g => !g.disabled && g.slug !== 'admins').map(g => {
|
||||
return { value: g.id, label: g.name }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered when the user select a group in the dropdown list
|
||||
*/
|
||||
const handleGroupSelected = (option: selectOption): void => {
|
||||
onGroupSelected(option.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="plans-filter">
|
||||
{!user && <div className="group-filter">
|
||||
<label htmlFor="group">{t('app.public.plans_filter.i_am')}</label>
|
||||
<Select placeholder={t('app.public.plans_filter.select_group')}
|
||||
className="group-select"
|
||||
onChange={handleGroupSelected}
|
||||
options={buildGroupOptions()}/>
|
||||
</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
@ -12,6 +12,7 @@ import { Loader } from '../base/loader';
|
||||
import { react2angular } from 'react2angular';
|
||||
import { IApplication } from '../../models/application';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PlansFilter } from './plans-filter';
|
||||
|
||||
declare var Application: IApplication;
|
||||
|
||||
@ -41,6 +42,8 @@ const PlansList: React.FC<PlansListProps> = ({ onError, onPlanSelection, onLogin
|
||||
const [groups, setGroups] = useState<Array<Group>>(null);
|
||||
// currently selected plan
|
||||
const [selectedPlan, setSelectedPlan] = useState<Plan>(null);
|
||||
// filter shown plans by only one group
|
||||
const [groupFilter, setGroupFilter] = useState<number>(null);
|
||||
|
||||
// fetch data on component mounted
|
||||
useEffect(() => {
|
||||
@ -60,6 +63,7 @@ const PlansList: React.FC<PlansListProps> = ({ onError, onPlanSelection, onLogin
|
||||
// reset the selected plan when the user changes
|
||||
useEffect(() => {
|
||||
setSelectedPlan(null);
|
||||
setGroupFilter(null);
|
||||
}, [customer, operator]);
|
||||
|
||||
/**
|
||||
@ -96,10 +100,11 @@ const PlansList: React.FC<PlansListProps> = ({ onError, onPlanSelection, onLogin
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the plans to display, depending on the connected/selected user
|
||||
* Filter the plans to display, depending on the connected/selected user and on the selected group filter (if any)
|
||||
*/
|
||||
const filteredPlans = (): PlansTree => {
|
||||
if (_.isEmpty(customer)) return plans;
|
||||
if (_.isEmpty(customer) && !groupFilter) return plans;
|
||||
if (groupFilter) return new Map([[groupFilter, plans.get(groupFilter)]]);
|
||||
|
||||
return new Map([[customer.group_id, plans.get(customer.group_id)]]);
|
||||
}
|
||||
@ -154,6 +159,13 @@ const PlansList: React.FC<PlansListProps> = ({ onError, onPlanSelection, onLogin
|
||||
onPlanSelection(plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback triggered when the user select a group to filter the current list
|
||||
*/
|
||||
const handleFilterByGroup = (groupId: number): void => {
|
||||
setGroupFilter(groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the provided list of categories, with each associated plans
|
||||
*/
|
||||
@ -197,6 +209,7 @@ const PlansList: React.FC<PlansListProps> = ({ onError, onPlanSelection, onLogin
|
||||
|
||||
return (
|
||||
<div className="plans-list">
|
||||
{groups && <PlansFilter user={customer} groups={groups} onGroupSelected={handleFilterByGroup} />}
|
||||
{plans && Array.from(filteredPlans()).map(([groupId, plansByGroup]) => {
|
||||
return (
|
||||
<div key={groupId} className="plans-per-group">
|
||||
|
@ -49,5 +49,6 @@
|
||||
@import "modules/create-plan-category";
|
||||
@import "modules/edit-plan-category";
|
||||
@import "modules/delete-plan-category";
|
||||
@import "modules/plans-filter";
|
||||
|
||||
@import "app.responsive";
|
||||
|
14
app/frontend/src/stylesheets/modules/plans-filter.scss
Normal file
14
app/frontend/src/stylesheets/modules/plans-filter.scss
Normal file
@ -0,0 +1,14 @@
|
||||
.plans-filter {
|
||||
margin: 1.5em;
|
||||
|
||||
.group-filter {
|
||||
& > * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.group-select {
|
||||
min-width: 40%;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
@ -259,6 +259,9 @@ en:
|
||||
the_user_s_group_was_successfully_changed: "The user's group was successfully changed."
|
||||
an_error_prevented_your_group_from_being_changed: "An error prevented your group from being changed."
|
||||
an_error_prevented_to_change_the_user_s_group: "An error prevented to change the user's group."
|
||||
plans_filter:
|
||||
i_am: "I am"
|
||||
select_group: "select a group"
|
||||
#Fablab's events list
|
||||
events_list:
|
||||
the_fablab_s_events: "The Fablab's events"
|
||||
|
Loading…
x
Reference in New Issue
Block a user