모달 열렸을 떄 위젯이 끌리는 현상 해결
This commit is contained in:
parent
8b28107147
commit
809ded3746
|
|
@ -162,6 +162,11 @@ export function CanvasElement({
|
||||||
// 요소 선택 처리
|
// 요소 선택 처리
|
||||||
const handleMouseDown = useCallback(
|
const handleMouseDown = useCallback(
|
||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
|
// 모달이나 다이얼로그가 열려있으면 드래그 무시
|
||||||
|
if (document.querySelector('[role="dialog"]')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 닫기 버튼이나 리사이즈 핸들 클릭 시 무시
|
// 닫기 버튼이나 리사이즈 핸들 클릭 시 무시
|
||||||
if ((e.target as HTMLElement).closest(".element-close, .resize-handle")) {
|
if ((e.target as HTMLElement).closest(".element-close, .resize-handle")) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -192,6 +197,11 @@ export function CanvasElement({
|
||||||
// 리사이즈 핸들 마우스다운
|
// 리사이즈 핸들 마우스다운
|
||||||
const handleResizeMouseDown = useCallback(
|
const handleResizeMouseDown = useCallback(
|
||||||
(e: React.MouseEvent, handle: string) => {
|
(e: React.MouseEvent, handle: string) => {
|
||||||
|
// 모달이나 다이얼로그가 열려있으면 리사이즈 무시
|
||||||
|
if (document.querySelector('[role="dialog"]')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setIsResizing(true);
|
setIsResizing(true);
|
||||||
setResizeStart({
|
setResizeStart({
|
||||||
|
|
@ -522,16 +532,15 @@ export function CanvasElement({
|
||||||
<span className="text-sm font-bold text-gray-800">{element.customTitle || element.title}</span>
|
<span className="text-sm font-bold text-gray-800">{element.customTitle || element.title}</span>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
{/* 설정 버튼 (기사관리 위젯만 자체 설정 UI 사용) */}
|
{/* 설정 버튼 (기사관리 위젯만 자체 설정 UI 사용) */}
|
||||||
{onConfigure &&
|
{onConfigure && !(element.type === "widget" && element.subtype === "driver-management") && (
|
||||||
!(element.type === "widget" && element.subtype === "driver-management") && (
|
<button
|
||||||
<button
|
className="hover:bg-accent0 flex h-6 w-6 items-center justify-center rounded text-gray-400 transition-colors duration-200 hover:text-white"
|
||||||
className="hover:bg-accent0 flex h-6 w-6 items-center justify-center rounded text-gray-400 transition-colors duration-200 hover:text-white"
|
onClick={() => onConfigure(element)}
|
||||||
onClick={() => onConfigure(element)}
|
title="설정"
|
||||||
title="설정"
|
>
|
||||||
>
|
⚙️
|
||||||
⚙️
|
</button>
|
||||||
</button>
|
)}
|
||||||
)}
|
|
||||||
{/* 삭제 버튼 */}
|
{/* 삭제 버튼 */}
|
||||||
<button
|
<button
|
||||||
className="element-close hover:bg-destructive/100 flex h-6 w-6 items-center justify-center rounded text-gray-400 transition-colors duration-200 hover:text-white"
|
className="element-close hover:bg-destructive/100 flex h-6 w-6 items-center justify-center rounded text-gray-400 transition-colors duration-200 hover:text-white"
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,9 @@ export default function YardManagement3DWidget({
|
||||||
};
|
};
|
||||||
|
|
||||||
// 새 레이아웃 생성
|
// 새 레이아웃 생성
|
||||||
const handleCreateLayout = async (name: string, description: string) => {
|
const handleCreateLayout = async (name: string) => {
|
||||||
try {
|
try {
|
||||||
const response = await yardLayoutApi.createLayout({ name, description });
|
const response = await yardLayoutApi.createLayout({ name });
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
await loadLayouts();
|
await loadLayouts();
|
||||||
setIsCreateModalOpen(false);
|
setIsCreateModalOpen(false);
|
||||||
|
|
@ -105,7 +105,7 @@ export default function YardManagement3DWidget({
|
||||||
// 편집 모드: 레이아웃 선택 UI
|
// 편집 모드: 레이아웃 선택 UI
|
||||||
if (isEditMode) {
|
if (isEditMode) {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col bg-white">
|
<div className="widget-interactive-area flex h-full w-full flex-col bg-white">
|
||||||
<div className="flex items-center justify-between border-b p-4">
|
<div className="flex items-center justify-between border-b p-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-semibold text-gray-700">야드 레이아웃 선택</h3>
|
<h3 className="text-sm font-semibold text-gray-700">야드 레이아웃 선택</h3>
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,17 @@ import {
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2, AlertCircle } from "lucide-react";
|
||||||
|
|
||||||
interface YardLayoutCreateModalProps {
|
interface YardLayoutCreateModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onCreate: (name: string, description: string) => Promise<void>;
|
onCreate: (name: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: YardLayoutCreateModalProps) {
|
export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: YardLayoutCreateModalProps) {
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [description, setDescription] = useState("");
|
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
const [isCreating, setIsCreating] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
|
@ -38,9 +37,8 @@ export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: Yar
|
||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await onCreate(name.trim(), description.trim());
|
await onCreate(name.trim());
|
||||||
setName("");
|
setName("");
|
||||||
setDescription("");
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("야드 생성 실패:", error);
|
console.error("야드 생성 실패:", error);
|
||||||
setError(error.message || "야드 생성에 실패했습니다");
|
setError(error.message || "야드 생성에 실패했습니다");
|
||||||
|
|
@ -53,7 +51,6 @@ export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: Yar
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
if (isCreating) return;
|
if (isCreating) return;
|
||||||
setName("");
|
setName("");
|
||||||
setDescription("");
|
|
||||||
setError("");
|
setError("");
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
@ -68,14 +65,13 @@ export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: Yar
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={handleClose}>
|
<Dialog open={isOpen} onOpenChange={handleClose}>
|
||||||
<DialogContent className="sm:max-w-[500px]">
|
<DialogContent className="sm:max-w-[500px]" onPointerDown={(e) => e.stopPropagation()}>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>새 야드 생성</DialogTitle>
|
<DialogTitle>새 야드 생성</DialogTitle>
|
||||||
<DialogDescription>야드의 이름과 설명을 입력하세요</DialogDescription>
|
<DialogDescription>야드 이름을 입력하세요</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="space-y-4 py-4">
|
<div className="space-y-4 py-4">
|
||||||
{/* 야드 이름 */}
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="yard-name">
|
<Label htmlFor="yard-name">
|
||||||
야드 이름 <span className="text-red-500">*</span>
|
야드 이름 <span className="text-red-500">*</span>
|
||||||
|
|
@ -94,21 +90,12 @@ export default function YardLayoutCreateModal({ isOpen, onClose, onCreate }: Yar
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 설명 */}
|
{error && (
|
||||||
<div className="space-y-2">
|
<Alert variant="destructive">
|
||||||
<Label htmlFor="yard-description">설명</Label>
|
<AlertCircle className="h-4 w-4" />
|
||||||
<Textarea
|
<AlertDescription>{error}</AlertDescription>
|
||||||
id="yard-description"
|
</Alert>
|
||||||
value={description}
|
)}
|
||||||
onChange={(e) => setDescription(e.target.value)}
|
|
||||||
placeholder="야드에 대한 설명을 입력하세요 (선택사항)"
|
|
||||||
rows={3}
|
|
||||||
disabled={isCreating}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 에러 메시지 */}
|
|
||||||
{error && <div className="rounded-md bg-red-50 p-3 text-sm text-red-600">{error}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue