@hed-hog/core 0.0.278 → 0.0.285

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.
Files changed (51) hide show
  1. package/README.md +60 -0
  2. package/dist/auth/auth.controller.d.ts +3 -3
  3. package/dist/auth/auth.service.d.ts +8 -8
  4. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +12 -0
  5. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
  6. package/dist/dashboard/dashboard-core/dashboard-core.controller.js +9 -0
  7. package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
  8. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +12 -0
  9. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
  10. package/dist/dashboard/dashboard-core/dashboard-core.service.js +25 -0
  11. package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
  12. package/dist/file/file.controller.d.ts +2 -2
  13. package/dist/file/file.service.d.ts +4 -4
  14. package/dist/role/guards/role.guard.d.ts.map +1 -1
  15. package/dist/role/guards/role.guard.js +1 -1
  16. package/dist/role/guards/role.guard.js.map +1 -1
  17. package/dist/session/session.controller.d.ts +1 -1
  18. package/dist/session/session.service.d.ts +3 -3
  19. package/dist/user/user.controller.d.ts +2 -2
  20. package/dist/user/user.service.d.ts +6 -6
  21. package/hedhog/data/dashboard_component.yaml +95 -77
  22. package/hedhog/data/dashboard_component_role.yaml +91 -79
  23. package/hedhog/data/dashboard_item.yaml +121 -101
  24. package/hedhog/data/route.yaml +8 -0
  25. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +69 -62
  26. package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +23 -12
  27. package/hedhog/frontend/app/dashboard/components/draggable-grid.tsx.ejs +80 -5
  28. package/hedhog/frontend/app/dashboard/components/widgets/account-security.tsx.ejs +33 -29
  29. package/hedhog/frontend/app/dashboard/components/widgets/activity-timeline.tsx.ejs +18 -14
  30. package/hedhog/frontend/app/dashboard/components/widgets/email-notifications.tsx.ejs +39 -32
  31. package/hedhog/frontend/app/dashboard/components/widgets/login-history-chart.tsx.ejs +22 -19
  32. package/hedhog/frontend/app/dashboard/components/widgets/menus-card.tsx.ejs +58 -0
  33. package/hedhog/frontend/app/dashboard/components/widgets/routes-card.tsx.ejs +58 -0
  34. package/hedhog/frontend/app/dashboard/components/widgets/stat-access-level.tsx.ejs +18 -18
  35. package/hedhog/frontend/app/dashboard/components/widgets/stat-actions-today.tsx.ejs +18 -18
  36. package/hedhog/frontend/app/dashboard/components/widgets/stat-consecutive-days.tsx.ejs +18 -18
  37. package/hedhog/frontend/app/dashboard/components/widgets/stat-online-time.tsx.ejs +18 -18
  38. package/hedhog/frontend/app/dashboard/components/widgets/user-roles.tsx.ejs +15 -11
  39. package/hedhog/frontend/app/dashboard/components/widgets/user-sessions.tsx.ejs +39 -37
  40. package/hedhog/frontend/app/dashboard/dashboard.css.ejs +20 -4
  41. package/hedhog/frontend/app/mail/log/page.tsx.ejs +36 -47
  42. package/hedhog/frontend/app/mail/template/page.tsx.ejs +176 -126
  43. package/hedhog/frontend/app/menu/page.tsx.ejs +45 -39
  44. package/hedhog/frontend/app/roles/page.tsx.ejs +45 -46
  45. package/hedhog/frontend/app/users/page.tsx.ejs +70 -73
  46. package/hedhog/frontend/messages/en.json +15 -2
  47. package/hedhog/frontend/messages/pt.json +15 -2
  48. package/package.json +4 -4
  49. package/src/dashboard/dashboard-core/dashboard-core.controller.ts +5 -0
  50. package/src/dashboard/dashboard-core/dashboard-core.service.ts +34 -0
  51. package/src/role/guards/role.guard.ts +9 -8
@@ -2,7 +2,13 @@
2
2
 
3
3
  import type React from 'react';
4
4
 
