mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-21 10:14:26 +08:00
migrate two column list item selection sheet to composition API and typescript
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
<div class="swipe-handler"></div>
|
<div class="swipe-handler"></div>
|
||||||
<div class="left"></div>
|
<div class="left"></div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<f7-link sheet-close :text="$t('Done')"></f7-link>
|
<f7-link sheet-close :text="tt('Done')"></f7-link>
|
||||||
</div>
|
</div>
|
||||||
</f7-toolbar>
|
</f7-toolbar>
|
||||||
<f7-page-content>
|
<f7-page-content>
|
||||||
@@ -15,16 +15,16 @@
|
|||||||
<f7-list dividers class="primary-list no-margin-vertical">
|
<f7-list dividers class="primary-list no-margin-vertical">
|
||||||
<f7-list-item link="#" no-chevron
|
<f7-list-item link="#" no-chevron
|
||||||
:class="{ 'primary-list-item-selected': item === selectedPrimaryItem }"
|
:class="{ 'primary-list-item-selected': item === selectedPrimaryItem }"
|
||||||
:value="primaryValueField ? item[primaryValueField] : item"
|
:value="primaryValueField ? (item as Record<string, unknown>)[primaryValueField] : item"
|
||||||
:title="$tIf(item[primaryTitleField], primaryTitleI18n)"
|
:title="ti(primaryTitleField ? (item as Record<string, unknown>)[primaryTitleField] as string : '', !!primaryTitleI18n)"
|
||||||
:header="$tIf(item[primaryHeaderField], primaryHeaderI18n)"
|
:header="ti(primaryHeaderField ? (item as Record<string, unknown>)[primaryHeaderField] as string : '', !!primaryHeaderI18n)"
|
||||||
:footer="$tIf(item[primaryFooterField], primaryFooterI18n)"
|
:footer="ti(primaryFooterField ? (item as Record<string, unknown>)[primaryFooterField] as string : '', !!primaryFooterI18n)"
|
||||||
:key="primaryKeyField ? item[primaryKeyField] : item"
|
:key="primaryKeyField ? (item as Record<string, unknown>)[primaryKeyField] : item"
|
||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
v-show="item && (!primaryHiddenField || !item[primaryHiddenField])"
|
v-show="item && (!primaryHiddenField || !(item as Record<string, unknown>)[primaryHiddenField])"
|
||||||
@click="onPrimaryItemClicked(item)">
|
@click="onPrimaryItemClicked(item)">
|
||||||
<template #media>
|
<template #media>
|
||||||
<ItemIcon :icon-type="primaryIconType" :icon-id="item[primaryIconField]" :color="item[primaryColorField]"></ItemIcon>
|
<ItemIcon :icon-type="primaryIconType" :icon-id="primaryIconField ? (item as Record<string, unknown>)[primaryIconField] : undefined" :color="primaryColorField ? (item as Record<string, unknown>)[primaryColorField] : undefined"></ItemIcon>
|
||||||
</template>
|
</template>
|
||||||
<template #after>
|
<template #after>
|
||||||
<f7-icon class="list-item-showing" f7="chevron_right" v-if="item === selectedPrimaryItem"></f7-icon>
|
<f7-icon class="list-item-showing" f7="chevron_right" v-if="item === selectedPrimaryItem"></f7-icon>
|
||||||
@@ -35,19 +35,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="secondary-list-container">
|
<div class="secondary-list-container">
|
||||||
<f7-list dividers class="secondary-list no-margin-vertical" v-if="selectedPrimaryItem && primarySubItemsField && selectedPrimaryItem[primarySubItemsField]">
|
<f7-list dividers class="secondary-list no-margin-vertical" v-if="selectedPrimaryItem && primarySubItemsField && (selectedPrimaryItem as Record<string, unknown>)[primarySubItemsField]">
|
||||||
<f7-list-item link="#" no-chevron
|
<f7-list-item link="#" no-chevron
|
||||||
:class="{ 'secondary-list-item-selected': isSecondarySelected(subItem) }"
|
:class="{ 'secondary-list-item-selected': isSecondarySelected(subItem) }"
|
||||||
:value="secondaryValueField ? subItem[secondaryValueField] : subItem"
|
:value="secondaryValueField ? subItem[secondaryValueField] : subItem"
|
||||||
:title="$tIf(subItem[secondaryTitleField], secondaryTitleI18n)"
|
:title="ti(secondaryTitleField ? subItem[secondaryTitleField] as string : '', !!secondaryTitleI18n)"
|
||||||
:header="$tIf(subItem[secondaryHeaderField], secondaryHeaderI18n)"
|
:header="ti(secondaryHeaderField ? subItem[secondaryHeaderField] as string : '', !!secondaryHeaderI18n)"
|
||||||
:footer="$tIf(subItem[secondaryFooterField], secondaryFooterI18n)"
|
:footer="ti(secondaryFooterField ? subItem[secondaryFooterField] as string : '', !!secondaryFooterI18n)"
|
||||||
:key="secondaryKeyField ? subItem[secondaryKeyField] : subItem"
|
:key="secondaryKeyField ? subItem[secondaryKeyField] : subItem"
|
||||||
v-for="subItem in selectedPrimaryItem[primarySubItemsField]"
|
v-for="subItem in (selectedPrimaryItem as Record<string, unknown>)[primarySubItemsField]"
|
||||||
v-show="subItem && (!secondaryHiddenField || !subItem[secondaryHiddenField])"
|
v-show="subItem && (!secondaryHiddenField || !subItem[secondaryHiddenField])"
|
||||||
@click="onSecondaryItemClicked(subItem)">
|
@click="onSecondaryItemClicked(subItem)">
|
||||||
<template #media>
|
<template #media>
|
||||||
<ItemIcon :icon-type="secondaryIconType" :icon-id="subItem[secondaryIconField]" :color="subItem[secondaryColorField]"></ItemIcon>
|
<ItemIcon :icon-type="secondaryIconType" :icon-id="secondaryIconField ? subItem[secondaryIconField] : undefined" :color="secondaryColorField ? subItem[secondaryColorField] : undefined"></ItemIcon>
|
||||||
</template>
|
</template>
|
||||||
<template #after>
|
<template #after>
|
||||||
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="isSecondarySelected(subItem)"></f7-icon>
|
<f7-icon class="list-item-checked-icon" f7="checkmark_alt" v-if="isSecondarySelected(subItem)"></f7-icon>
|
||||||
@@ -61,107 +61,110 @@
|
|||||||
</f7-sheet>
|
</f7-sheet>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/locales/helpers.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getItemByKeyValue,
|
getItemByKeyValue,
|
||||||
getPrimaryValueBySecondaryValue
|
getPrimaryValueBySecondaryValue
|
||||||
} from '@/lib/common.ts';
|
} from '@/lib/common.ts';
|
||||||
import { scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
import { type Framework7Dom, scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
||||||
|
|
||||||
export default {
|
const props = defineProps<{
|
||||||
props: [
|
modelValue: unknown;
|
||||||
'modelValue',
|
primaryKeyField?: string;
|
||||||
'primaryKeyField',
|
primaryValueField?: string;
|
||||||
'primaryValueField',
|
primaryTitleField?: string;
|
||||||
'primaryTitleField',
|
primaryTitleI18n?: boolean;
|
||||||
'primaryTitleI18n',
|
primaryHeaderField?: string;
|
||||||
'primaryHeaderField',
|
primaryHeaderI18n?: boolean;
|
||||||
'primaryHeaderI18n',
|
primaryFooterField?: string;
|
||||||
'primaryFooterField',
|
primaryFooterI18n?: boolean;
|
||||||
'primaryFooterI18n',
|
primaryIconField?: string;
|
||||||
'primaryIconField',
|
primaryIconType?: string;
|
||||||
'primaryIconType',
|
primaryColorField?: string;
|
||||||
'primaryColorField',
|
primaryHiddenField?: string;
|
||||||
'primaryHiddenField',
|
primarySubItemsField?: string;
|
||||||
'primarySubItemsField',
|
secondaryKeyField?: string;
|
||||||
'secondaryKeyField',
|
secondaryValueField?: string;
|
||||||
'secondaryValueField',
|
secondaryTitleField?: string;
|
||||||
'secondaryTitleField',
|
secondaryTitleI18n?: boolean;
|
||||||
'secondaryTitleI18n',
|
secondaryHeaderField?: string;
|
||||||
'secondaryHeaderField',
|
secondaryHeaderI18n?: boolean;
|
||||||
'secondaryHeaderI18n',
|
secondaryFooterField?: string;
|
||||||
'secondaryFooterField',
|
secondaryFooterI18n?: boolean;
|
||||||
'secondaryFooterI18n',
|
secondaryIconField?: string;
|
||||||
'secondaryIconField',
|
secondaryIconType?: string;
|
||||||
'secondaryIconType',
|
secondaryColorField?: string;
|
||||||
'secondaryColorField',
|
secondaryHiddenField?: string;
|
||||||
'secondaryHiddenField',
|
items: unknown[];
|
||||||
'items',
|
show: boolean;
|
||||||
'show'
|
}>();
|
||||||
],
|
const emit = defineEmits<{
|
||||||
emits: [
|
(e: 'update:modelValue', value: unknown): void;
|
||||||
'update:modelValue',
|
(e: 'update:show', value: boolean): void;
|
||||||
'update:show'
|
}>();
|
||||||
],
|
|
||||||
data() {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return {
|
const { tt, ti } = useI18n();
|
||||||
currentPrimaryValue: self.getPrimaryValueBySecondaryValue(self.modelValue),
|
|
||||||
currentSecondaryValue: self.modelValue
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
selectedPrimaryItem() {
|
|
||||||
if (this.primaryValueField) {
|
|
||||||
return getItemByKeyValue(this.items, this.currentPrimaryValue, this.primaryValueField);
|
|
||||||
} else {
|
|
||||||
return this.currentPrimaryValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSheetOpen(event) {
|
|
||||||
this.currentPrimaryValue = this.getPrimaryValueBySecondaryValue(this.modelValue);
|
|
||||||
this.currentSecondaryValue = this.modelValue;
|
|
||||||
scrollToSelectedItem(event.$el, '.primary-list-container', 'li.primary-list-item-selected');
|
|
||||||
scrollToSelectedItem(event.$el, '.secondary-list-container', 'li.secondary-list-item-selected');
|
|
||||||
},
|
|
||||||
onSheetClosed() {
|
|
||||||
this.close();
|
|
||||||
},
|
|
||||||
onPrimaryItemClicked(item) {
|
|
||||||
if (this.primaryValueField) {
|
|
||||||
this.currentPrimaryValue = item[this.primaryValueField];
|
|
||||||
} else {
|
|
||||||
this.currentPrimaryValue = item;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSecondaryItemClicked(subItem) {
|
|
||||||
if (this.secondaryValueField) {
|
|
||||||
this.currentSecondaryValue = subItem[this.secondaryValueField];
|
|
||||||
} else {
|
|
||||||
this.currentSecondaryValue = subItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$emit('update:modelValue', this.currentSecondaryValue);
|
const currentPrimaryValue = ref<unknown>(getCurrentPrimaryValueBySecondaryValue(props.modelValue));
|
||||||
this.close();
|
const currentSecondaryValue = ref<unknown>(props.modelValue);
|
||||||
},
|
|
||||||
isSecondarySelected(subItem) {
|
function getCurrentPrimaryValueBySecondaryValue(secondaryValue: unknown): unknown {
|
||||||
if (this.secondaryValueField) {
|
return getPrimaryValueBySecondaryValue(props.items as Record<string, Record<string, unknown>[]>[] | Record<string, Record<string, Record<string, unknown>[]>>, props.primarySubItemsField, props.primaryValueField, props.primaryHiddenField, props.secondaryValueField, props.secondaryHiddenField, secondaryValue);
|
||||||
return this.currentSecondaryValue === subItem[this.secondaryValueField];
|
}
|
||||||
} else {
|
|
||||||
return this.currentSecondaryValue === subItem;
|
function isSecondarySelected(subItem: unknown): boolean {
|
||||||
}
|
if (props.secondaryValueField) {
|
||||||
},
|
return currentSecondaryValue.value === (subItem as Record<string, unknown>)[props.secondaryValueField];
|
||||||
getPrimaryValueBySecondaryValue(secondaryValue) {
|
} else {
|
||||||
return getPrimaryValueBySecondaryValue(this.items, this.primarySubItemsField, this.primaryValueField, this.primaryHiddenField, this.secondaryValueField, this.secondaryHiddenField, secondaryValue);
|
return currentSecondaryValue.value === subItem;
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.$emit('update:show', false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectedPrimaryItem = computed<unknown>(() => {
|
||||||
|
if (props.primaryValueField) {
|
||||||
|
return getItemByKeyValue(props.items as Record<string, unknown>[] | Record<string, Record<string, unknown>>, currentPrimaryValue.value, props.primaryValueField);
|
||||||
|
} else {
|
||||||
|
return currentPrimaryValue.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
emit('update:show', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPrimaryItemClicked(item: unknown): void {
|
||||||
|
if (props.primaryValueField) {
|
||||||
|
currentPrimaryValue.value = (item as Record<string, unknown>)[props.primaryValueField];
|
||||||
|
} else {
|
||||||
|
currentPrimaryValue.value = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSecondaryItemClicked(subItem: unknown): void {
|
||||||
|
if (props.secondaryValueField) {
|
||||||
|
currentSecondaryValue.value = (subItem as Record<string, unknown>)[props.secondaryValueField];
|
||||||
|
} else {
|
||||||
|
currentSecondaryValue.value = subItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('update:modelValue', currentSecondaryValue.value);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSheetOpen(event: { $el: Framework7Dom }): void {
|
||||||
|
currentPrimaryValue.value = getCurrentPrimaryValueBySecondaryValue(props.modelValue);
|
||||||
|
currentSecondaryValue.value = props.modelValue;
|
||||||
|
scrollToSelectedItem(event.$el, '.primary-list-container', 'li.primary-list-item-selected');
|
||||||
|
scrollToSelectedItem(event.$el, '.secondary-list-container', 'li.secondary-list-item-selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSheetClosed() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
+2
-2
@@ -530,7 +530,7 @@ export function selectInvert(filterItemIds: Record<string, boolean>, allItemsMap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, Record<string, unknown>[]>, primarySubItemsField: string, secondaryValueField: string, secondaryHiddenField: string, secondaryValue: unknown): boolean {
|
export function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, Record<string, unknown>[]>, primarySubItemsField: string, secondaryValueField: string | undefined, secondaryHiddenField: string | undefined, secondaryValue: unknown): boolean {
|
||||||
for (let i = 0; i < primaryItem[primarySubItemsField].length; i++) {
|
for (let i = 0; i < primaryItem[primarySubItemsField].length; i++) {
|
||||||
const secondaryItem = primaryItem[primarySubItemsField][i];
|
const secondaryItem = primaryItem[primarySubItemsField][i];
|
||||||
|
|
||||||
@@ -548,7 +548,7 @@ export function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, Recor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPrimaryValueBySecondaryValue<T>(items: Record<string, Record<string, T>[]>[] | Record<string, Record<string, Record<string, T>[]>>, primarySubItemsField: string, primaryValueField: string, primaryHiddenField: string, secondaryValueField: string, secondaryHiddenField: string, secondaryValue: T): Record<string, T>[] | Record<string, Record<string, T>[]> | null {
|
export function getPrimaryValueBySecondaryValue<T>(items: Record<string, Record<string, T>[]>[] | Record<string, Record<string, Record<string, T>[]>>, primarySubItemsField: string | undefined, primaryValueField: string | undefined, primaryHiddenField: string | undefined, secondaryValueField: string | undefined, secondaryHiddenField: string | undefined, secondaryValue: T): Record<string, T>[] | Record<string, Record<string, T>[]> | null {
|
||||||
if (primarySubItemsField) {
|
if (primarySubItemsField) {
|
||||||
if (isArray(items)) {
|
if (isArray(items)) {
|
||||||
const arr = items as Record<string, Record<string, T>[]>[];
|
const arr = items as Record<string, Record<string, T>[]>[];
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ import { KnownErrorCode, SPECIFIED_API_NOT_FOUND_ERRORS, PARAMETERIZED_ERRORS }
|
|||||||
import type { LatestExchangeRateResponse, LocalizedLatestExchangeRate } from '@/models/exchange_rate.ts';
|
import type { LatestExchangeRateResponse, LocalizedLatestExchangeRate } from '@/models/exchange_rate.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
isDefined,
|
||||||
isObject,
|
isObject,
|
||||||
isString,
|
isString,
|
||||||
isNumber,
|
isNumber,
|
||||||
@@ -478,8 +479,12 @@ export function useI18n() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// public functions
|
// public functions
|
||||||
function translateIf(text: string, isTranslate: boolean): string {
|
function translateIf(text: string | undefined, isTranslate: boolean): string | undefined {
|
||||||
if (isTranslate) {
|
if (!isDefined(text)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text && isTranslate) {
|
||||||
return t(text);
|
return t(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user