diff --git a/map4.js b/map4.js index 7698a15..714760c 100644 --- a/map4.js +++ b/map4.js @@ -19,21 +19,20 @@ let currentGroup = ""; let currentUser = ""; let isHost = false; -let currentHostName = ""; // DB に記録されたホスト名 +let currentHostName = ""; // Supabase に保存されているホスト名 let map; let selfMarker = null; let otherMarkers = []; let latestByDevice = {}; let allMembers = []; - let lastLat = null; let lastLng = null; -// 駅 +// 駅関連 let stationMarkers = []; -// 待ち合わせ +// 待ち合わせ関連 let targetMarker = null; let targetLat = null; let targetLng = null; @@ -55,23 +54,36 @@ // =================================== function loadParams() { const p = new URLSearchParams(location.search); - currentGroup = p.get("group") || ""; - currentUser = p.get("user") || ""; + currentGroup = p.get("group"); + currentUser = p.get("user"); const hostParam = p.get("host"); isHost = hostParam === "1" || hostParam === "true"; document.getElementById("groupName").textContent = currentGroup; document.getElementById("userName").textContent = currentUser; - document.getElementById("hostStatus").textContent = - isHost ? "あなたはホストです" : "一般メンバーです"; + document.getElementById("hostStatus").textContent = isHost + ? "あなたはホストです" + : "一般メンバーです"; localStorage.setItem("group", currentGroup); localStorage.setItem("userName", currentUser); + + // ★ host=1 なら Supabase 側のホスト名も強制更新 + if (isHost) { + supa + .from("groups") + .update({ host_name: currentUser }) + .eq("group_name", currentGroup) + .then(() => { + currentHostName = currentUser; + console.log("[Host Update] ホスト情報を更新:", currentUser); + }); + } } // =================================== -// 位置情報取得 +// 現在位置取得 // =================================== function getPosition() { return new Promise((resolve, reject) => { @@ -100,7 +112,6 @@ const newLat = e.latlng.lat; const newLng = e.latlng.lng; - // 置き直し確認 if (targetLat !== null && targetLng !== null) { const ok = confirm("待ち合わせ場所を置き直しますか?"); if (!ok) return; @@ -110,7 +121,6 @@ targetLng = newLng; if (targetMarker) map.removeLayer(targetMarker); - targetMarker = L.marker([targetLat, targetLng], { icon: meetIcon }).addTo( map ); @@ -146,7 +156,7 @@ } // =================================== -// ピン表示 +// ピン生成 // =================================== function createLabeledMarker(lat, lng, name, isSelf) { const pinUrl = isSelf @@ -177,14 +187,14 @@ } // =================================== -// 距離計算(修正済み) +// 距離計算(修正版) // =================================== function distanceMeters(lat1, lng1, lat2, lng2) { const R = 6371000; const toRad = (deg) => (deg * Math.PI) / 180; const dLat = toRad(lat2 - lat1); - const dLng = toRad(lng2 - lng1); // ← 修正済み + const dLng = toRad(lng2 - lng1); // ← 修正済み! const a = Math.sin(dLat / 2) ** 2 + @@ -196,10 +206,11 @@ } // =================================== -// メンバー一覧 +// メンバー一覧表示 // =================================== function showMemberList(latestByDevice) { const list = document.getElementById("memberList"); + list.innerHTML = ""; Object.values(latestByDevice).forEach((row) => { if (!allMembers.some((m) => m.device_id === row.device_id)) { @@ -210,13 +221,10 @@ } }); - list.innerHTML = ""; - allMembers.forEach((member) => { const row = latestByDevice[member.device_id]; const li = document.createElement("li"); - li.classList.add("member-item"); const online = row && row.updated_at @@ -226,7 +234,7 @@ li.classList.toggle("online", online); li.classList.toggle("offline", !online); - let crown = member.user_name === currentHostName ? "👑 " : ""; + const crown = member.user_name === currentHostName ? "👑 " : ""; li.innerHTML = ` @@ -251,16 +259,16 @@ currentHostName = group.host_name; - const exists = Object.values(latestByDevice).some( + const hostExists = Object.values(latestByDevice).some( (r) => r.user_name === currentHostName ); - if (exists) { + if (hostExists) { isHost = currentUser === currentHostName; return; } - // ホスト不在 → 最新のユーザーを新ホストへ + // ホスト不在 → 最新更新ユーザーに交代 const users = Object.values(latestByDevice); if (users.length === 0) return; @@ -275,7 +283,7 @@ .update({ host_name: currentHostName }) .eq("group_name", currentGroup); - isHost = newest.user_name === currentUser; + isHost = currentUser === currentHostName; } // =================================== @@ -294,15 +302,13 @@ if (!all) return; - const box = document.getElementById("targetInfo"); - box.innerHTML = ` + document.getElementById("targetInfo").innerHTML = ` 🎉 全員が待ち合わせ場所に到着しました! 🎉 -
ホストは新しい待ち合わせ場所を置けます +
ホストは新しい待ち合わせ場所を設定できます `; targetLat = null; targetLng = null; - if (targetMarker) { map.removeLayer(targetMarker); targetMarker = null; @@ -315,7 +321,7 @@ } // =================================== -// 他ユーザー表示 +// 全メンバーの位置表示 // =================================== async function showOtherUsers() { const { data } = await supa @@ -325,7 +331,6 @@ .order("updated_at", { ascending: false }); latestByDevice = {}; - data.forEach((r) => { if (!latestByDevice[r.device_id]) latestByDevice[r.device_id] = r; }); @@ -339,6 +344,7 @@ Object.values(latestByDevice).forEach((r) => { if (r.device_id === deviceId) return; + const mk = createLabeledMarker(r.lat, r.lng, r.user_name, false); mk.addTo(map); otherMarkers.push(mk); @@ -346,21 +352,21 @@ } // =================================== -// 待ち合わせまでの距離 +// 待ち合わせ距離表示 // =================================== function showDistanceToTarget() { - const box = document.getElementById("targetInfo"); - if (!box) return; if (targetLat === null) return; const d = distanceMeters(lastLat, lastLng, targetLat, targetLng); const km = (d / 1000).toFixed(2); - box.innerHTML = `待ち合わせ場所まで 約 ${km} km`; + document.getElementById( + "targetInfo" + ).innerHTML = `待ち合わせ場所まで 約 ${km} km`; } // =================================== -// 駅情報 +// 駅表示 // =================================== async function fetchStationsAround(lat, lng) { const query = ` @@ -368,61 +374,55 @@ node["railway"="station"](around:5000,${lat},${lng}); out; `; - const url = - "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query); - const res = await fetch(url); + const res = await fetch( + "https://overpass-api.de/api/interpreter?data=" + + encodeURIComponent(query) + ); return (await res.json()).elements || []; } async function loadStations() { const box = document.getElementById("nearestBox"); - if (!box) return; - try { - const stations = await fetchStationsAround(lastLat, lastLng); + const stations = await fetchStationsAround(lastLat, lastLng); - stationMarkers.forEach((m) => map.removeLayer(m)); - stationMarkers = []; + stationMarkers.forEach((m) => map.removeLayer(m)); + stationMarkers = []; - if (stations.length === 0) { - box.textContent = "駅が見つかりませんでした。"; - return; + if (stations.length === 0) { + box.textContent = "駅が見つかりませんでした。"; + return; + } + + let nearest = null; + let nearestDist = Infinity; + + stations.forEach((st) => { + const name = st.tags?.name || "駅名不明"; + const d = distanceMeters(lastLat, lastLng, st.lat, st.lon); + + if (d < nearestDist) { + nearest = { name, lat: st.lat, lng: st.lon }; + nearestDist = d; } - let nearest = null; - let nearestDist = Infinity; + const mk = L.marker([st.lat, st.lon]).addTo(map); + mk.bindPopup(name + "駅"); + stationMarkers.push(mk); + }); - stations.forEach((st) => { - const name = st.tags?.name || "駅名不明"; - const d = distanceMeters(lastLat, lastLng, st.lat, st.lon); - - if (d < nearestDist) { - nearest = { name, lat: st.lat, lng: st.lon }; - nearestDist = d; - } - - const mk = L.marker([st.lat, st.lon]).addTo(map); - mk.bindPopup(name + "駅"); - stationMarkers.push(mk); - }); - - box.textContent = - "最寄り駅:" + - nearest.name + - "(約 " + - (nearestDist / 1000).toFixed(2) + - " km)"; - } catch (e) { - box.textContent = "駅情報を取得できませんでした。"; - } + box.textContent = + "最寄り駅:" + + nearest.name + + "(約 " + + (nearestDist / 1000).toFixed(2) + + " km)"; } // =================================== // 共有待ち合わせ読み込み // =================================== async function loadSharedTarget() { - const box = document.getElementById("targetInfo"); - const { data } = await supa .from("shared_target") .select("*") @@ -437,12 +437,12 @@ targetLng = data.lng; if (targetMarker) map.removeLayer(targetMarker); - targetMarker = L.marker([targetLat, targetLng], { icon: meetIcon }).addTo( map ); - box.textContent = "待ち合わせ場所が共有されました!"; + document.getElementById("targetInfo").textContent = + "待ち合わせ場所が共有されました!"; } // =================================== @@ -463,12 +463,12 @@ const side = isMe ? "chat-right" : "chat-left"; return ` -
-
- ${isMe ? "" : `${m.user_name}
`} - ${m.message} -
-
`; +
+
+ ${isMe ? "" : `${m.user_name}
`} + ${m.message} +
+
`; }) .join(""); @@ -491,7 +491,7 @@ } // =================================== -// メイン +// メイン処理 // =================================== async function main() { loadParams(); @@ -503,9 +503,7 @@ const pos = await getPosition(); lat = pos.latitude; lng = pos.longitude; - } catch { - console.warn("位置情報が取得できず、デフォルト位置を使用"); - } + } catch {} lastLat = lat; lastLng = lng;