@greatapps/common 1.1.281 → 1.1.283

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 (28) hide show
  1. package/dist/components/layouts/NavBar.mjs +1 -1
  2. package/dist/components/layouts/NavBar.mjs.map +1 -1
  3. package/dist/components/layouts/SideBarNavigation.mjs +35 -5
  4. package/dist/components/layouts/SideBarNavigation.mjs.map +1 -1
  5. package/dist/components/layouts/UsersSelectorPopover.mjs +3 -3
  6. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  7. package/dist/components/navigation/NavItem.mjs +4 -0
  8. package/dist/components/navigation/NavItem.mjs.map +1 -1
  9. package/dist/modules/accounts/services/account.service.mjs +2 -2
  10. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  11. package/dist/modules/auth/services/auth.service.mjs +2 -2
  12. package/dist/modules/auth/services/auth.service.mjs.map +1 -1
  13. package/dist/modules/users/services/user.service.mjs +2 -2
  14. package/dist/modules/users/services/user.service.mjs.map +1 -1
  15. package/dist/modules/whitelabel/services/whitelabel.service.mjs +7 -4
  16. package/dist/modules/whitelabel/services/whitelabel.service.mjs.map +1 -1
  17. package/dist/store/useMdSidebarStore.mjs +1 -1
  18. package/dist/store/useMdSidebarStore.mjs.map +1 -1
  19. package/package.json +1 -1
  20. package/src/components/layouts/NavBar.tsx +1 -1
  21. package/src/components/layouts/SideBarNavigation.tsx +52 -22
  22. package/src/components/layouts/UsersSelectorPopover.tsx +19 -17
  23. package/src/components/navigation/NavItem.tsx +4 -0
  24. package/src/modules/accounts/services/account.service.ts +3 -2
  25. package/src/modules/auth/services/auth.service.ts +4 -3
  26. package/src/modules/users/services/user.service.ts +2 -2
  27. package/src/modules/whitelabel/services/whitelabel.service.ts +9 -7
  28. package/src/store/useMdSidebarStore.ts +1 -1
@@ -61,7 +61,7 @@ function NavBar({
61
61
  "button",
62
62
  {
63
63
  onClick: onExpandClick,
64
- className: "lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10",
64
+ className: "absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10",
65
65
  children: /* @__PURE__ */ jsx(IconChevronRight, { size: 16, className: "text-gray-500" })
66
66
  }
67
67
  ) }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/NavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport Image from \"next/image\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\nimport { cn } from \"../../infra/utils/clsx\";\n\ntype NavBarProps = {\n onLogoClick: () => void;\n onAppIconClick?: () => void;\n activeApp?: \"gapps\" | \"gpages\";\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n children?: React.ReactNode;\n className?: string;\n};\n\nfunction NavBar({\n onLogoClick,\n onAppIconClick,\n activeApp,\n showExpandButton = false,\n onExpandClick,\n children,\n className,\n}: NavBarProps) {\n return (\n <div\n className={cn(\n \"hidden md:flex flex-col justify-between h-screen p-4 border-r border-gray-200 overflow-visible z-40 bg-white\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-4 items-center mt-[6.5px]\">\n {/* GreatApps logo */}\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger\n className=\"cursor-pointer\"\n asChild\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great Icon\"\n width={28}\n height={28}\n />\n </TooltipTrigger>\n <TooltipContent side=\"right\">Great</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-[22px] top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 bg-gray-950 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gapps\" ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n </div>\n\n <div className=\"relative w-full mt-[7.5px]\">\n <Separator />\n {showExpandButton && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={onExpandClick}\n className=\"lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10\"\n >\n <IconChevronRight size={16} className=\"text-gray-500\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Expandir menu</TooltipContent>\n </Tooltip>\n )}\n </div>\n\n {/* GreatPages icon */}\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild onClick={onAppIconClick}>\n {activeApp === \"gpages\" ? (\n <div className=\"size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-100 border-2 border-white ring-2 ring-cyan-300\">\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n ) : (\n <div className=\"size-10 flex items-center justify-center rounded-lg cursor-pointer hover:bg-gray-100 transition-colors duration-300 border-2 border-transparent ring-2 ring-transparent\">\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent side=\"right\">GreatPages</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-4 top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 bg-cyan-300 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gpages\" ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n </div>\n </div>\n\n <div className=\"flex flex-col items-center gap-2\">{children}</div>\n </div>\n );\n}\n\nexport { NavBar };\nexport type { NavBarProps };\n"],"mappings":";AAsCU,SAMI,KANJ;AAnCV,OAAO,WAAW;AAClB,SAAS,wBAAwB;AACjC,SAAS,iBAAiB;AAC1B,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,UAAU;AAYnB,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAAgB;AACd,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEA;AAAA,6BAAC,SAAI,WAAU,+CAEb;AAAA,+BAAC,SAAI,WAAU,YACb;AAAA,iCAAC,WACC;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,SAAO;AAAA,kBACP,SAAS;AAAA,kBAET;AAAA,oBAAC;AAAA;AAAA,sBACC,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO;AAAA,sBACP,QAAQ;AAAA;AAAA,kBACV;AAAA;AAAA,cACF;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,mBAAK;AAAA,eACpC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,cAAc,UAAU,gBAAgB;AAAA,gBAC1C;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,8BACb;AAAA,gCAAC,aAAU;AAAA,YACV,oBACC,qBAAC,WACC;AAAA,kCAAC,kBAAe,SAAO,MACrB;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS;AAAA,kBACT,WAAU;AAAA,kBAEV,8BAAC,oBAAiB,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,cACxD,GACF;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,2BAAa;AAAA,eAC5C;AAAA,aAEJ;AAAA,UAGA,qBAAC,SAAI,WAAU,YACb;AAAA,iCAAC,WACC;AAAA,kCAAC,kBAAe,SAAO,MAAC,SAAS,gBAC9B,wBAAc,WACb,oBAAC,SAAI,WAAU,6HACb;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV,GACF,IAEA,oBAAC,SAAI,WAAU,2KACb;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV,GACF,GAEJ;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,wBAAU;AAAA,eACzC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,cAAc,WAAW,gBAAgB;AAAA,gBAC3C;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WACF;AAAA,QAEA,oBAAC,SAAI,WAAU,oCAAoC,UAAS;AAAA;AAAA;AAAA,EAC9D;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/NavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport Image from \"next/image\";\nimport { IconChevronRight } from \"@tabler/icons-react\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\nimport { cn } from \"../../infra/utils/clsx\";\n\ntype NavBarProps = {\n onLogoClick: () => void;\n onAppIconClick?: () => void;\n activeApp?: \"gapps\" | \"gpages\";\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n children?: React.ReactNode;\n className?: string;\n};\n\nfunction NavBar({\n onLogoClick,\n onAppIconClick,\n activeApp,\n showExpandButton = false,\n onExpandClick,\n children,\n className,\n}: NavBarProps) {\n return (\n <div\n className={cn(\n \"hidden md:flex flex-col justify-between h-screen p-4 border-r border-gray-200 overflow-visible z-40 bg-white\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-4 items-center mt-[6.5px]\">\n {/* GreatApps logo */}\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger\n className=\"cursor-pointer\"\n asChild\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great Icon\"\n width={28}\n height={28}\n />\n </TooltipTrigger>\n <TooltipContent side=\"right\">Great</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-[22px] top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 bg-gray-950 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gapps\" ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n </div>\n\n <div className=\"relative w-full mt-[7.5px]\">\n <Separator />\n {showExpandButton && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={onExpandClick}\n className=\"absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10\"\n >\n <IconChevronRight size={16} className=\"text-gray-500\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Expandir menu</TooltipContent>\n </Tooltip>\n )}\n </div>\n\n {/* GreatPages icon */}\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild onClick={onAppIconClick}>\n {activeApp === \"gpages\" ? (\n <div className=\"size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-100 border-2 border-white ring-2 ring-cyan-300\">\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n ) : (\n <div className=\"size-10 flex items-center justify-center rounded-lg cursor-pointer hover:bg-gray-100 transition-colors duration-300 border-2 border-transparent ring-2 ring-transparent\">\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent side=\"right\">GreatPages</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-4 top-1/2 -translate-y-1/2 z-10 w-[3px] h-5 bg-cyan-300 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gpages\" ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n </div>\n </div>\n\n <div className=\"flex flex-col items-center gap-2\">{children}</div>\n </div>\n );\n}\n\nexport { NavBar };\nexport type { NavBarProps };\n"],"mappings":";AAsCU,SAMI,KANJ;AAnCV,OAAO,WAAW;AAClB,SAAS,wBAAwB;AACjC,SAAS,iBAAiB;AAC1B,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,UAAU;AAYnB,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAAgB;AACd,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEA;AAAA,6BAAC,SAAI,WAAU,+CAEb;AAAA,+BAAC,SAAI,WAAU,YACb;AAAA,iCAAC,WACC;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,SAAO;AAAA,kBACP,SAAS;AAAA,kBAET;AAAA,oBAAC;AAAA;AAAA,sBACC,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO;AAAA,sBACP,QAAQ;AAAA;AAAA,kBACV;AAAA;AAAA,cACF;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,mBAAK;AAAA,eACpC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,cAAc,UAAU,gBAAgB;AAAA,gBAC1C;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,8BACb;AAAA,gCAAC,aAAU;AAAA,YACV,oBACC,qBAAC,WACC;AAAA,kCAAC,kBAAe,SAAO,MACrB;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS;AAAA,kBACT,WAAU;AAAA,kBAEV,8BAAC,oBAAiB,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,cACxD,GACF;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,2BAAa;AAAA,eAC5C;AAAA,aAEJ;AAAA,UAGA,qBAAC,SAAI,WAAU,YACb;AAAA,iCAAC,WACC;AAAA,kCAAC,kBAAe,SAAO,MAAC,SAAS,gBAC9B,wBAAc,WACb,oBAAC,SAAI,WAAU,6HACb;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV,GACF,IAEA,oBAAC,SAAI,WAAU,2KACb;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV,GACF,GAEJ;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,wBAAU;AAAA,eACzC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,cAAc,WAAW,gBAAgB;AAAA,gBAC3C;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WACF;AAAA,QAEA,oBAAC,SAAI,WAAU,oCAAoC,UAAS;AAAA;AAAA;AAAA,EAC9D;AAEJ;","names":[]}
@@ -1,18 +1,48 @@
1
1
  "use client";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { IconChevronLeft } from "@tabler/icons-react";
4
+ import { useMdSidebarStore } from "../../store/useMdSidebarStore";
3
5
  import { cn } from "../../infra/utils/clsx";
6
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
4
7
  function SideBarNavigation({
5
8
  className,
6
9
  children,
7
10
  ...props
8
11
  }) {
9
- return /* @__PURE__ */ jsx(
12
+ const { isExpanded, collapse } = useMdSidebarStore();
13
+ return /* @__PURE__ */ jsxs(
10
14
  "div",
11
15
  {
12
16
  "data-slot": "sidebar-navigation",
13
- className: cn("hidden lg:flex flex-col h-screen p-4 border-r w-[273px] border-gray-200", className),
14
- ...props,
15
- children
17
+ className: "hidden lg:block relative overflow-visible shrink-0",
18
+ children: [
19
+ /* @__PURE__ */ jsx(
20
+ "div",
21
+ {
22
+ className: cn(
23
+ "flex flex-col h-screen border-r border-gray-200 transition-all duration-300 ease-in-out overflow-hidden",
24
+ isExpanded ? "w-[273px] p-4" : "w-0 p-0 border-r-0",
25
+ className
26
+ ),
27
+ ...props,
28
+ children: /* @__PURE__ */ jsx("div", { className: cn(
29
+ "flex flex-col flex-1 min-w-[241px] transition-opacity duration-200",
30
+ isExpanded ? "opacity-100" : "opacity-0 pointer-events-none"
31
+ ), children })
32
+ }
33
+ ),
34
+ isExpanded && /* @__PURE__ */ jsxs(Tooltip, { children: [
35
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
36
+ "button",
37
+ {
38
+ onClick: collapse,
39
+ className: "absolute top-[74px] -translate-y-1/2 -right-4 size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-40",
40
+ children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 16, className: "text-gray-500" })
41
+ }
42
+ ) }),
43
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: "Recolher menu" })
44
+ ] })
45
+ ]
16
46
  }
