diff --git a/src/frontend/src/components/panels/Panel.tsx b/src/frontend/src/components/panels/Panel.tsx index e1940bbb93..d8b82eaf13 100644 --- a/src/frontend/src/components/panels/Panel.tsx +++ b/src/frontend/src/components/panels/Panel.tsx @@ -8,7 +8,7 @@ export type PanelType = { label: string; controls?: ReactNode; icon?: ReactNode; - content: ReactNode; + content?: ReactNode; hidden?: boolean; disabled?: boolean; showHeadline?: boolean; diff --git a/src/frontend/src/components/panels/SegmentedControlPanel.tsx b/src/frontend/src/components/panels/SegmentedControlPanel.tsx new file mode 100644 index 0000000000..e403948070 --- /dev/null +++ b/src/frontend/src/components/panels/SegmentedControlPanel.tsx @@ -0,0 +1,53 @@ +import SegmentedIconControl from '../buttons/SegmentedIconControl'; +import type { PanelType } from './Panel'; + +export type SegmentedControlPanelSelection = { + value: string; + label: string; + icon: React.ReactNode; + content: React.ReactNode; +}; + +interface SegmentedPanelType extends PanelType { + options: SegmentedControlPanelSelection[]; + selection: string; + onChange: (value: string) => void; +} + +/** + * Display a panel which can be used to display multiple options, + * based on a built-in segmented control. + */ +export default function SegmentedControlPanel( + props: SegmentedPanelType +): PanelType { + // Extract the content based on the selection + let content = null; + + for (const option of props.options) { + if (option.value === props.selection) { + content = option.content; + break; + } + } + + if (content === null && props.options.length > 0) { + content = props.options[0].content; + } + + return { + ...props, + content: content, + controls: ( + ({ + value: option.value, + label: option.label, + icon: option.icon + }))} + /> + ) + }; +} diff --git a/src/frontend/src/pages/build/BuildIndex.tsx b/src/frontend/src/pages/build/BuildIndex.tsx index bd95117a53..7ad932d08b 100644 --- a/src/frontend/src/pages/build/BuildIndex.tsx +++ b/src/frontend/src/pages/build/BuildIndex.tsx @@ -7,12 +7,12 @@ import { ModelType } from '@lib/enums/ModelType'; import { UserRoles } from '@lib/enums/Roles'; import type { TableFilter } from '@lib/types/Filters'; import { useLocalStorage } from '@mantine/hooks'; -import SegmentedIconControl from '../../components/buttons/SegmentedIconControl'; import OrderCalendar from '../../components/calendar/OrderCalendar'; import PermissionDenied from '../../components/errors/PermissionDenied'; import { PageDetail } from '../../components/nav/PageDetail'; import type { PanelType } from '../../components/panels/Panel'; import { PanelGroup } from '../../components/panels/PanelGroup'; +import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel'; import { useGlobalSettingsState } from '../../states/SettingsStates'; import { useUserState } from '../../states/UserState'; import { PartCategoryFilter } from '../../tables/Filter'; @@ -43,20 +43,6 @@ function BuildOrderCalendar() { ); } -function BuildOverview({ - view -}: { - view: string; -}) { - switch (view) { - case 'calendar': - return ; - case 'table': - default: - return ; - } -} - /** * Build Order index page */ @@ -64,34 +50,35 @@ export default function BuildIndex() { const user = useUserState(); const [buildOrderView, setBuildOrderView] = useLocalStorage({ - key: 'buildOrderView', + key: 'build-order-view', defaultValue: 'table' }); const panels: PanelType[] = useMemo(() => { return [ - { - name: 'buildorders', + SegmentedControlPanel({ + name: 'buildorder', label: t`Build Orders`, - content: , icon: , - controls: ( - }, - { - value: 'calendar', - label: t`Calendar View`, - icon: - } - ]} - /> - ) - } + selection: buildOrderView, + onChange: setBuildOrderView, + options: [ + { + value: 'table', + label: t`Table View`, + icon: , + content: + }, + { + value: 'calendar', + label: t`Calendar View`, + icon: , + content: + } + ] + }) ]; - }, [buildOrderView, setBuildOrderView]); + }, [user, buildOrderView]); if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.build)) { return ; diff --git a/src/frontend/src/pages/purchasing/PurchasingIndex.tsx b/src/frontend/src/pages/purchasing/PurchasingIndex.tsx index 0101f84f21..f946dd22a9 100644 --- a/src/frontend/src/pages/purchasing/PurchasingIndex.tsx +++ b/src/frontend/src/pages/purchasing/PurchasingIndex.tsx @@ -14,68 +14,55 @@ import { useMemo } from 'react'; import { ModelType } from '@lib/enums/ModelType'; import { UserRoles } from '@lib/enums/Roles'; import { useLocalStorage } from '@mantine/hooks'; -import SegmentedIconControl from '../../components/buttons/SegmentedIconControl'; import OrderCalendar from '../../components/calendar/OrderCalendar'; import PermissionDenied from '../../components/errors/PermissionDenied'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/panels/PanelGroup'; +import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel'; import { useUserState } from '../../states/UserState'; import { CompanyTable } from '../../tables/company/CompanyTable'; import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable'; import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable'; -function PurchaseOrderOverview({ - view -}: { - view: string; -}) { - switch (view) { - case 'calendar': - return ( - - ); - case 'table': - default: - return ; - } -} - export default function PurchasingIndex() { const user = useUserState(); - const [purchaseOrderView, setpurchaseOrderView] = useLocalStorage({ - key: 'purchaseOrderView', + const [purchaseOrderView, setPurchaseOrderView] = useLocalStorage({ + key: 'purchase-order-view', defaultValue: 'table' }); const panels = useMemo(() => { return [ - { + SegmentedControlPanel({ name: 'purchaseorders', label: t`Purchase Orders`, icon: , hidden: !user.hasViewRole(UserRoles.purchase_order), - content: , - controls: ( - }, - { - value: 'calendar', - label: t`Calendar View`, - icon: - } - ]} - /> - ) - }, + selection: purchaseOrderView, + onChange: setPurchaseOrderView, + options: [ + { + value: 'table', + label: t`Table View`, + icon: , + content: + }, + { + value: 'calendar', + label: t`Calendar View`, + icon: , + content: ( + + ) + } + ] + }), { name: 'suppliers', label: t`Suppliers`, diff --git a/src/frontend/src/pages/sales/SalesIndex.tsx b/src/frontend/src/pages/sales/SalesIndex.tsx index ffa1e1d5d3..4b4fae9059 100644 --- a/src/frontend/src/pages/sales/SalesIndex.tsx +++ b/src/frontend/src/pages/sales/SalesIndex.tsx @@ -13,57 +13,17 @@ import { useMemo } from 'react'; import { ModelType } from '@lib/enums/ModelType'; import { UserRoles } from '@lib/enums/Roles'; import { useLocalStorage } from '@mantine/hooks'; -import SegmentedIconControl from '../../components/buttons/SegmentedIconControl'; import OrderCalendar from '../../components/calendar/OrderCalendar'; import PermissionDenied from '../../components/errors/PermissionDenied'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/panels/PanelGroup'; +import SegmentedControlPanel from '../../components/panels/SegmentedControlPanel'; import { useUserState } from '../../states/UserState'; import { CompanyTable } from '../../tables/company/CompanyTable'; import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable'; import SalesOrderShipmentTable from '../../tables/sales/SalesOrderShipmentTable'; import { SalesOrderTable } from '../../tables/sales/SalesOrderTable'; -function SalesOrderOverview({ - view -}: { - view: string; -}) { - switch (view) { - case 'calendar': - return ( - - ); - case 'table': - default: - return ; - } -} - -function ReturnOrderOverview({ - view -}: { - view: string; -}) { - switch (view) { - case 'calendar': - return ( - - ); - case 'table': - default: - return ; - } -} - export default function SalesIndex() { const user = useUserState(); @@ -79,27 +39,34 @@ export default function SalesIndex() { const panels = useMemo(() => { return [ - { + SegmentedControlPanel({ name: 'salesorders', label: t`Sales Orders`, icon: , - content: , - controls: ( - }, - { - value: 'calendar', - label: t`Calendar View`, - icon: - } - ]} - /> - ), - hidden: !user.hasViewRole(UserRoles.sales_order) - }, + hidden: !user.hasViewRole(UserRoles.sales_order), + selection: salesOrderView, + onChange: setSalesOrderView, + options: [ + { + value: 'table', + label: t`Table View`, + icon: , + content: + }, + { + value: 'calendar', + label: t`Calendar View`, + icon: , + content: ( + + ) + } + ] + }), { name: 'shipments', label: t`Pending Shipments`, @@ -112,27 +79,34 @@ export default function SalesIndex() { /> ) }, - { + SegmentedControlPanel({ name: 'returnorders', label: t`Return Orders`, icon: , - content: , - controls: ( - }, - { - value: 'calendar', - label: t`Calendar View`, - icon: - } - ]} - /> - ), - hidden: !user.hasViewRole(UserRoles.return_order) - }, + hidden: !user.hasViewRole(UserRoles.return_order), + selection: returnOrderView, + onChange: setReturnOrderView, + options: [ + { + value: 'table', + label: t`Table View`, + icon: , + content: + }, + { + value: 'calendar', + label: t`Calendar View`, + icon: , + content: ( + + ) + } + ] + }), { name: 'customers', label: t`Customers`,