2020-07-31 17:36:10 +02:00
|
|
|
import React, { FunctionComponent, useState, useEffect } from "react";
|
|
|
|
import { Link } from "react-router-dom";
|
|
|
|
import { WithLoader } from "../WithLoader";
|
|
|
|
|
|
|
|
export interface Item {
|
|
|
|
id: string
|
|
|
|
[propName: string]: any;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface TabDefinition {
|
|
|
|
label: string
|
|
|
|
itemFilter?: (item: Item) => boolean
|
|
|
|
}
|
|
|
|
export interface ItemPanelProps {
|
|
|
|
className?: string
|
|
|
|
itemIconClassName?: string
|
|
|
|
title?: string
|
|
|
|
newItemUrl: string
|
|
|
|
isLoading?: boolean
|
|
|
|
items: Item[]
|
|
|
|
tabs?: TabDefinition[],
|
|
|
|
itemKey: (item: Item, index: number) => string
|
|
|
|
itemLabel: (item: Item, index: number) => string
|
|
|
|
itemUrl: (item: Item, index: number) => string
|
|
|
|
}
|
|
|
|
|
|
|
|
export const ItemPanel: FunctionComponent<ItemPanelProps> = (props) => {
|
|
|
|
const {
|
|
|
|
title, className, newItemUrl,
|
|
|
|
itemKey, itemLabel,
|
2020-09-04 12:28:38 +02:00
|
|
|
itemIconClassName, itemUrl,
|
2020-07-31 17:36:10 +02:00
|
|
|
} = props;
|
|
|
|
|
2020-09-04 12:28:38 +02:00
|
|
|
const items = props.items || [];
|
|
|
|
const tabs = props.tabs || [];
|
|
|
|
|
2020-07-31 17:36:10 +02:00
|
|
|
const [ state, setState ] = useState({ selectedTab: 0, filteredItems: [] });
|
|
|
|
|
|
|
|
const filterItemsForTab = (tab: TabDefinition, items: Item[]) => {
|
|
|
|
const itemFilter = tab && typeof tab.itemFilter === 'function' ? tab.itemFilter : () => true;
|
|
|
|
return items.filter(itemFilter);
|
|
|
|
};
|
|
|
|
|
|
|
|
const selectTab = (tabIndex: number) => {
|
|
|
|
setState(state => {
|
|
|
|
const newTab = Array.isArray(tabs) && tabs.length > 0 ? tabs[tabIndex] : null;
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
selectedTab: tabIndex,
|
|
|
|
filteredItems: filterItemsForTab(newTab, items)
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
setState(state => {
|
|
|
|
const { tabs, items } = props;
|
|
|
|
const newTab = Array.isArray(tabs) && tabs.length > 0 ? tabs[state.selectedTab] : null;
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
filteredItems: filterItemsForTab(newTab, items),
|
|
|
|
}
|
|
|
|
});
|
2020-09-04 12:28:38 +02:00
|
|
|
}, [items, tabs]);
|
2020-07-31 17:36:10 +02:00
|
|
|
|
|
|
|
const itemElements = state.filteredItems.map((item: Item, i: number) => {
|
|
|
|
return (
|
|
|
|
<Link to={itemUrl(item, i)} key={`item-${itemKey(item, i)}`} className="panel-block">
|
|
|
|
<span className="panel-icon">
|
|
|
|
<i className={itemIconClassName} aria-hidden="true"></i>
|
|
|
|
</span>
|
|
|
|
{itemLabel(item, i)}
|
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
return (
|
|
|
|
<nav className={`panel ${className}`}>
|
2020-07-31 18:04:31 +02:00
|
|
|
<div className="level is-mobile panel-heading mb-0">
|
2020-07-31 17:36:10 +02:00
|
|
|
<div className="level-left">
|
|
|
|
<p className="level-item">{title}</p>
|
|
|
|
</div>
|
|
|
|
<div className="level-right">
|
|
|
|
<Link to={newItemUrl} className="button level-item is-outlined is-info is-inverted">
|
|
|
|
<i className="icon fa fa-plus"></i>
|
|
|
|
</Link>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="panel-block">
|
|
|
|
<p className="control has-icons-left">
|
2020-10-05 15:18:35 +02:00
|
|
|
<input disabled={true} className="input" type="text" placeholder="Filtrer..." />
|
2020-07-31 17:36:10 +02:00
|
|
|
<span className="icon is-left">
|
|
|
|
<i className="fas fa-search" aria-hidden="true"></i>
|
|
|
|
</span>
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<p className="panel-tabs">
|
|
|
|
{
|
|
|
|
tabs.map((tab, i) => {
|
|
|
|
return (
|
|
|
|
<a key={`workgroup-tab-${i}`}
|
|
|
|
onClick={selectTab.bind(null, i)}
|
|
|
|
className={i === state.selectedTab ? 'is-active' : ''}>
|
|
|
|
{tab.label}
|
|
|
|
</a>
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</p>
|
|
|
|
{
|
|
|
|
itemElements.length > 0 ?
|
|
|
|
itemElements :
|
|
|
|
<a className="panel-block has-text-centered is-block">
|
|
|
|
<em>Aucun élément pour l'instant.</em>
|
|
|
|
</a>
|
|
|
|
}
|
|
|
|
</nav>
|
|
|
|
)
|
|
|
|
};
|