17
47
  );
18
48
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/SideBarNavigation.tsx"],"sourcesContent":["'use client';\n\n\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { cn } from \"../../infra/utils/clsx\"\r\n\r\nfunction SideBarNavigation({\r\n className,\r\n children,\r\n ...props\r\n}: React.ComponentProps<\"div\">) {\r\n return (\r\n <div\r\n data-slot=\"sidebar-navigation\"\r\n className={cn(\"hidden lg:flex flex-col h-screen p-4 border-r w-[273px] border-gray-200\", className)}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n )\r\n}\r\n\r\nexport { SideBarNavigation };\r\n"],"mappings":";AAaQ;AARR,SAAS,UAAU;AAEnB,SAAS,kBAAkB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,GAAG;AACP,GAAgC;AAC5B,SACI;AAAA,IAAC;AAAA;AAAA,MACG,aAAU;AAAA,MACV,WAAW,GAAG,2EAA2E,SAAS;AAAA,MACjG,GAAG;AAAA,MAEH;AAAA;AAAA,EACL;AAER;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/SideBarNavigation.tsx"],"sourcesContent":["'use client';\n\nimport * as React from \"react\"\nimport { IconChevronLeft } from '@tabler/icons-react'\nimport { useMdSidebarStore } from \"../../store/useMdSidebarStore\"\nimport { cn } from \"../../infra/utils/clsx\"\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\"\n\nfunction SideBarNavigation({\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\">) {\n const { isExpanded, collapse } = useMdSidebarStore()\n\n return (\n <div\n data-slot=\"sidebar-navigation\"\n className=\"hidden lg:block relative overflow-visible shrink-0\"\n >\n <div\n className={cn(\n \"flex flex-col h-screen border-r border-gray-200 transition-all duration-300 ease-in-out overflow-hidden\",\n isExpanded ? \"w-[273px] p-4\" : \"w-0 p-0 border-r-0\",\n className\n )}\n {...props}\n >\n <div className={cn(\n \"flex flex-col flex-1 min-w-[241px] transition-opacity duration-200\",\n isExpanded ? \"opacity-100\" : \"opacity-0 pointer-events-none\"\n )}>\n {children}\n </div>\n </div>\n\n {isExpanded && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={collapse}\n className=\"absolute top-[74px] -translate-y-1/2 -right-4 size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-40\"\n >\n <IconChevronLeft size={16} className=\"text-gray-500\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Recolher menu</TooltipContent>\n </Tooltip>\n )}\n </div>\n )\n}\n\nexport { SideBarNavigation };\n"],"mappings":";AA4BgB,cASA,YATA;AAzBhB,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,UAAU;AACnB,SAAS,SAAS,gBAAgB,sBAAsB;AAExD,SAAS,kBAAkB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,GAAG;AACP,GAAgC;AAC5B,QAAM,EAAE,YAAY,SAAS,IAAI,kBAAkB;AAEnD,SACI;AAAA,IAAC;AAAA;AAAA,MACG,aAAU;AAAA,MACV,WAAU;AAAA,MAEV;AAAA;AAAA,UAAC;AAAA;AAAA,YACG,WAAW;AAAA,cACP;AAAA,cACA,aAAa,kBAAkB;AAAA,cAC/B;AAAA,YACJ;AAAA,YACC,GAAG;AAAA,YAEJ,8BAAC,SAAI,WAAW;AAAA,cACZ;AAAA,cACA,aAAa,gBAAgB;AAAA,YACjC,GACK,UACL;AAAA;AAAA,QACJ;AAAA,QAEC,cACG,qBAAC,WACG;AAAA,8BAAC,kBAAe,SAAO,MACnB;AAAA,YAAC;AAAA;AAAA,cACG,SAAS;AAAA,cACT,WAAU;AAAA,cAEV,8BAAC,mBAAgB,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,UACzD,GACJ;AAAA,UACA,oBAAC,kBAAe,MAAK,SAAQ,2BAAa;AAAA,WAC9C;AAAA;AAAA;AAAA,EAER;AAER;","names":[]}
@@ -169,8 +169,8 @@ function UsersSelectorPopover({
169
169
  /* @__PURE__ */ jsx("span", { className: "truncate", children: user.name })
170
170
  ] }),
171
171
  /* @__PURE__ */ jsxs(Tooltip, { open: interactive && hoveredId === user.id, children: [
172
- /* @__PURE__ */ jsx(
173
- TooltipTrigger,
172
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
173
+ "div",
174
174
  {
175
175
  onClick: (e) => e.stopPropagation(),
176
176
  onPointerDown: (e) => e.stopPropagation(),
@@ -187,7 +187,7 @@ function UsersSelectorPopover({
187
187
  }
188
188
  )
189
189
  }
190
- ),
190
+ ) }),
191
191
  /* @__PURE__ */ jsx(TooltipContent, { className: "z-[1002]", children: inProject ? "Remover do projeto" : "Adicionar ao projeto" })
192
192
  ] })
