analytica-frontend-lib 1.1.34 → 1.1.36

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.
package/dist/index.js CHANGED
@@ -75,6 +75,7 @@ __export(src_exports, {
75
75
  NavButton: () => NavButton_default,
76
76
  NotFound: () => NotFound_default,
77
77
  NotificationCard: () => NotificationCard_default,
78
+ NotificationEntityType: () => NotificationEntityType,
78
79
  ProfileMenuFooter: () => ProfileMenuFooter,
79
80
  ProfileMenuHeader: () => ProfileMenuHeader,
80
81
  ProfileMenuSection: () => ProfileMenuSection,
@@ -107,6 +108,7 @@ __export(src_exports, {
107
108
  Radio: () => Radio_default,
108
109
  RadioGroup: () => RadioGroup,
109
110
  RadioGroupItem: () => RadioGroupItem,
111
+ SUBTYPE_ENUM: () => SUBTYPE_ENUM,
110
112
  Search: () => Search_default,
111
113
  Select: () => Select_default,
112
114
  SelectContent: () => SelectContent,
@@ -130,7 +132,10 @@ __export(src_exports, {
130
132
  Toaster: () => Toaster_default,
131
133
  VideoPlayer: () => VideoPlayer_default,
132
134
  Whiteboard: () => Whiteboard_default,
135
+ createNotificationStore: () => createNotificationStore,
136
+ createUseNotificationStore: () => createUseNotificationStore,
133
137
  createZustandAuthAdapter: () => createZustandAuthAdapter,
138
+ formatTimeAgo: () => formatTimeAgo,
134
139
  getDeviceType: () => getDeviceType,
135
140
  getRootDomain: () => getRootDomain,
136
141
  getStatusBadge: () => getStatusBadge,
@@ -8082,6 +8087,15 @@ var ANSWER_STATUS = /* @__PURE__ */ ((ANSWER_STATUS2) => {
8082
8087
  ANSWER_STATUS2["NAO_RESPONDIDO"] = "NAO_RESPONDIDO";
8083
8088
  return ANSWER_STATUS2;
8084
8089
  })(ANSWER_STATUS || {});
8090
+ var SUBTYPE_ENUM = /* @__PURE__ */ ((SUBTYPE_ENUM2) => {
8091
+ SUBTYPE_ENUM2["PROVA"] = "PROVA";
8092
+ SUBTYPE_ENUM2["ENEM_PROVA_1"] = "ENEM_PROVA_1";
8093
+ SUBTYPE_ENUM2["ENEM_PROVA_2"] = "ENEM_PROVA_2";
8094
+ SUBTYPE_ENUM2["VESTIBULAR"] = "VESTIBULAR";
8095
+ SUBTYPE_ENUM2["SIMULADO"] = "SIMULADO";
8096
+ SUBTYPE_ENUM2["SIMULADAO"] = "SIMULADAO";
8097
+ return SUBTYPE_ENUM2;
8098
+ })(SUBTYPE_ENUM || {});
8085
8099
  var MINUTE_INTERVAL_MS = 6e4;
8086
8100
  var useQuizStore = (0, import_zustand7.create)()(
8087
8101
  (0, import_middleware.devtools)(
@@ -8767,26 +8781,65 @@ var QuizTitle = (0, import_react28.forwardRef)(
8767
8781
  formatTime: formatTime2,
8768
8782
  isStarted
8769
8783
  } = useQuizStore();
8784
+ const [showExitConfirmation, setShowExitConfirmation] = (0, import_react28.useState)(false);
8770
8785
  const totalQuestions = getTotalQuestions();
8771
8786
  const quizTitle = getQuizTitle();
8772
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8773
- "div",
8774
- {
8775
- ref,
8776
- className: cn(
8777
- "flex flex-row justify-center items-center relative p-2",
8778
- className
8779
- ),
8780
- ...props,
8781
- children: [
8782
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "flex flex-col gap-2 text-center", children: [
8783
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-950 font-bold text-md", children: quizTitle }),
8784
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-600 text-xs", children: totalQuestions > 0 ? `${currentQuestionIndex + 1} de ${totalQuestions}` : "0 de 0" })
8785
- ] }),
8786
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "absolute right-2", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "outlined", action: "info", iconLeft: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_phosphor_react20.Clock, {}), children: isStarted ? formatTime2(timeElapsed) : "00:00" }) })
8787
- ]
8787
+ const handleBackClick = () => {
8788
+ if (isStarted) {
8789
+ setShowExitConfirmation(true);
8790
+ } else {
8791
+ window.history.back();
8788
8792
  }
8789
- );
8793
+ };
8794
+ const handleConfirmExit = () => {
8795
+ setShowExitConfirmation(false);
8796
+ window.history.back();
8797
+ };
8798
+ const handleCancelExit = () => {
8799
+ setShowExitConfirmation(false);
8800
+ };
8801
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
8802
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8803
+ "div",
8804
+ {
8805
+ ref,
8806
+ className: cn(
8807
+ "flex flex-row justify-between items-center relative p-2",
8808
+ className
8809
+ ),
8810
+ ...props,
8811
+ children: [
8812
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8813
+ IconButton_default,
8814
+ {
8815
+ icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_phosphor_react20.CaretLeft, { size: 24 }),
8816
+ size: "md",
8817
+ "aria-label": "Voltar",
8818
+ onClick: handleBackClick
8819
+ }
8820
+ ),
8821
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "flex flex-col gap-2 text-center", children: [
8822
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-950 font-bold text-md", children: quizTitle }),
8823
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-600 text-xs", children: totalQuestions > 0 ? `${currentQuestionIndex + 1} de ${totalQuestions}` : "0 de 0" })
8824
+ ] }),
8825
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "flex flex-row items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "outlined", action: "info", iconLeft: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_phosphor_react20.Clock, {}), children: isStarted ? formatTime2(timeElapsed) : "00:00" }) })
8826
+ ]
8827
+ }
8828
+ ),
8829
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8830
+ AlertDialog,
8831
+ {
8832
+ isOpen: showExitConfirmation,
8833
+ onChangeOpen: setShowExitConfirmation,
8834
+ title: "Deseja sair?",
8835
+ description: "Se voc\xEA sair do simulado agora, todas as respostas ser\xE3o perdidas.",
8836
+ cancelButtonLabel: "Voltar e revisar",
8837
+ submitButtonLabel: "Sair Mesmo Assim",
8838
+ onSubmit: handleConfirmExit,
8839
+ onCancel: handleCancelExit
8840
+ }
8841
+ )
8842
+ ] });
8790
8843
  }
