219 lines
5.7 KiB
JavaScript
219 lines
5.7 KiB
JavaScript
// public/js/galleryUtils.js
|
|
// Ordinamento, filtri, raggruppamento e formattazione.
|
|
|
|
(() => {
|
|
"use strict";
|
|
|
|
function sortByDate(items, direction = "desc") {
|
|
return items.slice().sort((a, b) => {
|
|
const da = a?.taken_at ? new Date(a.taken_at) : 0;
|
|
const db = b?.taken_at ? new Date(b.taken_at) : 0;
|
|
return direction === "asc" ? da - db : db - da;
|
|
});
|
|
}
|
|
|
|
function applyFilters(items) {
|
|
if (window.state?.mode === "activities") return items;
|
|
|
|
const filter = window.currentFilter || "";
|
|
const query = String(window.currentSearch || "")
|
|
.trim()
|
|
.toLocaleLowerCase("it-IT");
|
|
const selectedYear = window.currentYear
|
|
? Number(window.currentYear)
|
|
: null;
|
|
const selectedMonth = window.currentMonth
|
|
? Number(window.currentMonth)
|
|
: null;
|
|
const selectedFolder = String(window.currentFolder || "");
|
|
|
|
function getFolder(item) {
|
|
return String(item?.cartella || item?.folder || "").trim();
|
|
}
|
|
|
|
function hasGps(item) {
|
|
const gps = item?.gps;
|
|
if (!gps) return false;
|
|
|
|
const lat = Number(gps.lat);
|
|
const lng = Number(gps.lng);
|
|
|
|
return Number.isFinite(lat) &&
|
|
Number.isFinite(lng) &&
|
|
lat >= -90 && lat <= 90 &&
|
|
lng >= -180 && lng <= 180;
|
|
}
|
|
|
|
function searchableText(item) {
|
|
return [
|
|
item?.name,
|
|
item?.file_name,
|
|
item?.filename,
|
|
item?.originalname,
|
|
item?.path,
|
|
item?.relative_path,
|
|
item?.full_path,
|
|
item?.cartella,
|
|
item?.folder
|
|
]
|
|
.filter(value => value !== undefined && value !== null)
|
|
.join(" ")
|
|
.toLocaleLowerCase("it-IT");
|
|
}
|
|
|
|
return items.filter(item => {
|
|
const mime = String(item?.mime_type || "").toLowerCase();
|
|
|
|
if (selectedFolder && getFolder(item) !== selectedFolder) {
|
|
return false;
|
|
}
|
|
|
|
switch (filter) {
|
|
case "folder":
|
|
if (!(item?.cartella || item?.folder)) return false;
|
|
break;
|
|
|
|
case "location":
|
|
if (!hasGps(item)) return false;
|
|
break;
|
|
|
|
case "type": // Compatibilità con il vecchio pulsante.
|
|
case "images":
|
|
if (!mime.startsWith("image/")) return false;
|
|
break;
|
|
|
|
case "videos":
|
|
if (!mime.startsWith("video/")) return false;
|
|
break;
|
|
}
|
|
|
|
if (query && !searchableText(item).includes(query)) {
|
|
return false;
|
|
}
|
|
|
|
if (selectedYear || selectedMonth) {
|
|
if (!item?.taken_at) return false;
|
|
|
|
const date = new Date(item.taken_at);
|
|
if (Number.isNaN(date.getTime())) return false;
|
|
|
|
if (selectedYear && date.getFullYear() !== selectedYear) {
|
|
return false;
|
|
}
|
|
|
|
if (selectedMonth && date.getMonth() + 1 !== selectedMonth) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
function formatDay(date) {
|
|
return date.toLocaleDateString("it-IT", {
|
|
weekday: "long",
|
|
day: "numeric",
|
|
month: "long"
|
|
});
|
|
}
|
|
|
|
function formatMonth(date) {
|
|
return date.toLocaleDateString("it-IT", {
|
|
month: "long",
|
|
year: "numeric"
|
|
});
|
|
}
|
|
|
|
function groupByDate(items, mode = "auto") {
|
|
const sections = [];
|
|
const sectionMap = new Map();
|
|
const now = new Date();
|
|
|
|
function getLabel(item) {
|
|
if (mode === "folder") {
|
|
return String(item?.cartella || item?.folder || "").trim()
|
|
|| "Senza cartella";
|
|
}
|
|
|
|
const date = item?.taken_at ? new Date(item.taken_at) : null;
|
|
if (!date || Number.isNaN(date.getTime())) return "Senza data";
|
|
|
|
const diffDays = Math.floor((now - date) / 86400000);
|
|
|
|
if (mode === "day") return formatDay(date);
|
|
if (mode === "month") return formatMonth(date);
|
|
if (mode === "year") return String(date.getFullYear());
|
|
|
|
if (diffDays === 0) return "Oggi";
|
|
if (diffDays === 1) return "Ieri";
|
|
if (diffDays <= 7) return "Questa settimana";
|
|
if (diffDays <= 14) return "La settimana scorsa";
|
|
if (diffDays <= 30) return "Questo mese";
|
|
if (diffDays <= 60) return "Mese scorso";
|
|
if (date.getFullYear() === now.getFullYear()) return formatMonth(date);
|
|
return String(date.getFullYear());
|
|
}
|
|
|
|
for (const item of items) {
|
|
const label = getLabel(item);
|
|
let section = sectionMap.get(label);
|
|
|
|
if (!section) {
|
|
section = { label, items: [] };
|
|
sectionMap.set(label, section);
|
|
sections.push(section);
|
|
}
|
|
|
|
section.items.push(item);
|
|
}
|
|
|
|
return sections;
|
|
}
|
|
|
|
function escapeHtml(value) {
|
|
return String(value ?? "")
|
|
.replaceAll("&", "&")
|
|
.replaceAll("<", "<")
|
|
.replaceAll(">", ">")
|
|
.replaceAll('"', """)
|
|
.replaceAll("'", "'");
|
|
}
|
|
|
|
function formatDurationShort(ms) {
|
|
const totalSec = Math.round(ms / 1000);
|
|
const hours = Math.floor(totalSec / 3600);
|
|
const minutes = Math.floor((totalSec % 3600) / 60);
|
|
return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
|
|
}
|
|
|
|
function formatActivityMeta(item) {
|
|
const parts = [];
|
|
|
|
if (item.sport) parts.push(item.sport);
|
|
if (Number.isFinite(Number(item.distance_meters))) {
|
|
parts.push(`${(Number(item.distance_meters) / 1000).toFixed(1)} km`);
|
|
}
|
|
if (Number.isFinite(Number(item.duration_millis))) {
|
|
parts.push(formatDurationShort(Number(item.duration_millis)));
|
|
}
|
|
|
|
return parts.join(" · ");
|
|
}
|
|
|
|
window.GalleryUtils = Object.freeze({
|
|
sortByDate,
|
|
applyFilters,
|
|
groupByDate,
|
|
formatDay,
|
|
formatMonth,
|
|
escapeHtml,
|
|
formatDurationShort,
|
|
formatActivityMeta
|
|
});
|
|
|
|
// Compatibilità con gli script esistenti.
|
|
window.sortByDate = sortByDate;
|
|
window.applyFilters = applyFilters;
|
|
window.groupByDate = groupByDate;
|
|
})();
|