u
This commit is contained in:
42
src/components/category/CategoryBreadcrumbs.jsx
Normal file
42
src/components/category/CategoryBreadcrumbs.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Component } from 'react';
|
||||
import Breadcrumbs from '@mui/material/Breadcrumbs';
|
||||
import Link from '@mui/material/Link';
|
||||
|
||||
class CategoryBreadcrumbs extends Component {
|
||||
handleNavigate = (categoryId) => {
|
||||
this.props.onNavigate(categoryId);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { crumbs } = this.props;
|
||||
const visible = (crumbs ?? []).filter((crumb) => crumb.name);
|
||||
if (visible.length === 0) return null;
|
||||
|
||||
return (
|
||||
<Breadcrumbs sx={{ mb: 2 }} aria-label="Kategoriepfad">
|
||||
{visible.map((crumb, index) => (
|
||||
<Link
|
||||
key={crumb.id}
|
||||
component="button"
|
||||
type="button"
|
||||
variant="body2"
|
||||
underline="always"
|
||||
color="inherit"
|
||||
aria-current={index === visible.length - 1 ? 'page' : undefined}
|
||||
onClick={() => this.handleNavigate(crumb.id)}
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.43,
|
||||
p: 0,
|
||||
minWidth: 0,
|
||||
}}
|
||||
>
|
||||
{crumb.name}
|
||||
</Link>
|
||||
))}
|
||||
</Breadcrumbs>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CategoryBreadcrumbs;
|
||||
30
src/components/category/CategoryNameDialog.jsx
Normal file
30
src/components/category/CategoryNameDialog.jsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import NameDialog from '../NameDialog';
|
||||
|
||||
const TITLES = {
|
||||
create: 'Neue Kategorie',
|
||||
edit: 'Kategorie bearbeiten',
|
||||
};
|
||||
|
||||
const SUBMIT_LABELS = {
|
||||
create: 'Anlegen',
|
||||
edit: 'Speichern',
|
||||
};
|
||||
|
||||
export default function CategoryNameDialog({
|
||||
open,
|
||||
mode = 'create',
|
||||
initialName,
|
||||
onClose,
|
||||
onSubmit,
|
||||
}) {
|
||||
return (
|
||||
<NameDialog
|
||||
open={open}
|
||||
title={TITLES[mode]}
|
||||
submitLabel={SUBMIT_LABELS[mode]}
|
||||
initialName={initialName}
|
||||
onClose={onClose}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
);
|
||||
}
|
||||
21
src/components/category/EditCategoryDialog.jsx
Normal file
21
src/components/category/EditCategoryDialog.jsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Component } from 'react';
|
||||
import CategoryNameDialog from './CategoryNameDialog';
|
||||
|
||||
/** Edit flow — wire onSubmit when PUT /api/category/:id exists. */
|
||||
class EditCategoryDialog extends Component {
|
||||
render() {
|
||||
const { open, onClose, initialName, onSubmit } = this.props;
|
||||
|
||||
return (
|
||||
<CategoryNameDialog
|
||||
open={open}
|
||||
mode="edit"
|
||||
initialName={initialName}
|
||||
onClose={onClose}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EditCategoryDialog;
|
||||
56
src/components/category/NewCategoryTile.jsx
Normal file
56
src/components/category/NewCategoryTile.jsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { ActionTile } from '../tiles';
|
||||
import { createCategory as createCategoryThunk } from '../../store/categorySlice';
|
||||
import CategoryNameDialog from './CategoryNameDialog';
|
||||
|
||||
class NewCategoryTile extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { open: false };
|
||||
this.handleOpen = this.handleOpen.bind(this);
|
||||
this.handleClose = this.handleClose.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
}
|
||||
|
||||
handleOpen() {
|
||||
this.setState({ open: true });
|
||||
}
|
||||
|
||||
handleClose() {
|
||||
this.setState({ open: false });
|
||||
}
|
||||
|
||||
async handleSubmit({ name }) {
|
||||
const { parentId } = this.props;
|
||||
await this.props.createCategory({ parentId, name }).unwrap();
|
||||
enqueueSnackbar('Kategorie angelegt.', { variant: 'success' });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { parentId, disabled } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ActionTile
|
||||
label="Neue Kategorie"
|
||||
disabled={disabled || parentId == null}
|
||||
onClick={this.handleOpen}
|
||||
/>
|
||||
<CategoryNameDialog
|
||||
open={this.state.open}
|
||||
mode="create"
|
||||
onClose={this.handleClose}
|
||||
onSubmit={this.handleSubmit}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
createCategory: createCategoryThunk,
|
||||
};
|
||||
|
||||
export default connect(null, mapDispatchToProps)(NewCategoryTile);
|
||||
4
src/components/category/index.js
Normal file
4
src/components/category/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export { default as CategoryNameDialog } from './CategoryNameDialog';
|
||||
export { default as CategoryBreadcrumbs } from './CategoryBreadcrumbs';
|
||||
export { default as NewCategoryTile } from './NewCategoryTile';
|
||||
export { default as EditCategoryDialog } from './EditCategoryDialog';
|
||||
Reference in New Issue
Block a user