Fix seatmap slot matching and update member modal layout

This commit is contained in:
hyunho
2026-03-27 18:12:20 +09:00
parent d66614123e
commit 24852d4401
11 changed files with 517 additions and 89 deletions

View File

@@ -861,6 +861,7 @@ function renderDxfSeatMapBoard() {
const viewerUrl = resolveAppUrl(`/api/seat-maps/${seatMapState.seatMap.id}/viewer`);
seatMapBoard.innerHTML = `
<div class="seatmap-dxf-frame-shell">
<div class="seatmap-dxf-drop-overlay" data-seatmap-drop-overlay></div>
<iframe
id="seatmap-dxf-frame"
class="seatmap-dxf-frame"
@@ -874,6 +875,12 @@ function renderDxfSeatMapBoard() {
setupSeatMapViewerFrame();
}
function setSeatMapDropOverlayActive(active) {
const overlay = seatMapBoard?.querySelector("[data-seatmap-drop-overlay]");
if (!overlay) return;
overlay.classList.toggle("is-active", Boolean(active && seatMapState.editMode));
}
function getDraftPlacedSlotKeys() {
const slotMap = getSeatSlotMap();
return (seatMapState.draftPlacements || [])
@@ -917,6 +924,13 @@ function syncSeatMapViewerFrame() {
);
}
function scheduleSeatMapViewerSync() {
syncSeatMapViewerFrame();
window.setTimeout(() => {
syncSeatMapViewerFrame();
}, 80);
}
function renderSeatMapActions() {
const hasSeatMap = Boolean(seatMapState.seatMap);
const adminMode = isSeatMapAdminMode();
@@ -940,6 +954,7 @@ function updateSeatMapDraftUi() {
function setupSeatMapViewerFrame() {
const frame = seatMapBoard?.querySelector("#seatmap-dxf-frame");
const overlay = seatMapBoard?.querySelector("[data-seatmap-drop-overlay]");
if (!frame) return;
frame.addEventListener("load", () => {
@@ -950,26 +965,42 @@ function setupSeatMapViewerFrame() {
const canvas = frameDocument?.getElementById("canvas");
if (!frameWindow || !frameDocument || !canvas || !frameWindow.__mhSeatmap) return;
canvas.addEventListener("dragover", (event) => {
event.preventDefault();
event.dataTransfer.dropEffect = "move";
});
canvas.addEventListener("drop", (event) => {
const handleDrop = (event) => {
event.preventDefault();
const memberId = getDraggedMemberId(event);
if (!memberId) return;
const rect = canvas.getBoundingClientRect();
if (!memberId) {
setSeatMapStatus("드롭 감지됨: memberId를 읽지 못했습니다.", "error");
return;
}
const frameRect = frame.getBoundingClientRect();
const canvasRect = canvas.getBoundingClientRect();
const picked = frameWindow.__mhSeatmap.pickChairAt(
event.clientX - rect.left,
event.clientY - rect.top,
event.clientX - frameRect.left - canvasRect.left,
event.clientY - frameRect.top - canvasRect.top,
);
if (!picked?.key) return;
if (!picked?.key) {
setSeatMapStatus(`드롭 감지됨: 좌석 인식 실패 (memberId=${memberId})`, "error");
return;
}
const matchedSlot = (seatMapState.slots || []).find((item) => String(item.slot_key) === String(picked.key));
if (!matchedSlot) return;
if (!matchedSlot) {
setSeatMapStatus(`드롭 감지됨: slot 매칭 실패 (${picked.key})`, "error");
return;
}
upsertDraftPlacementForSlot(memberId, Number(matchedSlot.id));
setSeatMapStatus(`드롭 성공: memberId=${memberId}, slot=${picked.key}, slotId=${matchedSlot.id}`, "info");
updateSeatMapDraftUi();
});
};
const handleDragOver = (event) => {
event.preventDefault();
event.dataTransfer.dropEffect = "move";
};
canvas.addEventListener("dragover", handleDragOver);
canvas.addEventListener("drop", handleDrop);
overlay?.addEventListener("dragover", handleDragOver);
overlay?.addEventListener("drop", handleDrop);
}, { once: true });
}
@@ -1666,12 +1697,14 @@ document.addEventListener("dragstart", (event) => {
const memberId = Number(card.dataset.memberId);
if (!memberId) return;
seatMapState.draggingMemberId = memberId;
setSeatMapDropOverlayActive(true);
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("text/plain", String(memberId));
});
document.addEventListener("dragend", () => {
seatMapState.draggingMemberId = null;
setSeatMapDropOverlayActive(false);
});
document.addEventListener("click", () => {

View File

@@ -623,6 +623,7 @@ body {
}
.seatmap-dxf-frame-shell {
position: relative;
width: 100%;
height: 100%;
min-height: 0;
@@ -630,6 +631,18 @@ body {
overflow: hidden;
}
.seatmap-dxf-drop-overlay {
position: absolute;
inset: 0;
z-index: 3;
pointer-events: none;
background: transparent;
}
.seatmap-dxf-drop-overlay.is-active {
pointer-events: auto;
}
.seatmap-dxf-frame {
display: block;
width: 100%;