193
193
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/UsersSelectorPopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { IconPlus, IconSettings, IconUser, IconUsers } from '@tabler/icons-react';\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay/Popover\";\nimport { Button } from \"../ui/buttons/Button\";\nimport {\n Command,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"../ui/overlay/Command\";\nimport { Checkbox } from \"../ui/form/Checkbox\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useListProjectUsers } from \"../../modules/projects/hooks/list-project-users.hook\";\nimport { useListAllAccountUsers } from \"../../modules/projects/hooks/list-all-account-users.hook\";\nimport { useAddProjectUser } from \"../../modules/projects/hooks/add-project-user.hook\";\nimport { useRemoveProjectUser } from \"../../modules/projects/hooks/remove-project-user.hook\";\nimport { useWhitelabelUrls } from \"../../providers/whitelabel.provider\";\n\nexport interface UsersSelectorPopoverProps {\n projectId?: number;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n}\n\nfunction UserItemSkeleton() {\n return (\n <div className=\"flex items-center justify-between px-2 py-1.5 gap-2\">\n <div className=\"flex items-center gap-2 flex-1\">\n <div className=\"skeleton size-8 rounded-full shrink-0\" />\n <div className=\"skeleton h-3.5 w-28 rounded\" />\n </div>\n <div className=\"skeleton size-4 rounded shrink-0\" />\n </div>\n );\n}\n\nexport function UsersSelectorPopover({\n projectId,\n side,\n align,\n contentClassName,\n}: UsersSelectorPopoverProps) {\n const { accountsUrl } = useWhitelabelUrls();\n const [open, setOpen] = useState(false);\n const [hoveredId, setHoveredId] = useState<number | null>(null);\n const [searchInput, setSearchInput] = useState(\"\");\n const [search, setSearch] = useState(\"\");\n\n const id = projectId ?? 0;\n\n useEffect(() => {\n const timer = setTimeout(() => setSearch(searchInput), 300);\n return () => clearTimeout(timer);\n }, [searchInput]);\n\n const accountUsers = useListAllAccountUsers(search, id || undefined);\n const projectUsers = useListProjectUsers(id, \"\");\n const addMutation = useAddProjectUser(id);\n const removeMutation = useRemoveProjectUser(id);\n\n const allUsers = accountUsers.data?.pages.flatMap((p) => p.data) ?? [];\n const isLoading = accountUsers.isLoading;\n const isFetchingMore = accountUsers.isFetchingNextPage;\n const totalInProject = projectUsers.data?.pages[0]?.total ?? 0;\n\n const toggleUser = (userId: number, inProject: boolean, removable: boolean) => {\n if (inProject) {\n if (!removable) return;\n removeMutation.mutate(userId);\n } else {\n addMutation.mutate(userId);\n }\n };\n\n const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {\n const target = e.currentTarget;\n const nearBottom =\n target.scrollTop + target.clientHeight >= target.scrollHeight - 50;\n if (!nearBottom) return;\n if (accountUsers.hasNextPage && !accountUsers.isFetchingNextPage) {\n accountUsers.fetchNextPage();\n }\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger className=\"cursor-pointer\">\n <div className=\"flex items-center gap-2 text-gray-950 px-3 py-2 border border-gray-200 rounded-full hover:border-gray-950\">\n <span className=\"paragraph-small-semibold\">{totalInProject}</span>\n <IconUser size={16} />\n </div>\n </PopoverTrigger>\n\n <PopoverContent\n className={cn(\n \"absolute right-0 md:right-[-88px] w-[273px] p-0 bg-white rounded-2xl shadow-md border border-gray-200\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"flex flex-col p-3 gap-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-small-semibold\">Usuários</span>\n <div className=\"flex items-center gap-1.5\">\n <Button\n variant=\"secondary\"\n className=\"h-8 paragraph-small-semibold text-gray-950\"\n onClick={() => {\n window.location.href = `${accountsUrl}/my-teams?createNew=true`;\n }}\n >\n <IconPlus size={16} />\n Adicionar\n </Button>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"secondary\"\n className=\"p-0 size-8\"\n onClick={() => {\n window.location.href = `${accountsUrl}/my-teams`;\n }}\n >\n <IconSettings size={18} />\n </Button>\n </TooltipTrigger>\n <TooltipContent className=\"z-[1002]\">\n Visualizar todos usuários\n </TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n <Command shouldFilter={false} className=\"gap-2\" value=\"\">\n <CommandInput\n placeholder=\"Busque aqui\"\n value={searchInput}\n onValueChange={setSearchInput}\n />\n <CommandList\n className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\"\n onScroll={handleScroll}\n >\n {isLoading ? (\n <>\n <UserItemSkeleton />\n <UserItemSkeleton />\n <UserItemSkeleton />\n </>\n ) : allUsers.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4\">\n <IconUsers size={28} className=\"text-gray-300\" />\n <span className=\"paragraph-small-medium text-center text-gray-500\">\n Nenhum usuário encontrado.\n </span>\n </div>\n ) : (\n <>\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\n {allUsers.map((user) => {\n const inProject = user.in_project ?? false;\n const removable =\n inProject &&\n user.profile !== \"owner\" &&\n user.profile !== \"admin\";\n const interactive = !inProject || removable;\n\n return (\n <CommandItem\n key={user.id}\n value={user.name || String(user.id)}\n autoFocus={false}\n onPointerEnter={() => setHoveredId(user.id)}\n onPointerLeave={() => setHoveredId(null)}\n onFocus={() => setHoveredId(user.id)}\n onBlur={() => setHoveredId(null)}\n onSelect={() => toggleUser(user.id, inProject, removable)}\n className={interactive ? \"cursor-pointer\" : \"cursor-default\"}\n >\n <div className=\"flex items-center justify-between w-full\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <UserAvatar\n photo={user.photo}\n name={user.name ?? undefined}\n size={32}\n />\n <span className=\"truncate\">{user.name}</span>\n </div>\n <Tooltip open={interactive && hoveredId === user.id}>\n <TooltipTrigger\n onClick={(e) => e.stopPropagation()}\n onPointerDown={(e) => e.stopPropagation()}\n >\n <Checkbox\n checked={inProject}\n disabled={!interactive}\n onCheckedChange={() =>\n toggleUser(user.id, inProject, removable)\n }\n className={cn(\n interactive && hoveredId === user.id\n ? \"border-gray-950\"\n : \"\",\n \"disabled:opacity-10\",\n )}\n />\n </TooltipTrigger>\n <TooltipContent className=\"z-[1002]\">\n {inProject ? \"Remover do projeto\" : \"Adicionar ao projeto\"}\n </TooltipContent>\n </Tooltip>\n </div>\n </CommandItem>\n );\n })}\n {isFetchingMore && (\n <>\n <UserItemSkeleton />\n <UserItemSkeleton />\n </>\n )}\n </>\n )}\n </CommandList>\n </Command>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/UsersSelectorPopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { IconPlus, IconSettings, IconUser, IconUsers } from '@tabler/icons-react';\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay/Popover\";\nimport { Button } from \"../ui/buttons/Button\";\nimport {\n Command,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"../ui/overlay/Command\";\nimport { Checkbox } from \"../ui/form/Checkbox\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useListProjectUsers } from \"../../modules/projects/hooks/list-project-users.hook\";\nimport { useListAllAccountUsers } from \"../../modules/projects/hooks/list-all-account-users.hook\";\nimport { useAddProjectUser } from \"../../modules/projects/hooks/add-project-user.hook\";\nimport { useRemoveProjectUser } from \"../../modules/projects/hooks/remove-project-user.hook\";\nimport { useWhitelabelUrls } from \"../../providers/whitelabel.provider\";\n\nexport interface UsersSelectorPopoverProps {\n projectId?: number;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n}\n\nfunction UserItemSkeleton() {\n return (\n <div className=\"flex items-center justify-between px-2 py-1.5 gap-2\">\n <div className=\"flex items-center gap-2 flex-1\">\n <div className=\"skeleton size-8 rounded-full shrink-0\" />\n <div className=\"skeleton h-3.5 w-28 rounded\" />\n </div>\n <div className=\"skeleton size-4 rounded shrink-0\" />\n </div>\n );\n}\n\nexport function UsersSelectorPopover({\n projectId,\n side,\n align,\n contentClassName,\n}: UsersSelectorPopoverProps) {\n const { accountsUrl } = useWhitelabelUrls();\n const [open, setOpen] = useState(false);\n const [hoveredId, setHoveredId] = useState<number | null>(null);\n const [searchInput, setSearchInput] = useState(\"\");\n const [search, setSearch] = useState(\"\");\n\n const id = projectId ?? 0;\n\n useEffect(() => {\n const timer = setTimeout(() => setSearch(searchInput), 300);\n return () => clearTimeout(timer);\n }, [searchInput]);\n\n const accountUsers = useListAllAccountUsers(search, id || undefined);\n const projectUsers = useListProjectUsers(id, \"\");\n const addMutation = useAddProjectUser(id);\n const removeMutation = useRemoveProjectUser(id);\n\n const allUsers = accountUsers.data?.pages.flatMap((p) => p.data) ?? [];\n const isLoading = accountUsers.isLoading;\n const isFetchingMore = accountUsers.isFetchingNextPage;\n const totalInProject = projectUsers.data?.pages[0]?.total ?? 0;\n\n const toggleUser = (userId: number, inProject: boolean, removable: boolean) => {\n if (inProject) {\n if (!removable) return;\n removeMutation.mutate(userId);\n } else {\n addMutation.mutate(userId);\n }\n };\n\n const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {\n const target = e.currentTarget;\n const nearBottom =\n target.scrollTop + target.clientHeight >= target.scrollHeight - 50;\n if (!nearBottom) return;\n if (accountUsers.hasNextPage && !accountUsers.isFetchingNextPage) {\n accountUsers.fetchNextPage();\n }\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger className=\"cursor-pointer\">\n <div className=\"flex items-center gap-2 text-gray-950 px-3 py-2 border border-gray-200 rounded-full hover:border-gray-950\">\n <span className=\"paragraph-small-semibold\">{totalInProject}</span>\n <IconUser size={16} />\n </div>\n </PopoverTrigger>\n\n <PopoverContent\n className={cn(\n \"absolute right-0 md:right-[-88px] w-[273px] p-0 bg-white rounded-2xl shadow-md border border-gray-200\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"flex flex-col p-3 gap-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"paragraph-small-semibold\">Usuários</span>\n <div className=\"flex items-center gap-1.5\">\n <Button\n variant=\"secondary\"\n className=\"h-8 paragraph-small-semibold text-gray-950\"\n onClick={() => {\n window.location.href = `${accountsUrl}/my-teams?createNew=true`;\n }}\n >\n <IconPlus size={16} />\n Adicionar\n </Button>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"secondary\"\n className=\"p-0 size-8\"\n onClick={() => {\n window.location.href = `${accountsUrl}/my-teams`;\n }}\n >\n <IconSettings size={18} />\n </Button>\n </TooltipTrigger>\n <TooltipContent className=\"z-[1002]\">\n Visualizar todos usuários\n </TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n <Command shouldFilter={false} className=\"gap-2\" value=\"\">\n <CommandInput\n placeholder=\"Busque aqui\"\n value={searchInput}\n onValueChange={setSearchInput}\n />\n <CommandList\n className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\"\n onScroll={handleScroll}\n >\n {isLoading ? (\n <>\n <UserItemSkeleton />\n <UserItemSkeleton />\n <UserItemSkeleton />\n </>\n ) : allUsers.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4\">\n <IconUsers size={28} className=\"text-gray-300\" />\n <span className=\"paragraph-small-medium text-center text-gray-500\">\n Nenhum usuário encontrado.\n </span>\n </div>\n ) : (\n <>\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\n {allUsers.map((user) => {\n const inProject = user.in_project ?? false;\n const removable =\n inProject &&\n user.profile !== \"owner\" &&\n user.profile !== \"admin\";\n const interactive = !inProject || removable;\n\n return (\n <CommandItem\n key={user.id}\n value={user.name || String(user.id)}\n autoFocus={false}\n onPointerEnter={() => setHoveredId(user.id)}\n onPointerLeave={() => setHoveredId(null)}\n onFocus={() => setHoveredId(user.id)}\n onBlur={() => setHoveredId(null)}\n onSelect={() => toggleUser(user.id, inProject, removable)}\n className={interactive ? \"cursor-pointer\" : \"cursor-default\"}\n >\n <div className=\"flex items-center justify-between w-full\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <UserAvatar\n photo={user.photo}\n name={user.name ?? undefined}\n size={32}\n />\n <span className=\"truncate\">{user.name}</span>\n </div>\n <Tooltip open={interactive && hoveredId === user.id}>\n <TooltipTrigger asChild>\n <div\n onClick={(e) => e.stopPropagation()}\n onPointerDown={(e) => e.stopPropagation()}\n >\n <Checkbox\n checked={inProject}\n disabled={!interactive}\n onCheckedChange={() =>\n toggleUser(user.id, inProject, removable)\n }\n className={cn(\n interactive && hoveredId === user.id\n ? \"border-gray-950\"\n : \"\",\n \"disabled:opacity-10\",\n )}\n />\n </div>\n </TooltipTrigger>\n <TooltipContent className=\"z-[1002]\">\n {inProject ? \"Remover do projeto\" : \"Adicionar ao projeto\"}\n </TooltipContent>\n </Tooltip>\n </div>\n </CommandItem>\n );\n })}\n {isFetchingMore && (\n <>\n <UserItemSkeleton />\n <UserItemSkeleton />\n </>\n )}\n </>\n )}\n </CommandList>\n </Command>\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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","names":[]}
@@ -2,13 +2,17 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useAppNavigationContext } from "./AppNavigationContext";
4
4
  import { useMobileNavbarSheet } from "../../store/useMobileNavbarSheet";