8791
8844
  );
8792
8845
  var QuizSubTitle = (0, import_react28.forwardRef)(
@@ -9870,17 +9923,21 @@ var QuizFooter = (0, import_react28.forwardRef)(
9870
9923
  ] });
9871
9924
  }
9872
9925
  );
9873
- var QuizBadge = ({ subtype }) => {
9926
+ var QuizBadge = ({
9927
+ subtype
9928
+ }) => {
9874
9929
  switch (subtype) {
9875
- case "PROVA":
9876
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", "data-testid": "quiz-badge", children: "Prova" });
9877
- case "ENEM":
9878
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", "data-testid": "quiz-badge", children: "Enem" });
9879
- case "VESTIBULAR":
9880
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", "data-testid": "quiz-badge", children: "Vestibular" });
9881
- case "SIMULADO":
9882
- case null:
9883
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", "data-testid": "quiz-badge", children: "Simulado" });
9930
+ case "PROVA" /* PROVA */:
9931
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "examsOutlined", action: "exam2", "data-testid": "quiz-badge", children: "Prova" });
9932
+ case "ENEM_PROVA_1" /* ENEM_PROVA_1 */:
9933
+ case "ENEM_PROVA_2" /* ENEM_PROVA_2 */:
9934
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "examsOutlined", action: "exam1", "data-testid": "quiz-badge", children: "Enem" });
9935
+ case "VESTIBULAR" /* VESTIBULAR */:
9936
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "examsOutlined", action: "exam4", "data-testid": "quiz-badge", children: "Vestibular" });
9937
+ case "SIMULADO" /* SIMULADO */:
9938
+ case "SIMULADAO" /* SIMULADAO */:
9939
+ case void 0:
9940
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "examsOutlined", action: "exam3", "data-testid": "quiz-badge", children: "Simulad\xE3o" });
9884
9941
  default:
