Skip to content

Commit b0f588f

Browse files
committed
feat: implement draf and drop functionality
1 parent f3ce6d7 commit b0f588f

1 file changed

Lines changed: 76 additions & 4 deletions

File tree

src/pages/MapPage/index.tsx

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const MapPage = () => {
6767
const defaultLinePathsRef = useRef<[number, number][][]>([]);
6868
const pendingPinkMarkerRef = useRef<L.Marker | null>(null);
6969
const pendingMemorialMarkerRef = useRef<L.Marker | null>(null);
70+
const centralSiteRef = useRef<PendingSite | null>(null);
7071

7172
useEffect(() => {
7273
activeProjectRef.current = activeProject;
@@ -76,6 +77,10 @@ const MapPage = () => {
7677
activeMemorialTypeRef.current = activeMemorialType;
7778
}, [activeMemorialType]);
7879

80+
useEffect(() => {
81+
centralSiteRef.current = centralSite;
82+
}, [centralSite]);
83+
7984
useEffect(() => {
8085
const bootstrap = async () => {
8186
try {
@@ -140,6 +145,12 @@ const MapPage = () => {
140145
setPendingPinkTarget({ lat: e.latlng.lat, lng: e.latlng.lng });
141146
return;
142147
}
148+
if (activeMemorialTypeRef.current === "central" && centralSiteRef.current) {
149+
if (!confirm("ניתן לבחור רק אנדרטה מרכזית אחת. האם להחליף את הקיימת?")) {
150+
return;
151+
}
152+
setCentralSite(null);
153+
}
143154
setPendingMemorialTarget({
144155
lat: e.latlng.lat,
145156
lng: e.latlng.lng,
@@ -320,6 +331,65 @@ const MapPage = () => {
320331
};
321332
const isEntryModalOpen = Boolean(pendingPinkTarget || pendingMemorialTarget);
322333

334+
const ghostRef = useRef<HTMLDivElement | null>(null);
335+
336+
const handleToolbarDragStart = (e: React.PointerEvent, type: "central" | "local") => {
337+
const startX = e.clientX;
338+
const startY = e.clientY;
339+
let dragging = false;
340+
const iconSrc = type === "central" ? regionalMemorialIconUrl : localMemorialIconUrl;
341+
342+
const onMove = (ev: PointerEvent) => {
343+
if (!dragging) {
344+
const dx = ev.clientX - startX;
345+
const dy = ev.clientY - startY;
346+
if (dx * dx + dy * dy < 25) return;
347+
dragging = true;
348+
const ghost = document.createElement("div");
349+
ghost.style.cssText = "position:fixed;pointer-events:none;z-index:10000;opacity:0.85;transform:translate(-50%,-50%)";
350+
const img = document.createElement("img");
351+
img.src = iconSrc;
352+
img.style.cssText = "width:40px;height:40px;filter:drop-shadow(0 2px 6px rgba(0,0,0,0.4))";
353+
ghost.appendChild(img);
354+
document.body.appendChild(ghost);
355+
ghostRef.current = ghost;
356+
}
357+
if (ghostRef.current) {
358+
ghostRef.current.style.left = `${ev.clientX}px`;
359+
ghostRef.current.style.top = `${ev.clientY}px`;
360+
}
361+
};
362+
363+
const onUp = (ev: PointerEvent) => {
364+
document.removeEventListener("pointermove", onMove);
365+
document.removeEventListener("pointerup", onUp);
366+
if (ghostRef.current) {
367+
ghostRef.current.remove();
368+
ghostRef.current = null;
369+
}
370+
if (!dragging || !mapRef.current) return;
371+
372+
const mapEl = document.getElementById("map");
373+
if (!mapEl) return;
374+
const rect = mapEl.getBoundingClientRect();
375+
const x = ev.clientX - rect.left;
376+
const y = ev.clientY - rect.top;
377+
if (x < 0 || y < 0 || x > rect.width || y > rect.height) return;
378+
379+
const latlng = mapRef.current.containerPointToLatLng([x, y]);
380+
381+
if (type === "central" && centralSiteRef.current) {
382+
if (!confirm("ניתן לבחור רק אנדרטה מרכזית אחת. האם להחליף את הקיימת?")) return;
383+
setCentralSite(null);
384+
}
385+
386+
setPendingMemorialTarget({ lat: latlng.lat, lng: latlng.lng, type });
387+
};
388+
389+
document.addEventListener("pointermove", onMove);
390+
document.addEventListener("pointerup", onUp);
391+
};
392+
323393
const handleClearPink = () => {
324394
if (pinkNodes.length === 0) return;
325395
if (!confirm("למחוק את כל נקודות הקו הוורוד?")) return;
@@ -490,14 +560,15 @@ const MapPage = () => {
490560
type="button"
491561
className={`memorial-toolbar-section ${activeMemorialType === "central" ? "memorial-toolbar-active" : ""}`}
492562
onClick={() => setActiveMemorialType("central")}
563+
onPointerDown={(e) => handleToolbarDragStart(e, "central")}
493564
>
494565
<div className="memorial-toolbar-drag-item">
495-
<img src={regionalMemorialIconUrl} alt="" className="memorial-toolbar-icon" />
566+
<img src={regionalMemorialIconUrl} alt="" className="memorial-toolbar-icon" draggable={false} />
496567
</div>
497568
<div className="memorial-toolbar-item-text">
498569
<span className="memorial-toolbar-item-label">אנדרטה מרכזית אזורית</span>
499570
<span className="memorial-toolbar-item-value">
500-
{centralSite ? centralSite.name || "—" : "ניתן לבחור אחת בלבד"}
571+
{centralSite ? centralSite.name || "—" : "גררו למפה או לחצו"}
501572
</span>
502573
</div>
503574
</button>
@@ -508,13 +579,14 @@ const MapPage = () => {
508579
type="button"
509580
className={`memorial-toolbar-section ${activeMemorialType === "local" ? "memorial-toolbar-active" : ""}`}
510581
onClick={() => setActiveMemorialType("local")}
582+
onPointerDown={(e) => handleToolbarDragStart(e, "local")}
511583
>
512584
<div className="memorial-toolbar-drag-item">
513-
<img src={localMemorialIconUrl} alt="" className="memorial-toolbar-icon" />
585+
<img src={localMemorialIconUrl} alt="" className="memorial-toolbar-icon" draggable={false} />
514586
</div>
515587
<div className="memorial-toolbar-item-text">
516588
<span className="memorial-toolbar-item-label">אנדרטות מקומיות ({localSites.length})</span>
517-
<span className="memorial-toolbar-item-value">לחצו על המפה להוספה</span>
589+
<span className="memorial-toolbar-item-value">גררו למפה או לחצו</span>
518590
</div>
519591
</button>
520592

0 commit comments

Comments
 (0)