use for-of statements to replace for and for-in

This commit is contained in:
MaysWind
2025-09-14 01:40:53 +08:00
parent 67bc81d3e2
commit 4700446ca0
38 changed files with 389 additions and 597 deletions
@@ -69,9 +69,7 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
let minUnixTimeClosingBalance = 0; let minUnixTimeClosingBalance = 0;
let maxUnixTimeClosingBalance = 0; let maxUnixTimeClosingBalance = 0;
for (let i = 0; i < props.items.length; i++) { for (const item of props.items) {
const item = props.items[i];
if (item.time < minUnixTime) { if (item.time < minUnixTime) {
minUnixTime = item.time; minUnixTime = item.time;
minUnixTimeOpeningBalance = item.accountOpeningBalance; minUnixTimeOpeningBalance = item.accountOpeningBalance;
@@ -120,8 +118,7 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
const dayDataItemsMap: Record<number, TransactionReconciliationStatementResponseItem[]> = {}; const dayDataItemsMap: Record<number, TransactionReconciliationStatementResponseItem[]> = {};
for (let i = 0; i < props.items.length; i++) { for (const dateItem of props.items) {
const dateItem = props.items[i];
let dateRangeMinUnixTime = 0; let dateRangeMinUnixTime = 0;
if (props.dateAggregationType === ChartDateAggregationType.Year.type) { if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
@@ -149,8 +146,7 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
let lastMedianBalance = lastClosingBalance; let lastMedianBalance = lastClosingBalance;
let lastAverageBalance = lastClosingBalance; let lastAverageBalance = lastClosingBalance;
for (let i = 0; i < allDateRanges.value.length; i++) { for (const dateRange of allDateRanges.value) {
const dateRange = allDateRanges.value[i];
const dataItems = dayDataItemsMap[dateRange.minUnixTime]; const dataItems = dayDataItemsMap[dateRange.minUnixTime];
let displayDate = ''; let displayDate = '';
@@ -176,11 +172,11 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
return data1.time - data2.time; return data1.time - data2.time;
}); });
const openingBalance = dataItems[0].accountOpeningBalance; const openingBalance = dataItems[0]!.accountOpeningBalance;
const closingBalance = dataItems[dataItems.length - 1].accountClosingBalance; const closingBalance = dataItems[dataItems.length - 1]!.accountClosingBalance;
const minimumBalance = Math.min(...dataItems.map(item => item.accountClosingBalance)); const minimumBalance = Math.min(...dataItems.map(item => item.accountClosingBalance));
const maximumBalance = Math.max(...dataItems.map(item => item.accountClosingBalance)); const maximumBalance = Math.max(...dataItems.map(item => item.accountClosingBalance));
const medianBalance = dataItems[Math.floor(dataItems.length / 2)].accountClosingBalance; const medianBalance = dataItems[Math.floor(dataItems.length / 2)]!.accountClosingBalance;
const averageBalance = Math.trunc(sumAmounts(dataItems.map(item => item.accountClosingBalance)) / dataItems.length); const averageBalance = Math.trunc(sumAmounts(dataItems.map(item => item.accountClosingBalance)) / dataItems.length);
if (props.account.isAsset) { if (props.account.isAsset) {
@@ -56,11 +56,11 @@ export function useDateRangeSelectionBase(props: CommonDateRangeSelectionProps)
const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek); const firstDayOfWeek = computed<WeekDayValue>(() => userStore.currentUserFirstDayOfWeek);
const beginDateTime = computed<string>(() => { const beginDateTime = computed<string>(() => {
const actualBeginUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[0]), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()); const actualBeginUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[0] as Date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return formatUnixTimeToLongDateTime(actualBeginUnixTime); return formatUnixTimeToLongDateTime(actualBeginUnixTime);
}); });
const endDateTime = computed<string>(() => { const endDateTime = computed<string>(() => {
const actualEndUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[1]), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes()); const actualEndUnixTime = getActualUnixTimeForStore(getUnixTimeFromLocalDatetime(dateRange.value[1] as Date), getTimezoneOffsetMinutes(), getBrowserTimezoneOffsetMinutes());
return formatUnixTimeToLongDateTime(actualEndUnixTime); return formatUnixTimeToLongDateTime(actualEndUnixTime);
}); });
const presetRanges = computed<PresetDateRange[]>(() => { const presetRanges = computed<PresetDateRange[]>(() => {
+8 -4
View File
@@ -42,11 +42,13 @@ export function useItemIconBase(props: CommonIconProps) {
iconId = iconId.toString(); iconId = iconId.toString();
} }
if (!ALL_ACCOUNT_ICONS[iconId]) { const iconInfo = ALL_ACCOUNT_ICONS[iconId];
if (!iconInfo) {
return DEFAULT_ACCOUNT_ICON.icon; return DEFAULT_ACCOUNT_ICON.icon;
} }
return ALL_ACCOUNT_ICONS[iconId].icon; return iconInfo.icon;
} }
function getCategoryIcon(iconId: string | number): string { function getCategoryIcon(iconId: string | number): string {
@@ -54,11 +56,13 @@ export function useItemIconBase(props: CommonIconProps) {
iconId = iconId.toString(); iconId = iconId.toString();
} }
if (!ALL_CATEGORY_ICONS[iconId]) { const iconInfo = ALL_CATEGORY_ICONS[iconId];
if (!iconInfo) {
return DEFAULT_CATEGORY_ICON.icon; return DEFAULT_CATEGORY_ICON.icon;
} }
return ALL_CATEGORY_ICONS[iconId].icon; return iconInfo.icon;
} }
function getAccountIconStyle(color?: ColorValue, defaultColor?: ColorStyleValue, additionalColorAttr?: string): Record<IconItemStyleName, IconItemStyleValue> { function getAccountIconStyle(color?: ColorValue, defaultColor?: ColorStyleValue, additionalColorAttr?: string): Record<IconItemStyleName, IconItemStyleValue> {
@@ -57,8 +57,8 @@ export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps
maxDate maxDate
]); ]);
const beginDateTime = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthFirstUnixTime(dateRange.value[0]))); const beginDateTime = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthFirstUnixTime(dateRange.value[0] as Year0BasedMonth)));
const endDateTime = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthLastUnixTime(dateRange.value[1]))); const endDateTime = computed<string>(() => formatUnixTimeToGregorianLikeLongYearMonth(getYearMonthLastUnixTime(dateRange.value[1] as Year0BasedMonth)));
function getFinalMonthRange(): { minYearMonth: TextualYearMonth | '', maxYearMonth: TextualYearMonth | '' } | null { function getFinalMonthRange(): { minYearMonth: TextualYearMonth | '', maxYearMonth: TextualYearMonth | '' } | null {
if (!dateRange.value[0] || !dateRange.value[1]) { if (!dateRange.value[0] || !dateRange.value[1]) {
@@ -69,8 +69,8 @@ export function useMonthRangeSelectionBase(props: CommonMonthRangeSelectionProps
throw new Error('Date is too early'); throw new Error('Date is too early');
} }
const minYearMonth = getYearMonthStringFromYear0BasedMonthObject(dateRange.value[0]); const minYearMonth = getYearMonthStringFromYear0BasedMonthObject(dateRange.value[0] as Year0BasedMonth);
const maxYearMonth = getYearMonthStringFromYear0BasedMonthObject(dateRange.value[1]); const maxYearMonth = getYearMonthStringFromYear0BasedMonthObject(dateRange.value[1] as Year0BasedMonth);
return { return {
minYearMonth, minYearMonth,
+1 -1
View File
@@ -146,7 +146,7 @@ function getDisplayYear(year: number): string {
function getDisplayMonth(month: number): string { function getDisplayMonth(month: number): string {
if (isArray(dateTime.value)) { if (isArray(dateTime.value)) {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value[0].getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value); return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value[0]!.getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value);
} else if (dateTime.value) { } else if (dateTime.value) {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value.getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value); return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value.getFullYear(), month + 1, 1).getUnixTime(), actualNumeralSystem.value);
} else { } else {
+1 -1
View File
@@ -102,7 +102,7 @@ function getDisplayYear(year: number): string {
function getDisplayMonth(month: number): string { function getDisplayMonth(month: number): string {
if (isArray(dateTime.value)) { if (isArray(dateTime.value)) {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value[0].year, month + 1, 1).getUnixTime()); return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value[0]!.year, month + 1, 1).getUnixTime());
} else { } else {
return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value.year, month + 1, 1).getUnixTime()); return getCalendarDisplayShortMonthFromUnixTime(getYearMonthDayDateTime(dateTime.value.year, month + 1, 1).getUnixTime());
} }
@@ -8,11 +8,15 @@ import { useTheme } from 'vuetify';
import type { CallbackDataParams } from 'echarts/types/dist/shared'; import type { CallbackDataParams } from 'echarts/types/dist/shared';
import { useI18n } from '@/locales/helpers.ts'; import { useI18n } from '@/locales/helpers.ts';
import { type CommonAccountBalanceTrendsChartProps, useAccountBalanceTrendsChartBase } from '@/components/base/AccountBalanceTrendsChartBase.ts' import {
type AccountBalanceTrendsChartItem,
type CommonAccountBalanceTrendsChartProps,
useAccountBalanceTrendsChartBase
} from '@/components/base/AccountBalanceTrendsChartBase.ts'
import { useUserStore } from '@/stores/user.ts'; import { useUserStore } from '@/stores/user.ts';
import type { NameValue } from '@/core/base.ts'; import { type NameValue, itemAndIndex } from '@/core/base.ts';
import { TextDirection } from '@/core/text.ts'; import { TextDirection } from '@/core/text.ts';
import type { ColorStyleValue } from '@/core/color.ts'; import type { ColorStyleValue } from '@/core/color.ts';
import { ThemeType } from '@/core/theme.ts'; import { ThemeType } from '@/core/theme.ts';
@@ -83,9 +87,7 @@ const allSeries = computed<AccountBalanceTrendsChartDataItem[]>(() => {
series.itemStyle.borderColor0 = expenseIncomeAmountColor.expenseAmountColor; series.itemStyle.borderColor0 = expenseIncomeAmountColor.expenseAmountColor;
} }
for (let i = 0; i < allDataItems.value.length; i++) { for (const item of allDataItems.value) {
const item = allDataItems.value[i];
if (props.type === AccountBalanceTrendChartType.Candlestick.type) { if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
series.data.push([ series.data.push([
item.openingBalance, item.openingBalance,
@@ -110,13 +112,12 @@ const yAxisWidth = computed<number>(() => {
return width; return width;
} }
for (let i = 0; i < allSeries.value.length; i++) { for (const series of allSeries.value) {
for (let j = 0; j < allSeries.value[i].data.length; j++) { for (const data of series.data) {
const data = allSeries.value[i].data[j];
let value: number; let value: number;
if (isArray(data)) { if (isArray(data)) {
value = data[1]; // for candlestick, use closing balance value = data[1] as number; // for candlestick, use closing balance
} else { } else {
value = data as number; // for line or bar chart value = data as number; // for line or bar chart
} }
@@ -172,8 +173,8 @@ const chartOptions = computed<object>(() => {
}, },
formatter: (params: CallbackDataParams[]) => { formatter: (params: CallbackDataParams[]) => {
if (props.type === AccountBalanceTrendChartType.Candlestick.type) { if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
const dataIndex = params[0].dataIndex; const dataIndex = params[0]!.dataIndex;
const dataItem = allDataItems.value[dataIndex]; const dataItem = allDataItems.value[dataIndex] as AccountBalanceTrendsChartItem;
const displayItems: NameValue[] = [ const displayItems: NameValue[] = [
{ {
name: tt('Opening Balance'), name: tt('Opening Balance'),
@@ -201,20 +202,20 @@ const chartOptions = computed<object>(() => {
} }
]; ];
let tooltip = `${params[0].name} ${props.legendName}<br/>`; let tooltip = `${params[0]!.name} ${props.legendName}<br/>`;
for (let i = 0; i < displayItems.length; i++) { for (const [displayItem, index] of itemAndIndex(displayItems)) {
tooltip += `<div><span class="chart-pointer" style="background-color: #${DEFAULT_CHART_COLORS[i]}"></span>` tooltip += `<div><span class="chart-pointer" style="background-color: #${DEFAULT_CHART_COLORS[index]}"></span>`
+ `<span>${displayItems[i].name}</span><span class="ms-5" style="float: inline-end">${displayItems[i].value}</span><br/>` + `<span>${displayItem.name}</span><span class="ms-5" style="float: inline-end">${displayItem.value}</span><br/>`
+ `</div>`; + `</div>`;
} }
return tooltip; return tooltip;
} else { } else {
const amount = params[0].data as number; const amount = params[0]!.data as number;
const value = formatAmountToLocalizedNumeralsWithCurrency(amount, props.account.currency); const value = formatAmountToLocalizedNumeralsWithCurrency(amount, props.account.currency);
return `${params[0].name}<br/>` return `${params[0]!.name}<br/>`
+ '<div><span class="chart-pointer" style="background-color: #' + DEFAULT_CHART_COLORS[0] + '"></span>' + '<div><span class="chart-pointer" style="background-color: #' + DEFAULT_CHART_COLORS[0] + '"></span>'
+ `<span>${props.legendName}</span><span class="ms-5" style="float: inline-end">${value}</span><br/>` + `<span>${props.legendName}</span><span class="ms-5" style="float: inline-end">${value}</span><br/>`
+ '</div>'; + '</div>';
+27 -33
View File
@@ -14,6 +14,7 @@ import { type CommonMonthlyTrendsChartProps, type MonthlyTrendsBarChartClickEven
import { useUserStore } from '@/stores/user.ts'; import { useUserStore } from '@/stores/user.ts';
import { itemAndIndex } from '@/core/base.ts';
import { TextDirection } from '@/core/text.ts'; import { TextDirection } from '@/core/text.ts';
import { type Year1BasedMonth, DateRangeScene } from '@/core/datetime.ts'; import { type Year1BasedMonth, DateRangeScene } from '@/core/datetime.ts';
import type { ColorStyleValue } from '@/core/color.ts'; import type { ColorStyleValue } from '@/core/color.ts';
@@ -100,8 +101,7 @@ const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType
const itemsMap = computed<Record<string, Record<string, unknown>>>(() => { const itemsMap = computed<Record<string, Record<string, unknown>>>(() => {
const map: Record<string, Record<string, unknown>> = {}; const map: Record<string, Record<string, unknown>> = {};
for (let i = 0; i < props.items.length; i++) { for (const item of props.items) {
const item = props.items[i];
let id: string = ''; let id: string = '';
if (props.idField && item[props.idField]) { if (props.idField && item[props.idField]) {
@@ -135,9 +135,7 @@ const itemsMap = computed<Record<string, Record<string, unknown>>>(() => {
const allDisplayDateRanges = computed<string[]>(() => { const allDisplayDateRanges = computed<string[]>(() => {
const allDisplayDateRanges: string[] = []; const allDisplayDateRanges: string[] = [];
for (let i = 0; i < allDateRanges.value.length; i++) { for (const dateRange of allDateRanges.value) {
const dateRange = allDateRanges.value[i];
if (props.dateAggregationType === ChartDateAggregationType.Year.type) { if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
allDisplayDateRanges.push(formatUnixTimeToGregorianLikeShortYear(dateRange.minUnixTime)); allDisplayDateRanges.push(formatUnixTimeToGregorianLikeShortYear(dateRange.minUnixTime));
} else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) { } else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) {
@@ -155,9 +153,7 @@ const allDisplayDateRanges = computed<string[]>(() => {
const allSeries = computed<MonthlyTrendsChartDataItem[]>(() => { const allSeries = computed<MonthlyTrendsChartDataItem[]>(() => {
const allSeries: MonthlyTrendsChartDataItem[] = []; const allSeries: MonthlyTrendsChartDataItem[] = [];
for (let i = 0; i < props.items.length; i++) { for (const [item, index] of itemAndIndex(props.items)) {
const item = props.items[i];
if (props.hiddenField && item[props.hiddenField]) { if (props.hiddenField && item[props.hiddenField]) {
continue; continue;
} }
@@ -165,8 +161,7 @@ const allSeries = computed<MonthlyTrendsChartDataItem[]>(() => {
const allAmounts: number[] = []; const allAmounts: number[] = [];
const dateRangeAmountMap: Record<string, YearMonthDataItem[]> = {}; const dateRangeAmountMap: Record<string, YearMonthDataItem[]> = {};
for (let j = 0; j < item.items.length; j++) { for (const dataItem of item.items) {
const dataItem = item.items[j];
let dateRangeKey = ''; let dateRangeKey = '';
if (props.dateAggregationType === ChartDateAggregationType.Year.type) { if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
@@ -189,8 +184,7 @@ const allSeries = computed<MonthlyTrendsChartDataItem[]>(() => {
dateRangeAmountMap[dateRangeKey] = dataItems; dateRangeAmountMap[dateRangeKey] = dataItems;
} }
for (let j = 0; j < allDateRanges.value.length; j++) { for (const dateRange of allDateRanges.value) {
const dateRange = allDateRanges.value[j];
let dateRangeKey = ''; let dateRangeKey = '';
if (props.dateAggregationType === ChartDateAggregationType.Year.type) { if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
@@ -207,9 +201,7 @@ const allSeries = computed<MonthlyTrendsChartDataItem[]>(() => {
const dataItems = dateRangeAmountMap[dateRangeKey]; const dataItems = dateRangeAmountMap[dateRangeKey];
if (isArray(dataItems)) { if (isArray(dataItems)) {
for (let i = 0; i < dataItems.length; i++) { for (const dataItem of dataItems) {
const dataItem = dataItems[i];
if (isNumber(dataItem[props.valueField])) { if (isNumber(dataItem[props.valueField])) {
amount += dataItem[props.valueField] as number; amount += dataItem[props.valueField] as number;
} }
@@ -223,7 +215,7 @@ const allSeries = computed<MonthlyTrendsChartDataItem[]>(() => {
id: (props.idField && item[props.idField]) ? item[props.idField] as string : getItemName(item[props.nameField] as string), id: (props.idField && item[props.idField]) ? item[props.idField] as string : getItemName(item[props.nameField] as string),
name: (props.idField && item[props.idField]) ? item[props.idField] as string : getItemName(item[props.nameField] as string), name: (props.idField && item[props.idField]) ? item[props.idField] as string : getItemName(item[props.nameField] as string),
itemStyle: { itemStyle: {
color: getDisplayColor(props.colorField && item[props.colorField] ? item[props.colorField] as string : DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length]), color: getDisplayColor(props.colorField && item[props.colorField] ? item[props.colorField] as string : DEFAULT_CHART_COLORS[index % DEFAULT_CHART_COLORS.length]),
}, },
selected: true, selected: true,
type: 'line', type: 'line',
@@ -253,10 +245,9 @@ const yAxisWidth = computed<number>(() => {
return width; return width;
} }
for (let i = 0; i < allSeries.value.length; i++) {
for (let j = 0; j < allSeries.value[i].data.length; j++) {
const value = allSeries.value[i].data[j];
for (const series of allSeries.value) {
for (const value of series.data) {
if (value > maxValue) { if (value > maxValue) {
maxValue = value; maxValue = value;
} }
@@ -311,12 +302,12 @@ const chartOptions = computed<object>(() => {
let totalAmount = 0; let totalAmount = 0;
const displayItems: MonthlyTrendsChartTooltipItem[] = []; const displayItems: MonthlyTrendsChartTooltipItem[] = [];
for (let i = 0; i < params.length; i++) { for (const param of params) {
const id = params[i].seriesId as string; const id = param.seriesId as string;
const name = itemsMap.value[id] && props.nameField && itemsMap.value[id][props.nameField] ? getItemName(itemsMap.value[id][props.nameField] as string) : id; const name = itemsMap.value[id] && props.nameField && itemsMap.value[id][props.nameField] ? getItemName(itemsMap.value[id][props.nameField] as string) : id;
const color = params[i].color; const color = param.color;
const displayOrders = itemsMap.value[id] && props.displayOrdersField && itemsMap.value[id][props.displayOrdersField] ? itemsMap.value[id][props.displayOrdersField] as number[] : [0]; const displayOrders = itemsMap.value[id] && props.displayOrdersField && itemsMap.value[id][props.displayOrdersField] ? itemsMap.value[id][props.displayOrdersField] as number[] : [0];
const amount = params[i].data as number; const amount = param.data as number;
displayItems.push({ displayItems.push({
name: name, name: name,
@@ -330,9 +321,7 @@ const chartOptions = computed<object>(() => {
sortStatisticsItems(displayItems, props.sortingType); sortStatisticsItems(displayItems, props.sortingType);
for (let i = 0; i < displayItems.length; i++) { for (const item of displayItems) {
const item = displayItems[i];
if (displayItems.length === 1 || item.totalAmount !== 0) { if (displayItems.length === 1 || item.totalAmount !== 0) {
const value = formatAmountToLocalizedNumeralsWithCurrency(item.totalAmount, props.defaultCurrency); const value = formatAmountToLocalizedNumeralsWithCurrency(item.totalAmount, props.defaultCurrency);
tooltip += '<div><span class="chart-pointer" style="background-color: ' + item.color + '"></span>'; tooltip += '<div><span class="chart-pointer" style="background-color: ' + item.color + '"></span>';
@@ -349,7 +338,7 @@ const chartOptions = computed<object>(() => {
+ '</div>' + tooltip; + '</div>' + tooltip;
} }
if (params.length && params[0].name) { if (params.length && params[0] && params[0].name) {
tooltip = `${params[0].name}<br/>` + tooltip; tooltip = `${params[0].name}<br/>` + tooltip;
} }
@@ -410,9 +399,14 @@ function clickItem(e: ECElementEvent): void {
} }
const id = e.seriesId as string; const id = e.seriesId as string;
const item = itemsMap.value[id]; const item = itemsMap.value[id] as Record<string, unknown>;
const itemId = props.idField ? item[props.idField] as string : ''; const itemId = props.idField ? item[props.idField] as string : '';
const dateRange = allDateRanges.value[e.dataIndex]; const dateRange = allDateRanges.value[e.dataIndex];
if (!dateRange) {
return;
}
let minUnixTime = dateRange.minUnixTime; let minUnixTime = dateRange.minUnixTime;
let maxUnixTime = dateRange.maxUnixTime; let maxUnixTime = dateRange.maxUnixTime;
@@ -450,16 +444,16 @@ function exportData(): { headers: string[], data: string[][] } {
headers.push(tt('Date')); headers.push(tt('Date'));
for (let i = 0; i < allSeries.value.length; i++) { for (const series of allSeries.value) {
const id = allSeries.value[i].id; const id = series.id;
const name = itemsMap.value[id] && props.nameField && itemsMap.value[id][props.nameField] ? getItemName(itemsMap.value[id][props.nameField] as string) : id; const name = itemsMap.value[id] && props.nameField && itemsMap.value[id][props.nameField] ? getItemName(itemsMap.value[id][props.nameField] as string) : id;
headers.push(name); headers.push(name);
} }
for (let i = 0; i < allDisplayDateRanges.value.length; i++) { for (const [displayDateRange, index] of itemAndIndex(allDisplayDateRanges.value)) {
const row: string[] = []; const row: string[] = [];
row.push(allDisplayDateRanges.value[i]); row.push(displayDateRange);
row.push(...allSeries.value.map(item => formatAmountToWesternArabicNumeralsWithoutDigitGrouping(item.data[i]))); row.push(...allSeries.value.map(item => formatAmountToWesternArabicNumeralsWithoutDigitGrouping(item.data[index] ?? 0)));
data.push(row); data.push(row);
} }
@@ -252,8 +252,8 @@ function getTimerPickerItemStyle(textualValue: string, textualCurrentValue: stri
return ''; return '';
} }
const minValue = parseInt(values[0].value); const minValue = parseInt(values[0]!.value);
const maxValue = parseInt(values[values.length - 1].value); const maxValue = parseInt(values[values.length - 1]!.value);
const value = parseInt(textualValue, 10); const value = parseInt(textualValue, 10);
const currentValue = parseInt(textualCurrentValue, 10); const currentValue = parseInt(textualCurrentValue, 10);
let valueDiff = value - currentValue; let valueDiff = value - currentValue;
@@ -327,7 +327,7 @@ function scrollToSelectedItem(itemsClass: string, itemClass: string, value: stri
} }
for (let i = 0; i < itemElements.length; i++) { for (let i = 0; i < itemElements.length; i++) {
const itemElement = itemElements[i]; const itemElement = itemElements[i] as HTMLElement;
if ('offsetHeight' in itemsElement && 'offsetTop' in itemElement && 'offsetHeight' in itemElement if ('offsetHeight' in itemsElement && 'offsetTop' in itemElement && 'offsetHeight' in itemElement
&& (!itemElement.hasAttribute('data-items-index') || itemElement.getAttribute('data-items-index') === '1') && (!itemElement.hasAttribute('data-items-index') || itemElement.getAttribute('data-items-index') === '1')
+15 -20
View File
@@ -95,6 +95,7 @@ import { type CommonMonthlyTrendsChartProps, type MonthlyTrendsBarChartClickEven
import { useUserStore } from '@/stores/user.ts'; import { useUserStore } from '@/stores/user.ts';
import { itemAndIndex } from '@/core/base.ts';
import { type Year1BasedMonth, type UnixTimeRange, DateRangeScene } from '@/core/datetime.ts'; import { type Year1BasedMonth, type UnixTimeRange, DateRangeScene } from '@/core/datetime.ts';
import type { ColorStyleValue } from '@/core/color.ts'; import type { ColorStyleValue } from '@/core/color.ts';
import { ChartDateAggregationType } from '@/core/statistics.ts'; import { ChartDateAggregationType } from '@/core/statistics.ts';
@@ -173,9 +174,7 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
const allDateRangeItemsMap: Record<string, MonthlyTrendsBarChartDataAmount[]> = {}; const allDateRangeItemsMap: Record<string, MonthlyTrendsBarChartDataAmount[]> = {};
const legends: TrendsBarChartLegend[] = []; const legends: TrendsBarChartLegend[] = [];
for (let i = 0; i < props.items.length; i++) { for (const [item, index] of itemAndIndex(props.items)) {
const item = props.items[i];
if (props.hiddenField && item[props.hiddenField]) { if (props.hiddenField && item[props.hiddenField]) {
continue; continue;
} }
@@ -185,7 +184,7 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
const legend: TrendsBarChartLegend = { const legend: TrendsBarChartLegend = {
id: id, id: id,
name: (props.nameField && item[props.nameField]) ? getItemName(item[props.nameField] as string) : id, name: (props.nameField && item[props.nameField]) ? getItemName(item[props.nameField] as string) : id,
color: getDisplayColor(props.colorField && item[props.colorField] ? item[props.colorField] as string : DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length]), color: getDisplayColor(props.colorField && item[props.colorField] ? item[props.colorField] as string : DEFAULT_CHART_COLORS[index % DEFAULT_CHART_COLORS.length]),
displayOrders: (props.displayOrdersField && item[props.displayOrdersField]) ? item[props.displayOrdersField] as number[] : [0] displayOrders: (props.displayOrdersField && item[props.displayOrdersField]) ? item[props.displayOrdersField] as number[] : [0]
}; };
@@ -197,8 +196,7 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
const dateRangeItemMap: Record<string, MonthlyTrendsBarChartDataAmount> = {}; const dateRangeItemMap: Record<string, MonthlyTrendsBarChartDataAmount> = {};
for (let j = 0; j < item.items.length; j++) { for (const dataItem of item.items) {
const dataItem = item.items[j];
let dateRangeKey = ''; let dateRangeKey = '';
if (props.dateAggregationType === ChartDateAggregationType.Year.type) { if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
@@ -216,7 +214,7 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
} }
if (dateRangeItemMap[dateRangeKey]) { if (dateRangeItemMap[dateRangeKey]) {
dateRangeItemMap[dateRangeKey].totalAmount += (props.valueField && isNumber(dataItem[props.valueField])) ? dataItem[props.valueField] as number : 0; dateRangeItemMap[dateRangeKey]!.totalAmount += (props.valueField && isNumber(dataItem[props.valueField])) ? dataItem[props.valueField] as number : 0;
} else { } else {
const allDataItems: MonthlyTrendsBarChartDataAmount[] = allDateRangeItemsMap[dateRangeKey] || []; const allDataItems: MonthlyTrendsBarChartDataAmount[] = allDateRangeItemsMap[dateRangeKey] || [];
const finalDataItem: MonthlyTrendsBarChartDataAmount = Object.assign({}, legend, { const finalDataItem: MonthlyTrendsBarChartDataAmount = Object.assign({}, legend, {
@@ -233,8 +231,7 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
const finalDataItems: MonthlyTrendsBarChartDataItem[] = []; const finalDataItems: MonthlyTrendsBarChartDataItem[] = [];
let maxTotalAmount = 0; let maxTotalAmount = 0;
for (let i = 0; i < allDateRanges.value.length; i++) { for (const dateRange of allDateRanges.value) {
const dateRange = allDateRanges.value[i];
let dateRangeKey = ''; let dateRangeKey = '';
if (props.dateAggregationType === ChartDateAggregationType.Year.type) { if (props.dateAggregationType === ChartDateAggregationType.Year.type) {
@@ -265,12 +262,12 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
sortStatisticsItems(dataItems, props.sortingType); sortStatisticsItems(dataItems, props.sortingType);
for (let j = 0; j < dataItems.length; j++) { for (const dataItem of dataItems) {
if (dataItems[j].totalAmount > 0) { if (dataItem.totalAmount > 0) {
totalPositiveAmount += dataItems[j].totalAmount; totalPositiveAmount += dataItem.totalAmount;
} }
totalAmount += dataItems[j].totalAmount; totalAmount += dataItem.totalAmount;
} }
if (totalAmount > maxTotalAmount) { if (totalAmount > maxTotalAmount) {
@@ -289,11 +286,11 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
finalDataItems.push(finalDataItem); finalDataItems.push(finalDataItem);
} }
for (let i = 0; i < finalDataItems.length; i++) { for (const finalDataItem of finalDataItems) {
if (maxTotalAmount > 0 && finalDataItems[i].totalAmount > 0) { if (maxTotalAmount > 0 && finalDataItem.totalAmount > 0) {
finalDataItems[i].percent = 100.0 * finalDataItems[i].totalAmount / maxTotalAmount; finalDataItem.percent = 100.0 * finalDataItem.totalAmount / maxTotalAmount;
} else { } else {
finalDataItems[i].percent = 0.0; finalDataItem.percent = 0.0;
} }
} }
@@ -306,9 +303,7 @@ const allDisplayDataItems = computed<MonthlyTrendsBarChartData>(() => {
function clickItem(item: MonthlyTrendsBarChartDataItem): void { function clickItem(item: MonthlyTrendsBarChartDataItem): void {
let itemId = ''; let itemId = '';
for (let i = 0; i < props.items.length; i++) { for (const item of props.items) {
const item = props.items[i];
if (!props.hiddenField || item[props.hiddenField]) { if (!props.hiddenField || item[props.hiddenField]) {
continue; continue;
} }
@@ -143,8 +143,8 @@ const allTags = computed<TransactionTag[]>(() => {
const noAvailableTag = computed<boolean>(() => { const noAvailableTag = computed<boolean>(() => {
if (transactionTagsStore.allTransactionTags) { if (transactionTagsStore.allTransactionTags) {
for (let i = 0; i < transactionTagsStore.allTransactionTags.length; i++) { for (const transactionTag of transactionTagsStore.allTransactionTags) {
if (!transactionTagsStore.allTransactionTags[i].hidden) { if (!transactionTag.hidden) {
return false; return false;
} }
} }
+37 -67
View File
@@ -1,3 +1,4 @@
import { itemAndIndex, keys, keysIfValueEquals, values } from '@/core/base.ts';
import { AccountType, AccountCategory } from '@/core/account.ts'; import { AccountType, AccountCategory } from '@/core/account.ts';
import { PARENT_ACCOUNT_CURRENCY_PLACEHOLDER } from '@/consts/currency.ts'; import { PARENT_ACCOUNT_CURRENCY_PLACEHOLDER } from '@/consts/currency.ts';
import { type AccountBalance, type CategorizedAccount, type AccountCategoriesWithVisibleCount, Account } from '@/models/account.ts'; import { type AccountBalance, type CategorizedAccount, type AccountCategoriesWithVisibleCount, Account } from '@/models/account.ts';
@@ -5,9 +6,7 @@ import { type AccountBalance, type CategorizedAccount, type AccountCategoriesWit
export function getCategorizedAccountsMap(allAccounts: Account[]): Record<number, CategorizedAccount> { export function getCategorizedAccountsMap(allAccounts: Account[]): Record<number, CategorizedAccount> {
const ret: Record<number, CategorizedAccount> = {}; const ret: Record<number, CategorizedAccount> = {};
for (let i = 0; i < allAccounts.length; i++) { for (const account of allAccounts) {
const account = allAccounts[i];
if (!ret[account.category]) { if (!ret[account.category]) {
const categoryInfo = AccountCategory.valueOf(account.category); const categoryInfo = AccountCategory.valueOf(account.category);
@@ -21,8 +20,10 @@ export function getCategorizedAccountsMap(allAccounts: Account[]): Record<number
} }
} }
if (ret[account.category]) { const categorizedAccount = ret[account.category];
const accountList = ret[account.category].accounts;
if (categorizedAccount) {
const accountList = categorizedAccount.accounts;
accountList.push(account); accountList.push(account);
} }
} }
@@ -35,15 +36,16 @@ export function getCategorizedAccounts(allAccounts: Account[]): CategorizedAccou
const allCategories = AccountCategory.values(); const allCategories = AccountCategory.values();
const categorizedAccounts = getCategorizedAccountsMap(allAccounts); const categorizedAccounts = getCategorizedAccountsMap(allAccounts);
for (let i = 0; i < allCategories.length; i++) { for (const category of allCategories) {
const category = allCategories[i];
if (!categorizedAccounts[category.type]) { if (!categorizedAccounts[category.type]) {
continue; continue;
} }
const accountCategory = categorizedAccounts[category.type]; const accountCategory = categorizedAccounts[category.type];
ret.push(accountCategory);
if (accountCategory) {
ret.push(accountCategory);
}
} }
return ret; return ret;
@@ -56,14 +58,11 @@ export function getAccountMapByName(allAccounts: Account[]): Record<string, Acco
return ret; return ret;
} }
for (let i = 0; i < allAccounts.length; i++) { for (const account of allAccounts) {
const account = allAccounts[i];
if (account.type === AccountType.SingleAccount.type) { if (account.type === AccountType.SingleAccount.type) {
ret[account.name] = account; ret[account.name] = account;
} else if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) { } else if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) {
for (let j = 0; j < account.subAccounts.length; j++) { for (const subAccount of account.subAccounts) {
const subAccount = account.subAccounts[j];
ret[subAccount.name] = subAccount; ret[subAccount.name] = subAccount;
} }
} }
@@ -76,28 +75,26 @@ export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap: R
const ret: AccountCategoriesWithVisibleCount[] = []; const ret: AccountCategoriesWithVisibleCount[] = [];
const allCategories = AccountCategory.values(); const allCategories = AccountCategory.values();
for (let i = 0; i < allCategories.length; i++) { for (const accountCategory of allCategories) {
const accountCategory = allCategories[i]; const categorizedAccount = categorizedAccountsMap[accountCategory.type];
if (!categorizedAccountsMap[accountCategory.type] || !categorizedAccountsMap[accountCategory.type].accounts) { if (!categorizedAccount || !categorizedAccount.accounts) {
continue; continue;
} }
const allAccounts = categorizedAccountsMap[accountCategory.type].accounts; const allAccounts = categorizedAccount.accounts;
const allSubAccounts: Record<string, Account[]> = {}; const allSubAccounts: Record<string, Account[]> = {};
const allVisibleSubAccountCounts: Record<string, number> = {}; const allVisibleSubAccountCounts: Record<string, number> = {};
const allFirstVisibleSubAccountIndexes: Record<string, number> = {}; const allFirstVisibleSubAccountIndexes: Record<string, number> = {};
let allVisibleAccountCount = 0; let allVisibleAccountCount = 0;
let firstVisibleAccountIndex = -1; let firstVisibleAccountIndex = -1;
for (let j = 0; j < allAccounts.length; j++) { for (const [account, accountIndex] of itemAndIndex(allAccounts)) {
const account = allAccounts[j];
if (!account.hidden) { if (!account.hidden) {
allVisibleAccountCount++; allVisibleAccountCount++;
if (firstVisibleAccountIndex === -1) { if (firstVisibleAccountIndex === -1) {
firstVisibleAccountIndex = j; firstVisibleAccountIndex = accountIndex;
} }
} }
@@ -105,14 +102,12 @@ export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap: R
let visibleSubAccountCount = 0; let visibleSubAccountCount = 0;
let firstVisibleSubAccountIndex = -1; let firstVisibleSubAccountIndex = -1;
for (let k = 0; k < account.subAccounts.length; k++) { for (const [subAccount, subAccountIndex] of itemAndIndex(account.subAccounts)) {
const subAccount = account.subAccounts[k];
if (!subAccount.hidden) { if (!subAccount.hidden) {
visibleSubAccountCount++; visibleSubAccountCount++;
if (firstVisibleSubAccountIndex === -1) { if (firstVisibleSubAccountIndex === -1) {
firstVisibleSubAccountIndex = k; firstVisibleSubAccountIndex = subAccountIndex;
} }
} }
} }
@@ -147,16 +142,14 @@ export function getAllFilteredAccountsBalance(categorizedAccounts: Record<number
const allAccountCategories = AccountCategory.values(); const allAccountCategories = AccountCategory.values();
const ret: AccountBalance[] = []; const ret: AccountBalance[] = [];
for (let categoryIdx = 0; categoryIdx < allAccountCategories.length; categoryIdx++) { for (const accountCategory of allAccountCategories) {
const accountCategory = allAccountCategories[categoryIdx]; const categorizedAccount = categorizedAccounts[accountCategory.type];
if (!categorizedAccounts[accountCategory.type] || !categorizedAccounts[accountCategory.type].accounts) { if (!categorizedAccount || !categorizedAccount.accounts) {
continue; continue;
} }
for (let accountIdx = 0; accountIdx < categorizedAccounts[accountCategory.type].accounts.length; accountIdx++) { for (const account of categorizedAccount.accounts) {
const account = categorizedAccounts[accountCategory.type].accounts[accountIdx];
if (account.hidden || !accountFilter(account)) { if (account.hidden || !accountFilter(account)) {
continue; continue;
} }
@@ -169,9 +162,7 @@ export function getAllFilteredAccountsBalance(categorizedAccounts: Record<number
currency: account.currency currency: account.currency
}); });
} else if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) { } else if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) {
for (let subAccountIdx = 0; subAccountIdx < account.subAccounts.length; subAccountIdx++) { for (const subAccount of account.subAccounts) {
const subAccount = account.subAccounts[subAccountIdx];
if (subAccount.hidden || !accountFilter(subAccount)) { if (subAccount.hidden || !accountFilter(subAccount)) {
continue; continue;
} }
@@ -197,13 +188,7 @@ export function getFinalAccountIdsByFilteredAccountIds(allAccountsMap: Record<st
return finalAccountIds; return finalAccountIds;
} }
for (const accountId in allAccountsMap) { for (const account of values(allAccountsMap)) {
if (!Object.prototype.hasOwnProperty.call(allAccountsMap, accountId)) {
continue;
}
const account = allAccountsMap[accountId];
if (filteredAccountIds && !isAccountOrSubAccountsAllChecked(account, filteredAccountIds)) { if (filteredAccountIds && !isAccountOrSubAccountsAllChecked(account, filteredAccountIds)) {
continue; continue;
} }
@@ -225,13 +210,13 @@ export function getUnifiedSelectedAccountsCurrencyOrDefaultCurrency(allAccountsM
let accountCurrency = ''; let accountCurrency = '';
for (const accountId in selectedAccountIds) { for (const accountId of keysIfValueEquals(selectedAccountIds, true)) {
if (!Object.prototype.hasOwnProperty.call(selectedAccountIds, accountId)) { const account = allAccountsMap[accountId];
if (!account) {
continue; continue;
} }
const account = allAccountsMap[accountId];
if (account.currency === PARENT_ACCOUNT_CURRENCY_PLACEHOLDER) { if (account.currency === PARENT_ACCOUNT_CURRENCY_PLACEHOLDER) {
continue; continue;
} }
@@ -258,19 +243,14 @@ export function selectAccountOrSubAccounts(filterAccountIds: Record<string, bool
return; return;
} }
for (let i = 0; i < account.subAccounts.length; i++) { for (const subAccount of account.subAccounts) {
const subAccount = account.subAccounts[i];
filterAccountIds[subAccount.id] = value; filterAccountIds[subAccount.id] = value;
} }
} }
} }
export function selectAll(filterAccountIds: Record<string, boolean>, allAccountsMap: Record<string, Account>, skipHiddenAccount: boolean): void { export function selectAll(filterAccountIds: Record<string, boolean>, allAccountsMap: Record<string, Account>, skipHiddenAccount: boolean): void {
for (const accountId in filterAccountIds) { for (const accountId of keys(filterAccountIds)) {
if (!Object.prototype.hasOwnProperty.call(filterAccountIds, accountId)) {
continue;
}
const account = allAccountsMap[accountId]; const account = allAccountsMap[accountId];
if (skipHiddenAccount && account && account.hidden) { if (skipHiddenAccount && account && account.hidden) {
@@ -284,11 +264,7 @@ export function selectAll(filterAccountIds: Record<string, boolean>, allAccounts
} }
export function selectNone(filterAccountIds: Record<string, boolean>, allAccountsMap: Record<string, Account>, skipHiddenAccount: boolean): void { export function selectNone(filterAccountIds: Record<string, boolean>, allAccountsMap: Record<string, Account>, skipHiddenAccount: boolean): void {
for (const accountId in filterAccountIds) { for (const accountId of keys(filterAccountIds)) {
if (!Object.prototype.hasOwnProperty.call(filterAccountIds, accountId)) {
continue;
}
const account = allAccountsMap[accountId]; const account = allAccountsMap[accountId];
if (skipHiddenAccount && account && account.hidden) { if (skipHiddenAccount && account && account.hidden) {
@@ -302,11 +278,7 @@ export function selectNone(filterAccountIds: Record<string, boolean>, allAccount
} }
export function selectInvert(filterAccountIds: Record<string, boolean>, allAccountsMap: Record<string, Account>, skipHiddenAccount: boolean): void { export function selectInvert(filterAccountIds: Record<string, boolean>, allAccountsMap: Record<string, Account>, skipHiddenAccount: boolean): void {
for (const accountId in filterAccountIds) { for (const accountId of keys(filterAccountIds)) {
if (!Object.prototype.hasOwnProperty.call(filterAccountIds, accountId)) {
continue;
}
const account = allAccountsMap[accountId]; const account = allAccountsMap[accountId];
if (skipHiddenAccount && account && account.hidden) { if (skipHiddenAccount && account && account.hidden) {
@@ -324,8 +296,7 @@ export function isAccountOrSubAccountsAllChecked(account: Account, filterAccount
return !filterAccountIds[account.id]; return !filterAccountIds[account.id];
} }
for (let i = 0; i < account.subAccounts.length; i++) { for (const subAccount of account.subAccounts) {
const subAccount = account.subAccounts[i];
if (filterAccountIds[subAccount.id]) { if (filterAccountIds[subAccount.id]) {
return false; return false;
} }
@@ -341,8 +312,7 @@ export function isAccountOrSubAccountsHasButNotAllChecked(account: Account, filt
let checkedCount = 0; let checkedCount = 0;
for (let i = 0; i < account.subAccounts.length; i++) { for (const subAccount of account.subAccounts) {
const subAccount = account.subAccounts[i];
if (!filterAccountIds[subAccount.id]) { if (!filterAccountIds[subAccount.id]) {
checkedCount++; checkedCount++;
} }
+2 -2
View File
@@ -20,8 +20,8 @@ export function getColorsInRows(allColorValues: ColorValue[], itemPerRow: number
ret[++rowCount] = []; ret[++rowCount] = [];
} }
ret[rowCount].push({ ret[rowCount]!.push({
color: allColorValues[i] color: allColorValues[i] as ColorValue
}); });
} }
+13 -8
View File
@@ -4,12 +4,15 @@ import { replaceAll } from './common.ts';
import logger from './logger.ts'; import logger from './logger.ts';
type Operator = '+' | '-' | '*' | '/';
type OperatorAndParenthesis = Operator | '(' | ')';
const maxAllowedDecimalCount = 6; const maxAllowedDecimalCount = 6;
const normalizeFactor: number = 1000000; const normalizeFactor: number = 1000000;
const normalizedDecimalsMaxZeroString: string = '000000'; const normalizedDecimalsMaxZeroString: string = '000000';
const normalizedNumberToAmountFactor: number = 10000; // 1000000 / 100 const normalizedNumberToAmountFactor: number = 10000; // 1000000 / 100
const operatorPriority: Record<string, number> = { const operatorPriority: Record<Operator, number> = {
'+': 1, '+': 1,
'-': 1, '-': 1,
'*': 2, '*': 2,
@@ -48,20 +51,20 @@ function checkNumberRange(num: number): void {
function toPostfixExprTokens(expr: string): string[] | null { function toPostfixExprTokens(expr: string): string[] | null {
const finalTokens: string[] = []; const finalTokens: string[] = [];
const operatorStack: string[] = []; const operatorStack: OperatorAndParenthesis[] = [];
let currentNumberBuilder = ''; let currentNumberBuilder = '';
let isLastTokenOperator = true; let isLastTokenOperator = true;
expr = replaceAll(expr, ' ', ''); expr = replaceAll(expr, ' ', '');
for (let i = 0; i < expr.length; i++) { for (let i = 0; i < expr.length; i++) {
const ch = expr[i]; const ch = expr[i] as string;
// number // number
if ('0' <= ch && ch <= '9' || ch === '.') { if ('0' <= ch && ch <= '9' || ch === '.') {
currentNumberBuilder += ch; currentNumberBuilder += ch;
continue continue
} else if (ch === '-' && i + 1 < expr.length && '0' <= expr[i + 1] && expr[i + 1] <= '9' && currentNumberBuilder.length === 0 && isLastTokenOperator) { } else if (ch === '-' && i + 1 < expr.length && '0' <= (expr[i + 1] as string) && (expr[i + 1] as string) <= '9' && currentNumberBuilder.length === 0 && isLastTokenOperator) {
currentNumberBuilder += ch; currentNumberBuilder += ch;
continue continue
} }
@@ -84,13 +87,15 @@ function toPostfixExprTokens(expr: string): string[] | null {
} }
while (operatorStack.length > 0) { while (operatorStack.length > 0) {
const topOperator = operatorStack[operatorStack.length - 1]; const topOperator = operatorStack[operatorStack.length - 1] as OperatorAndParenthesis;
if (topOperator === '(') { if (topOperator === '(') {
break; break;
} }
if (operatorPriority[topOperator] >= operatorPriority[ch]) { const isCurrentOperator = topOperator === '+' || topOperator === '-' || topOperator === '*' || topOperator === '/';
if (isCurrentOperator && operatorPriority[topOperator] >= operatorPriority[ch]) {
finalTokens.push(topOperator); finalTokens.push(topOperator);
operatorStack.pop(); operatorStack.pop();
} else { } else {
@@ -154,7 +159,7 @@ function evaluatePostfixExpr(tokens: string[]): number | null {
const stack: number[] = []; const stack: number[] = [];
for (let i = 0; i < tokens.length; i++) { for (let i = 0; i < tokens.length; i++) {
const token = tokens[i]; const token = tokens[i] as string;
switch (token) { switch (token) {
case '+': case '+':
@@ -211,7 +216,7 @@ function evaluatePostfixExpr(tokens: string[]): number | null {
return null; return null;
} }
return stack[0]; return stack[0] as number;
} }
export function evaluateExpressionToAmount(expr: string): number | undefined { export function evaluateExpressionToAmount(expr: string): number | undefined {
if (!expr) { if (!expr) {
+3 -3
View File
@@ -13,8 +13,8 @@ import { isDefined, isString, isNumber, replaceAll, removeAll } from './common.t
export function sumAmounts(amounts: number[]): number { export function sumAmounts(amounts: number[]): number {
let sum = 0; let sum = 0;
for (let i = 0; i < amounts.length; i++) { for (const amount of amounts) {
sum += amounts[i]; sum += amount;
} }
return sum; return sum;
@@ -292,7 +292,7 @@ export function formatExchangeRateAmount(exchangeRateAmount: number, options: Nu
} }
} }
export function getAdaptiveDisplayAmountRate(amount1: number, amount2: number, fromExchangeRate: { rate: string }, toExchangeRate: { rate: string }, options: NumberFormatOptions): string | null { export function getAdaptiveDisplayAmountRate(amount1: number, amount2: number, options: NumberFormatOptions, fromExchangeRate?: { rate: string }, toExchangeRate?: { rate: string }): string | null {
const numeralSystem = options.numeralSystem || NumeralSystem.Default; const numeralSystem = options.numeralSystem || NumeralSystem.Default;
if (!amount1 || !amount2 || amount1 === amount2) { if (!amount1 || !amount2 || amount1 === amount2) {
+3 -5
View File
@@ -1,3 +1,5 @@
import { keys } from '@/core/base.ts';
import type { import type {
ApplicationSettingKey, ApplicationSettingKey,
ApplicationSettingValue, ApplicationSettingValue,
@@ -28,11 +30,7 @@ function getStoredApplicationSettings(): BaseApplicationSetting {
export function getApplicationSettings(): ApplicationSettings { export function getApplicationSettings(): ApplicationSettings {
const storedApplicationSettings = getStoredApplicationSettings(); const storedApplicationSettings = getStoredApplicationSettings();
for (const key in storedApplicationSettings) { for (const key of keys(storedApplicationSettings)) {
if (!Object.prototype.hasOwnProperty.call(storedApplicationSettings, key)) {
continue;
}
if (typeof(DEFAULT_APPLICATION_SETTINGS[key]) === 'object') { if (typeof(DEFAULT_APPLICATION_SETTINGS[key]) === 'object') {
storedApplicationSettings[key] = Object.assign({}, DEFAULT_APPLICATION_SETTINGS[key], storedApplicationSettings[key]); storedApplicationSettings[key] = Object.assign({}, DEFAULT_APPLICATION_SETTINGS[key], storedApplicationSettings[key]);
} }
+11 -10
View File
@@ -1,8 +1,9 @@
import { reversed } from '@/core/base.ts';
import { TransactionTag } from '@/models/transaction_tag.ts'; import { TransactionTag } from '@/models/transaction_tag.ts';
export function isNoAvailableTag(tags: TransactionTag[], showHidden: boolean): boolean { export function isNoAvailableTag(tags: TransactionTag[], showHidden: boolean): boolean {
for (let i = 0; i < tags.length; i++) { for (const tag of tags) {
if (showHidden || !tags[i].hidden) { if (showHidden || !tag.hidden) {
return false; return false;
} }
} }
@@ -13,8 +14,8 @@ export function isNoAvailableTag(tags: TransactionTag[], showHidden: boolean): b
export function getAvailableTagCount(tags: TransactionTag[], showHidden: boolean): number { export function getAvailableTagCount(tags: TransactionTag[], showHidden: boolean): number {
let count = 0; let count = 0;
for (let i = 0; i < tags.length; i++) { for (const tag of tags) {
if (showHidden || !tags[i].hidden) { if (showHidden || !tag.hidden) {
count++; count++;
} }
} }
@@ -23,9 +24,9 @@ export function getAvailableTagCount(tags: TransactionTag[], showHidden: boolean
} }
export function getFirstShowingId(tags: TransactionTag[], showHidden: boolean): string | null { export function getFirstShowingId(tags: TransactionTag[], showHidden: boolean): string | null {
for (let i = 0; i < tags.length; i++) { for (const tag of tags) {
if (showHidden || !tags[i].hidden) { if (showHidden || !tag.hidden) {
return tags[i].id; return tag.id;
} }
} }
@@ -33,9 +34,9 @@ export function getFirstShowingId(tags: TransactionTag[], showHidden: boolean):
} }
export function getLastShowingId(tags: TransactionTag[], showHidden: boolean): string | null { export function getLastShowingId(tags: TransactionTag[], showHidden: boolean): string | null {
for (let i = tags.length - 1; i >= 0; i--) { for (const tag of reversed(tags)) {
if (showHidden || !tags[i].hidden) { if (showHidden || !tag.hidden) {
return tags[i].id; return tag.id;
} }
} }
+11 -10
View File
@@ -1,8 +1,9 @@
import { reversed } from '@/core/base.ts';
import { TransactionTemplate } from '@/models/transaction_template.ts'; import { TransactionTemplate } from '@/models/transaction_template.ts';
export function isNoAvailableTemplate(templates: TransactionTemplate[], showHidden: boolean): boolean { export function isNoAvailableTemplate(templates: TransactionTemplate[], showHidden: boolean): boolean {
for (let i = 0; i < templates.length; i++) { for (const template of templates) {
if (showHidden || !templates[i].hidden) { if (showHidden || !template.hidden) {
return false; return false;
} }
} }
@@ -13,8 +14,8 @@ export function isNoAvailableTemplate(templates: TransactionTemplate[], showHidd
export function getAvailableTemplateCount(templates: TransactionTemplate[], showHidden: boolean): number { export function getAvailableTemplateCount(templates: TransactionTemplate[], showHidden: boolean): number {
let count = 0; let count = 0;
for (let i = 0; i < templates.length; i++) { for (const template of templates) {
if (showHidden || !templates[i].hidden) { if (showHidden || !template.hidden) {
count++; count++;
} }
} }
@@ -23,9 +24,9 @@ export function getAvailableTemplateCount(templates: TransactionTemplate[], show
} }
export function getFirstShowingId(templates: TransactionTemplate[], showHidden: boolean): string | null { export function getFirstShowingId(templates: TransactionTemplate[], showHidden: boolean): string | null {
for (let i = 0; i < templates.length; i++) { for (const template of templates) {
if (showHidden || !templates[i].hidden) { if (showHidden || !template.hidden) {
return templates[i].id; return template.id;
} }
} }
@@ -33,9 +34,9 @@ export function getFirstShowingId(templates: TransactionTemplate[], showHidden:
} }
export function getLastShowingId(templates: TransactionTemplate[], showHidden: boolean): string | null { export function getLastShowingId(templates: TransactionTemplate[], showHidden: boolean): string | null {
for (let i = templates.length - 1; i >= 0; i--) { for (const template of reversed(templates)) {
if (showHidden || !templates[i].hidden) { if (showHidden || !template.hidden) {
return templates[i].id; return template.id;
} }
} }
+6 -7
View File
@@ -39,7 +39,7 @@ export function setTransactionModelByTransaction(transaction: Transaction, trans
} }
if (!options.type && options.categoryId && options.categoryId !== '0' && allCategoriesMap[options.categoryId]) { if (!options.type && options.categoryId && options.categoryId !== '0' && allCategoriesMap[options.categoryId]) {
const category = allCategoriesMap[options.categoryId]; const category = allCategoriesMap[options.categoryId] as TransactionCategory;
const type = categoryTypeToTransactionType(category.type); const type = categoryTypeToTransactionType(category.type);
if (isNumber(type)) { if (isNumber(type)) {
@@ -102,8 +102,8 @@ export function setTransactionModelByTransaction(transaction: Transaction, trans
if (allVisibleAccounts.length) { if (allVisibleAccounts.length) {
if (options.accountId && options.accountId !== '0') { if (options.accountId && options.accountId !== '0') {
for (let i = 0; i < allVisibleAccounts.length; i++) { for (const account of allVisibleAccounts) {
if (allVisibleAccounts[i].id === options.accountId) { if (account.id === options.accountId) {
transaction.sourceAccountId = options.accountId; transaction.sourceAccountId = options.accountId;
transaction.destinationAccountId = options.accountId; transaction.destinationAccountId = options.accountId;
break; break;
@@ -115,7 +115,7 @@ export function setTransactionModelByTransaction(transaction: Transaction, trans
if (defaultAccountId && allAccountsMap[defaultAccountId] && !allAccountsMap[defaultAccountId].hidden) { if (defaultAccountId && allAccountsMap[defaultAccountId] && !allAccountsMap[defaultAccountId].hidden) {
transaction.sourceAccountId = defaultAccountId; transaction.sourceAccountId = defaultAccountId;
} else { } else {
transaction.sourceAccountId = allVisibleAccounts[0].id; transaction.sourceAccountId = allVisibleAccounts[0]!.id;
} }
} }
@@ -123,7 +123,7 @@ export function setTransactionModelByTransaction(transaction: Transaction, trans
if (defaultAccountId && allAccountsMap[defaultAccountId] && !allAccountsMap[defaultAccountId].hidden) { if (defaultAccountId && allAccountsMap[defaultAccountId] && !allAccountsMap[defaultAccountId].hidden) {
transaction.destinationAccountId = defaultAccountId; transaction.destinationAccountId = defaultAccountId;
} else { } else {
transaction.destinationAccountId = allVisibleAccounts[0].id; transaction.destinationAccountId = allVisibleAccounts[0]!.id;
} }
} }
} }
@@ -132,8 +132,7 @@ export function setTransactionModelByTransaction(transaction: Transaction, trans
const tagIds = options.tagIds.split(','); const tagIds = options.tagIds.split(',');
const finalTagIds = []; const finalTagIds = [];
for (let i = 0; i < tagIds.length; i++) { for (const tagId of tagIds) {
const tagId = tagIds[i];
const tag = allTagsMap[tagId]; const tag = allTagsMap[tagId];
if (tag && !tag.hidden) { if (tag && !tag.hidden) {
+87 -163
View File
@@ -21,6 +21,11 @@ import {
DEFAULT_CONTENT as PERSIAN_CALENDAR_DEFAULT_CONTENT DEFAULT_CONTENT as PERSIAN_CALENDAR_DEFAULT_CONTENT
} from '@/locales/calendar/persian/index.ts'; } from '@/locales/calendar/persian/index.ts';
import {
entries,
keys
} from '@/core/base.ts';
import { import {
TextDirection TextDirection
} from '@/core/text.ts'; } from '@/core/text.ts';
@@ -257,12 +262,7 @@ export function getI18nOptions(): object {
messages: (function () { messages: (function () {
const messages: Record<string, object> = {}; const messages: Record<string, object> = {};
for (const languageKey in ALL_LANGUAGES) { for (const [languageKey, languageInfo] of entries(ALL_LANGUAGES)) {
if (!Object.prototype.hasOwnProperty.call(ALL_LANGUAGES, languageKey)) {
continue;
}
const languageInfo = ALL_LANGUAGES[languageKey];
messages[languageKey] = languageInfo.content; messages[languageKey] = languageInfo.content;
} }
@@ -274,13 +274,7 @@ export function getI18nOptions(): object {
export function getRtlLocales(): Record<string, boolean> { export function getRtlLocales(): Record<string, boolean> {
const rtlLocales: Record<string, boolean> = {}; const rtlLocales: Record<string, boolean> = {};
for (const languageKey in ALL_LANGUAGES) { for (const [languageKey, languageInfo] of entries(ALL_LANGUAGES)) {
if (!Object.prototype.hasOwnProperty.call(ALL_LANGUAGES, languageKey)) {
continue;
}
const languageInfo = ALL_LANGUAGES[languageKey];
if (languageInfo.textDirection === 'rtl') { if (languageInfo.textDirection === 'rtl') {
rtlLocales[languageKey] = true; rtlLocales[languageKey] = true;
} }
@@ -346,7 +340,7 @@ export function useI18n() {
// fallback to use marco language tag // fallback to use marco language tag
if (languageTagParts.length > 1) { if (languageTagParts.length > 1) {
browserLanguage = languageTagParts[0]; browserLanguage = languageTagParts[0] as string;
// try to match marco language tag with full language tag in i18n file // try to match marco language tag with full language tag in i18n file
if (ALL_LANGUAGES[browserLanguage]) { if (ALL_LANGUAGES[browserLanguage]) {
@@ -373,24 +367,19 @@ export function useI18n() {
} }
function getLanguageKeyFromLanguageAlias(alias: string): string | null { function getLanguageKeyFromLanguageAlias(alias: string): string | null {
for (const languageKey in ALL_LANGUAGES) { for (const [languageKey, languageInfo] of entries(ALL_LANGUAGES)) {
if (!Object.prototype.hasOwnProperty.call(ALL_LANGUAGES, languageKey)) {
continue;
}
if (languageKey.toLowerCase() === alias.toLowerCase()) { if (languageKey.toLowerCase() === alias.toLowerCase()) {
return languageKey; return languageKey;
} }
const langInfo = ALL_LANGUAGES[languageKey]; const aliases = languageInfo.aliases;
const aliases = langInfo.aliases;
if (!aliases || aliases.length < 1) { if (!aliases || aliases.length < 1) {
continue; continue;
} }
for (let i = 0; i < aliases.length; i++) { for (const aliasName of aliases) {
if (aliases[i].toLowerCase() === alias.toLowerCase()) { if (aliasName.toLowerCase() === alias.toLowerCase()) {
return languageKey; return languageKey;
} }
} }
@@ -400,16 +389,12 @@ export function useI18n() {
} }
function getLanguageKeyFromMarcoLanguageTag(languageTag: string): string | null { function getLanguageKeyFromMarcoLanguageTag(languageTag: string): string | null {
for (const languageKey in ALL_LANGUAGES) { for (const languageKey of keys(ALL_LANGUAGES)) {
if (!Object.prototype.hasOwnProperty.call(ALL_LANGUAGES, languageKey)) {
continue;
}
if (languageKey.indexOf('-') < 0) { if (languageKey.indexOf('-') < 0) {
continue; continue;
} }
const marcoLanguageTag = languageKey.split('-')[0]; const marcoLanguageTag = languageKey.split('-')[0] as string;
if (marcoLanguageTag.toLowerCase() === languageTag.toLowerCase()) { if (marcoLanguageTag.toLowerCase() === languageTag.toLowerCase()) {
return languageKey; return languageKey;
@@ -422,7 +407,7 @@ export function useI18n() {
function getLocalizedError(error: ErrorResponse): LocalizedError { function getLocalizedError(error: ErrorResponse): LocalizedError {
if (error.errorCode === KnownErrorCode.ApiNotFound && SPECIFIED_API_NOT_FOUND_ERRORS[error.path]) { if (error.errorCode === KnownErrorCode.ApiNotFound && SPECIFIED_API_NOT_FOUND_ERRORS[error.path]) {
return { return {
message: `${SPECIFIED_API_NOT_FOUND_ERRORS[error.path].message}` message: `${SPECIFIED_API_NOT_FOUND_ERRORS[error.path]!.message}`
}; };
} }
@@ -432,8 +417,7 @@ export function useI18n() {
}; };
} }
for (let i = 0; i < PARAMETERIZED_ERRORS.length; i++) { for (const errorInfo of PARAMETERIZED_ERRORS) {
const errorInfo = PARAMETERIZED_ERRORS[i];
const matches = error.errorMessage.match(errorInfo.regex); const matches = error.errorMessage.match(errorInfo.regex);
if (matches && matches.length === errorInfo.parameters.length + 1) { if (matches && matches.length === errorInfo.parameters.length + 1) {
@@ -443,7 +427,7 @@ export function useI18n() {
return { return {
key: param.field, key: param.field,
localized: param.localized, localized: param.localized,
value: matches[index + 1] value: matches[index + 1] as string
} }
}) })
}; };
@@ -459,9 +443,7 @@ export function useI18n() {
const localizedParameters: Record<string, string> = {}; const localizedParameters: Record<string, string> = {};
if (parameters) { if (parameters) {
for (let i = 0; i < parameters.length; i++) { for (const parameter of parameters) {
const parameter = parameters[i];
if (parameter.localized) { if (parameter.localized) {
localizedParameters[parameter.key] = t(`parameter.${parameter.value}`); localizedParameters[parameter.key] = t(`parameter.${parameter.value}`);
} else { } else {
@@ -520,8 +502,7 @@ export function useI18n() {
const allCurrencyDisplayTypes = CurrencyDisplayType.values(); const allCurrencyDisplayTypes = CurrencyDisplayType.values();
for (let i = 0; i < allCurrencyDisplayTypes.length; i++) { for (const type of allCurrencyDisplayTypes) {
const type = allCurrencyDisplayTypes[i];
const sampleValue = getFormattedAmountWithCurrency(12345, defaultCurrency, type, numeralSystem, decimalSeparator); const sampleValue = getFormattedAmountWithCurrency(12345, defaultCurrency, type, numeralSystem, decimalSeparator);
const displayName = `${t(type.name)} (${sampleValue})` const displayName = `${t(type.name)} (${sampleValue})`
@@ -534,7 +515,7 @@ export function useI18n() {
return ret; return ret;
} }
function getAllLocalizedCalendarTypes(allTypeAndNameArray: CalendarDisplayType[] | DateDisplayType[], localeDefaultType: CalendarDisplayType | DateDisplayType | undefined, systemDefaultType: CalendarDisplayType | DateDisplayType, languageDefaultValue: number): TypeAndDisplayName[] { function getAllLocalizedCalendarTypes(allCalendarDisplayTypeArray: CalendarDisplayType[] | DateDisplayType[], localeDefaultType: CalendarDisplayType | DateDisplayType | undefined, systemDefaultType: CalendarDisplayType | DateDisplayType, languageDefaultValue: number): TypeAndDisplayName[] {
let defaultType: TypeAndName | undefined = localeDefaultType; let defaultType: TypeAndName | undefined = localeDefaultType;
if (!defaultType) { if (!defaultType) {
@@ -548,12 +529,10 @@ export function useI18n() {
displayName: `${t('Language Default')} (${t('calendar.' + defaultType.name)})` displayName: `${t('Language Default')} (${t('calendar.' + defaultType.name)})`
}); });
for (let i = 0; i < allTypeAndNameArray.length; i++) { for (const calendarDisplayType of allCalendarDisplayTypeArray) {
const type = allTypeAndNameArray[i];
ret.push({ ret.push({
type: type.type, type: calendarDisplayType.type,
displayName: t('calendar.' + type.name) displayName: t('calendar.' + calendarDisplayType.name)
}); });
} }
@@ -563,12 +542,10 @@ export function useI18n() {
function getLocalizedDisplayNameAndType(typeAndNames: TypeAndName[]): TypeAndDisplayName[] { function getLocalizedDisplayNameAndType(typeAndNames: TypeAndName[]): TypeAndDisplayName[] {
const ret: TypeAndDisplayName[] = []; const ret: TypeAndDisplayName[] = [];
for (let i = 0; i < typeAndNames.length; i++) { for (const typeAndName of typeAndNames) {
const nameAndType = typeAndNames[i];
ret.push({ ret.push({
type: nameAndType.type, type: typeAndName.type,
displayName: t(nameAndType.name) displayName: t(typeAndName.name)
}); });
} }
@@ -583,12 +560,10 @@ export function useI18n() {
displayName: t('System Default') + (defaultType.name ? ` (${t(defaultType.name)})` : '') displayName: t('System Default') + (defaultType.name ? ` (${t(defaultType.name)})` : '')
}); });
for (let i = 0; i < typeAndNames.length; i++) { for (const typeAndName of typeAndNames) {
const nameAndType = typeAndNames[i];
ret.push({ ret.push({
type: nameAndType.type, type: typeAndName.type,
displayName: t(nameAndType.name) displayName: t(typeAndName.name)
}); });
} }
@@ -610,13 +585,11 @@ export function useI18n() {
displayName: `${t('Language Default')} (${defaultSeparatorType.symbol})` displayName: `${t('Language Default')} (${defaultSeparatorType.symbol})`
}); });
for (let i = 0; i < allSeparatorArray.length; i++) { for (const separator of allSeparatorArray) {
const type = allSeparatorArray[i];
ret.push({ ret.push({
type: type.type, type: separator.type,
symbol: type.symbol, symbol: separator.symbol,
displayName: `${t('numeral.' + type.name)} (${type.symbol})` displayName: `${t('numeral.' + separator.name)} (${separator.symbol})`
}); });
} }
@@ -627,9 +600,7 @@ export function useI18n() {
const ret: TypeAndDisplayName[] = []; const ret: TypeAndDisplayName[] = [];
const allTypes: ChartDateAggregationType[] = ChartDateAggregationType.values(); const allTypes: ChartDateAggregationType[] = ChartDateAggregationType.values();
for (let i = 0; i < allTypes.length; i++) { for (const type of allTypes) {
const type = allTypes[i];
ret.push({ ret.push({
type: type.type, type: type.type,
displayName: t(fullName ? type.fullName : `granularity.${type.shortName}`) displayName: t(fullName ? type.fullName : `granularity.${type.shortName}`)
@@ -643,8 +614,7 @@ export function useI18n() {
const ret = []; const ret = [];
const allMonths = Month.values(); const allMonths = Month.values();
for (let i = 0; i < allMonths.length; i++) { for (const month of allMonths) {
const month = allMonths[i];
ret.push(t(`datetime.${month.name}.${type}`)); ret.push(t(`datetime.${month.name}.${type}`));
} }
@@ -655,8 +625,7 @@ export function useI18n() {
const ret = []; const ret = [];
const allWeekDays = WeekDay.values(); const allWeekDays = WeekDay.values();
for (let i = 0; i < allWeekDays.length; i++) { for (const weekDay of allWeekDays) {
const weekDay = allWeekDays[i];
ret.push(t(`datetime.${weekDay.name}.${type}`)); ret.push(t(`datetime.${weekDay.name}.${type}`));
} }
@@ -952,17 +921,12 @@ export function useI18n() {
function getAllLanguageOptions(includeSystemDefault: boolean): LanguageOption[] { function getAllLanguageOptions(includeSystemDefault: boolean): LanguageOption[] {
const ret: LanguageOption[] = []; const ret: LanguageOption[] = [];
for (const languageTag in ALL_LANGUAGES) { for (const [languageKey, languageInfo] of entries(ALL_LANGUAGES)) {
if (!Object.prototype.hasOwnProperty.call(ALL_LANGUAGES, languageTag)) {
continue;
}
const languageInfo = ALL_LANGUAGES[languageTag];
const displayName = languageInfo.displayName; const displayName = languageInfo.displayName;
const languageNameInCurrentLanguage = getLanguageDisplayName(languageInfo.name); const languageNameInCurrentLanguage = getLanguageDisplayName(languageInfo.name);
ret.push({ ret.push({
languageTag: languageTag, languageTag: languageKey,
displayName: languageNameInCurrentLanguage, displayName: languageNameInCurrentLanguage,
nativeDisplayName: displayName nativeDisplayName: displayName
}); });
@@ -996,11 +960,7 @@ export function useI18n() {
function getAllCurrencies(): LocalizedCurrencyInfo[] { function getAllCurrencies(): LocalizedCurrencyInfo[] {
const allCurrencies: LocalizedCurrencyInfo[] = []; const allCurrencies: LocalizedCurrencyInfo[] = [];
for (const currencyCode in ALL_CURRENCIES) { for (const currencyCode of keys(ALL_CURRENCIES)) {
if (!Object.prototype.hasOwnProperty.call(ALL_CURRENCIES, currencyCode)) {
continue;
}
const localizedCurrencyInfo: LocalizedCurrencyInfo = { const localizedCurrencyInfo: LocalizedCurrencyInfo = {
currencyCode: currencyCode, currencyCode: currencyCode,
displayName: getCurrencyName(currencyCode) displayName: getCurrencyName(currencyCode)
@@ -1020,9 +980,7 @@ export function useI18n() {
const allMeridiemIndicators = MeridiemIndicator.values(); const allMeridiemIndicators = MeridiemIndicator.values();
const localizedMeridiemIndicatorNames = []; const localizedMeridiemIndicatorNames = [];
for (let i = 0; i < allMeridiemIndicators.length; i++) { for (const indicator of allMeridiemIndicators) {
const indicator = allMeridiemIndicators[i];
localizedMeridiemIndicatorNames.push({ localizedMeridiemIndicatorNames.push({
name: t(`datetime.${indicator.name}.content`), name: t(`datetime.${indicator.name}.content`),
value: indicator.name value: indicator.name
@@ -1061,7 +1019,7 @@ export function useI18n() {
} }
for (let i = firstDayOfWeek; i < allWeekDays.length; i++) { for (let i = firstDayOfWeek; i < allWeekDays.length; i++) {
const weekDay = allWeekDays[i]; const weekDay = allWeekDays[i] as WeekDay;
ret.push({ ret.push({
type: weekDay.type, type: weekDay.type,
@@ -1070,7 +1028,7 @@ export function useI18n() {
} }
for (let i = 0; i < firstDayOfWeek; i++) { for (let i = 0; i < firstDayOfWeek; i++) {
const weekDay = allWeekDays[i]; const weekDay = allWeekDays[i] as WeekDay;
ret.push({ ret.push({
type: weekDay.type, type: weekDay.type,
@@ -1092,8 +1050,7 @@ export function useI18n() {
displayName: `${t('Language Default')} (${formatCurrentTime(defaultFormat, dateTimeFormatOptions)})` displayName: `${t('Language Default')} (${formatCurrentTime(defaultFormat, dateTimeFormatOptions)})`
}); });
for (let i = 0; i < allFormatArray.length; i++) { for (const formatType of allFormatArray) {
const formatType = allFormatArray[i];
const format = t(`format.${type}.${formatType.key}`); const format = t(`format.${type}.${formatType.key}`);
ret.push({ ret.push({
@@ -1110,9 +1067,7 @@ export function useI18n() {
const ret: LocalizedDateRange[] = []; const ret: LocalizedDateRange[] = [];
const allDateRanges = DateRange.values(); const allDateRanges = DateRange.values();
for (let i = 0; i < allDateRanges.length; i++) { for (const dateRange of allDateRanges) {
const dateRange = allDateRanges[i];
if (!dateRange.isAvailableForScene(scene)) { if (!dateRange.isAvailableForScene(scene)) {
continue; continue;
} }
@@ -1158,9 +1113,7 @@ export function useI18n() {
}); });
} }
for (let i = 0; i < recentDateRanges.length; i++) { for (const recentDateRange of recentDateRanges) {
const recentDateRange = recentDateRanges[i];
allRecentMonthDateRanges.push({ allRecentMonthDateRanges.push({
dateType: recentDateRange.dateType, dateType: recentDateRange.dateType,
minTime: recentDateRange.minTime, minTime: recentDateRange.minTime,
@@ -1190,14 +1143,14 @@ export function useI18n() {
const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes(); const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes();
const allTimezoneInfos: LocalizedTimezoneInfo[] = []; const allTimezoneInfos: LocalizedTimezoneInfo[] = [];
for (let i = 0; i < ALL_TIMEZONES.length; i++) { for (const timezoneInfo of ALL_TIMEZONES) {
const utcOffset = (ALL_TIMEZONES[i].timezoneName !== UTC_TIMEZONE.timezoneName ? numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(ALL_TIMEZONES[i].timezoneName)) : ''); const utcOffset = (timezoneInfo.timezoneName !== UTC_TIMEZONE.timezoneName ? numeralSystem.replaceWesternArabicDigitsToLocalizedDigits(getTimezoneOffset(timezoneInfo.timezoneName)) : '');
const displayName = t(`timezone.${ALL_TIMEZONES[i].displayName}`); const displayName = t(`timezone.${timezoneInfo.displayName}`);
allTimezoneInfos.push({ allTimezoneInfos.push({
name: ALL_TIMEZONES[i].timezoneName, name: timezoneInfo.timezoneName,
utcOffset: utcOffset, utcOffset: utcOffset,
utcOffsetMinutes: getTimezoneOffsetMinutes(ALL_TIMEZONES[i].timezoneName), utcOffsetMinutes: getTimezoneOffsetMinutes(timezoneInfo.timezoneName),
displayName: displayName, displayName: displayName,
displayNameWithUtcOffset: `(UTC${utcOffset}) ${displayName}` displayNameWithUtcOffset: `(UTC${utcOffset}) ${displayName}`
}); });
@@ -1269,9 +1222,7 @@ export function useI18n() {
const allFiscalYearFormats = FiscalYearFormat.values(); const allFiscalYearFormats = FiscalYearFormat.values();
for (let i = 0; i < allFiscalYearFormats.length; i++) { for (const fiscalYearFormat of allFiscalYearFormats) {
const fiscalYearFormat = allFiscalYearFormats[i];
ret.push({ ret.push({
type: fiscalYearFormat.type, type: fiscalYearFormat.type,
displayName: formatTimeRangeToGregorianLikeFiscalYearFormat(fiscalYearFormat, currentFiscalYearRange, numeralSystem, calendarType), displayName: formatTimeRangeToGregorianLikeFiscalYearFormat(fiscalYearFormat, currentFiscalYearRange, numeralSystem, calendarType),
@@ -1298,9 +1249,7 @@ export function useI18n() {
const allNumeralSystemTypes = NumeralSystem.values(); const allNumeralSystemTypes = NumeralSystem.values();
for (let i = 0; i < allNumeralSystemTypes.length; i++) { for (const type of allNumeralSystemTypes) {
const type = allNumeralSystemTypes[i];
ret.push({ ret.push({
type: type.type, type: type.type,
displayName: `${t('numeral.' + type.name)} (${type.textualAllDigits})` displayName: `${t('numeral.' + type.name)} (${type.textualAllDigits})`
@@ -1329,8 +1278,7 @@ export function useI18n() {
const allDigitGroupingTypes = DigitGroupingType.values(); const allDigitGroupingTypes = DigitGroupingType.values();
const numberCharacters = numeralSystem.replaceWesternArabicDigitsToLocalizedDigits('123456789').split(''); const numberCharacters = numeralSystem.replaceWesternArabicDigitsToLocalizedDigits('123456789').split('');
for (let i = 0; i < allDigitGroupingTypes.length; i++) { for (const type of allDigitGroupingTypes) {
const type = allDigitGroupingTypes[i];
const sampleValue = type.format(numberCharacters, digitGroupingSymbol); const sampleValue = type.format(numberCharacters, digitGroupingSymbol);
ret.push({ ret.push({
@@ -1364,9 +1312,7 @@ export function useI18n() {
const allPresetAmountColors = PresetAmountColor.values(); const allPresetAmountColors = PresetAmountColor.values();
for (let i = 0; i < allPresetAmountColors.length; i++) { for (const amountColor of allPresetAmountColors) {
const amountColor = allPresetAmountColors[i];
ret.push({ ret.push({
type: amountColor.type, type: amountColor.type,
displayName: t('color.amount.' + amountColor.name) displayName: t('color.amount.' + amountColor.name)
@@ -1380,9 +1326,7 @@ export function useI18n() {
const ret: LocalizedAccountCategory[] = []; const ret: LocalizedAccountCategory[] = [];
const allCategories = AccountCategory.values(); const allCategories = AccountCategory.values();
for (let i = 0; i < allCategories.length; i++) { for (const accountCategory of allCategories) {
const accountCategory = allCategories[i];
ret.push({ ret.push({
type: accountCategory.type, type: accountCategory.type,
displayName: t(accountCategory.name), displayName: t(accountCategory.name),
@@ -1403,9 +1347,8 @@ export function useI18n() {
categoryTypes.push(categoryType); categoryTypes.push(categoryType);
} }
for (let i = 0; i < categoryTypes.length; i++) { for (const categoryType of categoryTypes) {
const categories: LocalizedPresetCategory[] = []; const categories: LocalizedPresetCategory[] = [];
const categoryType = categoryTypes[i];
let defaultCategories: PresetCategory[] = []; let defaultCategories: PresetCategory[] = [];
if (categoryType === CategoryType.Income) { if (categoryType === CategoryType.Income) {
@@ -1416,9 +1359,7 @@ export function useI18n() {
defaultCategories = DEFAULT_TRANSFER_CATEGORIES; defaultCategories = DEFAULT_TRANSFER_CATEGORIES;
} }
for (let j = 0; j < defaultCategories.length; j++) { for (const category of defaultCategories) {
const category = defaultCategories[j];
const submitCategory: LocalizedPresetCategory = { const submitCategory: LocalizedPresetCategory = {
name: t('category.' + category.name, {}, { locale: locale }), name: t('category.' + category.name, {}, { locale: locale }),
type: categoryType, type: categoryType,
@@ -1427,8 +1368,7 @@ export function useI18n() {
subCategories: [] subCategories: []
}; };
for (let k = 0; k < category.subCategories.length; k++) { for (const subCategory of category.subCategories) {
const subCategory = category.subCategories[k];
const submitSubCategory: LocalizedPresetSubCategory = { const submitSubCategory: LocalizedPresetSubCategory = {
name: t('category.' + subCategory.name, {}, { locale: locale }), name: t('category.' + subCategory.name, {}, { locale: locale }),
type: categoryType, type: categoryType,
@@ -1455,9 +1395,7 @@ export function useI18n() {
return availableExchangeRates; return availableExchangeRates;
} }
for (let i = 0; i < exchangeRatesData.exchangeRates.length; i++) { for (const exchangeRate of exchangeRatesData.exchangeRates) {
const exchangeRate = exchangeRatesData.exchangeRates[i];
availableExchangeRates.push({ availableExchangeRates.push({
currencyCode: exchangeRate.currency, currencyCode: exchangeRate.currency,
currencyDisplayName: getCurrencyName(exchangeRate.currency), currencyDisplayName: getCurrencyName(exchangeRate.currency),
@@ -1494,16 +1432,13 @@ export function useI18n() {
function getAllSupportedImportFileCagtegoryAndTypes(): LocalizedImportFileCategoryAndTypes[] { function getAllSupportedImportFileCagtegoryAndTypes(): LocalizedImportFileCategoryAndTypes[] {
const allSupportedImportFileCategoryAndTypes: LocalizedImportFileCategoryAndTypes[] = []; const allSupportedImportFileCategoryAndTypes: LocalizedImportFileCategoryAndTypes[] = [];
for (let i = 0; i < SUPPORTED_IMPORT_FILE_CATEGORY_AND_TYPES.length; i++) { for (const categoryAndTypes of SUPPORTED_IMPORT_FILE_CATEGORY_AND_TYPES) {
const categoryAndTypes = SUPPORTED_IMPORT_FILE_CATEGORY_AND_TYPES[i];
const localizedCategoryAndTypes: LocalizedImportFileCategoryAndTypes = { const localizedCategoryAndTypes: LocalizedImportFileCategoryAndTypes = {
displayCategoryName: t(categoryAndTypes.categoryName), displayCategoryName: t(categoryAndTypes.categoryName),
fileTypes: [] fileTypes: []
}; };
for (let j = 0; j < categoryAndTypes.fileTypes.length; j++) { for (const fileType of categoryAndTypes.fileTypes) {
const fileType = categoryAndTypes.fileTypes[j];
let document: LocalizedImportFileDocument | undefined; let document: LocalizedImportFileDocument | undefined;
if (fileType.document) { if (fileType.document) {
@@ -1517,7 +1452,7 @@ export function useI18n() {
if (SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage] === documentLanguage) { if (SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage] === documentLanguage) {
documentAnchor = t(`document.anchor.export_and_import.${fileType.document.anchor}`); documentAnchor = t(`document.anchor.export_and_import.${fileType.document.anchor}`);
} else if (SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage]) { } else if (SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage]) {
documentLanguage = SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage]; documentLanguage = SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage] as string;
documentAnchor = t(`document.anchor.export_and_import.${fileType.document.anchor}`, {}, { locale: documentLanguage }); documentAnchor = t(`document.anchor.export_and_import.${fileType.document.anchor}`, {}, { locale: documentLanguage });
} else { } else {
documentLanguage = DEFAULT_DOCUMENT_LANGUAGE_FOR_IMPORT_FILE; documentLanguage = DEFAULT_DOCUMENT_LANGUAGE_FOR_IMPORT_FILE;
@@ -1528,8 +1463,8 @@ export function useI18n() {
documentAnchor = fileType.document.anchor; documentAnchor = fileType.document.anchor;
} }
if (documentLanguage && documentLanguage !== getCurrentLanguageTag()) { if (documentLanguage && documentLanguage !== getCurrentLanguageTag() && ALL_LANGUAGES[documentLanguage]) {
documentDisplayLanguageName = getLanguageDisplayName(ALL_LANGUAGES[documentLanguage].name); documentDisplayLanguageName = getLanguageDisplayName((ALL_LANGUAGES[documentLanguage] as LanguageInfo).name);
} }
if (documentLanguage) { if (documentLanguage) {
@@ -1556,8 +1491,7 @@ export function useI18n() {
const subTypes: LocalizedImportFileTypeSubType[] = []; const subTypes: LocalizedImportFileTypeSubType[] = [];
if (fileType.subTypes) { if (fileType.subTypes) {
for (let k = 0; k < fileType.subTypes.length; k++) { for (const subType of fileType.subTypes) {
const subType = fileType.subTypes[k];
const localizedSubType: LocalizedImportFileTypeSubType = { const localizedSubType: LocalizedImportFileTypeSubType = {
type: subType.type, type: subType.type,
displayName: t(subType.name), displayName: t(subType.name),
@@ -1571,8 +1505,7 @@ export function useI18n() {
const supportedEncodings: LocalizedImportFileTypeSupportedEncodings[] = []; const supportedEncodings: LocalizedImportFileTypeSupportedEncodings[] = [];
if (fileType.supportedEncodings) { if (fileType.supportedEncodings) {
for (let k = 0; k < fileType.supportedEncodings.length; k++) { for (const encoding of fileType.supportedEncodings) {
const encoding = fileType.supportedEncodings[k];
const localizedEncoding: LocalizedImportFileTypeSupportedEncodings = { const localizedEncoding: LocalizedImportFileTypeSupportedEncodings = {
encoding: encoding, encoding: encoding,
displayName: t(`encoding.${encoding}`) displayName: t(`encoding.${encoding}`)
@@ -1638,7 +1571,7 @@ export function useI18n() {
if (monthDays.length === 1) { if (monthDays.length === 1) {
return t('format.misc.monthDay', { return t('format.misc.monthDay', {
ordinal: getMonthdayOrdinal(monthDays[0]) ordinal: getMonthdayOrdinal(monthDays[0] as number)
}); });
} else { } else {
return t('format.misc.monthDays', { return t('format.misc.monthDays', {
@@ -1657,16 +1590,14 @@ export function useI18n() {
firstDayOfWeek = WeekDay.DefaultFirstDay.type; firstDayOfWeek = WeekDay.DefaultFirstDay.type;
} }
for (let i = 0; i < weekdayTypes.length; i++) { for (const weekdayType of weekdayTypes) {
weekdayTypesMap[weekdayTypes[i]] = true; weekdayTypesMap[weekdayType] = true;
} }
const allWeekDays = getAllWeekDays(firstDayOfWeek); const allWeekDays = getAllWeekDays(firstDayOfWeek);
const finalWeekdayNames = []; const finalWeekdayNames = [];
for (let i = 0; i < allWeekDays.length; i++) { for (const weekDay of allWeekDays) {
const weekDay = allWeekDays[i];
if (weekdayTypesMap[weekDay.type]) { if (weekdayTypesMap[weekDay.type]) {
finalWeekdayNames.push(weekDay.displayName); finalWeekdayNames.push(weekDay.displayName);
} }
@@ -1894,9 +1825,7 @@ export function useI18n() {
const dateTimeFormatOptions = getDateTimeFormatOptions(); const dateTimeFormatOptions = getDateTimeFormatOptions();
const gregorianLikeDateTimeFormatOptions = getDateTimeFormatOptions({ calendarType: gregorianLikeCalendarType }); const gregorianLikeDateTimeFormatOptions = getDateTimeFormatOptions({ calendarType: gregorianLikeCalendarType });
for (let i = 0; i < allDateRanges.length; i++) { for (const dateRange of allDateRanges) {
const dateRange = allDateRanges[i];
if (dateRange && dateRange.type !== DateRange.Custom.type && dateRange.type === dateType && dateRange.name) { if (dateRange && dateRange.type !== DateRange.Custom.type && dateRange.type === dateType && dateRange.name) {
return t(dateRange.name); return t(dateRange.name);
} }
@@ -1984,8 +1913,7 @@ export function useI18n() {
const ret: CalendarAlternateDate[] = []; const ret: CalendarAlternateDate[] = [];
for (let i = 0; i < chineseDates.length; i++) { for (const chineseDate of chineseDates) {
const chineseDate = chineseDates[i];
const alternateDate = getChineseCalendarAlternateDisplayDate(chineseDate); const alternateDate = getChineseCalendarAlternateDisplayDate(chineseDate);
ret.push(alternateDate); ret.push(alternateDate);
} }
@@ -2117,11 +2045,9 @@ export function useI18n() {
return formatExchangeRateAmount(value, numberFormatOptions); return formatExchangeRateAmount(value, numberFormatOptions);
} }
function getAdaptiveAmountRate(amount1: number, amount2: number, fromExchangeRate: { function getAdaptiveAmountRate(amount1: number, amount2: number, fromExchangeRate?: { rate: string }, toExchangeRate?: { rate: string }): string | null {
rate: string
}, toExchangeRate: { rate: string }): string | null {
const numberFormatOptions = getNumberFormatOptions({}); const numberFormatOptions = getNumberFormatOptions({});
return getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, numberFormatOptions); return getAdaptiveDisplayAmountRate(amount1, amount2, numberFormatOptions, fromExchangeRate, toExchangeRate);
} }
function getAmountPrependAndAppendText(currencyCode: string, isPlural: boolean): CurrencyPrependAndAppendText | null { function getAmountPrependAndAppendText(currencyCode: string, isPlural: boolean): CurrencyPrependAndAppendText | null {
@@ -2137,19 +2063,17 @@ export function useI18n() {
const allCategories = AccountCategory.values(); const allCategories = AccountCategory.values();
const categorizedAccounts: Record<number, CategorizedAccount> = getCategorizedAccountsMap(Account.cloneAccounts(allVisibleAccounts)); const categorizedAccounts: Record<number, CategorizedAccount> = getCategorizedAccountsMap(Account.cloneAccounts(allVisibleAccounts));
for (let i = 0; i < allCategories.length; i++) { for (const category of allCategories) {
const category = allCategories[i]; const accountCategory = categorizedAccounts[category.type];
if (!categorizedAccounts[category.type]) { if (!accountCategory) {
continue; continue;
} }
const accountCategory = categorizedAccounts[category.type];
const accountsWithDisplayBalance: AccountWithDisplayBalance[] = []; const accountsWithDisplayBalance: AccountWithDisplayBalance[] = [];
if (accountCategory.accounts) { if (accountCategory.accounts) {
for (let i = 0; i < accountCategory.accounts.length; i++) { for (const account of accountCategory.accounts) {
const account = accountCategory.accounts[i];
let accountWithDisplaceBalance: AccountWithDisplayBalance; let accountWithDisplaceBalance: AccountWithDisplayBalance;
if (showAccountBalance && account.isAsset) { if (showAccountBalance && account.isAsset) {
@@ -2171,24 +2095,24 @@ export function useI18n() {
let totalBalance = 0; let totalBalance = 0;
let hasUnCalculatedAmount = false; let hasUnCalculatedAmount = false;
for (let i = 0; i < accountsBalance.length; i++) { for (const accountBalance of accountsBalance) {
if (accountsBalance[i].currency === defaultCurrency) { if (accountBalance.currency === defaultCurrency) {
if (accountsBalance[i].isAsset) { if (accountBalance.isAsset) {
totalBalance += accountsBalance[i].balance; totalBalance += accountBalance.balance;
} else if (accountsBalance[i].isLiability) { } else if (accountBalance.isLiability) {
totalBalance -= accountsBalance[i].balance; totalBalance -= accountBalance.balance;
} }
} else { } else {
const balance = exchangeRatesStore.getExchangedAmount(accountsBalance[i].balance, accountsBalance[i].currency, defaultCurrency); const balance = exchangeRatesStore.getExchangedAmount(accountBalance.balance, accountBalance.currency, defaultCurrency);
if (!isNumber(balance)) { if (!isNumber(balance)) {
hasUnCalculatedAmount = true; hasUnCalculatedAmount = true;
continue; continue;
} }
if (accountsBalance[i].isAsset) { if (accountBalance.isAsset) {
totalBalance += Math.trunc(balance); totalBalance += Math.trunc(balance);
} else if (accountsBalance[i].isLiability) { } else if (accountBalance.isLiability) {
totalBalance -= Math.trunc(balance); totalBalance -= Math.trunc(balance);
} }
} }
+15 -27
View File
@@ -108,7 +108,7 @@ export class Account implements AccountInfoResponse {
} }
for (let i = 0; i < this.subAccounts.length; i++) { for (let i = 0; i < this.subAccounts.length; i++) {
if (!this.subAccounts[i].equals(other.subAccounts[i])) { if (!(this.subAccounts[i] as Account).equals(other.subAccounts[i] as Account)) {
return false; return false;
} }
} }
@@ -137,9 +137,9 @@ export class Account implements AccountInfoResponse {
public setSuitableIcon(oldCategory: number, newCategory: number): void { public setSuitableIcon(oldCategory: number, newCategory: number): void {
const allCategories = AccountCategory.values(); const allCategories = AccountCategory.values();
for (let i = 0; i < allCategories.length; i++) { for (const category of allCategories) {
if (allCategories[i].type === oldCategory) { if (category.type === oldCategory) {
if (this.icon !== allCategories[i].defaultAccountIconId) { if (this.icon !== category.defaultAccountIconId) {
return; return;
} else { } else {
break; break;
@@ -147,9 +147,9 @@ export class Account implements AccountInfoResponse {
} }
} }
for (let i = 0; i < allCategories.length; i++) { for (const category of allCategories) {
if (allCategories[i].type === newCategory) { if (category.type === newCategory) {
this.icon = allCategories[i].defaultAccountIconId; this.icon = category.defaultAccountIconId;
} }
} }
} }
@@ -231,9 +231,7 @@ export class Account implements AccountInfoResponse {
return null; return null;
} }
for (let i = 0; i < this.subAccounts.length; i++) { for (const subAccount of this.subAccounts) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) { if (subAccountId && subAccountId === subAccount.id) {
return subAccount.id; return subAccount.id;
} }
@@ -255,9 +253,7 @@ export class Account implements AccountInfoResponse {
return false; return false;
} }
for (let i = 0; i < this.subAccounts.length; i++) { for (const subAccount of this.subAccounts) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) { if (subAccountId && subAccountId === subAccount.id) {
return subAccount.hidden; return subAccount.hidden;
} }
@@ -279,9 +275,7 @@ export class Account implements AccountInfoResponse {
return null; return null;
} }
for (let i = 0; i < this.subAccounts.length; i++) { for (const subAccount of this.subAccounts) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) { if (subAccountId && subAccountId === subAccount.id) {
return subAccount.comment; return subAccount.comment;
} }
@@ -303,9 +297,7 @@ export class Account implements AccountInfoResponse {
return null; return null;
} }
for (let i = 0; i < this.subAccounts.length; i++) { for (const subAccount of this.subAccounts) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) { if (subAccountId && subAccountId === subAccount.id) {
return subAccount; return subAccount;
} }
@@ -322,9 +314,7 @@ export class Account implements AccountInfoResponse {
return null; return null;
} }
for (let i = 0; i < this.subAccounts.length; i++) { for (const subAccount of this.subAccounts) {
const subAccount = this.subAccounts[i];
if (subAccountId && subAccountId === subAccount.id) { if (subAccountId && subAccountId === subAccount.id) {
return subAccount; return subAccount;
} }
@@ -341,9 +331,7 @@ export class Account implements AccountInfoResponse {
const subAccountCurrenciesMap: Record<string, boolean> = {}; const subAccountCurrenciesMap: Record<string, boolean> = {};
const subAccountCurrencies: string[] = []; const subAccountCurrencies: string[] = [];
for (let i = 0; i < this.subAccounts.length; i++) { for (const subAccount of this.subAccounts) {
const subAccount = this.subAccounts[i];
if (!showHidden && subAccount.hidden) { if (!showHidden && subAccount.hidden) {
continue; continue;
} }
@@ -508,7 +496,7 @@ export class Account implements AccountInfoResponse {
if (account1.parentId && account1.parentId !== '0') { if (account1.parentId && account1.parentId !== '0') {
if (allAccountsMap && allAccountsMap[account1.parentId]) { if (allAccountsMap && allAccountsMap[account1.parentId]) {
account1DisplayOrder = allAccountsMap[account1.parentId].displayOrder; account1DisplayOrder = (allAccountsMap[account1.parentId] as Account).displayOrder;
} else { } else {
account1DisplayOrder = null; account1DisplayOrder = null;
} }
@@ -516,7 +504,7 @@ export class Account implements AccountInfoResponse {
if (account2.parentId && account2.parentId !== '0') { if (account2.parentId && account2.parentId !== '0') {
if (allAccountsMap && allAccountsMap[account2.parentId]) { if (allAccountsMap && allAccountsMap[account2.parentId]) {
account2DisplayOrder = allAccountsMap[account2.parentId].displayOrder; account2DisplayOrder = (allAccountsMap[account2.parentId] as Account).displayOrder;
} else { } else {
account2DisplayOrder = null; account2DisplayOrder = null;
} }
+4 -4
View File
@@ -1,4 +1,4 @@
import type { PartialRecord } from '@/core/base.ts'; import { type PartialRecord, itemAndIndex } from '@/core/base.ts';
import type { Year1BasedMonth, TextualYearMonthDay, StartEndTime, WeekDay } from '@/core/datetime.ts'; import type { Year1BasedMonth, TextualYearMonthDay, StartEndTime, WeekDay } from '@/core/datetime.ts';
import { type Coordinate, getNormalizedCoordinate } from '@/core/coordinate.ts'; import { type Coordinate, getNormalizedCoordinate } from '@/core/coordinate.ts';
import { TransactionType } from '@/core/transaction.ts'; import { TransactionType } from '@/core/transaction.ts';
@@ -185,9 +185,9 @@ export class Transaction implements TransactionInfoResponse {
return; return;
} }
for (let i = 0; i < this._pictures.length; i++) { for (const [picture, index] of itemAndIndex(this._pictures)) {
if (this._pictures[i].pictureId === pictureInfo.pictureId) { if (picture.pictureId === pictureInfo.pictureId) {
this._pictures.splice(i, 1); this._pictures.splice(index, 1);
} }
} }
} }
+4 -7
View File
@@ -1,3 +1,4 @@
import { entries } from '@/core/base.ts';
import type { ColorValue } from '@/core/color.ts'; import type { ColorValue } from '@/core/color.ts';
import { CategoryType } from '@/core/category.ts'; import { CategoryType } from '@/core/category.ts';
import { DEFAULT_CATEGORY_ICON_ID } from '@/consts/icon.ts'; import { DEFAULT_CATEGORY_ICON_ID } from '@/consts/icon.ts';
@@ -58,7 +59,7 @@ export class TransactionCategory implements TransactionCategoryInfoResponse {
} }
for (let i = 0; i < this.subCategories.length; i++) { for (let i = 0; i < this.subCategories.length; i++) {
if (!this.subCategories[i].equals(other.subCategories[i])) { if (!(this.subCategories[i] as TransactionCategory).equals(other.subCategories[i] as TransactionCategory)) {
return false; return false;
} }
} }
@@ -132,12 +133,8 @@ export class TransactionCategory implements TransactionCategoryInfoResponse {
public static ofMap(categoriesByType: Record<number, TransactionCategoryInfoResponse[]>): Record<number, TransactionCategory[]> { public static ofMap(categoriesByType: Record<number, TransactionCategoryInfoResponse[]>): Record<number, TransactionCategory[]> {
const ret: Record<number, TransactionCategory[]> = {}; const ret: Record<number, TransactionCategory[]> = {};
for (const categoryType in categoriesByType) { for (const [categoryType, categories] of entries(categoriesByType)) {
if (!Object.prototype.hasOwnProperty.call(categoriesByType, categoryType)) { ret[parseInt(categoryType)] = TransactionCategory.ofMulti(categories);
continue;
}
ret[categoryType] = TransactionCategory.ofMulti(categoriesByType[categoryType]);
} }
return ret; return ret;
+11 -13
View File
@@ -1,7 +1,7 @@
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import type { BeforeResolveFunction } from '@/core/base.ts'; import { type BeforeResolveFunction, itemAndIndex } from '@/core/base.ts';
import type { import type {
UserCustomExchangeRateUpdateResponse, UserCustomExchangeRateUpdateResponse,
@@ -65,15 +65,14 @@ export const useExchangeRatesStore = defineStore('exchangeRates', () => {
return exchangeRateMap; return exchangeRateMap;
} }
for (let i = 0; i < latestExchangeRates.value.data.exchangeRates.length; i++) { for (const exchangeRate of latestExchangeRates.value.data.exchangeRates) {
const exchangeRate = latestExchangeRates.value.data.exchangeRates[i];
exchangeRateMap[exchangeRate.currency] = exchangeRate; exchangeRateMap[exchangeRate.currency] = exchangeRate;
} }
return exchangeRateMap; return exchangeRateMap;
}); });
function updateExchangeRateToLatestExchangeRateList(exchangeRate: LatestExchangeRate, updateTime: number): void { function updateExchangeRateToLatestExchangeRateList(latestExchangeRate: LatestExchangeRate, updateTime: number): void {
if (!latestExchangeRates.value || !latestExchangeRates.value.data || !latestExchangeRates.value.data.exchangeRates) { if (!latestExchangeRates.value || !latestExchangeRates.value.data || !latestExchangeRates.value.data.exchangeRates) {
return; return;
} }
@@ -81,16 +80,16 @@ export const useExchangeRatesStore = defineStore('exchangeRates', () => {
const exchangeRates = latestExchangeRates.value.data.exchangeRates; const exchangeRates = latestExchangeRates.value.data.exchangeRates;
let changed = false; let changed = false;
for (let i = 0; i < exchangeRates.length; i++) { for (const [exchangeRate, index] of itemAndIndex(exchangeRates)) {
if (exchangeRates[i].currency === exchangeRate.currency) { if (exchangeRate.currency === latestExchangeRate.currency) {
exchangeRates.splice(i, 1, exchangeRate); exchangeRates.splice(index, 1, latestExchangeRate);
changed = true; changed = true;
break; break;
} }
} }
if (!changed) { if (!changed) {
exchangeRates.push(exchangeRate); exchangeRates.push(latestExchangeRate);
changed = true; changed = true;
} }
@@ -109,9 +108,9 @@ export const useExchangeRatesStore = defineStore('exchangeRates', () => {
const exchangeRates = latestExchangeRates.value.data.exchangeRates; const exchangeRates = latestExchangeRates.value.data.exchangeRates;
let changed = false; let changed = false;
for (let i = 0; i < exchangeRates.length; i++) { for (const [exchangeRate, index] of itemAndIndex(exchangeRates)) {
if (exchangeRates[i].currency === currency) { if (exchangeRate.currency === currency) {
exchangeRates.splice(i, 1); exchangeRates.splice(index, 1);
changed = true; changed = true;
break; break;
} }
@@ -262,8 +261,7 @@ export const useExchangeRatesStore = defineStore('exchangeRates', () => {
const exchangeRates = latestExchangeRates.value.data.exchangeRates; const exchangeRates = latestExchangeRates.value.data.exchangeRates;
const exchangeRateMap: Record<string, LatestExchangeRate> = {}; const exchangeRateMap: Record<string, LatestExchangeRate> = {};
for (let i = 0; i < exchangeRates.length; i++) { for (const exchangeRate of exchangeRates) {
const exchangeRate = exchangeRates[i];
exchangeRateMap[exchangeRate.currency] = exchangeRate; exchangeRateMap[exchangeRate.currency] = exchangeRate;
} }
+17 -18
View File
@@ -1,6 +1,10 @@
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import {
values
} from '@/core/base.ts';
import { import {
type ApplicationSettingValue, type ApplicationSettingValue,
type ApplicationSettingSubValue, type ApplicationSettingSubValue,
@@ -39,13 +43,15 @@ export const useSettingsStore = defineStore('settings', () => {
function updateApplicationSettingsValueAndAppSettingsFromCloudSetting(key: string, value: string | number | boolean | Record<string, boolean>): void { function updateApplicationSettingsValueAndAppSettingsFromCloudSetting(key: string, value: string | number | boolean | Record<string, boolean>): void {
const keyItems = key.split('.'); const keyItems = key.split('.');
const keyFirstPart = keyItems[0] as string;
if (keyItems.length === 1) { if (keyItems.length === 1) {
updateApplicationSettingsValue(keyItems[0], value); updateApplicationSettingsValue(keyFirstPart, value);
appSettings.value[keyItems[0]] = value; appSettings.value[keyFirstPart] = value;
} else if (keyItems.length === 2) { } else if (keyItems.length === 2) {
updateApplicationSettingsSubValue(keyItems[0], keyItems[1], value); const subKey = keyItems[1] as string;
(appSettings.value[keyItems[0]] as Record<string, ApplicationSettingSubValue>)[keyItems[1]] = value; updateApplicationSettingsSubValue(keyFirstPart, subKey, value);
(appSettings.value[keyFirstPart] as Record<string, ApplicationSettingSubValue>)[subKey] = value;
} else { } else {
logger.warn(`cannot load application cloud setting "${key}", because it has invalid key format`); logger.warn(`cannot load application cloud setting "${key}", because it has invalid key format`);
} }
@@ -60,10 +66,12 @@ export const useSettingsStore = defineStore('settings', () => {
} }
const keyItems = key.split('.'); const keyItems = key.split('.');
let value: ApplicationSettingValue | ApplicationSettingSubValue = appSettings.value[key]; let value: ApplicationSettingValue | ApplicationSettingSubValue = appSettings.value[key] as (ApplicationSettingValue | ApplicationSettingSubValue);
if (keyItems.length === 2) { if (keyItems.length === 2) {
value = (appSettings.value[keyItems[0]] as Record<string, ApplicationSettingSubValue>)[keyItems[1]]; const primaryKey = keyItems[0] as string;
const subKey = keyItems[1] as string;
value = (appSettings.value[primaryKey] as Record<string, ApplicationSettingSubValue>)[subKey] as ApplicationSettingSubValue;
} else if (keyItems.length > 2) { } else if (keyItems.length > 2) {
logger.warn(`cannot get application cloud setting "${key}", because it has invalid key format`); logger.warn(`cannot get application cloud setting "${key}", because it has invalid key format`);
return null; return null;
@@ -313,8 +321,7 @@ export const useSettingsStore = defineStore('settings', () => {
const settings: ApplicationCloudSetting[] = []; const settings: ApplicationCloudSetting[] = [];
for (let i = 0; i < applicationSettingKeys.length; i++) { for (const settingKey of applicationSettingKeys) {
const settingKey = applicationSettingKeys[i];
const cloudSetting = createUserApplicationCloudSetting(settingKey); const cloudSetting = createUserApplicationCloudSetting(settingKey);
if (cloudSetting) { if (cloudSetting) {
@@ -333,9 +340,7 @@ export const useSettingsStore = defineStore('settings', () => {
syncedAppSettings.value = arrayItemToObjectField(cloudSettings.map(item => item.settingKey), true); syncedAppSettings.value = arrayItemToObjectField(cloudSettings.map(item => item.settingKey), true);
for (let i = 0; i < cloudSettings.length; i++) { for (const setting of cloudSettings) {
const setting = cloudSettings[i];
if (!setting || !setting.settingKey) { if (!setting || !setting.settingKey) {
continue; continue;
} }
@@ -371,13 +376,7 @@ export const useSettingsStore = defineStore('settings', () => {
let isValid = isObject(map); let isValid = isObject(map);
if (isValid) { if (isValid) {
for (const key in map) { for (const value of values(map)) {
if (!Object.prototype.hasOwnProperty.call(map, key)) {
continue;
}
const value = map[key];
if (!isBoolean(value)) { if (!isBoolean(value)) {
isValid = false; isValid = false;
break; break;
+3 -5
View File
@@ -140,11 +140,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
const allFilterTagIdsCount = computed<number>(() => countSplitItems(transactionsFilter.value.tagIds, ',')); const allFilterTagIdsCount = computed<number>(() => countSplitItems(transactionsFilter.value.tagIds, ','));
const noTransaction = computed<boolean>(() => { const noTransaction = computed<boolean>(() => {
for (let i = 0; i < transactions.value.length; i++) { for (const transactionMonthList of transactions.value) {
const transactionMonthList = transactions.value[i]; for (const transaction of transactionMonthList.items) {
if (transaction) {
for (let j = 0; j < transactionMonthList.items.length; j++) {
if (transactionMonthList.items[j]) {
return false; return false;
} }
} }
+22 -22
View File
@@ -1,7 +1,7 @@
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import type { BeforeResolveFunction } from '@/core/base.ts'; import { type BeforeResolveFunction, itemAndIndex } from '@/core/base.ts';
import { import {
type TransactionTagCreateBatchRequest, type TransactionTagCreateBatchRequest,
@@ -49,37 +49,37 @@ export const useTransactionTagsStore = defineStore('transactionTags', () => {
allTransactionTagsMap.value[tag.id] = tag; allTransactionTagsMap.value[tag.id] = tag;
} }
function updateTagInTransactionTagList(tag: TransactionTag): void { function updateTagInTransactionTagList(currentTag: TransactionTag): void {
for (let i = 0; i < allTransactionTags.value.length; i++) { for (const [transactionTag, index] of itemAndIndex(allTransactionTags.value)) {
if (allTransactionTags.value[i].id === tag.id) { if (transactionTag.id === currentTag.id) {
allTransactionTags.value.splice(i, 1, tag); allTransactionTags.value.splice(index, 1, currentTag);
break; break;
} }
} }
allTransactionTagsMap.value[tag.id] = tag; allTransactionTagsMap.value[currentTag.id] = currentTag;
} }
function updateTagDisplayOrderInTransactionTagList({ from, to }: { from: number, to: number }): void { function updateTagDisplayOrderInTransactionTagList({ from, to }: { from: number, to: number }): void {
allTransactionTags.value.splice(to, 0, allTransactionTags.value.splice(from, 1)[0]); allTransactionTags.value.splice(to, 0, allTransactionTags.value.splice(from, 1)[0] as TransactionTag);
} }
function updateTagVisibilityInTransactionTagList({ tag, hidden }: { tag: TransactionTag, hidden: boolean }): void { function updateTagVisibilityInTransactionTagList({ tag, hidden }: { tag: TransactionTag, hidden: boolean }): void {
if (allTransactionTagsMap.value[tag.id]) { if (allTransactionTagsMap.value[tag.id]) {
allTransactionTagsMap.value[tag.id].hidden = hidden; allTransactionTagsMap.value[tag.id]!.hidden = hidden;
} }
} }
function removeTagFromTransactionTagList(tag: TransactionTag): void { function removeTagFromTransactionTagList(currentTag: TransactionTag): void {
for (let i = 0; i < allTransactionTags.value.length; i++) { for (const [transactionTag, index] of itemAndIndex(allTransactionTags.value)) {
if (allTransactionTags.value[i].id === tag.id) { if (transactionTag.id === currentTag.id) {
allTransactionTags.value.splice(i, 1); allTransactionTags.value.splice(index, 1);
break; break;
} }
} }
if (allTransactionTagsMap.value[tag.id]) { if (allTransactionTagsMap.value[currentTag.id]) {
delete allTransactionTagsMap.value[tag.id]; delete allTransactionTagsMap.value[currentTag.id];
} }
} }
@@ -223,16 +223,16 @@ export const useTransactionTagsStore = defineStore('transactionTags', () => {
function changeTagDisplayOrder({ tagId, from, to }: { tagId: string, from: number, to: number }): Promise<void> { function changeTagDisplayOrder({ tagId, from, to }: { tagId: string, from: number, to: number }): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let tag: TransactionTag | null = null; let currentTag: TransactionTag | null = null;
for (let i = 0; i < allTransactionTags.value.length; i++) { for (const transactionTag of allTransactionTags.value) {
if (allTransactionTags.value[i].id === tagId) { if (transactionTag.id === tagId) {
tag = allTransactionTags.value[i]; currentTag = transactionTag;
break; break;
} }
} }
if (!tag || !allTransactionTags.value[to]) { if (!currentTag || !allTransactionTags.value[to]) {
reject({ message: 'Unable to move tag' }); reject({ message: 'Unable to move tag' });
return; return;
} }
@@ -250,10 +250,10 @@ export const useTransactionTagsStore = defineStore('transactionTags', () => {
function updateTagDisplayOrders(): Promise<boolean> { function updateTagDisplayOrders(): Promise<boolean> {
const newDisplayOrders: TransactionTagNewDisplayOrderRequest[] = []; const newDisplayOrders: TransactionTagNewDisplayOrderRequest[] = [];
for (let i = 0; i < allTransactionTags.value.length; i++) { for (const [transactionTag, index] of itemAndIndex(allTransactionTags.value)) {
newDisplayOrders.push({ newDisplayOrders.push({
id: allTransactionTags.value[i].id, id: transactionTag.id,
displayOrder: i + 1 displayOrder: index + 1
}); });
} }
@@ -6,6 +6,7 @@ import { useTransactionsStore } from '@/stores/transaction.ts';
import { useStatisticsStore } from '@/stores/statistics.ts'; import { useStatisticsStore } from '@/stores/statistics.ts';
import { useOverviewStore } from '@/stores/overview.ts'; import { useOverviewStore } from '@/stores/overview.ts';
import { keys, keysIfValueEquals, values } from '@/core/base.ts';
import type { Account, AccountCategoriesWithVisibleCount } from '@/models/account.ts'; import type { Account, AccountCategoriesWithVisibleCount } from '@/models/account.ts';
import { import {
@@ -65,13 +66,7 @@ export function useAccountFilterSettingPageBase(type?: AccountFilterType) {
function loadFilterAccountIds(): boolean { function loadFilterAccountIds(): boolean {
const allAccountIds: Record<string, boolean> = {}; const allAccountIds: Record<string, boolean> = {};
for (const accountId in accountsStore.allAccountsMap) { for (const account of values(accountsStore.allAccountsMap)) {
if (!Object.prototype.hasOwnProperty.call(accountsStore.allAccountsMap, accountId)) {
continue;
}
const account = accountsStore.allAccountsMap[accountId];
if (!allowHiddenAccount.value && account.hidden) { if (!allowHiddenAccount.value && account.hidden) {
continue; continue;
} }
@@ -93,11 +88,7 @@ export function useAccountFilterSettingPageBase(type?: AccountFilterType) {
filterAccountIds.value = Object.assign(allAccountIds, settingsStore.appSettings.overviewAccountFilterInHomePage); filterAccountIds.value = Object.assign(allAccountIds, settingsStore.appSettings.overviewAccountFilterInHomePage);
return true; return true;
} else if (type === 'transactionListCurrent') { } else if (type === 'transactionListCurrent') {
for (const accountId in transactionsStore.allFilterAccountIds) { for (const accountId of keysIfValueEquals(transactionsStore.allFilterAccountIds, true)) {
if (!Object.prototype.hasOwnProperty.call(transactionsStore.allFilterAccountIds, accountId)) {
continue;
}
const account = accountsStore.allAccountsMap[accountId]; const account = accountsStore.allAccountsMap[accountId];
if (account) { if (account) {
@@ -120,11 +111,7 @@ export function useAccountFilterSettingPageBase(type?: AccountFilterType) {
let finalAccountIds = ''; let finalAccountIds = '';
let changed = true; let changed = true;
for (const accountId in filterAccountIds.value) { for (const accountId of keys(filterAccountIds.value)) {
if (!Object.prototype.hasOwnProperty.call(filterAccountIds.value, accountId)) {
continue;
}
const account = accountsStore.allAccountsMap[accountId]; const account = accountsStore.allAccountsMap[accountId];
if (!account) { if (!account) {
+14 -37
View File
@@ -2,6 +2,7 @@ import { ref, computed } from 'vue';
import { useSettingsStore } from '@/stores/setting.ts'; import { useSettingsStore } from '@/stores/setting.ts';
import { keysIfValueEquals } from '@/core/base.ts';
import type { ApplicationCloudSetting } from '@/core/setting.ts'; import type { ApplicationCloudSetting } from '@/core/setting.ts';
export interface CategorizedApplicationCloudSettingItems { export interface CategorizedApplicationCloudSettingItems {
@@ -101,14 +102,8 @@ export function useAppCloudSyncBase() {
const isEnableCloudSync = computed<boolean>(() => settingsStore.enableApplicationCloudSync); const isEnableCloudSync = computed<boolean>(() => settingsStore.enableApplicationCloudSync);
const hasEnabledApplicationCloudSettings = computed<boolean>(() => { const hasEnabledApplicationCloudSettings = computed<boolean>(() => {
for (const key in enabledApplicationCloudSettings.value) { for (const _ of keysIfValueEquals(enabledApplicationCloudSettings.value, true)) {
if (!Object.prototype.hasOwnProperty.call(enabledApplicationCloudSettings.value, key)) { return true;
continue;
}
if (enabledApplicationCloudSettings.value[key]) {
return true;
}
} }
return false; return false;
@@ -117,22 +112,15 @@ export function useAppCloudSyncBase() {
const enabledApplicationCloudSettingKeys = computed<string[]>(() => { const enabledApplicationCloudSettingKeys = computed<string[]>(() => {
const keys: string[] = []; const keys: string[] = [];
for (const key in enabledApplicationCloudSettings.value) { for (const key of keysIfValueEquals(enabledApplicationCloudSettings.value, true)) {
if (!Object.prototype.hasOwnProperty.call(enabledApplicationCloudSettings.value, key)) { keys.push(key);
continue;
}
if (enabledApplicationCloudSettings.value[key]) {
keys.push(key);
}
} }
return keys; return keys;
}); });
function isAllSettingsSelected(categorizedItems: CategorizedApplicationCloudSettingItems): boolean { function isAllSettingsSelected(categorizedItems: CategorizedApplicationCloudSettingItems): boolean {
for (let i = 0; i < categorizedItems.items.length; i++) { for (const item of categorizedItems.items) {
const item = categorizedItems.items[i];
if (!enabledApplicationCloudSettings.value[item.settingKey]) { if (!enabledApplicationCloudSettings.value[item.settingKey]) {
return false; return false;
} }
@@ -144,8 +132,7 @@ export function useAppCloudSyncBase() {
function hasSettingSelectedButNotAllChecked(categorizedItems: CategorizedApplicationCloudSettingItems): boolean { function hasSettingSelectedButNotAllChecked(categorizedItems: CategorizedApplicationCloudSettingItems): boolean {
let checkedCount = 0; let checkedCount = 0;
for (let i = 0; i < categorizedItems.items.length; i++) { for (const item of categorizedItems.items) {
const item = categorizedItems.items[i];
if (!enabledApplicationCloudSettings.value[item.settingKey]) { if (!enabledApplicationCloudSettings.value[item.settingKey]) {
checkedCount++; checkedCount++;
} }
@@ -155,40 +142,30 @@ export function useAppCloudSyncBase() {
} }
function updateSettingsSelected(categorizedItems: CategorizedApplicationCloudSettingItems, value: boolean): void { function updateSettingsSelected(categorizedItems: CategorizedApplicationCloudSettingItems, value: boolean): void {
for (let i = 0; i < categorizedItems.items.length; i++) { for (const item of categorizedItems.items) {
const item = categorizedItems.items[i];
enabledApplicationCloudSettings.value[item.settingKey] = value; enabledApplicationCloudSettings.value[item.settingKey] = value;
} }
} }
function selectAllSettings(): void { function selectAllSettings(): void {
for (let i = 0; i < ALL_APPLICATION_CLOUD_SETTINGS.length; i++) { for (const categorizedItems of ALL_APPLICATION_CLOUD_SETTINGS) {
const categorizedItems = ALL_APPLICATION_CLOUD_SETTINGS[i]; for (const item of categorizedItems.items) {
for (let j = 0; j < categorizedItems.items.length; j++) {
const item = categorizedItems.items[j];
enabledApplicationCloudSettings.value[item.settingKey] = true; enabledApplicationCloudSettings.value[item.settingKey] = true;
} }
} }
} }
function selectNoneSettings(): void { function selectNoneSettings(): void {
for (let i = 0; i < ALL_APPLICATION_CLOUD_SETTINGS.length; i++) { for (const categorizedItems of ALL_APPLICATION_CLOUD_SETTINGS) {
const categorizedItems = ALL_APPLICATION_CLOUD_SETTINGS[i]; for (const item of categorizedItems.items) {
for (let j = 0; j < categorizedItems.items.length; j++) {
const item = categorizedItems.items[j];
enabledApplicationCloudSettings.value[item.settingKey] = false; enabledApplicationCloudSettings.value[item.settingKey] = false;
} }
} }
} }
function selectInvertSettings(): void { function selectInvertSettings(): void {
for (let i = 0; i < ALL_APPLICATION_CLOUD_SETTINGS.length; i++) { for (const categorizedItems of ALL_APPLICATION_CLOUD_SETTINGS) {
const categorizedItems = ALL_APPLICATION_CLOUD_SETTINGS[i]; for (const item of categorizedItems.items) {
for (let j = 0; j < categorizedItems.items.length; j++) {
const item = categorizedItems.items[j];
enabledApplicationCloudSettings.value[item.settingKey] = !enabledApplicationCloudSettings.value[item.settingKey]; enabledApplicationCloudSettings.value[item.settingKey] = !enabledApplicationCloudSettings.value[item.settingKey];
} }
} }
+7 -23
View File
@@ -9,7 +9,7 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useOverviewStore } from '@/stores/overview.ts'; import { useOverviewStore } from '@/stores/overview.ts';
import { useStatisticsStore } from '@/stores/statistics.ts'; import { useStatisticsStore } from '@/stores/statistics.ts';
import type { NameValue, TypeAndDisplayName } from '@/core/base.ts'; import { type NameValue, type TypeAndDisplayName, keysIfValueEquals, values } from '@/core/base.ts';
import type { LocalizedTimezoneInfo } from '@/core/timezone.ts'; import type { LocalizedTimezoneInfo } from '@/core/timezone.ts';
import { CategoryType } from '@/core/category.ts'; import { CategoryType } from '@/core/category.ts';
import type { Account } from '@/models/account.ts'; import type { Account } from '@/models/account.ts';
@@ -145,12 +145,8 @@ export function useAppSettingPageBase() {
let hasExcludeAccount = false; let hasExcludeAccount = false;
for (const accountId in excludeAccountIds) { for (const accountId of keysIfValueEquals(excludeAccountIds, true)) {
if (!Object.prototype.hasOwnProperty.call(excludeAccountIds, accountId)) { if (accountsStore.allAccountsMap[accountId]) {
continue;
}
if (excludeAccountIds[accountId] && accountsStore.allAccountsMap[accountId]) {
hasExcludeAccount = true; hasExcludeAccount = true;
break; break;
} }
@@ -162,9 +158,7 @@ export function useAppSettingPageBase() {
let allAccountExcluded = true; let allAccountExcluded = true;
for (let i = 0; i < allAccounts.length; i++) { for (const account of allAccounts) {
const account = allAccounts[i];
if (!excludeAccountIds[account.id]) { if (!excludeAccountIds[account.id]) {
allAccountExcluded = false; allAccountExcluded = false;
break; break;
@@ -185,12 +179,8 @@ export function useAppSettingPageBase() {
let hasExcludeTransactionCategory = false; let hasExcludeTransactionCategory = false;
for (const transactionCategoryId in excludeTransactionCategoryIds) { for (const transactionCategoryId of keysIfValueEquals(excludeTransactionCategoryIds, true)) {
if (!Object.prototype.hasOwnProperty.call(excludeTransactionCategoryIds, transactionCategoryId)) { if (transactionCategoriesStore.allTransactionCategoriesMap[transactionCategoryId]) {
continue;
}
if (excludeTransactionCategoryIds[transactionCategoryId] && transactionCategoriesStore.allTransactionCategoriesMap[transactionCategoryId]) {
hasExcludeTransactionCategory = true; hasExcludeTransactionCategory = true;
break; break;
} }
@@ -202,13 +192,7 @@ export function useAppSettingPageBase() {
let allTransactionCategoryExcluded = true; let allTransactionCategoryExcluded = true;
for (const transactionCategoryId in transactionCategoriesStore.allTransactionCategoriesMap) { for (const transactionCategory of values(transactionCategoriesStore.allTransactionCategoriesMap)) {
if (!Object.prototype.hasOwnProperty.call(transactionCategoriesStore.allTransactionCategoriesMap, transactionCategoryId)) {
continue;
}
const transactionCategory = transactionCategoriesStore.allTransactionCategoriesMap[transactionCategoryId];
if (transactionCategory.type !== CategoryType.Income && transactionCategory.type !== CategoryType.Expense) { if (transactionCategory.type !== CategoryType.Income && transactionCategory.type !== CategoryType.Expense) {
continue; continue;
} }
@@ -6,7 +6,7 @@ import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { useTransactionsStore } from '@/stores/transaction.ts'; import { useTransactionsStore } from '@/stores/transaction.ts';
import { useStatisticsStore } from '@/stores/statistics.ts'; import { useStatisticsStore } from '@/stores/statistics.ts';
import type { TypeAndDisplayName } from '@/core/base.ts'; import { type TypeAndDisplayName, keys, keysIfValueEquals, values } from '@/core/base.ts';
import { TransactionTagFilterType } from '@/core/transaction.ts'; import { TransactionTagFilterType } from '@/core/transaction.ts';
import type { TransactionTag } from '@/models/transaction_tag.ts'; import type { TransactionTag } from '@/models/transaction_tag.ts';
@@ -44,20 +44,14 @@ export function useTransactionTagFilterSettingPageBase(type?: string) {
function loadFilterTagIds(): boolean { function loadFilterTagIds(): boolean {
const allTransactionTagIds: Record<string, boolean> = {}; const allTransactionTagIds: Record<string, boolean> = {};
for (const transactionTagId in transactionTagsStore.allTransactionTagsMap) { for (const transactionTag of values(transactionTagsStore.allTransactionTagsMap)) {
if (!Object.prototype.hasOwnProperty.call(transactionTagsStore.allTransactionTagsMap, transactionTagId)) {
continue;
}
const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId];
allTransactionTagIds[transactionTag.id] = true; allTransactionTagIds[transactionTag.id] = true;
} }
if (type === 'statisticsCurrent') { if (type === 'statisticsCurrent') {
const transactionTagIds = statisticsStore.transactionStatisticsFilter.tagIds ? statisticsStore.transactionStatisticsFilter.tagIds.split(',') : []; const transactionTagIds = statisticsStore.transactionStatisticsFilter.tagIds ? statisticsStore.transactionStatisticsFilter.tagIds.split(',') : [];
for (let i = 0; i < transactionTagIds.length; i++) { for (const transactionTagId of transactionTagIds) {
const transactionTagId = transactionTagIds[i];
const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId]; const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId];
if (transactionTag) { if (transactionTag) {
@@ -68,11 +62,7 @@ export function useTransactionTagFilterSettingPageBase(type?: string) {
tagFilterType.value = statisticsStore.transactionStatisticsFilter.tagFilterType; tagFilterType.value = statisticsStore.transactionStatisticsFilter.tagFilterType;
return true; return true;
} else if (type === 'transactionListCurrent') { } else if (type === 'transactionListCurrent') {
for (const transactionTagId in transactionsStore.allFilterTagIds) { for (const transactionTagId of keysIfValueEquals(transactionsStore.allFilterTagIds, true)) {
if (!Object.prototype.hasOwnProperty.call(transactionsStore.allFilterTagIds, transactionTagId)) {
continue;
}
const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId]; const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId];
if (transactionTag) { if (transactionTag) {
@@ -91,11 +81,7 @@ export function useTransactionTagFilterSettingPageBase(type?: string) {
let finalTagIds = ''; let finalTagIds = '';
let changed = true; let changed = true;
for (const transactionTagId in filterTagIds.value) { for (const transactionTagId of keys(filterTagIds.value)) {
if (!Object.prototype.hasOwnProperty.call(filterTagIds.value, transactionTagId)) {
continue;
}
const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId]; const transactionTag = transactionTagsStore.allTransactionTagsMap[transactionTagId];
if (!transactionTag) { if (!transactionTag) {
@@ -9,7 +9,7 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionTagsStore } from '@/stores/transactionTag.ts'; import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type TransactionListFilter, type TransactionMonthList, useTransactionsStore } from '@/stores/transaction.ts'; import { type TransactionListFilter, type TransactionMonthList, useTransactionsStore } from '@/stores/transaction.ts';
import type { TypeAndName } from '@/core/base.ts'; import { type TypeAndName, entries } from '@/core/base.ts';
import type { NumeralSystem } from '@/core/numeral.ts'; import type { NumeralSystem } from '@/core/numeral.ts';
import { type TextualYearMonthDay, type Year0BasedMonth, type LocalizedDateRange, type WeekDayValue, DateRange, DateRangeScene } from '@/core/datetime.ts'; import { type TextualYearMonthDay, type Year0BasedMonth, type LocalizedDateRange, type WeekDayValue, DateRange, DateRangeScene } from '@/core/datetime.ts';
import { AccountType } from '@/core/account.ts'; import { AccountType } from '@/core/account.ts';
@@ -113,16 +113,12 @@ export function useTransactionListPageBase() {
const allPrimaryCategories = computed<Record<string, TransactionCategory[]>>(() => { const allPrimaryCategories = computed<Record<string, TransactionCategory[]>>(() => {
const primaryCategories: Record<string, TransactionCategory[]> = {}; const primaryCategories: Record<string, TransactionCategory[]> = {};
for (const categoryType in transactionCategoriesStore.allTransactionCategories) { for (const [categoryType, categories] of entries(transactionCategoriesStore.allTransactionCategories)) {
if (!Object.prototype.hasOwnProperty.call(transactionCategoriesStore.allTransactionCategories, categoryType)) {
continue;
}
if (query.value.type && categoryTypeToTransactionType(parseInt(categoryType)) !== query.value.type) { if (query.value.type && categoryTypeToTransactionType(parseInt(categoryType)) !== query.value.type) {
continue; continue;
} }
primaryCategories[categoryType] = transactionCategoriesStore.allTransactionCategories[categoryType]; primaryCategories[categoryType] = categories;
} }
return primaryCategories; return primaryCategories;
@@ -131,17 +127,13 @@ export function useTransactionListPageBase() {
const allAvailableCategoriesCount = computed<number>(() => { const allAvailableCategoriesCount = computed<number>(() => {
let totalCount = 0; let totalCount = 0;
for (const categoryType in transactionCategoriesStore.allTransactionCategories) { for (const [categoryType, categories] of entries(transactionCategoriesStore.allTransactionCategories)) {
if (!Object.prototype.hasOwnProperty.call(transactionCategoriesStore.allTransactionCategories, categoryType)) {
continue;
}
if (query.value.type && categoryTypeToTransactionType(parseInt(categoryType)) !== query.value.type) { if (query.value.type && categoryTypeToTransactionType(parseInt(categoryType)) !== query.value.type) {
continue; continue;
} }
if (transactionCategoriesStore.allTransactionCategories[categoryType]) { if (categories) {
totalCount += transactionCategoriesStore.allTransactionCategories[categoryType].length; totalCount += categories.length;
} }
} }
@@ -229,7 +221,7 @@ export function useTransactionListPageBase() {
const displayAmount: string[] = []; const displayAmount: string[] = [];
for (let i = 1; i < amountFilterItems.length; i++) { for (let i = 1; i < amountFilterItems.length; i++) {
displayAmount.push(formatAmountToLocalizedNumeralsWithCurrency(parseInt(amountFilterItems[i]), false)); displayAmount.push(formatAmountToLocalizedNumeralsWithCurrency(parseInt(amountFilterItems[i] as string), false));
} }
return displayAmount.join(' ~ '); return displayAmount.join(' ~ ');
@@ -249,9 +241,9 @@ export function useTransactionListPageBase() {
const currentYear = currentMonthMinDate.getGregorianCalendarYear(); const currentYear = currentMonthMinDate.getGregorianCalendarYear();
const currentMonth = currentMonthMinDate.getGregorianCalendarMonth(); const currentMonth = currentMonthMinDate.getGregorianCalendarMonth();
for (let i = 0; i < allTransactions.length; i++) { for (const transactionMonth of allTransactions) {
if (allTransactions[i].year === currentYear && allTransactions[i].month === currentMonth) { if (transactionMonth.year === currentYear && transactionMonth.month === currentMonth) {
return allTransactions[i]; return transactionMonth;
} }
} }
@@ -111,7 +111,7 @@
v-if="(showHidden || !account.hidden) && account.type === AccountType.MultiSubAccounts.type && ((showHidden && accountCategory.allSubAccounts[account.id]) || accountCategory.allVisibleSubAccountCounts[account.id])"> v-if="(showHidden || !account.hidden) && account.type === AccountType.MultiSubAccounts.type && ((showHidden && accountCategory.allSubAccounts[account.id]) || accountCategory.allVisibleSubAccountCounts[account.id])">
<template :key="subAccount.id" <template :key="subAccount.id"
v-for="(subAccount, subIdx) in accountCategory.allSubAccounts[account.id]"> v-for="(subAccount, subIdx) in accountCategory.allSubAccounts[account.id]">
<v-divider v-if="showHidden ? subIdx > 0 : (!subAccount.hidden ? subIdx > accountCategory.allFirstVisibleSubAccountIndexes[account.id] : false)"/> <v-divider v-if="showHidden ? subIdx > 0 : (!subAccount.hidden ? subIdx > (accountCategory.allFirstVisibleSubAccountIndexes[account.id] as number) : false)"/>
<v-list-item v-if="showHidden || !subAccount.hidden"> <v-list-item v-if="showHidden || !subAccount.hidden">
<template #prepend> <template #prepend>
@@ -108,7 +108,7 @@
v-if="(showHidden || !category.hidden) && ((showHidden && transactionType.allSubCategories[category.id]) || transactionType.allVisibleSubCategoryCounts[category.id])"> v-if="(showHidden || !category.hidden) && ((showHidden && transactionType.allSubCategories[category.id]) || transactionType.allVisibleSubCategoryCounts[category.id])">
<template :key="subCategory.id" <template :key="subCategory.id"
v-for="(subCategory, subIdx) in transactionType.allSubCategories[category.id]"> v-for="(subCategory, subIdx) in transactionType.allSubCategories[category.id]">
<v-divider v-if="showHidden ? subIdx > 0 : (!subCategory.hidden ? subIdx > transactionType.allFirstVisibleSubCategoryIndexes[category.id] : false)"/> <v-divider v-if="showHidden ? subIdx > 0 : (!subCategory.hidden ? subIdx > (transactionType.allFirstVisibleSubCategoryIndexes[category.id] as number) : false)"/>
<v-list-item v-if="showHidden || !subCategory.hidden"> <v-list-item v-if="showHidden || !subCategory.hidden">
<template #prepend> <template #prepend>
+1 -2
View File
@@ -227,8 +227,7 @@ function reload(force: boolean): void {
const exchangeRates = exchangeRatesData.value.exchangeRates; const exchangeRates = exchangeRatesData.value.exchangeRates;
let foundDefaultCurrency = false; let foundDefaultCurrency = false;
for (let i = 0; i < exchangeRates.length; i++) { for (const exchangeRate of exchangeRates) {
const exchangeRate = exchangeRates[i];
if (exchangeRate.currency === baseCurrency.value) { if (exchangeRate.currency === baseCurrency.value) {
foundDefaultCurrency = true; foundDefaultCurrency = true;
break; break;
@@ -696,7 +696,7 @@ function close(completed: boolean): void {
watch(fileType, () => { watch(fileType, () => {
if (allFileSubTypes.value && allFileSubTypes.value.length) { if (allFileSubTypes.value && allFileSubTypes.value.length) {
fileSubType.value = allFileSubTypes.value[0].type; fileSubType.value = allFileSubTypes.value[0]!.type;
} }
importFile.value = null; importFile.value = null;
@@ -145,6 +145,7 @@ import { useRootStore } from '@/stores/index.ts';
import { useSettingsStore } from '@/stores/setting.ts'; import { useSettingsStore } from '@/stores/setting.ts';
import { useTokensStore } from '@/stores/token.ts'; import { useTokensStore } from '@/stores/token.ts';
import { itemAndIndex, reversedItemAndIndex } from '@/core/base.ts';
import { type TokenInfoResponse, SessionInfo } from '@/models/token.ts'; import { type TokenInfoResponse, SessionInfo } from '@/models/token.ts';
import { isEquals } from '@/lib/common.ts'; import { isEquals } from '@/lib/common.ts';
@@ -203,8 +204,7 @@ const sessions = computed<DesktopPageSessionInfo[]>(() => {
return sessions; return sessions;
} }
for (let i = 0; i < tokens.value.length; i++) { for (const token of tokens.value) {
const token = tokens.value[i];
const sessionInfo = parseSessionInfo(token); const sessionInfo = parseSessionInfo(token);
sessions.push(new DesktopPageSessionInfo(sessionInfo)); sessions.push(new DesktopPageSessionInfo(sessionInfo));
} }
@@ -336,9 +336,9 @@ function revokeSession(session: SessionInfo): void {
}).then(() => { }).then(() => {
loadingSession.value = false; loadingSession.value = false;
for (let i = 0; i < tokens.value.length; i++) { for (const [token, index] of itemAndIndex(tokens.value)) {
if (tokens.value[i].tokenId === session.tokenId) { if (token.tokenId === session.tokenId) {
tokens.value.splice(i, 1); tokens.value.splice(index, 1);
} }
} }
}).catch(error => { }).catch(error => {
@@ -362,9 +362,9 @@ function revokeAllSessions(): void {
tokensStore.revokeAllTokens().then(() => { tokensStore.revokeAllTokens().then(() => {
loadingSession.value = false; loadingSession.value = false;
for (let i = tokens.value.length - 1; i >= 0; i--) { for (const [token, index] of reversedItemAndIndex(tokens.value)) {
if (!tokens.value[i].isCurrent) { if (!token.isCurrent) {
tokens.value.splice(i, 1); tokens.value.splice(index, 1);
} }
} }
+1 -2
View File
@@ -309,8 +309,7 @@ exchangeRatesStore.getLatestExchangeRates({
const exchangeRates = exchangeRatesData.value.exchangeRates; const exchangeRates = exchangeRatesData.value.exchangeRates;
let hasBaseCurrency = false; let hasBaseCurrency = false;
for (let i = 0; i < exchangeRates.length; i++) { for (const exchangeRate of exchangeRates) {
const exchangeRate = exchangeRates[i];
if (exchangeRate.currency === baseCurrency.value) { if (exchangeRate.currency === baseCurrency.value) {
hasBaseCurrency = true; hasBaseCurrency = true;
break; break;