9885
9942
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Badge_default, { variant: "solid", action: "info", "data-testid": "quiz-badge", children: subtype });
9886
9943
  }
@@ -9896,7 +9953,7 @@ var QuizResultHeaderTitle = (0, import_react28.forwardRef)(({ className, ...prop
9896
9953
  ...props,
9897
9954
  children: [
9898
9955
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-text-950 font-bold text-2xl", children: "Resultado" }),
9899
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuizBadge, { subtype: activeQuiz?.quiz.subtype || null })
9956
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(QuizBadge, { subtype: activeQuiz?.quiz.subtype || void 0 })
9900
9957
  ]
9901
9958
  }
9902
9959
  );
@@ -10177,7 +10234,282 @@ var loadingModal_default = LoadingModal;
10177
10234
 
10178
10235
  // src/components/NotificationCard/NotificationCard.tsx
10179
10236
  var import_phosphor_react21 = require("phosphor-react");
10237
+ var import_react30 = require("react");
10238
+
10239
+ // src/store/notificationStore.ts
10240
+ var import_zustand8 = require("zustand");
10241
+ var import_middleware2 = require("zustand/middleware");
10242
+
10243
+ // src/types/notifications.ts
10244
+ var NotificationEntityType = /* @__PURE__ */ ((NotificationEntityType2) => {
10245
+ NotificationEntityType2["ACTIVITY"] = "ACTIVITY";
10246
+ NotificationEntityType2["TRAIL"] = "TRAIL";
10247
+ NotificationEntityType2["GOAL"] = "GOAL";
10248
+ return NotificationEntityType2;
10249
+ })(NotificationEntityType || {});
10250
+
10251
+ // src/store/notificationStore.ts
10252
+ var mapBackendNotification = (backendNotification) => {
10253
+ let type = "GENERAL";
10254
+ let entityType = null;
10255
+ if (backendNotification.entityType) {
10256
+ const backendEntityType = backendNotification.entityType.toUpperCase();
10257
+ switch (backendEntityType) {
10258
+ case "ACTIVITY" /* ACTIVITY */:
10259
+ type = "ACTIVITY";
10260
+ entityType = "ACTIVITY" /* ACTIVITY */;
10261
+ break;
10262
+ case "TRAIL" /* TRAIL */:
10263
+ type = "TRAIL";
10264
+ entityType = "TRAIL" /* TRAIL */;
10265
+ break;
10266
+ case "GOAL" /* GOAL */:
10267
+ type = "GOAL";
10268
+ entityType = "GOAL" /* GOAL */;
10269
+ break;
10270
+ default:
10271
+ break;
10272
+ }
10273
+ }
10274
+ return {
10275
+ id: backendNotification.id,
10276
+ title: backendNotification.title,
10277
+ message: backendNotification.description,
10278
+ type,
10279
+ isRead: backendNotification.read,
10280
+ createdAt: new Date(backendNotification.createdAt),
10281
+ entityType,
10282
+ entityId: backendNotification.entityId,
10283
+ sender: backendNotification.sender,
10284
+ activity: backendNotification.activity,
10285
+ goal: backendNotification.goal
10286
+ };
10287
+ };
10288
+ var groupNotificationsByTime = (notifications) => {
10289
+ const now = /* @__PURE__ */ new Date();
10290
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
10291
+ const lastWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1e3);
10292
+ const sortDesc = (a, b) => +new Date(b.createdAt) - +new Date(a.createdAt);
10293
+ const todayNotifications = notifications.filter((notification) => new Date(notification.createdAt) >= today).sort(sortDesc);
10294
+ const lastWeekNotifications = notifications.filter(
10295
+ (notification) => new Date(notification.createdAt) >= lastWeek && new Date(notification.createdAt) < today
10296
+ ).sort(sortDesc);
10297
+ const olderNotifications = notifications.filter((notification) => new Date(notification.createdAt) < lastWeek).sort(sortDesc);
10298
+ const groups = [];
10299
+ if (todayNotifications.length > 0) {
10300
+ groups.push({
10301
+ label: "Hoje",
10302
+ notifications: todayNotifications
10303
+ });
10304
+ }
10305
+ if (lastWeekNotifications.length > 0) {
10306
+ groups.push({
10307
+ label: "\xDAltima semana",
10308
+ notifications: lastWeekNotifications
10309
+ });
10310
+ }
10311
+ if (olderNotifications.length > 0) {
10312
+ groups.push({
10313
+ label: "Mais antigas",
10314
+ notifications: olderNotifications
10315
+ });
10316
+ }
10317
+ return groups;
10318
+ };
10319
+ var formatTimeAgo = (date) => {
10320
+ const now = /* @__PURE__ */ new Date();
10321
+ const diffInMs = now.getTime() - new Date(date).getTime();
10322
+ const diffInHours = Math.floor(diffInMs / (1e3 * 60 * 60));
10323
+ const diffInDays = Math.floor(diffInMs / (1e3 * 60 * 60 * 24));
10324
+ if (diffInHours < 24) {
10325
+ return `H\xE1 ${diffInHours}h`;
10326
+ } else if (diffInDays < 30) {
10327
+ const day = new Date(date).getDate();
10328
+ const months = [
10329
+ "Jan",
10330
+ "Fev",
10331
+ "Mar",
10332
+ "Abr",
10333
+ "Mai",
10334
+ "Jun",
10335
+ "Jul",
10336
+ "Ago",
10337
+ "Set",
10338
+ "Out",
10339
+ "Nov",
10340
+ "Dez"
10341
+ ];
10342
+ const month = months[new Date(date).getMonth()];
10343
+ return `${day} ${month}`;
10344
+ }
10345
+ return new Date(date).toLocaleDateString("pt-BR");
10346
+ };
10347
+ var createNotificationStore = (apiClient) => {
10348
+ return (0, import_zustand8.create)()(
10349
+ (0, import_middleware2.devtools)(
10350
+ (set, get) => ({
10351
+ // Initial state
10352
+ notifications: [],
10353
+ unreadCount: 0,
10354
+ loading: false,
10355
+ error: null,
10356
+ hasMore: true,
10357
+ currentPage: 1,
10358
+ // Actions
10359
+ fetchNotifications: async (params = {}) => {
10360
+ set({ loading: true, error: null });
10361
+ try {
10362
+ const response = await apiClient.get(
10363
+ "/notifications",
10364
+ { params: { ...params } }
10365
+ );
10366
+ const mappedNotifications = response.data.notifications.map(
10367
+ mapBackendNotification
10368
+ );
10369
+ const page = response.data.pagination.page;
10370
+ const totalPages = response.data.pagination.totalPages;
10371
+ const merged = params.page && params.page > 1 ? [...get().notifications, ...mappedNotifications] : mappedNotifications;
10372
+ const deduped = Array.from(
10373
+ new Map(merged.map((n) => [n.id, n])).values()
10374
+ );
10375
+ set({
10376
+ notifications: deduped,
10377
+ unreadCount: deduped.filter((n) => !n.isRead).length,
10378
+ hasMore: page < totalPages,
10379
+ currentPage: page,
10380
+ loading: false
10381
+ });
10382
+ } catch (error) {
10383
+ console.error("Error fetching notifications:", error);
10384
+ set({
10385
+ error: "Erro ao carregar notifica\xE7\xF5es",
10386
+ loading: false
10387
+ });
10388
+ }
10389
+ },
10390
+ markAsRead: async (id) => {
10391
+ const { notifications } = get();
10392
+ const notification = notifications.find((n) => n.id === id);
10393
+ if (notification?.isRead) {
10394
+ return;
10395
+ }
10396
+ try {
10397
+ await apiClient.patch(`/notifications/${id}`, { read: true });
10398
+ const updatedNotifications = notifications.map(
10399
+ (notification2) => notification2.id === id ? { ...notification2, isRead: true } : notification2
10400
+ );
10401
+ const unreadCount = updatedNotifications.filter(
10402
+ (n) => !n.isRead
10403
+ ).length;
10404
+ set({
10405
+ notifications: updatedNotifications,
10406
+ unreadCount
10407
+ });
10408
+ } catch (error) {
10409
+ console.error("Error marking notification as read:", error);
10410
+ set({ error: "Erro ao marcar notifica\xE7\xE3o como lida" });
10411
+ }
10412
+ },
10413
+ markAllAsRead: async () => {
10414
+ const { notifications } = get();
10415
+ try {
10416
+ const unreadNotifications = notifications.filter((n) => !n.isRead);
10417
+ await Promise.all(
10418
+ unreadNotifications.map(
10419
+ (notification) => apiClient.patch(`/notifications/${notification.id}`, {
10420
+ read: true
10421
+ })
10422
+ )
10423
+ );
10424
+ const updatedNotifications = notifications.map((notification) => ({
10425
+ ...notification,
10426
+ isRead: true
10427
+ }));
10428
+ set({
10429
+ notifications: updatedNotifications,
10430
+ unreadCount: 0
10431
+ });
10432
+ } catch (error) {
10433
+ console.error("Error marking all notifications as read:", error);
10434
+ set({ error: "Erro ao marcar todas as notifica\xE7\xF5es como lidas" });
10435
+ }
10436
+ },
10437
+ deleteNotification: async (id) => {
10438
+ const { notifications } = get();
10439
+ try {
10440
+ await apiClient.delete(`/notifications/${id}`);
10441
+ const updatedNotifications = notifications.filter(
10442
+ (notification) => notification.id !== id
10443
+ );
10444
+ const unreadCount = updatedNotifications.filter(
10445
+ (n) => !n.isRead
10446
+ ).length;
10447
+ set({
10448
+ notifications: updatedNotifications,
10449
+ unreadCount
10450
+ });
10451
+ } catch (error) {
10452
+ console.error("Error deleting notification:", error);
10453
+ set({ error: "Erro ao deletar notifica\xE7\xE3o" });
10454
+ }
10455
+ },
10456
+ clearNotifications: () => {
10457
+ set({
10458
+ notifications: [],
10459
+ unreadCount: 0,
10460
+ hasMore: false,
10461
+ currentPage: 1
10462
+ });
10463
+ },
10464
+ resetError: () => {
10465
+ set({ error: null });
10466
+ },
10467
+ getGroupedNotifications: () => {
10468
+ const { notifications } = get();
10469
+ return groupNotificationsByTime(notifications);
10470
+ }
10471
+ }),
10472
+ {
10473
+ name: "notification-store"
10474
+ }
10475
+ )
10476
+ );
10477
+ };
10478
+
10479
+ // src/components/NotificationCard/NotificationCard.tsx
10180
10480
  var import_jsx_runtime41 = require("react/jsx-runtime");
