324 lines
9.0 KiB
JavaScript
324 lines
9.0 KiB
JavaScript
import { PureComponent, createElement } from 'react';
|
|
import Badge from '@mui/material/Badge';
|
|
import Inventory2Icon from '@mui/icons-material/Inventory2';
|
|
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
|
|
import AssignmentIcon from '@mui/icons-material/Assignment';
|
|
import PeopleIcon from '@mui/icons-material/People';
|
|
import InfoIcon from '@mui/icons-material/Info';
|
|
import ViewListIcon from '@mui/icons-material/ViewList';
|
|
import CategoryIcon from '@mui/icons-material/Category';
|
|
import WarehouseIcon from '@mui/icons-material/Warehouse';
|
|
import CopyrightIcon from '@mui/icons-material/Copyright';
|
|
import ListAltIcon from '@mui/icons-material/ListAlt';
|
|
import GroupsIcon from '@mui/icons-material/Groups';
|
|
import AddBoxIcon from '@mui/icons-material/AddBox';
|
|
import StorefrontIcon from '@mui/icons-material/Storefront';
|
|
import RequestQuoteIcon from '@mui/icons-material/RequestQuote';
|
|
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
|
|
import LabelIcon from '@mui/icons-material/Label';
|
|
import TuneIcon from '@mui/icons-material/Tune';
|
|
import HistoryIcon from '@mui/icons-material/History';
|
|
import PublicIcon from '@mui/icons-material/Public';
|
|
import BarChartIcon from '@mui/icons-material/BarChart';
|
|
import { isKategorienPath } from './components/category/categoryRoute';
|
|
import { deliveryEditorAutomat } from './automats/deliveryEditorAutomat';
|
|
|
|
class DeliveryNavIcon extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
const state = deliveryEditorAutomat.state;
|
|
const isDraft = state.id == null && state.deliveryId == null;
|
|
this.state = {
|
|
hasDraft: isDraft && (state.lines?.length || 0) > 0,
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.unsub = deliveryEditorAutomat.subscribe(this, (state) => {
|
|
const isDraft = state.id == null && state.deliveryId == null;
|
|
return {
|
|
hasDraft: isDraft && (state.lines?.length || 0) > 0,
|
|
};
|
|
});
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.unsub?.();
|
|
}
|
|
|
|
render() {
|
|
const { hasDraft } = this.state;
|
|
const { sx, ...rest } = this.props;
|
|
return createElement(LocalShippingIcon, {
|
|
...rest,
|
|
sx: [
|
|
...(Array.isArray(sx) ? sx : sx ? [sx] : []),
|
|
(theme) => (hasDraft ? { color: theme.nav?.itemActiveAccent || '#2dd4bf' } : null),
|
|
],
|
|
});
|
|
}
|
|
}
|
|
|
|
export const NAV_ITEMS = [
|
|
{
|
|
path: '/artikel',
|
|
label: 'Artikel',
|
|
icon: Inventory2Icon,
|
|
help: 'Artikelübersicht, Stammdaten, Barcodes und Bestandsverwaltung',
|
|
},
|
|
{
|
|
path: '/lieferung',
|
|
label: 'Lieferung',
|
|
icon: DeliveryNavIcon,
|
|
help: 'Wareneingänge verwalten, Lieferungen buchen und Lieferscheine erfassen',
|
|
},
|
|
{
|
|
path: '/auftrag',
|
|
label: 'Auftrag',
|
|
icon: AssignmentIcon,
|
|
help: 'Kundenangebote kalkulieren und Bestellungen abwickeln',
|
|
},
|
|
{
|
|
path: '/kunde',
|
|
label: 'Kunde',
|
|
icon: PeopleIcon,
|
|
help: 'Kundenstammdaten, Adressen, Ansprechpartner und Kundengruppen',
|
|
},
|
|
{
|
|
path: '/infos',
|
|
label: 'Infos',
|
|
icon: InfoIcon,
|
|
help: 'Systemstatus, Serververbindung und Mandanteneinstellungen',
|
|
},
|
|
];
|
|
|
|
class DeliveryNeuIcon extends PureComponent {
|
|
constructor(props) {
|
|
super(props);
|
|
const state = deliveryEditorAutomat.state;
|
|
const isDraft = state.id == null && state.deliveryId == null;
|
|
this.state = {
|
|
badgeCount: isDraft ? (state.lines?.length || 0) : 0,
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.unsub = deliveryEditorAutomat.subscribe(this, (state) => {
|
|
const isDraft = state.id == null && state.deliveryId == null;
|
|
return {
|
|
badgeCount: isDraft ? (state.lines?.length || 0) : 0,
|
|
};
|
|
});
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.unsub?.();
|
|
}
|
|
|
|
render() {
|
|
return createElement(
|
|
Badge,
|
|
{
|
|
badgeContent: this.state.badgeCount,
|
|
invisible: !this.state.badgeCount,
|
|
color: 'primary',
|
|
max: 999,
|
|
},
|
|
createElement(AddBoxIcon, this.props)
|
|
);
|
|
}
|
|
}
|
|
|
|
export const SUB_NAV = {
|
|
'/artikel': [
|
|
{
|
|
segment: '',
|
|
label: 'Liste',
|
|
title: 'Artikel',
|
|
icon: ViewListIcon,
|
|
help: 'Gesamtliste aller Artikel durchsuchen, filtern und öffnen',
|
|
},
|
|
{
|
|
segment: 'kategorien',
|
|
label: 'Kategorieen',
|
|
title: 'Kategorien',
|
|
icon: CategoryIcon,
|
|
help: 'Hierarchischer Kategoriebaum zur Sortimentsgliederung',
|
|
},
|
|
{
|
|
segment: 'lager',
|
|
label: 'Lager',
|
|
icon: WarehouseIcon,
|
|
help: 'Lagerbestände einsehen, Bestandsabgleiche und Lagerplatzverwaltung',
|
|
},
|
|
{
|
|
segment: 'marken',
|
|
label: 'Marken',
|
|
icon: CopyrightIcon,
|
|
help: 'Katalog aller Hersteller und Marken verwalten',
|
|
},
|
|
{
|
|
segment: 'vorlagen',
|
|
label: 'Vorlagen',
|
|
icon: LabelIcon,
|
|
help: 'Druckvorlagen für Etiketten und Barcodes bearbeiten',
|
|
},
|
|
{
|
|
segment: 'merkmale',
|
|
label: 'Merkmale',
|
|
title: 'Merkmale & Attribute',
|
|
icon: TuneIcon,
|
|
help: 'Globale Merkmale, Attribute und Werte verwalten',
|
|
},
|
|
],
|
|
'/lieferung': [
|
|
{
|
|
segment: '',
|
|
label: 'Liste',
|
|
title: 'Lieferungen',
|
|
icon: ListAltIcon,
|
|
help: 'Historie und Status aller Wareneingänge und Lieferungen',
|
|
},
|
|
{
|
|
segment: 'neu',
|
|
label: 'Neu',
|
|
title: 'Neue Lieferung',
|
|
icon: DeliveryNeuIcon,
|
|
help: 'Neuen Wareneingang mit Belegscan und Positionserfassung buchen',
|
|
},
|
|
{
|
|
segment: 'lieferanten',
|
|
label: 'Lieferanten',
|
|
icon: StorefrontIcon,
|
|
help: 'Lieferantenverzeichnis mit hinterlegten Katalogen und Konditionen',
|
|
},
|
|
],
|
|
'/auftrag': [
|
|
{
|
|
segment: '',
|
|
label: 'Angebot',
|
|
title: 'Angebot',
|
|
icon: RequestQuoteIcon,
|
|
help: 'Angebote für Kunden kalkulieren und versenden',
|
|
},
|
|
{
|
|
segment: 'bestellung',
|
|
label: 'Bestellung',
|
|
title: 'Bestellung',
|
|
icon: ShoppingCartIcon,
|
|
help: 'Bestellungen prüfen, freigeben und kommissionieren',
|
|
},
|
|
],
|
|
'/kunde': [
|
|
{
|
|
segment: '',
|
|
label: 'Liste',
|
|
title: 'Kundenliste',
|
|
icon: PeopleIcon,
|
|
help: 'Kundenkartei mit Kontaktdaten und Historie',
|
|
},
|
|
{
|
|
segment: 'neu',
|
|
label: 'neu',
|
|
title: 'Neuer Kunde',
|
|
icon: AddBoxIcon,
|
|
help: 'Neuen Kundenstamm mit Anschriften anlegen',
|
|
},
|
|
{
|
|
segment: 'gruppen',
|
|
label: 'Gruppen',
|
|
title: 'Gruppen',
|
|
icon: GroupsIcon,
|
|
help: 'Kundengruppen für Staffelpreise und Rabatte verwalten',
|
|
},
|
|
],
|
|
'/infos': [
|
|
{
|
|
segment: '',
|
|
label: 'ArticleHistory',
|
|
title: 'ArticleHistory',
|
|
icon: HistoryIcon,
|
|
help: 'Historie aller Artikeländerungen und Ereignisse',
|
|
},
|
|
{
|
|
segment: 'globalhistory',
|
|
label: 'GlobalHistory',
|
|
title: 'GlobalHistory',
|
|
icon: PublicIcon,
|
|
help: 'Globale System- und Änderungshistorie',
|
|
},
|
|
{
|
|
segment: 'statistics',
|
|
label: 'Statistics',
|
|
title: 'Statistics',
|
|
icon: BarChartIcon,
|
|
help: 'Statistische Auswertungen und Kennzahlen',
|
|
},
|
|
],
|
|
};
|
|
|
|
export function isNavItemActive(pathname, navPath) {
|
|
if (navPath === '/artikel') {
|
|
return (
|
|
pathname === navPath ||
|
|
pathname.startsWith(`${navPath}/`) ||
|
|
isKategorienPath(pathname)
|
|
);
|
|
}
|
|
return pathname === navPath || pathname.startsWith(`${navPath}/`);
|
|
}
|
|
|
|
/** Stable across article tab changes (e.g. always `/artikel`). */
|
|
export function resolveActiveNav(pathname) {
|
|
for (const item of NAV_ITEMS) {
|
|
if (isNavItemActive(pathname, item.path)) return item.path;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Active sub-nav segment for a section.
|
|
* `''` = section index, `null` = none (e.g. article / kunde detail).
|
|
*/
|
|
export function resolveActiveSub(pathname, sectionPath) {
|
|
const subNav = SUB_NAV[sectionPath];
|
|
if (!subNav) return null;
|
|
|
|
const knownSegments = new Set(subNav.map((item) => item.segment).filter(Boolean));
|
|
const rest = pathname.slice(sectionPath.length).replace(/^\//, '').split('/')[0];
|
|
const isArticleDetail =
|
|
sectionPath === '/artikel' &&
|
|
!isKategorienPath(pathname) &&
|
|
rest &&
|
|
!knownSegments.has(rest);
|
|
const isKundeDetail =
|
|
sectionPath === '/kunde' && rest && !knownSegments.has(rest);
|
|
const isLieferungDetail =
|
|
sectionPath === '/lieferung' && rest && !knownSegments.has(rest);
|
|
// Angebot neu/edit: /auftrag/neu or /auftrag/:quoteId (not a known sub)
|
|
const isAngebotDoc =
|
|
sectionPath === '/auftrag' && rest && !knownSegments.has(rest);
|
|
if (isArticleDetail || isKundeDetail || isLieferungDetail || isAngebotDoc) {
|
|
return null;
|
|
}
|
|
|
|
// Keep Bestellung active for nested paths (e.g. /auftrag/bestellung/neu).
|
|
if (sectionPath === '/auftrag' && rest && knownSegments.has(rest)) {
|
|
return rest;
|
|
}
|
|
|
|
// Treat /infos/articlehistory as segment ''
|
|
if (sectionPath === '/infos' && rest === 'articlehistory') {
|
|
return '';
|
|
}
|
|
|
|
const active = subNav.find((item) => {
|
|
if (item.segment === 'kategorien') {
|
|
return isKategorienPath(pathname);
|
|
}
|
|
const subPath = item.segment ? `${sectionPath}/${item.segment}` : sectionPath;
|
|
return pathname === subPath || pathname === `${subPath}/`;
|
|
});
|
|
return active ? active.segment : null;
|
|
}
|