5
+ import { useMdSidebarStore } from "../../store/useMdSidebarStore";
5
6
  function NavItem({ icon: Icon, label, onClick, isActive = false }) {
6
7
  const { breakpoint } = useAppNavigationContext();
7
8
  const { close } = useMobileNavbarSheet();
9
+ const { collapse } = useMdSidebarStore();
8
10
  const handleClick = () => {
9
11
  onClick();
10
12
  if (breakpoint === "mobile") {
11
13
  close();
14
+ } else if (breakpoint === "md") {
15
+ collapse();
12
16
  }
13
17
  };
14
18
  return /* @__PURE__ */ jsxs(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/navigation/NavItem.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { ElementType } from 'react';\r\nimport { useAppNavigationContext } from './AppNavigationContext';\r\nimport { useMobileNavbarSheet } from '../../store/useMobileNavbarSheet';\r\n\r\ninterface NavItemProps {\r\n icon?: ElementType;\r\n label: string;\r\n onClick: () => void;\r\n isActive?: boolean;\r\n}\r\n\r\nexport function NavItem({ icon: Icon, label, onClick, isActive = false }: NavItemProps) {\r\n const { breakpoint } = useAppNavigationContext();\r\n const { close } = useMobileNavbarSheet();\r\n\r\n const handleClick = () => {\r\n onClick();\r\n if (breakpoint === 'mobile') {\r\n close();\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n className={`rounded-md flex items-center gap-2 p-3 cursor-pointer transition-colors ${\r\n isActive ? 'bg-gray-50' : 'bg-white hover:bg-gray-100'\r\n } active:bg-gray-50`}\r\n onClick={handleClick}\r\n >\r\n {Icon && (\r\n <Icon\r\n size={20}\r\n className={isActive ? 'text-gray-950' : 'text-gray-400'}\r\n />\r\n )}\r\n <span className={`paragraph-small-medium ${isActive ? 'text-gray-950' : 'text-gray-500'}`}>\r\n {label}\r\n </span>\r\n </div>\r\n );\r\n}\r\n"],"mappings":";AAyBI,SAOI,KAPJ;AAtBJ,SAAS,+BAA+B;AACxC,SAAS,4BAA4B;AAS9B,SAAS,QAAQ,EAAE,MAAM,MAAM,OAAO,SAAS,WAAW,MAAM,GAAiB;AACtF,QAAM,EAAE,WAAW,IAAI,wBAAwB;AAC/C,QAAM,EAAE,MAAM,IAAI,qBAAqB;AAEvC,QAAM,cAAc,MAAM;AACxB,YAAQ;AACR,QAAI,eAAe,UAAU;AAC3B,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,2EACT,WAAW,eAAe,4BAC5B;AAAA,MACA,SAAS;AAAA,MAER;AAAA,gBACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAW,WAAW,kBAAkB;AAAA;AAAA,QAC1C;AAAA,QAEF,oBAAC,UAAK,WAAW,0BAA0B,WAAW,kBAAkB,eAAe,IACpF,iBACH;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/navigation/NavItem.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { ElementType } from 'react';\r\nimport { useAppNavigationContext } from './AppNavigationContext';\r\nimport { useMobileNavbarSheet } from '../../store/useMobileNavbarSheet';\r\nimport { useMdSidebarStore } from '../../store/useMdSidebarStore';\r\n\r\ninterface NavItemProps {\r\n icon?: ElementType;\r\n label: string;\r\n onClick: () => void;\r\n isActive?: boolean;\r\n}\r\n\r\nexport function NavItem({ icon: Icon, label, onClick, isActive = false }: NavItemProps) {\r\n const { breakpoint } = useAppNavigationContext();\r\n const { close } = useMobileNavbarSheet();\r\n const { collapse } = useMdSidebarStore();\r\n\r\n const handleClick = () => {\r\n onClick();\r\n if (breakpoint === 'mobile') {\r\n close();\r\n } else if (breakpoint === 'md') {\r\n collapse();\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n className={`rounded-md flex items-center gap-2 p-3 cursor-pointer transition-colors ${\r\n isActive ? 'bg-gray-50' : 'bg-white hover:bg-gray-100'\r\n } active:bg-gray-50`}\r\n onClick={handleClick}\r\n >\r\n {Icon && (\r\n <Icon\r\n size={20}\r\n className={isActive ? 'text-gray-950' : 'text-gray-400'}\r\n />\r\n )}\r\n <span className={`paragraph-small-medium ${isActive ? 'text-gray-950' : 'text-gray-500'}`}>\r\n {label}\r\n </span>\r\n </div>\r\n );\r\n}\r\n"],"mappings":";AA6BI,SAOI,KAPJ;AA1BJ,SAAS,+BAA+B;AACxC,SAAS,4BAA4B;AACrC,SAAS,yBAAyB;AAS3B,SAAS,QAAQ,EAAE,MAAM,MAAM,OAAO,SAAS,WAAW,MAAM,GAAiB;AACtF,QAAM,EAAE,WAAW,IAAI,wBAAwB;AAC/C,QAAM,EAAE,MAAM,IAAI,qBAAqB;AACvC,QAAM,EAAE,SAAS,IAAI,kBAAkB;AAEvC,QAAM,cAAc,MAAM;AACxB,YAAQ;AACR,QAAI,eAAe,UAAU;AAC3B,YAAM;AAAA,IACR,WAAW,eAAe,MAAM;AAC9B,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,2EACT,WAAW,eAAe,4BAC5B;AAAA,MACA,SAAS;AAAA,MAER;AAAA,gBACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,WAAW,WAAW,kBAAkB;AAAA;AAAA,QAC1C;AAAA,QAEF,oBAAC,UAAK,WAAW,0BAA0B,WAAW,kBAAkB,eAAe,IACpF,iBACH;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -5,9 +5,9 @@ import { buildQueryParams } from "../../../infra/utils/params";
5
5
  import { getUserContext } from "../../auth/utils/get-user-context";
6
6
  import { fileToBase64 } from "../../../utils/file/index";
7
7
  class AccountService {
8
- async findCurrentAccount() {
8
+ async findCurrentAccount(config) {
9
9
  const { id_account } = await getUserContext();
10
- const response = await api.apps.get(`/accounts/${id_account}`);
10
+ const response = await api.apps.get(`/accounts/${id_account}`, config);
11
11
  if (response.status === 0 || !response.data?.[0]) {
12
12
  throw new ApiError(
13
13
  response.message || "Erro ao buscar dados da conta",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/accounts/services/account.service.ts"],"sourcesContent":["import 'server-only';\n\nimport { api } from '../../../infra/api/client';\nimport { ApiError } from '../../../infra/api/types';\nimport { buildQueryParams } from '../../../infra/utils/params';\nimport { getUserContext } from '../../auth/utils/get-user-context';\nimport { fileToBase64 } from '../../../utils/file/index';\nimport type {\n Account,\n AccountUsersPaginationParams,\n ChangePasswordRequest,\n ChangePasswordResponse,\n ChangeUserPhotoResponse,\n CreateAccountUserRequest,\n CreateAccountUserResponse,\n DeleteAccountResponse,\n DeleteAccountUserResponse,\n GetAccountDataResponse,\n ListAccountUsersResponse,\n UpdateAccountRequest,\n UpdateAccountResponse,\n UpdateAccountUserRequest,\n UpdateAccountUserResponse,\n} from '../types';\n\nclass AccountService {\n async findCurrentAccount(): Promise<Account> {\n const { id_account } = await getUserContext();\n const response = await api.apps.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 async listAccountUsers(params?: Partial<AccountUsersPaginationParams>) {\n const { id_account } = await getUserContext();\n const queryParams = buildQueryParams(params);\n const endpoint = `/accounts/${id_account}/users?${queryParams}`;\n const response = await api.apps.get<ListAccountUsersResponse>(endpoint);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar usuários',\n 'LIST_ACCOUNT_USERS_FAILED',\n 400\n );\n }\n\n return {\n users: response.data || [],\n total: response.total || 0,\n };\n }\n\n async changeUserPhoto(userId: number, photo: File): Promise<ChangeUserPhotoResponse> {\n const { id_account } = await getUserContext();\n const base64 = await fileToBase64(photo);\n const response = await api.apps.put<ChangeUserPhotoResponse>(\n `/accounts/${id_account}/users/${userId}/file/photo`,\n { file: base64 }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao mudar foto do usuário',\n 'CHANGE_USER_PHOTO_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async deleteAccountUser(userId: number): Promise<DeleteAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar usuário', 'DELETE_USER_FAILED', 400);\n }\n\n return response;\n }\n\n async deleteAccount(): Promise<DeleteAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountResponse>(`/accounts/${id_account}`);\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar conta', 'DELETE_ACCOUNT_FAILED', 400);\n }\n\n return response;\n }\n\n async createAccountUser(user: CreateAccountUserRequest): Promise<CreateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.post<CreateAccountUserResponse>(\n `/accounts/${id_account}/users`,\n {\n ...user,\n photo: user.photo ? await fileToBase64(user.photo) : null,\n }\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao criar usuário', 'CREATE_USER_FAILED', 400);\n }\n\n return response;\n }\n\n private async resolvePhotoField(user: UpdateAccountUserRequest): Promise<{ photo?: string | null }> {\n if (user.photo === undefined) return {};\n const photo =\n user.photo != null && typeof user.photo !== 'string'\n ? await fileToBase64(user.photo)\n : user.photo;\n return { photo };\n }\n\n async updateAccountUser(user: UpdateAccountUserRequest): Promise<UpdateAccountUserResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${id_user}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async updateAccountUserById(\n userId: number,\n user: UpdateAccountUserRequest\n ): Promise<UpdateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async updateAccount(data: UpdateAccountRequest): Promise<UpdateAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountResponse>(`/accounts/${id_account}`, data);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar conta',\n 'UPDATE_ACCOUNT_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async requestContactReset(type: 'email' | 'phone', newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/request`,\n { type, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao solicitar alteração',\n 'REQUEST_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n async confirmContactReset(type: 'email' | 'phone', token: string, newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/confirm`,\n { type, token, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Código inválido ou expirado',\n 'CONFIRM_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n async changePassword(data: ChangePasswordRequest): Promise<ChangePasswordResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<ChangePasswordResponse>(\n `/accounts/${id_account}/users/${id_user}/action/changePassword`,\n data\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao alterar senha',\n 'CHANGE_PASSWORD_FAILED',\n 400\n );\n }\n\n return response;\n }\n}\n\nexport const accountService = new AccountService();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/accounts/services/account.service.ts"],"sourcesContent":["import 'server-only';\n\nimport { api } from '../../../infra/api/client';\nimport { ApiError } from '../../../infra/api/types';\nimport { buildQueryParams } from '../../../infra/utils/params';\nimport { getUserContext } from '../../auth/utils/get-user-context';\nimport { fileToBase64 } from '../../../utils/file/index';\nimport type { RequestConfig } from '../../../infra/api/client';\nimport type {\n Account,\n AccountUsersPaginationParams,\n ChangePasswordRequest,\n ChangePasswordResponse,\n ChangeUserPhotoResponse,\n CreateAccountUserRequest,\n CreateAccountUserResponse,\n DeleteAccountResponse,\n DeleteAccountUserResponse,\n GetAccountDataResponse,\n ListAccountUsersResponse,\n UpdateAccountRequest,\n UpdateAccountResponse,\n UpdateAccountUserRequest,\n UpdateAccountUserResponse,\n} from '../types';\n\nclass AccountService {\n async findCurrentAccount(config?: RequestConfig): Promise<Account> {\n const { id_account } = await getUserContext();\n const response = await api.apps.get<GetAccountDataResponse>(`/accounts/${id_account}`, config);\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 async listAccountUsers(params?: Partial<AccountUsersPaginationParams>) {\n const { id_account } = await getUserContext();\n const queryParams = buildQueryParams(params);\n const endpoint = `/accounts/${id_account}/users?${queryParams}`;\n const response = await api.apps.get<ListAccountUsersResponse>(endpoint);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao listar usuários',\n 'LIST_ACCOUNT_USERS_FAILED',\n 400\n );\n }\n\n return {\n users: response.data || [],\n total: response.total || 0,\n };\n }\n\n async changeUserPhoto(userId: number, photo: File): Promise<ChangeUserPhotoResponse> {\n const { id_account } = await getUserContext();\n const base64 = await fileToBase64(photo);\n const response = await api.apps.put<ChangeUserPhotoResponse>(\n `/accounts/${id_account}/users/${userId}/file/photo`,\n { file: base64 }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao mudar foto do usuário',\n 'CHANGE_USER_PHOTO_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async deleteAccountUser(userId: number): Promise<DeleteAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar usuário', 'DELETE_USER_FAILED', 400);\n }\n\n return response;\n }\n\n async deleteAccount(): Promise<DeleteAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.delete<DeleteAccountResponse>(`/accounts/${id_account}`);\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao deletar conta', 'DELETE_ACCOUNT_FAILED', 400);\n }\n\n return response;\n }\n\n async createAccountUser(user: CreateAccountUserRequest): Promise<CreateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.post<CreateAccountUserResponse>(\n `/accounts/${id_account}/users`,\n {\n ...user,\n photo: user.photo ? await fileToBase64(user.photo) : null,\n }\n );\n\n if (response.status === 0) {\n throw new ApiError(response.message || 'Erro ao criar usuário', 'CREATE_USER_FAILED', 400);\n }\n\n return response;\n }\n\n private async resolvePhotoField(user: UpdateAccountUserRequest): Promise<{ photo?: string | null }> {\n if (user.photo === undefined) return {};\n const photo =\n user.photo != null && typeof user.photo !== 'string'\n ? await fileToBase64(user.photo)\n : user.photo;\n return { photo };\n }\n\n async updateAccountUser(user: UpdateAccountUserRequest): Promise<UpdateAccountUserResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${id_user}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async updateAccountUserById(\n userId: number,\n user: UpdateAccountUserRequest\n ): Promise<UpdateAccountUserResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountUserResponse>(\n `/accounts/${id_account}/users/${userId}`,\n { ...user, ...(await this.resolvePhotoField(user)) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar usuário',\n 'UPDATE_USER_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async updateAccount(data: UpdateAccountRequest): Promise<UpdateAccountResponse> {\n const { id_account } = await getUserContext();\n const response = await api.apps.put<UpdateAccountResponse>(`/accounts/${id_account}`, data);\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao atualizar conta',\n 'UPDATE_ACCOUNT_FAILED',\n 400\n );\n }\n\n return response;\n }\n\n async requestContactReset(type: 'email' | 'phone', newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/request`,\n { type, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao solicitar alteração',\n 'REQUEST_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n async confirmContactReset(type: 'email' | 'phone', token: string, newContact: string, ddi?: string): Promise<void> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.post<{ status: number; message: string }>(\n `/accounts/${id_account}/users/${id_user}/resetContact/confirm`,\n { type, token, newContact, ...(ddi ? { ddi } : {}) }\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Código inválido ou expirado',\n 'CONFIRM_CONTACT_RESET_FAILED',\n 400\n );\n }\n }\n\n async changePassword(data: ChangePasswordRequest): Promise<ChangePasswordResponse> {\n const { id_account, id_user } = await getUserContext();\n const response = await api.apps.put<ChangePasswordResponse>(\n `/accounts/${id_account}/users/${id_user}/action/changePassword`,\n data\n );\n\n if (response.status === 0) {\n throw new ApiError(\n response.message || 'Erro ao alterar senha',\n 'CHANGE_PASSWORD_FAILED',\n 400\n );\n }\n\n return response;\n }\n}\n\nexport const accountService = new AccountService();\n"],"mappings":"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","names":[]}
@@ -51,8 +51,8 @@ class AuthService {
51
51
  import("../../accounts/services/account.service")
52
52
  ]);
53
53
  const [user, account] = await Promise.all([
54
- userService.findById(),
55
- accountService.findCurrentAccount()
54
+ userService.findById(requestConfig ? { authToken: requestConfig.authToken } : void 0),
55
+ accountService.findCurrentAccount(requestConfig)
56
56
  ]);
57
57
  return {
58
58
  result: "success",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\r\n\r\nimport { api } from \"../../../infra/api/client\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\r\nimport {\r\n ClientInfo,\r\n ForgotPasswordRequest,\r\n ForgotPasswordResponse,\r\n GeoLocation,\r\n LoginApiResponse,\r\n LoginRequest,\r\n LoginResponse,\r\n LogoutApiResponse,\r\n LogoutRequest,\r\n LogoutResponse,\r\n RegisterApiRequest,\r\n RegisterApiResponse,\r\n RegisterRequest,\r\n RegisterResponse,\r\n ResendVerificationRequest,\r\n ResendVerificationResponse,\r\n ResetPasswordRequest,\r\n ResetPasswordResponse,\r\n SearchPlansApiResponse,\r\n SessionKeepRequest,\r\n SessionKeepResponse,\r\n TwoFactorApiResponse,\r\n TwoFactorRequest,\r\n TwoFactorResponse,\r\n VerifyEmailRequest,\r\n VerifyEmailResponse,\r\n} from \"../schema\";\r\nimport { findWhitelabel } from \"../../../server\";\r\n\r\nconst AUTH_COOKIE_NAME = \"greatapps\";\r\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\r\n\r\nconst COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === \"production\",\r\n sameSite: \"lax\" as const,\r\n path: \"/\",\r\n domain: process.env.DOMAIN_COOKIE,\r\n};\r\n\r\nclass AuthService {\r\n async login(\r\n credentials: LoginRequest,\r\n clientInfo: ClientInfo\r\n ): Promise<LoginResponse> {\r\n let requestConfig: import(\"../../../infra/api/client\").RequestConfig | undefined;\r\n\r\n if (credentials.id_wl) {\r\n const wlToken = await whitelabelService.getTokenByWhitelabelId(credentials.id_wl);\r\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\r\n }\r\n\r\n const response = await api.apps.post<LoginApiResponse>(\"/auth/login\", {\r\n email: credentials.email,\r\n password: credentials.password,\r\n source: credentials?.source,\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n }, requestConfig);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"E-mail ou senha incorretos\",\r\n response.code || \"LOGIN_FAILED\",\r\n 401\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (response.two_factor_required) {\r\n return { result: 'two_factor_required', cookie: response.cookie };\r\n }\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n result: 'success',\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n };\r\n }\r\n\r\n async verifyTwoFactor(\r\n cookie: string,\r\n code: string,\r\n clientInfo: ClientInfo\r\n ): Promise<TwoFactorResponse> {\r\n const payload: TwoFactorRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n code,\r\n };\r\n\r\n const response = await api.apps.post<TwoFactorApiResponse>(\r\n \"/auth/code\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\r\n }\r\n\r\n if (!response?.data?.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida após 2FA\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n await this.setAuthCookie(response.data.cookie);\r\n\r\n return { status: 1 };\r\n }\r\n async register(data: RegisterRequest, clientInfo: ClientInfo): Promise<RegisterResponse> {\r\n const today = new Date();\r\n const trialEndDate = new Date(today);\r\n trialEndDate.setDate(today.getDate() + 7); // 7 dias de trial\r\n\r\n const idPlan = await this.resolvePlanId(data.idPlan);\r\n\r\n const payload: RegisterApiRequest = {\r\n name: data.accountName,\r\n bussiness_type: data.businessType ?? 0,\r\n language: \"pt-br\",\r\n timezone: \"America/Sao_Paulo\",\r\n currency: \"BRL\",\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n agent: clientInfo.agent,\r\n user: {\r\n id_api: \"\",\r\n name: data.name,\r\n last_name: data.lastName || \"\",\r\n rg: data.rg || \"\",\r\n cpf: data.cpf || \"\",\r\n gender: data.gender,\r\n email: data.email,\r\n phone: data.phone,\r\n password: data.password,\r\n profile: \"owner\",\r\n language: \"pt-br\",\r\n },\r\n subscription: {\r\n type: \"trial\",\r\n id_cupom: data.couponCode || \"\",\r\n id_plan: idPlan,\r\n due_date: trialEndDate.toISOString().split(\"T\")[0],\r\n id_product: 1,\r\n },\r\n };\r\n\r\n const response = await api.apps.post<RegisterApiResponse>(\r\n \"/accounts\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao criar conta\",\r\n \"REGISTER_FAILED\",\r\n 400\r\n );\r\n }\r\n\r\n if (!response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n \"Resposta de registro inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n const accountData = response.data[0];\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n requiresEmailVerification: !accountData.verified,\r\n };\r\n }\r\n\r\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n throw new ApiError(\r\n \"Usuário não autenticado\",\r\n \"NOT_AUTHENTICATED_LOGOUT\",\r\n 401\r\n );\r\n }\r\n\r\n const payload: LogoutRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n try {\r\n const response = await api.apps.post<LogoutApiResponse>(\r\n \"/auth/logout\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao realizar logout\",\r\n response.code || \"LOGOUT_FAILED\",\r\n 400\r\n );\r\n }\r\n } finally {\r\n await this.removeAuthCookie();\r\n }\r\n\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n async forgotPassword(\r\n _data: ForgotPasswordRequest\r\n ): Promise<ForgotPasswordResponse> {\r\n throw new ApiError(\r\n \"Recuperação de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resetPassword(\r\n _data: ResetPasswordRequest\r\n ): Promise<ResetPasswordResponse> {\r\n throw new ApiError(\r\n \"Redefinição de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\r\n throw new ApiError(\r\n \"Verificação de email não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resendVerification(\r\n _data: ResendVerificationRequest\r\n ): Promise<ResendVerificationResponse> {\r\n throw new ApiError(\r\n \"Reenvio de verificação não implementado\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n return false;\r\n }\r\n\r\n try {\r\n const payload: SessionKeepRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n const response = await api.apps.post<SessionKeepResponse>(\r\n \"/auth/keep\",\r\n payload\r\n );\r\n\r\n return response.status === 1;\r\n } catch (error) {\r\n console.error(\"[AuthService] validateSession error\", error);\r\n return false;\r\n }\r\n }\r\n\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getToken();\r\n return !!token;\r\n }\r\n\r\n async getToken(): Promise<string | undefined> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n }\r\n\r\n private async resolvePlanId(idPlan?: number | string): Promise<number> {\r\n if (idPlan === undefined || idPlan === null) return 1;\r\n if (typeof idPlan === 'number') return idPlan;\r\n\r\n const response = await api.apps.get<SearchPlansApiResponse>(\r\n `/plans?search=${encodeURIComponent(idPlan)}`\r\n );\r\n\r\n if (response.status === 0 || !response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n `Plano \"${idPlan}\" não encontrado`,\r\n \"PLAN_NOT_FOUND\",\r\n 404\r\n );\r\n }\r\n\r\n return response.data[0].id;\r\n }\r\n\r\n private async setAuthCookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.set(AUTH_COOKIE_NAME, token, {\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n maxAge: COOKIE_MAX_AGE,\r\n });\r\n }\r\n\r\n async removeAuthCookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.delete({\r\n name: AUTH_COOKIE_NAME,\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n });\r\n }\r\n\r\n private normalizeCookieDomain(domain?: string | null): string | undefined {\r\n if (!domain) return undefined;\r\n\r\n const normalized = domain.trim();\r\n if (!normalized) return undefined;\r\n\r\n const rawHost = (() => {\r\n try {\r\n return new URL(normalized).hostname;\r\n } catch {\r\n return normalized\r\n .replace(/^https?:\\/\\//i, \"\")\r\n .replace(/^www\\./i, \"\")\r\n .split(\"/\")[0]\r\n .split(\":\")[0];\r\n }\r\n })();\r\n\r\n if (!rawHost || rawHost === \"localhost\") {\r\n return undefined;\r\n }\r\n\r\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\r\n }\r\n}\r\n\r\nexport const authService = new AuthService();\r\n\r\nexport type { ClientInfo, GeoLocation };\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/auth/services/auth.service.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\r\n\r\nimport { api } from \"../../../infra/api/client\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { whitelabelService } from \"../../whitelabel/services/whitelabel.service\";\r\nimport {\r\n ClientInfo,\r\n ForgotPasswordRequest,\r\n ForgotPasswordResponse,\r\n GeoLocation,\r\n LoginApiResponse,\r\n LoginRequest,\r\n LoginResponse,\r\n LogoutApiResponse,\r\n LogoutRequest,\r\n LogoutResponse,\r\n RegisterApiRequest,\r\n RegisterApiResponse,\r\n RegisterRequest,\r\n RegisterResponse,\r\n ResendVerificationRequest,\r\n ResendVerificationResponse,\r\n ResetPasswordRequest,\r\n ResetPasswordResponse,\r\n SearchPlansApiResponse,\r\n SessionKeepRequest,\r\n SessionKeepResponse,\r\n TwoFactorApiResponse,\r\n TwoFactorRequest,\r\n TwoFactorResponse,\r\n VerifyEmailRequest,\r\n VerifyEmailResponse,\r\n} from \"../schema\";\r\nimport { findWhitelabel } from \"../../../server\";\r\n\r\nconst AUTH_COOKIE_NAME = \"greatapps\";\r\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30;\r\n\r\nconst COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === \"production\",\r\n sameSite: \"lax\" as const,\r\n path: \"/\",\r\n domain: process.env.DOMAIN_COOKIE,\r\n};\r\n\r\nclass AuthService {\r\n \r\n async login(\r\n credentials: LoginRequest,\r\n clientInfo: ClientInfo\r\n ): Promise<LoginResponse> {\r\n let requestConfig: import(\"../../../infra/api/client\").RequestConfig | undefined;\r\n if (credentials.id_wl) {\r\n const wlToken = await whitelabelService.getTokenByWhitelabelId(credentials.id_wl);\r\n requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };\r\n \r\n }\r\n\r\n const response = await api.apps.post<LoginApiResponse>(\"/auth/login\", {\r\n email: credentials.email,\r\n password: credentials.password,\r\n source: credentials?.source,\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n }, requestConfig);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"E-mail ou senha incorretos\",\r\n response.code || \"LOGIN_FAILED\",\r\n 401\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (response.two_factor_required) {\r\n return { result: 'two_factor_required', cookie: response.cookie };\r\n }\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(requestConfig ? { authToken: requestConfig.authToken } : undefined),\r\n accountService.findCurrentAccount(requestConfig),\r\n ]);\r\n\r\n return {\r\n result: 'success',\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n };\r\n }\r\n\r\n async verifyTwoFactor(\r\n cookie: string,\r\n code: string,\r\n clientInfo: ClientInfo\r\n ): Promise<TwoFactorResponse> {\r\n const payload: TwoFactorRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n code,\r\n };\r\n\r\n const response = await api.apps.post<TwoFactorApiResponse>(\r\n \"/auth/code\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\"Código 2FA inválido\", \"TWO_FACTOR_FAILED\", 401);\r\n }\r\n\r\n if (!response?.data?.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida após 2FA\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n await this.setAuthCookie(response.data.cookie);\r\n\r\n return { status: 1 };\r\n }\r\n async register(data: RegisterRequest, clientInfo: ClientInfo): Promise<RegisterResponse> {\r\n const today = new Date();\r\n const trialEndDate = new Date(today);\r\n trialEndDate.setDate(today.getDate() + 7); // 7 dias de trial\r\n\r\n const idPlan = await this.resolvePlanId(data.idPlan);\r\n\r\n const payload: RegisterApiRequest = {\r\n name: data.accountName,\r\n bussiness_type: data.businessType ?? 0,\r\n language: \"pt-br\",\r\n timezone: \"America/Sao_Paulo\",\r\n currency: \"BRL\",\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n agent: clientInfo.agent,\r\n user: {\r\n id_api: \"\",\r\n name: data.name,\r\n last_name: data.lastName || \"\",\r\n rg: data.rg || \"\",\r\n cpf: data.cpf || \"\",\r\n gender: data.gender,\r\n email: data.email,\r\n phone: data.phone,\r\n password: data.password,\r\n profile: \"owner\",\r\n language: \"pt-br\",\r\n },\r\n subscription: {\r\n type: \"trial\",\r\n id_cupom: data.couponCode || \"\",\r\n id_plan: idPlan,\r\n due_date: trialEndDate.toISOString().split(\"T\")[0],\r\n id_product: 1,\r\n },\r\n };\r\n\r\n const response = await api.apps.post<RegisterApiResponse>(\r\n \"/accounts\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao criar conta\",\r\n \"REGISTER_FAILED\",\r\n 400\r\n );\r\n }\r\n\r\n if (!response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n \"Resposta de registro inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n if (!response.cookie) {\r\n throw new ApiError(\r\n \"Resposta de autenticação inválida\",\r\n \"INVALID_RESPONSE\",\r\n 500\r\n );\r\n }\r\n\r\n const accountData = response.data[0];\r\n\r\n await this.setAuthCookie(response.cookie);\r\n\r\n const [{ userService }, { accountService }] = await Promise.all([\r\n import('../../users/services/user.service'),\r\n import('../../accounts/services/account.service'),\r\n ]);\r\n const [user, account] = await Promise.all([\r\n userService.findById(),\r\n accountService.findCurrentAccount(),\r\n ]);\r\n\r\n return {\r\n user,\r\n account,\r\n accessToken: response.cookie,\r\n refreshToken: \"\",\r\n expiresAt: new Date(Date.now() + COOKIE_MAX_AGE * 1000).toISOString(),\r\n requiresEmailVerification: !accountData.verified,\r\n };\r\n }\r\n\r\n async logout(clientInfo: ClientInfo): Promise<LogoutResponse> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n throw new ApiError(\r\n \"Usuário não autenticado\",\r\n \"NOT_AUTHENTICATED_LOGOUT\",\r\n 401\r\n );\r\n }\r\n\r\n const payload: LogoutRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n try {\r\n const response = await api.apps.post<LogoutApiResponse>(\r\n \"/auth/logout\",\r\n payload\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao realizar logout\",\r\n response.code || \"LOGOUT_FAILED\",\r\n 400\r\n );\r\n }\r\n } finally {\r\n await this.removeAuthCookie();\r\n }\r\n\r\n return {\r\n success: true,\r\n };\r\n }\r\n\r\n async forgotPassword(\r\n _data: ForgotPasswordRequest\r\n ): Promise<ForgotPasswordResponse> {\r\n throw new ApiError(\r\n \"Recuperação de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resetPassword(\r\n _data: ResetPasswordRequest\r\n ): Promise<ResetPasswordResponse> {\r\n throw new ApiError(\r\n \"Redefinição de senha não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async verifyEmail(_data: VerifyEmailRequest): Promise<VerifyEmailResponse> {\r\n throw new ApiError(\r\n \"Verificação de email não implementada\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async resendVerification(\r\n _data: ResendVerificationRequest\r\n ): Promise<ResendVerificationResponse> {\r\n throw new ApiError(\r\n \"Reenvio de verificação não implementado\",\r\n \"NOT_IMPLEMENTED\",\r\n 501\r\n );\r\n }\r\n\r\n async validateSession(clientInfo: ClientInfo): Promise<boolean> {\r\n const cookie = await this.getToken();\r\n\r\n if (!cookie) {\r\n return false;\r\n }\r\n\r\n try {\r\n const payload: SessionKeepRequest = {\r\n location: clientInfo.location,\r\n ip: clientInfo.ip,\r\n timezone: clientInfo.timezone,\r\n agent: clientInfo.agent,\r\n cookie,\r\n };\r\n\r\n const response = await api.apps.post<SessionKeepResponse>(\r\n \"/auth/keep\",\r\n payload\r\n );\r\n\r\n return response.status === 1;\r\n } catch (error) {\r\n console.error(\"[AuthService] validateSession error\", error);\r\n return false;\r\n }\r\n }\r\n\r\n async isAuthenticated(): Promise<boolean> {\r\n const token = await this.getToken();\r\n return !!token;\r\n }\r\n\r\n async getToken(): Promise<string | undefined> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n return cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n }\r\n\r\n private async resolvePlanId(idPlan?: number | string): Promise<number> {\r\n if (idPlan === undefined || idPlan === null) return 1;\r\n if (typeof idPlan === 'number') return idPlan;\r\n\r\n const response = await api.apps.get<SearchPlansApiResponse>(\r\n `/plans?search=${encodeURIComponent(idPlan)}`\r\n );\r\n\r\n if (response.status === 0 || !response.data || response.data.length === 0) {\r\n throw new ApiError(\r\n `Plano \"${idPlan}\" não encontrado`,\r\n \"PLAN_NOT_FOUND\",\r\n 404\r\n );\r\n }\r\n\r\n return response.data[0].id;\r\n }\r\n\r\n private async setAuthCookie(token: string): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.set(AUTH_COOKIE_NAME, token, {\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n maxAge: COOKIE_MAX_AGE,\r\n });\r\n }\r\n\r\n async removeAuthCookie(): Promise<void> {\r\n const cookieStore = await cookies();\r\n const whitelabel = await findWhitelabel().catch(() => null);\r\n const cookieDomain =\r\n this.normalizeCookieDomain(whitelabel?.domain) ??\r\n this.normalizeCookieDomain(process.env.DOMAIN_COOKIE);\r\n\r\n cookieStore.delete({\r\n name: AUTH_COOKIE_NAME,\r\n ...COOKIE_OPTIONS,\r\n ...(cookieDomain ? { domain: cookieDomain } : {}),\r\n });\r\n }\r\n\r\n private normalizeCookieDomain(domain?: string | null): string | undefined {\r\n if (!domain) return undefined;\r\n\r\n const normalized = domain.trim();\r\n if (!normalized) return undefined;\r\n\r\n const rawHost = (() => {\r\n try {\r\n return new URL(normalized).hostname;\r\n } catch {\r\n return normalized\r\n .replace(/^https?:\\/\\//i, \"\")\r\n .replace(/^www\\./i, \"\")\r\n .split(\"/\")[0]\r\n .split(\":\")[0];\r\n }\r\n })();\r\n\r\n if (!rawHost || rawHost === \"localhost\") {\r\n return undefined;\r\n }\r\n\r\n return rawHost.startsWith(\".\") ? rawHost : `.${rawHost}`;\r\n }\r\n}\r\n\r\nexport const authService = new AuthService();\r\n\r\nexport type { ClientInfo, GeoLocation };\r\n"],"mappings":"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","names":[]}
@@ -20,11 +20,11 @@ class UserService {
20
20
  throw new ApiError("Token inv\xE1lido", "INVALID_TOKEN", 401);
21
21
  }
22
22
  }
