diff --git a/map4.js b/map4.js index 64a7825..97820df 100644 --- a/map4.js +++ b/map4.js @@ -37,7 +37,7 @@ let stationMarkers = []; // =================================== -// ステータス +// ステータス(移動中 / 遅れます / 寄り道中 / 到着) // =================================== let myStatus = localStorage.getItem("myStatus") || "移動中"; @@ -51,7 +51,7 @@ .eq("group_name", currentGroup) .eq("device_id", deviceId); - showOtherUsers(); + showOtherUsers(); // メンバーリスト更新 } function setupStatusButtons() { @@ -68,8 +68,8 @@ currentGroup = p.get("group"); currentUser = p.get("user"); - document.getElementById("groupName").textContent = currentGroup; - document.getElementById("userName").textContent = currentUser; + document.getElementById("groupName").textContent = currentGroup || ""; + document.getElementById("userName").textContent = currentUser || ""; } // =================================== @@ -107,6 +107,7 @@ maxZoom: 19, }).addTo(map); + // ホストだけ待ち合わせを設定 map.on("click", async (e) => { if (!isHost) return; @@ -137,24 +138,6 @@ } // =================================== -// ★ 自分のピンを描画 -// =================================== -function renderSelfMarker() { - if (!map || lastLat === null || lastLng === null) return; - - if (selfMarker) map.removeLayer(selfMarker); - - selfMarker = createLabeledMarker( - lastLat, - lastLng, - currentUser, - true, - myStatus - ); - - selfMarker.addTo(map); -} -// =================================== // ピン(自分 & 他人) // =================================== function createLabeledMarker(lat, lng, name, isSelf, status) { @@ -169,33 +152,21 @@ "到着": "#9c27b0", }[status || "移動中"]; - const shortName = name.length > 4 ? name.slice(0, 4) : name; + const shortName = name && name.length > 6 ? name.slice(0, 6) + "…" : name; const html = ` -
- -
- - ${shortName} - - - ${status} - +
+ +
${shortName || ""}
+
+ ${status || ""}
`; @@ -203,9 +174,9 @@ return L.marker([lat, lng], { icon: L.divIcon({ html, - className: "", - iconSize: [70, 40], - iconAnchor: [10, 32], + className: "custom-pin", + iconSize: [40, 60], + iconAnchor: [20, 60], }), }); } @@ -274,7 +245,7 @@ // 待ち合わせ距離表示 // =================================== function showDistanceToTarget() { - if (targetLat === null) return; + if (targetLat === null || lastLat === null) return; const d = distanceMeters(lastLat, lastLng, targetLat, targetLng); const km = (d / 1000).toFixed(2); @@ -305,6 +276,8 @@ // 最寄り駅のピン // =================================== async function loadStations() { + if (!map || lastLat === null) return; + const box = document.getElementById("nearestBox"); const stations = await fetchStationsAround(lastLat, lastLng); @@ -312,7 +285,7 @@ stationMarkers.forEach((m) => map.removeLayer(m)); stationMarkers = []; - if (stations.length === 0) { + if (!stations || stations.length === 0) { box.textContent = "駅が見つかりませんでした。"; return; } @@ -345,6 +318,7 @@ const list = document.getElementById("memberList"); list.innerHTML = ""; + // 全員を固定順で並べるために allMembers を育てる Object.values(latestByDevice).forEach((row) => { if (!allMembers.some((m) => m.device_id === row.device_id)) { allMembers.push({ @@ -392,7 +366,7 @@
`; - // ★ メンバークリックでその位置へ移動 + // メンバークリックでその位置へ移動 li.addEventListener("click", () => { const r = latestByDevice[member.device_id]; if (!r) return; @@ -411,17 +385,21 @@ "到着": "#9c27b0", }[s] || "#ccc"; } - // =================================== // 他ユーザーのピン表示 // =================================== async function showOtherUsers() { - const { data } = await supa + const { data, error } = await supa .from("locations") .select("*") .eq("group_name", currentGroup) .order("updated_at", { ascending: false }); + if (error) { + console.error("locations 読み込みエラー:", error); + return; + } + latestByDevice = {}; (data || []).forEach((r) => { if (!latestByDevice[r.device_id]) latestByDevice[r.device_id] = r; @@ -430,8 +408,21 @@ await checkHostAuto(); showMemberList(latestByDevice); + // 他人のピン描画し直し otherMarkers.forEach((m) => map.removeLayer(m)); otherMarkers = []; + + Object.values(latestByDevice).forEach((r) => { + if (r.device_id === deviceId) return; + + const mk = createLabeledMarker(r.lat, r.lng, r.user_name, false, r.status); + mk.addTo(map); + otherMarkers.push(mk); + }); + + checkAllArrived(); +} + // =================================== // 待ち合わせ到着判定 // =================================== @@ -443,7 +434,7 @@ const ok = users.every((u) => { const d = distanceMeters(u.lat, u.lng, targetLat, targetLng); - return d < 120; // 120m 以内を「到着」とみなす + return d < 120; // 120m 以内 }); if (!ok) return; @@ -468,19 +459,25 @@ // 共有待ち合わせ読み込み // =================================== async function loadSharedTarget() { - const { data } = await supa + const { data, error } = await supa .from("shared_target") .select("*") .eq("group_name", currentGroup) .maybeSingle(); + if (error) { + console.error("shared_target 読み込みエラー:", error); + return; + } if (!data) return; targetLat = data.lat; targetLng = data.lng; if (targetMarker) map.removeLayer(targetMarker); - targetMarker = L.marker([targetLat, targetLng], { icon: meetIcon }).addTo(map); + targetMarker = L.marker([targetLat, targetLng], { icon: meetIcon }).addTo( + map + ); document.getElementById("targetInfo").textContent = "待ち合わせ場所が共有されました!"; @@ -494,12 +491,17 @@ async function loadMessages() { const chatList = document.getElementById("chatList"); - const { data } = await supa + const { data, error } = await supa .from("messages") .select("*") .eq("group_name", currentGroup) .order("created_at", { ascending: true }); + if (error) { + console.error("messages 読み込みエラー:", error); + return; + } + chatList.innerHTML = (data || []) .map((m) => { const isMe = m.user_name === currentUser; @@ -549,13 +551,13 @@ // ホスト自動交代 // =================================== async function checkHostAuto() { - const { data: group } = await supa + const { data: group, error } = await supa .from("groups") .select("*") .eq("group_name", currentGroup) .maybeSingle(); - if (!group) return; + if (error || !group) return; currentHostName = group.host_name; @@ -566,6 +568,7 @@ const hostOnline = onlineUsers.some((u) => u.user_name === currentHostName); if (!hostOnline && onlineUsers.length > 0) { + // 一番新しい人を新ホストに const newHost = onlineUsers.sort( (a, b) => new Date(b.updated_at) - new Date(a.updated_at) )[0]; @@ -577,6 +580,8 @@ currentHostName = newHost.user_name; isHost = currentUser === currentHostName; + } else { + isHost = currentUser === currentHostName; } const hostLabel = document.getElementById("hostStatus"); @@ -611,12 +616,17 @@ // グループ状態監視 // =================================== async function checkGroupActive() { - const { data } = await supa + const { data, error } = await supa .from("groups") .select("is_active") .eq("group_name", currentGroup) .maybeSingle(); + if (error) { + console.error("groups 読み込みエラー:", error); + return; + } + if (!data || data.is_active === false) { alert("このグループは解散されました。"); location.href = `archive.html?group=${encodeURIComponent(currentGroup)}`; @@ -631,7 +641,7 @@ setupStatusButtons(); let lat = 35.681236, - lng = 139.767125; // 皇居(初期値) + lng = 139.767125; // 皇居 try { const pos = await getPosition(); @@ -693,6 +703,7 @@ }); } + // 画面表示後に地図サイズ調整 setTimeout(() => map.invalidateSize(), 500); } @@ -745,14 +756,3 @@ main(); }); - - Object.values(latestByDevice).forEach((r) => { - if (r.device_id === deviceId) return; - - const mk = createLabeledMarker(r.lat, r.lng, r.user_name, false, r.status); - mk.addTo(map); - otherMarkers.push(mk); - }); - - checkAllArrived(); -}