10481
+ var NotificationEmpty = ({
10482
+ emptyStateImage,
10483
+ emptyStateTitle = "Nenhuma notifica\xE7\xE3o no momento",
10484
+ emptyStateDescription = "Voc\xEA est\xE1 em dia com todas as novidades. Volte depois para conferir atualiza\xE7\xF5es!"
10485
+ }) => {
10486
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-col items-center justify-center gap-4 p-6 w-full", children: [
10487
+ emptyStateImage && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "w-20 h-20 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10488
+ "img",
10489
+ {
10490
+ src: emptyStateImage,
10491
+ alt: "Sem notifica\xE7\xF5es",
10492
+ width: 82,
10493
+ height: 82,
10494
+ className: "object-contain"
10495
+ }
10496
+ ) }),
10497
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h3", { className: "text-xl font-semibold text-text-950 text-center leading-[23px]", children: emptyStateTitle }),
10498
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm font-normal text-text-400 text-center max-w-[316px] leading-[21px]", children: emptyStateDescription })
10499
+ ] });
10500
+ };
10501
+ var NotificationHeader = ({
10502
+ unreadCount,
10503
+ variant = "modal"
10504
+ }) => {
10505
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center justify-between", children: [
10506
+ variant === "modal" ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Text_default, { size: "sm", weight: "bold", className: "text-text-950", children: "Notifica\xE7\xF5es" }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h3", { className: "text-sm font-semibold text-text-950", children: "Notifica\xE7\xF5es" }),
10507
+ unreadCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "px-2 py-1 bg-info-100 text-info-700 text-xs rounded-full", children: [
10508
+ unreadCount,
10509
+ " n\xE3o lidas"
10510
+ ] })
10511
+ ] });
10512
+ };
10181
10513
  var SingleNotificationCard = ({
10182
10514
  title,
10183
10515
  message,
@@ -10296,7 +10628,7 @@ var NotificationList = ({
10296
10628
  ) });
10297
10629
  }
