98 lines
3.1 KiB
Vue
98 lines
3.1 KiB
Vue
<script setup lang="ts">
|
|
import {Calendar, Heart, Home, Sparkles, Wallet} from 'lucide-vue-next';
|
|
import { computed, type Component } from 'vue';
|
|
import { useI18n } from '../i18n';
|
|
|
|
interface NavItem {
|
|
icon: Component;
|
|
labelKey: string;
|
|
id: string;
|
|
}
|
|
|
|
const props = defineProps<{
|
|
activeScreen: string;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
navigate: [screen: string];
|
|
}>();
|
|
const { t } = useI18n();
|
|
|
|
const navItems: NavItem[] = [
|
|
{ icon: Calendar, labelKey: 'nav.calendar', id: 'calendar' },
|
|
{ icon: Wallet, labelKey: 'nav.finance', id: 'finance' },
|
|
{ icon: Home, labelKey: 'nav.home', id: 'home' },
|
|
{ icon: Heart, labelKey: 'nav.votes', id: 'votes' },
|
|
{ icon: Sparkles, labelKey: 'nav.intimacy', id: 'intimacy' },
|
|
];
|
|
|
|
const localizedNavItems = computed(() =>
|
|
navItems.map((item) => ({
|
|
...item,
|
|
label: t(item.labelKey),
|
|
})),
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<nav class="pointer-events-none fixed bottom-0 left-0 right-0 mx-auto max-w-md px-5 pb-5">
|
|
<div class="pointer-events-auto rounded-[20px] border border-white/[0.08] bg-[#1A1A24]/95 px-2 py-3 shadow-[0_8px_32px_rgba(0,0,0,0.6)] backdrop-blur-xl">
|
|
<div class="flex items-center justify-between">
|
|
<button
|
|
v-for="item in localizedNavItems"
|
|
:key="item.id"
|
|
type="button"
|
|
@click="emit('navigate', item.id)"
|
|
:class="[
|
|
'relative flex flex-col items-center gap-1.5 py-2 transition-all',
|
|
item.id === 'home' ? 'px-5' : 'px-3',
|
|
]"
|
|
>
|
|
<div
|
|
v-if="props.activeScreen === item.id"
|
|
class="absolute inset-0 rounded-[14px] border border-purple-500/20 bg-gradient-to-br from-purple-500/15 to-blue-500/15"
|
|
/>
|
|
|
|
<div
|
|
v-if="item.id === 'home'"
|
|
:class="[
|
|
'relative z-10 flex h-12 w-12 items-center justify-center rounded-full transition-all',
|
|
props.activeScreen === item.id
|
|
? 'bg-gradient-to-br from-purple-500 to-blue-600 shadow-lg shadow-purple-500/30'
|
|
: 'bg-zinc-800',
|
|
]"
|
|
>
|
|
<component
|
|
:is="item.icon"
|
|
:class="[
|
|
'h-6 w-6',
|
|
props.activeScreen === item.id ? 'text-white' : 'text-zinc-400',
|
|
]"
|
|
:stroke-width="props.activeScreen === item.id ? 2.5 : 2"
|
|
/>
|
|
</div>
|
|
|
|
<template v-else>
|
|
<component
|
|
:is="item.icon"
|
|
:class="[
|
|
'relative z-10 h-5 w-5 transition-colors',
|
|
props.activeScreen === item.id ? 'text-purple-400' : 'text-zinc-500',
|
|
]"
|
|
:stroke-width="props.activeScreen === item.id ? 2.5 : 2"
|
|
/>
|
|
<span
|
|
:class="[
|
|
'relative z-10 text-[10px] font-medium transition-colors',
|
|
props.activeScreen === item.id ? 'text-purple-400' : 'text-zinc-600',
|
|
]"
|
|
>
|
|
{{ item.label }}
|
|
</span>
|
|
</template>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</template>
|