134 lines
5.2 KiB
Vue
134 lines
5.2 KiB
Vue
<script setup lang="ts">
|
|
defineProps<{ activities: string[], stays: string[], weathers: string[], weatherExtras: string[], hasSeasons: boolean }>()
|
|
|
|
const settings = defineModel<PackerSettings>({ required: true })
|
|
const { packer } = useAppConfig()
|
|
|
|
const toggled = (list: string[], label: string) => list.includes(label) ? list.filter(item => item !== label) : [...list, label]
|
|
|
|
function toggleActivity(label: string) {
|
|
settings.value.activities = toggled(settings.value.activities, label)
|
|
}
|
|
|
|
function toggleWeather(label: string) {
|
|
settings.value.weatherExtras = toggled(settings.value.weatherExtras, label)
|
|
}
|
|
|
|
const weatherIcon = (weather: string) => packer.weatherIcons[weather] ?? 'i-lucide-cloud'
|
|
|
|
const activityIcon = (activity: string) => packer.activityIcons[activity] ?? 'i-lucide-tag'
|
|
|
|
const SEASON_ICONS: Record<PackerSeason, string> = {
|
|
Frühling: 'i-lucide-flower',
|
|
Sommer: 'i-lucide-sun',
|
|
Herbst: 'i-lucide-leaf',
|
|
Winter: 'i-lucide-snowflake'
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col gap-6 rounded-lg p-4 ring-1 ring-default sm:p-5">
|
|
<!-- Side by side once there is room; Reise only takes the width it needs, so the four seasons fit next to it -->
|
|
<div class="grid gap-x-8 gap-y-6 md:grid-cols-[auto_1fr]">
|
|
<section class="flex flex-col gap-4">
|
|
<h2 class="text-xs font-semibold tracking-wide text-muted uppercase">
|
|
Reise
|
|
</h2>
|
|
<UFormField label="Personen">
|
|
<UInputNumber v-model="settings.people" :min="1" :max="PACKER_MAX_PEOPLE" class="w-32" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Tage">
|
|
<UInputNumber v-model="settings.days" :min="1" :max="PACKER_MAX_DAYS" class="w-32" />
|
|
</UFormField>
|
|
|
|
<!-- Only once the trip has a night -->
|
|
<UFormField v-if="settings.days > 1 && stays.length > 1" label="Schlafen">
|
|
<UFieldGroup>
|
|
<UButton
|
|
v-for="stay in stays"
|
|
:key="stay"
|
|
:label="stay"
|
|
:icon="activityIcon(stay)"
|
|
:color="settings.stay === stay ? 'primary' : 'neutral'"
|
|
:variant="settings.stay === stay ? 'solid' : 'outline'"
|
|
:aria-pressed="settings.stay === stay"
|
|
@click="settings.stay = stay"
|
|
/>
|
|
</UFieldGroup>
|
|
</UFormField>
|
|
</section>
|
|
|
|
<section v-if="weathers.length > 1 || weatherExtras.length || hasSeasons" class="flex flex-col gap-4">
|
|
<h2 class="text-xs font-semibold tracking-wide text-muted uppercase">
|
|
Bedingungen
|
|
</h2>
|
|
<UFormField v-if="weathers.length > 1 || weatherExtras.length" label="Wetter">
|
|
<div class="flex flex-wrap gap-2">
|
|
<UFieldGroup v-if="weathers.length > 1">
|
|
<UButton
|
|
v-for="weather in weathers"
|
|
:key="weather"
|
|
:label="weather"
|
|
:icon="weatherIcon(weather)"
|
|
:ui="{ leadingIcon: 'max-sm:hidden' }"
|
|
:color="settings.weather === weather ? 'primary' : 'neutral'"
|
|
:variant="settings.weather === weather ? 'solid' : 'outline'"
|
|
:aria-pressed="settings.weather === weather"
|
|
@click="settings.weather = weather"
|
|
/>
|
|
</UFieldGroup>
|
|
<!-- On top of the weather above, e.g. windy -->
|
|
<UButton
|
|
v-for="weather in weatherExtras"
|
|
:key="weather"
|
|
:label="weather"
|
|
:icon="weatherIcon(weather)"
|
|
:ui="{ leadingIcon: 'max-sm:hidden' }"
|
|
:color="settings.weatherExtras.includes(weather) ? 'primary' : 'neutral'"
|
|
:variant="settings.weatherExtras.includes(weather) ? 'solid' : 'outline'"
|
|
:aria-pressed="settings.weatherExtras.includes(weather)"
|
|
@click="toggleWeather(weather)"
|
|
/>
|
|
</div>
|
|
</UFormField>
|
|
|
|
<!-- Without icons on phones, so the four fit in one row -->
|
|
<UFormField v-if="hasSeasons" label="Jahreszeit">
|
|
<UFieldGroup>
|
|
<UButton
|
|
v-for="season in PACKER_SEASONS"
|
|
:key="season"
|
|
:label="season"
|
|
:icon="SEASON_ICONS[season]"
|
|
:ui="{ leadingIcon: 'max-sm:hidden' }"
|
|
:color="settings.season === season ? 'primary' : 'neutral'"
|
|
:variant="settings.season === season ? 'solid' : 'outline'"
|
|
:aria-pressed="settings.season === season"
|
|
@click="settings.season = season"
|
|
/>
|
|
</UFieldGroup>
|
|
</UFormField>
|
|
</section>
|
|
</div>
|
|
|
|
<section v-if="activities.length" class="flex flex-col gap-4">
|
|
<h2 class="text-xs font-semibold tracking-wide text-muted uppercase">
|
|
Extras
|
|
</h2>
|
|
<div class="flex flex-wrap gap-2">
|
|
<UButton
|
|
v-for="activity in activities"
|
|
:key="activity"
|
|
:label="activity"
|
|
:icon="activityIcon(activity)"
|
|
:color="settings.activities.includes(activity) ? 'primary' : 'neutral'"
|
|
:variant="settings.activities.includes(activity) ? 'solid' : 'outline'"
|
|
:aria-pressed="settings.activities.includes(activity)"
|
|
@click="toggleActivity(activity)"
|
|
/>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</template>
|