From 7b344d4fa4d44013d3dab510928010a21d74e657 Mon Sep 17 00:00:00 2001 From: Pascal Syma Date: Sun, 26 May 2024 19:12:46 +0200 Subject: [PATCH] Setup basic structure --- index.html | 10 +-- package-lock.json | 70 ++++++++++++++++++ package.json | 2 + src/App.vue | 134 ++++++++++++++++++++++++++++------ src/assets/main.css | 5 ++ src/components/TheWelcome.vue | 39 ++++++++++ src/i18n.ts | 16 ++++ src/locales/de.json | 7 ++ src/locales/en.json | 7 ++ src/main.ts | 9 ++- src/stores/menu.ts | 47 ++++++++++++ src/stores/theme.ts | 45 ++++++++++++ tailwind.config.js | 1 + 13 files changed, 364 insertions(+), 28 deletions(-) create mode 100644 src/i18n.ts create mode 100644 src/locales/de.json create mode 100644 src/locales/en.json create mode 100644 src/stores/menu.ts create mode 100644 src/stores/theme.ts diff --git a/index.html b/index.html index a888544..a77cf6f 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - + - - - - Vite App + + + + OSM Filter
diff --git a/package-lock.json b/package-lock.json index cf432ab..57ba261 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "dependencies": { "@vuestic/tailwind": "^0.1.5", "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", "vue": "^3.4.21", + "vue-i18n": "^9.13.1", "vue-router": "^4.3.0", "vuestic-ui": "^1.9.9" }, @@ -615,6 +617,47 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@intlify/core-base": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.13.1.tgz", + "integrity": "sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==", + "dependencies": { + "@intlify/message-compiler": "9.13.1", + "@intlify/shared": "9.13.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.13.1.tgz", + "integrity": "sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==", + "dependencies": { + "@intlify/shared": "9.13.1", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.13.1.tgz", + "integrity": "sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -3126,6 +3169,14 @@ } } }, + "node_modules/pinia-plugin-persistedstate": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz", + "integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==", + "peerDependencies": { + "pinia": "^2.0.0" + } + }, "node_modules/pinia/node_modules/vue-demi": { "version": "0.14.7", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", @@ -4104,6 +4155,25 @@ "eslint": ">=6.0.0" } }, + "node_modules/vue-i18n": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.13.1.tgz", + "integrity": "sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==", + "dependencies": { + "@intlify/core-base": "9.13.1", + "@intlify/shared": "9.13.1", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, "node_modules/vue-router": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz", diff --git a/package.json b/package.json index c26a561..7a65506 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "dependencies": { "@vuestic/tailwind": "^0.1.5", "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", "vue": "^3.4.21", + "vue-i18n": "^9.13.1", "vue-router": "^4.3.0", "vuestic-ui": "^1.9.9" }, diff --git a/src/App.vue b/src/App.vue index 20d10c7..51ea0e7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,29 +1,119 @@ diff --git a/src/assets/main.css b/src/assets/main.css index d47b6c0..dd1345d 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -4,3 +4,8 @@ @tailwind base; @tailwind components; @tailwind utilities; + +body { + background-color: var(--va-background-primary); + color: var(--va-text-primary); +} diff --git a/src/components/TheWelcome.vue b/src/components/TheWelcome.vue index 0143747..cf377f3 100644 --- a/src/components/TheWelcome.vue +++ b/src/components/TheWelcome.vue @@ -5,6 +5,21 @@ import ToolingIcon from './icons/IconTooling.vue'; import EcosystemIcon from './icons/IconEcosystem.vue'; import CommunityIcon from './icons/IconCommunity.vue'; import SupportIcon from './icons/IconSupport.vue'; +import { useAdditionalMenu } from '@/stores/menu'; +import { computed, ref } from 'vue'; + +const toggle = ref(false); + +const menu = computed(() => { + return [ + { + text: toggle.value ? 'option 1 select' : 'option 1 unselect', + onClick: () => (toggle.value = !toggle.value) + }, + { text: 'option 2' } + ]; +}); +useAdditionalMenu(menu); diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 0000000..5adb2fd --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,16 @@ +import { createI18n } from 'vue-i18n'; +import en from './locales/en.json'; +import de from './locales/de.json'; + +export const SUPPORT_LOCALES = [{ code: 'en' }, { code: 'de' }]; + +export const i18n = createI18n({ + legacy: false, + locale: 'en', + fallbackLocale: 'en', + messages: { + en, + de + }, + availableLocales: SUPPORT_LOCALES.map((l) => l.code) +}); diff --git a/src/locales/de.json b/src/locales/de.json new file mode 100644 index 0000000..4f174da --- /dev/null +++ b/src/locales/de.json @@ -0,0 +1,7 @@ +{ + "text": "Hallo", + "locales": { + "en": "Englisch", + "de": "Deutsch" + } +} diff --git a/src/locales/en.json b/src/locales/en.json new file mode 100644 index 0000000..879ded8 --- /dev/null +++ b/src/locales/en.json @@ -0,0 +1,7 @@ +{ + "text": "Hello", + "locales": { + "en": "English", + "de": "German" + } +} diff --git a/src/main.ts b/src/main.ts index 67595c4..f58dc6d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,11 +2,18 @@ import './assets/main.css'; import { createApp } from 'vue'; import { createPinia } from 'pinia'; +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; import App from './App.vue'; import router from './router'; import { createVuestic } from 'vuestic-ui'; +import { i18n } from '@/i18n'; const app = createApp(App); -app.use(createPinia()).use(router).use(createVuestic()).mount('#app'); +app + .use(i18n) + .use(createPinia().use(piniaPluginPersistedstate)) + .use(router) + .use(createVuestic()) + .mount('#app'); diff --git a/src/stores/menu.ts b/src/stores/menu.ts new file mode 100644 index 0000000..f927a16 --- /dev/null +++ b/src/stores/menu.ts @@ -0,0 +1,47 @@ +import { acceptHMRUpdate, defineStore } from 'pinia'; +import { onMounted, onUnmounted, type Ref, ref, toRef, watch } from 'vue'; + +type MenuOption = { + icon?: string; + rightIcon?: string; + text: string; + onClick?: () => void; +}; +export const useMenuStore = defineStore( + 'menu', + () => { + const items = ref>([]); + + function click(index: number) { + if (items.value.length <= index) { + return; + } + console.log('menu', `selected ${index}`, items.value[index]); + items.value[index].onClick?.(); + } + + return { items, click }; + }, + { persist: false } +); + +export function useAdditionalMenu( + items: Ref> | Array +) { + const store = useMenuStore(); + onMounted(() => { + store.items.splice(0); + store.items.push(...toRef(items).value); + }); + onUnmounted(() => { + store.items.splice(0); + }); + watch(toRef(items), (newItems) => { + store.items.splice(0); + store.items.push(...newItems); + }); +} + +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useMenuStore, import.meta.hot)); +} diff --git a/src/stores/theme.ts b/src/stores/theme.ts new file mode 100644 index 0000000..365de3c --- /dev/null +++ b/src/stores/theme.ts @@ -0,0 +1,45 @@ +import { ref, watch } from 'vue'; +import { acceptHMRUpdate, defineStore } from 'pinia'; +import { useColors } from 'vuestic-ui'; +import { i18n, SUPPORT_LOCALES } from '@/i18n'; + +export const useThemeStore = defineStore( + 'theme', + () => { + const { applyPreset, currentPresetName } = useColors(); + const mode = ref(currentPresetName.value); + const h = document.querySelector('html'); + watch(mode, (newMode, oldMode) => { + applyPreset(newMode); + console.log(newMode); + if (h?.classList.replace(oldMode, newMode) === false) { + h?.classList.add(newMode); + } + }); + + console.log(navigator.language); + const lang = ref( + SUPPORT_LOCALES.find((l) => + navigator.language.toLowerCase().startsWith(l.code) + )?.code || SUPPORT_LOCALES[0].code + ); + watch(lang, (l) => { + console.log(l); + i18n.global.locale.value = l as any; + document.querySelector('html')?.setAttribute('lang', l); + }); + + return { mode, lang }; + }, + { + persist: { + afterRestore: (ctx) => { + i18n.global.locale.value = ctx.store.lang as any; + document.querySelector('html')?.setAttribute('lang', ctx.store.lang); + } + } + } +); +if (import.meta.hot) { + import.meta.hot.accept(acceptHMRUpdate(useThemeStore, import.meta.hot)); +} diff --git a/tailwind.config.js b/tailwind.config.js index 35d66ec..cd76ec9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,5 +1,6 @@ /** @type {import('tailwindcss').Config} */ export default { + darkMode: 'class', content: ['./index.html', './src/**/*.{vue,js,ts}'], theme: { extend: {