rl-core-front 0.3.0 → 0.5.0

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 (80) hide show
  1. package/package.json +1 -1
  2. package/src/_services/api/app-error-code.enum.ts +23 -0
  3. package/src/_services/api/schema.d.ts +86 -132
  4. package/src/_services/auth/index.ts +2 -0
  5. package/src/_utils/filter.ts +15 -34
  6. package/src/_utils/password.ts +40 -0
  7. package/src/_utils/permission.ts +14 -0
  8. package/src/_utils/storage.ts +64 -0
  9. package/src/_utils/user.ts +19 -0
  10. package/src/components/app-shell.tsx +85 -11
  11. package/src/components/brand-header.tsx +23 -8
  12. package/src/components/brand-panel.tsx +41 -0
  13. package/src/components/index.ts +1 -0
  14. package/src/components/password-field.tsx +49 -22
  15. package/src/components/ui/alert.tsx +34 -5
  16. package/src/components/ui/badge.tsx +2 -2
  17. package/src/components/ui/button.tsx +5 -0
  18. package/src/components/ui/confirm-dialog.tsx +3 -1
  19. package/src/components/ui/data-table.tsx +13 -4
  20. package/src/components/ui/dialog.tsx +120 -21
  21. package/src/components/ui/filter-sheet.tsx +47 -25
  22. package/src/components/ui/index.ts +3 -1
  23. package/src/components/ui/password-requirements.tsx +105 -0
  24. package/src/components/ui/segmented-control.tsx +75 -0
  25. package/src/components/ui/simple-select.tsx +74 -0
  26. package/src/components/ui/switch.tsx +3 -1
  27. package/src/components/ui/tabs.tsx +4 -8
  28. package/src/components/ui/track.styles.ts +31 -0
  29. package/src/contexts/brand-context.tsx +15 -0
  30. package/src/contexts/color-mode-context.tsx +4 -2
  31. package/src/contexts/i18n-context.tsx +72 -6
  32. package/src/contexts/socket-context.tsx +27 -1
  33. package/src/features/audit/audit-screen.tsx +13 -140
  34. package/src/features/audit/components/audit-diff.tsx +156 -0
  35. package/src/features/audit/components/index.ts +3 -0
  36. package/src/features/audit/components/record-audit-button.tsx +176 -0
  37. package/src/features/audit/enums/audit-data-action.enum.ts +20 -0
  38. package/src/features/audit/hooks/use-audit-trail.ts +9 -2
  39. package/src/features/audit/services/audit.service.ts +43 -1
  40. package/src/features/login/components/backup-codes-dialog.tsx +4 -4
  41. package/src/features/login/components/login-form.tsx +18 -3
  42. package/src/features/login/components/two-factor-setup.tsx +32 -2
  43. package/src/features/login/hooks/use-login-flow.ts +60 -7
  44. package/src/features/login/login-screen.tsx +99 -40
  45. package/src/features/logs/enums/error-type.enum.ts +21 -0
  46. package/src/features/logs/enums/request-outcome.enum.ts +14 -0
  47. package/src/features/logs/hooks/use-request-logs.ts +26 -3
  48. package/src/features/logs/logs-screen.tsx +2 -14
  49. package/src/features/logs/panels/index.ts +0 -1
  50. package/src/features/logs/panels/request-logs-panel.tsx +177 -25
  51. package/src/features/logs/services/logs.service.ts +13 -51
  52. package/src/features/notifications/components/notification-item.tsx +10 -8
  53. package/src/features/notifications/enums/notification-type.enum.ts +8 -0
  54. package/src/features/profile/force-password-change.tsx +18 -3
  55. package/src/features/profile/profile-screen.tsx +10 -2
  56. package/src/features/rbac/panels/groups-panel.tsx +78 -30
  57. package/src/features/rbac/panels/roles-panel.tsx +2 -2
  58. package/src/features/rbac/services/rbac.service.ts +23 -27
  59. package/src/features/recovery/reset-password-screen.tsx +16 -2
  60. package/src/features/users/components/user-form-dialog.tsx +65 -9
  61. package/src/features/users/hooks/use-users.ts +24 -3
  62. package/src/features/users/services/users.service.ts +16 -0
  63. package/src/features/users/users-screen.tsx +17 -12
  64. package/src/hooks/use-column-visibility.ts +13 -12
  65. package/src/hooks/use-countdown.ts +70 -0
  66. package/src/hooks/use-filters.ts +25 -2
  67. package/src/hooks/use-list-query.ts +14 -1
  68. package/src/hooks/use-request.ts +21 -2
  69. package/src/i18n/messages/en.ts +37 -6
  70. package/src/i18n/messages/pt.ts +41 -6
  71. package/src/index.ts +15 -1
  72. package/src/styles/core.css +99 -2
  73. package/src/styles/fonts/poppins-latin-400.woff2 +0 -0
  74. package/src/styles/fonts/poppins-latin-500.woff2 +0 -0
  75. package/src/styles/fonts/poppins-latin-600.woff2 +0 -0
  76. package/src/styles/fonts/poppins-latin-700.woff2 +0 -0
  77. package/tailwind-preset.ts +17 -0
  78. package/src/components/ui/filter-chips.tsx +0 -88
  79. package/src/features/logs/hooks/use-error-logs.ts +0 -65
  80. package/src/features/logs/panels/error-logs-panel.tsx +0 -183
