11<script setup lang="ts">
2- import { Button } from ' @/components/ui/button' ;
3- import { Card , CardContent , CardDescription , CardHeader , CardTitle } from ' @/components/ui/card' ;
4- import { DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuTrigger } from ' @/components/ui/dropdown-menu' ;
5- import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from ' @/components/ui/select' ;
62import { useLocale } from ' @/composables/useLocale' ;
73import { router , usePage } from ' @inertiajs/vue3' ;
8- import { Globe } from ' lucide-vue-next' ;
9- import { computed , watch } from ' vue' ;
4+ import { computed , defineAsyncComponent , watch } from ' vue' ;
105import { useI18n } from ' vue-i18n' ;
116
127interface Props {
138 display? : ' dropdown' | ' select' | ' cards' ;
149}
1510
16- withDefaults (defineProps <Props >(), {
17- display: ' dropdown' ,
18- });
19-
20- const { t, locale } = useI18n ();
11+ const { locale } = useI18n ();
2112const page = usePage ();
2213const { initializeLocale } = useLocale ();
2314
24- const availableLocales = page .props .locale .available ;
15+ const availableLocales = ( page .props .locale as any ) .available ;
2516
2617const capitalize = (s : string ) => (s ? s .charAt (0 ).toUpperCase () + s .slice (1 ) : s );
2718
@@ -31,7 +22,7 @@ const languages = availableLocales.map((code: string) => {
3122});
3223
3324const currentLanguage = computed (() => {
34- return languages .find ((lang ) => lang .code === locale .value ) || languages [0 ];
25+ return languages .find ((lang : any ) => lang .code === locale .value ) || languages [0 ];
3526});
3627
3728watch (locale , async (newLocale , oldLocale ) => {
@@ -65,75 +56,23 @@ const syncLocaleWithBackend = async (langCode: string) => {
6556const switchLanguage = async (langCode : string ) => {
6657 locale .value = langCode ;
6758};
68- </script >
6959
70- <template >
71- <!-- Dropdown Display (Default) -->
72- <DropdownMenu v-if =" display === 'dropdown'" >
73- <DropdownMenuTrigger as-child >
74- <Button variant =" ghost" size =" icon" class =" h-8 w-8 p-0" >
75- <Globe class =" h-4 w-4 text-foreground" />
76- <span class =" sr-only" >{{ t('common.switchLanguage') }}</span >
77- </Button >
78- </DropdownMenuTrigger >
79- <DropdownMenuContent align =" end" >
80- <DropdownMenuItem
81- v-for =" language in languages"
82- :key =" language.code"
83- @click =" switchLanguage(language.code)"
84- :class =" { 'bg-accent': language.code === currentLanguage.code }"
85- >
86- {{ language.name }}
87- </DropdownMenuItem >
88- </DropdownMenuContent >
89- </DropdownMenu >
60+ // Dynamic component mapping
61+ const componentMap = {
62+ dropdown: defineAsyncComponent (() => import (' ./LanguageSwitcherDropdown.vue' )),
63+ select: defineAsyncComponent (() => import (' ./LanguageSwitcherSelect.vue' )),
64+ cards: defineAsyncComponent (() => import (' ./LanguageSwitcherCards.vue' )),
65+ };
9066
91- <!-- Select Display -->
92- <Select v-else-if =" display === 'select'" v-model =" locale" >
93- <SelectTrigger class =" w-[180px]" >
94- <SelectValue class =" text-foreground" >
95- <span class =" flex items-center gap-2" >
96- <span class =" text-foreground" >{{ currentLanguage.name }}</span >
97- </span >
98- </SelectValue >
99- </SelectTrigger >
100- <SelectContent >
101- <SelectItem v-for =" language in languages" :key =" language.code" :value =" language.code" >
102- <span class =" flex items-center gap-2" >
103- <span >{{ language.name }}</span >
104- </span >
105- </SelectItem >
106- </SelectContent >
107- </Select >
67+ const props = withDefaults (defineProps <Props >(), {
68+ display: ' dropdown' ,
69+ });
70+
71+ const currentComponent = computed (() => {
72+ return componentMap [props .display as keyof typeof componentMap ] || componentMap .dropdown ;
73+ });
74+ </script >
10875
109- <!-- Card Display -->
110- <Card v-else-if =" display === 'cards'" >
111- <CardHeader >
112- <CardTitle class =" flex items-center gap-2" >
113- <Globe class =" h-5 w-5" />
114- {{ t('settings.language.title') }}
115- </CardTitle >
116- <CardDescription >
117- {{ t('settings.language.description') }}
118- </CardDescription >
119- </CardHeader >
120- <CardContent >
121- <div class =" grid gap-3" >
122- <Button
123- v-for =" language in languages"
124- :key =" language.code"
125- @click =" switchLanguage(language.code)"
126- variant =" outline"
127- :class =" ['justify-start', language.code === currentLanguage.code ? 'border-primary bg-primary/5' : 'hover:bg-muted']"
128- >
129- <div class =" flex w-full items-center justify-between" >
130- <span class =" font-medium" >{{ language.name }}</span >
131- <span v-if =" language.code === currentLanguage.code" class =" text-xs text-muted-foreground" >
132- {{ t('settings.language.currentLanguage') }}
133- </span >
134- </div >
135- </Button >
136- </div >
137- </CardContent >
138- </Card >
76+ <template >
77+ <component :is =" currentComponent" :languages =" languages" :current-language =" currentLanguage" :locale =" locale" @switch-language =" switchLanguage" />
13978</template >
0 commit comments