diff --git a/src/components/desktop/AxisChart.vue b/src/components/desktop/AxisChart.vue index 0eb443a6..255058d6 100644 --- a/src/components/desktop/AxisChart.vue +++ b/src/components/desktop/AxisChart.vue @@ -42,6 +42,7 @@ interface AxisChartDataItem { } interface AxisChartTooltipItem extends SortableTransactionStatisticDataItem { + readonly id: string; readonly name: string; readonly color: unknown; readonly displayOrders: number[]; @@ -71,6 +72,9 @@ const props = defineProps<{ amountValue?: boolean; defaultCurrency?: string; enableClickItem?: boolean; + tooltipExtraColumnNames?: string[]; + tooltipExtraColumnTotalValues?: (categoryIndex: number, totalValue: number, visibleSeriesIds: string[]) => string[]; + tooltipExtraColumnValues?: (seriesId: string, categoryIndex: number, currentValue: number) => string[]; }>(); const emit = defineEmits<{ @@ -290,6 +294,8 @@ const chartOptions = computed(() => { let totalAmount = 0; let actualDisplayItemCount = 0; const displayItems: AxisChartTooltipItem[] = []; + const categoryIndex = params.length > 0 && params[0] ? (params[0].dataIndex ?? 0) : 0; + const visibleSeriesIds: string[] = []; for (const param of params) { const id = param.seriesId as string; @@ -299,38 +305,111 @@ const chartOptions = computed(() => { const amount = param.data as number; displayItems.push({ + id: id, name: name, color: color, displayOrders: displayOrders, totalAmount: amount }); + visibleSeriesIds.push(id); totalAmount += amount; } sortStatisticsItems(displayItems, props.sortingType); - for (const item of displayItems) { + const extraColumnValuesMap: Record = {}; + const extraColumnTotalValues: string[] = []; + const hasExtraColumnIndexes: Record = {}; + + if (props.tooltipExtraColumnNames) { + if (props.tooltipExtraColumnValues) { + for (const [item, index] of itemAndIndex(displayItems)) { + const values = props.tooltipExtraColumnValues(item.id, categoryIndex, item.totalAmount); + extraColumnValuesMap[index] = values; + + for (const [value, columnIndex] of itemAndIndex(values)) { + if (value && value !== '-') { + hasExtraColumnIndexes[columnIndex] = true; + } + } + } + } + + if (props.tooltipExtraColumnTotalValues) { + const values = props.tooltipExtraColumnTotalValues(categoryIndex, totalAmount, visibleSeriesIds); + extraColumnTotalValues.push(...values); + + for (const [value, columnIndex] of itemAndIndex(values)) { + if (value && value !== '-') { + hasExtraColumnIndexes[columnIndex] = true; + } + } + } + } + + for (const [item, index] of itemAndIndex(displayItems)) { if (displayItems.length === 1 || item.totalAmount !== 0) { const value = getDisplayValue(item.totalAmount); - tooltip += '
'; - tooltip += `${item.name}${value}`; - tooltip += '
'; + tooltip += ''; + tooltip += `${item.name}${value}`; + + if (props.tooltipExtraColumnNames) { + const values = extraColumnValuesMap[index] ?? []; + + for (let i = 0; i < props.tooltipExtraColumnNames.length; i++) { + if (!hasExtraColumnIndexes[i]) { + continue; + } + + const value = values[i] ?? '-'; + tooltip += `${value}`; + } + } + + tooltip += ''; actualDisplayItemCount++; } } if (props.showTotalAmountInTooltip && !props.oneHundredPercentStacked) { const displayTotalAmount = getDisplayValue(totalAmount); - tooltip = '
' - + `${props.totalNameInTooltip}${displayTotalAmount}` - + '
' - + (actualDisplayItemCount > 0 ? '
' : '') - + tooltip; + let totalColumnCount = 2; + + let totalTooltip = `` + + `${props.totalNameInTooltip}${displayTotalAmount}`; + + if (props.tooltipExtraColumnNames) { + for (let i = 0; i < props.tooltipExtraColumnNames.length; i++) { + if (!hasExtraColumnIndexes[i]) { + continue; + } + + const value = extraColumnTotalValues[i] ?? '-'; + totalTooltip += `${value}`; + totalColumnCount++; + } + } + + totalTooltip += ''; + totalTooltip += ` 0 ? 'style="border-bottom: ' + (isDarkMode.value ? '#eee' : '#333') + ' dashed 1px"' : ''}>`; + tooltip = totalTooltip + tooltip; } if (params.length && params[0] && params[0].name) { - tooltip = `${params[0].name}
` + tooltip; + let tooltipHeader = `${params[0].name}`; + + if (props.tooltipExtraColumnNames) { + for (const [columnName, columnIndex] of itemAndIndex(props.tooltipExtraColumnNames)) { + if (!hasExtraColumnIndexes[columnIndex]) { + continue; + } + + tooltipHeader += `${columnName}`; + } + } + + tooltip = `${tooltipHeader}${tooltip}
` } return tooltip; diff --git a/src/components/desktop/TrendsChart.vue b/src/components/desktop/TrendsChart.vue index 2d4bc105..8364c845 100644 --- a/src/components/desktop/TrendsChart.vue +++ b/src/components/desktop/TrendsChart.vue @@ -9,6 +9,9 @@ :translate-name="translateName" :amount-value="true" :default-currency="defaultCurrency" :enable-click-item="enableClickItem" + :tooltip-extra-column-names="allTooltipExtraColumnNames" + :tooltip-extra-column-total-values="showYearOverYear || showPeriodOverPeriod ? getTooltipExtraColumnTotalValues : undefined" + :tooltip-extra-column-values="showYearOverYear || showPeriodOverPeriod ? getTooltipExtraColumnValues : undefined" @click="clickItem" v-if="chartDisplayType" /> @@ -29,18 +32,31 @@ import { import { useUserStore } from '@/stores/user.ts'; +import { + itemAndIndex +} from '@/core/base.ts'; import { type Year1BasedMonth, type YearMonthDay, + type YearUnixTime, + type YearQuarterUnixTime, + type YearMonthUnixTime, + type YearMonthDayUnixTime, DateRangeScene } from '@/core/datetime.ts'; +import { + type FiscalYearUnixTime +} from '@/core/fiscalyear.ts'; import { ChartDataAggregationType, TrendChartType, ChartDateAggregationType } from '@/core/statistics.ts'; -import { isArray, isNumber } from '@/lib/common.ts'; +import { + isArray, + isNumber +} from '@/lib/common.ts'; import { parseDateTimeFromUnixTime, getYearMonthFirstUnixTime, @@ -56,6 +72,8 @@ interface DesktopTrendsChartProps extends CommonT type?: number; showValue?: boolean; showTotalAmountInTooltip?: boolean; + showYearOverYear?: boolean; + showPeriodOverPeriod?: boolean; } const props = defineProps>(); @@ -70,7 +88,8 @@ const { formatDateTimeToGregorianLikeShortYear, formatDateTimeToGregorianLikeShortYearMonth, formatYearQuarterToGregorianLikeYearQuarter, - formatDateTimeToGregorianLikeFiscalYear + formatDateTimeToGregorianLikeFiscalYear, + formatPercentToLocalizedNumerals } = useI18n(); const { allDateRanges } = useTrendsChartBase(props); @@ -91,6 +110,20 @@ const chartDisplayType = computed(() => { } }); +const allTooltipExtraColumnNames = computed(() => { + const extraColumnNames: string[] = []; + + if (props.showYearOverYear) { + extraColumnNames.push(tt('Year-over-Year')); + } + + if (props.showPeriodOverPeriod) { + extraColumnNames.push(tt('Period-over-Period')); + } + + return extraColumnNames; +}); + const allDisplayDateRanges = computed(() => { const allDisplayDateRanges: string[] = []; @@ -188,22 +221,9 @@ const allSeriesData = computed[]>(() => { } for (const dateRange of allDateRanges.value) { - let dateRangeKey = ''; - - if (props.dateAggregationType === ChartDateAggregationType.Year.type) { - dateRangeKey = dateRange.year.toString(); - } else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) { - dateRangeKey = dateRange.year.toString(); - } else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type && 'quarter' in dateRange) { - dateRangeKey = `${dateRange.year}-${dateRange.quarter}`; - } else if (props.dateAggregationType === ChartDateAggregationType.Month.type && 'month0base' in dateRange) { - dateRangeKey = `${dateRange.year}-${dateRange.month0base + 1}`; - } else if (props.dateAggregationType === ChartDateAggregationType.Day.type && 'day' in dateRange && props.chartMode === 'daily') { - dateRangeKey = `${dateRange.year}-${dateRange.month}-${dateRange.day}`; - } - - let amount = 0; + const dateRangeKey = getDateRangeKey(dateRange) ?? ''; const dataItems = dateRangeAmountMap[dateRangeKey]; + let amount = 0; if (isArray(dataItems)) { for (const dataItem of dataItems) { @@ -229,6 +249,172 @@ const allSeriesData = computed[]>(() => { return result; }); +const seriesIdValuesMap = computed>(() => { + const result: Record = {}; + + for (const item of allSeriesData.value) { + const id = getSeriesId(item); + const values = item['values'] as number[]; + + if (id && values) { + result[id] = values; + } + } + + return result; +}); + +const yoyIndexMap = computed>(() => { + const result: Record = {}; + const dateKeyToIndex: Record = {}; + + for (const [dateRange, index] of itemAndIndex(allDateRanges.value)) { + const key = getDateRangeKey(dateRange); + + if (key) { + dateKeyToIndex[key] = index; + } + } + + for (const [dateRange, index] of itemAndIndex(allDateRanges.value)) { + const yoyKey = getDateRangeKey(dateRange, -1); + + if (yoyKey && isNumber(dateKeyToIndex[yoyKey])) { + result[index] = dateKeyToIndex[yoyKey]; + } + } + + return result; +}); + +function getSeriesId(item: Record): string { + if (props.idField && item[props.idField]) { + return item[props.idField] as string; + } + + const name = item[props.nameField] as string; + return props.translateName ? tt(name) : name; +} + +function getDateRangeKey(dateRange: YearUnixTime | FiscalYearUnixTime | YearQuarterUnixTime | YearMonthUnixTime | YearMonthDayUnixTime, yearOffset?: number): string | undefined { + if (props.dateAggregationType === ChartDateAggregationType.Year.type) { + return (dateRange.year + (yearOffset ?? 0)).toString(); + } else if (props.dateAggregationType === ChartDateAggregationType.FiscalYear.type && 'year' in dateRange) { + return (dateRange.year + (yearOffset ?? 0)).toString(); + } else if (props.dateAggregationType === ChartDateAggregationType.Quarter.type && 'quarter' in dateRange) { + return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.quarter}`; + } else if (props.dateAggregationType === ChartDateAggregationType.Month.type && 'month0base' in dateRange) { + return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.month0base + 1}`; + } else if (props.dateAggregationType === ChartDateAggregationType.Day.type && 'day' in dateRange && props.chartMode === 'daily') { + return `${dateRange.year + (yearOffset ?? 0)}-${dateRange.month}-${dateRange.day}`; + } else { + return undefined; + } +} + +function formatDisplayChangeRate(current: number, reference: number): string { + if (reference === 0 && current === 0) { + return formatPercentToLocalizedNumerals(0, 2, '<0.01'); + } + + if (reference === 0) { + return '-'; + } + + const rate = (current - reference) / reference * 100; + return formatPercentToLocalizedNumerals(rate, 2, '<0.01'); +} + +function getTooltipExtraColumnTotalValues(categoryIndex: number, totalValue: number, visibleSeriesIds: string[]): string[] { + const extraColumnValues: string[] = []; + + if (!props.showYearOverYear && !props.showPeriodOverPeriod) { + return extraColumnValues; + } + + if (props.showYearOverYear) { + const yoyReferenceIndex = yoyIndexMap.value[categoryIndex]; + let displayChangeRate = '-'; + + if (isNumber(yoyReferenceIndex)) { + let referenceTotalValue = 0; + + for (const seriesId of visibleSeriesIds) { + const values = seriesIdValuesMap.value[seriesId]; + + if (values) { + referenceTotalValue += values[yoyReferenceIndex] ?? 0; + } + } + + displayChangeRate = formatDisplayChangeRate(totalValue, referenceTotalValue); + } + + extraColumnValues.push(displayChangeRate); + } + + if (props.showPeriodOverPeriod) { + const popReferenceIndex = categoryIndex - 1; + let displayChangeRate = '-'; + + if (popReferenceIndex >= 0) { + let referenceTotalValue = 0; + + for (const seriesId of visibleSeriesIds) { + const values = seriesIdValuesMap.value[seriesId]; + + if (values) { + referenceTotalValue += values[popReferenceIndex] ?? 0; + } + } + + displayChangeRate = formatDisplayChangeRate(totalValue, referenceTotalValue); + } + + extraColumnValues.push(displayChangeRate); + } + + return extraColumnValues; +} + +function getTooltipExtraColumnValues(seriesId: string, categoryIndex: number, currentValue: number): string[] { + const extraColumnValues: string[] = []; + + if (!props.showYearOverYear && !props.showPeriodOverPeriod) { + return extraColumnValues; + } + + const values = seriesIdValuesMap.value[seriesId]; + + if (!values) { + return extraColumnValues; + } + + if (props.showYearOverYear) { + const yoyReferenceIndex = yoyIndexMap.value[categoryIndex]; + let displayChangeRate = '-'; + + if (isNumber(yoyReferenceIndex) && yoyReferenceIndex >= 0 && yoyReferenceIndex < values.length) { + displayChangeRate = formatDisplayChangeRate(currentValue, values[yoyReferenceIndex] ?? 0); + } + + extraColumnValues.push(displayChangeRate); + } + + if (props.showPeriodOverPeriod) { + const popReferenceIndex = categoryIndex - 1; + let displayChangeRate = '-'; + + if (popReferenceIndex >= 0 && popReferenceIndex < values.length) { + displayChangeRate = formatDisplayChangeRate(currentValue, values[popReferenceIndex] ?? 0); + } + + extraColumnValues.push(displayChangeRate); + } + + return extraColumnValues; +} + function clickItem(itemId: string, categoryIndex: number): void { const dateRange = allDateRanges.value[categoryIndex]; diff --git a/src/locales/de.json b/src/locales/de.json index bceb9819..6fe8a4aa 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Nach Quartal aggregieren", "Aggregate by Year": "Nach Jahr aggregieren", "Aggregate by Fiscal Year": "Aggregate by Fiscal Year", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Konten filtern", "Filter Transaction Categories": "Transaktionskategorien filtern", "Filter Transaction Tags": "Transaktions-Tags filtern", diff --git a/src/locales/en.json b/src/locales/en.json index 703663f5..d9c1fcc6 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Aggregate by Quarter", "Aggregate by Year": "Aggregate by Year", "Aggregate by Fiscal Year": "Aggregate by Fiscal Year", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Filter Accounts", "Filter Transaction Categories": "Filter Transaction Categories", "Filter Transaction Tags": "Filter Transaction Tags", diff --git a/src/locales/es.json b/src/locales/es.json index cbe404d9..fbfcb5d7 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Agregado por Trimestre", "Aggregate by Year": "Agregado por Año", "Aggregate by Fiscal Year": "Agregado por Año Fiscal", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Filtrar cuentas", "Filter Transaction Categories": "Filtrar categorías de transacciones", "Filter Transaction Tags": "Filtrar etiquetas de transacciones", diff --git a/src/locales/fr.json b/src/locales/fr.json index d6d461b0..a04374c9 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Agréger par trimestre", "Aggregate by Year": "Agréger par année", "Aggregate by Fiscal Year": "Agréger par année fiscale", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Filtrer les comptes", "Filter Transaction Categories": "Filtrer les catégories de transaction", "Filter Transaction Tags": "Filtrer les étiquettes de transaction", diff --git a/src/locales/it.json b/src/locales/it.json index 48b25d17..78d22972 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Aggrega per trimestre", "Aggregate by Year": "Aggrega per anno", "Aggregate by Fiscal Year": "Aggregate by Fiscal Year", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Filtra conti", "Filter Transaction Categories": "Filtra categorie transazione", "Filter Transaction Tags": "Filtra tag transazione", diff --git a/src/locales/ja.json b/src/locales/ja.json index 93c157e8..88946cb0 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "四半期ごとに集計", "Aggregate by Year": "年ごとに集計", "Aggregate by Fiscal Year": "Aggregate by Fiscal Year", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "口座で絞り込み", "Filter Transaction Categories": "取引カテゴリで絞り込み", "Filter Transaction Tags": "取引タグで絞り込み", diff --git a/src/locales/kn.json b/src/locales/kn.json index cb27abbf..7d0e3a2f 100644 --- a/src/locales/kn.json +++ b/src/locales/kn.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "ತ್ರೈಮಾಸಿಕ ಒಕ್ಕೂಟ", "Aggregate by Year": "ವರ್ಷವಾರು ಒಕ್ಕೂಟ", "Aggregate by Fiscal Year": "ಹಣಕಾಸು ವರ್ಷವಾರು ಒಕ್ಕೂಟ", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "ಖಾತೆಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಿ", "Filter Transaction Categories": "ವಹಿವಾಟು ವರ್ಗಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಿ", "Filter Transaction Tags": "ವಹಿವಾಟು ಟ್ಯಾಗ್ಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಿ", diff --git a/src/locales/ko.json b/src/locales/ko.json index f1ec6d06..bd54ff0a 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "분기별 집계", "Aggregate by Year": "연도별 집계", "Aggregate by Fiscal Year": "회계 연도별 집계", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "계좌 필터", "Filter Transaction Categories": "거래 범주 필터", "Filter Transaction Tags": "거래 태그 필터", diff --git a/src/locales/nl.json b/src/locales/nl.json index 555b312a..5c56a974 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Groeperen per kwartaal", "Aggregate by Year": "Groeperen per jaar", "Aggregate by Fiscal Year": "Groeperen per boekjaar", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Rekeningen filteren", "Filter Transaction Categories": "Transactiecategorieën filteren", "Filter Transaction Tags": "Transactietags filteren", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index 9a08a578..06212ca7 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Agregar por Trimestre", "Aggregate by Year": "Agregar por Ano", "Aggregate by Fiscal Year": "Agregar por Ano Fiscal", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Filtrar Contas", "Filter Transaction Categories": "Filtrar Categorias de Transações", "Filter Transaction Tags": "Filtrar Tags de Transações", diff --git a/src/locales/ru.json b/src/locales/ru.json index a8509d56..4aa87634 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Агрегировать по кварталам", "Aggregate by Year": "Агрегировать по годам", "Aggregate by Fiscal Year": "Агрегировать по фискальным годам", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Фильтровать счета", "Filter Transaction Categories": "Фильтровать категории транзакций", "Filter Transaction Tags": "Фильтровать теги транзакций", diff --git a/src/locales/sl.json b/src/locales/sl.json index 271955e8..007673e7 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Združi po četrtletjih", "Aggregate by Year": "Združi po letih", "Aggregate by Fiscal Year": "Združi po fiskalnih letih", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Filtriraj račune", "Filter Transaction Categories": "Filtriraj kategorije transakcij", "Filter Transaction Tags": "Filtriraj oznake transakcij", diff --git a/src/locales/ta.json b/src/locales/ta.json index bda39233..06eb1438 100644 --- a/src/locales/ta.json +++ b/src/locales/ta.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "காலாண்டு கூட்டமைப்பு", "Aggregate by Year": "ஆண்டுவாரி கூட்டமைப்பு", "Aggregate by Fiscal Year": "நிதி ஆண்டுவாரி கூட்டமைப்பு", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "கணக்குகளை வடிகட்டி செய்", "Filter Transaction Categories": "பரிவர்த்தனை வகைகளை வடிகட்டி செய்", "Filter Transaction Tags": "பரிவர்த்தனை குறிச்சொல்களை வடிகட்டி செய்", diff --git a/src/locales/th.json b/src/locales/th.json index 2ff43ff8..392a0078 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "รวมตามไตรมาส", "Aggregate by Year": "รวมตามปี", "Aggregate by Fiscal Year": "รวมตามปีงบประมาณ", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "กรองบัญชี", "Filter Transaction Categories": "กรองหมวดรายการ", "Filter Transaction Tags": "กรองแท็กรายการ", diff --git a/src/locales/tr.json b/src/locales/tr.json index e18fe0d6..ebcd7e2f 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Çeyreğe Göre Topla", "Aggregate by Year": "Yıla Göre Topla", "Aggregate by Fiscal Year": "Mali Yıla Göre Topla", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Hesapları Filtrele", "Filter Transaction Categories": "İşlem Kategorilerini Filtrele", "Filter Transaction Tags": "İşlem Etiketlerini Filtrele", diff --git a/src/locales/uk.json b/src/locales/uk.json index a4b1c702..2f3f6e1b 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Агрегувати за кварталами", "Aggregate by Year": "Агрегувати за роками", "Aggregate by Fiscal Year": "Aggregate by Fiscal Year", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Фільтрувати рахунки", "Filter Transaction Categories": "Фільтрувати категорії транзакцій", "Filter Transaction Tags": "Фільтрувати теги транзакцій", diff --git a/src/locales/vi.json b/src/locales/vi.json index f1499da0..6b7d5597 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "Tổng hợp theo quý", "Aggregate by Year": "Tổng hợp theo năm", "Aggregate by Fiscal Year": "Aggregate by Fiscal Year", + "Year-over-Year": "Year-over-Year", + "Period-over-Period": "Period-over-Period", "Filter Accounts": "Lọc tài khoản", "Filter Transaction Categories": "Lọc danh mục giao dịch", "Filter Transaction Tags": "Lọc thẻ giao dịch", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 9fad8ff0..27ebbabf 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "按季度聚合", "Aggregate by Year": "按年聚合", "Aggregate by Fiscal Year": "按财年聚合", + "Year-over-Year": "同比", + "Period-over-Period": "环比", "Filter Accounts": "过滤账户", "Filter Transaction Categories": "过滤交易分类", "Filter Transaction Tags": "过滤交易标签", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 2fcda0d5..076d8890 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -2210,6 +2210,8 @@ "Aggregate by Quarter": "依季度彙整", "Aggregate by Year": "依年份彙整", "Aggregate by Fiscal Year": "依財年彙整", + "Year-over-Year": "同比", + "Period-over-Period": "環比", "Filter Accounts": "篩選帳戶", "Filter Transaction Categories": "篩選交易分類", "Filter Transaction Tags": "篩選交易標籤", diff --git a/src/styles/desktop/global.scss b/src/styles/desktop/global.scss index d80be5fc..9d7ca48e 100644 --- a/src/styles/desktop/global.scss +++ b/src/styles/desktop/global.scss @@ -174,6 +174,11 @@ html[dir="rtl"] .bidirectional-switch { background-color: #2f2f2f; } +.chart-tooltip-table { + border-collapse: collapse; + border-spacing: 0; +} + /** Common class for replacing the default style of vuetify **/ .v-input.v-input--readonly input, .v-input.v-input--readonly textarea, diff --git a/src/views/desktop/statistics/TransactionPage.vue b/src/views/desktop/statistics/TransactionPage.vue index fca07766..9339efcf 100644 --- a/src/views/desktop/statistics/TransactionPage.vue +++ b/src/views/desktop/statistics/TransactionPage.vue @@ -400,6 +400,8 @@ :default-currency="defaultCurrency" :stacked="showStackedInTrendsChart" :show-total-amount-in-tooltip="showTotalAmountInTrendsChart" + :show-year-over-year="true" + :show-period-over-period="trendDateAggregationType === ChartDateAggregationType.Month.type || trendDateAggregationType === ChartDateAggregationType.Quarter.type" ref="monthlyTrendsChart" id-field="id" name-field="name" @@ -449,6 +451,8 @@ :default-currency="defaultCurrency" :stacked="showStackedInTrendsChart" :show-total-amount-in-tooltip="showTotalAmountInTrendsChart" + :show-year-over-year="true" + :show-period-over-period="assetTrendsDateAggregationType === ChartDateAggregationType.Day.type || assetTrendsDateAggregationType === ChartDateAggregationType.Month.type || assetTrendsDateAggregationType === ChartDateAggregationType.Quarter.type" ref="dailyTrendsChart" id-field="id" name-field="name"