1313 size =" x-small"
1414 icon
1515 class =" dialogClose"
16- @ click =" drawer = false"
16+ v-on: click =" drawer = false"
1717 variant =" text"
1818 color =" white"
1919 >
2323
2424 <v-list-item
2525 class =" list-item-avatar"
26- :prepend-avatar =" authStore.getUserAvatar"
27- :prepend-icon ="
26+ v-bind :prepend-avatar =" authStore.getUserAvatar"
27+ v-bind :prepend-icon ="
2828 authStore.getUserAvatar === 'default' ? 'mdi-account-circle-outline' : undefined
2929 "
30- :title =" authStore.getUsername"
30+ v-bind :title =" authStore.getUsername"
3131 lines =" two"
3232 color =" white"
3333 ></v-list-item >
3434
3535 <v-list-item >
3636 <v-select
37- :items =" availableLocale"
37+ v-bind :items =" availableLocale"
3838 label =" Locale"
3939 v-model =" locale"
4040 density =" compact"
4848
4949 <v-divider class =" my-2 bg-white" ></v-divider >
5050
51- <!-- Authentication Section -->
5251 <template v-if =" ! authStore .getIsLoggedIn " >
5352 <v-list density =" compact" nav >
5453 <v-list-item
55- @ click.stop =" showAuthModal(true)"
54+ v-on: click =" showAuthModal(true)"
5655 prepend-icon =" mdi-login"
5756 title =" Sign In"
5857 value =" sign_in"
5958 variant =" text"
6059 color =" white"
6160 ></v-list-item >
6261 <v-list-item
63- @ click.stop =" showAuthModal(false)"
62+ v-on: click =" showAuthModal(false)"
6463 prepend-icon =" mdi-account-plus"
6564 title =" Register"
6665 value =" register"
7069 </v-list >
7170 </template >
7271
73- <!-- User Menu Section -->
7472 <template v-else >
7573 <v-list density =" compact" nav >
7674 <v-list-item
77- @ click.stop =" dashboard"
75+ v-on: click =" dashboard"
7876 prepend-icon =" mdi-view-dashboard-outline"
7977 title =" Dashboard"
8078 value =" dashboard"
8179 variant =" text"
8280 color =" white"
8381 ></v-list-item >
8482 <v-list-item
85- @ click.stop =" my_groups"
83+ v-on: click =" my_groups"
8684 prepend-icon =" mdi-account-group-outline"
8785 title =" My Groups"
8886 value =" my_groups"
8987 variant =" text"
9088 color =" white"
9189 ></v-list-item >
9290 <v-list-item
93- @ click.stop =" notifications"
91+ v-on: click =" notifications"
9492 prepend-icon =" mdi-bell-outline"
9593 title =" Notifications"
9694 value =" notifications"
9795 variant =" text"
9896 color =" white"
9997 >
10098 <template v-if =" unreadCount > 0 " v-slot :append >
101- <v-badge :content =" unreadCount" color =" error" ></v-badge >
99+ <v-badge v-bind :content =" unreadCount" color =" error" ></v-badge >
102100 </template >
103101 </v-list-item >
104102 </v-list >
105103
106104 <v-divider class =" my-2 bg-white" ></v-divider >
107105
108106 <v-list-item
109- @ click.stop =" signout"
107+ v-on: click =" signout"
110108 prepend-icon =" mdi-logout"
111109 title =" Logout"
112110 value =" logout"
120118 <v-btn
121119 class =" avatar-btn"
122120 variant =" text"
123- @ click.stop =" drawer = !drawer"
121+ v-on: click =" drawer = !drawer"
124122 rounded =" xl"
125123 color =" white"
126124 >
127125 <v-avatar
128126 v-if =" authStore.getUserAvatar !== 'default'"
129127 size =" 32"
130- :image =" authStore.getUserAvatar"
128+ v-bind :image =" authStore.getUserAvatar"
131129 color =" white"
132130 ></v-avatar >
133131 <v-icon
141139 </v-main >
142140 </v-layout >
143141
144- <!-- Authentication Dialog -->
145142 <v-dialog v-model =" authModal" max-width =" 500" persistent >
146143 <v-card class =" auth-modal" style =" background-color : white " >
147144 <v-toolbar color =" #43b984" >
148145 <v-toolbar-title class =" text-white" >
149146 {{ isLoginMode ? 'Sign In' : 'Register' }}
150147 </v-toolbar-title >
151148 <v-spacer ></v-spacer >
152- <v-btn icon @ click =" authModal = false" color =" white" >
149+ <v-btn icon v-on: click =" authModal = false" color =" white" >
153150 <v-icon >mdi-close</v-icon >
154151 </v-btn >
155152 </v-toolbar >
156153
157154 <v-card-text class =" pa-6" >
158- <v-form @ submit.prevent =" handleAuthSubmit" ref =" authForm" >
155+ <v-form v-on: submit.prevent =" handleAuthSubmit" ref =" authForm" >
159156 <v-text-field
160157 v-if =" !isLoginMode"
161158 v-model =" name"
162159 label =" Name"
163160 type =" text"
164- :rules =" [requiredRule]"
161+ v-bind :rules =" [requiredRule]"
165162 variant =" outlined"
166163 class =" mb-0"
167164 bg-color =" #f0eee6"
171168 v-model =" email"
172169 label =" Email"
173170 type =" email"
174- :rules =" [requiredRule, emailRule]"
171+ v-bind :rules =" [requiredRule, emailRule]"
175172 variant =" outlined"
176173 class =" mb-0"
177174 bg-color =" #f0eee6"
181178 v-model =" password"
182179 label =" Password"
183180 type =" password"
184- :rules =" [requiredRule, passwordRule]"
181+ v-bind :rules =" [requiredRule, passwordRule]"
185182 variant =" outlined"
186183 class =" mb-0"
187184 bg-color =" #f0eee6"
191188 <v-btn
192189 color =" #43b984"
193190 type =" submit"
194- :loading =" isLoading"
195- :disabled =" isLoading"
191+ v-bind :loading =" isLoading"
192+ v-bind :disabled =" isLoading"
196193 size =" large"
197194 block
198195 class =" mb-2"
202199
203200 <v-btn
204201 variant =" text"
205- @ click =" toggleAuthMode"
202+ v-on: click =" toggleAuthMode"
206203 size =" small"
207204 color =" #43b984"
208205 >
214211 </v-card >
215212 </v-dialog >
216213
217- <!-- Snackbar Notification -->
218214 <v-snackbar
219215 v-model =" snackbar.visible"
220- :color =" snackbar.color"
221- :timeout =" 3000"
216+ v-bind :color =" snackbar.color"
217+ v-bind :timeout =" 3000"
222218 location =" bottom right"
223219 >
224220 {{ snackbar.message }}
225221
226222 <template v-slot :actions >
227223 <v-btn
228224 variant =" text"
229- @ click =" snackbar.visible = false"
230- :icon =" mdiClose"
225+ v-on: click =" snackbar.visible = false"
226+ v-bind :icon =" mdiClose"
231227 color =" white"
232228 ></v-btn >
233229 </template >
236232</template >
237233
238234<script lang="ts" setup>
239- import { ref } from ' vue'
235+ import { ref , watch , onMounted } from ' vue'
240236import { useI18n } from ' vue-i18n'
241237import { availableLocale } from ' #/locales/i18n'
242238import { useAuthStore } from ' #/store/authStore'
243239import { mdiClose } from ' @mdi/js'
244- // import { fetch } from '@tauri-apps/plugin-http' // Uncomment if using Tauri's HTTP plugin
245240import ' ./User.scss'
246241
247242const authStore = useAuthStore ()
@@ -256,10 +251,43 @@ const isLoading = ref(false)
256251const authForm = ref ()
257252const unreadCount = ref (0 )
258253
254+ /**
255+ * Watcher to handle language changes:
256+ * 1. Saves preference to localStorage for refresh persistence.
257+ * 2. Updates the document lang and direction (RTL support).
258+ */
259+ watch (locale , function (newLocale ) {
260+ localStorage .setItem (' locale' , newLocale )
261+ document .documentElement .lang = newLocale
262+
263+ if (newLocale === ' ar' ) {
264+ document .documentElement .dir = ' rtl'
265+ } else {
266+ document .documentElement .dir = ' ltr'
267+ }
268+ })
269+
270+ /**
271+ * Lifecycle hook to restore user's language preference on load.
272+ */
273+ onMounted (function () {
274+ const savedLocale = localStorage .getItem (' locale' )
275+ if (savedLocale ) {
276+ locale .value = savedLocale
277+ }
278+
279+ document .documentElement .lang = locale .value
280+ if (locale .value === ' ar' ) {
281+ document .documentElement .dir = ' rtl'
282+ } else {
283+ document .documentElement .dir = ' ltr'
284+ }
285+ })
286+
259287// Form validation rules
260- const requiredRule = (v : string ) => !! v || ' This field is required'
261- const emailRule = (v : string ) => / . + @. + \. . + / .test (v ) || ' E-mail must be valid'
262- const passwordRule = (v : string ) => v .length >= 6 || ' Password must be at least 6 characters'
288+ const requiredRule = function (v : string ) { return !! v || ' This field is required' }
289+ const emailRule = function (v : string ) { return / . + @. + \. . + / .test (v ) || ' E-mail must be valid' }
290+ const passwordRule = function (v : string ) { return v .length >= 6 || ' Password must be at least 6 characters' }
263291
264292// Snackbar state
265293const snackbar = ref ({
@@ -312,13 +340,11 @@ async function handleAuthSubmit() {
312340 } catch (e ) {
313341 errorData = { message: ' An error occurred' }
314342 }
315- console .error (' Authentication failed:' , response .status , errorData )
316343 handleLoginError (response .status , errorData )
317344 return
318345 }
319346
320347 const data = await response .json ()
321- console .log (' Auth successful:' , data )
322348
323349 if (! data .token ) {
324350 throw new Error (' No token received from server' )
@@ -330,8 +356,7 @@ async function handleAuthSubmit() {
330356 ' success'
331357 )
332358 authModal .value = false
333- } catch (error ) {
334- console .error (' Authentication error:' , error )
359+ } catch (error : any ) {
335360 showSnackbar (` Authentication failed: ${error .message } ` , ' error' )
336361 } finally {
337362 isLoading .value = false
@@ -361,7 +386,7 @@ function showSnackbar(message: string, type: 'success' | 'error' | 'warning' | '
361386 snackbar .value = {
362387 visible: true ,
363388 message ,
364- color: type
389+ color: type === ' error ' ? ' #dc5656 ' : ' #43b984 '
365390 }
366391}
367392
@@ -381,4 +406,4 @@ function signout() {
381406 authStore .signOut ()
382407 showSnackbar (' You have been logged out' , ' info' )
383408}
384- </script >
409+ </script >
0 commit comments