Skip to content

Commit

Permalink
feat(core): synchronize both locale and currency with vue-i18n
Browse files Browse the repository at this point in the history
add new state version to store both the locale and currency
add separate buttons to change the locale / currency
add li18nt to lint localization files
reformat localization files

simonwep#1
  • Loading branch information
simonwep committed Aug 27, 2022
1 parent f0c8531 commit fdb14c8
Show file tree
Hide file tree
Showing 34 changed files with 658 additions and 412 deletions.
14 changes: 14 additions & 0 deletions .li18ntrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"quiet": true,
"rules": {
"prettified": [
"error",
{
"indent": 2
}
],
"conflicts": "error",
"naming": "error",
"duplicates": "off"
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ free to [set it up yourself](#setup)!
> **Attention:** It's currently **not** possibly to sync the app with your personal gmail account due to the google-cloud app not being verified yet. You can still use it and
> download / upload your data or [deploy it yourself](#setup) (which is even cooler!).
> Thanks [@nateseymour](https://github.com/nateseymour) for coming up with a good name for this!
> Thanks, [@nateseymour](https://github.com/nateseymour) for coming up with a good name for this!
### State of this project

Expand Down
292 changes: 127 additions & 165 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"lint": "eslint '{scripts,src}/**/*.{js,ts,vue}' --no-error-on-unmatched-pattern",
"lint:fix": "npm run lint -- --fix",
"lint:src": "eslint '{scripts,src}/**/*.{js,ts,vue}' --no-error-on-unmatched-pattern",
"lint:src:fix": "npm run lint:src -- --fix",
"lint:i18n": "li18nt 'src/i18n/locales/*.json'",
"lint:i18n:fix": "npm run lint:i18n -- --fix",
"lint": "npm run lint:i18n && npm run lint:src",
"lint:fix": "npm run lint:i18n:fix && npm run lint:src:fix",
"test": "vitest run",
"test:watch": "vitest",
"test:ci": "npm run build && npm run lint:fix && npm run test",
Expand All @@ -17,9 +21,10 @@
"dependencies": {
"@popperjs/core": "^2.11.5",
"echarts": "^5.3.3",
"li18nt": "^4.0.1",
"papaparse": "^5.3.2",
"vue": "^3.2.37",
"vue-i18n": "^9.1.10",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.3"
},
"devDependencies": {
Expand Down
87 changes: 42 additions & 45 deletions src/app/components/base/context-menu/ContextMenu.vue
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
<template>
<div :class="$style.contextMenu">
<button ref="reference" :class="$style.reference" @click="toggle">
<div :class="[$style.contextMenu, classes]">
<div ref="reference" :class="$style.reference" @click="toggle">
<slot />
</button>
<div ref="popper" :class="$style.popper">
<ul :class="[$style.list, { [$style.visible]: visible }]">
<li :class="$style.item" v-for="option of options" :key="option.id">
<button :class="[$style.btn, { [$style.highlight]: highlight === option.id }]" @click="select(option)">
{{ option.label ?? option.id }}
</button>
</li>
</div>
<div ref="popper" :class="[$style.popper, { [$style.visible]: visible }]">
<ul :class="$style.list">
<slot name="options" v-if="$slots.options"></slot>
<template v-else-if="options">
<ContextMenuButton
v-for="option of options"
:pad-icon="hasOptionWithIcon"
:key="option.id"
:text="option.label ?? option.id"
:icon="option.icon"
:highlight="option.id === highlight"
@click="select(option)"
/>
</template>
</ul>
</div>
</div>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue';
import { computed, ref, watch } from 'vue';
import { createPopper, Instance } from '@popperjs/core';
import { ContextMenuOption, ContextMenuOptionId } from '.';
import { useOutOfElementClick } from '@composables';
import ContextMenuButton from './ContextMenuButton.vue';
import { ClassNames } from '@utils';
const emit = defineEmits<{
(e: 'select', option: ContextMenuOption): void;
}>();
defineProps<{
options: ContextMenuOption[];
const props = defineProps<{
class?: ClassNames;
options?: ContextMenuOption[];
highlight?: ContextMenuOptionId;
}>();
Expand All @@ -48,6 +58,12 @@ watch([reference, popper], () => {
}
});
const classes = computed(() => props.class);
const hasOptionWithIcon = computed(() => {
return props.options?.some((v) => v.icon);
});
const select = (option: ContextMenuOption): void => {
emit('select', option);
visible.value = false;
Expand All @@ -71,7 +87,19 @@ const toggle = () => {
.popper {
display: flex;
position: absolute;
z-index: 1;
transition: all var(--transition-m) var(--transition-m);
z-index: -1;
&.visible {
z-index: 1;
transition: all var(--transition-m);
.list {
visibility: visible;
opacity: 1;
transform: none;
}
}
}
.list {
Expand All @@ -89,36 +117,5 @@ const toggle = () => {
opacity: 0;
transform: translateX(-10px);
transition: all var(--transition-m);
&.visible {
visibility: visible;
opacity: 1;
transform: none;
}
.item {
display: flex;
.btn {
all: unset;
display: flex;
align-items: center;
cursor: pointer;
font-size: var(--font-size-xs);
padding: 6px 12px;
transition: all var(--transition-s);
color: var(--context-menu-item-color);
position: relative;
&:hover,
&.highlight {
color: var(--context-menu-item-color-hover);
}
&:hover {
background: var(--context-menu-item-background-hover);
}
}
}
}
</style>
82 changes: 82 additions & 0 deletions src/app/components/base/context-menu/ContextMenuButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<li :class="$style.item">
<button :class="classes" @click="emit('click', $event)">
<Icon v-if="icon" :icon="icon" :class="$style.icon"></Icon>
<span>{{ text }}</span>
</button>
</li>
</template>

<script lang="ts" setup>
import { computed, useCssModule } from 'vue';
import { ClassNames } from '@utils';
import Icon from '@components/base/icon/Icon.vue';
import { AppIcon } from '@components/base/icon/Icon.types';
const emit = defineEmits<{
(e: 'click', evt: MouseEvent): void;
}>();
const props = withDefaults(
defineProps<{
class?: ClassNames;
text: string | number;
icon?: AppIcon;
padIcon?: boolean;
highlight?: boolean;
}>(),
{
highlight: false,
padIcon: false
}
);
const styles = useCssModule();
const classes = computed(() => [
props.class,
styles.btn,
{
[styles.highlight]: props.highlight,
[styles.padIcon]: props.padIcon && !props.icon
}
]);
</script>

<style lang="scss" module>
.item {
display: flex;
width: 100%;
}
.btn {
all: unset;
width: 100%;
display: flex;
align-items: center;
cursor: pointer;
font-size: var(--font-size-xs);
padding: 6px 12px;
transition: color var(--transition-s), background var(--transition-s);
color: var(--context-menu-item-color);
position: relative;
.icon {
width: 12px;
height: 12px;
margin-right: 8px;
}
&.padIcon {
margin-left: 20px;
}
&:hover,
&.highlight {
color: var(--context-menu-item-color-hover);
}
&:hover {
background: var(--context-menu-item-background-hover);
}
}
</style>
5 changes: 4 additions & 1 deletion src/app/components/base/context-menu/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export type ContextMenuOptionId = number;
import { AppIcon } from '@components/base/icon/Icon.types';

export type ContextMenuOptionId = number | string;

export interface ContextMenuOption {
id: ContextMenuOptionId;
icon?: AppIcon;
label?: string;
}
4 changes: 3 additions & 1 deletion src/app/components/base/currency/Currency.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<template>
{{ n(value ?? 0, 'currency') }}
{{ n(value ?? 0, { key: 'currency', currency: state.currency }) }}
</template>

<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import { useDataStore } from '@store/state';
const { n } = useI18n();
const { state } = useDataStore();
defineProps<{
value?: number;
Expand Down
3 changes: 0 additions & 3 deletions src/app/components/base/dialog-button/DialogButton.types.ts

This file was deleted.

39 changes: 0 additions & 39 deletions src/app/components/base/dialog-button/DialogButton.vue

This file was deleted.

13 changes: 11 additions & 2 deletions src/app/components/base/dialog/Dialog.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<template>
<dialog ref="dialog" :class="classes" @transitionend="transitionEnd">
<div ref="content" :class="$style.content">
<div ref="content" :class="[$style.content, contentClass]">
<slot />
</div>
</dialog>
</template>

<script lang="ts" setup>
import { computed, ref, useCssModule, watch } from 'vue';
import { computed, onMounted, ref, useCssModule, watch } from 'vue';
import { useOutOfElementClick } from '@composables';
import { ClassNames } from '@utils';
const emit = defineEmits<{
(e: 'close'): void;
}>();
const props = defineProps<{
open: boolean;
contentClass?: ClassNames;
}>();
const content = ref<HTMLDivElement>();
Expand Down Expand Up @@ -44,6 +46,13 @@ watch(
}
}
);
onMounted(() => {
if (dialog.value) {
dialog.value.remove();
document.getElementById('app')?.append(dialog.value);
}
});
</script>

<style lang="scss" module>
Expand Down
4 changes: 4 additions & 0 deletions src/app/components/base/icon/Icon.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ export type AppIcon =
| 'arrow-down-s-line'
| 'arrow-left-s-line'
| 'arrow-right-s-line'
| 'calendar-check-line'
| 'calendar-line'
| 'calendar-todo-line'
| 'check'
| 'close-circle'
| 'cloud-line'
| 'cloud-off-line'
| 'currency-line'
| 'donut-chart'
| 'download-cloud-2-line'
| 'file-fill'
| 'global-line'
| 'google-fill'
| 'grid-line'
| 'hand-coin'
Expand Down
Loading

0 comments on commit fdb14c8

Please sign in to comment.