mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-19 21:09:37 +02:00
Update map filtering
This commit is contained in:
parent
5ff4f66fdb
commit
d0791faad5
5 changed files with 56 additions and 26 deletions
|
@ -19,7 +19,7 @@
|
|||
import DotsHorizontal from '~icons/mdi/dots-horizontal';
|
||||
import DeleteWarning from './DeleteWarning.svelte';
|
||||
import ImageDisplayModal from './ImageDisplayModal.svelte';
|
||||
import { typeToString } from '$lib';
|
||||
import { isAdventureVisited, typeToString } from '$lib';
|
||||
|
||||
export let type: string;
|
||||
export let user: User | null;
|
||||
|
@ -28,7 +28,6 @@
|
|||
let isCollectionModalOpen: boolean = false;
|
||||
let isWarningModalOpen: boolean = false;
|
||||
|
||||
let keyword: string = '';
|
||||
let image_url: string | null = null;
|
||||
export let adventure: Adventure;
|
||||
|
||||
|
@ -201,7 +200,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<div class="badge badge-primary">{typeToString(adventure.type)}</div>
|
||||
<div class="badge badge-success">{adventure.visits.length > 0 ? 'Visited' : 'Planned'}</div>
|
||||
<div class="badge badge-success">{isAdventureVisited(adventure) ? 'Visited' : 'Planned'}</div>
|
||||
<div class="badge badge-secondary">{adventure.is_public ? 'Public' : 'Private'}</div>
|
||||
</div>
|
||||
{#if adventure.location && adventure.location !== ''}
|
||||
|
|
|
@ -27,13 +27,12 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="collapse collapse-plus bg-base-300 mb-4 overflow-visible">
|
||||
<div class="collapse collapse-plus mb-4">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Category Filter</div>
|
||||
<div class="collapse-content">
|
||||
<button class="btn btn-wide mb-1 btn-neutral-300" on:click={clearTypes}>Clear</button>
|
||||
<div class="collapse-title text-xl bg-base-300 font-medium">Category Filter</div>
|
||||
<div class="collapse-content bg-base-300">
|
||||
<button class="btn btn-wide btn-neutral-300" on:click={clearTypes}>Clear</button>
|
||||
{#each ADVENTURE_TYPES as type}
|
||||
<!-- checkbox for each -->
|
||||
<li>
|
||||
<label class="cursor-pointer">
|
||||
<input
|
||||
|
|
|
@ -252,3 +252,22 @@ export function typeToString(type: string) {
|
|||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an adventure has been visited.
|
||||
*
|
||||
* This function determines if the `adventure.visits` array contains at least one visit
|
||||
* with a `start_date` that is before the current date.
|
||||
*
|
||||
* @param adventure - The adventure object to check.
|
||||
* @returns `true` if the adventure has been visited, otherwise `false`.
|
||||
*/
|
||||
export function isAdventureVisited(adventure: Adventure) {
|
||||
const currentTime = Date.now();
|
||||
|
||||
// Check if any visit's start_date is before the current time.
|
||||
return adventure.visits.some((visit) => {
|
||||
const visitStartTime = new Date(visit.start_date).getTime();
|
||||
return visit.start_date && visitStartTime <= currentTime;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ export const load = (async (event) => {
|
|||
if (!event.locals.user) {
|
||||
return redirect(302, '/login');
|
||||
} else {
|
||||
let visitedFetch = await fetch(`${endpoint}/api/adventures/all/`, {
|
||||
let visitedFetch = await fetch(`${endpoint}/api/adventures/`, {
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
|
@ -25,16 +25,26 @@ export const load = (async (event) => {
|
|||
console.error('Failed to fetch visited adventures');
|
||||
return redirect(302, '/login');
|
||||
} else {
|
||||
let visited = (await visitedFetch.json()) as Adventure[];
|
||||
let visited: Adventure[] = [];
|
||||
try {
|
||||
let api_result = await visitedFetch.json();
|
||||
visited = api_result.results as Adventure[];
|
||||
if (!Array.isArray(visited) || visited.length === 0 || !visited) {
|
||||
throw new Error('Visited adventures response is not an array');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing visited adventures:', error);
|
||||
return redirect(302, '/login');
|
||||
}
|
||||
|
||||
// make a long lat array like this { lngLat: [-20, 0], name: 'Adventure 1' },
|
||||
let markers = visited
|
||||
.filter((adventure) => adventure.latitude !== null && adventure.longitude !== null)
|
||||
.map((adventure) => {
|
||||
return {
|
||||
lngLat: [adventure.longitude, adventure.latitude] as [number, number],
|
||||
lngLat: [adventure.longitude, adventure.latitude],
|
||||
name: adventure.name,
|
||||
type: adventure.type,
|
||||
collection: adventure.collection
|
||||
visits: adventure.visits
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<script>
|
||||
// @ts-nocheck
|
||||
|
||||
import { isAdventureVisited } from '$lib';
|
||||
import AdventureModal from '$lib/components/AdventureModal.svelte';
|
||||
import {
|
||||
DefaultMarker,
|
||||
|
@ -16,12 +18,14 @@
|
|||
|
||||
let clickedName = '';
|
||||
|
||||
console.log(data);
|
||||
|
||||
let showVisited = true;
|
||||
let showPlanned = true;
|
||||
|
||||
$: filteredMarkers = markers.filter(
|
||||
(marker) =>
|
||||
(showVisited && marker.type === 'visited') || (showPlanned && marker.type === 'planned')
|
||||
(showVisited && isAdventureVisited(marker)) || (showPlanned && !isAdventureVisited(marker))
|
||||
);
|
||||
|
||||
let newMarker = [];
|
||||
|
@ -46,7 +50,8 @@
|
|||
let newMarker = {
|
||||
lngLat: [event.detail.longitude, event.detail.latitude],
|
||||
name: event.detail.name,
|
||||
type: event.detail.type
|
||||
type: event.detail.type,
|
||||
visits: event.detail.visits
|
||||
};
|
||||
markers = [...markers, newMarker];
|
||||
clearMarkers();
|
||||
|
@ -138,11 +143,11 @@
|
|||
class="relative aspect-[9/16] max-h-[70vh] w-full sm:aspect-video sm:max-h-full"
|
||||
standardControls
|
||||
>
|
||||
{#each filteredMarkers as { lngLat, name, type }}
|
||||
{#if type == 'visited'}
|
||||
{#each filteredMarkers as marker}
|
||||
{#if isAdventureVisited(marker)}
|
||||
<Marker
|
||||
{lngLat}
|
||||
on:click={() => (clickedName = name)}
|
||||
lngLat={marker.lngLat}
|
||||
on:click={() => (clickedName = marker.name)}
|
||||
class="grid h-8 w-8 place-items-center rounded-full border border-gray-200 bg-red-300 text-black shadow-md"
|
||||
>
|
||||
<svg
|
||||
|
@ -155,16 +160,14 @@
|
|||
<circle cx="12" cy="12" r="10" stroke="red" stroke-width="2" fill="red" />
|
||||
</svg>
|
||||
<Popup openOn="click" offset={[0, -10]}>
|
||||
<div class="text-lg text-black font-bold">{name}</div>
|
||||
<div class="text-lg text-black font-bold">{marker.name}</div>
|
||||
<p class="font-semibold text-black text-md">Visited</p>
|
||||
</Popup>
|
||||
</Marker>
|
||||
{/if}
|
||||
|
||||
{#if type == 'planned'}
|
||||
{:else}
|
||||
<Marker
|
||||
{lngLat}
|
||||
on:click={() => (clickedName = name)}
|
||||
lngLat={marker.lngLat}
|
||||
on:click={() => (clickedName = marker.name)}
|
||||
class="grid h-8 w-8 place-items-center rounded-full border border-gray-200 bg-blue-300 text-black shadow-2xl focus:outline-2 focus:outline-black"
|
||||
>
|
||||
<svg
|
||||
|
@ -177,7 +180,7 @@
|
|||
<circle cx="12" cy="12" r="10" stroke="blue" stroke-width="2" fill="blue" />
|
||||
</svg>
|
||||
<Popup openOn="click" offset={[0, -10]}>
|
||||
<div class="text-lg text-black font-bold">{name}</div>
|
||||
<div class="text-lg text-black font-bold">{marker.name}</div>
|
||||
<p class="font-semibold text-black text-md">Planned</p>
|
||||
</Popup>
|
||||
</Marker>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue