@htlkg/components 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,59 @@
1
- import { describe, it, expect, beforeEach } from 'vitest';
2
- import { mount } from '@vue/test-utils';
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { shallowMount } from '@vue/test-utils';
3
+ import { h, defineComponent } from 'vue';
4
+
5
+ // Mock the @hotelinking/ui module
6
+ vi.mock('@hotelinking/ui', () => ({
7
+ uiInput: defineComponent({
8
+ name: 'uiInput',
9
+ props: ['name', 'label', 'type', 'value', 'placeholder', 'error', 'color', 'loading', 'requiredText', 'min', 'max'],
10
+ emits: ['input-changed'],
11
+ setup(props, { emit }) {
12
+ return () => h('div', { class: 'ui-input' });
13
+ }
14
+ }),
15
+ uiSelect: defineComponent({
16
+ name: 'uiSelect',
17
+ props: ['label', 'items', 'select', 'placeholder', 'error', 'color', 'loading', 'requiredText'],
18
+ emits: ['select-changed'],
19
+ setup() {
20
+ return () => h('div', { class: 'ui-select' });
21
+ }
22
+ }),
23
+ uiToggle: defineComponent({
24
+ name: 'uiToggle',
25
+ props: ['item', 'checked', 'loading'],
26
+ emits: ['toggle-changed'],
27
+ setup() {
28
+ return () => h('div', { class: 'ui-toggle' });
29
+ }
30
+ }),
31
+ uiTextArea: defineComponent({
32
+ name: 'uiTextArea',
33
+ props: ['name', 'label', 'value', 'placeholder', 'error', 'color', 'loading', 'requiredText', 'rows'],
34
+ emits: ['input-changed'],
35
+ setup() {
36
+ return () => h('div', { class: 'ui-textarea' });
37
+ }
38
+ }),
39
+ uiRangeSlider: defineComponent({
40
+ name: 'uiRangeSlider',
41
+ props: ['label', 'min', 'max', 'sliderValue', 'loading', 'requiredText'],
42
+ emits: ['sliderUpdated'],
43
+ setup() {
44
+ return () => h('div', { class: 'ui-slider' });
45
+ }
46
+ }),
47
+ uiButton: defineComponent({
48
+ name: 'uiButton',
49
+ props: ['type', 'color', 'loading', 'disabled'],
50
+ setup(props, { slots }) {
51
+ return () => h('button', { class: 'ui-button', type: props.type }, slots.default?.());
52
+ }
53
+ })
54
+ }));
55
+
56
+ // Import after mocking
3
57
  import JsonSchemaForm from './JsonSchemaForm.vue';
4
58
 