10298
10630
  if (!groupedNotifications || groupedNotifications.length === 0) {
10299
- return renderEmpty ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "w-full", children: renderEmpty() }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex flex-col items-center justify-center gap-4 p-6 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm text-text-400", children: "Nenhuma notifica\xE7\xE3o encontrada" }) });
10631
+ return renderEmpty ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "w-full", children: renderEmpty() }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(NotificationEmpty, {});
10300
10632
  }
10301
10633
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: cn("flex flex-col gap-0 w-full", className), children: groupedNotifications.map((group, idx) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-col", children: [
10302
10634
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex items-end px-4 py-6 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h4", { className: "text-lg font-bold text-text-500 flex-grow", children: group.label }) }),
@@ -10305,49 +10637,234 @@ var NotificationList = ({
10305
10637
  {
10306
10638
  title: notification.title,
10307
10639
  message: notification.message,
10308
- time: notification.time,
10640
+ time: notification.time ?? formatTimeAgo(new Date(notification.createdAt)),
10309
10641
  isRead: notification.isRead,
10310
10642
  onMarkAsRead: () => onMarkAsReadById?.(notification.id),
10311
10643
  onDelete: () => onDeleteById?.(notification.id),
10312
10644
  onNavigate: notification.entityType && notification.entityId && onNavigateById ? () => onNavigateById(
10313
- notification.entityType,
10314
- notification.entityId
10645
+ notification.entityType ?? void 0,
10646
+ notification.entityId ?? void 0
10315
10647
  ) : void 0,
10316
- actionLabel: getActionLabel?.(notification.entityType)
10648
+ actionLabel: getActionLabel?.(
10649
+ notification.entityType ?? void 0
10650
+ )
10317
10651
  },
10318
10652
  notification.id
10319
10653
  ))
10320
10654
  ] }, `${group.label}-${idx}`)) });
