u
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Component } from 'react';
|
||||
import { Component, PureComponent } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
@@ -74,7 +74,7 @@ function TopBand({ onSettingsClick, settingsTab, terminalCount }) {
|
||||
/**
|
||||
* Middle row (1/3): gray band — TextField or terminal toggle.
|
||||
*/
|
||||
function MiddleBand({ settingsTab, nameInput, terminals, categoryPosterminalIds, onTerminalToggle, onPhotoUpload, onPhotoDelete, categoryFullHash }) {
|
||||
function MiddleBand({ settingsTab, nameInput, terminals, categoryPosterminalIds, onTerminalToggle, onPhotoUpload, onPhotoDelete, fullHash }) {
|
||||
const fillSx = {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
@@ -121,7 +121,7 @@ function MiddleBand({ settingsTab, nameInput, terminals, categoryPosterminalIds,
|
||||
noWrap
|
||||
sx={{ maxWidth: 80, color: 'text.secondary' }}
|
||||
>
|
||||
{categoryFullHash ? 'Löschen' : 'Hochladen'}
|
||||
{fullHash ? 'Löschen' : 'Hochladen'}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -217,7 +217,7 @@ function BottomRow({ onOpen, editBand }) {
|
||||
* Renders a ThumbHash preview and the full thumbnail as backdrop for a category tile.
|
||||
* ThumbHash is shown immediately as a placeholder; the thumb fades in once loaded.
|
||||
*/
|
||||
class CategoryBackdrop extends Component {
|
||||
class CategoryBackdrop extends PureComponent {
|
||||
state = { thumbLoaded: false };
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@@ -265,13 +265,52 @@ class CategoryBackdrop extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* Category tile (normal mode): no icon, click navigates to the category.
|
||||
* Category tile.
|
||||
*
|
||||
* Normal mode (edit=false): clickable tile with label overlay; click navigates.
|
||||
* Edit mode (edit=true): three rows of 1/3 each —
|
||||
* Top row: sort-handle | settings toggle | drop-handle
|
||||
* Middle row: gray band — TextField, POS toggle, or photo upload
|
||||
* Bottom row: upper half = open-category click zone
|
||||
* lower half = gray band with chevrons + delete
|
||||
*/
|
||||
export class CategoryTile extends Component {
|
||||
state = { settingsTab: -1 }; // -1 = rename, -2 = photo, 0..n-1 = terminal index
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClick?.();
|
||||
};
|
||||
|
||||
handleKeyDown = (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
this.handleClick();
|
||||
}
|
||||
};
|
||||
|
||||
handleSettingsToggle = () => {
|
||||
const { terminals } = this.props;
|
||||
const terminalCount = terminals?.length || 0;
|
||||
this.setState((prev) => {
|
||||
const next = prev.settingsTab + 1;
|
||||
// Cycle: photo (-2) → rename (-1) → terminal 0 → ... → terminal n-1 → photo (-2)
|
||||
const nextTab = next >= terminalCount ? -2 : next;
|
||||
return { settingsTab: nextTab };
|
||||
});
|
||||
};
|
||||
|
||||
handleMiddleBandClick = () => {
|
||||
const { settingsTab } = this.state;
|
||||
const { onPhotoUpload, onPhotoDelete, fullHash } = this.props;
|
||||
if (settingsTab === -2) {
|
||||
if (fullHash) {
|
||||
onPhotoDelete?.();
|
||||
} else {
|
||||
onPhotoUpload?.();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
renderLabel() {
|
||||
const { label, nameInput } = this.props;
|
||||
if (label == null) return null;
|
||||
@@ -304,123 +343,85 @@ export class CategoryTile extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sx, onClick: _onClick, label, thumbHash, fullHash, ...rest } = this.props;
|
||||
return (
|
||||
<Box
|
||||
component="button"
|
||||
type="button"
|
||||
onClick={this.handleClick}
|
||||
{...rest}
|
||||
sx={{
|
||||
...tileBaseSx,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
...sx,
|
||||
}}
|
||||
>
|
||||
<CategoryBackdrop thumbHash={thumbHash} fullHash={fullHash} />
|
||||
<Box sx={{ position: 'absolute', inset: 0, zIndex: 1 }}>
|
||||
{this.renderLabel()}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Category tile for edit mode: three rows of 1/3 each.
|
||||
*
|
||||
* Top row: sort-handle | settings toggle | drop-handle
|
||||
* Middle row: gray band — TextField, POS toggle, or photo upload
|
||||
* Bottom row: upper half = open-category click zone
|
||||
* lower half = gray band with chevrons + delete
|
||||
*/
|
||||
export class CategoryEditTile extends Component {
|
||||
state = { settingsTab: -1 }; // -1 = rename, -2 = photo, 0..n-1 = terminal index
|
||||
|
||||
handleSettingsToggle = () => {
|
||||
const { terminals } = this.props;
|
||||
const terminalCount = terminals?.length || 0;
|
||||
this.setState((prev) => {
|
||||
const next = prev.settingsTab + 1;
|
||||
// Cycle: photo (-2) → rename (-1) → terminal 0 → ... → terminal n-1 → photo (-2)
|
||||
const nextTab = next >= terminalCount ? -2 : next;
|
||||
return { settingsTab: nextTab };
|
||||
});
|
||||
};
|
||||
|
||||
handleMiddleBandClick = () => {
|
||||
const { settingsTab } = this.state;
|
||||
const { onPhotoUpload, onPhotoDelete, categoryFullHash } = this.props;
|
||||
if (settingsTab === -2) {
|
||||
if (categoryFullHash) {
|
||||
onPhotoDelete?.();
|
||||
} else {
|
||||
onPhotoUpload?.();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
sx,
|
||||
edit,
|
||||
label,
|
||||
thumbHash,
|
||||
fullHash,
|
||||
onClick,
|
||||
nameInput,
|
||||
editBand,
|
||||
onOpen,
|
||||
terminals,
|
||||
categoryPosterminalIds,
|
||||
onTerminalToggle,
|
||||
hasTerminals: _hasTerminals,
|
||||
categoryFullHash,
|
||||
thumbHash,
|
||||
onPhotoUpload: _onPhotoUpload,
|
||||
onPhotoDelete: _onPhotoDelete,
|
||||
sx,
|
||||
onPhotoUpload,
|
||||
onPhotoDelete,
|
||||
...rest
|
||||
} = this.props;
|
||||
const { settingsTab } = this.state;
|
||||
|
||||
// Shared by both modes: the thumbnail backdrop.
|
||||
const backdrop = (
|
||||
<CategoryBackdrop thumbHash={thumbHash} fullHash={fullHash} />
|
||||
);
|
||||
|
||||
// Only the overlay differs between normal and edit mode.
|
||||
const overlay = edit ? (
|
||||
<>
|
||||
<TopBand
|
||||
onSettingsClick={this.handleSettingsToggle}
|
||||
settingsTab={settingsTab}
|
||||
terminalCount={terminals?.length || 0}
|
||||
/>
|
||||
<Box
|
||||
onClick={this.handleMiddleBandClick}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '33.33%',
|
||||
bottom: '33.33%',
|
||||
left: 0,
|
||||
right: 0,
|
||||
cursor: settingsTab === -2 ? 'pointer' : 'default',
|
||||
}}
|
||||
>
|
||||
<MiddleBand
|
||||
settingsTab={settingsTab}
|
||||
nameInput={nameInput}
|
||||
terminals={terminals}
|
||||
categoryPosterminalIds={categoryPosterminalIds}
|
||||
onTerminalToggle={onTerminalToggle}
|
||||
fullHash={fullHash}
|
||||
/>
|
||||
</Box>
|
||||
<BottomRow onOpen={onOpen} editBand={editBand} />
|
||||
</>
|
||||
) : (
|
||||
this.renderLabel()
|
||||
);
|
||||
|
||||
return (
|
||||
<Box
|
||||
{...rest}
|
||||
role={edit ? undefined : 'button'}
|
||||
tabIndex={edit ? undefined : 0}
|
||||
onClick={edit ? undefined : this.handleClick}
|
||||
onKeyDown={edit ? undefined : this.handleKeyDown}
|
||||
sx={{
|
||||
...tileBaseSx,
|
||||
cursor: 'default',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
'&:hover': { bgcolor: 'background.paper', boxShadow: 0 },
|
||||
...(edit
|
||||
? { cursor: 'default', '&:hover': { bgcolor: 'background.paper', boxShadow: 0 } }
|
||||
: { cursor: 'pointer', '&:hover': { bgcolor: 'action.hover' } }),
|
||||
...sx,
|
||||
}}
|
||||
>
|
||||
<CategoryBackdrop thumbHash={thumbHash} fullHash={categoryFullHash} />
|
||||
{backdrop}
|
||||
<Box sx={{ position: 'absolute', inset: 0, zIndex: 1 }}>
|
||||
<TopBand
|
||||
onSettingsClick={this.handleSettingsToggle}
|
||||
settingsTab={settingsTab}
|
||||
terminalCount={terminals?.length || 0}
|
||||
/>
|
||||
<Box
|
||||
onClick={this.handleMiddleBandClick}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '33.33%',
|
||||
bottom: '33.33%',
|
||||
left: 0,
|
||||
right: 0,
|
||||
cursor: settingsTab === -2 ? 'pointer' : 'default',
|
||||
}}
|
||||
>
|
||||
<MiddleBand
|
||||
settingsTab={settingsTab}
|
||||
nameInput={nameInput}
|
||||
terminals={terminals}
|
||||
categoryPosterminalIds={categoryPosterminalIds}
|
||||
onTerminalToggle={onTerminalToggle}
|
||||
categoryFullHash={categoryFullHash}
|
||||
/>
|
||||
</Box>
|
||||
<BottomRow onOpen={onOpen} editBand={editBand} />
|
||||
{overlay}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export { TILE_SIZE, Tile, tileBaseSx } from 'dashgui/tiles';
|
||||
export { BackTile } from './BackTile';
|
||||
export { CategoryTile, CategoryEditTile } from './CategoryTile';
|
||||
export { CategoryTile } from './CategoryTile';
|
||||
export { ArticleTile } from './ArticleTile';
|
||||
export { ActionTile } from './ActionTile';
|
||||
|
||||
Reference in New Issue
Block a user