22import { ref , onMounted , computed , watch } from ' vue'
33import { useRoute } from ' vue-router'
44import { useI18n } from ' vue-i18n'
5+ import { toast } from ' vue-sonner'
56import { useEventBus } from ' @/composables/useEventBus'
67import GlobalSettingsSidebarNav , { type GlobalSettingGroup } from ' @/components/settings/GlobalSettingsSidebarNav.vue'
78import DashboardLayout from ' @/components/DashboardLayout.vue'
89import { getEnv } from ' @/utils/env'
9- import { Alert , AlertDescription , AlertTitle } from ' @/components/ui/alert'
10- import { CheckCircle2Icon , XIcon } from ' lucide-vue-next'
10+
1111import {
1212 Card ,
1313 CardContent ,
@@ -23,21 +23,20 @@ const route = useRoute()
2323const settingGroups = ref <GlobalSettingGroup []>([])
2424const isLoading = ref (true )
2525const error = ref <string | null >(null )
26- const showSuccessAlert = ref (false )
27- const successAlertMessage = ref (' ' )
26+
2827
2928const apiUrl = getEnv (' VITE_DEPLOYSTACK_BACKEND_URL' ) || ' ' // Fallback to empty string if not set
3029
3130// Placeholder for the actual API call
3231async function fetchSettingGroupsApi(): Promise <GlobalSettingGroup []> {
3332 if (! apiUrl ) {
34- throw new Error (' VITE_DEPLOYSTACK_BACKEND_URL is not configured. ' )
33+ throw new Error (t ( ' globalSettings.errors.configNotSet ' ) )
3534 }
3635 const response = await fetch (` ${apiUrl }/api/settings/groups ` , { credentials: ' include' })
3736
3837 if (! response .ok ) {
3938 const errorData = await response .json ().catch (() => ({}))
40- throw new Error (errorData .message || ` Failed to fetch setting groups : ${response .statusText } (status: ${response .status })` )
39+ throw new Error (errorData .message || ` ${ t ( ' globalSettings.errors.fetchFailed ' )} : ${response .statusText } (status: ${response .status })` )
4140 }
4241
4342 const result = await response .json ()
@@ -62,7 +61,7 @@ onMounted(async () => {
6261 settingGroups .value = fetchedGroups // Direct assignment is fine now
6362 error .value = null
6463 } catch (err ) {
65- error .value = err instanceof Error ? err .message : ' An unknown error occurred '
64+ error .value = err instanceof Error ? err .message : t ( ' globalSettings.errors.unknownError ' )
6665 settingGroups .value = [] // Clear or set to empty on error
6766 } finally {
6867 isLoading .value = false
@@ -108,9 +107,10 @@ function handleSettingsUpdated(updatedSettings: Setting[]) {
108107 settingGroups .value = newSettingGroups
109108 }
110109
111- // Show success message
112- successAlertMessage .value = t (' globalSettings.alerts.saveSuccess' )
113- showSuccessAlert .value = true
110+ // Show success message with Sonner toast
111+ toast .success (t (' globalSettings.alerts.successTitle' ), {
112+ description: t (' globalSettings.alerts.saveSuccess' )
113+ })
114114
115115 // Emit event for other components
116116 eventBus .emit (' settings-updated' )
@@ -161,10 +161,7 @@ function createInitialValues(settings: Setting[]) {
161161 return values
162162}
163163
164- // Watch for route changes and reset success alert
165- watch (() => route .params .groupId , () => {
166- showSuccessAlert .value = false
167- })
164+
168165
169166// Watch for group changes and set form values
170167watch (() => selectedGroup .value , (newGroup ) => {
@@ -206,7 +203,7 @@ async function handleSubmit(event: Event) {
206203
207204 try {
208205 if (! apiUrl ) {
209- throw new Error (' VITE_DEPLOYSTACK_BACKEND_URL is not configured for saving settings. ' )
206+ throw new Error (t ( ' globalSettings.errors.savingConfigNotSet ' ) )
210207 }
211208
212209 const requestBody = { settings: settingsToUpdate }
@@ -222,18 +219,21 @@ async function handleSubmit(event: Event) {
222219
223220 if (! response .ok ) {
224221 const errorData = await response .json ().catch (() => ({}))
225- throw new Error (errorData .error || errorData .message || ` Failed to save settings : ${response .statusText } (status: ${response .status })` )
222+ throw new Error (errorData .error || errorData .message || ` ${ t ( ' globalSettings.errors.saveSettings ' )} : ${response .statusText } (status: ${response .status })` )
226223 }
227224
228225
229226
230227 const result = await response .json ()
231228
232229 if (! result .success ) {
233- throw new Error (result .message || ' Failed to save settings due to an API error. ' )
230+ throw new Error (result .message || t ( ' globalSettings.errors.saveFailed ' ) )
234231 }
235- successAlertMessage .value = t (' globalSettings.alerts.saveSuccess' )
236- showSuccessAlert .value = true
232+
233+ // Show success message with Sonner toast
234+ toast .success (t (' globalSettings.alerts.successTitle' ), {
235+ description: t (' globalSettings.alerts.saveSuccess' )
236+ })
237237
238238 // Update local state
239239 const groupIndex = settingGroups .value .findIndex (g => g .id === selectedGroup .value ?.id )
@@ -253,8 +253,15 @@ async function handleSubmit(event: Event) {
253253 settingGroups .value = newSettingGroups
254254 }
255255
256+ // Emit event for other components
257+ eventBus .emit (' settings-updated' )
258+
256259 } catch (err ) {
257- // Handle save error silently or show user-friendly error message
260+ // Show error toast with meaningful message
261+ const errorMessage = err instanceof Error ? err .message : t (' globalSettings.errors.unknownError' )
262+ toast .error (t (' globalSettings.errors.saveSettings' ), {
263+ description: errorMessage
264+ })
258265 console .error (' Failed to save settings:' , err )
259266 }
260267}
@@ -271,25 +278,8 @@ async function handleSubmit(event: Event) {
271278 </aside >
272279 <div class =" flex-1 lg:max-w-3xl" >
273280
274- <Alert v-if =" showSuccessAlert" variant =" default" class =" mb-8 border-green-500 bg-green-50 text-green-700 relative" >
275- <CheckCircle2Icon class =" h-5 w-5 text-green-600" />
276- <AlertTitle class =" font-semibold text-green-800" >{{ t('globalSettings.alerts.successTitle') }}</AlertTitle >
277- <AlertDescription >
278- {{ successAlertMessage }}
279- </AlertDescription >
280- <Button
281- variant =" ghost"
282- size =" sm"
283- class =" absolute top-2 right-2 p-1 h-auto text-green-700 hover:bg-green-100"
284- @click =" showSuccessAlert = false"
285- aria-label =" Dismiss success alert"
286- >
287- <XIcon class =" h-4 w-4" />
288- </Button >
289- </Alert >
290-
291- <div v-if =" isLoading" class =" text-muted-foreground" >Loading settings...</div >
292- <div v-else-if =" error" class =" text-red-500" >Error loading settings: {{ error }}</div >
281+ <div v-if =" isLoading" class =" text-muted-foreground" >{{ t('globalSettings.loading') }}</div >
282+ <div v-else-if =" error" class =" text-red-500" >{{ t('globalSettings.errors.loadSettings') }}: {{ error }}</div >
293283
294284
295285 <div v-else-if =" selectedGroup" class =" space-y-6" >
@@ -348,29 +338,29 @@ async function handleSubmit(event: Event) {
348338 />
349339 </div >
350340
351- <p v-if =" setting.is_encrypted" class =" text-xs text-muted-foreground" >This value is encrypted. </p >
341+ <p v-if =" setting.is_encrypted" class =" text-xs text-muted-foreground" >{{ t('globalSettings.form.encryptedValue') }} </p >
352342 </div >
353343
354344 <Button type =" submit" >
355- Save Changes
345+ {{ t('globalSettings.form.saveChanges') }}
356346 </Button >
357347 </form >
358348 <div v-else-if =" selectedGroup && (!selectedGroup.settings || selectedGroup.settings.length === 0)" >
359- <p class =" text-sm text-muted-foreground" >No settings in this group. </p >
349+ <p class =" text-sm text-muted-foreground" >{{ t('globalSettings.form.noSettings') }} </p >
360350 </div >
361351 <div v-else >
362- <p class =" text-sm text-muted-foreground" >Group not found or settings unavailable. </p >
352+ <p class =" text-sm text-muted-foreground" >{{ t('globalSettings.form.groupNotFound') }} </p >
363353 </div >
364354 </CardContent >
365355 </Card >
366356 </div >
367357
368358
369359 <div v-else-if =" !currentGroupId && settingGroups.length > 0" >
370- <p class =" text-muted-foreground" >Select a category from the sidebar to view its settings. </p >
360+ <p class =" text-muted-foreground" >{{ t('globalSettings.form.selectCategory') }} </p >
371361 </div >
372362 <div v-else-if =" !currentGroupId && settingGroups.length === 0 && !isLoading" >
373- <p class =" text-muted-foreground" >No setting groups found. </p >
363+ <p class =" text-muted-foreground" >{{ t('globalSettings.form.noGroups') }} </p >
374364 </div >
375365 </div >
376366 </div >
0 commit comments