Merge branch 'gbpark-node' of http://39.117.244.52:3000/kjs/ERP-node into jskim-node

This commit is contained in:
kjs
2026-03-11 12:23:52 +09:00
588 changed files with 25062 additions and 13798 deletions

View File

@@ -66,7 +66,7 @@ function DraggableItem({
return (
<div
ref={drag}
className={`flex cursor-move items-center gap-2 rounded border p-2 text-sm hover:border-blue-500 hover:bg-blue-50 ${
className={`flex cursor-move items-center gap-2 rounded border p-2 text-sm hover:border-primary hover:bg-primary/10 ${
isDragging ? "opacity-50" : ""
}`}
>

View File

@@ -15,15 +15,8 @@ export function BarcodeDesignerCanvas() {
const containerRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLDivElement>(null);
const [scale, setScale] = useState(1);
const {
widthMm,
heightMm,
components,
addComponent,
selectComponent,
showGrid,
snapValueToGrid,
} = useBarcodeDesigner();
const { widthMm, heightMm, components, addComponent, selectComponent, showGrid, snapValueToGrid } =
useBarcodeDesigner();
const widthPx = widthMm * MM_TO_PX;
const heightPx = heightMm * MM_TO_PX;
@@ -55,49 +48,46 @@ export function BarcodeDesignerCanvas() {
return () => observer.disconnect();
}, [widthPx, heightPx]);
const [{ isOver }, drop] = useDrop(() => ({
accept: "barcode-component",
drop: (item: { component: BarcodeLabelComponent }, monitor) => {
const canvasEl = canvasRef.current;
if (!canvasEl) return;
const offset = monitor.getClientOffset();
const rect = canvasEl.getBoundingClientRect();
if (!offset) return;
// 스케일 적용된 좌표 → 실제 캔버스 좌표
const s = scale;
let x = (offset.x - rect.left) / s;
let y = (offset.y - rect.top) / s;
x -= item.component.width / 2;
y -= item.component.height / 2;
x = Math.max(0, Math.min(x, widthPx - item.component.width));
y = Math.max(0, Math.min(y, heightPx - item.component.height));
const [{ isOver }, drop] = useDrop(
() => ({
accept: "barcode-component",
drop: (item: { component: BarcodeLabelComponent }, monitor) => {
const canvasEl = canvasRef.current;
if (!canvasEl) return;
const offset = monitor.getClientOffset();
const rect = canvasEl.getBoundingClientRect();
if (!offset) return;
// 스케일 적용된 좌표 → 실제 캔버스 좌표
const s = scale;
let x = (offset.x - rect.left) / s;
let y = (offset.y - rect.top) / s;
x -= item.component.width / 2;
y -= item.component.height / 2;
x = Math.max(0, Math.min(x, widthPx - item.component.width));
y = Math.max(0, Math.min(y, heightPx - item.component.height));
const newComp: BarcodeLabelComponent = {
...item.component,
id: `comp_${uuidv4()}`,
x: snapValueToGrid(x),
y: snapValueToGrid(y),
zIndex: components.length,
};
addComponent(newComp);
},
collect: (m) => ({ isOver: m.isOver() }),
}), [widthPx, heightPx, scale, components.length, addComponent, snapValueToGrid]);
const newComp: BarcodeLabelComponent = {
...item.component,
id: `comp_${uuidv4()}`,
x: snapValueToGrid(x),
y: snapValueToGrid(y),
zIndex: components.length,
};
addComponent(newComp);
},
collect: (m) => ({ isOver: m.isOver() }),
}),
[widthPx, heightPx, scale, components.length, addComponent, snapValueToGrid],
);
// 스케일된 캔버스가 컨테이너 안에 들어가도록 fit (하단 잘림 방지)
const scaledW = widthPx * scale;
const scaledH = heightPx * scale;
return (
<div
ref={containerRef}
className="flex min-h-0 flex-1 items-center justify-center overflow-auto bg-gray-100 p-6"
>
<div ref={containerRef} className="bg-muted flex flex-1 items-center justify-center overflow-auto p-6">
{/* 래퍼: 스케일된 크기만큼 차지해서 flex로 정확히 가운데 + 하단 잘림 방지 */}
<div
className="flex shrink-0 items-center justify-center"
style={{ width: scaledW, height: scaledH }}
>
<div className="flex shrink-0 items-center justify-center" style={{ width: scaledW, height: scaledH }}>
<div
style={{
transform: `scale(${scale})`,

View File

@@ -202,7 +202,7 @@ export function BarcodeLabelCanvasComponent({ component }: Props) {
}}
/>
) : (
<div className="flex h-full w-full items-center justify-center bg-gray-100 text-xs text-gray-400">
<div className="flex h-full w-full items-center justify-center bg-muted text-xs text-muted-foreground/70">
</div>
);
@@ -244,7 +244,7 @@ export function BarcodeLabelCanvasComponent({ component }: Props) {
{selected && component.type !== "line" && (
<div
data-resize-handle
className="absolute bottom-0 right-0 h-2 w-2 cursor-se-resize bg-blue-500"
className="absolute bottom-0 right-0 h-2 w-2 cursor-se-resize bg-primary"
onMouseDown={(e) => {
e.stopPropagation();
setIsResizing(true);

View File

@@ -151,7 +151,7 @@ export function BarcodePrintPreviewModal({
</p>
{/* 미리보기 캔버스 (축소) */}
<div className="flex justify-center rounded border bg-gray-100 p-4">
<div className="flex justify-center rounded border bg-muted p-4">
<div
className="relative bg-white shadow"
style={{