Merge branch 'front-styles' of ssh://git.ma-al.com:8822/goc_daniel/b2b into translate
This commit is contained in:
7
bo/components.d.ts
vendored
7
bo/components.d.ts
vendored
@@ -12,13 +12,14 @@ export {}
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
CartDetails: typeof import('./src/components/customer/CartDetails.vue')['default']
|
||||
CategoryMenu: typeof import('./src/components/inner/categoryMenu.vue')['default']
|
||||
CategoryMenu: typeof import('./src/components/inner/CategoryMenu.vue')['default']
|
||||
CategoryMenuListing: typeof import('./src/components/inner/categoryMenuListing.vue')['default']
|
||||
CountryCurrencySwitch: typeof import('./src/components/inner/CountryCurrencySwitch.vue')['default']
|
||||
Cs_PrivacyPolicyView: typeof import('./src/components/terms/cs_PrivacyPolicyView.vue')['default']
|
||||
Cs_TermsAndConditionsView: typeof import('./src/components/terms/cs_TermsAndConditionsView.vue')['default']
|
||||
En_PrivacyPolicyView: typeof import('./src/components/terms/en_PrivacyPolicyView.vue')['default']
|
||||
En_TermsAndConditionsView: typeof import('./src/components/terms/en_TermsAndConditionsView.vue')['default']
|
||||
LangSwitch: typeof import('./src/components/inner/langSwitch.vue')['default']
|
||||
LangSwitch: typeof import('./src/components/inner/LangSwitch.vue')['default']
|
||||
PageAddresses: typeof import('./src/components/customer/PageAddresses.vue')['default']
|
||||
PageCarts: typeof import('./src/components/customer/PageCarts.vue')['default']
|
||||
PageOrders: typeof import('./src/components/customer/PageOrders.vue')['default']
|
||||
@@ -34,7 +35,7 @@ declare module 'vue' {
|
||||
ProductVariants: typeof import('./src/components/customer/components/ProductVariants.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
ThemeSwitch: typeof import('./src/components/inner/themeSwitch.vue')['default']
|
||||
ThemeSwitch: typeof import('./src/components/inner/ThemeSwitch.vue')['default']
|
||||
TopBar: typeof import('./src/components/TopBar.vue')['default']
|
||||
TopBarLogin: typeof import('./src/components/TopBarLogin.vue')['default']
|
||||
UAlert: typeof import('./node_modules/@nuxt/ui/dist/runtime/components/Alert.vue')['default']
|
||||
|
||||
@@ -1,13 +1,49 @@
|
||||
<template>
|
||||
<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)">
|
||||
<!-- px-4 sm:px-6 lg:px-8 -->
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="flex items-center justify-between h-14">
|
||||
<!-- Logo -->
|
||||
<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">
|
||||
<UIcon name="i-heroicons-clock" class="w-5 h-5" />
|
||||
</div>
|
||||
<span class="font-semibold text-gray-900 dark:text-white">TimeTracker</span>
|
||||
</RouterLink>
|
||||
|
||||
<UNavigationMenu :type="'trigger'" :ui="{
|
||||
root: 'justify-center',
|
||||
list: 'gap-4'
|
||||
}" :items="menuItems" class="w-full"></UNavigationMenu>
|
||||
<div class="flex items-center gap-2">
|
||||
<CountryCurrencySwitch />
|
||||
<!-- Language Switcher -->
|
||||
<LangSwitch />
|
||||
<!-- Theme Switcher -->
|
||||
<ThemeSwitch />
|
||||
<!-- Logout Button (only when authenticated) -->
|
||||
<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)">
|
||||
{{ $t('general.logout') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFetchJson } from '@/composable/useFetchJson'
|
||||
import LangSwitch from './inner/langSwitch.vue'
|
||||
import ThemeSwitch from './inner/themeSwitch.vue'
|
||||
import LangSwitch from './inner/LangSwitch.vue'
|
||||
import ThemeSwitch from './inner/ThemeSwitch.vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { currentLang } from '@/router/langs'
|
||||
import type { LabelTrans, TopMenuItem } from '@/types'
|
||||
import type { NavigationMenuItem } from '@nuxt/ui'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import CountryCurrencySwitch from './inner/CountryCurrencySwitch.vue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
let menu = ref()
|
||||
@@ -51,37 +87,3 @@ function transformMenu(items: TopMenuItem[], locale: string | undefined): Naviga
|
||||
}
|
||||
await getTopMenu()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<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)">
|
||||
<!-- px-4 sm:px-6 lg:px-8 -->
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="flex items-center justify-between h-14">
|
||||
<!-- Logo -->
|
||||
<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">
|
||||
<UIcon name="i-heroicons-clock" class="w-5 h-5" />
|
||||
</div>
|
||||
<span class="font-semibold text-gray-900 dark:text-white">TimeTracker</span>
|
||||
</RouterLink>
|
||||
|
||||
<UNavigationMenu :type="'trigger'" :ui="{
|
||||
root: 'justify-center',
|
||||
list: 'gap-4'
|
||||
}" :items="menuItems" class="w-full"></UNavigationMenu>
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Language Switcher -->
|
||||
<LangSwitch />
|
||||
<!-- Theme Switcher -->
|
||||
<ThemeSwitch />
|
||||
<!-- Logout Button (only when authenticated) -->
|
||||
<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)">
|
||||
{{ $t('general.logout') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import LangSwitch from './inner/langSwitch.vue'
|
||||
import ThemeSwitch from './inner/themeSwitch.vue'
|
||||
import LangSwitch from './inner/LangSwitch.vue'
|
||||
import ThemeSwitch from './inner/ThemeSwitch.vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useFetchJson } from '@/composable/useFetchJson'
|
||||
import Default from '@/layouts/default.vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { TableColumn } from '@nuxt/ui'
|
||||
import CategoryMenu from '../inner/categoryMenu.vue'
|
||||
import CategoryMenu from '../inner/CategoryMenu.vue'
|
||||
import type { Product } from '@/types/product'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -46,7 +46,7 @@ import { useFetchJson } from '@/composable/useFetchJson'
|
||||
import Default from '@/layouts/default.vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import type { TableColumn } from '@nuxt/ui'
|
||||
import CategoryMenu from '../inner/categoryMenu.vue'
|
||||
import CategoryMenu from '../inner/CategoryMenu.vue'
|
||||
|
||||
interface Product {
|
||||
reference: number
|
||||
|
||||
68
bo/src/components/inner/CountryCurrencySwitch.vue
Normal file
68
bo/src/components/inner/CountryCurrencySwitch.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<p>Country: {{ currentCountry?.name }}</p>
|
||||
<p>Currency: {{ currentCountry?.ps_currency.iso_code }}</p>
|
||||
<USelectMenu v-model="country" :items="countries"
|
||||
class="w-40 bg-(--main-light) dark:bg-(--black) rounded-md shadow-sm hover:none!" valueKey="id"
|
||||
:searchInput="false">
|
||||
<template #default="{ modelValue }">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="font-medium dark:text-white text-black">{{ modelValue.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #item-leading="{ item }">
|
||||
<div class="flex items-center rounded-md cursor-pointer transition-colors">
|
||||
<span class="ml-2 dark:text-white text-black font-medium">{{ item.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { countries, currentCountry } from '@/router/langs'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useCookie } from '@/composable/useCookie'
|
||||
import { computed, watch } from 'vue'
|
||||
import { i18n } from '@/plugins/02_i18n'
|
||||
import { useFetchJson } from '@/composable/useFetchJson'
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const cookie = useCookie()
|
||||
|
||||
const country = computed({
|
||||
get() {
|
||||
return currentCountry.value
|
||||
},
|
||||
set(value: string) {
|
||||
// i18n.locale.value = 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' })
|
||||
|
||||
// changeLang()
|
||||
},
|
||||
})
|
||||
|
||||
// async function changeLang() {
|
||||
// try {
|
||||
// const { items } = await useFetchJson('/api/v1/public/auth/update-choice', {
|
||||
// method: 'POST'
|
||||
// })
|
||||
|
||||
// } catch (error) {
|
||||
// console.log(error)
|
||||
// }
|
||||
// }
|
||||
|
||||
watch(
|
||||
() => country,
|
||||
(newCountry) => {
|
||||
if (newCountry) {
|
||||
console.log(newCountry.value);
|
||||
|
||||
// i18n.locale.value = newLocale
|
||||
currentCountry.value = countries.find((x) => x.id == Number(newCountry.value?.id))
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
@@ -1,11 +1,12 @@
|
||||
|
||||
import { useFetchJson } from '@/composable/useFetchJson'
|
||||
import { initLangs, langs } from '@/router/langs'
|
||||
import { initCountryCurrency, initLangs, langs } from '@/router/langs'
|
||||
import { watch } from 'vue'
|
||||
import { createI18n, type PathValue } from 'vue-i18n'
|
||||
|
||||
// const x =
|
||||
await initLangs()
|
||||
await initCountryCurrency()
|
||||
export const i18ninstall = createI18n({
|
||||
legacy: false, // you must set `false`, to use Composition API
|
||||
locale: 'en',
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { useCookie } from "@/composable/useCookie"
|
||||
import { useFetchJson } from "@/composable/useFetchJson"
|
||||
import type { Language } from "@/types"
|
||||
import type { Country, Language } from "@/types"
|
||||
import { reactive, ref } from "vue"
|
||||
|
||||
export const langs = reactive([] as Language[])
|
||||
export const currentLang = ref<Language>()
|
||||
|
||||
const deflang = ref<Language>()
|
||||
export const countries = reactive([] as Country[])
|
||||
export const currentCountry = ref<Country>()
|
||||
|
||||
const defLang = ref<Language>()
|
||||
const defCountry = ref<Country>()
|
||||
const cookie = useCookie()
|
||||
// Get available language codes for route matching
|
||||
// export const availableLocales = computed(() => langs.map((l) => l.lang_code))
|
||||
@@ -22,8 +26,27 @@ export async function initLangs() {
|
||||
if (cc) {
|
||||
idfromcookie = langs.find((x) => x.id == parseInt(cc))
|
||||
}
|
||||
deflang.value = items.find((x) => x.is_default == true)
|
||||
currentLang.value = idfromcookie ?? deflang.value
|
||||
defLang.value = items.find((x) => x.is_default == true)
|
||||
currentLang.value = idfromcookie ?? defLang.value
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch languages:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize country/currency from API
|
||||
|
||||
export async function initCountryCurrency() {
|
||||
try {
|
||||
const { items } = await useFetchJson<Country[]>('/api/v1/restricted/langs-and-countries/get-countries')
|
||||
countries.push(...items)
|
||||
|
||||
let idfromcookie = null
|
||||
const cc = cookie.getCookie('country_id')
|
||||
if (cc) {
|
||||
idfromcookie = langs.find((x) => x.id == parseInt(cc))
|
||||
}
|
||||
defCountry.value = items.find((x) => x.id === defLang.value?.id)
|
||||
currentCountry.value = idfromcookie ?? defCountry.value
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch languages:', error)
|
||||
}
|
||||
|
||||
17
bo/src/types/lang.d.ts
vendored
17
bo/src/types/lang.d.ts
vendored
@@ -12,3 +12,20 @@ export interface Language {
|
||||
active: boolean
|
||||
flag: string
|
||||
}
|
||||
|
||||
export interface Country {
|
||||
id: number
|
||||
name: string
|
||||
flag: string
|
||||
currency_id: string
|
||||
ps_currency: {
|
||||
id_currency: string
|
||||
name: string
|
||||
iso_code: string
|
||||
numeric_iso_code: string
|
||||
precision: number
|
||||
conversion_rate: number
|
||||
deleted: boolean
|
||||
active: boolean
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user