PronounsPage/components/TimezoneSelect.vue

131 lines
4.0 KiB
Vue

<template>
<div>
<div class="input-group mb-3">
<button type="button" class="btn btn-outline-primary" @click="detect">
<Icon v="location" />
<T>profile.timezone.detect</T>
</button>
<AutocompleteSelect v-model="timezone" :options="timezones" :placeholder="$t('profile.timezone.placeholder')" />
<button v-if="timezone" class="btn btn-outline-danger" type="button" @click="timezone = null">
<Icon v="times" />
</button>
</div>
<div v-if="timezoneInfo">
<div class="form-check form-switch my-2">
<label>
<input v-model="publishArea" class="form-check-input" type="checkbox" role="switch">
<T>profile.timezone.publishArea</T><T>quotation.colon</T>
<br class="d-md-none">
<strong>
<Icon :v="timezoneInfo.icon" />
<T>profile.timezone.areas.{{ timezoneInfo.area }}</T>
</strong>
</label>
</div>
<div class="form-check form-switch my-2">
<label>
<input v-model="publishLocation" class="form-check-input" type="checkbox" role="switch">
<T>profile.timezone.publishLocation</T><T>quotation.colon</T>
<br class="d-md-none">
<strong>
<Icon v="map-marked-alt" />
{{ timezoneInfo.displayLocation }}
</strong>
</label>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import useTimezone from '../composables/useTimezone.ts';
import type { Timezone } from '../src/profile.ts';
interface Data {
timezones: Record<string, string>;
timezone: string | null;
publishArea: boolean;
publishLocation: boolean;
}
export default defineComponent({
props: {
modelValue: { required: true, type: Object as PropType<Timezone | null> },
},
emits: ['update:modelValue'],
setup() {
const { getTimezoneInfo, timezoneDisplayName, detectBrowserTimezone } = useTimezone();
return {
getTimezoneInfo,
timezoneDisplayName,
detectBrowserTimezone,
};
},
data(): Data {
return {
timezones: {},
timezone: this.modelValue?.tz ?? null,
publishArea: !!this.modelValue?.area,
publishLocation: !!this.modelValue?.loc,
};
},
computed: {
timezoneInfo() {
return this.getTimezoneInfo(this.timezone);
},
},
watch: {
timezone() {
this.update();
},
publishArea() {
this.update();
},
publishLocation() {
this.update();
},
},
mounted() {
for (const tz of Intl.supportedValuesOf('timeZone')) {
if (!tz.includes('/')) {
// some browsers (Firefox) include timezones like "UTC" or "MST7MDT", while others (Chrome) don't
// we assume a <continent>/<city> format, so we skip these
continue;
}
this.timezones[tz] = this.timezoneDisplayName(tz);
}
},
methods: {
detect(): void {
this.timezone = this.detectBrowserTimezone();
},
update(): void {
this.$emit('update:modelValue', this.timezone
? {
tz: this.timezone,
area: this.publishArea,
loc: this.publishLocation,
}
: null);
},
},
});
</script>
<style lang="scss" scoped>
.select {
position: relative;
.list-group {
position: absolute;
top: 100%;
max-height: 300px;
overflow-y: auto;
z-index: 999;
}
}
</style>