10321
10655
  };
10322
- var NotificationCard = (props) => {
10323
- if (props.groupedNotifications !== void 0 || props.notifications !== void 0 || props.loading || props.error) {
10324
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10325
- NotificationList,
10656
+ var NotificationCenter = ({
10657
+ isActive,
10658
+ onToggleActive,
10659
+ unreadCount = 0,
10660
+ groupedNotifications = [],
10661
+ loading = false,
10662
+ error = null,
10663
+ onRetry,
10664
+ onMarkAsReadById,
10665
+ onDeleteById,
10666
+ onNavigateById,
10667
+ getActionLabel,
10668
+ onFetchNotifications,
10669
+ onMarkAllAsRead,
10670
+ emptyStateImage,
10671
+ emptyStateTitle,
10672
+ emptyStateDescription,
10673
+ className
10674
+ }) => {
10675
+ const { isMobile } = useMobile();
10676
+ const [isModalOpen, setIsModalOpen] = (0, import_react30.useState)(false);
10677
+ const handleMobileClick = () => {
10678
+ setIsModalOpen(true);
10679
+ onFetchNotifications?.();
10680
+ };
10681
+ const handleDesktopClick = () => {
10682
+ onToggleActive?.();
10683
+ };
10684
+ (0, import_react30.useEffect)(() => {
10685
+ if (isActive) {
10686
+ onFetchNotifications?.();
10687
+ }
10688
+ }, [isActive, onFetchNotifications]);
10689
+ const handleNavigate = (entityType, entityId, onCleanup) => {
10690
+ onCleanup?.();
10691
+ onNavigateById?.(entityType, entityId);
10692
+ };
10693
+ const renderEmptyState = () => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10694
+ NotificationEmpty,
10695
+ {
10696
+ emptyStateImage,
10697
+ emptyStateTitle,
10698
+ emptyStateDescription
10699
+ }
10700
+ );
10701
+ if (isMobile) {
10702
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
10703
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10704
+ IconButton_default,
10705
+ {
10706
+ active: isModalOpen,
10707
+ onClick: handleMobileClick,
10708
+ icon: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_phosphor_react21.Bell, { size: 24, className: "text-primary" }),
10709
+ className
10710
+ }
10711
+ ),
10712
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10713
+ Modal_default,
10714
+ {
10715
+ isOpen: isModalOpen,
10716
+ onClose: () => setIsModalOpen(false),
10717
+ title: "Notifica\xE7\xF5es",
10718
+ size: "md",
10719
+ hideCloseButton: false,
10720
+ closeOnBackdropClick: true,
10721
+ closeOnEscape: true,
10722
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-col h-full max-h-[80vh]", children: [
10723
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "px-0 pb-3 border-b border-border-200", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center justify-between", children: [
10724
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(NotificationHeader, { unreadCount, variant: "modal" }),
10725
+ unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10726
+ "button",
10727
+ {
10728
+ type: "button",
10729
+ onClick: onMarkAllAsRead,
10730
+ className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer",
10731
+ children: "Marcar todas como lidas"
10732
+ }
10733
+ )
10734
+ ] }) }),
10735
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10736
+ NotificationList,
10737
+ {
10738
+ groupedNotifications,
10739
+ loading,
10740
+ error,
10741
+ onRetry,
10742
+ onMarkAsReadById,
10743
+ onDeleteById,
10744
+ onNavigateById: (entityType, entityId) => handleNavigate(
10745
+ entityType,
10746
+ entityId,
10747
+ () => setIsModalOpen(false)
10748
+ ),
10749
+ getActionLabel,
10750
+ renderEmpty: renderEmptyState
10751
+ }
10752
+ ) })
10753
+ ] })
10754
+ }
10755
+ )
10756
+ ] });
10757
+ }
10758
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(DropdownMenu_default, { children: [
10759
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(DropdownMenuTrigger, { className: "text-primary cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10760
+ IconButton_default,
10326
10761
  {
10327
- ...props,
10328
- groupedNotifications: props.groupedNotifications ?? (props.notifications ? [{ label: "Notifica\xE7\xF5es", notifications: props.notifications }] : [])
10762
+ active: isActive,
10763
+ onClick: handleDesktopClick,
10764
+ icon: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10765
+ import_phosphor_react21.Bell,
10766
+ {
10767
+ size: 24,
10768
+ className: isActive ? "text-primary-950" : "text-primary"
10769
+ }
10770
+ ),
10771
+ className
10329
10772
  }
10330
- );
10331
- }
10332
- if (props.title !== void 0 && props.message !== void 0 && props.time !== void 0 && props.isRead !== void 0 && props.onMarkAsRead && props.onDelete) {
10333
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10334
- SingleNotificationCard,
10773
+ ) }),
10774
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10775
+ DropdownMenuContent,
10335
10776
  {
10336
- title: props.title,
10337
- message: props.message,
10338
- time: props.time,
10339
- isRead: props.isRead,
10340
- onMarkAsRead: props.onMarkAsRead,
10341
- onDelete: props.onDelete,
10342
- onNavigate: props.onNavigate,
10343
- actionLabel: props.actionLabel,
10344
- className: props.className
10777
+ className: "min-w-[320px] max-w-[400px] max-h-[500px] overflow-hidden",
10778
+ side: "bottom",
10779
+ align: "end",
10780
+ children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex flex-col", children: [
10781
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "px-4 py-3 border-b border-border-200", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center justify-between", children: [
10782
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10783
+ NotificationHeader,
10784
+ {
10785
+ unreadCount,
10786
+ variant: "dropdown"
10787
+ }
10788
+ ),
10789
+ unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10790
+ "button",
10791
+ {
10792
+ type: "button",
10793
+ onClick: onMarkAllAsRead,
10794
+ className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer",
10795
+ children: "Marcar todas como lidas"
10796
+ }
10797
+ )
10798
+ ] }) }),
10799
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "max-h-[350px] overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10800
+ NotificationList,
10801
+ {
10802
+ groupedNotifications,
10803
+ loading,
10804
+ error,
10805
+ onRetry,
10806
+ onMarkAsReadById,
10807
+ onDeleteById,
10808
+ onNavigateById: (entityType, entityId) => handleNavigate(entityType, entityId, onToggleActive),
10809
+ getActionLabel,
10810
+ renderEmpty: renderEmptyState
10811
+ }
10812
+ ) })
10813
+ ] })
10345
10814
  }
