Skip to content

Commit 0eb2ae6

Browse files
author
Lasim
committed
feat(frontend): implement settings menu components for client configuration
1 parent e88c5fb commit 0eb2ae6

File tree

6 files changed

+87
-27
lines changed

6 files changed

+87
-27
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script setup lang="ts">
2+
</script>
3+
4+
<template>
5+
<div class="space-y-6">
6+
<slot />
7+
</div>
8+
</template>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script setup lang="ts">
2+
interface Props {
3+
title?: string
4+
}
5+
6+
defineProps<Props>()
7+
</script>
8+
9+
<template>
10+
<div class="space-y-2">
11+
<h3 v-if="title" class="font-semibold text-sm text-muted-foreground pl-3">
12+
{{ title }}
13+
</h3>
14+
<nav class="space-y-1">
15+
<slot />
16+
</nav>
17+
</div>
18+
</template>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<script setup lang="ts">
2+
import { computed, type Component } from 'vue'
3+
import { RouterLink } from 'vue-router'
4+
5+
interface Props {
6+
to: string
7+
active?: boolean
8+
icon?: Component
9+
iconUrl?: string
10+
}
11+
12+
const props = withDefaults(defineProps<Props>(), {
13+
active: false
14+
})
15+
16+
const itemClass = computed(() => [
17+
'flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors',
18+
props.active
19+
? 'bg-secondary text-secondary-foreground font-medium border border-border'
20+
: 'text-muted-foreground hover:bg-secondary/50 hover:text-foreground border border-transparent'
21+
])
22+
</script>
23+
24+
<template>
25+
<RouterLink :to="to" :class="itemClass">
26+
<img
27+
v-if="iconUrl"
28+
:src="iconUrl"
29+
alt=""
30+
class="w-5 h-5 object-contain"
31+
/>
32+
<component
33+
v-else-if="icon"
34+
:is="icon"
35+
class="w-5 h-5"
36+
/>
37+
<slot />
38+
</RouterLink>
39+
</template>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script setup lang="ts">
2+
</script>
3+
4+
<template>
5+
<div class="h-px w-full bg-border" role="separator" />
6+
</template>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export { default as SettingsMenu } from './SettingsMenu.vue'
2+
export { default as SettingsMenuGroup } from './SettingsMenuGroup.vue'
3+
export { default as SettingsMenuItem } from './SettingsMenuItem.vue'
4+
export { default as SettingsMenuSeparator } from './SettingsMenuSeparator.vue'

services/frontend/src/views/client-configuration/index.vue

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<script setup lang="ts">
22
import { ref, onMounted, computed, watch } from 'vue'
3-
import { useRoute, useRouter, RouterLink } from 'vue-router'
3+
import { useRoute, useRouter } from 'vue-router'
44
import { useI18n } from 'vue-i18n'
55
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
66
import { toast } from 'vue-sonner'
77
import DashboardLayout from '@/components/DashboardLayout.vue'
88
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@/components/ui/select'
9+
import { SettingsMenu, SettingsMenuGroup, SettingsMenuItem, SettingsMenuSeparator } from '@/components/ui/settings-menu'
910
import { GatewayConfigService, type ClientConfigResponse, type ConfigAction, type ClientInfo, type ClientCategory } from '@/services/satelliteConfigService'
1011
import LinkActionRenderer from '@/components/client-config/LinkActionRenderer.vue'
1112
import StepsActionRenderer from '@/components/client-config/StepsActionRenderer.vue'
@@ -203,38 +204,22 @@ onMounted(async () => {
203204
<div class="flex flex-col space-y-8 md:flex-row md:space-x-12 md:space-y-0 md:min-h-[calc(100vh-12rem)]">
204205
<!-- Desktop Sidebar Navigation -->
205206
<aside class="hidden md:block md:w-1/5 md:border-r md:pr-8">
206-
<div v-if="!isLoading" class="space-y-6">
207+
<SettingsMenu v-if="!isLoading">
207208
<template v-for="(category, categoryIndex) in clientCategories" :key="category.id">
208-
<div class="space-y-2">
209-
<h3 class="font-semibold text-sm text-muted-foreground pl-3">
210-
{{ category.name }}
211-
</h3>
212-
<nav class="space-y-1">
213-
<RouterLink
209+
<SettingsMenuGroup :title="category.name">
210+
<SettingsMenuItem
214211
v-for="client in category.clients"
215212
:key="client.id"
216213
:to="`/client-configuration/${category.id}/${client.id}`"
217-
class="flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors"
218-
:class="[
219-
selectedClient === client.id && selectedCategory === category.id
220-
? 'bg-secondary text-secondary-foreground font-medium border border-border'
221-
: 'text-muted-foreground hover:bg-secondary/50 hover:text-foreground border border-transparent!'
222-
]"
214+
:icon-url="client.iconPath"
215+
:active="selectedClient === client.id && selectedCategory === category.id"
223216
>
224-
<img
225-
v-if="client.iconPath"
226-
:src="client.iconPath"
227-
:alt="client.name"
228-
class="w-5 h-5 object-contain"
229-
/>
230-
<span>{{ client.name }}</span>
231-
</RouterLink>
232-
</nav>
233-
</div>
234-
<!-- Separator between categories -->
235-
<div v-if="categoryIndex < clientCategories.length - 1" class="h-px w-full bg-border" />
217+
{{ client.name }}
218+
</SettingsMenuItem>
219+
</SettingsMenuGroup>
220+
<SettingsMenuSeparator v-if="categoryIndex < clientCategories.length - 1" />
236221
</template>
237-
</div>
222+
</SettingsMenu>
238223
<div v-else class="text-muted-foreground text-sm">
239224
{{ t('common.common.loading') }}
240225
</div>

0 commit comments

Comments
 (0)