@greatapps/common 1.1.17 → 1.1.19

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.
@@ -39,7 +39,7 @@ function ProfilePopover({
39
39
  };
40
40
  const hasSubscription = !isSubscriptionLoading && subscription !== null;
41
41
  const showCreditsSkeleton = hasSubscription && isCreditsLoading;
42
- const showCredits = hasSubscription && !isCreditsLoading && summary.totalCredits > 0;
42
+ const showCredits = hasSubscription && !isCreditsLoading;
43
43
  const creditsPercentage = showCredits && summary.totalCredits > 0 ? summary.usedCredits / summary.totalCredits * 100 : 0;
44
44
  return /* @__PURE__ */ jsxs(Fragment, { children: [
45
45
  isLoggingOut && logoutOverlay,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { useState } from \"react\";\r\nimport { useRouter } from \"next/navigation\";\r\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\r\nimport { Popover } from \"../ui/overlay/Popover\";\r\nimport { Button } from \"../ui/buttons/Button\";\r\nimport { Progress } from \"../ui/feedback/Progress\";\r\nimport { Separator } from \"../ui/data-display/Separator\";\r\nimport { NavBarItem } from \"./NavBarItem\";\r\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\r\nimport { useAuth } from \"../../providers/auth.provider\";\r\nimport { cn } from \"../../infra/utils/clsx\";\r\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\r\n\r\nexport interface ProfileMenuItem {\r\n icon?: React.ReactNode;\r\n label: string;\r\n onClick: () => void;\r\n}\r\n\r\nexport interface ProfilePopoverProps {\r\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\r\n align?: \"start\" | \"center\" | \"end\";\r\n contentClassName?: string;\r\n onEditProfile?: () => void;\r\n onCreditsClick?: () => void;\r\n menuItems?: ProfileMenuItem[];\r\n logoutRedirect?: string;\r\n logoutOverlay?: React.ReactNode;\r\n}\r\n\r\nfunction ProfilePopover({\r\n side = \"top\",\r\n align = \"start\",\r\n contentClassName = \"absolute bottom-2 left-[26px]\",\r\n onEditProfile,\r\n onCreditsClick,\r\n menuItems = [],\r\n logoutRedirect = \"/login\",\r\n logoutOverlay,\r\n}: ProfilePopoverProps) {\r\n const router = useRouter();\r\n const { user, logout } = useAuth();\r\n const [isLoggingOut, setIsLoggingOut] = useState(false);\r\n\r\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\r\n useIaCredits();\r\n\r\n const handleLogout = async () => {\r\n try {\r\n setIsLoggingOut(true);\r\n await logout();\r\n router.push(logoutRedirect);\r\n } catch (error) {\r\n console.error(\"Erro ao fazer logout:\", error);\r\n } finally {\r\n setIsLoggingOut(false);\r\n }\r\n };\r\n\r\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\r\n const showCreditsSkeleton = hasSubscription && isCreditsLoading;\r\n const showCredits =\r\n hasSubscription && !isCreditsLoading && summary.totalCredits > 0;\r\n const creditsPercentage =\r\n showCredits && summary.totalCredits > 0\r\n ? (summary.usedCredits / summary.totalCredits) * 100\r\n : 0;\r\n\r\n return (\r\n <>\r\n {isLoggingOut && logoutOverlay}\r\n <Popover>\r\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\r\n {user && (\r\n <UserAvatar\r\n key={user.id}\r\n photo={user.photo}\r\n name={user.name}\r\n size={40}\r\n />\r\n )}\r\n </PopoverPrimitive.Trigger>\r\n\r\n <PopoverPrimitive.Portal>\r\n <PopoverPrimitive.Content\r\n className={cn(\r\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\r\n contentClassName,\r\n )}\r\n side={side}\r\n align={align}\r\n sideOffset={8}\r\n >\r\n <div className=\"grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full\">\r\n {user && (\r\n <UserAvatar\r\n key={user.id}\r\n photo={user.photo}\r\n name={user.name}\r\n size={32}\r\n />\r\n )}\r\n\r\n <div className=\"flex flex-col gap-0.5 min-w-0\">\r\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\r\n {user?.name || \"\"}\r\n </span>\r\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\r\n {user?.email || \"\"}\r\n </span>\r\n </div>\r\n\r\n {onEditProfile && (\r\n <Button\r\n variant=\"secondary\"\r\n className=\"paragraph-small-semibold h-8! whitespace-nowrap px-3 w-fit\"\r\n onClick={onEditProfile}\r\n >\r\n Editar Perfil\r\n </Button>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\r\n {showCreditsSkeleton && (\r\n <div className=\"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4\">\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\r\n Créditos usados\r\n </span>\r\n <div className=\"h-3.5 w-16 rounded bg-white/20 animate-pulse\" />\r\n </div>\r\n <div className=\"h-1.5 w-full rounded-full bg-white/20 animate-pulse\" />\r\n </div>\r\n )}\r\n\r\n {showCredits && (\r\n <div\r\n className={cn(\r\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\r\n onCreditsClick && \"cursor-pointer hover:bg-gray-900\",\r\n )}\r\n onClick={onCreditsClick}\r\n >\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\r\n Créditos usados\r\n </span>\r\n <span className=\"paragraph-xsmall-medium text-white/50\">\r\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\r\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\r\n </span>\r\n </div>\r\n <Progress\r\n className=\"bg-white/10\"\r\n indicatorColor=\"bg-white\"\r\n value={creditsPercentage}\r\n />\r\n </div>\r\n )}\r\n\r\n <div className=\"flex flex-col gap-2\">\r\n {menuItems.length > 0 && (\r\n <div className=\"flex flex-col\">\r\n {menuItems.map((item, index) => (\r\n <NavBarItem\r\n key={index}\r\n icon={item.icon}\r\n label={item.label}\r\n onClick={item.onClick}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n <Separator />\r\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\r\n </div>\r\n </div>\r\n </PopoverPrimitive.Content>\r\n </PopoverPrimitive.Portal>\r\n </Popover>\r\n </>\r\n );\r\n}\r\n\r\nexport { ProfilePopover };\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { useState } from \"react\";\r\nimport { useRouter } from \"next/navigation\";\r\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\r\nimport { Popover } from \"../ui/overlay/Popover\";\r\nimport { Button } from \"../ui/buttons/Button\";\r\nimport { Progress } from \"../ui/feedback/Progress\";\r\nimport { Separator } from \"../ui/data-display/Separator\";\r\nimport { NavBarItem } from \"./NavBarItem\";\r\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\r\nimport { useAuth } from \"../../providers/auth.provider\";\r\nimport { cn } from \"../../infra/utils/clsx\";\r\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\r\n\r\nexport interface ProfileMenuItem {\r\n icon?: React.ReactNode;\r\n label: string;\r\n onClick: () => void;\r\n}\r\n\r\nexport interface ProfilePopoverProps {\r\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\r\n align?: \"start\" | \"center\" | \"end\";\r\n contentClassName?: string;\r\n onEditProfile?: () => void;\r\n onCreditsClick?: () => void;\r\n menuItems?: ProfileMenuItem[];\r\n logoutRedirect?: string;\r\n logoutOverlay?: React.ReactNode;\r\n}\r\n\r\nfunction ProfilePopover({\r\n side = \"top\",\r\n align = \"start\",\r\n contentClassName = \"absolute bottom-2 left-[26px]\",\r\n onEditProfile,\r\n onCreditsClick,\r\n menuItems = [],\r\n logoutRedirect = \"/login\",\r\n logoutOverlay,\r\n}: ProfilePopoverProps) {\r\n const router = useRouter();\r\n const { user, logout } = useAuth();\r\n const [isLoggingOut, setIsLoggingOut] = useState(false);\r\n\r\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\r\n useIaCredits();\r\n\r\n const handleLogout = async () => {\r\n try {\r\n setIsLoggingOut(true);\r\n await logout();\r\n router.push(logoutRedirect);\r\n } catch (error) {\r\n console.error(\"Erro ao fazer logout:\", error);\r\n } finally {\r\n setIsLoggingOut(false);\r\n }\r\n };\r\n\r\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\r\n const showCreditsSkeleton = hasSubscription && isCreditsLoading;\r\n const showCredits =\r\n hasSubscription && !isCreditsLoading;\r\n const creditsPercentage =\r\n showCredits && summary.totalCredits > 0\r\n ? (summary.usedCredits / summary.totalCredits) * 100\r\n : 0;\r\n\r\n return (\r\n <>\r\n {isLoggingOut && logoutOverlay}\r\n <Popover>\r\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\r\n {user && (\r\n <UserAvatar\r\n key={user.id}\r\n photo={user.photo}\r\n name={user.name}\r\n size={40}\r\n />\r\n )}\r\n </PopoverPrimitive.Trigger>\r\n\r\n <PopoverPrimitive.Portal>\r\n <PopoverPrimitive.Content\r\n className={cn(\r\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\r\n contentClassName,\r\n )}\r\n side={side}\r\n align={align}\r\n sideOffset={8}\r\n >\r\n <div className=\"grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full\">\r\n {user && (\r\n <UserAvatar\r\n key={user.id}\r\n photo={user.photo}\r\n name={user.name}\r\n size={32}\r\n />\r\n )}\r\n\r\n <div className=\"flex flex-col gap-0.5 min-w-0\">\r\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\r\n {user?.name || \"\"}\r\n </span>\r\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\r\n {user?.email || \"\"}\r\n </span>\r\n </div>\r\n\r\n {onEditProfile && (\r\n <Button\r\n variant=\"secondary\"\r\n className=\"paragraph-small-semibold h-8! whitespace-nowrap px-3 w-fit\"\r\n onClick={onEditProfile}\r\n >\r\n Editar Perfil\r\n </Button>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\r\n {showCreditsSkeleton && (\r\n <div className=\"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4\">\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\r\n Créditos usados\r\n </span>\r\n <div className=\"h-3.5 w-16 rounded bg-white/20 animate-pulse\" />\r\n </div>\r\n <div className=\"h-1.5 w-full rounded-full bg-white/20 animate-pulse\" />\r\n </div>\r\n )}\r\n\r\n {showCredits && (\r\n <div\r\n className={cn(\r\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\r\n onCreditsClick && \"cursor-pointer hover:bg-gray-900\",\r\n )}\r\n onClick={onCreditsClick}\r\n >\r\n <div className=\"flex items-center justify-between gap-2\">\r\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\r\n Créditos usados\r\n </span>\r\n <span className=\"paragraph-xsmall-medium text-white/50\">\r\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\r\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\r\n </span>\r\n </div>\r\n <Progress\r\n className=\"bg-white/10\"\r\n indicatorColor=\"bg-white\"\r\n value={creditsPercentage}\r\n />\r\n </div>\r\n )}\r\n\r\n <div className=\"flex flex-col gap-2\">\r\n {menuItems.length > 0 && (\r\n <div className=\"flex flex-col\">\r\n {menuItems.map((item, index) => (\r\n <NavBarItem\r\n key={index}\r\n icon={item.icon}\r\n label={item.label}\r\n onClick={item.onClick}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n <Separator />\r\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\r\n </div>\r\n </div>\r\n </PopoverPrimitive.Content>\r\n </PopoverPrimitive.Portal>\r\n </Popover>\r\n </>\r\n );\r\n}\r\n\r\nexport { ProfilePopover };\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,9 @@
1
+ "use server";
2
+ import { accountService } from "../services/account.service";
3
+ async function findCurrentAccount() {
4
+ return await accountService.findCurrentAccount();
5
+ }
6
+ export {
7
+ findCurrentAccount
8
+ };
9
+ //# sourceMappingURL=find-current-account.action.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/modules/accounts/actions/find-current-account.action.ts"],"sourcesContent":["'use server';\n\nimport { accountService } from \"../services/account.service\";\nimport { Account } from \"../types\";\n\nexport async function findCurrentAccount(): Promise<Account> {\n return await accountService.findCurrentAccount();\n}\n"],"mappings":";AAEA,SAAS,sBAAsB;AAG/B,eAAsB,qBAAuC;AACzD,SAAO,MAAM,eAAe,mBAAmB;AACnD;","names":[]}
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { findCurrentAccount } from "../actions/find-current-account.action";
4
+ const ACCOUNT_QUERY_KEY = ["account"];
5
+ function useCurrentAccount() {
6
+ return useQuery({
7
+ queryKey: ACCOUNT_QUERY_KEY,
8
+ queryFn: findCurrentAccount,
9
+ staleTime: 0,
10
+ gcTime: 10 * 60 * 1e3,
11
+ retry: false
12
+ });
13
+ }
14
+ function useInvalidateAccount() {
15
+ const queryClient = useQueryClient();
16
+ return () => queryClient.invalidateQueries({ queryKey: ACCOUNT_QUERY_KEY });
17
+ }
18
+ export {
19
+ ACCOUNT_QUERY_KEY,
20
+ useCurrentAccount,
21
+ useInvalidateAccount
22
+ };
23
+ //# sourceMappingURL=current-account.hook.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/modules/accounts/hooks/current-account.hook.tsx"],"sourcesContent":["\"use client\";\n\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { findCurrentAccount } from \"../actions/find-current-account.action\";\n\nexport const ACCOUNT_QUERY_KEY = [\"account\"];\n\nexport function useCurrentAccount() {\n return useQuery({\n queryKey: ACCOUNT_QUERY_KEY,\n queryFn: findCurrentAccount,\n staleTime: 0,\n gcTime: 10 * 60 * 1000,\n retry: false,\n });\n}\n\nexport function useInvalidateAccount() {\n const queryClient = useQueryClient();\n return () => queryClient.invalidateQueries({ queryKey: ACCOUNT_QUERY_KEY });\n}\n"],"mappings":";AAEA,SAAS,UAAU,sBAAsB;AACzC,SAAS,0BAA0B;AAE5B,MAAM,oBAAoB,CAAC,SAAS;AAEpC,SAAS,oBAAoB;AAClC,SAAO,SAAS;AAAA,IACd,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW;AAAA,IACX,QAAQ,KAAK,KAAK;AAAA,IAClB,OAAO;AAAA,EACT,CAAC;AACH;AAEO,SAAS,uBAAuB;AACrC,QAAM,cAAc,eAAe;AACnC,SAAO,MAAM,YAAY,kBAAkB,EAAE,UAAU,kBAAkB,CAAC;AAC5E;","names":[]}
@@ -0,0 +1,43 @@
1
+ import "server-only";
2
+ import { cookies } from "next/headers";
3
+ import { apiClient } from "@greatapps/common/server";
4
+ import { ApiError } from "@greatapps/common";
5
+ class AccountService {
6
+ /**
7
+ * Obtém o contexto do usuário a partir do JWT
8
+ * @private
9
+ */
10
+ async getUserContext() {
11
+ const cookieStore = await cookies();
12
+ const token = cookieStore.get("greatapps")?.value;
13
+ if (!token) {
14
+ throw new ApiError("Usu\xE1rio n\xE3o autenticado", "NOT_AUTHENTICATED", 401);
15
+ }
16
+ try {
17
+ const payload = JSON.parse(atob(token.split(".")[1]));
18
+ return {
19
+ id_account: payload.id_account,
20
+ id_user: payload.id_user
21
+ };
22
+ } catch (error) {
23
+ throw new ApiError("Token inv\xE1lido", "INVALID_TOKEN", 401);
24
+ }
25
+ }
26
+ async findCurrentAccount() {
27
+ const { id_account } = await this.getUserContext();
28
+ const response = await apiClient.get(`/accounts/${id_account}`);
29
+ if (response.status === 0 || !response.data?.[0]) {
30
+ throw new ApiError(
31
+ response.message || "Erro ao buscar dados da conta",
32
+ "GET_ACCOUNT_FAILED",
33
+ 400
34
+ );
35
+ }
36
+ return response.data[0];
37
+ }
38
+ }
39
+ const accountService = new AccountService();
40
+ export {
41
+ accountService
42
+ };
43
+ //# sourceMappingURL=account.service.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/modules/accounts/services/account.service.ts"],"sourcesContent":["import 'server-only';\n\nimport { cookies } from 'next/headers';\nimport { apiClient } from '@greatapps/common/server';\nimport { ApiError, JWTPayload, User, buildQueryParams } from '@greatapps/common';\nimport { Account, AccountUsersPaginationParams, GetAccountDataResponse, ListAccountUsersResponse } from '../types';\n\n/**\n * Service para gerenciar usuários da conta\n * Executado apenas no servidor (server-only)\n */\nclass AccountService {\n /**\n * Obtém o contexto do usuário a partir do JWT\n * @private\n */\n async getUserContext(): Promise<{\n id_account: number;\n id_user: number;\n }> {\n const cookieStore = await cookies();\n const token = cookieStore.get('greatapps')?.value;\n\n if (!token) {\n throw new ApiError('Usuário não autenticado', 'NOT_AUTHENTICATED', 401);\n }\n\n try {\n const payload = JSON.parse(atob(token.split('.')[1])) as JWTPayload;\n\n return {\n id_account: payload.id_account,\n id_user: payload.id_user,\n };\n } catch (error) {\n throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);\n }\n }\n\n async findCurrentAccount(): Promise<Account> {\n const { id_account } = await this.getUserContext();\n\n const response = await apiClient.get<GetAccountDataResponse>(`/accounts/${id_account}`);\n\n if (response.status === 0 || !response.data?.[0]) {\n throw new ApiError(\n response.message || 'Erro ao buscar dados da conta',\n 'GET_ACCOUNT_FAILED',\n 400\n );\n }\n\n return response.data[0];\n }\n}\n\nexport const accountService = new AccountService();\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,gBAAoD;AAO7D,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAKjB,MAAM,iBAGH;AACC,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,QAAQ,YAAY,IAAI,WAAW,GAAG;AAE5C,QAAI,CAAC,OAAO;AACR,YAAM,IAAI,SAAS,iCAA2B,qBAAqB,GAAG;AAAA,IAC1E;AAEA,QAAI;AACA,YAAM,UAAU,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;AAEpD,aAAO;AAAA,QACH,YAAY,QAAQ;AAAA,QACpB,SAAS,QAAQ;AAAA,MACrB;AAAA,IACJ,SAAS,OAAO;AACZ,YAAM,IAAI,SAAS,qBAAkB,iBAAiB,GAAG;AAAA,IAC7D;AAAA,EACJ;AAAA,EAEA,MAAM,qBAAuC;AACzC,UAAM,EAAE,WAAW,IAAI,MAAM,KAAK,eAAe;AAEjD,UAAM,WAAW,MAAM,UAAU,IAA4B,aAAa,UAAU,EAAE;AAEtF,QAAI,SAAS,WAAW,KAAK,CAAC,SAAS,OAAO,CAAC,GAAG;AAC9C,YAAM,IAAI;AAAA,QACN,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO,SAAS,KAAK,CAAC;AAAA,EAC1B;AACJ;AAEO,MAAM,iBAAiB,IAAI,eAAe;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -15,40 +15,48 @@ import {
15
15
  import { useLogin } from "../modules/auth/hooks/login.hook";
16
16
  import { useRegister } from "../modules/auth/hooks/register.hook";
17
17
  import { useLogout } from "../modules/auth/hooks/logout.hook";
18
+ import {
19
+ useCurrentAccount,
20
+ useInvalidateAccount
21
+ } from "../modules/accounts/hooks/current-account.hook";
18
22
  const AuthContext = createContext(
19
23
  void 0
20
24
  );
21
25
  function AuthProvider({ children }) {
22
26
  const { data: user, isLoading: isQueryLoading } = useUserQuery();
27
+ const { data: account, isLoading: isAccountLoading } = useCurrentAccount();
23
28
  const { isLoading: isSessionLoading } = useUserValidateSession();
24
29
  const setUserData = useSetUserData();
25
30
  const invalidateUser = useInvalidateUser();
31
+ const invalidateAccount = useInvalidateAccount();
26
32
  const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();
27
33
  const { mutateAsync: registerMutate, isPending: isRegistering } = useRegister();
28
34
  const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();
29
35
  const isAuthenticated = !!user;
30
- const isLoading = isLogging || isRegistering || isLoggingOut || isQueryLoading || isSessionLoading;
36
+ const isLoading = isLogging || isRegistering || isLoggingOut || isQueryLoading || isAccountLoading || isSessionLoading;
31
37
  const login = useCallback(
32
38
  async (credentials) => {
33
39
  await loginMutate(credentials, {
34
40
  onSuccess: (data) => {
35
41
  invalidateUser();
42
+ invalidateAccount();
36
43
  setUserData(data.user);
37
44
  }
38
45
  });
39
46
  },
40
- [invalidateUser]
47
+ [setUserData, invalidateUser, invalidateAccount]
41
48
  );
42
49
  const register = useCallback(
43
50
  async (data) => {
44
51
  await registerMutate(data, {
45
52
  onSuccess: (data2) => {
46
53
  invalidateUser();
54
+ invalidateAccount();
47
55
  setUserData(data2.user);
48
56
  }
49
57
  });
50
58
  },
51
- [setUserData]
59
+ [setUserData, invalidateUser, invalidateAccount]
52
60
  );
53
61
  const logout = useCallback(async () => {
54
62
  await logoutMutate(void 0, {
@@ -60,6 +68,7 @@ function AuthProvider({ children }) {
60
68
  const value = useMemo(
61
69
  () => ({
62
70
  user: user ?? null,
71
+ account: account ?? null,
63
72
  isAuthenticated,
64
73
  isLoading,
65
74
  login,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/auth.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n createContext,\r\n ReactNode,\r\n useCallback,\r\n useContext,\r\n useMemo,\r\n} from \"react\";\r\nimport {\r\n useUserQuery,\r\n useSetUserData,\r\n useInvalidateUser,\r\n useUserValidateSession,\r\n} from \"../modules/auth/hooks/useUserQuery\";\r\nimport { useLogin } from \"../modules/auth/hooks/login.hook\";\r\nimport { useRegister } from \"../modules/auth/hooks/register.hook\";\r\nimport { useLogout } from \"../modules/auth/hooks/logout.hook\";\r\nimport {\r\n AuthState,\r\n LoginRequest,\r\n RegisterRequest,\r\n} from \"../modules/auth/schema\";\r\n\r\ninterface AuthContextProps extends AuthState {\r\n login: (credentials: LoginRequest) => Promise<void>;\r\n register: (data: RegisterRequest) => Promise<void>;\r\n logout: () => Promise<void>;\r\n}\r\n\r\nexport const AuthContext = createContext<AuthContextProps | undefined>(\r\n undefined,\r\n);\r\n\r\ninterface AuthProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function AuthProvider({ children }: AuthProviderProps) {\r\n const { data: user, isLoading: isQueryLoading } = useUserQuery();\r\n const { isLoading: isSessionLoading } = useUserValidateSession();\r\n const setUserData = useSetUserData();\r\n const invalidateUser = useInvalidateUser();\r\n\r\n const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();\r\n const { mutateAsync: registerMutate, isPending: isRegistering } =\r\n useRegister();\r\n const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();\r\n\r\n const isAuthenticated = !!user;\r\n const isLoading =\r\n isLogging ||\r\n isRegistering ||\r\n isLoggingOut ||\r\n isQueryLoading ||\r\n isSessionLoading;\r\n\r\n const login = useCallback(\r\n async (credentials: LoginRequest): Promise<void> => {\r\n await loginMutate(credentials, {\r\n onSuccess: (data) => {\r\n invalidateUser();\r\n setUserData(data.user);\r\n },\r\n });\r\n },\r\n [invalidateUser],\r\n );\r\n\r\n const register = useCallback(\r\n async (data: RegisterRequest): Promise<void> => {\r\n await registerMutate(data, {\r\n onSuccess: (data) => {\r\n invalidateUser();\r\n setUserData(data.user);\r\n },\r\n });\r\n },\r\n [setUserData],\r\n );\r\n\r\n const logout = useCallback(async (): Promise<void> => {\r\n await logoutMutate(undefined, {\r\n onSuccess: () => {\r\n invalidateUser();\r\n },\r\n });\r\n }, [setUserData]);\r\n\r\n const value: AuthContextProps = useMemo(\r\n () => ({\r\n user: user ?? null,\r\n isAuthenticated,\r\n isLoading,\r\n login,\r\n register,\r\n logout,\r\n }),\r\n [user, isAuthenticated, isLoading, login, register, logout],\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n\r\nexport function useAuth(): AuthContextProps {\r\n const context = useContext(AuthContext);\r\n\r\n if (context === undefined) {\r\n throw new Error(\"useAuth deve ser usado dentro de um AuthProvider\");\r\n }\r\n\r\n return context;\r\n}\r\n"],"mappings":";AAqGS;AAnGT;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAanB,MAAM,cAAc;AAAA,EACzB;AACF;AAMO,SAAS,aAAa,EAAE,SAAS,GAAsB;AAC5D,QAAM,EAAE,MAAM,MAAM,WAAW,eAAe,IAAI,aAAa;AAC/D,QAAM,EAAE,WAAW,iBAAiB,IAAI,uBAAuB;AAC/D,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAiB,kBAAkB;AAEzC,QAAM,EAAE,aAAa,aAAa,WAAW,UAAU,IAAI,SAAS;AACpE,QAAM,EAAE,aAAa,gBAAgB,WAAW,cAAc,IAC5D,YAAY;AACd,QAAM,EAAE,aAAa,cAAc,WAAW,aAAa,IAAI,UAAU;AAEzE,QAAM,kBAAkB,CAAC,CAAC;AAC1B,QAAM,YACJ,aACA,iBACA,gBACA,kBACA;AAEF,QAAM,QAAQ;AAAA,IACZ,OAAO,gBAA6C;AAClD,YAAM,YAAY,aAAa;AAAA,QAC7B,WAAW,CAAC,SAAS;AACnB,yBAAe;AACf,sBAAY,KAAK,IAAI;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,WAAW;AAAA,IACf,OAAO,SAAyC;AAC9C,YAAM,eAAe,MAAM;AAAA,QACzB,WAAW,CAACA,UAAS;AACnB,yBAAe;AACf,sBAAYA,MAAK,IAAI;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,SAAS,YAAY,YAA2B;AACpD,UAAM,aAAa,QAAW;AAAA,MAC5B,WAAW,MAAM;AACf,uBAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,QAA0B;AAAA,IAC9B,OAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,MAAM,iBAAiB,WAAW,OAAO,UAAU,MAAM;AAAA,EAC5D;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAEO,SAAS,UAA4B;AAC1C,QAAM,UAAU,WAAW,WAAW;AAEtC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AAEA,SAAO;AACT;","names":["data"]}
1
+ {"version":3,"sources":["../../src/providers/auth.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n createContext,\r\n ReactNode,\r\n useCallback,\r\n useContext,\r\n useMemo,\r\n} from \"react\";\r\nimport {\r\n useUserQuery,\r\n useSetUserData,\r\n useInvalidateUser,\r\n useUserValidateSession,\r\n} from \"../modules/auth/hooks/useUserQuery\";\r\nimport { useLogin } from \"../modules/auth/hooks/login.hook\";\r\nimport { useRegister } from \"../modules/auth/hooks/register.hook\";\r\nimport { useLogout } from \"../modules/auth/hooks/logout.hook\";\r\nimport {\r\n AuthState,\r\n LoginRequest,\r\n RegisterRequest,\r\n} from \"../modules/auth/schema\";\r\nimport {\r\n useCurrentAccount,\r\n useInvalidateAccount,\r\n} from \"../modules/accounts/hooks/current-account.hook\";\r\n\r\ninterface AuthContextProps extends AuthState {\r\n login: (credentials: LoginRequest) => Promise<void>;\r\n register: (data: RegisterRequest) => Promise<void>;\r\n logout: () => Promise<void>;\r\n}\r\n\r\nexport const AuthContext = createContext<AuthContextProps | undefined>(\r\n undefined,\r\n);\r\n\r\ninterface AuthProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function AuthProvider({ children }: AuthProviderProps) {\r\n const { data: user, isLoading: isQueryLoading } = useUserQuery();\r\n const { data: account, isLoading: isAccountLoading } = useCurrentAccount();\r\n const { isLoading: isSessionLoading } = useUserValidateSession();\r\n\r\n const setUserData = useSetUserData();\r\n const invalidateUser = useInvalidateUser();\r\n const invalidateAccount = useInvalidateAccount();\r\n\r\n const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();\r\n const { mutateAsync: registerMutate, isPending: isRegistering } =\r\n useRegister();\r\n const { mutateAsync: logoutMutate, isPending: isLoggingOut } = useLogout();\r\n\r\n const isAuthenticated = !!user;\r\n const isLoading =\r\n isLogging ||\r\n isRegistering ||\r\n isLoggingOut ||\r\n isQueryLoading ||\r\n isAccountLoading ||\r\n isSessionLoading;\r\n\r\n const login = useCallback(\r\n async (credentials: LoginRequest): Promise<void> => {\r\n await loginMutate(credentials, {\r\n onSuccess: (data) => {\r\n invalidateUser();\r\n invalidateAccount();\r\n setUserData(data.user);\r\n },\r\n });\r\n },\r\n [setUserData, invalidateUser, invalidateAccount],\r\n );\r\n\r\n const register = useCallback(\r\n async (data: RegisterRequest): Promise<void> => {\r\n await registerMutate(data, {\r\n onSuccess: (data) => {\r\n invalidateUser();\r\n invalidateAccount();\r\n setUserData(data.user);\r\n },\r\n });\r\n },\r\n [setUserData, invalidateUser, invalidateAccount],\r\n );\r\n\r\n const logout = useCallback(async (): Promise<void> => {\r\n await logoutMutate(undefined, {\r\n onSuccess: () => {\r\n invalidateUser();\r\n },\r\n });\r\n }, [setUserData]);\r\n\r\n const value: AuthContextProps = useMemo(\r\n () => ({\r\n user: user ?? null,\r\n account: account ?? null,\r\n isAuthenticated,\r\n isLoading,\r\n login,\r\n register,\r\n logout,\r\n }),\r\n [user, isAuthenticated, isLoading, login, register, logout],\r\n );\r\n\r\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\r\n}\r\n\r\nexport function useAuth(): AuthContextProps {\r\n const context = useContext(AuthContext);\r\n\r\n if (context === undefined) {\r\n throw new Error(\"useAuth deve ser usado dentro de um AuthProvider\");\r\n }\r\n\r\n return context;\r\n}\r\n"],"mappings":";AAgHS;AA9GT;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAM1B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAQA,MAAM,cAAc;AAAA,EACzB;AACF;AAMO,SAAS,aAAa,EAAE,SAAS,GAAsB;AAC5D,QAAM,EAAE,MAAM,MAAM,WAAW,eAAe,IAAI,aAAa;AAC/D,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,IAAI,kBAAkB;AACzE,QAAM,EAAE,WAAW,iBAAiB,IAAI,uBAAuB;AAE/D,QAAM,cAAc,eAAe;AACnC,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,oBAAoB,qBAAqB;AAE/C,QAAM,EAAE,aAAa,aAAa,WAAW,UAAU,IAAI,SAAS;AACpE,QAAM,EAAE,aAAa,gBAAgB,WAAW,cAAc,IAC5D,YAAY;AACd,QAAM,EAAE,aAAa,cAAc,WAAW,aAAa,IAAI,UAAU;AAEzE,QAAM,kBAAkB,CAAC,CAAC;AAC1B,QAAM,YACJ,aACA,iBACA,gBACA,kBACA,oBACA;AAEF,QAAM,QAAQ;AAAA,IACZ,OAAO,gBAA6C;AAClD,YAAM,YAAY,aAAa;AAAA,QAC7B,WAAW,CAAC,SAAS;AACnB,yBAAe;AACf,4BAAkB;AAClB,sBAAY,KAAK,IAAI;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,aAAa,gBAAgB,iBAAiB;AAAA,EACjD;AAEA,QAAM,WAAW;AAAA,IACf,OAAO,SAAyC;AAC9C,YAAM,eAAe,MAAM;AAAA,QACzB,WAAW,CAACA,UAAS;AACnB,yBAAe;AACf,4BAAkB;AAClB,sBAAYA,MAAK,IAAI;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC,aAAa,gBAAgB,iBAAiB;AAAA,EACjD;AAEA,QAAM,SAAS,YAAY,YAA2B;AACpD,UAAM,aAAa,QAAW;AAAA,MAC5B,WAAW,MAAM;AACf,uBAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,QAA0B;AAAA,IAC9B,OAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,SAAS,WAAW;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,MAAM,iBAAiB,WAAW,OAAO,UAAU,MAAM;AAAA,EAC5D;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAEO,SAAS,UAA4B;AAC1C,QAAM,UAAU,WAAW,WAAW;AAEtC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AAEA,SAAO;AACT;","names":["data"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.17",
3
+ "version": "1.1.19",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -62,7 +62,7 @@ function ProfilePopover({
62
62
  const hasSubscription = !isSubscriptionLoading && subscription !== null;
63
63
  const showCreditsSkeleton = hasSubscription && isCreditsLoading;
64
64
  const showCredits =
65
- hasSubscription && !isCreditsLoading && summary.totalCredits > 0;
65
+ hasSubscription && !isCreditsLoading;
66
66
  const creditsPercentage =
67
67
  showCredits && summary.totalCredits > 0
68
68
  ? (summary.usedCredits / summary.totalCredits) * 100
@@ -0,0 +1,8 @@
1
+ 'use server';
2
+
3
+ import { accountService } from "../services/account.service";
4
+ import { Account } from "../types";
5
+
6
+ export async function findCurrentAccount(): Promise<Account> {
7
+ return await accountService.findCurrentAccount();
8
+ }
@@ -0,0 +1,21 @@
1
+ "use client";
2
+
3
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
4
+ import { findCurrentAccount } from "../actions/find-current-account.action";
5
+
6
+ export const ACCOUNT_QUERY_KEY = ["account"];
7
+
8
+ export function useCurrentAccount() {
9
+ return useQuery({
10
+ queryKey: ACCOUNT_QUERY_KEY,
11
+ queryFn: findCurrentAccount,
12
+ staleTime: 0,
13
+ gcTime: 10 * 60 * 1000,
14
+ retry: false,
15
+ });
16
+ }
17
+
18
+ export function useInvalidateAccount() {
19
+ const queryClient = useQueryClient();
20
+ return () => queryClient.invalidateQueries({ queryKey: ACCOUNT_QUERY_KEY });
21
+ }
@@ -0,0 +1,57 @@
1
+ import 'server-only';
2
+
3
+ import { cookies } from 'next/headers';
4
+ import { apiClient } from '@greatapps/common/server';
5
+ import { ApiError, JWTPayload, User, buildQueryParams } from '@greatapps/common';
6
+ import { Account, AccountUsersPaginationParams, GetAccountDataResponse, ListAccountUsersResponse } from '../types';
7
+
8
+ /**
9
+ * Service para gerenciar usuários da conta
10
+ * Executado apenas no servidor (server-only)
11
+ */
12
+ class AccountService {
13
+ /**
14
+ * Obtém o contexto do usuário a partir do JWT
15
+ * @private
16
+ */
17
+ async getUserContext(): Promise<{
18
+ id_account: number;
19
+ id_user: number;
20
+ }> {
21
+ const cookieStore = await cookies();
22
+ const token = cookieStore.get('greatapps')?.value;
23
+
24
+ if (!token) {
25
+ throw new ApiError('Usuário não autenticado', 'NOT_AUTHENTICATED', 401);
26
+ }
27
+
28
+ try {
29
+ const payload = JSON.parse(atob(token.split('.')[1])) as JWTPayload;
30
+
31
+ return {
32
+ id_account: payload.id_account,
33
+ id_user: payload.id_user,
34
+ };
35
+ } catch (error) {
36
+ throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);
37
+ }
38
+ }
39
+
40
+ async findCurrentAccount(): Promise<Account> {
41
+ const { id_account } = await this.getUserContext();
42
+
43
+ const response = await apiClient.get<GetAccountDataResponse>(`/accounts/${id_account}`);
44
+
45
+ if (response.status === 0 || !response.data?.[0]) {
46
+ throw new ApiError(
47
+ response.message || 'Erro ao buscar dados da conta',
48
+ 'GET_ACCOUNT_FAILED',
49
+ 400
50
+ );
51
+ }
52
+
53
+ return response.data[0];
54
+ }
55
+ }
56
+
57
+ export const accountService = new AccountService();
@@ -0,0 +1,56 @@
1
+ import { User, UserProfile } from "../users/schema";
2
+
3
+ export interface Account {
4
+ id: number;
5
+ id_wl: number;
6
+ id_affiliate: number;
7
+ id_api: number;
8
+ name: string;
9
+ language: string;
10
+ timezone: string;
11
+ currency: string;
12
+ verified: boolean;
13
+ bussiness_type: number;
14
+ gateway: string;
15
+ gateway_customer_id: string | null;
16
+ origin: string | null;
17
+ zipcode: string | null;
18
+ address: string | null;
19
+ address_number: string | null;
20
+ address_complement: string | null;
21
+ neighborhood: string | null;
22
+ city: string | null;
23
+ state: string | null;
24
+ country: string | null;
25
+ financial_document: string | null;
26
+ financial_name: string | null;
27
+ financial_email: string | null;
28
+ financial_document_type: number;
29
+ deleted: number;
30
+ datetime_add: string;
31
+ datetime_alt: string;
32
+ datetime_del: string | null;
33
+ }
34
+
35
+
36
+ export interface ListAccountUsersResponse {
37
+ status: 0 | 1;
38
+ total: number;
39
+ data: User[];
40
+ message?: string;
41
+ }
42
+
43
+ export interface AccountUsersPaginationParams {
44
+ page?: number;
45
+ limit?: number;
46
+ search?: string;
47
+ notInProject?: number;
48
+ profiles?: UserProfile[];
49
+ }
50
+
51
+ export interface GetAccountDataResponse {
52
+ status: 0 | 1;
53
+ message: string;
54
+ data: Account[];
55
+ total: number;
56
+ }
@@ -1,3 +1,4 @@
1
+ import { Account } from '../accounts/types';
1
2
  import { User } from '../users/schema';
2
3
 
3
4
  export interface ClientInfo {
@@ -25,6 +26,7 @@ export interface GeoLocation {
25
26
 
26
27
  export interface AuthState {
27
28
  user: User | null;
29
+ account: Account | null;
28
30
  isAuthenticated: boolean;
29
31
  isLoading: boolean;
30
32
  }
@@ -21,6 +21,10 @@ import {
21
21
  LoginRequest,
22
22
  RegisterRequest,
23
23
  } from "../modules/auth/schema";
24
+ import {
25
+ useCurrentAccount,
26
+ useInvalidateAccount,
27
+ } from "../modules/accounts/hooks/current-account.hook";
24
28
 
25
29
  interface AuthContextProps extends AuthState {
26
30
  login: (credentials: LoginRequest) => Promise<void>;
@@ -38,9 +42,12 @@ interface AuthProviderProps {
38
42
 
39
43
  export function AuthProvider({ children }: AuthProviderProps) {
40
44
  const { data: user, isLoading: isQueryLoading } = useUserQuery();
45
+ const { data: account, isLoading: isAccountLoading } = useCurrentAccount();
41
46
  const { isLoading: isSessionLoading } = useUserValidateSession();
47
+
42
48
  const setUserData = useSetUserData();
43
49
  const invalidateUser = useInvalidateUser();
50
+ const invalidateAccount = useInvalidateAccount();
44
51
 
45
52
  const { mutateAsync: loginMutate, isPending: isLogging } = useLogin();
46
53
  const { mutateAsync: registerMutate, isPending: isRegistering } =
@@ -53,6 +60,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
53
60
  isRegistering ||
54
61
  isLoggingOut ||
55
62
  isQueryLoading ||
63
+ isAccountLoading ||
56
64
  isSessionLoading;
57
65
 
58
66
  const login = useCallback(
@@ -60,11 +68,12 @@ export function AuthProvider({ children }: AuthProviderProps) {
60
68
  await loginMutate(credentials, {
61
69
  onSuccess: (data) => {
62
70
  invalidateUser();
71
+ invalidateAccount();
63
72
  setUserData(data.user);
64
73
  },
65
74
  });
66
75
  },
67
- [invalidateUser],
76
+ [setUserData, invalidateUser, invalidateAccount],
68
77
  );
69
78
 
70
79
  const register = useCallback(
@@ -72,11 +81,12 @@ export function AuthProvider({ children }: AuthProviderProps) {
72
81
  await registerMutate(data, {
73
82
  onSuccess: (data) => {
74
83
  invalidateUser();
84
+ invalidateAccount();
75
85
  setUserData(data.user);
76
86
  },
77
87
  });
78
88
  },
79
- [setUserData],
89
+ [setUserData, invalidateUser, invalidateAccount],
80
90
  );
81
91
 
82
92
  const logout = useCallback(async (): Promise<void> => {
@@ -90,6 +100,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
90
100
  const value: AuthContextProps = useMemo(
91
101
  () => ({
92
102
  user: user ?? null,
103
+ account: account ?? null,
93
104
  isAuthenticated,
94
105
  isLoading,
95
106
  login,