fix: selects
This commit is contained in:
@@ -7,3 +7,37 @@ import { RouterView } from 'vue-router'
|
|||||||
<RouterView />
|
<RouterView />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <template>
|
||||||
|
<component :is="layoutComponent">
|
||||||
|
<Suspense>
|
||||||
|
<RouterView />
|
||||||
|
</Suspense>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
import DefaultLayout from '@/layouts/default.vue'
|
||||||
|
import EmptyLayout from '@/layouts/empty.vue'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const layouts = {
|
||||||
|
default: DefaultLayout,
|
||||||
|
auth: EmptyLayout
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(route.fullPath)
|
||||||
|
console.log(route.name)
|
||||||
|
console.log(route.matched)
|
||||||
|
|
||||||
|
const layoutComponent = computed(() => {
|
||||||
|
console.log(route.meta);
|
||||||
|
|
||||||
|
return layouts[route.meta.layout as keyof typeof layouts] || DefaultLayout
|
||||||
|
})
|
||||||
|
</script> -->
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ export const uiOptions: NuxtUIOptions = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
slots: {
|
// slots: {
|
||||||
base: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0!',
|
// base: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0!',
|
||||||
},
|
// },
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
slots: {
|
slots: {
|
||||||
@@ -40,9 +40,10 @@ export const uiOptions: NuxtUIOptions = {
|
|||||||
},
|
},
|
||||||
selectMenu: {
|
selectMenu: {
|
||||||
slots: {
|
slots: {
|
||||||
base: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0!',
|
// base: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0!',
|
||||||
content: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! z-80 text-(--black)! dark:text-white!',
|
// content: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! z-80',
|
||||||
itemLeadingIcon: 'text-(--black)! dark:text-white!'
|
// content: 'border! border-(--border-light)! dark:border-(--border-dark)! outline-0! ring-0! z-80 text-(--black)! dark:text-white!',
|
||||||
|
// itemLeadingIcon: 'text-(--black)! dark:text-white!'
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
1
bo/src/assets/error.svg
Normal file
1
bo/src/assets/error.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none"><path stroke="#5b5b5b" stroke-width="2" d="M3 11c0-3.771 0-5.657 1.172-6.828S7.229 3 11 3h2c3.771 0 5.657 0 6.828 1.172S21 7.229 21 11v2c0 3.771 0 5.657-1.172 6.828S16.771 21 13 21h-2c-3.771 0-5.657 0-6.828-1.172S3 16.771 3 13z"/><path fill="#5b5b5b" fill-rule="evenodd" d="m19 13.585l-.02-.02c-.39-.39-.726-.726-1.026-.979c-.317-.267-.662-.502-1.088-.63a3 3 0 0 0-1.732 0c-.426.129-.77.363-1.088.63c-.3.253-.636.59-1.025.98l-.029.028c-.307.306-.487.486-.628.601l-.02.017l-.012-.023c-.087-.16-.189-.393-.36-.792l-.053-.124l-.022-.052c-.356-.83-.655-1.528-.95-2.054c-.305-.541-.685-1.05-1.277-1.346a3 3 0 0 0-1.597-.307c-.66.055-1.201.386-1.685.775c-.406.327-.86.77-1.388 1.297V13q0 .774.003 1.411l1.114-1.114c.69-.69 1.15-1.147 1.525-1.45c.37-.298.53-.335.6-.34a1 1 0 0 1 .532.102c.061.031.196.124.43.54c.236.42.493 1.016.877 1.912l.053.124l.017.038c.149.348.287.67.425.924c.145.265.355.583.709.802a2 2 0 0 0 1.398.27c.41-.073.723-.29.956-.482c.222-.184.47-.432.738-.7l.03-.03c.425-.425.701-.7.928-.891c.218-.184.32-.228.376-.245a1 1 0 0 1 .578 0c.056.017.158.061.376.245c.227.191.503.466.929.892l1.35 1.35c.046-.718.054-1.61.056-2.773" clip-rule="evenodd"/><circle cx="16.5" cy="7.5" r="1.5" fill="#5b5b5b"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -71,3 +71,6 @@ body {
|
|||||||
@apply text-(--accent-green) dark:text-(--accent-green-dark) font-medium;
|
@apply text-(--accent-green) dark:text-(--accent-green-dark) font-medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blue-button {
|
||||||
|
@apply bg-info! text-white!
|
||||||
|
}
|
||||||
@@ -1,35 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<header
|
<header
|
||||||
class="fixed top-0 left-0 right-0 z-50 bg-white/80 dark:bg-(--black) backdrop-blur-md border-b border-(--border-light) dark:border-(--border-dark)">
|
class="fixed top-0 left-0 right-0 z-50 bg-white/80 dark:bg-(--black) backdrop-blur-md border-b border-(--border-light) dark:border-(--border-dark)">
|
||||||
<!-- px-4 sm:px-6 lg:px-8 -->
|
|
||||||
<div class="container mx-auto px-4">
|
<div class="container mx-auto px-4">
|
||||||
<div class="flex items-center justify-between h-14">
|
<div class="flex items-center justify-between h-16">
|
||||||
<!-- Logo -->
|
|
||||||
<RouterLink :to="{ name: 'home' }" class="flex items-center gap-2">
|
<RouterLink :to="{ name: 'home' }" class="flex items-center gap-2">
|
||||||
<div class="w-8 h-8 rounded-lg bg-primary text-white flex items-center justify-center">
|
<div class="w-8 h-8 rounded-lg bg-primary text-white flex items-center justify-center">
|
||||||
<UIcon name="i-heroicons-clock" class="w-5 h-5" />
|
<UIcon name="i-heroicons-clock" class="w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
<span class="font-semibold text-gray-900 dark:text-white">TimeTracker</span>
|
<span class="font-semibold text-gray-900 dark:text-white">{{ settings.app.name }}</span>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
|
||||||
<UNavigationMenu :type="'trigger'" :ui="{
|
<UNavigationMenu :type="'trigger'" :ui="{
|
||||||
root: 'justify-center',
|
root: 'justify-center',
|
||||||
list: 'gap-4'
|
list: 'gap-4 text-(--black)',
|
||||||
}" :items="menuItems" class="w-full"></UNavigationMenu>
|
linkLabel: 'text-(--black) text-sm!'
|
||||||
|
}" :items="menuItems" class="" />
|
||||||
|
<div class="flex items-center gap-12">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<CountryCurrencySwitch />
|
<CountryCurrencySwitch />
|
||||||
<!-- Language Switcher -->
|
|
||||||
<LangSwitch />
|
<LangSwitch />
|
||||||
<!-- Theme Switcher -->
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
<ThemeSwitch />
|
<ThemeSwitch />
|
||||||
<!-- Logout Button (only when authenticated) -->
|
|
||||||
<button v-if="authStore.isAuthenticated" @click="authStore.logout()"
|
<button v-if="authStore.isAuthenticated" @click="authStore.logout()"
|
||||||
class="px-3 py-1.5 text-sm font-medium text-black dark:text-white hover:text-black dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-600 rounded-lg transition-colors border border-(--border-light) dark:border-(--border-dark)">
|
class="px-3 py-1.5 text-sm font-medium text-black dark:text-white hover:text-black dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-600 rounded-lg transition-colors border border-(--border-light) dark:border-(--border-dark) whitespace-nowrap">
|
||||||
{{ $t('general.logout') }}
|
{{ $t('general.logout') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ import type { LabelTrans, TopMenuItem } from '@/types'
|
|||||||
import type { NavigationMenuItem } from '@nuxt/ui'
|
import type { NavigationMenuItem } from '@nuxt/ui'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import CountryCurrencySwitch from './inner/CountryCurrencySwitch.vue'
|
import CountryCurrencySwitch from './inner/CountryCurrencySwitch.vue'
|
||||||
|
import { settings } from '@/router/settings'
|
||||||
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
let menu = ref()
|
let menu = ref()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<UTable :data="productsList" :columns="columns" class="flex-1 w-full" />
|
<UTable :data="productsList" :columns="columns" class="flex-1 w-full" />
|
||||||
<UPagination v-model:page="page" :total="total" :items-per-page="perPage" />
|
<UPagination v-model:page="page" :total="total" :items-per-page="perPage" />
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
</component>
|
</component>
|
||||||
</suspense>
|
</suspense>
|
||||||
</template>
|
</template>
|
||||||
@@ -173,6 +173,7 @@ const UInput = resolveComponent('UInput')
|
|||||||
const UButton = resolveComponent('UButton')
|
const UButton = resolveComponent('UButton')
|
||||||
const UIcon = resolveComponent('UIcon')
|
const UIcon = resolveComponent('UIcon')
|
||||||
|
|
||||||
|
import errorImg from '@/assets/error.svg'
|
||||||
const columns: TableColumn<Product>[] = [
|
const columns: TableColumn<Product>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: 'product_id',
|
accessorKey: 'product_id',
|
||||||
@@ -209,9 +210,13 @@ const columns: TableColumn<Product>[] = [
|
|||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
return h('img', {
|
return h('img', {
|
||||||
src: row.getValue('image_link') as string,
|
src: row.getValue('image_link') as string,
|
||||||
style: 'width:40px;height:40px;object-fit:cover;'
|
style: 'width:40px;height:40px;object-fit:cover;',
|
||||||
})
|
onError: (e: Event) => {
|
||||||
|
const target = e.target as HTMLImageElement
|
||||||
|
target.src = errorImg
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'name',
|
accessorKey: 'name',
|
||||||
@@ -272,8 +277,9 @@ const columns: TableColumn<Product>[] = [
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
goToProduct(row.original.product_id)
|
goToProduct(row.original.product_id)
|
||||||
},
|
},
|
||||||
color: 'primary',
|
class: 'cursor-pointer',
|
||||||
variant: 'solid'
|
color: 'info',
|
||||||
|
variant: 'soft'
|
||||||
}, () => 'Show product')
|
}, () => 'Show product')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<component :is="Default || 'div'">
|
<component :is="Default || 'div'">
|
||||||
|
<p @click="backToProducts()">Back to products</p>
|
||||||
<div class="container my-10 mx-auto">
|
<div class="container my-10 mx-auto">
|
||||||
|
|
||||||
<div class="flex items-end justify-between gap-4 mb-6 bg-(--second-light) dark:bg-(--main-dark) border border-(--border-light) dark:border-(--border-dark) p-4 rounded-md">
|
<div
|
||||||
|
class="flex items-end justify-between gap-4 mb-6 bg-(--second-light) dark:bg-(--main-dark) border border-(--border-light) dark:border-(--border-dark) p-4 rounded-md">
|
||||||
|
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
|
|
||||||
<template v-if="!isViewingExistingTranslation">
|
<template v-if="!isViewingExistingTranslation">
|
||||||
<USelectMenu
|
<USelectMenu v-model="selectedLangId" :items="langOptions" value-key="id" class="w-40"
|
||||||
v-model="selectedLangId"
|
:search-input="false">
|
||||||
:items="langOptions"
|
|
||||||
value-key="id"
|
|
||||||
class="w-40"
|
|
||||||
:search-input="false"
|
|
||||||
>
|
|
||||||
<template #default="{ modelValue }">
|
<template #default="{ modelValue }">
|
||||||
<span class="dark:text-white text-black">
|
<span class="dark:text-white text-black">
|
||||||
{{langOptions.find(l => l.id === modelValue)?.name}}
|
{{langOptions.find(l => l.id === modelValue)?.name}}
|
||||||
@@ -27,24 +24,15 @@
|
|||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
|
|
||||||
<UButton
|
<UButton @click="translateOrSave" :disabled="selectedLangId === defaultLangId" :loading="translating"
|
||||||
@click="translateOrSave"
|
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) px-12!">
|
||||||
:disabled="selectedLangId === defaultLangId"
|
|
||||||
:loading="translating"
|
|
||||||
class="text-white bg-(--accent-blue-light) dark:bg-(--accent-blue-dark) px-12!"
|
|
||||||
>
|
|
||||||
Translate
|
Translate
|
||||||
</UButton>
|
</UButton>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<UButton
|
<UButton @click="goBackToDefault" color="neutral" variant="outline" class="cursor-pointer">
|
||||||
@click="goBackToDefault"
|
|
||||||
color="neutral"
|
|
||||||
variant="outline"
|
|
||||||
class="cursor-pointer"
|
|
||||||
>
|
|
||||||
<UIcon name="i-lucide-arrow-left" class="mr-1" />
|
<UIcon name="i-lucide-arrow-left" class="mr-1" />
|
||||||
<p class="dark:text-white">Back to Polish</p>
|
<p class="dark:text-white">Back to Polish</p>
|
||||||
</UButton>
|
</UButton>
|
||||||
@@ -116,25 +104,34 @@
|
|||||||
<!-- USAGE -->
|
<!-- USAGE -->
|
||||||
<div v-if="activeTab === 'usage'" class="box">
|
<div v-if="activeTab === 'usage'" class="box">
|
||||||
<div class="flex justify-end mb-4 gap-2">
|
<div class="flex justify-end mb-4 gap-2">
|
||||||
<UButton v-if="!isEditing" @click="enableUsageEdit" class="bg-(--accent-blue-light)! dark:bg-(--accent-blue-dark)! text-white px-3 py-1 rounded">
|
<UButton v-if="!isEditing" @click="enableUsageEdit"
|
||||||
|
class="bg-(--accent-blue-light)! dark:bg-(--accent-blue-dark)! text-white px-3 py-1 rounded">
|
||||||
Edit Usage
|
Edit Usage
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton v-if="isEditing" @click="saveUsage" class="px-3 py-1 border rounded">Save</UButton>
|
<UButton v-if="isEditing" @click="saveUsage" class="px-3 py-1 border rounded">Save</UButton>
|
||||||
<UButton v-if="isEditing" @click="cancelUsageEdit" class="px-3 py-1 border rounded">Cancel</UButton>
|
<UButton v-if="isEditing" @click="cancelUsageEdit" class="px-3 py-1 border rounded">Cancel</UButton>
|
||||||
</div>
|
</div>
|
||||||
<p ref="usageRef" v-html="displayedUsage || 'Usage information not available'" class="text-black dark:text-white"></p>
|
<p ref="usageRef" v-html="displayedUsage || 'Usage information not available'"
|
||||||
|
class="text-black dark:text-white">
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- DESCRIPTION -->
|
<!-- DESCRIPTION -->
|
||||||
<div v-if="activeTab === 'description'" class="box">
|
<div v-if="activeTab === 'description'" class="box">
|
||||||
<div class="flex justify-end mb-4 gap-2">
|
<div class="flex justify-end mb-4 gap-2">
|
||||||
<UButton v-if="!descriptionEdit.isEditing.value" @click="enableDescriptionEdit" class="bg-(--accent-blue-light)! dark:bg-(--accent-blue-dark)! text-white px-3 py-1 rounded">
|
<UButton v-if="!descriptionEdit.isEditing.value" @click="enableDescriptionEdit"
|
||||||
|
class="bg-(--accent-blue-light)! dark:bg-(--accent-blue-dark)! text-white px-3 py-1 rounded">
|
||||||
Edit Description
|
Edit Description
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton v-if="descriptionEdit.isEditing.value" @click="saveDescription" class="px-3 py-1 border rounded">Save</UButton>
|
<UButton v-if="descriptionEdit.isEditing.value" @click="saveDescription" class="px-3 py-1 border rounded">
|
||||||
<UButton v-if="descriptionEdit.isEditing.value" @click="cancelDescriptionEdit" class="px-3 py-1 border rounded">Cancel</UButton>
|
Save
|
||||||
|
</UButton>
|
||||||
|
<UButton v-if="descriptionEdit.isEditing.value" @click="cancelDescriptionEdit"
|
||||||
|
class="px-3 py-1 border rounded">
|
||||||
|
Cancel</UButton>
|
||||||
</div>
|
</div>
|
||||||
<div ref="descriptionRef" v-html="displayedDescription || 'Description not available'" class="text-black dark:text-white"></div>
|
<div ref="descriptionRef" v-html="displayedDescription || 'Description not available'"
|
||||||
|
class="text-black dark:text-white"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<p>Country: {{ currentCountry?.name }}</p>
|
<div class="flex flex-col">
|
||||||
<p>Currency: {{ currentCountry?.ps_currency.iso_code }}</p>
|
<p class="text-sm">Country/Currency:</p>
|
||||||
<USelectMenu v-model="country" :items="countries"
|
<USelectMenu v-model="country" :items="countries"
|
||||||
class="w-40 bg-(--main-light) dark:bg-(--black) rounded-md shadow-sm hover:none!" valueKey="id"
|
class="w-44 bg-(--main-light) dark:bg-(--black) rounded-md hover:none! text-sm!" valueKey="id"
|
||||||
:searchInput="false">
|
:searchInput="false">
|
||||||
<template #default="{ modelValue }">
|
<template #default="{ modelValue }">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<span class="font-medium dark:text-white text-black">{{ modelValue.name }}</span>
|
<span class="font-medium dark:text-white text-black whitespace-nowrap">{{ modelValue.name }} / {{
|
||||||
|
currentCountry?.ps_currency.iso_code }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #item-leading="{ item }">
|
<template #item-leading="{ item }">
|
||||||
@@ -15,15 +16,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { countries, currentCountry } from '@/router/langs'
|
import { countries, currentCountry, switchLocalization } from '@/router/langs'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useCookie } from '@/composable/useCookie'
|
import { useCookie } from '@/composable/useCookie'
|
||||||
import { computed, watch } from 'vue'
|
import { computed, watch } from 'vue'
|
||||||
import { i18n } from '@/plugins/02_i18n'
|
|
||||||
import { useFetchJson } from '@/composable/useFetchJson'
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
@@ -34,32 +34,17 @@ const country = computed({
|
|||||||
return currentCountry.value
|
return currentCountry.value
|
||||||
},
|
},
|
||||||
set(value: string) {
|
set(value: string) {
|
||||||
// i18n.locale.value = value
|
|
||||||
currentCountry.value = countries.find((x) => x.id == Number(value))
|
currentCountry.value = countries.find((x) => x.id == Number(value))
|
||||||
cookie.setCookie('country_id', `${countries.find((x) => x.id == Number(value))?.id}`, { days: 60, secure: true, sameSite: 'Lax' })
|
cookie.setCookie('country_id', `${countries.find((x) => x.id == Number(value))?.id}`, { days: 60, secure: true, sameSite: 'Lax' })
|
||||||
|
|
||||||
// changeLang()
|
switchLocalization()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// async function changeLang() {
|
|
||||||
// try {
|
|
||||||
// const { items } = await useFetchJson('/api/v1/public/auth/update-choice', {
|
|
||||||
// method: 'POST'
|
|
||||||
// })
|
|
||||||
|
|
||||||
// } catch (error) {
|
|
||||||
// console.log(error)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => country,
|
() => country,
|
||||||
(newCountry) => {
|
(newCountry) => {
|
||||||
if (newCountry) {
|
if (newCountry) {
|
||||||
console.log(newCountry.value);
|
|
||||||
|
|
||||||
// i18n.locale.value = newLocale
|
|
||||||
currentCountry.value = countries.find((x) => x.id == Number(newCountry.value?.id))
|
currentCountry.value = countries.find((x) => x.id == Number(newCountry.value?.id))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p class="text-sm">Language:</p>
|
||||||
<USelectMenu v-model="locale" :items="langs"
|
<USelectMenu v-model="locale" :items="langs"
|
||||||
class="w-40 bg-(--main-light) dark:bg-(--black) rounded-md shadow-sm hover:none!" valueKey="iso_code"
|
class="w-40 bg-(--main-light) dark:bg-(--black) rounded-md shadow-sm hover:none!" valueKey="iso_code"
|
||||||
:searchInput="false">
|
:searchInput="false">
|
||||||
<template #default="{ modelValue }">
|
<template #default="{ modelValue }">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<!-- <span class="text-md dark:text-white text-black">{{langs.find(x => x.iso_code == modelValue)?.flag}}</span> -->
|
<!-- <span class="text-md dark:text-white text-black">{{langs.find(x => x.iso_code == modelValue)?.flag}}</span> -->
|
||||||
<span class="font-medium dark:text-white text-black">{{langs.find(x => x.iso_code == modelValue)?.name}}</span>
|
<span class="font-medium dark:text-white text-black">{{langs.find(x => x.iso_code ==
|
||||||
|
modelValue)?.name}}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #item-leading="{ item }">
|
<template #item-leading="{ item }">
|
||||||
@@ -15,20 +18,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</USelectMenu>
|
</USelectMenu>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { langs, currentLang } from '@/router/langs'
|
import { langs, currentLang, switchLocalization } from '@/router/langs'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useCookie } from '@/composable/useCookie'
|
import { useCookie } from '@/composable/useCookie'
|
||||||
import { computed, watch } from 'vue'
|
import { computed, watch } from 'vue'
|
||||||
import { i18n } from '@/plugins/02_i18n'
|
import { i18n } from '@/plugins/02_i18n'
|
||||||
import { useFetchJson } from '@/composable/useFetchJson'
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
const cookie = useCookie()
|
const cookie = useCookie()
|
||||||
|
|
||||||
const locale = computed({
|
const locale = computed({
|
||||||
get() {
|
get() {
|
||||||
return currentLang.value?.iso_code || i18n.locale.value
|
return currentLang.value?.iso_code || i18n.locale.value
|
||||||
@@ -52,21 +55,10 @@ const locale = computed({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeLang()
|
switchLocalization()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
async function changeLang() {
|
|
||||||
try {
|
|
||||||
const { items } = await useFetchJson('/api/v1/public/auth/update-choice', {
|
|
||||||
method: 'POST'
|
|
||||||
})
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.params.locale,
|
() => route.params.locale,
|
||||||
(newLocale) => {
|
(newLocale) => {
|
||||||
|
|||||||
@@ -1,9 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<UButton variant="ghost" size="sm" @click="themeStorage.setTheme()">
|
<UButton variant="outline" size="sm" color="info" @click="themeStorage.setTheme()">
|
||||||
<span class="hidden sm:inline">
|
<span class="hidden sm:inline">
|
||||||
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
||||||
</span>
|
</span>
|
||||||
</UButton>
|
</UButton>
|
||||||
|
<!-- <UButton variant="solid" size="sm" color="info" @click="themeStorage.setTheme()">
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
||||||
|
</span>
|
||||||
|
</UButton>
|
||||||
|
<UButton variant="soft" size="sm" color="info" @click="themeStorage.setTheme()">
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
||||||
|
</span>
|
||||||
|
</UButton>
|
||||||
|
<UButton variant="subtle" size="sm" color="info" @click="themeStorage.setTheme()">
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
||||||
|
</span>
|
||||||
|
</UButton>
|
||||||
|
<UButton variant="ghost" size="sm" color="info" @click="themeStorage.setTheme()">
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
||||||
|
</span>
|
||||||
|
</UButton>
|
||||||
|
<UButton variant="link" size="sm" color="info" @click="themeStorage.setTheme()">
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
<UIcon class="size-5" :name="themeStorage.themeIcon" />
|
||||||
|
</span>
|
||||||
|
</UButton> -->
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ async function setRoutes() {
|
|||||||
meta: item.meta ? JSON.parse(item.meta) : {}
|
meta: item.meta ? JSON.parse(item.meta) : {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// await router.replace(router.currentRoute.value.fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
await setRoutes()
|
await setRoutes()
|
||||||
|
|||||||
@@ -51,3 +51,14 @@ export async function initCountryCurrency() {
|
|||||||
console.error('Failed to fetch languages:', error)
|
console.error('Failed to fetch languages:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function switchLocalization() {
|
||||||
|
try {
|
||||||
|
await useFetchJson('/api/v1/public/auth/update-choice', {
|
||||||
|
method: 'POST'
|
||||||
|
})
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user