@@ -1,65 +0,0 @@
1
- "use client";
2
-
3
- import type { SortingState } from "@tanstack/react-table";
4
- import {
5
- Dispatch,
6
- SetStateAction,
7
- useCallback,
8
- useEffect,
9
- useState,
10
- } from "react";
11
-
12
- import { ErrorLog, logsService } from "#core/features/logs/services/logs.service";
13
- import type { FiltersState } from "#core/hooks/use-filters";
14
- import { useListQuery } from "#core/hooks/use-list-query";
15
- import { useRequest } from "#core/hooks/use-request";
16
-
17
- export interface UseErrorLogsResult {
18
- rows: ErrorLog[];
19
- total: number;
20
- page: number;
21
- pageSize: number;
22
- sorting: SortingState;
23
- loading: boolean;
24
- setPage: Dispatch<SetStateAction<number>>;
25
- setPageSize: Dispatch<SetStateAction<number>>;
26
- setSorting: Dispatch<SetStateAction<SortingState>>;
27
- /** Filtros dinâmicos — repassar para o `DataTable`. */
28
- filters: FiltersState;
29
- refresh: () => Promise<void>;
30
- }
31
-
32
- export function useErrorLogs(): UseErrorLogsResult {
33
- const { run, loading } = useRequest();
34
-
35
- const list = useListQuery("/audit/errors/filter-schema", 20);
36
-
37
- const [rows, setRows] = useState<ErrorLog[]>([]);
38
- const [total, setTotal] = useState(0);
39
-
40
- const fetch = useCallback(async () => {
41
- const res = await run(() => logsService.listErrors(list.query));
42
- if (res) {
43
- setRows(res.items);
44
- setTotal(res.meta.total);
45
- }
46
- }, [run, list.query]);
47
-
48
- useEffect(() => {
49
- void fetch();
50
- }, [fetch]);
51
-
52
- return {
53
- rows,
54
- total,
55
- page: list.page,
56
- pageSize: list.pageSize,
57
- sorting: list.sorting,
58
- loading,
59
- setPage: list.setPage,
60
- setPageSize: list.setPageSize,
61
- setSorting: list.setSorting,
62
- filters: list.filters,
63
- refresh: fetch,
64
- };
65
- }
@@ -1,183 +0,0 @@
1
- "use client";
2
-
3
- import type {
4
- ColumnDef,
5
- OnChangeFn,
6
- PaginationState,
7
- SortingState,
8
- } from "@tanstack/react-table";
9
- import { Eye } from "lucide-react";
10
- import type { JSX } from "react";
11
- import { useMemo, useState } from "react";
12
-
13
- import {
14
- Badge,
15
- Button,
16
- DataTable,
17
- DataTableFeatures,
18
- Dialog,
19
- DialogContent,
20
- DialogHeader,
21
- DialogTitle,
22
- RowActions,
23
- } from "#core/components/ui";
24
- import { useI18n } from "#core/contexts";
25
- import { useErrorLogs } from "#core/features/logs/hooks/use-error-logs";
26
- import { ErrorLog, ErrorType } from "#core/features/logs/services/logs.service";
27
-
28
- function typeVariant(type: ErrorType): "warning" | "destructive" | "secondary" {
29
- if (type === "DATABASE" || type === "INTEGRATION" || type === "INTERNAL")
30
- {return "destructive";}
31
- if (type === "VALIDATION") {return "secondary";}
32
- return "warning";
33
- }
34
-
35
- export function ErrorLogsPanel(): JSX.Element {
36
- const { t } = useI18n();
37
- const logs = useErrorLogs();
38
- const [detail, setDetail] = useState<ErrorLog | null>(null);
39
-
40
- const columns = useMemo<ColumnDef<DataTableFeatures, ErrorLog, unknown>[]>(
41
- () => [
42
- {
43
- accessorKey: "createdAt",
44
- header: t("logs.date"),
45
- meta: { label: t("logs.date") },
46
- cell: ({ getValue }) => new Date(String(getValue())).toLocaleString(),
47
- },
48
- {
49
- accessorKey: "type",
50
- header: t("logs.type"),
51
- meta: { label: t("logs.type") },
52
- cell: ({ getValue }) => {
53
- const type = getValue() as ErrorType;
54
- return <Badge variant={typeVariant(type)}>{type}</Badge>;
55
- },
56
- },
57
- {
58
- accessorKey: "statusCode",
59
- header: t("logs.status"),
60
- meta: { label: t("logs.status") },
61
- },
62
- {
63
- accessorKey: "message",
64
- header: t("logs.message"),
65
- meta: { label: t("logs.message") },
66
- enableSorting: false,
67
- cell: ({ getValue }) => (
68
- <span className="line-clamp-1 max-w-md">{String(getValue())}</span>
69
- ),
70
- },
71
- {
72
- id: "user",
73
- header: t("logs.user"),
74
- meta: { label: t("logs.user") },
75
- enableSorting: false,
76
- cell: ({ row }) => row.original.user?.name ?? t("logs.systemUser"),
77
- },
78
- {
79
- id: "actions",
80
- header: () => <div className="text-center">{t("common.actions")}</div>,
81
- meta: { shrink: true },
82
- enableHiding: false,
83
- enableSorting: false,
84
- cell: ({ row }) => (
85
- <RowActions>
86
- <Button
87
- variant="ghost"
88
- size="sm"
89
- onClick={() => setDetail(row.original)}
90
- >
91
- <Eye className="h-4 w-4" />
92
- {t("logs.viewDetails")}
93
- </Button>
94
- </RowActions>
95
- ),
96
- },
97
- ],
98
-
99
- [t],
100
- );
101
-
102
- const pagination: PaginationState = {
103
- pageIndex: logs.page,
104
- pageSize: logs.pageSize,
105
- };
106
- const onPaginationChange: OnChangeFn<PaginationState> = (updater) => {
107
- const next = typeof updater === "function" ? updater(pagination) : updater;
108
- if (next.pageSize !== logs.pageSize) {
109
- logs.setPageSize(next.pageSize);
110
- logs.setPage(0);
111
- } else if (next.pageIndex !== logs.page) {
112
- logs.setPage(next.pageIndex);
113
- }
114
- };
115
- const onSortingChange: OnChangeFn<SortingState> = (updater) => {
116
- const next =
117
- typeof updater === "function" ? updater(logs.sorting) : updater;
118
- logs.setSorting(next);
119
- logs.setPage(0);
120
- };
121
-
122
- return (
123
- <div>
124
- <DataTable
125
- columns={columns}
126
- data={logs.rows}
127
- getRowId={(r) => r.id}
128
- storageKey="logs-errors"
129
- loading={logs.loading}
130
- manualPagination
131
- rowCount={logs.total}
132
- pagination={pagination}
133
- onPaginationChange={onPaginationChange}
134
- manualSorting
135
- sorting={logs.sorting}
136
- onSortingChange={onSortingChange}
137
- filters={logs.filters}
138
- />
139
-
140
- <Dialog open={!!detail} onOpenChange={(o) => !o && setDetail(null)}>
141
- <DialogContent className="max-w-2xl">
142
- <DialogHeader>
143
- <DialogTitle>
144
- {t("logs.detailsTitle")} — {detail?.type} ({detail?.statusCode})
145
- </DialogTitle>
146
- </DialogHeader>
147
- {detail && (
148
- <div className="flex min-w-0 flex-col gap-3 text-sm">
149
- <div>
150
- <span className="font-medium">{t("logs.route")}: </span>
151
- <span className="font-mono text-xs">
152
- {detail.method} {detail.path}
153
- </span>
154
- </div>
155
- <div>
156
- <span className="font-medium">{t("logs.message")}: </span>
157
- {detail.message}
158
- </div>
159
- <div>
160
- <span className="font-medium">{t("logs.user")}: </span>
161
- {detail.user?.name ?? t("logs.systemUser")}
162
- </div>
163
- <div>
164
- <span className="font-medium">{t("logs.requestId")}: </span>
165
- <span className="font-mono text-xs">
166
- {detail.requestId ?? "—"}
167
- </span>
168
- </div>
169
- {detail.stack && (
170
- <div className="min-w-0">
171
- <p className="mb-1 font-medium">{t("logs.stackTrace")}</p>
172
- <pre className="max-h-64 min-w-0 max-w-full overflow-auto rounded-md bg-muted p-3 text-xs">
173
- {detail.stack}
174
- </pre>
175
- </div>
176
- )}
177
- </div>
178
- )}
179
- </DialogContent>
180
- </Dialog>
181
- </div>
182
- );
183
- }