5
- import { PageHeader } from '@/components/entity-list';
5
+ import {
6
+ EmptyState,
7
+ Page,
8
+ PageHeader,
9
+ PaginationFooter,
10
+ SearchBar,
11
+ } from '@/components/entity-list';
6
12
  import { RichTextEditor } from '@/components/rich-text-editor';
7
13
  import {
8
14
  AlertDialog,
@@ -33,6 +39,13 @@ import {
33
39
  SelectTrigger,
34
40
  SelectValue,
35
41
  } from '@/components/ui/select';
42
+ import {
43
+ Sheet,
44
+ SheetContent,
45
+ SheetDescription,
46
+ SheetHeader,
47
+ SheetTitle,
48
+ } from '@/components/ui/sheet';
36
49
  import {
37
50
  Table,
38
51
  TableBody,
@@ -82,7 +95,17 @@ interface ImportResponse {
82
95
  export default function EmailTemplatesPage() {
83
96
  const { locales, request, currentLocaleCode, getSettingValue } = useApp();
84
97
  const t = useTranslations('core.MailPage');
85
- const { items, refetch } = usePagination({ url: '/mail' });
98
+ const {
99
+ items,
100
+ refetch,
101
+ page,
102
+ setPage,
103
+ pageSize,
104
+ setPageSize,
105
+ totalItems,
106
+ search,
107
+ setSearch,
108
+ } = usePagination({ url: '/mail' });
86
109
  const [templates, setTemplates] = useState<Mail[]>([]);
87
110
  const [isDialogOpen, setIsDialogOpen] = useState(false);
88
111
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
@@ -689,7 +712,7 @@ export default function EmailTemplatesPage() {
689
712
  };
690
713
 
691
714
  return (
692
- <div className="flex flex-col h-screen px-4">
715
+ <Page>
693
716
  <PageHeader
694
717
  breadcrumbs={[
695
718
  { label: t('breadcrumbHome'), href: '/' },
@@ -720,118 +743,154 @@ export default function EmailTemplatesPage() {
720
743
  description={t('description')}
721
744
  />
722
745
 
723
- <Table>
724
- <TableHeader>
725
- <TableRow>
726
- <TableHead className="w-12">
727
- <Checkbox
728
- checked={
729
- selectedTemplates.size === templates.length &&
730
- templates.length > 0
731
- }
732
- onCheckedChange={handleToggleAll}
733
- />
734
- </TableHead>
735
- <TableHead>{t('tableSlug')}</TableHead>
736
- <TableHead>{t('tableSubject')}</TableHead>
737
- <TableHead>{t('tableVariables')}</TableHead>
738
- <TableHead>{t('tableUpdated')}</TableHead>
739
- <TableHead className="text-right">{t('tableActions')}</TableHead>
740
- </TableRow>
741
- </TableHeader>
742
- <TableBody>
743
- {templates.map((template) => (
744
- <TableRow
745
- key={template.id}
746
- onDoubleClick={() => handleEdit(template)}
747
- className="cursor-pointer"
748
- >
749
- <TableCell onClick={(e) => e.stopPropagation()}>
750
- <Checkbox
751
- checked={selectedTemplates.has(
752
- template.mail_id || template.id
753
- )}
754
- onCheckedChange={() =>
755
- handleToggleTemplate(template.mail_id || template.id)
756
- }
757
- />
758
- </TableCell>
759
- <TableCell className="font-mono text-sm">
760
- {template.slug}
761
- </TableCell>
762
- <TableCell>{template.subject}</TableCell>
763
- <TableCell>
764
- <div className="flex flex-wrap gap-1">
765
- {template.mail_var.map((v, index) => (
766
- <Badge
767
- key={`${template.id}-${v.id}-${index}`}
768
- variant="secondary"
769
- className="text-xs"
770
- >
771
- {v.name}
772
- </Badge>
773
- ))}
774
- </div>
775
- </TableCell>
776
- <TableCell className="text-muted-foreground">
777
- {formatDate(
778
- template.updated_at,
779
- getSettingValue,
780
- currentLocaleCode
781
- )}
782
- </TableCell>
783
- <TableCell className="text-right">
784
- <div className="flex justify-end gap-2">
785
- <Button
786
- variant="ghost"
787
- size="icon"
788
- onClick={(e) => {
789
- e.stopPropagation();
790
- handleDownloadHTML(template);
791
- }}
792
- title={t('downloadHTML')}
793
- >
794
- <FileDown className="h-4 w-4" />
795
- </Button>
796
- <Button
797
- variant="ghost"
798
- size="icon"
799
- onClick={(e) => {
800
- e.stopPropagation();
801
- handleEdit(template);
802
- }}
803
- >
804
- <Pencil className="h-4 w-4" />
805
- </Button>
806
- <Button
807
- variant="ghost"
808
- size="icon"
809
- onClick={(e) => {
810
- e.stopPropagation();
811
- handleDelete(Number(template.mail_id || template.id));
812
- }}
813
- >
814
- <Trash2 className="h-4 w-4 text-destructive" />
815
- </Button>
816
- </div>
817
- </TableCell>
818
- </TableRow>
819
- ))}
820
- </TableBody>
821
- </Table>
822
-
823
- <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
824
- <DialogContent className="max-h-[90vh] max-w-[95vw] overflow-y-auto">
825
- <DialogHeader>
826
- <DialogTitle>
746
+ <SearchBar
747
+ searchQuery={search}
748
+ onSearchChange={(value) => {
749
+ setSearch(value);
750
+ setPage(1);
751
+ }}
752
+ onSearch={() => setPage(1)}
753
+ placeholder={t('searchPlaceholder')}
754
+ />
755
+
756
+ {templates.length === 0 ? (
757
+ <EmptyState
758
+ icon={<MailIcon className="h-12 w-12" />}
759
+ title={t('noTemplatesFound')}
760
+ description={t('noTemplatesHint')}
761
+ actionLabel={t('newTemplate')}
762
+ onAction={handleCreate}
763
+ />
764
+ ) : (
765
+ <div className="rounded-md border">
766
+ <Table>
767
+ <TableHeader>
768
+ <TableRow>
769
+ <TableHead className="w-12">
770
+ <Checkbox
771
+ checked={
772
+ selectedTemplates.size === templates.length &&
773
+ templates.length > 0
774
+ }
775
+ onCheckedChange={handleToggleAll}
776
+ />
777
+ </TableHead>
778
+ <TableHead>{t('tableSlug')}</TableHead>
779
+ <TableHead>{t('tableSubject')}</TableHead>
780
+ <TableHead>{t('tableVariables')}</TableHead>
781
+ <TableHead>{t('tableUpdated')}</TableHead>
782
+ <TableHead className="text-right">{t('tableActions')}</TableHead>
783
+ </TableRow>
784
+ </TableHeader>
785
+ <TableBody>
786
+ {templates.map((template) => (
787
+ <TableRow
788
+ key={template.id}
789
+ onDoubleClick={() => handleEdit(template)}
790
+ className="cursor-pointer"
791
+ >
792
+ <TableCell onClick={(e) => e.stopPropagation()}>
793
+ <Checkbox
794
+ checked={selectedTemplates.has(
795
+ template.mail_id || template.id
796
+ )}
797
+ onCheckedChange={() =>
798
+ handleToggleTemplate(template.mail_id || template.id)
799
+ }
800
+ />
801
+ </TableCell>
802
+ <TableCell className="font-mono text-sm">
803
+ {template.slug}
804
+ </TableCell>
805
+ <TableCell>{template.subject}</TableCell>
806
+ <TableCell>
807
+ <div className="flex flex-wrap gap-1">
808
+ {template.mail_var.map((v, index) => (
809
+ <Badge
810
+ key={`${template.id}-${v.id}-${index}`}
811
+ variant="secondary"
812
+ className="text-xs"
813
+ >
814
+ {v.name}
815
+ </Badge>
816
+ ))}
817
+ </div>
818
+ </TableCell>
819
+ <TableCell className="text-muted-foreground">
820
+ {formatDate(
821
+ template.updated_at,
822
+ getSettingValue,
823
+ currentLocaleCode
824
+ )}
825
+ </TableCell>
826
+ <TableCell className="text-right">
827
+ <div className="flex justify-end gap-2">
828
+ <Button
829
+ variant="ghost"
830
+ size="icon"
831
+ onClick={(e) => {
832
+ e.stopPropagation();
833
+ handleDownloadHTML(template);
834
+ }}
835
+ title={t('downloadHTML')}
836
+ >
837
+ <FileDown className="h-4 w-4" />
838
+ </Button>
839
+ <Button
840
+ variant="ghost"
841
+ size="icon"
842
+ onClick={(e) => {
843
+ e.stopPropagation();
844
+ handleEdit(template);
845
+ }}
846
+ >
847
+ <Pencil className="h-4 w-4" />
848
+ </Button>
849
+ <Button
850
+ variant="ghost"
851
+ size="icon"
852
+ onClick={(e) => {
853
+ e.stopPropagation();
854
+ handleDelete(Number(template.mail_id || template.id));
855
+ }}
856
+ >
857
+ <Trash2 className="h-4 w-4 text-destructive" />
858
+ </Button>
859
+ </div>
860
+ </TableCell>
861
+ </TableRow>
862
+ ))}
863
+ </TableBody>
864
+ </Table>
865
+ </div>
866
+ )}
867
+
868
+ <PaginationFooter
869
+ currentPage={page}
870
+ pageSize={pageSize}
871
+ totalItems={totalItems}
872
+ onPageChange={setPage}
873
+ onPageSizeChange={(newSize) => {
874
+ setPageSize(newSize);
875
+ setPage(1);
876
+ }}
877
+ />
878
+
879
+ <Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
880
+ <SheetContent
881
+ side="right"
882
+ className="w-full max-w-[95vw] overflow-y-auto sm:max-w-6xl"
883
+ >
884
+ <SheetHeader>
885
+ <SheetTitle>
827
886
  {editMode ? t('editTemplate') : t('newTemplateTitle')}
828
- </DialogTitle>
829
- <DialogDescription>
887
+ </SheetTitle>
888
+ <SheetDescription>
830
889
  {editMode
831
890
  ? t('editTemplateDescription')
832
891
  : t('newTemplateDescription')}
833
- </DialogDescription>
834
- </DialogHeader>
892
+ </SheetDescription>
893
+ </SheetHeader>
835
894
  <form onSubmit={handleSubmit} className="space-y-6">
836
895
  <div className="grid grid-cols-2 gap-6">
837
896
  <div className="space-y-4 overflow-y-auto max-h-[calc(90vh-200px)] pr-4">
@@ -987,22 +1046,13 @@ export default function EmailTemplatesPage() {
987
1046
  {t('sendTestEmail')}
988
1047
  </Button>
989
1048
  </div>
990
- <div className="flex gap-3">
991
- <Button
992
- type="button"
993
- variant="outline"
994
- onClick={() => setIsDialogOpen(false)}
995
- >
996
- {t('cancel')}
997
- </Button>
998
- <Button type="submit">
999
- {editMode ? t('saveChanges') : t('createTemplate')}
1000
- </Button>
1001
- </div>
1049
+ <Button type="submit" className="min-w-40">
1050
+ {editMode ? t('saveChanges') : t('createTemplate')}
1051
+ </Button>
1002
1052
  </div>
1003
1053
  </form>
1004
- </DialogContent>
1005
- </Dialog>
1054
+ </SheetContent>
1055
+ </Sheet>
1006
1056
 
1007
1057
  <Dialog
1008
1058
  open={isTestEmailDialogOpen}
@@ -1172,6 +1222,6 @@ export default function EmailTemplatesPage() {
1172
1222
  </AlertDialogFooter>
1173
1223
  </AlertDialogContent>
1174
1224
  </AlertDialog>
1175
- </div>
1225
+ </Page>
1176
1226
  );
1177
1227
  }
@@ -1,12 +1,24 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
+ EmptyState,
5
+ icon={<Menu className="h-12 w-12" />}
4
6
  PageHeader,
5
7
  PaginationFooter,
6
8
  SearchBar,
7
9
  StatsCards,
8
10
  } from '@/components/entity-list';
9
11
  import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
12
+ import {
13
+ AlertDialog,
14
+ AlertDialogAction,
15
+ AlertDialogCancel,
16
+ AlertDialogContent,
17
+ AlertDialogDescription,
18
+ AlertDialogFooter,
19
+ AlertDialogHeader,
20
+ AlertDialogTitle,
21
+ } from '@/components/ui/alert-dialog';
10
22
  import { Badge } from '@/components/ui/badge';
11
23
  import { Button } from '@/components/ui/button';
12
24
  import {
@@ -885,7 +897,7 @@ export default function MenuPage() {
885
897
  );
886
898
 
887
899
  return (
888
- <div className="flex flex-col h-screen px-4">
900
+ <Page>
889
901
  <PageHeader
890
902
  breadcrumbs={[{ label: 'Home', href: '/' }, { label: t('menus') }]}
891
903
  actions={[
@@ -947,7 +959,13 @@ export default function MenuPage() {
947
959
 
948
960
  {!isLoading &&
949
961
  (!menusResponse?.data || menusResponse.data.length === 0) ? (
950
- <p className="text-sm text-muted-foreground">{t('noMenusFound')}</p>
962
+ <EmptyState
963
+ icon={Menu}
964
+ title={t('noMenusFound')}
965
+ description={t('description')}
966
+ actionLabel={t('buttonAddMenu')}
967
+ onAction={() => setIsDialogOpen(true)}
968
+ />
951
969
  ) : (
952
970
  <div className="grid gap-4 grid-cols-1 lg:grid-cols-2 xl:grid-cols-3">
953
971
  {menusResponse?.data?.map((menu: MenuItem) => (
@@ -1022,19 +1040,18 @@ export default function MenuPage() {
1022
1040
  />
1023
1041
  </div>
1024
1042
 
1025
- <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
1026
- <DialogContent className="sm:max-w-lg">
1027
- <DialogHeader>
1028
- <DialogTitle>{t('dialogAddMenuTitle')}</DialogTitle>
1029
- <DialogDescription>
1043
+ <Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
1044
+ <SheetContent className="w-full sm:max-w-lg overflow-y-auto gap-0">
1045
+ <SheetHeader>
1046
+ <SheetTitle>{t('dialogAddMenuTitle')}</SheetTitle>
1047
+ <SheetDescription>
1030
1048
  {t('dialogAddMenuDescription')}
1031
- </DialogDescription>
1032
- </DialogHeader>
1033
- <div className="w-full border-t pt-1 mt-1" />
1049
+ </SheetDescription>
1050
+ </SheetHeader>
1034
1051
  <Form {...form}>
1035
1052
  <form
1036
1053
  onSubmit={form.handleSubmit(onSubmit)}
1037
- className="space-y-4"
1054
+ className="space-y-4 px-4 pt-2"
1038
1055
  >
1039
1056
  <FormField
1040
1057
  control={form.control}
@@ -1175,8 +1192,8 @@ export default function MenuPage() {
1175
1192
  </Button>
1176
1193
  </form>
1177
1194
  </Form>
1178
- </DialogContent>
1179
- </Dialog>
1195
+ </SheetContent>
1196
+ </Sheet>
1180
1197
 
1181
1198
  {editingMenu && (
1182
1199
  <Sheet open={!!editingMenu} onOpenChange={() => setEditingMenu(null)}>
@@ -1399,33 +1416,22 @@ export default function MenuPage() {
1399
1416
  </Sheet>
1400
1417
  )}
1401
1418
 
1402
- <Dialog open={openDeleteModal} onOpenChange={setOpenDeleteModal}>
1403
- <DialogContent className="sm:max-w-lg">
1404
- <DialogHeader>
1405
- <DialogTitle>{t('dialogDeleteMenuTitle')}</DialogTitle>
1406
- <DialogDescription>
1419
+ <AlertDialog open={openDeleteModal} onOpenChange={setOpenDeleteModal}>
1420
+ <AlertDialogContent>
1421
+ <AlertDialogHeader>
1422
+ <AlertDialogTitle>{t('dialogDeleteMenuTitle')}</AlertDialogTitle>
1423
+ <AlertDialogDescription>
1407
1424
  {t('dialogDeleteMenuDescription')}
1408
- </DialogDescription>
1409
- </DialogHeader>
1410
- <hr className="mt-4" />
1411
- <div className="flex justify-end">
1412
- <Button
1413
- type="button"
1414
- className="px-4 w-28 h-12 py-2 bg-gray-300 text-black hover:bg-gray-300 hover:text-black rounded-sm mr-2 text-md"
1415
- onClick={() => setOpenDeleteModal(false)}
1416
- >
1417
- {t('deleteMenuCancel')}
1418
- </Button>
1419
- <Button
1420
- onClick={onDelete}
1421
- variant="destructive"
1422
- className="px-4 w-32 h-12 py-2 text-white hover:text-white rounded-sm text-md cursor-pointer"
1423
- >
1425
+ </AlertDialogDescription>
1426
+ </AlertDialogHeader>
1427
+ <AlertDialogFooter>
1428
+ <AlertDialogCancel>{t('deleteMenuCancel')}</AlertDialogCancel>
1429
+ <AlertDialogAction onClick={onDelete}>
1424
1430
  {t('deleteMenuConfirm')}
1425
- </Button>
1426
- </div>
1427
- </DialogContent>
1428
- </Dialog>
1431
+ </AlertDialogAction>
1432
+ </AlertDialogFooter>
1433
+ </AlertDialogContent>
1434
+ </AlertDialog>
1429
1435
 
1430
1436
  <MenuTreeDialog
1431
1437
  open={isTreeOpen}
@@ -1436,6 +1442,6 @@ export default function MenuPage() {
1436
1442
  }}
1437
1443
  />
1438
1444
  </div>
1439
- </div>
1445
+ </Page>
1440
1446
  );
1441
1447
  }
@@ -1,12 +1,24 @@
1
1
  'use client';
2
2
 
3
3
  import {
4
+ EmptyState,
5
+ icon={<ShieldCheck className="h-12 w-12" />}
4
6
  PageHeader,
5
7
  PaginationFooter,
6
8
  SearchBar,
7
9
  StatsCards,
8
10
  } from '@/components/entity-list';
9
11
  import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
12
+ import {
13
+ AlertDialog,
14
+ AlertDialogAction,
15
+ AlertDialogCancel,
16
+ AlertDialogContent,
17
+ AlertDialogDescription,
18
+ AlertDialogFooter,
19
+ AlertDialogHeader,
20
+ AlertDialogTitle,
21
+ } from '@/components/ui/alert-dialog';
10
22
  import { Button } from '@/components/ui/button';
11
23
  import {
12
24
  Card,
@@ -15,13 +27,6 @@ import {
15
27
  CardHeader,
16
28
  CardTitle,
17
29
  } from '@/components/ui/card';
18
- import {
19
- Dialog,
20
- DialogContent,
21
- DialogDescription,
22
- DialogHeader,
23
- DialogTitle,
24
- } from '@/components/ui/dialog';
25
30
  import {
26
31
  Form,
27
32
  FormControl,
@@ -367,7 +372,7 @@ export default function RolePage() {
367
372
  };
368
373
 
369
374
  return (
370
- <div className="flex flex-col h-screen px-4">
375
+ <Page>
371
376
  <PageHeader
372
377
  breadcrumbs={[{ label: 'Home', href: '/' }, { label: t('roles') }]}
373
378
  actions={[
@@ -423,7 +428,13 @@ export default function RolePage() {
423
428
 
424
429
  {!isLoading &&
425
430
  (!rolesResponse?.data || rolesResponse.data.length === 0) ? (
426
- <p className="text-sm text-muted-foreground">{t('noRolesFound')}</p>
431
+ <EmptyState
432
+ icon={ShieldCheck}
433
+ title={t('noRolesFound')}
434
+ description={t('description')}
435
+ actionLabel={t('buttonAddRole')}
436
+ onAction={() => setIsDialogOpen(true)}
437
+ />
427
438
  ) : (
428
439
  <div className="grid gap-4 grid-cols-1 lg:grid-cols-2 xl:grid-cols-3">
429
440
  {(rolesResponse?.data as (Role & { role_id: number })[])?.map(
@@ -504,19 +515,18 @@ export default function RolePage() {
504
515
  />
505
516
  </div>
506
517
 
507
- <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
508
- <DialogContent className="sm:max-w-lg">
509
- <DialogHeader>
510
- <DialogTitle>{t('dialogAddRoleTitle')}</DialogTitle>
511
- <DialogDescription>
518
+ <Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
519
+ <SheetContent className="w-full sm:max-w-lg overflow-y-auto gap-0">
520
+ <SheetHeader>
521
+ <SheetTitle>{t('dialogAddRoleTitle')}</SheetTitle>
522
+ <SheetDescription>
512
523
  {t('dialogAddRoleDescription')}
513
- </DialogDescription>
514
- </DialogHeader>
515
- <div className="w-full border-t pt-1 mt-1" />
524
+ </SheetDescription>
525
+ </SheetHeader>
516
526
  <Form {...form}>
517
527
  <form
518
528
  onSubmit={form.handleSubmit(onSubmit)}
519
- className="space-y-4"
529
+ className="space-y-4 px-4 pt-2"
520
530
  >
521
531
  <FormField
522
532
  control={form.control}
@@ -586,8 +596,8 @@ export default function RolePage() {
586
596
  </Button>
587
597
  </form>
588
598
  </Form>
589
- </DialogContent>
590
- </Dialog>
599
+ </SheetContent>
600
+ </Sheet>
591
601
 
592
602
  {editingRole && (
593
603
  <Sheet open={!!editingRole} onOpenChange={() => setEditingRole(null)}>
@@ -783,34 +793,23 @@ export default function RolePage() {
783
793
  </Sheet>
784
794
  )}
785
795
 
786
- <Dialog open={openDeleteModal} onOpenChange={setOpenDeleteModal}>
787
- <DialogContent className="sm:max-w-lg">
788
- <DialogHeader>
789
- <DialogTitle>{t('dialogDeleteRoleTitle')}</DialogTitle>
790
- <DialogDescription>
796
+ <AlertDialog open={openDeleteModal} onOpenChange={setOpenDeleteModal}>
797
+ <AlertDialogContent>
798
+ <AlertDialogHeader>
799
+ <AlertDialogTitle>{t('dialogDeleteRoleTitle')}</AlertDialogTitle>
800
+ <AlertDialogDescription>
791
801
  {t('dialogDeleteRoleDescription')}
792
- </DialogDescription>
793
- </DialogHeader>
794
- <hr className="mt-4" />
795
- <div className="flex justify-end">
796
- <Button
797
- type="button"
798
- className="px-4 w-28 h-12 py-2 bg-gray-300 text-black hover:bg-gray-300 hover:text-black rounded-sm mr-2 text-md"
799
- onClick={() => setOpenDeleteModal(false)}
800
- >
801
- {t('deleteRoleCancel')}
802
- </Button>
803
- <Button
804
- onClick={onDelete}
805
- variant="destructive"
806
- className="px-4 w-32 h-12 py-2 text-white hover:text-white rounded-sm text-md cursor-pointer"
807
- >
802
+ </AlertDialogDescription>
803
+ </AlertDialogHeader>
804
+ <AlertDialogFooter>
805
+ <AlertDialogCancel>{t('deleteRoleCancel')}</AlertDialogCancel>
806
+ <AlertDialogAction onClick={onDelete}>
808
807
  {t('deleteRoleConfirm')}
809
- </Button>
810
- </div>
811
- </DialogContent>
812
- </Dialog>
808
+ </AlertDialogAction>
809
+ </AlertDialogFooter>
810
+ </AlertDialogContent>
811
+ </AlertDialog>
813
812
  </div>
814
- </div>
813
+ </Page>
815
814
  );
816
815
  }