Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import React, { FC, useState, useEffect, useRef } from 'react';
import BreadcrumbEditModal from './breadcrumb-edit-modal';
import { ViewMode } from '../../typings';
import styles from './breadcrumb.module.scss';

interface BreadcrumbProps {
warehouseIds: string[];
viewMode: ViewMode;
showBreadcrumbEditButton?: (warehouseIds: string[]) => boolean;
onWarehouseClick?: (warehouseId: string, index: number) => void;
onNameChange?: (name: string) => Promise<void>;
}

const Breadcrumb: FC<BreadcrumbProps> = ({ warehouseIds, onWarehouseClick, onNameChange }) => {
const Breadcrumb: FC<BreadcrumbProps> = ({
warehouseIds,
viewMode,
showBreadcrumbEditButton = (): boolean => true,
onWarehouseClick,
onNameChange,
}) => {
const [showDropdown, setShowDropdown] = useState(false);
const [showEditModal, setShowEditModal] = useState(false);
const [editingIndex, setEditingIndex] = useState<number>(-1);
Expand Down Expand Up @@ -141,17 +150,19 @@ const Breadcrumb: FC<BreadcrumbProps> = ({ warehouseIds, onWarehouseClick, onNam
<div className={styles.breadcrumbSection}>
<div className={styles.warehouseIdSection}>
{shouldCollapse ? renderCollapsedBreadcrumb() : renderFullBreadcrumb()}
<button className={styles.editButton} onClick={handleEditClick} title="編輯當前區域名稱">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
d="M11.7803 2.21967C12.0732 1.92678 12.5481 1.92678 12.841 2.21967L13.7803 3.15901C14.0732 3.45191 14.0732 3.92678 13.7803 4.21967L5.11364 12.8863L2.66697 13.3333L3.11364 10.8863L11.7803 2.21967Z"
stroke="currentColor"
strokeWidth="1.33"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
{viewMode === ViewMode.EDIT && showBreadcrumbEditButton(warehouseIds) && (
<button className={styles.editButton} onClick={handleEditClick} title="編輯當前區域名稱">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
d="M11.7803 2.21967C12.0732 1.92678 12.5481 1.92678 12.841 2.21967L13.7803 3.15901C14.0732 3.45191 14.0732 3.92678 13.7803 4.21967L5.11364 12.8863L2.66697 13.3333L3.11364 10.8863L11.7803 2.21967Z"
stroke="currentColor"
strokeWidth="1.33"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
)}
</div>
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ interface ReactFlowCanvasProps {
onNodeMouseEnter?: (event: React.MouseEvent, node: ReactFlowNode) => void;
onNodeMouseLeave?: (event: React.MouseEvent, node: ReactFlowNode) => void;
onNodeClick?: (event: React.MouseEvent, node: ReactFlowNode) => void;
onNodeDoubleClick?: (event: React.MouseEvent, node: ReactFlowNode) => void;
showBackground?: boolean;
}

Expand Down Expand Up @@ -118,6 +119,7 @@ const ReactFlowCanvas: FC<ReactFlowCanvasProps> = ({
onNodeMouseEnter,
onNodeMouseLeave,
onNodeClick,
onNodeDoubleClick,
showBackground = true,
}) => {
// console.log('🖼️ ReactFlowCanvas 接收到 showBackground:', showBackground);
Expand Down Expand Up @@ -258,6 +260,7 @@ const ReactFlowCanvas: FC<ReactFlowCanvasProps> = ({
onNodeMouseEnter={onNodeMouseEnter}
onNodeMouseLeave={onNodeMouseLeave}
onNodeClick={onNodeClick}
onNodeDoubleClick={onNodeDoubleClick}
nodeTypes={nodeTypes}
className={styles.reactFlowCanvas}
style={{ background: '#F5F5F5' }}
Expand All @@ -271,7 +274,7 @@ const ReactFlowCanvas: FC<ReactFlowCanvasProps> = ({
panOnDrag={viewMode === ViewMode.VIEW || (viewMode === ViewMode.EDIT && drawingMode === DrawingMode.NONE)}
panOnScroll={false}
zoomOnScroll={true}
zoomOnDoubleClick={viewMode === ViewMode.EDIT && drawingMode !== DrawingMode.PEN}
zoomOnDoubleClick={false}
nodeOrigin={[0, 0]}
preventScrolling={true}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ const WMSMapContent: FC<WMSMapContentProps> = ({
selectedColor,
viewMode,
colorPalette,
showBreadcrumbEditButton,
onEditModeChange,
onToggleRectangleTool,
onTogglePenTool,
onColorChange,
onNodeClick,
onNodeDoubleClick,
onSave,
onBreadcrumbClick,
onNameChange,
Expand Down Expand Up @@ -674,11 +676,73 @@ const WMSMapContent: FC<WMSMapContentProps> = ({
[viewMode],
);

const clickTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

useEffect(
() => (): void => {
if (clickTimerRef.current) {
clearTimeout(clickTimerRef.current);
clickTimerRef.current = null;
}
},
[],
);

const handleNodeClick = useCallback(
(_event: React.MouseEvent, node: ReactFlowNode) => {
const flowNode = node as unknown as FlowNode;

debugLog('events', 'Node clicked (React Flow)', {
const fireClick = (): void => {
debugLog('events', 'Node clicked (React Flow)', {
id: flowNode.id.slice(-4),
type: flowNode.type,
viewMode,
editMode,
});

logNodeData(flowNode);

if (onNodeClick) {
const nodeClickInfo = transformNodeToClickInfo(flowNode);

if (nodeClickInfo) {
debugLog('events', '將點擊資訊傳遞給父組件:', nodeClickInfo);
onNodeClick(nodeClickInfo);
}
}
};

// 沒有訂閱雙擊事件時,單擊直接觸發避免引入無謂的 350ms 延遲
if (!onNodeDoubleClick) {
fireClick();

return;
}

// 延遲觸發 click,讓 double click 有機會取消
if (clickTimerRef.current) {
clearTimeout(clickTimerRef.current);
}

clickTimerRef.current = setTimeout(() => {
clickTimerRef.current = null;
fireClick();
}, 350);
},
[viewMode, editMode, onNodeClick, onNodeDoubleClick],
);

const handleNodeDoubleClick = useCallback(
(_event: React.MouseEvent, node: ReactFlowNode) => {
// 取消待執行的 click,避免 double click 同時觸發 click
if (clickTimerRef.current) {
clearTimeout(clickTimerRef.current);
clickTimerRef.current = null;
}

const flowNode = node as unknown as FlowNode;

debugLog('events', 'Node double clicked (React Flow)', {
id: flowNode.id.slice(-4),
type: flowNode.type,
viewMode,
Expand All @@ -687,16 +751,16 @@ const WMSMapContent: FC<WMSMapContentProps> = ({

logNodeData(flowNode);

if (onNodeClick) {
const nodeClickInfo = transformNodeToClickInfo(flowNode);
if (onNodeDoubleClick) {
const nodeDoubleClickInfo = transformNodeToClickInfo(flowNode);

if (nodeClickInfo) {
debugLog('events', '將點擊資訊傳遞給父組件:', nodeClickInfo);
onNodeClick(nodeClickInfo);
if (nodeDoubleClickInfo) {
debugLog('events', '將雙擊資訊傳遞給父組件:', nodeDoubleClickInfo);
onNodeDoubleClick(nodeDoubleClickInfo);
}
}
},
[viewMode, editMode, onNodeClick],
[viewMode, editMode, onNodeDoubleClick],
);

const handleToggleBackground = useCallback((show: boolean) => {
Expand Down Expand Up @@ -811,7 +875,13 @@ const WMSMapContent: FC<WMSMapContentProps> = ({

return (
<>
<Breadcrumb warehouseIds={warehouseIds} onWarehouseClick={onBreadcrumbClick} onNameChange={onNameChange} />
<Breadcrumb
warehouseIds={warehouseIds}
viewMode={viewMode}
showBreadcrumbEditButton={showBreadcrumbEditButton}
onWarehouseClick={onBreadcrumbClick}
onNameChange={onNameChange}
/>
{viewMode === ViewMode.EDIT && (
<Toolbar
onUpload={handleUpload}
Expand Down Expand Up @@ -855,6 +925,7 @@ const WMSMapContent: FC<WMSMapContentProps> = ({
onNodeMouseEnter={handleNodeMouseEnter}
onNodeMouseLeave={handleNodeMouseLeave}
onNodeClick={handleNodeClick}
onNodeDoubleClick={handleNodeDoubleClick}
showBackground={showBackground}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ export const WMSMapModalContent = ({
selectedColor,
viewMode,
colorPalette,
showBreadcrumbEditButton,
onEditModeChange,
onToggleRectangleTool,
onTogglePenTool,
onColorChange,
onNodeClick,
onNodeDoubleClick,
onSave,
onBreadcrumbClick,
onNameChange,
Expand All @@ -38,11 +40,13 @@ export const WMSMapModalContent = ({
selectedColor={selectedColor}
viewMode={viewMode}
colorPalette={colorPalette}
showBreadcrumbEditButton={showBreadcrumbEditButton}
onEditModeChange={onEditModeChange}
onToggleRectangleTool={onToggleRectangleTool}
onTogglePenTool={onTogglePenTool}
onColorChange={onColorChange}
onNodeClick={onNodeClick}
onNodeDoubleClick={onNodeDoubleClick}
onSave={onSave}
onBreadcrumbClick={onBreadcrumbClick}
onNameChange={onNameChange}
Expand All @@ -63,7 +67,9 @@ const WMSMapModalContainer: FC<WMSMapModalProps> = ({
onClose,
viewMode = ViewMode.EDIT,
colorPalette,
showBreadcrumbEditButton,
onNodeClick,
onNodeDoubleClick,
onSave,
onBreadcrumbClick,
onNameChange,
Expand Down Expand Up @@ -139,11 +145,13 @@ const WMSMapModalContainer: FC<WMSMapModalProps> = ({
selectedColor={selectedColor}
viewMode={viewMode}
colorPalette={colorPalette}
showBreadcrumbEditButton={showBreadcrumbEditButton}
onEditModeChange={handleEditModeChange}
onToggleRectangleTool={handleToggleRectangleTool}
onTogglePenTool={handleTogglePenTool}
onColorChange={handleColorChange}
onNodeClick={onNodeClick}
onNodeDoubleClick={onNodeDoubleClick}
onSave={onSave}
onBreadcrumbClick={onBreadcrumbClick}
onNameChange={onNameChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export interface WMSMapModalProps {
open: boolean;
viewMode?: ViewMode;
colorPalette?: string[];
showBreadcrumbEditButton?: (warehouseIds: string[]) => boolean;
onNodeClick?: (nodeInfo: WMSNodeClickInfo) => void;
onNodeDoubleClick?: (nodeInfo: WMSNodeClickInfo) => void;
onSave?: (mapData: Map) => void;
onBreadcrumbClick?: (warehouseId: string, index: number) => void;
onNameChange?: (name: string) => Promise<void>;
Expand All @@ -26,11 +28,13 @@ export interface WMSMapContentProps {
selectedColor: string;
viewMode: ViewMode;
colorPalette?: string[];
showBreadcrumbEditButton?: (warehouseIds: string[]) => boolean;
onEditModeChange: (mode: EditMode) => void;
onToggleRectangleTool: () => void;
onTogglePenTool: () => void;
onColorChange: (color: string) => void;
onNodeClick?: (nodeInfo: WMSNodeClickInfo) => void;
onNodeDoubleClick?: (nodeInfo: WMSNodeClickInfo) => void;
onSave?: (mapData: Map) => void;
onBreadcrumbClick?: (warehouseId: string, index: number) => void;
onNameChange?: (name: string) => Promise<void>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const meta: Meta<typeof WMSMapModal> = {
open: true,
onClose: action('onClose'),
onNodeClick: action('onNodeClick'),
onNodeDoubleClick: action('onNodeDoubleClick'),
onSave: action('onSave'),
onBreadcrumbClick: action('onBreadcrumbClick'),
onUpload: async (files: File[]): Promise<string[]> => {
Expand Down
Loading