5
59
  /**
@@ -16,7 +70,7 @@ describe('JsonSchemaForm unit tests', () => {
16
70
  }
17
71
  };
18
72
 
19
- const wrapper = mount(JsonSchemaForm, {
73
+ const wrapper = shallowMount(JsonSchemaForm, {
20
74
  props: { schema, modelValue: {} }
21
75
  });
22
76
 
@@ -32,7 +86,7 @@ describe('JsonSchemaForm unit tests', () => {
32
86
  }
33
87
  };
34
88
 
35
- const wrapper = mount(JsonSchemaForm, {
89
+ const wrapper = shallowMount(JsonSchemaForm, {
36
90
  props: { schema, modelValue: {} }
37
91
  });
38
92
 
@@ -46,7 +100,7 @@ describe('JsonSchemaForm unit tests', () => {
46
100
  properties: {}
47
101
  };
48
102
 
49
- const wrapper = mount(JsonSchemaForm, {
103
+ const wrapper = shallowMount(JsonSchemaForm, {
50
104
  props: { schema, modelValue: {} }
51
105
  });
52
106
 
@@ -67,7 +121,7 @@ describe('JsonSchemaForm unit tests', () => {
67
121
  }
68
122
  };
69
123
 
70
- const wrapper = mount(JsonSchemaForm, {
124
+ const wrapper = shallowMount(JsonSchemaForm, {
71
125
  props: { schema, modelValue: {} }
72
126
  });
73
127
 
@@ -83,7 +137,7 @@ describe('JsonSchemaForm unit tests', () => {
83
137
  }
84
138
  };
85
139
 
86
- const wrapper = mount(JsonSchemaForm, {
140
+ const wrapper = shallowMount(JsonSchemaForm, {
87
141
  props: { schema, modelValue: {} }
88
142
  });
89
143
 
@@ -102,7 +156,7 @@ describe('JsonSchemaForm unit tests', () => {
102
156
  required: ['email']
103
157
  };
104
158
 
105
- const wrapper = mount(JsonSchemaForm, {
159
+ const wrapper = shallowMount(JsonSchemaForm, {
106
160
  props: { schema, modelValue: {} }
107
161
  });
108
162
 
@@ -119,7 +173,7 @@ describe('JsonSchemaForm unit tests', () => {
119
173
  required: []
120
174
  };
121
175
 
122
- const wrapper = mount(JsonSchemaForm, {
176
+ const wrapper = shallowMount(JsonSchemaForm, {
123
177
  props: { schema, modelValue: {} }
124
178
  });
125
179
 
@@ -135,7 +189,7 @@ describe('JsonSchemaForm unit tests', () => {
135
189
  }
136
190
  };
137
191
 
138
- const wrapper = mount(JsonSchemaForm, {
192
+ const wrapper = shallowMount(JsonSchemaForm, {
139
193
  props: { schema, modelValue: {} }
140
194
  });
141
195
 
@@ -157,7 +211,7 @@ describe('JsonSchemaForm unit tests', () => {
157
211
  password: { 'ui:widget': 'password' }
158
212
  };
159
213
 
160
- const wrapper = mount(JsonSchemaForm, {
214
+ const wrapper = shallowMount(JsonSchemaForm, {
161
215
  props: { schema, uiSchema, modelValue: {} }
162
216
  });
163
217
 
@@ -173,7 +227,7 @@ describe('JsonSchemaForm unit tests', () => {
173
227
  }
174
228
  };
175
229
 
176
- const wrapper = mount(JsonSchemaForm, {
230
+ const wrapper = shallowMount(JsonSchemaForm, {
177
231
  props: { schema, modelValue: {} }
178
232
  });
179
233
 
@@ -189,7 +243,7 @@ describe('JsonSchemaForm unit tests', () => {
189
243
  }
190
244
  };
191
245
 
192
- const wrapper = mount(JsonSchemaForm, {
246
+ const wrapper = shallowMount(JsonSchemaForm, {
193
247
  props: { schema, modelValue: {} }
194
248
  });
195
249
 
@@ -205,7 +259,7 @@ describe('JsonSchemaForm unit tests', () => {
205
259
  }
206
260
  };
207
261
 
208
- const wrapper = mount(JsonSchemaForm, {
262
+ const wrapper = shallowMount(JsonSchemaForm, {
209
263
  props: { schema, modelValue: {} }
210
264
  });
211
265
 
@@ -222,7 +276,7 @@ describe('JsonSchemaForm unit tests', () => {
222
276
  }
223
277
  };
224
278
 
225
- const wrapper = mount(JsonSchemaForm, {
279
+ const wrapper = shallowMount(JsonSchemaForm, {
226
280
  props: { schema, modelValue: {} }
227
281
  });
228
282
 
@@ -238,7 +292,7 @@ describe('JsonSchemaForm unit tests', () => {
238
292
  }
239
293
  };
240
294
 
241
- const wrapper = mount(JsonSchemaForm, {
295
+ const wrapper = shallowMount(JsonSchemaForm, {
242
296
  props: { schema, modelValue: {} }
243
297
  });
244
298
 
@@ -254,7 +308,7 @@ describe('JsonSchemaForm unit tests', () => {
254
308
  }
255
309
  };
256
310
 
257
- const wrapper = mount(JsonSchemaForm, {
311
+ const wrapper = shallowMount(JsonSchemaForm, {
258
312
  props: { schema, modelValue: {} }
259
313
  });
260
314
 
@@ -270,7 +324,7 @@ describe('JsonSchemaForm unit tests', () => {
270
324
  }
271
325
  };
272
326
 
273
- const wrapper = mount(JsonSchemaForm, {
327
+ const wrapper = shallowMount(JsonSchemaForm, {
274
328
  props: { schema, modelValue: {} }
275
329
  });
276
330
 
@@ -286,7 +340,7 @@ describe('JsonSchemaForm unit tests', () => {
286
340
  }
287
341
  };
288
342
 
289
- const wrapper = mount(JsonSchemaForm, {
343
+ const wrapper = shallowMount(JsonSchemaForm, {
290
344
  props: { schema, modelValue: {} }
291
345
  });
292
346
 
@@ -308,7 +362,7 @@ describe('JsonSchemaForm unit tests', () => {
308
362
  pwd: { 'ui:widget': 'password' }
309
363
  };
310
364
 
311
- const wrapper = mount(JsonSchemaForm, {
365
+ const wrapper = shallowMount(JsonSchemaForm, {
312
366
  props: { schema, uiSchema, modelValue: {} }
313
367
  });
314
368
 
@@ -324,7 +378,7 @@ describe('JsonSchemaForm unit tests', () => {
324
378
  }
325
379
  };
326
380
 
327
- const wrapper = mount(JsonSchemaForm, {
381
+ const wrapper = shallowMount(JsonSchemaForm, {
328
382
  props: { schema, modelValue: {} }
329
383
  });
330
384
 
@@ -340,7 +394,7 @@ describe('JsonSchemaForm unit tests', () => {
340
394
  }
341
395
  };
342
396
 
343
- const wrapper = mount(JsonSchemaForm, {
397
+ const wrapper = shallowMount(JsonSchemaForm, {
344
398
  props: { schema, modelValue: {} }
345
399
  });
346
400
 
@@ -356,7 +410,7 @@ describe('JsonSchemaForm unit tests', () => {
356
410
  }
357
411
  };
358
412
 
359
- const wrapper = mount(JsonSchemaForm, {
413
+ const wrapper = shallowMount(JsonSchemaForm, {
360
414
  props: { schema, modelValue: {} }
361
415
  });
362
416
 
@@ -374,7 +428,7 @@ describe('JsonSchemaForm unit tests', () => {
374
428
  }
375
429
  };
376
430
 
377
- const wrapper = mount(JsonSchemaForm, {
431
+ const wrapper = shallowMount(JsonSchemaForm, {
378
432
  props: { schema, modelValue: {} }
379
433
  });
380
434
 
@@ -391,7 +445,7 @@ describe('JsonSchemaForm unit tests', () => {
391
445
  required: ['email']
392
446
  };
393
447
 
394
- const wrapper = mount(JsonSchemaForm, {
448
+ const wrapper = shallowMount(JsonSchemaForm, {
395
449
  props: { schema, modelValue: { email: 'invalid' } }
396
450
  });
397
451
 
@@ -413,7 +467,7 @@ describe('JsonSchemaForm unit tests', () => {
413
467
  required: ['name']
414
468
  };
415
469
 
416
- const wrapper = mount(JsonSchemaForm, {
470
+ const wrapper = shallowMount(JsonSchemaForm, {
417
471
  props: { schema, modelValue: { name: 'John' } }
418
472
  });
419
473
 
@@ -433,7 +487,7 @@ describe('JsonSchemaForm unit tests', () => {
433
487
  }
434
488
  };
435
489
 
436
- const wrapper = mount(JsonSchemaForm, {
490
+ const wrapper = shallowMount(JsonSchemaForm, {
437
491
  props: { schema, modelValue: {} }
438
492
  });
439
493
 
@@ -457,7 +511,7 @@ describe('JsonSchemaForm unit tests', () => {
457
511
  email: { 'ui:placeholder': 'Enter your email' }
458
512
  };
459
513
 
460
- const wrapper = mount(JsonSchemaForm, {
514
+ const wrapper = shallowMount(JsonSchemaForm, {
461
515
  props: { schema, uiSchema, modelValue: {} }
462
516
  });
463
517
 
@@ -473,7 +527,7 @@ describe('JsonSchemaForm unit tests', () => {
473
527
  }
474
528
  };
475
529
 
476
- const wrapper = mount(JsonSchemaForm, {
530
+ const wrapper = shallowMount(JsonSchemaForm, {
477
531
  props: { schema, modelValue: {} }
478
532
  });
479
533
 
@@ -494,7 +548,7 @@ describe('JsonSchemaForm unit tests', () => {
494
548
  }
495
549
  };
496
550
 
497
- const wrapper = mount(JsonSchemaForm, {
551
+ const wrapper = shallowMount(JsonSchemaForm, {
498
552
  props: { schema, modelValue: {} }
499
553
  });
500
554
 
@@ -503,8 +557,6 @@ describe('JsonSchemaForm unit tests', () => {
503
557
 
504
558
  expect(options).toHaveLength(3);
505
559
  expect(options[0]).toEqual({ id: 'active', name: 'active', label: 'active' });
506
- expect(options[1]).toEqual({ id: 'inactive', name: 'inactive', label: 'inactive' });
507
- expect(options[2]).toEqual({ id: 'pending', name: 'pending', label: 'pending' });
508
560
  });
509
561
 
510
562
  it('should return empty array when enum is not defined', () => {
@@ -515,7 +567,7 @@ describe('JsonSchemaForm unit tests', () => {
515
567
  }
516
568
  };
517
569
 
518
- const wrapper = mount(JsonSchemaForm, {
570
+ const wrapper = shallowMount(JsonSchemaForm, {
519
571
  props: { schema, modelValue: {} }
520
572
  });
521
573
 
@@ -531,7 +583,7 @@ describe('JsonSchemaForm unit tests', () => {
531
583
  }
532
584
  };
533
585
 
534
- const wrapper = mount(JsonSchemaForm, {
586
+ const wrapper = shallowMount(JsonSchemaForm, {
535
587
  props: { schema, modelValue: {} }
536
588
  });
537
589
 
@@ -552,7 +604,7 @@ describe('JsonSchemaForm unit tests', () => {
552
604
  }
553
605
  };
554
606
 
555
- const wrapper = mount(JsonSchemaForm, {
607
+ const wrapper = shallowMount(JsonSchemaForm, {
556
608
  props: {
557
609
  schema,
558
610
  modelValue: { status: 'active' }
@@ -573,7 +625,7 @@ describe('JsonSchemaForm unit tests', () => {
573
625
  }
574
626
  };
575
627
 
576
- const wrapper = mount(JsonSchemaForm, {
628
+ const wrapper = shallowMount(JsonSchemaForm, {
577
629
  props: { schema, modelValue: {} }
578
630
  });
579
631
 
@@ -593,7 +645,7 @@ describe('JsonSchemaForm unit tests', () => {
593
645
  }
594
646
  };
595
647
 
596
- const wrapper = mount(JsonSchemaForm, {
648
+ const wrapper = shallowMount(JsonSchemaForm, {
597
649
  props: { schema, modelValue: {} }
598
650
  });
599
651
 
@@ -614,7 +666,7 @@ describe('JsonSchemaForm unit tests', () => {
614
666
  }
615
667
  };
616
668
 
617
- const wrapper = mount(JsonSchemaForm, {
669
+ const wrapper = shallowMount(JsonSchemaForm, {
618
670
  props: { schema, modelValue: {} }
619
671
  });
620
672
 
@@ -638,7 +690,7 @@ describe('JsonSchemaForm unit tests', () => {
638
690
  required: ['email']
639
691
  };
640
692
 
641
- const wrapper = mount(JsonSchemaForm, {
693
+ const wrapper = shallowMount(JsonSchemaForm, {
642
694
  props: { schema, modelValue: {} }
643
695
  });
644
696
 
@@ -662,7 +714,7 @@ describe('JsonSchemaForm unit tests', () => {
662
714
  required: ['name']
663
715
  };
664
716
 
665
- const wrapper = mount(JsonSchemaForm, {
717
+ const wrapper = shallowMount(JsonSchemaForm, {
666
718
  props: {
667
719
  schema,
668
720
  modelValue: { name: 'John' }
@@ -684,7 +736,7 @@ describe('JsonSchemaForm unit tests', () => {
684
736
  required: ['email']
685
737
  };
686
738
 
687
- const wrapper = mount(JsonSchemaForm, {
739
+ const wrapper = shallowMount(JsonSchemaForm, {
688
740
  props: {
689
741
  schema,
690
742
  modelValue: { email: 'invalid' }
@@ -708,7 +760,7 @@ describe('JsonSchemaForm unit tests', () => {
708
760
  required: ['name']
709
761
  };
710
762
 
711
- const wrapper = mount(JsonSchemaForm, {
763
+ const wrapper = shallowMount(JsonSchemaForm, {
712
764
  props: { schema, modelValue: {} }
713
765
  });
714
766
 
@@ -729,7 +781,7 @@ describe('JsonSchemaForm unit tests', () => {
729
781
  }
730
782
  };
731
783
 
732
- const wrapper = mount(JsonSchemaForm, {
784
+ const wrapper = shallowMount(JsonSchemaForm, {
733
785
  props: {
734
786
  schema,
735
787
  modelValue: { name: 'John' }
@@ -758,7 +810,7 @@ describe('JsonSchemaForm unit tests', () => {
758
810
  required: ['email']
759
811
  };
760
812
 
761
- const wrapper = mount(JsonSchemaForm, {
813
+ const wrapper = shallowMount(JsonSchemaForm, {
762
814
  props: { schema, modelValue: {} }
763
815
  });
764
816
 
@@ -782,7 +834,7 @@ describe('JsonSchemaForm unit tests', () => {
782
834
  }
783
835
  };
784
836
 
785
- const wrapper = mount(JsonSchemaForm, {
837
+ const wrapper = shallowMount(JsonSchemaForm, {
786
838
  props: { schema, modelValue: {} }
787
839
  });
788
840
 
@@ -395,11 +395,27 @@ function updateArrayItem(fieldName: string, index: number, value: any) {
395
395
  // Expose methods
396
396
  defineExpose({
397
397
  validate,
398
+ validateField,
398
399
  reset: () => {
399
400
  emit('update:modelValue', {});
400
401
  errors.value = {};
401
402
  touched.value = {};
402
- }
403
+ },
404
+ // Expose internal state for testing
405
+ formData,
406
+ errors,
407
+ touched,
408
+ // Expose helper methods for testing
409
+ getFieldLabel,
410
+ getFieldDescription,
411
+ isRequired,
412
+ getWidget,
413
+ getInputType,
414
+ getFieldColor,
415
+ getPlaceholder,
416
+ getSelectOptions,
417
+ getSelectedOption,
418
+ updateField
403
419
  });
404
420
  </script>
405
421
 
package/src/index.ts CHANGED
@@ -15,3 +15,6 @@ export * from './domain';
15
15
 
16
16
  // Composables
17
17
  export * from './composables';
18
+
19
+ // Stores
20
+ export * from './stores';
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Admin Wrapper Component
3
+ *
4
+ * Wraps uiWrapper from @hotelinking/ui with sidebar, topbar, and content area.
5
+ */
6
+
7
+ <template>
8
+ <uiWrapper
9
+ :sidebar="sidebarConfig as any"
10
+ :topbar="topbarConfig as any"
11
+ :sidebarOpen="sidebarOpen"
12
+ @selectChanged="handleSelectChanged"
13
+ @topBarClick="handleTopBarClick"
14
+ @sideBarClick="handleSideBarClick"
15
+ @productBarClick="handleProductBarClick"
16
+ @inputChanged="handleInputChanged"
17
+ @sidebarToggle="(isOpen: boolean) => sidebarOpen = isOpen"
18
+ >
19
+ <slot></slot>
20
+ </uiWrapper>
21
+ </template>
22
+
23
+ <script setup lang="ts">
24
+ import type { SelectItemType } from "@hotelinking/ui";
25
+ import { uiWrapper } from "@hotelinking/ui";
26
+ import { useStore } from "@nanostores/vue";
27
+ import { computed, ref } from "vue";
28
+ import { $user } from "../stores/user";
29
+
30
+ // Props interface (user is now from nanostore)
31
+ interface Props {
32
+ sidebarLogo: string;
33
+ currentPage?: string;
34
+ sidebarTitle?: string;
35
+ sidebarItems?: Array<{
36
+ name: string;
37
+ icon?: string;
38
+ id: string;
39
+ routeName: string;
40
+ }>;
41
+ topbarActions?: Array<{
42
+ name: string;
43
+ event: string;
44
+ icon: string;
45
+ }>;
46
+ selectItems?: Array<{
47
+ name: string;
48
+ id: string;
49
+ }>;
50
+ selectedItem?: {
51
+ name: string;
52
+ id: string;
53
+ };
54
+ productsSidebar?: Array<{
55
+ name: string;
56
+ icon: string;
57
+ active?: boolean;
58
+ }>;
59
+ sidebarOpenByDefault?: boolean;
60
+ }
61
+
62
+ const props = withDefaults(defineProps<Props>(), {
63
+ currentPage: "dashboard",
64
+ sidebarItems: () => [],
65
+ topbarActions: () => [],
66
+ selectItems: () => [],
67
+ selectedItem: () => ({ name: "", id: "" }),
68
+ productsSidebar: () => [],
69
+ sidebarOpenByDefault: true,
70
+ });
71
+
72
+ // Emit events
73
+ const emit = defineEmits<{
74
+ selectChanged: [item: { name: string; id: string }];
75
+ }>();
76
+
77
+ // Reactive state
78
+ const sidebarOpen = ref(props.sidebarOpenByDefault);
79
+
80
+ // Get user from nanostore (no props needed!)
81
+ const user = useStore($user);
82
+
83
+ // Computed properties for UI configuration
84
+ const topbarConfig = computed(() => {
85
+ return {
86
+ logo: props.sidebarLogo,
87
+ accountLogo: user.value?.avatar || "",
88
+ alerted: false,
89
+ profileMenu: [
90
+ {
91
+ name: "Profile",
92
+ id: "profile",
93
+ href: "/profile",
94
+ },
95
+ {
96
+ name: "Settings",
97
+ id: "settings",
98
+ href: "/settings",
99
+ },
100
+ {
101
+ name: "Logout",
102
+ id: "logout",
103
+ href: "#",
104
+ },
105
+ ],
106
+ brand: {
107
+ name: user.value?.username || "User",
108
+ description: user.value?.email || "",
109
+ },
110
+ selectItems: props.selectItems,
111
+ selectedItem: props.selectedItem,
112
+ };
113
+ });
114
+
115
+ const sidebarConfig = computed(() => {
116
+ // Add current attribute dynamically based on currentPage
117
+ const navigationItems = props.sidebarItems.map((item) => ({
118
+ name: item.name,
119
+ icon: item.icon,
120
+ id: item.id,
121
+ current: item.id === props.currentPage,
122
+ }));
123
+
124
+ return {
125
+ navigation: navigationItems,
126
+ productsSidebar: props.productsSidebar,
127
+ logo: props.sidebarLogo,
128
+ };
129
+ });
130
+
131
+ // Event handlers
132
+ const handleSelectChanged = (item: SelectItemType | SelectItemType[]) => {
133
+ console.log("Select changed:", item);
134
+ // Emit to parent component
135
+ if (!Array.isArray(item) && item.id) {
136
+ emit("selectChanged", { name: item.name, id: item.id });
137
+ }
138
+ };
139
+
140
+ const handleTopBarClick = (event: unknown) => {
141
+ // Handle different possible event formats
142
+ let menuItem: string | undefined;
143
+
144
+ if (typeof event === "string") {
145
+ menuItem = event;
146
+ } else if (event && typeof event === "object") {
147
+ // Check if it's an object with name or href property
148
+ const eventObj = event as Record<string, unknown>;
149
+ menuItem = (eventObj.name as string) || (eventObj.href as string);
150
+ }
151
+
152
+ console.log("Extracted menu item:", menuItem);
153
+
154
+ // The event is the menu item name
155
+ if (menuItem === "logout") {
156
+ handleLogout();
157
+ } else if (menuItem === "profile") {
158
+ window.location.href = "/profile";
159
+ } else if (menuItem === "settings") {
160
+ window.location.href = "/settings";
161
+ }
162
+ };
163
+
164
+ const handleSideBarClick = (itemId: string) => {
165
+ console.log("Sidebar click:", itemId);
166
+
167
+ // Find the item by id to get the routeName
168
+ const item = props.sidebarItems.find(
169
+ (i) => (i.id || i.name.toLowerCase()) === itemId,
170
+ );
171
+
172
+ if (item?.routeName) {
173
+ window.location.href = item.routeName;
174
+ }
175
+ };
176
+
177
+ const handleProductBarClick = (event: unknown) => {
178
+ console.log("Product bar click:", event);
179
+ };
180
+
181
+ const handleInputChanged = (event: unknown) => {
182
+ console.log("Input changed:", event);
183
+ };
184
+
185
+ const handleLogout = async () => {
186
+ try {
187
+ // Import logout from auth package
188
+ const { signOut } = await import('@htlkg/core/auth');
189
+ await signOut();
190
+ // Redirect to login page
191
+ window.location.href = "/login";
192
+ } catch (error) {
193
+ console.error("Logout error:", error);
194
+ // Force redirect even if logout fails
195
+ window.location.href = "/login";
196
+ }
197
+ };
198
+ </script>