carrier info fix, right widget update, live tracking device upd, bug fixes
All checks were successful
release-tag / release-image (push) Successful in 55s
All checks were successful
release-tag / release-image (push) Successful in 55s
This commit is contained in:
@ -112,6 +112,24 @@ body {
|
|||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.back-button {
|
||||||
|
border: none;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: left;
|
||||||
|
padding: 15px;
|
||||||
|
color: #fff;
|
||||||
|
background: rgb(187, 179, 170);
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(187, 179, 170, 1) 0%,
|
||||||
|
rgba(159, 148, 135, 1) 100%
|
||||||
|
);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.stopdescription {
|
.stopdescription {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -687,6 +705,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-name {
|
.dropdown-name {
|
||||||
|
position: relative;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@ -695,7 +714,6 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,3 +1249,25 @@ li.checked {
|
|||||||
flex: 0 0 calc((100% - 24px) / 3);
|
flex: 0 0 calc((100% - 24px) / 3);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.carrier-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carrier-img {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carrier-slogan {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #fff;
|
||||||
|
opacity: 70%;
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -74,6 +74,8 @@ export default {
|
|||||||
manualTramDirection: null,
|
manualTramDirection: null,
|
||||||
manualDirectionUntil: 0,
|
manualDirectionUntil: 0,
|
||||||
inactivityTimer: null,
|
inactivityTimer: null,
|
||||||
|
isFollowingTram: false,
|
||||||
|
followTramTimer: null,
|
||||||
chooseTramDirection(canvasPt) {
|
chooseTramDirection(canvasPt) {
|
||||||
// canvasPt: [x, y] in PIXI coords
|
// canvasPt: [x, y] in PIXI coords
|
||||||
let bestDir = "right";
|
let bestDir = "right";
|
||||||
@ -141,6 +143,12 @@ export default {
|
|||||||
resetInactivity() {
|
resetInactivity() {
|
||||||
this.lastActivityTime = Date.now();
|
this.lastActivityTime = Date.now();
|
||||||
if (this.videoOverlayVisible) this.hideVideoOverlay();
|
if (this.videoOverlayVisible) this.hideVideoOverlay();
|
||||||
|
clearTimeout(this.inactivityTimer);
|
||||||
|
// stop following on any user activity
|
||||||
|
this.isFollowingTram = false;
|
||||||
|
this.stopFollowTram();
|
||||||
|
// restart inactivity timer on any user activity
|
||||||
|
this.resetInactivityTimer();
|
||||||
},
|
},
|
||||||
startInactivityCheck() {
|
startInactivityCheck() {
|
||||||
if (this.inactivityInterval) return;
|
if (this.inactivityInterval) return;
|
||||||
@ -325,20 +333,17 @@ export default {
|
|||||||
const minLat = Math.min(...lats);
|
const minLat = Math.min(...lats);
|
||||||
const maxLat = Math.max(...lats);
|
const maxLat = Math.max(...lats);
|
||||||
const minLng = Math.min(...lngs);
|
const minLng = Math.min(...lngs);
|
||||||
const maxLng = Math.max(...lngs);
|
|
||||||
|
|
||||||
const canvas = this.pixiApp.canvas;
|
|
||||||
const width = canvas.width;
|
|
||||||
const height = canvas.height;
|
|
||||||
const padding = 40;
|
const padding = 40;
|
||||||
|
|
||||||
const scaleX = (width - padding * 2) / (maxLng - minLng || 1);
|
const scale = 35000;
|
||||||
const scaleY = (height - padding * 2) / (maxLat - minLat || 1);
|
const midLat = (minLat + maxLat) / 2;
|
||||||
let scale = 30000;
|
const latFactor = Math.cos((midLat * Math.PI) / 180);
|
||||||
console.log(scaleX, scaleY, scale);
|
console.log(
|
||||||
|
`Using fixed scale ${scale} and latFactor ${latFactor.toFixed(4)}`
|
||||||
|
);
|
||||||
|
|
||||||
const toPoint = ([lat, lng]) => {
|
const toPoint = ([lat, lng]) => {
|
||||||
const x = (lng - minLng) * scale + padding;
|
const x = (lng - minLng) * scale * latFactor + padding;
|
||||||
const y = (maxLat - lat) * scale + padding;
|
const y = (maxLat - lat) * scale + padding;
|
||||||
return { x, y };
|
return { x, y };
|
||||||
};
|
};
|
||||||
@ -1079,29 +1084,39 @@ export default {
|
|||||||
},
|
},
|
||||||
// reset the inactivity timeout
|
// reset the inactivity timeout
|
||||||
resetInactivityTimer() {
|
resetInactivityTimer() {
|
||||||
|
console.log("[inactivity] scheduling follow in 15s");
|
||||||
clearTimeout(this.inactivityTimer);
|
clearTimeout(this.inactivityTimer);
|
||||||
this.inactivityTimer = setTimeout(() => {
|
this.inactivityTimer = setTimeout(() => {
|
||||||
|
this.isFollowingTram = true;
|
||||||
|
this.startFollowTram();
|
||||||
|
}, 15000);
|
||||||
|
},
|
||||||
|
|
||||||
|
startFollowTram() {
|
||||||
|
console.log("[follow] startFollowTram() triggered");
|
||||||
|
if (this.followTramTimer) return;
|
||||||
|
this.followTramTimer = setInterval(() => {
|
||||||
if (this.tramContainer) {
|
if (this.tramContainer) {
|
||||||
// compute tram position in viewport world coordinates
|
const local = new PIXI.Point(
|
||||||
const localPoint = new PIXI.Point(
|
|
||||||
this.tramContainer.x,
|
this.tramContainer.x,
|
||||||
this.tramContainer.y
|
this.tramContainer.y
|
||||||
);
|
);
|
||||||
const worldCenter = this.viewport.toLocal(
|
const worldCenter = this.viewport.toLocal(local, this.routeGroup);
|
||||||
localPoint,
|
|
||||||
this.routeGroup
|
|
||||||
);
|
|
||||||
// smooth pan and zoom to tram
|
|
||||||
this.viewport.animate({
|
this.viewport.animate({
|
||||||
time: 600,
|
time: 600,
|
||||||
position: { x: worldCenter.x, y: worldCenter.y },
|
position: { x: worldCenter.x, y: worldCenter.y },
|
||||||
scale: 1,
|
scale: 1,
|
||||||
easing: "easeInOutSine",
|
easing: "easeInOutSine",
|
||||||
});
|
});
|
||||||
// schedule next recenter
|
|
||||||
this.resetInactivityTimer();
|
|
||||||
}
|
}
|
||||||
}, 15000);
|
}, 500);
|
||||||
|
},
|
||||||
|
stopFollowTram() {
|
||||||
|
console.log("[follow] stopFollowTram() triggered");
|
||||||
|
if (this.followTramTimer) {
|
||||||
|
clearInterval(this.followTramTimer);
|
||||||
|
this.followTramTimer = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// start watching for user interactions
|
// start watching for user interactions
|
||||||
@ -1125,6 +1140,10 @@ export default {
|
|||||||
clearInterval(this.inactivityInterval);
|
clearInterval(this.inactivityInterval);
|
||||||
this.inactivityInterval = null;
|
this.inactivityInterval = null;
|
||||||
}
|
}
|
||||||
|
if (this.followTramTimer) {
|
||||||
|
clearInterval(this.followTramTimer);
|
||||||
|
this.followTramTimer = null;
|
||||||
|
}
|
||||||
["mousemove", "mousedown", "keydown", "touchstart", "scroll"].forEach(
|
["mousemove", "mousedown", "keydown", "touchstart", "scroll"].forEach(
|
||||||
(evt) => window.removeEventListener(evt, this.resetInactivity)
|
(evt) => window.removeEventListener(evt, this.resetInactivity)
|
||||||
);
|
);
|
||||||
|
@ -43,6 +43,26 @@
|
|||||||
class="watermark watermark-rd"
|
class="watermark watermark-rd"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
v-if="showBackButton"
|
||||||
|
class="back-button"
|
||||||
|
@click="returnToNearestSight"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="12"
|
||||||
|
height="21"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 12 21"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="#fff"
|
||||||
|
d="M3.53 10.574c.188.135.316.203.414.3 2.486 2.495 4.966 4.992 7.451 7.486.445.447.623.96.44 1.574a1.485 1.485 0 0 1-2.383.716c-.09-.076-.171-.16-.254-.244L.658 11.82c-.878-.885-.877-1.673.003-2.56C3.539 6.364 6.414 3.463 9.307.58c.252-.25.606-.46.948-.542.646-.154 1.26.184 1.563.75.307.566.22 1.274-.238 1.764-.352.378-.725.736-1.09 1.101-2.195 2.204-4.389 4.407-6.585 6.609-.082.083-.179.15-.374.312Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{{ t("back") }}
|
||||||
|
</button>
|
||||||
<span class="stopname">{{ stopName }}</span>
|
<span class="stopname">{{ stopName }}</span>
|
||||||
<span class="stopdescription">{{ selectedArticleBody }}</span>
|
<span class="stopdescription">{{ selectedArticleBody }}</span>
|
||||||
<div class="stoparticles">
|
<div class="stoparticles">
|
||||||
@ -261,6 +281,11 @@ export default {
|
|||||||
defaultImageUrl:
|
defaultImageUrl:
|
||||||
"https://lh3.googleusercontent.com/gps-cs-s/AB5caB8lUwofb2NIg6n0-cEl8nIWsySAUc52KNj4XezuOdo-aeqTgQlD1kTVa5MaynL2Yg4ByoTYTKNTR7K59f7kjzU9yzpudstjRiT2F6M_ilxFYFpcvMZz6OwlRFF2MrsCPSwUa7vqew=s680-w680-h510",
|
"https://lh3.googleusercontent.com/gps-cs-s/AB5caB8lUwofb2NIg6n0-cEl8nIWsySAUc52KNj4XezuOdo-aeqTgQlD1kTVa5MaynL2Yg4ByoTYTKNTR7K59f7kjzU9yzpudstjRiT2F6M_ilxFYFpcvMZz6OwlRFF2MrsCPSwUa7vqew=s680-w680-h510",
|
||||||
sightId: 17,
|
sightId: 17,
|
||||||
|
manualSightId: null,
|
||||||
|
nearestSightId: null,
|
||||||
|
returnTimer: null,
|
||||||
|
lastUserActivity: Date.now(),
|
||||||
|
firstLoad: true,
|
||||||
stopName: "",
|
stopName: "",
|
||||||
watermarkLU: "",
|
watermarkLU: "",
|
||||||
watermarkRD: "",
|
watermarkRD: "",
|
||||||
@ -291,10 +316,10 @@ export default {
|
|||||||
routeProgress: null,
|
routeProgress: null,
|
||||||
routeId: null,
|
routeId: null,
|
||||||
selectedLang: localStorage.getItem("selectedLangRight") || "ru",
|
selectedLang: localStorage.getItem("selectedLangRight") || "ru",
|
||||||
showLangToggle: true, // видна «глобус»-кнопка
|
showLangToggle: true,
|
||||||
showLanguageOptions: false, // виден блок из трёх иконок
|
showLanguageOptions: false,
|
||||||
languageOptionsTimer: null, // таймер на 10 с
|
languageOptionsTimer: null,
|
||||||
langRevertTimer: null, // таймер на 30 с
|
langRevertTimer: null,
|
||||||
icons: {
|
icons: {
|
||||||
ru: `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 28 28">
|
ru: `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="none" viewBox="0 0 28 28">
|
||||||
<path fill="#fff" d="M14 0C6.27 0 0 6.27 0 14s6.27 14 14 14 14-6.27 14-14S21.73 0 14 0Zm.117 19.57H11.62l-2.117-4.135H7.646v4.136H5.32V8.27h4.2c1.336 0 2.363.298 3.092.893.729.595 1.085 1.435 1.085 2.52 0 .77-.17 1.412-.502 1.931-.332.513-.84.928-1.517 1.23l2.444 4.62v.112l-.005-.006Zm9.391-3.855c0 1.237-.385 2.217-1.16 2.934-.776.718-1.832 1.08-3.174 1.08-1.341 0-2.368-.35-3.144-1.05-.776-.7-1.173-1.657-1.19-2.882V8.272h2.328v7.46c0 .741.175 1.278.53 1.616.356.339.846.508 1.47.508 1.307 0 1.972-.689 1.995-2.065V8.27h2.334v7.444h.011Z"/>
|
<path fill="#fff" d="M14 0C6.27 0 0 6.27 0 14s6.27 14 14 14 14-6.27 14-14S21.73 0 14 0Zm.117 19.57H11.62l-2.117-4.135H7.646v4.136H5.32V8.27h4.2c1.336 0 2.363.298 3.092.893.729.595 1.085 1.435 1.085 2.52 0 .77-.17 1.412-.502 1.931-.332.513-.84.928-1.517 1.23l2.444 4.62v.112l-.005-.006Zm9.391-3.855c0 1.237-.385 2.217-1.16 2.934-.776.718-1.832 1.08-3.174 1.08-1.341 0-2.368-.35-3.144-1.05-.776-.7-1.173-1.657-1.19-2.882V8.272h2.328v7.46c0 .741.175 1.278.53 1.616.356.339.846.508 1.47.508 1.307 0 1.972-.689 1.995-2.065V8.27h2.334v7.444h.011Z"/>
|
||||||
@ -310,7 +335,7 @@ export default {
|
|||||||
},
|
},
|
||||||
translations: {
|
translations: {
|
||||||
sights: { ru: "Достопримечательности", en: "Landmarks", zh: "景点" },
|
sights: { ru: "Достопримечательности", en: "Landmarks", zh: "景点" },
|
||||||
// при необходимости — другие подписи
|
back: { ru: "Вернуться назад", en: "Back", zh: "返回" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -352,6 +377,9 @@ export default {
|
|||||||
Object.entries(this.nextStopTransfers).filter(([, value]) => value)
|
Object.entries(this.nextStopTransfers).filter(([, value]) => value)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
showBackButton() {
|
||||||
|
return this.sightId !== this.nearestSightId;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
t(key) {
|
t(key) {
|
||||||
@ -513,86 +541,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async openSightCardDetails(id) {
|
async openSightCardDetails(id) {
|
||||||
// закрыть, если нажали повторно
|
this.manualSightId = id;
|
||||||
if (this.selectedSightCardId === id) {
|
this.sightId = id;
|
||||||
|
this.showSightsList = false;
|
||||||
this.selectedSightCardId = null;
|
this.selectedSightCardId = null;
|
||||||
this.cardDetail = null;
|
this.cardDetail = null;
|
||||||
return;
|
this.resetReturnTimer();
|
||||||
}
|
await this.fetchSightInfo();
|
||||||
this.selectedSightCardId = id;
|
await this.fetchArticles();
|
||||||
this.cardDetail = null;
|
|
||||||
this.resetSightsInactivityTimer();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [detailRes, articlesRes] = await Promise.all([
|
|
||||||
axios.get(this.addLangParam(`${API_URL}/sight/${id}`)),
|
|
||||||
axios.get(this.addLangParam(`${API_URL}/sight/${id}/article`)),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Fetch media for every article
|
|
||||||
const articlesWithMedia = await Promise.all(
|
|
||||||
articlesRes.data.map(async (article) => {
|
|
||||||
try {
|
|
||||||
const mediaRes = await axios.get(
|
|
||||||
this.addLangParam(`${API_URL}/article/${article.id}/media`)
|
|
||||||
);
|
|
||||||
return { ...article, media: mediaRes.data };
|
|
||||||
} catch (mediaErr) {
|
|
||||||
console.error(
|
|
||||||
`Failed to fetch media for article ${article.id}:`,
|
|
||||||
mediaErr
|
|
||||||
);
|
|
||||||
return { ...article, media: [] };
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// Console output: sight name, articles, and their media
|
|
||||||
console.log("Sight clicked:", {
|
|
||||||
name: detailRes.data.name,
|
|
||||||
articles: articlesWithMedia,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Choose preview image: prefer the first article's first media, otherwise fall back to sight thumbnail
|
|
||||||
let imageUrl = "";
|
|
||||||
if (
|
|
||||||
articlesWithMedia.length > 0 &&
|
|
||||||
articlesWithMedia[0].media &&
|
|
||||||
articlesWithMedia[0].media.length > 0
|
|
||||||
) {
|
|
||||||
const firstMediaId = articlesWithMedia[0].media[0].id;
|
|
||||||
try {
|
|
||||||
imageUrl = await this.getMediaBlobUrl(firstMediaId);
|
|
||||||
} catch {
|
|
||||||
imageUrl = this.addLangParam(
|
|
||||||
`${API_URL}/media/${firstMediaId}/download`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (detailRes.data.thumbnail) {
|
|
||||||
try {
|
|
||||||
imageUrl = await this.getMediaBlobUrl(detailRes.data.thumbnail);
|
|
||||||
} catch {
|
|
||||||
imageUrl = this.addLangParam(
|
|
||||||
`${API_URL}/media/${detailRes.data.thumbnail}/download`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cardDetail = {
|
|
||||||
name: detailRes.data.name,
|
|
||||||
imageUrl,
|
|
||||||
articles: articlesWithMedia,
|
|
||||||
};
|
|
||||||
if (articlesWithMedia.length > 0) {
|
|
||||||
this.selectedSightArticleId = articlesWithMedia[0].id;
|
|
||||||
this.selectedSightArticleBody = articlesWithMedia[0].body;
|
|
||||||
} else {
|
|
||||||
this.selectedSightArticleId = null;
|
|
||||||
this.selectedSightArticleBody = "";
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to load sight card details:", err);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
async selectSightArticle(id) {
|
async selectSightArticle(id) {
|
||||||
this.selectedSightArticleId = id;
|
this.selectedSightArticleId = id;
|
||||||
@ -657,10 +613,12 @@ export default {
|
|||||||
}, 300_000); // 5 m
|
}, 300_000); // 5 m
|
||||||
},
|
},
|
||||||
handleUserActivity() {
|
handleUserActivity() {
|
||||||
|
this.lastUserActivity = Date.now();
|
||||||
if (this.showSightsList || this.cardDetail)
|
if (this.showSightsList || this.cardDetail)
|
||||||
this.resetSightsInactivityTimer();
|
this.resetSightsInactivityTimer();
|
||||||
this.resetArticleInactivityTimer();
|
this.resetArticleInactivityTimer();
|
||||||
this.resetLangRevertTimer();
|
this.resetLangRevertTimer();
|
||||||
|
if (this.returnTimer) this.resetReturnTimer();
|
||||||
},
|
},
|
||||||
selectArticle(id) {
|
selectArticle(id) {
|
||||||
this.resetArticleInactivityTimer();
|
this.resetArticleInactivityTimer();
|
||||||
@ -738,23 +696,41 @@ export default {
|
|||||||
newSightId = this.sights[1].id;
|
newSightId = this.sights[1].id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newSightId && newSightId !== this.sightId) {
|
if (newSightId) {
|
||||||
|
if (this.firstLoad) {
|
||||||
|
this.nearestSightId = newSightId;
|
||||||
this.sightId = newSightId;
|
this.sightId = newSightId;
|
||||||
await this.fetchSightInfo();
|
await this.fetchSightInfo();
|
||||||
await this.fetchArticles();
|
await this.fetchArticles();
|
||||||
|
this.firstLoad = false;
|
||||||
|
this.clearReturnTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.nearestSightId !== newSightId) {
|
||||||
|
this.nearestSightId = newSightId;
|
||||||
|
}
|
||||||
|
if (!this.manualSightId) {
|
||||||
|
if (this.sightId !== this.nearestSightId) {
|
||||||
|
const userActive = Date.now() - this.lastUserActivity < 15_000; // 15-сек. окно
|
||||||
|
if (userActive) {
|
||||||
|
this.resetReturnTimer();
|
||||||
|
} else {
|
||||||
|
this.clearReturnTimer();
|
||||||
|
this.sightId = this.nearestSightId;
|
||||||
|
await this.fetchSightInfo();
|
||||||
|
await this.fetchArticles();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.clearReturnTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const nextStopId = response.data.routeProgress?.endStopId;
|
const nextStopId = response.data.routeProgress?.endStopId;
|
||||||
// console.log("Fetched next stop ID:", nextStopId);
|
|
||||||
// console.log("Stops:", this.stops);
|
|
||||||
if (nextStopId && this.stops) {
|
if (nextStopId && this.stops) {
|
||||||
const nextStop = this.stops.find((stop) => stop.id == nextStopId);
|
const nextStop = this.stops.find((stop) => stop.id == nextStopId);
|
||||||
// console.log("Fetched next stop ID:", nextStopId);
|
|
||||||
// console.log("Matching stop:", nextStop);
|
|
||||||
if (nextStop && nextStop.transfers) {
|
if (nextStop && nextStop.transfers) {
|
||||||
// console.log("Transfers at next stop:", nextStop.transfers);
|
|
||||||
this.nextStopTransfers = nextStop.transfers;
|
this.nextStopTransfers = nextStop.transfers;
|
||||||
} else {
|
} else {
|
||||||
// console.log("No transfers found at next stop");
|
|
||||||
this.nextStopTransfers = null;
|
this.nextStopTransfers = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -762,6 +738,29 @@ export default {
|
|||||||
console.error("Error fetching geolocation context:", error);
|
console.error("Error fetching geolocation context:", error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resetReturnTimer() {
|
||||||
|
this.clearReturnTimer();
|
||||||
|
this.returnTimer = setTimeout(() => {
|
||||||
|
this.returnToNearestSight();
|
||||||
|
}, 90_000);
|
||||||
|
},
|
||||||
|
clearReturnTimer() {
|
||||||
|
if (this.returnTimer) {
|
||||||
|
clearTimeout(this.returnTimer);
|
||||||
|
this.returnTimer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
returnToNearestSight() {
|
||||||
|
if (!this.nearestSightId) return;
|
||||||
|
this.manualSightId = null;
|
||||||
|
this.sightId = this.nearestSightId;
|
||||||
|
this.clearReturnTimer();
|
||||||
|
this.showSightsList = false;
|
||||||
|
this.selectedSightCardId = null;
|
||||||
|
this.cardDetail = null;
|
||||||
|
this.fetchSightInfo();
|
||||||
|
this.fetchArticles();
|
||||||
|
},
|
||||||
selectLetter(letter) {
|
selectLetter(letter) {
|
||||||
const anchorArr = this.$refs[`letter-${letter}`];
|
const anchorArr = this.$refs[`letter-${letter}`];
|
||||||
const anchor = anchorArr ? anchorArr[0] : null;
|
const anchor = anchorArr ? anchorArr[0] : null;
|
||||||
@ -818,6 +817,7 @@ export default {
|
|||||||
async mounted() {
|
async mounted() {
|
||||||
await this.fetchSights();
|
await this.fetchSights();
|
||||||
await this.fetchGeolocationContext();
|
await this.fetchGeolocationContext();
|
||||||
|
this.nearestSightId = this.sightId;
|
||||||
this.geolocationInterval = setInterval(() => {
|
this.geolocationInterval = setInterval(() => {
|
||||||
this.fetchGeolocationContext();
|
this.fetchGeolocationContext();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
373
src/icons/spb-gerb.svg
Normal file
373
src/icons/spb-gerb.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 176 KiB |
Reference in New Issue
Block a user