mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-15 15:37:33 +08:00
support daily and yearly intervals for scheduled transactions
This commit is contained in:
@@ -4,8 +4,11 @@ import { useI18n } from '@/locales/helpers.ts';
|
||||
|
||||
import { useUserStore } from '@/stores/user.ts';
|
||||
|
||||
import type { TypeAndDisplayName } from '@/core/base.ts';
|
||||
import { type TypeAndDisplayName, itemAndIndex } from '@/core/base.ts';
|
||||
import { type DateTime } from '@/core/datetime.ts';
|
||||
|
||||
import { sortNumbersArray } from '@/lib/common.ts';
|
||||
import { getCurrentDateTime } from '@/lib/datetime.ts';
|
||||
|
||||
export interface CommonScheduleFrequencySelectionProps {
|
||||
type: number;
|
||||
@@ -19,7 +22,8 @@ export function useScheduleFrequencySelectionBase() {
|
||||
const {
|
||||
getAllWeekDays,
|
||||
getAvailableMonthDays,
|
||||
getAllTransactionScheduledFrequencyTypes
|
||||
getAllTransactionScheduledFrequencyTypes,
|
||||
formatDateTimeToLongMonthDay
|
||||
} = useI18n();
|
||||
const userStore = useUserStore();
|
||||
|
||||
@@ -27,6 +31,33 @@ export function useScheduleFrequencySelectionBase() {
|
||||
const allWeekDays = computed<TypeAndDisplayName[]>(() => getAllWeekDays(userStore.currentUserFirstDayOfWeek));
|
||||
|
||||
const allAvailableMonthDays = computed<TypeAndDisplayName[]>(() => getAvailableMonthDays(28, 3));
|
||||
const allAvailableMonthAndDays = computed<TypeAndDisplayName[]>(() => {
|
||||
const ret: TypeAndDisplayName[] = [];
|
||||
const now: DateTime = getCurrentDateTime();
|
||||
const maxDaysOfMonth: number[] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||
|
||||
for (const [days, index] of itemAndIndex(maxDaysOfMonth)) {
|
||||
const month = index + 1;
|
||||
|
||||
for (let day = 1; day <= days; day++) {
|
||||
const dateTime = now.set({
|
||||
month: month,
|
||||
dayOfMonth: day,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
millisecond: 0
|
||||
});
|
||||
|
||||
ret.push({
|
||||
type: month * 100 + day,
|
||||
displayName: formatDateTimeToLongMonthDay(dateTime)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
function getFrequencyValues(value: string): number[] {
|
||||
const values = value.split(',');
|
||||
@@ -46,6 +77,7 @@ export function useScheduleFrequencySelectionBase() {
|
||||
allTransactionScheduledFrequencyTypes,
|
||||
allWeekDays,
|
||||
allAvailableMonthDays,
|
||||
allAvailableMonthAndDays,
|
||||
// functions
|
||||
getFrequencyValues
|
||||
};
|
||||
|
||||
@@ -28,14 +28,18 @@
|
||||
<v-list v-if="frequencyType === ScheduledTemplateFrequencyType.Disabled.type">
|
||||
<v-list-item :title="tt('None')"></v-list-item>
|
||||
</v-list>
|
||||
<v-list v-if="frequencyType === ScheduledTemplateFrequencyType.Daily.type">
|
||||
<v-list-item :title="tt('Daily')"></v-list-item>
|
||||
</v-list>
|
||||
<v-list select-strategy="classic" v-model:selected="frequencyValue"
|
||||
v-else-if="frequencyType === ScheduledTemplateFrequencyType.Weekly.type">
|
||||
<v-list-item :key="weekDay.type" :value="weekDay.type" :title="weekDay.displayName"
|
||||
:class="{ 'frequency-value-selected v-list-item--active text-primary': isFrequencyValueSelected(weekDay.type) }"
|
||||
v-for="weekDay in allWeekDays">
|
||||
<template #prepend="{ isActive }">
|
||||
<v-checkbox density="compact" class="me-1" :model-value="isActive"
|
||||
@update:model-value="updateFrequencyValue(weekDay.type, $event)"></v-checkbox>
|
||||
<template #prepend="{ isSelected, select }">
|
||||
<v-list-item-action start>
|
||||
<v-checkbox-btn density="compact" :model-value="isSelected" @update:model-value="select"></v-checkbox-btn>
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -44,9 +48,22 @@
|
||||
<v-list-item :key="monthDay.type" :value="monthDay.type" :title="monthDay.displayName"
|
||||
:class="{ 'frequency-value-selected v-list-item--active text-primary': isFrequencyValueSelected(monthDay.type) }"
|
||||
v-for="monthDay in allAvailableMonthDays">
|
||||
<template #prepend="{ isActive }">
|
||||
<v-checkbox density="compact" class="me-1" :model-value="isActive"
|
||||
@update:model-value="updateFrequencyValue(monthDay.type, $event)"></v-checkbox>
|
||||
<template #prepend="{ isSelected, select }">
|
||||
<v-list-item-action start>
|
||||
<v-checkbox-btn density="compact" :model-value="isSelected" @update:model-value="select"></v-checkbox-btn>
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<v-list select-strategy="classic" v-model:selected="frequencyValue"
|
||||
v-else-if="frequencyType === ScheduledTemplateFrequencyType.Yearly.type">
|
||||
<v-list-item :key="monthAndDay.type" :value="monthAndDay.type" :title="monthAndDay.displayName"
|
||||
:class="{ 'frequency-value-selected v-list-item--active text-primary': isFrequencyValueSelected(monthAndDay.type) }"
|
||||
v-for="monthAndDay in allAvailableMonthAndDays">
|
||||
<template #prepend="{ isSelected, select }">
|
||||
<v-list-item-action start>
|
||||
<v-checkbox-btn density="compact" :model-value="isSelected" @update:model-value="select"></v-checkbox-btn>
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
@@ -75,8 +92,19 @@ const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void;
|
||||
}>();
|
||||
|
||||
const { tt, getMultiMonthdayShortNames, getMultiWeekdayLongNames } = useI18n();
|
||||
const { allTransactionScheduledFrequencyTypes, allWeekDays, allAvailableMonthDays, getFrequencyValues } = useScheduleFrequencySelectionBase();
|
||||
const {
|
||||
tt,
|
||||
getMultiMonthAndDayLongNames,
|
||||
getMultiMonthdayShortNames,
|
||||
getMultiWeekdayLongNames
|
||||
} = useI18n();
|
||||
const {
|
||||
allTransactionScheduledFrequencyTypes,
|
||||
allWeekDays,
|
||||
allAvailableMonthDays,
|
||||
allAvailableMonthAndDays,
|
||||
getFrequencyValues
|
||||
} = useScheduleFrequencySelectionBase();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
@@ -92,10 +120,14 @@ const frequencyType = computed<number>({
|
||||
if (props.type !== value) {
|
||||
emit('update:type', value);
|
||||
|
||||
if (value === ScheduledTemplateFrequencyType.Weekly.type) {
|
||||
if (value === ScheduledTemplateFrequencyType.Daily.type) {
|
||||
frequencyValue.value = [0];
|
||||
} else if (value === ScheduledTemplateFrequencyType.Weekly.type) {
|
||||
frequencyValue.value = [firstDayOfWeek.value];
|
||||
} else if (value === ScheduledTemplateFrequencyType.Monthly.type) {
|
||||
frequencyValue.value = [1];
|
||||
} else if (value === ScheduledTemplateFrequencyType.Yearly.type) {
|
||||
frequencyValue.value = [101];
|
||||
} else {
|
||||
frequencyValue.value = [];
|
||||
}
|
||||
@@ -113,6 +145,8 @@ const frequencyValue = computed<number[]>({
|
||||
const displayFrequency = computed<string>(() => {
|
||||
if (frequencyType.value === ScheduledTemplateFrequencyType.Disabled.type) {
|
||||
return tt('Disabled');
|
||||
} else if (frequencyType.value === ScheduledTemplateFrequencyType.Daily.type) {
|
||||
return tt('Daily');
|
||||
} else if (frequencyType.value === ScheduledTemplateFrequencyType.Weekly.type) {
|
||||
if (frequencyValue.value.length) {
|
||||
return tt('format.misc.everyMultiDaysOfWeek', {
|
||||
@@ -129,28 +163,19 @@ const displayFrequency = computed<string>(() => {
|
||||
} else {
|
||||
return tt('Monthly');
|
||||
}
|
||||
} else if (frequencyType.value === ScheduledTemplateFrequencyType.Yearly.type) {
|
||||
if (frequencyValue.value.length) {
|
||||
return tt('format.misc.everyMultiDaysOfYear', {
|
||||
days: getMultiMonthAndDayLongNames(frequencyValue.value)
|
||||
});
|
||||
} else {
|
||||
return tt('Yearly');
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
function updateFrequencyValue(value: number, selected: boolean | null): void {
|
||||
const currentFrequencyValues = frequencyValue.value;
|
||||
const newFrequencyValues: number[] = [];
|
||||
|
||||
for (const currentFrequencyValue of currentFrequencyValues) {
|
||||
if (currentFrequencyValue !== value || selected) {
|
||||
newFrequencyValues.push(currentFrequencyValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
newFrequencyValues.push(value);
|
||||
}
|
||||
|
||||
frequencyValue.value = sortNumbersArray(newFrequencyValues);
|
||||
}
|
||||
|
||||
function isFrequencyValueSelected(currentValue: number): boolean {
|
||||
return frequencyValue.value.indexOf(currentValue) >= 0;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
v-if="currentFrequencyType === ScheduledTemplateFrequencyType.Disabled.type">
|
||||
<f7-list-item :title="tt('None')"></f7-list-item>
|
||||
</f7-list>
|
||||
<f7-list dividers class="schedule-frequency-value-list no-margin-vertical"
|
||||
v-if="currentFrequencyType === ScheduledTemplateFrequencyType.Daily.type">
|
||||
<f7-list-item :title="tt('Daily')"></f7-list-item>
|
||||
</f7-list>
|
||||
<f7-list dividers class="schedule-frequency-value-list no-margin-vertical"
|
||||
v-if="currentFrequencyType === ScheduledTemplateFrequencyType.Weekly.type">
|
||||
<f7-list-item checkbox
|
||||
@@ -57,6 +61,18 @@
|
||||
@change="changeFrequencyValue">
|
||||
</f7-list-item>
|
||||
</f7-list>
|
||||
<f7-list dividers class="schedule-frequency-value-list no-margin-vertical"
|
||||
v-if="currentFrequencyType === ScheduledTemplateFrequencyType.Yearly.type">
|
||||
<f7-list-item checkbox
|
||||
:class="isChecked(monthAndDay.type) ? 'list-item-selected' : ''"
|
||||
:key="monthAndDay.type"
|
||||
:value="monthAndDay.type"
|
||||
:checked="isChecked(monthAndDay.type)"
|
||||
:title="monthAndDay.displayName"
|
||||
v-for="monthAndDay in allAvailableMonthAndDays"
|
||||
@change="changeFrequencyValue">
|
||||
</f7-list-item>
|
||||
</f7-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,7 +107,13 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const { tt } = useI18n();
|
||||
const { allTransactionScheduledFrequencyTypes, allWeekDays, allAvailableMonthDays, getFrequencyValues } = useScheduleFrequencySelectionBase();
|
||||
const {
|
||||
allTransactionScheduledFrequencyTypes,
|
||||
allWeekDays,
|
||||
allAvailableMonthDays,
|
||||
allAvailableMonthAndDays,
|
||||
getFrequencyValues
|
||||
} = useScheduleFrequencySelectionBase();
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
@@ -108,10 +130,14 @@ function changeFrequencyType(value: number): void {
|
||||
if (currentFrequencyType.value !== value) {
|
||||
currentFrequencyType.value = value;
|
||||
|
||||
if (value === ScheduledTemplateFrequencyType.Weekly.type) {
|
||||
if (value === ScheduledTemplateFrequencyType.Daily.type) {
|
||||
currentFrequencyValue.value = [0];
|
||||
} else if (value === ScheduledTemplateFrequencyType.Weekly.type) {
|
||||
currentFrequencyValue.value = [firstDayOfWeek.value];
|
||||
} else if (value === ScheduledTemplateFrequencyType.Monthly.type) {
|
||||
currentFrequencyValue.value = [1];
|
||||
} else if (value === ScheduledTemplateFrequencyType.Yearly.type) {
|
||||
currentFrequencyValue.value = [101];
|
||||
} else {
|
||||
currentFrequencyValue.value = [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user