feat(reminders): move reminder settings to a popup
This commit is contained in:
parent
e6c4c18974
commit
ae177c73ea
26
src/components/input/SimpleButton.vue
Normal file
26
src/components/input/SimpleButton.vue
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<BaseButton class="simple-button">
|
||||||
|
<slot/>
|
||||||
|
</BaseButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.simple-button {
|
||||||
|
color: var(--text);
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
transition: background-color $transition;
|
||||||
|
border-radius: $radius;
|
||||||
|
display: block;
|
||||||
|
margin: .1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="datepicker">
|
<div class="datepicker">
|
||||||
<BaseButton @click.stop="toggleDatePopup" class="show" :disabled="disabled || undefined">
|
<SimpleButton @click.stop="toggleDatePopup" class="show" :disabled="disabled || undefined">
|
||||||
{{ date === null ? chooseDateLabel : formatDateShort(date) }}
|
{{ date === null ? chooseDateLabel : formatDateShort(date) }}
|
||||||
</BaseButton>
|
</SimpleButton>
|
||||||
|
|
||||||
<CustomTransition name="fade">
|
<CustomTransition name="fade">
|
||||||
<div v-if="show" class="datepicker-popup" ref="datepickerPopup">
|
<div v-if="show" class="datepicker-popup" ref="datepickerPopup">
|
||||||
@ -28,14 +28,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted, onBeforeUnmount, toRef, watch, type PropType} from 'vue'
|
import {ref, onMounted, onBeforeUnmount, toRef, watch, type PropType} from 'vue'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
|
||||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||||
|
import DatepickerInline from '@/components/input/datepickerInline.vue'
|
||||||
|
import SimpleButton from '@/components/input/SimpleButton.vue'
|
||||||
|
|
||||||
import {formatDateShort} from '@/helpers/time/formatDate'
|
import {formatDateShort} from '@/helpers/time/formatDate'
|
||||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||||
import {createDateFromString} from '@/helpers/time/createDateFromString'
|
import {createDateFromString} from '@/helpers/time/createDateFromString'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import DatepickerInline from '@/components/input/datepickerInline.vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -23,11 +23,14 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
|
||||||
const open = ref(false)
|
const open = ref(false)
|
||||||
const popup = ref<HTMLElement | null>(null)
|
const popup = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
open.value = false
|
open.value = false
|
||||||
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
|
@ -1,33 +1,44 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<Popup @close="showFormSwitch = null">
|
||||||
|
<template #trigger="{toggle}">
|
||||||
|
<SimpleButton
|
||||||
|
@click.prevent.stop="toggle()"
|
||||||
|
>
|
||||||
|
{{ reminderText }}
|
||||||
|
</SimpleButton>
|
||||||
|
</template>
|
||||||
|
<template #content="{isOpen}">
|
||||||
|
<Card class="reminder-options-popup" :class="{'is-open': isOpen}" :padding="false">
|
||||||
|
<div class="options" v-if="showFormSwitch === null">
|
||||||
|
<SimpleButton
|
||||||
|
class="option-button"
|
||||||
|
v-for="p in presets"
|
||||||
|
>
|
||||||
|
{{ formatReminder(p) }}
|
||||||
|
</SimpleButton>
|
||||||
|
<SimpleButton @click="showFormSwitch = 'relative'" class="option-button">
|
||||||
|
Custom
|
||||||
|
</SimpleButton>
|
||||||
|
<SimpleButton @click="showFormSwitch = 'absolute'" class="option-button">
|
||||||
|
Date
|
||||||
|
</SimpleButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ reminderText }}
|
<ReminderPeriod
|
||||||
|
v-if="showFormSwitch === 'relative'"
|
||||||
|
v-model="reminder"
|
||||||
|
@update:modelValue="emit('update:modelValue', reminder)"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="options" v-if="showFormSwitch === null">
|
<DatepickerInline
|
||||||
<BaseButton
|
v-if="showFormSwitch === 'absolute'"
|
||||||
v-for="p in presets"
|
v-model="reminderDate"
|
||||||
>
|
@update:modelValue="setReminderDate"
|
||||||
{{ formatReminder(p) }}
|
/>
|
||||||
</BaseButton>
|
</Card>
|
||||||
<BaseButton @click="showFormSwitch = 'relative'">
|
</template>
|
||||||
Custom
|
</Popup>
|
||||||
</BaseButton>
|
|
||||||
<BaseButton @click="showFormSwitch = 'absolute'">
|
|
||||||
Date
|
|
||||||
</BaseButton>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ReminderPeriod
|
|
||||||
v-if="showFormSwitch === 'relative'"
|
|
||||||
v-model="reminder"
|
|
||||||
@update:modelValue="emit('update:modelValue', reminder)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DatepickerInline
|
|
||||||
v-if="showFormSwitch === 'absolute'"
|
|
||||||
v-model="reminderDate"
|
|
||||||
@update:modelValue="setReminderDate"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -45,8 +56,11 @@ import {formatDateShort} from '@/helpers/time/formatDate'
|
|||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import DatepickerInline from '@/components/input/datepickerInline.vue'
|
import DatepickerInline from '@/components/input/datepickerInline.vue'
|
||||||
import ReminderPeriod from '@/components/tasks/partials/reminder-period.vue'
|
import ReminderPeriod from '@/components/tasks/partials/reminder-period.vue'
|
||||||
|
import Popup from '@/components/misc/popup.vue'
|
||||||
|
|
||||||
import TaskReminderModel from '@/models/taskReminder'
|
import TaskReminderModel from '@/models/taskReminder'
|
||||||
|
import Card from '@/components/misc/card.vue'
|
||||||
|
import SimpleButton from '@/components/input/SimpleButton.vue'
|
||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
|
||||||
@ -75,7 +89,7 @@ const reminderDate = ref(null)
|
|||||||
const showFormSwitch = ref<null | 'relative' | 'absolute'>(null)
|
const showFormSwitch = ref<null | 'relative' | 'absolute'>(null)
|
||||||
|
|
||||||
const reminderText = computed(() => {
|
const reminderText = computed(() => {
|
||||||
|
|
||||||
if (reminder.value.relativeTo !== null) {
|
if (reminder.value.relativeTo !== null) {
|
||||||
return formatReminder(reminder.value)
|
return formatReminder(reminder.value)
|
||||||
}
|
}
|
||||||
@ -106,7 +120,7 @@ function setReminderDate() {
|
|||||||
function formatReminder(reminder: TaskReminderModel) {
|
function formatReminder(reminder: TaskReminderModel) {
|
||||||
|
|
||||||
const period = secondsToPeriod(reminder.relativePeriod)
|
const period = secondsToPeriod(reminder.relativePeriod)
|
||||||
|
|
||||||
if (period.amount === 0) {
|
if (period.amount === 0) {
|
||||||
switch (reminder.relativeTo) {
|
switch (reminder.relativeTo) {
|
||||||
case REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE:
|
case REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE:
|
||||||
@ -117,9 +131,9 @@ function formatReminder(reminder: TaskReminderModel) {
|
|||||||
return t('task.reminder.onEndDate')
|
return t('task.reminder.onEndDate')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const amountAbs = Math.abs(period.amount)
|
const amountAbs = Math.abs(period.amount)
|
||||||
|
|
||||||
let relativeTo = ''
|
let relativeTo = ''
|
||||||
switch (reminder.relativeTo) {
|
switch (reminder.relativeTo) {
|
||||||
case REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE:
|
case REMINDER_PERIOD_RELATIVE_TO_TYPES.DUEDATE:
|
||||||
@ -132,7 +146,7 @@ function formatReminder(reminder: TaskReminderModel) {
|
|||||||
relativeTo = t('task.attributes.endDate')
|
relativeTo = t('task.attributes.endDate')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reminder.relativePeriod <= 0) {
|
if (reminder.relativePeriod <= 0) {
|
||||||
return t('task.reminder.before', {
|
return t('task.reminder.before', {
|
||||||
amount: amountAbs,
|
amount: amountAbs,
|
||||||
@ -140,7 +154,7 @@ function formatReminder(reminder: TaskReminderModel) {
|
|||||||
type: relativeTo,
|
type: relativeTo,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return t('task.reminder.after', {
|
return t('task.reminder.after', {
|
||||||
amount: amountAbs,
|
amount: amountAbs,
|
||||||
unit: translateUnit(amountAbs, period.unit),
|
unit: translateUnit(amountAbs, period.unit),
|
||||||
@ -174,4 +188,28 @@ function translateUnit(amount: number, unit: PeriodUnit): string {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.popup) {
|
||||||
|
top: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reminder-options-popup {
|
||||||
|
width: 300px;
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
@media screen and (max-width: ($tablet)) {
|
||||||
|
width: calc(100vw - 5rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-button {
|
||||||
|
font-size: .85rem;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: .5rem;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--grey-100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -95,7 +95,6 @@ const modelValue = toRef(props, 'modelValue')
|
|||||||
watch(
|
watch(
|
||||||
modelValue,
|
modelValue,
|
||||||
(value) => {
|
(value) => {
|
||||||
console.log({value})
|
|
||||||
const p = secondsToPeriod(value?.relativePeriod)
|
const p = secondsToPeriod(value?.relativePeriod)
|
||||||
period.value.durationUnit = p.unit
|
period.value.durationUnit = p.unit
|
||||||
period.value.duration = p.amount
|
period.value.duration = p.amount
|
||||||
|
Loading…
x
Reference in New Issue
Block a user