10346
- );
10815
+ )
10816
+ ] });
10817
+ };
10818
+ var NotificationCard = (props) => {
10819
+ switch (props.mode) {
10820
+ case "single":
10821
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10822
+ SingleNotificationCard,
10823
+ {
10824
+ title: props.title,
10825
+ message: props.message,
10826
+ time: props.time,
10827
+ isRead: props.isRead,
10828
+ onMarkAsRead: props.onMarkAsRead,
10829
+ onDelete: props.onDelete,
10830
+ onNavigate: props.onNavigate,
10831
+ actionLabel: props.actionLabel,
10832
+ className: props.className
10833
+ }
10834
+ );
10835
+ case "list":
10836
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
10837
+ NotificationList,
10838
+ {
10839
+ groupedNotifications: props.groupedNotifications ?? (props.notifications ? [
10840
+ {
10841
+ label: "Notifica\xE7\xF5es",
10842
+ notifications: props.notifications
10843
+ }
10844
+ ] : []),
10845
+ loading: props.loading,
10846
+ error: props.error,
10847
+ onRetry: props.onRetry,
10848
+ onMarkAsReadById: props.onMarkAsReadById,
10849
+ onDeleteById: props.onDeleteById,
10850
+ onNavigateById: props.onNavigateById,
10851
+ getActionLabel: props.getActionLabel,
10852
+ renderEmpty: props.renderEmpty,
10853
+ className: props.className
10854
+ }
10855
+ );
10856
+ case "center":
10857
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(NotificationCenter, { ...props });
10858
+ default:
10859
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex flex-col items-center gap-4 p-6 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm text-text-600", children: "Modo de notifica\xE7\xE3o n\xE3o reconhecido" }) });
10347
10860
  }
