Merge branch 'map-sorting' into 'master'

feat: map sorting and separate filter page

See merge request gk1623/drp-48!23
This commit is contained in:
2025-06-13 12:57:01 +00:00
9 changed files with 519 additions and 243 deletions

View File

@@ -0,0 +1,3 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M42 42L33.3 33.3M38 22C38 30.8366 30.8366 38 22 38C13.1634 38 6 30.8366 6 22C6 13.1634 13.1634 6 22 6C30.8366 6 38 13.1634 38 22Z" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 324 B

46
src/lib/filter.ts Normal file
View File

@@ -0,0 +1,46 @@
export interface SortFiler {
tags: string[];
/** Time strings of opening range. */
openAt: {
from: string;
to?: string;
};
nearby: {
lat: number;
lng: number;
};
}
export function urlencodeSortFilter(filter: Partial<SortFiler>): string {
const params = new URLSearchParams();
if (filter.tags) {
filter.tags.forEach((tag) => params.append("tags", tag));
}
if (filter.openAt) {
params.set("open_from", filter.openAt.from);
if (filter.openAt.to) params.set("open_to", filter.openAt.to);
}
if (filter.nearby) {
params.set("nearby", `${filter.nearby.lat},${filter.nearby.lng}`);
}
return params.toString();
}
export function urldecodeSortFilter(query: string): Partial<SortFiler> {
const params = new URLSearchParams(query);
const filter: Partial<SortFiler> = {};
if (params.has("tags")) {
filter.tags = params.getAll("tags");
}
if (params.has("open_from")) {
filter.openAt = {
from: params.get("open_from")!,
to: params.get("open_to") ?? undefined
};
}
if (params.has("nearby")) {
const [lat, lng] = params.get("nearby")!.split(",").map(Number);
filter.nearby = { lat, lng };
}
return filter;
}

View File

@@ -62,7 +62,25 @@ export const daysOfWeek = [
"All Other Days"
];
export function timeToMins(time: string) {
const [hour, min] = time.split(":");
return Number(hour) * 60 + Number(min);
// Convert "HH:MM" or "HH:MM:SS" to minutes since midnight
export function timeToMins(timeStr: string): number {
const [h, m] = timeStr.slice(0, 5).split(":").map(Number);
return h * 60 + m;
}
export function haversineDistance(
lat1Deg: number,
lng1Deg: number,
lat2Deg: number,
lng2Deg: number,
radius: number = 6371e3
): number {
const lat1 = lat1Deg * (Math.PI / 180);
const lat2 = lat2Deg * (Math.PI / 180);
const deltaLat = (lat2Deg - lat1Deg) * (Math.PI / 180);
const deltaLng = (lng2Deg - lng1Deg) * (Math.PI / 180);
const e1 =
Math.pow(Math.sin(deltaLat / 2), 2) +
Math.pow(Math.sin(deltaLng / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
return radius * 2 * Math.asin(Math.sqrt(e1));
}