Skip to content

Commit 15d52a1

Browse files
committed
feat: improve importing data from third party apps
1 parent 1e59675 commit 15d52a1

File tree

8 files changed

+126
-31
lines changed

8 files changed

+126
-31
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export type AlertType = 'error' | 'success' | 'warning';
1+
export type AlertType = 'info' | 'error' | 'success' | 'warning';

src/app/components/base/alert/Alert.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<script lang="ts" setup>
99
import { AlertType } from '@components/base/alert/Alert.types';
1010
import { Color, useThemeStyles } from '@composables/useThemeStyles.ts';
11-
import { RiCheckLine, RiErrorWarningLine } from '@remixicon/vue';
11+
import { RiCheckLine, RiErrorWarningLine, RiInformationLine } from '@remixicon/vue';
1212
import { ClassNames } from '@utils/types.ts';
1313
import { computed } from 'vue';
1414
import type { Component } from 'vue';
@@ -20,6 +20,7 @@ const props = defineProps<{
2020
}>();
2121
2222
const mapping: Record<AlertType, [Color, Component]> = {
23+
info: ['primary', RiInformationLine],
2324
error: ['danger', RiErrorWarningLine],
2425
success: ['success', RiCheckLine],
2526
warning: ['warning', RiErrorWarningLine]
@@ -39,6 +40,7 @@ const theme = useThemeStyles(() => mapping[props.type][0]);
3940
font-weight: var(--font-weight-l);
4041
font-size: var(--font-size-xs);
4142
border-radius: var(--border-radius-m);
43+
align-items: center;
4244
4345
.icon {
4446
width: 17px;

src/app/pages/navigation/tools/import/ImportButton.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@
44
<Dialog ref="dialog" :open="visible" @close="visible = false">
55
<Steps ref="steps" v-slot="{ previous }" @finish="close">
66
<Step :class="$style.step">
7-
<h1 :class="$style.title">{{ t('navigation.tools.import.what.title') }}</h1>
8-
<Button :icon="RiFileFill" :text="t('navigation.tools.import.what.ocular')" @click="next(BudgetFileScreen)" />
7+
<h1 :class="$style.title">{{ t('navigation.tools.import.source.title') }}</h1>
8+
<Button :icon="RiFileFill" :text="t('navigation.tools.import.source.ocular')" @click="next(BudgetFileScreen)" />
99
<Button
1010
:icon="RiGoogleFill"
11-
:text="t('navigation.tools.import.what.google')"
11+
:text="t('navigation.tools.import.source.google')"
1212
@click="next(GoogleAnnualBudgetScreen)"
1313
/>
14+
<Button
15+
:icon="RiDatabase2Fill"
16+
:text="t('navigation.tools.import.source.thirdParty')"
17+
@click="next(ThirdPartyScreen)"
18+
/>
1419
</Step>
1520
<Step>
1621
<component :is="screen" v-if="screen" :back="previous" @loaded="close" />
@@ -22,13 +27,14 @@
2227
<script lang="ts" setup>
2328
import BudgetFileScreen from './screens/BudgetFileScreen.vue';
2429
import GoogleAnnualBudgetScreen from './screens/GoogleAnnualBudgetScreen.vue';
30+
import ThirdPartyScreen from './screens/ThirdPartyScreen.vue';
2531
import Button from '@components/base/button/Button.vue';
2632
import ContextMenuButton from '@components/base/context-menu/ContextMenuButton.vue';
2733
import Dialog from '@components/base/dialog/Dialog.vue';
2834
import Step from '@components/base/steps/Step.vue';
2935
import { StepsExposed } from '@components/base/steps/Steps.types';
3036
import Steps from '@components/base/steps/Steps.vue';
31-
import { RiFileFill, RiGoogleFill, RiUploadCloud2Line } from '@remixicon/vue';
37+
import { RiDatabase2Fill, RiFileFill, RiGoogleFill, RiUploadCloud2Line } from '@remixicon/vue';
3238
import { ref, shallowRef, watch } from 'vue';
3339
import { useI18n } from 'vue-i18n';
3440

src/app/pages/navigation/tools/import/screens/BudgetFileScreen.vue

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<Screen :back="back" :class="$style.screen" :title="t('navigation.tools.import.what.ocular')">
2+
<Screen :back="back" :title="t('navigation.tools.import.what.ocular')">
33
<FilePicker
44
v-model="budgetFile"
55
:class="$style.input"
@@ -45,13 +45,6 @@ const load = async () => {
4545
</script>
4646

4747
<style lang="scss" module>
48-
.screen {
49-
display: flex;
50-
flex-direction: column;
51-
align-items: flex-end;
52-
gap: 10px;
53-
}
54-
5548
.input {
5649
width: 250px;
5750
}

src/app/pages/navigation/tools/import/screens/GoogleAnnualBudgetScreen.vue

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<Screen :back="back" :class="$style.screen" :title="t('navigation.tools.import.google.import')">
2+
<Screen :back="back" :title="t('navigation.tools.import.google.import')">
33
<FilePicker
44
v-model="incomeFile"
55
:class="$style.input"
@@ -57,13 +57,6 @@ const load = async () => {
5757
</script>
5858

5959
<style lang="scss" module>
60-
.screen {
61-
display: flex;
62-
flex-direction: column;
63-
align-items: flex-end;
64-
gap: 10px;
65-
}
66-
6760
.input {
6861
width: 250px;
6962
}

src/app/pages/navigation/tools/import/screens/Screen.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<template>
22
<div :class="$style.screen">
33
<h1 v-if="title" :class="$style.title">
4-
<Button v-if="back" color="dark" :icon="RiArrowLeftSLine" textual @click="back" />
4+
<Button v-if="back" color="dimmed" :icon="RiArrowLeftSLine" textual @click="back" />
55
<span>{{ title }}</span>
66
</h1>
7-
<div :class="classes">
7+
<div :class="[classes, $style.content]">
88
<slot />
99
</div>
1010
</div>
@@ -31,11 +31,19 @@ const classes = computed(() => props.class);
3131
flex-direction: column;
3232
}
3333
34+
.content {
35+
display: flex;
36+
flex-direction: column;
37+
align-items: flex-end;
38+
gap: 10px;
39+
}
40+
3441
.title {
3542
display: flex;
3643
align-items: center;
3744
font-size: var(--font-size-s);
3845
font-weight: var(--font-weight-m);
3946
margin-bottom: 10px;
47+
gap: 5px;
4048
}
4149
</style>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<template>
2+
<Screen :back="back" :class="$style.screen" :title="t('navigation.tools.import.thirdParty.import')">
3+
<Alert :text="t('navigation.tools.import.thirdParty.instructions')" type="info" />
4+
5+
<div :class="$style.content">
6+
<Button
7+
color="success"
8+
size="s"
9+
:text="t('navigation.tools.import.thirdParty.downloadTemplate')"
10+
:icon="RiFileDownloadLine"
11+
@click="downloadTemplate"
12+
/>
13+
14+
<FilePicker
15+
v-model="incomeFile"
16+
:placeholder="t('navigation.tools.import.thirdParty.income')"
17+
:accept="['.csv']"
18+
/>
19+
<FilePicker
20+
v-model="expensesFile"
21+
:placeholder="t('navigation.tools.import.thirdParty.expenses')"
22+
:accept="['.csv']"
23+
/>
24+
<Button
25+
v-if="expensesFile && incomeFile"
26+
:icon="RiUploadCloud2Line"
27+
:text="t('navigation.tools.import.thirdParty.import')"
28+
@click="load"
29+
/>
30+
</div>
31+
</Screen>
32+
</template>
33+
34+
<script lang="ts" setup>
35+
import Screen from './Screen.vue';
36+
import Alert from '@components/base/alert/Alert.vue';
37+
import Button from '@components/base/button/Button.vue';
38+
import FilePicker from '@components/base/file-picker/FilePicker.vue';
39+
import { RiFileDownloadLine, RiUploadCloud2Line } from '@remixicon/vue';
40+
import { useDataStore } from '@store/state';
41+
import { convertGoogleAnnualBudgetCSVToBudgetGroups } from '@store/state/parser/googleAnnualBudgetSheet';
42+
import { readFile } from '@utils/readFile.ts';
43+
import { ref } from 'vue';
44+
import { useI18n } from 'vue-i18n';
45+
46+
const emit = defineEmits<{
47+
(e: 'loaded'): void;
48+
}>();
49+
50+
defineProps<{
51+
back: () => void;
52+
}>();
53+
54+
const { setBudgetGroups } = useDataStore();
55+
const expensesFile = ref<File>();
56+
const incomeFile = ref<File>();
57+
const { t } = useI18n();
58+
59+
const load = async () => {
60+
if (expensesFile.value && incomeFile.value) {
61+
const expenses = convertGoogleAnnualBudgetCSVToBudgetGroups(await readFile(expensesFile.value));
62+
const income = convertGoogleAnnualBudgetCSVToBudgetGroups(await readFile(incomeFile.value));
63+
setBudgetGroups('expenses', expenses);
64+
setBudgetGroups('income', income);
65+
emit('loaded');
66+
}
67+
};
68+
69+
const downloadTemplate = () => {
70+
// TODO: Download template and implement the logic to import the file
71+
};
72+
</script>
73+
74+
<style lang="scss" module>
75+
.screen {
76+
width: 400px;
77+
}
78+
79+
.content {
80+
display: flex;
81+
flex-direction: column;
82+
gap: 10px;
83+
width: 100%;
84+
}
85+
</style>

src/i18n/locales/de.json

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,32 @@
2222
"confirm": "Sind Sie sicher, dass Sie das Jahr {year} löschen möchten?"
2323
},
2424
"export": {
25-
"export": "Als JSON-Datei exportieren"
25+
"export": "Daten exportieren"
2626
},
2727
"import": {
28-
"import": "Aus JSON-Datei importieren",
29-
"what": {
30-
"google": "Google Sheets Jahresbudget",
31-
"ocular": "Eine zuvor exportierte Datei",
28+
"import": "Daten importieren",
29+
"source": {
30+
"google": "Eine Google-Sheets Jahresbudget-Datei",
31+
"ocular": "Eine zuvor exportierte Datei von Ocular",
32+
"thirdParty": "Von Dritten bereitgestellte Daten",
3233
"title": "Was möchten Sie importieren?"
3334
},
3435
"ocular": {
35-
"pickFile": "Wählen Sie Ihre .json-Datei zum Importieren aus",
36-
"import": "Ocular-Daten importieren"
36+
"import": "Ocular-Daten importieren",
37+
"pickFile": "Wählen Sie Ihre .json-Datei zum Importieren aus"
3738
},
3839
"google": {
3940
"import": "Google-Daten importieren",
4041
"pickFile": "Wählen Sie Ihre .csv-Datei zum Importieren aus",
4142
"expenses": "Ausgaben.csv",
4243
"income": "Einnahmen.csv"
44+
},
45+
"thirdParty": {
46+
"import": "Daten von Dritten importieren",
47+
"downloadTemplate": "Vorlage für Einnahmen/Ausgaben herunterladen",
48+
"instructions": "Laden Sie die Vorlage herunter, sie gilt für Einnahmen und Ausgaben. Füllen Sie die Vorlage zweimal aus und wählen Sie dann die beiden Dateien aus, um sie zu importieren.",
49+
"expenses": "Ausgaben.csv",
50+
"income": "Einnahmen.csv"
4351
}
4452
},
4553
"privacyMode": {

0 commit comments

Comments
 (0)