many updates

This commit is contained in:
2026-01-11 06:06:43 -08:00
parent 67357b5038
commit 4bb86b603e
73 changed files with 2881 additions and 59 deletions

View File

@@ -35,9 +35,9 @@
</div>
<div class="col-auto">
<select class="form-select" id="filter-type">
<option value="">All</option>
<option value="">All Types</option>
<option value="running">Running</option>
<option value="cycling">Cycling</option>
<option value="cycling">Cycling (All)</option>
<option value="swimming">Swimming</option>
<option value="walking">Walking</option>
<option value="hiking">Hiking</option>
@@ -45,6 +45,15 @@
<option value="yoga">Yoga</option>
</select>
</div>
<div class="col-auto">
<label for="filter-bike" class="col-form-label">Bike:</label>
</div>
<div class="col-auto">
<select class="form-select" id="filter-bike">
<option value="">All Bikes</option>
<!-- Populated by JS -->
</select>
</div>
<div class="col-auto">
<button class="btn btn-secondary" id="apply-filters-btn">Filter</button>
</div>
@@ -315,7 +324,10 @@
detailsModal = new bootstrap.Modal(document.getElementById('activityDetailsModal'));
detailsModal = new bootstrap.Modal(document.getElementById('activityDetailsModal'));
loadActivities();
fetchBikeSetups();
document.getElementById('prev-page-btn').addEventListener('click', () => changePage(-1));
document.getElementById('next-page-btn').addEventListener('click', () => changePage(1));
@@ -375,10 +387,19 @@
tbody.innerHTML = '<tr><td colspan="9" class="text-center">Loading...</td></tr>';
const typeFilter = document.getElementById('filter-type').value;
const bikeFilter = document.getElementById('filter-bike').value;
let url = `/api/activities/list?limit=${limit}&offset=${currentPage * limit}`;
if (typeFilter) {
url = `/api/activities/query?activity_type=${typeFilter}`;
// If any filter is active, force query mode
if (typeFilter || bikeFilter) {
url = `/api/activities/query?`;
const params = new URLSearchParams();
if (typeFilter) params.append('activity_type', typeFilter);
if (bikeFilter) params.append('bike_setup_id', bikeFilter);
url += params.toString();
document.getElementById('prev-page-btn').disabled = true;
document.getElementById('next-page-btn').disabled = true;
} else {
@@ -438,8 +459,8 @@
<button class="btn btn-outline-primary" onclick="downloadFile('${act.garmin_activity_id}')" title="Download Local File">
<i class="bi bi-download"></i>
</button>
<button class="btn btn-outline-warning" onclick="redownload('${act.garmin_activity_id}')" title="Redownload from Garmin">
<i class="bi bi-cloud-download"></i>
<button class="btn btn-outline-warning" onclick="redownload('${act.garmin_activity_id}')" title="Refresh Data & Rematch Bike">
<i class="bi bi-arrow-clockwise"></i>
</button>
<a href="/activity/${act.garmin_activity_id}" target="_blank" class="btn btn-outline-info" title="View Details">
<i class="bi bi-eye"></i>
@@ -577,6 +598,44 @@
}
}
async function fetchBikeSetups() {
try {
const res = await fetch('/api/bike-setups');
if (!res.ok) throw new Error("Failed to fetch bikes");
const bikes = await res.json();
const select = document.getElementById('filter-bike');
bikes.forEach(bike => {
const opt = document.createElement('option');
opt.value = bike.id;
opt.textContent = bike.name ? `${bike.name} (${bike.frame})` : bike.frame;
select.appendChild(opt);
});
} catch (e) {
console.error(e);
}
}
async function refreshActivity(garminId) {
if (!confirm("Are you sure you want to re-download this activity from Garmin and run bike matching?")) {
return;
}
showToast("Processing...", "Refreshing activity data...", "info");
try {
const res = await fetch(`/api/activities/${garminId}/redownload`, { method: 'POST' });
const data = await res.json();
if (res.ok) {
showToast("Success", data.message, "success");
loadActivities(); // Reload table
} else {
throw new Error(data.detail || "Refresh failed");
}
} catch (e) {
showToast("Error", e.message, "error");
}
}
window.showActivityDetails = async function (id) {
// Reset fields
document.querySelectorAll('[id^="det-"]').forEach(el => el.textContent = '-');