initial commit

This commit is contained in:
Madison Grubb
2026-02-10 23:32:26 -05:00
commit b7046dc0e6
133 changed files with 26080 additions and 0 deletions

170
app/pages/poi.vue Normal file
View File

@@ -0,0 +1,170 @@
<template>
<div class="p-6">
<h2 class="mb-2 text-xl font-semibold tracking-wide text-kestrel-text [text-shadow:0_0_8px_rgba(34,201,201,0.25)]">
POI placement
</h2>
<p
v-if="!canEditPois"
class="mb-4 text-sm text-kestrel-muted"
>
View-only. Sign in as admin or leader to add or edit POIs.
</p>
<template v-else>
<form
class="mb-6 flex flex-wrap items-end gap-3 rounded border border-kestrel-border bg-kestrel-surface p-4"
@submit.prevent="onAdd"
>
<div>
<label
for="poi-lat"
class="mb-1 block text-xs text-kestrel-muted"
>Lat</label>
<input
id="poi-lat"
v-model.number="form.lat"
type="number"
step="any"
required
class="w-28 rounded border border-kestrel-border bg-kestrel-bg px-2 py-1 text-sm text-kestrel-text"
>
</div>
<div>
<label
for="poi-lng"
class="mb-1 block text-xs text-kestrel-muted"
>Lng</label>
<input
id="poi-lng"
v-model.number="form.lng"
type="number"
step="any"
required
class="w-28 rounded border border-kestrel-border bg-kestrel-bg px-2 py-1 text-sm text-kestrel-text"
>
</div>
<div>
<label
for="poi-label"
class="mb-1 block text-xs text-kestrel-muted"
>Label</label>
<input
id="poi-label"
v-model="form.label"
type="text"
class="w-40 rounded border border-kestrel-border bg-kestrel-bg px-2 py-1 text-sm text-kestrel-text"
>
</div>
<div>
<label
for="poi-icon"
class="mb-1 block text-xs text-kestrel-muted"
>Icon</label>
<select
id="poi-icon"
v-model="form.iconType"
class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1 text-sm text-kestrel-text"
>
<option value="pin">
pin
</option>
<option value="flag">
flag
</option>
<option value="waypoint">
waypoint
</option>
</select>
</div>
<button
type="submit"
class="rounded bg-kestrel-accent px-3 py-1.5 text-sm font-medium text-kestrel-bg hover:opacity-90"
>
Add POI
</button>
</form>
</template>
<div class="overflow-x-auto rounded border border-kestrel-border">
<table class="w-full text-left text-sm">
<thead>
<tr class="border-b border-kestrel-border bg-kestrel-surface-hover">
<th class="px-4 py-2 font-medium text-kestrel-text">
Label
</th>
<th class="px-4 py-2 font-medium text-kestrel-text">
Lat
</th>
<th class="px-4 py-2 font-medium text-kestrel-text">
Lng
</th>
<th class="px-4 py-2 font-medium text-kestrel-text">
Icon
</th>
<th
v-if="canEditPois"
class="px-4 py-2 font-medium text-kestrel-text"
>
Actions
</th>
</tr>
</thead>
<tbody>
<tr
v-for="p in poisList"
:key="p.id"
class="border-b border-kestrel-border"
>
<td class="px-4 py-2 text-kestrel-text">
{{ p.label || '—' }}
</td>
<td class="px-4 py-2 text-kestrel-muted">
{{ p.lat }}
</td>
<td class="px-4 py-2 text-kestrel-muted">
{{ p.lng }}
</td>
<td class="px-4 py-2 text-kestrel-muted">
{{ p.icon_type }}
</td>
<td
v-if="canEditPois"
class="px-4 py-2"
>
<button
type="button"
class="text-xs text-red-400 hover:underline"
@click="remove(p.id)"
>
Delete
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script setup>
const { data: poisData, refresh } = usePois()
const { canEditPois } = useUser()
const poisList = computed(() => poisData.value ?? [])
const form = ref({ lat: 37.77, lng: -122.42, label: '', iconType: 'pin' })
async function onAdd() {
const { lat, lng, label, iconType } = form.value
try {
await $fetch('/api/pois', { method: 'POST', body: { lat, lng, label, iconType } })
await refresh()
}
catch { /* ignore */ }
}
async function remove(id) {
try {
await $fetch(`/api/pois/${id}`, { method: 'DELETE' })
await refresh()
}
catch { /* ignore */ }
}
</script>