10348
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex flex-col items-center gap-4 p-6 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm text-text-600", children: "Nenhuma notifica\xE7\xE3o configurada" }) });
10349
10861
  };
10350
10862
  var NotificationCard_default = NotificationCard;
10863
+
10864
+ // src/hooks/useNotificationStore.ts
10865
+ var createUseNotificationStore = (apiClient) => {
10866
+ return createNotificationStore(apiClient);
10867
+ };
10351
10868
  // Annotate the CommonJS export names for ESM import in node:
10352
10869
  0 && (module.exports = {
10353
10870
  ANSWER_STATUS,
@@ -10395,6 +10912,7 @@ var NotificationCard_default = NotificationCard;
10395
10912
  NavButton,
10396
10913
  NotFound,
10397
10914
  NotificationCard,
10915
+ NotificationEntityType,
10398
10916
  ProfileMenuFooter,
10399
10917
  ProfileMenuHeader,
10400
10918
  ProfileMenuSection,
@@ -10427,6 +10945,7 @@ var NotificationCard_default = NotificationCard;
10427
10945
  Radio,
10428
10946
  RadioGroup,
10429
10947
  RadioGroupItem,
10948
+ SUBTYPE_ENUM,
10430
10949
  Search,
10431
10950
  Select,
10432
10951
  SelectContent,
@@ -10450,7 +10969,10 @@ var NotificationCard_default = NotificationCard;
10450
10969
  Toaster,
10451
10970
  VideoPlayer,
10452
10971
  Whiteboard,
10972
+ createNotificationStore,
10973
+ createUseNotificationStore,
10453
10974
  createZustandAuthAdapter,
10975
+ formatTimeAgo,
10454
10976
  getDeviceType,
10455
10977
  getRootDomain,
10456
10978
  getStatusBadge,