Merge pull request 'common/feat/dashboard-map' (#270) from common/feat/dashboard-map into main

Reviewed-on: http://39.117.244.52:3000/kjs/ERP-node/pulls/270
This commit is contained in:
hyeonsu 2025-12-10 16:25:51 +09:00
commit d0801e2ccc
3 changed files with 37 additions and 16 deletions

View File

@ -276,12 +276,12 @@ export function RestApiConnectionModal({ isOpen, onClose, onSave, connection }:
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="max-h-[90vh] max-w-3xl overflow-hidden">
<DialogHeader>
<DialogContent className="flex max-h-[90vh] max-w-3xl flex-col">
<DialogHeader className="flex-shrink-0">
<DialogTitle>{connection ? "REST API 연결 수정" : "새 REST API 연결 추가"}</DialogTitle>
</DialogHeader>
<div className="space-y-6 py-4">
<div className="flex-1 space-y-6 overflow-y-auto py-4 pr-2">
{/* 기본 정보 */}
<div className="space-y-4">
<h3 className="text-sm font-semibold"> </h3>
@ -588,7 +588,7 @@ export function RestApiConnectionModal({ isOpen, onClose, onSave, connection }:
</div>
</div>
<DialogFooter>
<DialogFooter className="flex-shrink-0 border-t pt-4">
<Button type="button" variant="outline" onClick={onClose}>
<X className="mr-2 h-4 w-4" />

View File

@ -526,7 +526,8 @@ function MaterialBox({
case "location-temp":
case "location-dest":
// 베드 타입 Location: 회색 철판들이 데이터 개수만큼 쌓이는 형태
const locPlateCount = placement.material_count || placement.quantity || 5; // 데이터 개수
// 자재가 없으면 0, 있으면 해당 개수 표시 (기본값 5 제거)
const locPlateCount = placement.material_count ?? placement.quantity ?? 0;
const locVisiblePlateCount = locPlateCount; // 데이터 개수만큼 모두 렌더링
const locPlateThickness = 0.15; // 각 철판 두께
const locPlateGap = 0.03; // 철판 사이 미세한 간격
@ -538,8 +539,32 @@ function MaterialBox({
return (
<>
{/* 철판 스택 - 데이터 개수만큼 회색 판 쌓기 (최대 20개) */}
{Array.from({ length: locVisiblePlateCount }).map((_, idx) => {
{/* 자재가 없을 때: 흰색 실선 테두리 바닥판 */}
{locPlateCount === 0 && (
<>
{/* 얇은 흰색 바닥판 */}
<Box
args={[boxWidth, 0.05, boxDepth]}
position={[0, locYOffset + 0.025, 0]}
>
<meshStandardMaterial
color="#f5f5f5"
roughness={0.6}
metalness={0.1}
emissive={isSelected ? "#e5e5e5" : "#000000"}
emissiveIntensity={isSelected ? glowIntensity * 0.2 : 0}
/>
</Box>
{/* 흰색 실선 테두리 */}
<lineSegments position={[0, locYOffset + 0.06, 0]}>
<edgesGeometry args={[new THREE.BoxGeometry(boxWidth, 0.05, boxDepth)]} />
<lineBasicMaterial color="#9ca3af" linewidth={2} />
</lineSegments>
</>
)}
{/* 철판 스택 - 데이터 개수만큼 회색 판 쌓기 */}
{locPlateCount > 0 && Array.from({ length: locVisiblePlateCount }).map((_, idx) => {
const yPos = locPlateBaseY + idx * (locPlateThickness + locPlateGap);
// 약간의 랜덤 오프셋으로 자연스러움 추가
const xOffset = (Math.sin(idx * 0.5) * 0.02);
@ -570,7 +595,7 @@ function MaterialBox({
{/* Location 이름 - 실제 폴리곤 높이 기준, 뒤쪽(+Z)에 배치 */}
{placement.name && (
<Text
position={[0, locYOffset + locVisibleStackHeight + 0.3, boxDepth * 0.3]}
position={[0, locYOffset + (locPlateCount > 0 ? locVisibleStackHeight : 0.1) + 0.3, boxDepth * 0.3]}
rotation={[-Math.PI / 2, 0, 0]}
fontSize={Math.min(boxWidth, boxDepth) * 0.18}
color="#374151"

View File

@ -115,17 +115,13 @@ export function TableHistoryModal({
const getOperationBadge = (type: string) => {
switch (type) {
case "INSERT":
return <Badge className="bg-green-100 text-xs text-green-800"></Badge>;
return <span className="text-sm font-medium text-green-600"></span>;
case "UPDATE":
return <Badge className="bg-blue-100 text-xs text-blue-800"></Badge>;
return <span className="text-sm font-medium text-blue-600"></span>;
case "DELETE":
return <Badge className="bg-red-100 text-xs text-red-800"></Badge>;
return <span className="text-sm font-medium text-red-600"></span>;
default:
return (
<Badge variant="secondary" className="text-xs">
{type}
</Badge>
);
return <span className="text-sm font-medium text-gray-600">{type}</span>;
}
};