feat(ui): copy logistics header/theme one-to-one

This commit is contained in:
Ruslan Bakiev
2026-04-21 10:34:54 +07:00
parent 670e9b7fd1
commit d3183bf6ad
11 changed files with 1052 additions and 236 deletions

View File

@@ -0,0 +1,70 @@
type LocalizedRouteTarget = string | {
path?: string
name?: string
params?: Record<string, unknown>
query?: Record<string, unknown>
hash?: string
}
// This composable is used in route middleware, where `useI18n()` is not available.
const LOCALE_CODES = ['ru', 'en']
function normalizePath(path: string) {
return path || '/'
}
export function stripLocalePrefix(path: string, localeCodes: string[]) {
const normalizedPath = normalizePath(path)
const localePattern = localeCodes.map(code => code.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')
if (!localePattern) return normalizedPath
const match = normalizedPath.match(new RegExp(`^/(${localePattern})(?=/|$)`))
if (!match) return normalizedPath
const nextPath = normalizedPath.slice(match[0].length)
return nextPath || '/'
}
export function useLocalizedNavigation() {
const route = useRoute()
const localePath = useLocalePath()
const basePath = computed(() => stripLocalePrefix(route.path, LOCALE_CODES))
function toLocalized(to: LocalizedRouteTarget) {
if (typeof to === 'string') {
return to.startsWith('/') ? localePath(to) : to
}
if (to.path) {
return {
...to,
path: to.path.startsWith('/') ? localePath(to.path) : to.path,
}
}
return to
}
function isBasePathActive(target: string, exact = false) {
const normalizedTarget = normalizePath(target)
if (exact) {
return basePath.value === normalizedTarget
}
return basePath.value === normalizedTarget || basePath.value.startsWith(`${normalizedTarget}/`)
}
function navigateToLocalized(to: LocalizedRouteTarget, options?: Parameters<typeof navigateTo>[1]) {
return navigateTo(toLocalized(to), options)
}
return {
basePath,
isBasePathActive,
localePath,
navigateToLocalized,
toLocalized,
}
}