23
- async findById() {
23
+ async findById(overrides) {
24
24
  const token = await this.getAuthToken();
25
25
  const payload = this.decodeJWT(token);
26
26
  const { id_wl, id_account, id_user } = payload;
27
- const { token: wlToken } = await findWhitelabel();
27
+ const wlToken = overrides?.authToken ?? (await findWhitelabel()).token;
28
28
  const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;
29
29
  const response = await fetch(url, {
30
30
  method: "GET",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/users/services/user.service.ts"],"sourcesContent":["\r\nimport { cookies } from 'next/headers';\r\n\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { GetUserDataResponse, JWTPayload, User } from '../schema';\r\nimport { findWhitelabel } from '../../whitelabel/actions/find-whitelabel.action';\r\n\r\nconst AUTH_COOKIE_NAME = 'greatapps';\r\nconst API_BASE_URL = process.env.GAPPS_R3_API_URL || 'https://r3-api.greatapps.dev.br';\r\n\r\nclass UserService {\r\n private async getAuthToken(): Promise<string> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n\r\n if (!token) {\r\n throw new ApiError('Não autenticado', 'NOT_AUTHENTICATED_GAT', 401);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private decodeJWT(token: string): JWTPayload {\r\n try {\r\n return JSON.parse(atob(token.split('.')[1])) as JWTPayload;\r\n } catch {\r\n throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);\r\n }\r\n }\r\n\r\n async findById(): Promise<User> {\r\n const token = await this.getAuthToken();\r\n const payload = this.decodeJWT(token);\r\n\r\n const { id_wl, id_account, id_user } = payload;\r\n const { token: wlToken } = await findWhitelabel();\r\n\r\n const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n authorization: wlToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new ApiError('Erro ao buscar dados do usuário', 'FETCH_ERROR', response.status);\r\n }\r\n\r\n const data = (await response.json()) as GetUserDataResponse;\r\n\r\n if (data.status === 0 || !data.data || data.data.length === 0) {\r\n throw new ApiError('Dados do usuário não encontrados', 'USER_NOT_FOUND', 404);\r\n }\r\n\r\n return data.data[0];\r\n }\r\n}\r\n\r\nexport const userService = new UserService();\r\n"],"mappings":"AACA,SAAS,eAAe;AAExB,SAAS,gBAAgB;AAEzB,SAAS,sBAAsB;AAE/B,MAAM,mBAAmB;AACzB,MAAM,eAAe,QAAQ,IAAI,oBAAoB;AAErD,MAAM,YAAY;AAAA,EAChB,MAAc,eAAgC;AAC5C,QAAI,QAAQ,IAAI,iBAAkB,QAAO,QAAQ,IAAI;AACrD,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,QAAQ,YAAY,IAAI,gBAAgB,GAAG;AAEjD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,SAAS,sBAAmB,yBAAyB,GAAG;AAAA,IACpE;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,OAA2B;AAC3C,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;AAAA,IAC7C,QAAQ;AACN,YAAM,IAAI,SAAS,qBAAkB,iBAAiB,GAAG;AAAA,IAC3D;AAAA,EACF;AAAA,EAEA,MAAM,WAA0B;AAC9B,UAAM,QAAQ,MAAM,KAAK,aAAa;AACtC,UAAM,UAAU,KAAK,UAAU,KAAK;AAEpC,UAAM,EAAE,OAAO,YAAY,QAAQ,IAAI;AACvC,UAAM,EAAE,OAAO,QAAQ,IAAI,MAAM,eAAe;AAEhD,UAAM,MAAM,GAAG,YAAY,aAAa,KAAK,aAAa,UAAU,UAAU,OAAO;AAErF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,SAAS,sCAAmC,eAAe,SAAS,MAAM;AAAA,IACtF;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,QAAI,KAAK,WAAW,KAAK,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW,GAAG;AAC7D,YAAM,IAAI,SAAS,0CAAoC,kBAAkB,GAAG;AAAA,IAC9E;AAEA,WAAO,KAAK,KAAK,CAAC;AAAA,EACpB;AACF;AAEO,MAAM,cAAc,IAAI,YAAY;","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/users/services/user.service.ts"],"sourcesContent":["\r\nimport { cookies } from 'next/headers';\r\n\r\nimport { ApiError } from '../../../infra/api/types';\r\nimport { GetUserDataResponse, JWTPayload, User } from '../schema';\r\nimport { findWhitelabel } from '../../whitelabel/actions/find-whitelabel.action';\r\n\r\nconst AUTH_COOKIE_NAME = 'greatapps';\r\nconst API_BASE_URL = process.env.GAPPS_R3_API_URL || 'https://r3-api.greatapps.dev.br';\r\n\r\nclass UserService {\r\n private async getAuthToken(): Promise<string> {\r\n if (process.env.DUMMY_AUTH_TOKEN) return process.env.DUMMY_AUTH_TOKEN;\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get(AUTH_COOKIE_NAME)?.value;\r\n\r\n if (!token) {\r\n throw new ApiError('Não autenticado', 'NOT_AUTHENTICATED_GAT', 401);\r\n }\r\n\r\n return token;\r\n }\r\n\r\n private decodeJWT(token: string): JWTPayload {\r\n try {\r\n return JSON.parse(atob(token.split('.')[1])) as JWTPayload;\r\n } catch {\r\n throw new ApiError('Token inválido', 'INVALID_TOKEN', 401);\r\n }\r\n }\r\n\r\n async findById(overrides?: { authToken?: string }): Promise<User> {\r\n const token = await this.getAuthToken();\r\n const payload = this.decodeJWT(token);\r\n\r\n const { id_wl, id_account, id_user } = payload;\r\n const wlToken = overrides?.authToken ?? (await findWhitelabel()).token;\r\n\r\n const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;\r\n\r\n const response = await fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n authorization: wlToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n throw new ApiError('Erro ao buscar dados do usuário', 'FETCH_ERROR', response.status);\r\n }\r\n\r\n const data = (await response.json()) as GetUserDataResponse;\r\n\r\n if (data.status === 0 || !data.data || data.data.length === 0) {\r\n throw new ApiError('Dados do usuário não encontrados', 'USER_NOT_FOUND', 404);\r\n }\r\n\r\n return data.data[0];\r\n }\r\n}\r\n\r\nexport const userService = new UserService();\r\n"],"mappings":"AACA,SAAS,eAAe;AAExB,SAAS,gBAAgB;AAEzB,SAAS,sBAAsB;AAE/B,MAAM,mBAAmB;AACzB,MAAM,eAAe,QAAQ,IAAI,oBAAoB;AAErD,MAAM,YAAY;AAAA,EAChB,MAAc,eAAgC;AAC5C,QAAI,QAAQ,IAAI,iBAAkB,QAAO,QAAQ,IAAI;AACrD,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,QAAQ,YAAY,IAAI,gBAAgB,GAAG;AAEjD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,SAAS,sBAAmB,yBAAyB,GAAG;AAAA,IACpE;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,OAA2B;AAC3C,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;AAAA,IAC7C,QAAQ;AACN,YAAM,IAAI,SAAS,qBAAkB,iBAAiB,GAAG;AAAA,IAC3D;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,WAAmD;AAChE,UAAM,QAAQ,MAAM,KAAK,aAAa;AACtC,UAAM,UAAU,KAAK,UAAU,KAAK;AAEpC,UAAM,EAAE,OAAO,YAAY,QAAQ,IAAI;AACvC,UAAM,UAAU,WAAW,cAAc,MAAM,eAAe,GAAG;AAEjE,UAAM,MAAM,GAAG,YAAY,aAAa,KAAK,aAAa,UAAU,UAAU,OAAO;AAErF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,SAAS,sCAAmC,eAAe,SAAS,MAAM;AAAA,IACtF;AAEA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAElC,QAAI,KAAK,WAAW,KAAK,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW,GAAG;AAC7D,YAAM,IAAI,SAAS,0CAAoC,kBAAkB,GAAG;AAAA,IAC9E;AAEA,WAAO,KAAK,KAAK,CAAC;AAAA,EACpB;AACF;AAEO,MAAM,cAAc,IAAI,YAAY;","names":[]}
@@ -79,10 +79,6 @@ class WhitelabelService {
79
79
  const apiUrl = this.getApiUrl();
80
80
  const masterToken = this.getToken();
81
81
  const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;
82
- const response = await fetch(url, {
83
- method: "GET",
84
- headers: { authorization: masterToken }
85
- });
86
82
  console.debug("[WhitelabelService] Fetching token by whitelabel ID", {
87
83
  url,
88
84
  config: {
@@ -90,6 +86,13 @@ class WhitelabelService {
90
86
  headers: { authorization: masterToken }
91
87
  }
92
88
  });
89
+ const response = await fetch(url, {
90
+ method: "GET",
91
+ headers: { authorization: masterToken }
92
+ });
93
+ console.debug("[WhitelabelService] Response received for whitelabel ID", {
94
+ response
95
+ });
93
96
  if (!response.ok) {
94
97
  throw new ApiError(
95
98
  `Failed to fetch whitelabel token: ${response.status}`,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/whitelabel/services/whitelabel.service.ts"],"sourcesContent":["import greatCache from \"@greatapps/cache\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { WhitelabelTokenApiResponse, WhitelabelTokenData } from \"../schema\";\r\nimport { normalizeHostname } from \"../utils/normalize-hostname\";\r\n\r\nclass WhitelabelService {\r\n private getApiUrl(): string {\r\n const apiUrl = process.env.GAPPS_R3_API_URL;\r\n if (!apiUrl) {\r\n throw new ApiError(\r\n \"GAPPS_R3_API_URL not configured\",\r\n \"CONFIG_ERROR\",\r\n 500,\r\n );\r\n }\r\n return apiUrl;\r\n }\r\n\r\n private getToken(): string {\r\n const token = process.env.WHITELABEL_TOKEN_MASTER;\r\n if (!token) {\r\n throw new ApiError(\r\n \"WHITELABEL_TOKEN_MASTER not configured\",\r\n \"CONFIG_ERROR\",\r\n 500,\r\n );\r\n }\r\n return token;\r\n }\r\n\r\n private createCache() {\r\n return new greatCache({\r\n service: \"whitelabel-service\",\r\n version: \"1.0\",\r\n domain: \"whitelabel-cache.greatapps.com.br\",\r\n ambient: process.env.NODE_ENV || \"development\",\r\n });\r\n }\r\n\r\n private getCacheKey(hostname: string): string {\r\n return `whitelabel-token-${hostname}`;\r\n }\r\n\r\n private async fetchFromApi(hostname: string): Promise<WhitelabelTokenData> {\r\n const apiUrl = this.getApiUrl();\r\n const whitelabelMasterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/1/whitelabel/${hostname}/token`;\r\n\r\n console.log(\"[WhitelabelService] Fetching token for domain\", { url });\r\n\r\n const response = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n authorization: whitelabelMasterToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n console.error(\"[WhitelabelService] Failed to fetch whitelabel token\", {\r\n response,\r\n });\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n \"FETCH_ERROR\",\r\n response.status,\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError(\"Whitelabel token not found\", \"TOKEN_NOT_FOUND\", 404);\r\n }\r\n\r\n return result.data[0];\r\n }\r\n\r\n async getTokenByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = `${normalizeHostname(process.env.WHITELABEL_DOMAIN || hostname)}`;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n const cachedData = await cache.select(cacheKey);\r\n\r\n if (cachedData.status == 1 && \"data\" in cachedData && cachedData.data) {\r\n console.log(\"[WhitelabelService] Cache hit for domain\", { hostname });\r\n return JSON.parse(cachedData.data) as WhitelabelTokenData;\r\n }\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n return data;\r\n }\r\n\r\n async getTokenByWhitelabelId(idWl: number): Promise<string> {\r\n const apiUrl = this.getApiUrl();\r\n const masterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;\r\n\r\n const response = await fetch(url, {\r\n method: \"GET\",\r\n headers: { authorization: masterToken },\r\n });\r\n\r\n console.debug(\"[WhitelabelService] Fetching token by whitelabel ID\", {\r\n url,\r\n config: {\r\n method: \"GET\",\r\n headers: { authorization: masterToken },\r\n },\r\n });\r\n\r\n \r\n\r\n if (!response.ok) {\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n \"WL_TOKEN_NOT_FOUND\",\r\n response.status,\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError(\r\n \"Token do whitelabel não encontrado\",\r\n \"WL_TOKEN_NOT_FOUND\",\r\n 404,\r\n );\r\n }\r\n\r\n return result.data[0].token;\r\n }\r\n\r\n async revalidateByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = `${normalizeHostname(process.env.WHITELABEL_DOMAIN || hostname)}`;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n console.log(\"[WhitelabelService] Revalidating cache for domain\", {\r\n hostname,\r\n });\r\n\r\n await cache.delete(cacheKey);\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n console.log(\"[WhitelabelService] Cache revalidated for domain\", {\r\n hostname,\r\n });\r\n\r\n return data;\r\n }\r\n}\r\n\r\nexport const whitelabelService = new WhitelabelService();\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/whitelabel/services/whitelabel.service.ts"],"sourcesContent":["import greatCache from \"@greatapps/cache\";\r\nimport { ApiError } from \"../../../infra/api/types\";\r\nimport { WhitelabelTokenApiResponse, WhitelabelTokenData } from \"../schema\";\r\nimport { normalizeHostname } from \"../utils/normalize-hostname\";\r\n\r\nclass WhitelabelService {\r\n private getApiUrl(): string {\r\n const apiUrl = process.env.GAPPS_R3_API_URL;\r\n if (!apiUrl) {\r\n throw new ApiError(\r\n \"GAPPS_R3_API_URL not configured\",\r\n \"CONFIG_ERROR\",\r\n 500,\r\n );\r\n }\r\n return apiUrl;\r\n }\r\n\r\n private getToken(): string {\r\n const token = process.env.WHITELABEL_TOKEN_MASTER;\r\n if (!token) {\r\n throw new ApiError(\r\n \"WHITELABEL_TOKEN_MASTER not configured\",\r\n \"CONFIG_ERROR\",\r\n 500,\r\n );\r\n }\r\n return token;\r\n }\r\n\r\n private createCache() {\r\n return new greatCache({\r\n service: \"whitelabel-service\",\r\n version: \"1.0\",\r\n domain: \"whitelabel-cache.greatapps.com.br\",\r\n ambient: process.env.NODE_ENV || \"development\",\r\n });\r\n }\r\n\r\n private getCacheKey(hostname: string): string {\r\n return `whitelabel-token-${hostname}`;\r\n }\r\n\r\n private async fetchFromApi(hostname: string): Promise<WhitelabelTokenData> {\r\n const apiUrl = this.getApiUrl();\r\n const whitelabelMasterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/1/whitelabel/${hostname}/token`;\r\n\r\n console.log(\"[WhitelabelService] Fetching token for domain\", { url });\r\n\r\n const response = await fetch(url, {\r\n method: \"GET\",\r\n headers: {\r\n authorization: whitelabelMasterToken,\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n console.error(\"[WhitelabelService] Failed to fetch whitelabel token\", {\r\n response,\r\n });\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n \"FETCH_ERROR\",\r\n response.status,\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError(\"Whitelabel token not found\", \"TOKEN_NOT_FOUND\", 404);\r\n }\r\n\r\n return result.data[0];\r\n }\r\n\r\n async getTokenByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = `${normalizeHostname(process.env.WHITELABEL_DOMAIN || hostname)}`;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n const cachedData = await cache.select(cacheKey);\r\n\r\n if (cachedData.status == 1 && \"data\" in cachedData && cachedData.data) {\r\n console.log(\"[WhitelabelService] Cache hit for domain\", { hostname });\r\n return JSON.parse(cachedData.data) as WhitelabelTokenData;\r\n }\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n return data;\r\n }\r\n\r\n async getTokenByWhitelabelId(idWl: number): Promise<string> {\r\n const apiUrl = this.getApiUrl();\r\n const masterToken = this.getToken();\r\n const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;\r\n console.debug(\"[WhitelabelService] Fetching token by whitelabel ID\", {\r\n url,\r\n config: {\r\n method: \"GET\",\r\n headers: { authorization: masterToken },\r\n },\r\n });\r\n\r\n\r\n const response = await fetch(url, {\r\n method: \"GET\",\r\n headers: { authorization: masterToken },\r\n });\r\n\r\n console.debug(\"[WhitelabelService] Response received for whitelabel ID\", {\r\n response\r\n });\r\n\r\n if (!response.ok) {\r\n throw new ApiError(\r\n `Failed to fetch whitelabel token: ${response.status}`,\r\n \"WL_TOKEN_NOT_FOUND\",\r\n response.status,\r\n );\r\n }\r\n\r\n const result: WhitelabelTokenApiResponse = await response.json();\r\n\r\n if (result.status !== 1 || !result.data?.length) {\r\n throw new ApiError(\r\n \"Token do whitelabel não encontrado\",\r\n \"WL_TOKEN_NOT_FOUND\",\r\n 404,\r\n );\r\n }\r\n\r\n return result.data[0].token;\r\n }\r\n\r\n async revalidateByDomain(hostname: string): Promise<WhitelabelTokenData> {\r\n hostname = `${normalizeHostname(process.env.WHITELABEL_DOMAIN || hostname)}`;\r\n\r\n const cache = this.createCache();\r\n const cacheKey = this.getCacheKey(hostname);\r\n\r\n console.log(\"[WhitelabelService] Revalidating cache for domain\", {\r\n hostname,\r\n });\r\n\r\n await cache.delete(cacheKey);\r\n\r\n const data = await this.fetchFromApi(hostname);\r\n\r\n await cache.insert(cacheKey, JSON.stringify(data), 604800);\r\n\r\n console.log(\"[WhitelabelService] Cache revalidated for domain\", {\r\n hostname,\r\n });\r\n\r\n return data;\r\n }\r\n}\r\n\r\nexport const whitelabelService = new WhitelabelService();\r\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import { create } from "zustand";
2
2
  const useMdSidebarStore = create((set) => ({
3
- isExpanded: false,
3
+ isExpanded: true,
4
4
  toggle: () => set((state) => ({ isExpanded: !state.isExpanded })),
5
5
  expand: () => set({ isExpanded: true }),
6
6
  collapse: () => set({ isExpanded: false })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/store/useMdSidebarStore.ts"],"sourcesContent":["import { create } from \"zustand\";\r\n\r\ntype MdSidebarStore = {\r\n isExpanded: boolean;\r\n toggle: () => void;\r\n expand: () => void;\r\n collapse: () => void;\r\n};\r\n\r\nexport const useMdSidebarStore = create<MdSidebarStore>((set) => ({\r\n isExpanded: false,\r\n toggle: () => set((state) => ({ isExpanded: !state.isExpanded })),\r\n expand: () => set({ isExpanded: true }),\r\n collapse: () => set({ isExpanded: false }),\r\n}));\r\n"],"mappings":"AAAA,SAAS,cAAc;AAShB,MAAM,oBAAoB,OAAuB,CAAC,SAAS;AAAA,EAC9D,YAAY;AAAA,EACZ,QAAQ,MAAM,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,MAAM,WAAW,EAAE;AAAA,EAChE,QAAQ,MAAM,IAAI,EAAE,YAAY,KAAK,CAAC;AAAA,EACtC,UAAU,MAAM,IAAI,EAAE,YAAY,MAAM,CAAC;AAC7C,EAAE;","names":[]}
1
+ {"version":3,"sources":["../../src/store/useMdSidebarStore.ts"],"sourcesContent":["import { create } from \"zustand\";\r\n\r\ntype MdSidebarStore = {\r\n isExpanded: boolean;\r\n toggle: () => void;\r\n expand: () => void;\r\n collapse: () => void;\r\n};\r\n\r\nexport const useMdSidebarStore = create<MdSidebarStore>((set) => ({\r\n isExpanded: true,\r\n toggle: () => set((state) => ({ isExpanded: !state.isExpanded })),\r\n expand: () => set({ isExpanded: true }),\r\n collapse: () => set({ isExpanded: false }),\r\n}));\r\n"],"mappings":"AAAA,SAAS,cAAc;AAShB,MAAM,oBAAoB,OAAuB,CAAC,SAAS;AAAA,EAC9D,YAAY;AAAA,EACZ,QAAQ,MAAM,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,MAAM,WAAW,EAAE;AAAA,EAChE,QAAQ,MAAM,IAAI,EAAE,YAAY,KAAK,CAAC;AAAA,EACtC,UAAU,MAAM,IAAI,EAAE,YAAY,MAAM,CAAC;AAC7C,EAAE;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.281",
3
+ "version": "1.1.283",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -66,7 +66,7 @@ function NavBar({
66
66
  <TooltipTrigger asChild>
67
67
  <button
68
68
  onClick={onExpandClick}
69
- className="lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10"
69
+ className="absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10"
70
70
  >
71
71
  <IconChevronRight size={16} className="text-gray-500" />
72
72
  </button>
@@ -1,24 +1,54 @@
1
1
  'use client';
2
2
 
3
- "use client"
4
-
5
- import * as React from "react"
6
- import { cn } from "../../infra/utils/clsx"
7
-
8
- function SideBarNavigation({
9
- className,
10
- children,
11
- ...props
12
- }: React.ComponentProps<"div">) {
13
- return (
14
- <div
15
- data-slot="sidebar-navigation"
16
- className={cn("hidden lg:flex flex-col h-screen p-4 border-r w-[273px] border-gray-200", className)}
17
- {...props}
18
- >
19
- {children}
20
- </div>
21
- )
22
- }
23
-
24
- export { SideBarNavigation };
3
+ import * as React from "react"
4
+ import { IconChevronLeft } from '@tabler/icons-react'
5
+ import { useMdSidebarStore } from "../../store/useMdSidebarStore"
6
+ import { cn } from "../../infra/utils/clsx"
7
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip"
8
+
9
+ function SideBarNavigation({
10
+ className,
11
+ children,
12
+ ...props
13
+ }: React.ComponentProps<"div">) {
14
+ const { isExpanded, collapse } = useMdSidebarStore()
15
+
16
+ return (
17
+ <div
18
+ data-slot="sidebar-navigation"
19
+ className="hidden lg:block relative overflow-visible shrink-0"
20
+ >
21
+ <div
22
+ className={cn(
23
+ "flex flex-col h-screen border-r border-gray-200 transition-all duration-300 ease-in-out overflow-hidden",
24
+ isExpanded ? "w-[273px] p-4" : "w-0 p-0 border-r-0",
25
+ className
26
+ )}
27
+ {...props}
28
+ >
29
+ <div className={cn(
30
+ "flex flex-col flex-1 min-w-[241px] transition-opacity duration-200",
31
+ isExpanded ? "opacity-100" : "opacity-0 pointer-events-none"
32
+ )}>
33
+ {children}
34
+ </div>
35
+ </div>
36
+
37
+ {isExpanded && (
38
+ <Tooltip>
39
+ <TooltipTrigger asChild>
40
+ <button
41
+ onClick={collapse}
42
+ className="absolute top-[74px] -translate-y-1/2 -right-4 size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-40"
43
+ >
44
+ <IconChevronLeft size={16} className="text-gray-500" />
45
+ </button>
46
+ </TooltipTrigger>
47
+ <TooltipContent side="right">Recolher menu</TooltipContent>
48
+ </Tooltip>
49
+ )}
50
+ </div>
51
+ )
52
+ }
53
+
54
+ export { SideBarNavigation };
@@ -195,23 +195,25 @@ export function UsersSelectorPopover({
195
195
  <span className="truncate">{user.name}</span>
196
196
  </div>
197
197
  <Tooltip open={interactive && hoveredId === user.id}>
198
- <TooltipTrigger
199
- onClick={(e) => e.stopPropagation()}
200
- onPointerDown={(e) => e.stopPropagation()}
201
- >
202
- <Checkbox
203
- checked={inProject}
204
- disabled={!interactive}
205
- onCheckedChange={() =>
206
- toggleUser(user.id, inProject, removable)
207
- }
208
- className={cn(
209
- interactive && hoveredId === user.id
210
- ? "border-gray-950"
211
- : "",
212
- "disabled:opacity-10",
213
- )}
214
- />
198
+ <TooltipTrigger asChild>
199
+ <div
200
+ onClick={(e) => e.stopPropagation()}
201
+ onPointerDown={(e) => e.stopPropagation()}
202
+ >
203
+ <Checkbox
204
+ checked={inProject}
205
+ disabled={!interactive}
206
+ onCheckedChange={() =>
207
+ toggleUser(user.id, inProject, removable)
208
+ }
209
+ className={cn(
210
+ interactive && hoveredId === user.id
211
+ ? "border-gray-950"
212
+ : "",
213
+ "disabled:opacity-10",
214
+ )}
215
+ />
216
+ </div>
215
217
  </TooltipTrigger>
216
218
  <TooltipContent className="z-[1002]">
217
219
  {inProject ? "Remover do projeto" : "Adicionar ao projeto"}
@@ -3,6 +3,7 @@
3
3
  import { ElementType } from 'react';
4
4
  import { useAppNavigationContext } from './AppNavigationContext';
5
5
  import { useMobileNavbarSheet } from '../../store/useMobileNavbarSheet';
6
+ import { useMdSidebarStore } from '../../store/useMdSidebarStore';
6
7
 
7
8
  interface NavItemProps {
8
9
  icon?: ElementType;
@@ -14,11 +15,14 @@ interface NavItemProps {
14
15
  export function NavItem({ icon: Icon, label, onClick, isActive = false }: NavItemProps) {
15
16
  const { breakpoint } = useAppNavigationContext();
16
17
  const { close } = useMobileNavbarSheet();
18
+ const { collapse } = useMdSidebarStore();
17
19
 
18
20
  const handleClick = () => {
19
21
  onClick();
20
22
  if (breakpoint === 'mobile') {
21
23
  close();
24
+ } else if (breakpoint === 'md') {
25
+ collapse();
22
26
  }
23
27
  };
24
28
 
@@ -5,6 +5,7 @@ import { ApiError } from '../../../infra/api/types';
5
5
  import { buildQueryParams } from '../../../infra/utils/params';
6
6
  import { getUserContext } from '../../auth/utils/get-user-context';
7
7
  import { fileToBase64 } from '../../../utils/file/index';
8
+ import type { RequestConfig } from '../../../infra/api/client';
8
9
  import type {
9
10
  Account,
10
11
  AccountUsersPaginationParams,
@@ -24,9 +25,9 @@ import type {
24
25
  } from '../types';
25
26
 
26
27
  class AccountService {
27
- async findCurrentAccount(): Promise<Account> {
28
+ async findCurrentAccount(config?: RequestConfig): Promise<Account> {
28
29
  const { id_account } = await getUserContext();
29
- const response = await api.apps.get<GetAccountDataResponse>(`/accounts/${id_account}`);
30
+ const response = await api.apps.get<GetAccountDataResponse>(`/accounts/${id_account}`, config);
30
31
 
31
32
  if (response.status === 0 || !response.data?.[0]) {
32
33
  throw new ApiError(
@@ -45,15 +45,16 @@ const COOKIE_OPTIONS = {
45
45
  };
46
46
 
47
47
  class AuthService {
48
+
48
49
  async login(
49
50
  credentials: LoginRequest,
50
51
  clientInfo: ClientInfo
51
52
  ): Promise<LoginResponse> {
52
53
  let requestConfig: import("../../../infra/api/client").RequestConfig | undefined;
53
-
54
54
  if (credentials.id_wl) {
55
55
  const wlToken = await whitelabelService.getTokenByWhitelabelId(credentials.id_wl);
56
56
  requestConfig = { whiteLabelId: credentials.id_wl, authToken: wlToken };
57
+
57
58
  }
58
59
 
59
60
  const response = await api.apps.post<LoginApiResponse>("/auth/login", {
@@ -93,8 +94,8 @@ class AuthService {
93
94
  import('../../accounts/services/account.service'),
94
95
  ]);
95
96
  const [user, account] = await Promise.all([
96
- userService.findById(),
97
- accountService.findCurrentAccount(),
97
+ userService.findById(requestConfig ? { authToken: requestConfig.authToken } : undefined),
98
+ accountService.findCurrentAccount(requestConfig),
98
99
  ]);
99
100
 
100
101
  return {
@@ -29,12 +29,12 @@ class UserService {
29
29
  }
30
30
  }
31
31
 
32
- async findById(): Promise<User> {
32
+ async findById(overrides?: { authToken?: string }): Promise<User> {
33
33
  const token = await this.getAuthToken();
34
34
  const payload = this.decodeJWT(token);
35
35
 
36
36
  const { id_wl, id_account, id_user } = payload;
37
- const { token: wlToken } = await findWhitelabel();
37
+ const wlToken = overrides?.authToken ?? (await findWhitelabel()).token;
38
38
 
39
39
  const url = `${API_BASE_URL}/v1/pt-br/${id_wl}/accounts/${id_account}/users/${id_user}`;
40
40
 
@@ -99,12 +99,6 @@ class WhitelabelService {
99
99
  const apiUrl = this.getApiUrl();
100
100
  const masterToken = this.getToken();
101
101
  const url = `${apiUrl}/v1/pt-br/${idWl}/tokens?limit=1&page=1&sort=id:desc`;
102
-
103
- const response = await fetch(url, {
104
- method: "GET",
105
- headers: { authorization: masterToken },
106
- });
107
-
108
102
  console.debug("[WhitelabelService] Fetching token by whitelabel ID", {
109
103
  url,
110
104
  config: {
@@ -113,7 +107,15 @@ class WhitelabelService {
113
107
  },
114
108
  });
115
109
 
116
-
110
+
111
+ const response = await fetch(url, {
112
+ method: "GET",
113
+ headers: { authorization: masterToken },
114
+ });
115
+
116
+ console.debug("[WhitelabelService] Response received for whitelabel ID", {
117
+ response
118
+ });
117
119
 
118
120
  if (!response.ok) {
119
121
  throw new ApiError(
@@ -8,7 +8,7 @@ type MdSidebarStore = {
8
8
  };
9
9
 
10
10
  export const useMdSidebarStore = create<MdSidebarStore>((set) => ({
11
- isExpanded: false,
11
+ isExpanded: true,
12
12
  toggle: () => set((state) => ({ isExpanded: !state.isExpanded })),
13
13
  expand: () => set({ isExpanded: true }),
14
14
  collapse: () => set({ isExpanded: false }),