mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 15:07:33 +08:00
314 lines
14 KiB
Vue
314 lines
14 KiB
Vue
<template>
|
|
<f7-page>
|
|
<f7-navbar>
|
|
<f7-nav-left :back-link="tt('Back')"></f7-nav-left>
|
|
<f7-nav-title :title="tt('Sign Up')"></f7-nav-title>
|
|
<f7-nav-right>
|
|
<f7-link icon-f7="checkmark_alt" :class="{ 'disabled': inputIsEmpty || submitting }" @click="submit"></f7-link>
|
|
</f7-nav-right>
|
|
</f7-navbar>
|
|
|
|
<f7-list form strong inset dividers class="margin-vertical">
|
|
<f7-list-input
|
|
type="text"
|
|
autocomplete="username"
|
|
autocapitalize="none"
|
|
autocorrect="off"
|
|
spellcheck="false"
|
|
inputmode="email"
|
|
clear-button
|
|
:label="tt('Username')"
|
|
:placeholder="tt('Your username')"
|
|
v-model:value="user.username"
|
|
></f7-list-input>
|
|
|
|
<f7-list-input
|
|
type="password"
|
|
autocomplete="new-password"
|
|
clear-button
|
|
:label="tt('Password')"
|
|
:placeholder="tt('Your password, at least 6 characters')"
|
|
v-model:value="user.password"
|
|
></f7-list-input>
|
|
|
|
<f7-list-input
|
|
type="password"
|
|
autocomplete="new-password"
|
|
clear-button
|
|
:label="tt('Confirm Password')"
|
|
:placeholder="tt('Re-enter the password')"
|
|
v-model:value="user.confirmPassword"
|
|
></f7-list-input>
|
|
|
|
<f7-list-input
|
|
type="email"
|
|
autocomplete="email"
|
|
clear-button
|
|
:label="tt('E-mail')"
|
|
:placeholder="tt('Your email address')"
|
|
v-model:value="user.email"
|
|
></f7-list-input>
|
|
|
|
<f7-list-input
|
|
type="text"
|
|
autocomplete="nickname"
|
|
clear-button
|
|
:label="tt('Nickname')"
|
|
:placeholder="tt('Your nickname')"
|
|
v-model:value="user.nickname"
|
|
></f7-list-input>
|
|
|
|
<f7-list-item class="ebk-list-item-error-info" v-if="inputIsInvalid" :footer="tt(inputInvalidProblemMessage)"></f7-list-item>
|
|
</f7-list>
|
|
|
|
<f7-list strong inset dividers class="margin-vertical">
|
|
<f7-list-item
|
|
class="list-item-with-header-and-title list-item-no-item-after"
|
|
link="#"
|
|
:header="languageTitle"
|
|
:title="currentLanguageName"
|
|
@click="showLanguagePopup = true"
|
|
>
|
|
<list-item-selection-popup value-type="item"
|
|
key-field="languageTag" value-field="languageTag"
|
|
title-field="nativeDisplayName" after-field="displayName"
|
|
:title="languageTitle"
|
|
:enable-filter="true"
|
|
:filter-placeholder="tt('Language')"
|
|
:filter-no-items-text="tt('No results')"
|
|
:items="allLanguages"
|
|
v-model:show="showLanguagePopup"
|
|
v-model="currentLocale">
|
|
</list-item-selection-popup>
|
|
</f7-list-item>
|
|
|
|
<f7-list-item
|
|
class="list-item-with-header-and-title list-item-no-item-after"
|
|
link="#"
|
|
:header="tt('Default Currency')"
|
|
@click="showDefaultCurrencyPopup = true"
|
|
>
|
|
<template #title>
|
|
<f7-block class="no-padding no-margin">
|
|
<span>{{ getCurrencyName(user.defaultCurrency) }} </span>
|
|
<small class="smaller">{{ user.defaultCurrency }}</small>
|
|
</f7-block>
|
|
</template>
|
|
<list-item-selection-popup value-type="item"
|
|
key-field="currencyCode" value-field="currencyCode"
|
|
title-field="displayName" after-field="currencyCode"
|
|
:title="tt('Default Currency')"
|
|
:enable-filter="true"
|
|
:filter-placeholder="tt('Currency')"
|
|
:filter-no-items-text="tt('No results')"
|
|
:items="allCurrencies"
|
|
v-model:show="showDefaultCurrencyPopup"
|
|
v-model="user.defaultCurrency">
|
|
</list-item-selection-popup>
|
|
</f7-list-item>
|
|
|
|
<f7-list-item
|
|
link="#"
|
|
class="list-item-with-header-and-title list-item-no-item-after"
|
|
:header="tt('First Day of Week')"
|
|
:title="currentDayOfWeekName"
|
|
@click="showFirstDayOfWeekPopup = true"
|
|
>
|
|
<list-item-selection-popup value-type="item"
|
|
key-field="type" value-field="type"
|
|
title-field="displayName"
|
|
:title="tt('First Day of Week')"
|
|
:enable-filter="true"
|
|
:filter-placeholder="tt('Date')"
|
|
:filter-no-items-text="tt('No results')"
|
|
:items="allWeekDays"
|
|
v-model:show="showFirstDayOfWeekPopup"
|
|
v-model="user.firstDayOfWeek">
|
|
</list-item-selection-popup>
|
|
</f7-list-item>
|
|
</f7-list>
|
|
|
|
<f7-list strong inset dividers class="margin-vertical">
|
|
<f7-list-item :title="tt('Use preset transaction categories')" link="#" @click="showPresetCategories = true">
|
|
<f7-toggle :checked="usePresetCategories" @toggle:change="usePresetCategories = $event"></f7-toggle>
|
|
</f7-list-item>
|
|
</f7-list>
|
|
|
|
<f7-popup push :close-on-escape="false" :opened="showPresetCategories"
|
|
@popup:closed="showPresetCategories = false">
|
|
<f7-page>
|
|
<f7-navbar>
|
|
<f7-nav-left>
|
|
<f7-link popup-close icon-f7="xmark"></f7-link>
|
|
</f7-nav-left>
|
|
<f7-nav-title :title="tt('Preset Categories')"></f7-nav-title>
|
|
<f7-nav-right class="navbar-compact-icons">
|
|
<f7-link icon-f7="ellipsis" @click="showPresetCategoriesMoreActionSheet = true"></f7-link>
|
|
<f7-link close @click="usePresetCategories = true; showPresetCategories = false" v-if="!usePresetCategories">{{ tt('Enable') }}</f7-link>
|
|
<f7-link close @click="usePresetCategories = false; showPresetCategories = false" v-if="usePresetCategories">{{ tt('Disable') }}</f7-link>
|
|
</f7-nav-right>
|
|
</f7-navbar>
|
|
<f7-block class="no-padding no-margin"
|
|
:key="categoryType" v-for="(categories, categoryType) in allPresetCategories">
|
|
<f7-block-title class="margin-top margin-horizontal">{{ getCategoryTypeName(parseInt(categoryType)) }}</f7-block-title>
|
|
<f7-list strong inset dividers v-if="showPresetCategories">
|
|
<f7-list-item :title="category.name"
|
|
:accordion-item="!!category.subCategories.length"
|
|
:key="idx"
|
|
v-for="(category, idx) in categories">
|
|
<template #media>
|
|
<ItemIcon icon-type="category" :icon-id="category.icon" :color="category.color"></ItemIcon>
|
|
</template>
|
|
|
|
<f7-accordion-content v-if="category.subCategories.length" class="padding-inline-start-half">
|
|
<f7-list>
|
|
<f7-list-item :title="subCategory.name"
|
|
:key="subIdx"
|
|
v-for="(subCategory, subIdx) in category.subCategories">
|
|
<template #media>
|
|
<ItemIcon icon-type="category" :icon-id="subCategory.icon" :color="subCategory.color"></ItemIcon>
|
|
</template>
|
|
</f7-list-item>
|
|
</f7-list>
|
|
</f7-accordion-content>
|
|
</f7-list-item>
|
|
</f7-list>
|
|
</f7-block>
|
|
</f7-page>
|
|
|
|
<f7-actions close-by-outside-click close-on-escape :opened="showPresetCategoriesMoreActionSheet" @actions:closed="showPresetCategoriesMoreActionSheet = false">
|
|
<f7-actions-group>
|
|
<f7-actions-button @click="showPresetCategoriesChangeLocaleSheet = true">{{ tt('Change Language') }}</f7-actions-button>
|
|
</f7-actions-group>
|
|
<f7-actions-group>
|
|
<f7-actions-button bold close>{{ tt('Cancel') }}</f7-actions-button>
|
|
</f7-actions-group>
|
|
</f7-actions>
|
|
|
|
<list-item-selection-sheet value-type="item"
|
|
key-field="languageTag" value-field="languageTag"
|
|
title-field="nativeDisplayName" after-field="displayName"
|
|
:items="allLanguages"
|
|
v-model:show="showPresetCategoriesChangeLocaleSheet"
|
|
v-model="currentLocale">
|
|
</list-item-selection-sheet>
|
|
</f7-popup>
|
|
</f7-page>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed } from 'vue';
|
|
import type { Router } from 'framework7/types';
|
|
|
|
import type { LanguageOption } from '@/locales/index.ts';
|
|
import { useI18n } from '@/locales/helpers.ts';
|
|
import { useI18nUIComponents, showLoading, hideLoading } from '@/lib/ui/mobile.ts';
|
|
import { useSignupPageBase } from '@/views/base/SignupPageBase.ts';
|
|
|
|
import { useRootStore } from '@/stores/index.ts';
|
|
|
|
import type { TypeAndDisplayName } from '@/core/base.ts';
|
|
import type { LocalizedCurrencyInfo } from '@/core/currency.ts';
|
|
import { type LocalizedPresetCategory } from '@/core/category.ts';
|
|
|
|
import { findDisplayNameByType, categorizedArrayToPlainArray } from '@/lib/common.ts';
|
|
import { isUserLogined } from '@/lib/userstate.ts';
|
|
|
|
const props = defineProps<{
|
|
f7router: Router.Router;
|
|
}>();
|
|
|
|
const { tt, getAllLanguageOptions, getAllCurrencies, getAllWeekDays, getAllTransactionDefaultCategories, getCurrencyName } = useI18n();
|
|
const { showAlert, showToast } = useI18nUIComponents();
|
|
|
|
const {
|
|
user,
|
|
submitting,
|
|
languageTitle,
|
|
currentLocale,
|
|
currentLanguageName,
|
|
inputEmptyProblemMessage,
|
|
inputInvalidProblemMessage,
|
|
inputIsEmpty,
|
|
inputIsInvalid,
|
|
getCategoryTypeName,
|
|
doAfterSignupSuccess
|
|
} = useSignupPageBase();
|
|
|
|
const rootStore = useRootStore();
|
|
|
|
const usePresetCategories = ref<boolean>(false);
|
|
const showLanguagePopup = ref<boolean>(false);
|
|
const showDefaultCurrencyPopup = ref<boolean>(false);
|
|
const showFirstDayOfWeekPopup = ref<boolean>(false);
|
|
const showPresetCategories = ref<boolean>(false);
|
|
const showPresetCategoriesMoreActionSheet = ref<boolean>(false);
|
|
const showPresetCategoriesChangeLocaleSheet = ref<boolean>(false);
|
|
|
|
const allLanguages = computed<LanguageOption[]>(() => getAllLanguageOptions(false));
|
|
const allCurrencies = computed<LocalizedCurrencyInfo[]>(() => getAllCurrencies());
|
|
const allWeekDays = computed<TypeAndDisplayName[]>(() => getAllWeekDays());
|
|
const allPresetCategories = computed<Record<string, LocalizedPresetCategory[]>>(() => getAllTransactionDefaultCategories(0, currentLocale.value));
|
|
const currentDayOfWeekName = computed<string | null>(() => findDisplayNameByType(allWeekDays.value, user.value.firstDayOfWeek));
|
|
|
|
function submit(): void {
|
|
const router = props.f7router;
|
|
|
|
const problemMessage = inputEmptyProblemMessage.value || inputInvalidProblemMessage.value;
|
|
|
|
if (problemMessage) {
|
|
showAlert(problemMessage);
|
|
return;
|
|
}
|
|
|
|
submitting.value = true;
|
|
showLoading(() => submitting.value);
|
|
|
|
let presetCategories: LocalizedPresetCategory[] = [];
|
|
|
|
if (usePresetCategories.value) {
|
|
presetCategories = categorizedArrayToPlainArray(allPresetCategories.value);
|
|
}
|
|
|
|
rootStore.register({
|
|
user: user.value,
|
|
presetCategories: presetCategories
|
|
}).then(response => {
|
|
if (!isUserLogined()) {
|
|
submitting.value = false;
|
|
hideLoading();
|
|
|
|
if (usePresetCategories.value && !response.presetCategoriesSaved) {
|
|
showToast('You have been successfully registered, but there was an failure when adding preset categories. You can re-add preset categories in settings page anytime.', 5000);
|
|
} else if (response.needVerifyEmail) {
|
|
showToast('You have been successfully registered. An account activation link has been sent to your email address, please activate your account first.', 5000);
|
|
} else {
|
|
showToast('You have been successfully registered');
|
|
}
|
|
|
|
router.navigate('/');
|
|
return;
|
|
}
|
|
|
|
doAfterSignupSuccess(response);
|
|
submitting.value = false;
|
|
hideLoading();
|
|
|
|
if (usePresetCategories.value && !response.presetCategoriesSaved) {
|
|
showToast('You have been successfully registered, but there was an failure when adding preset categories. You can re-add preset categories in settings page anytime.');
|
|
} else {
|
|
showToast('You have been successfully registered');
|
|
}
|
|
|
|
router.navigate('/');
|
|
}).catch(error => {
|
|
submitting.value = false;
|
|
hideLoading();
|
|
|
|
if (!error.processed) {
|
|
showToast(error.message || error);
|
|
}
|
|
});
|
|
}
|
|
</script>
|