@greatapps/common 1.1.240 → 1.1.242

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.
@@ -10,8 +10,7 @@ function AppMobileNavBar({
10
10
  onAppIconClick,
11
11
  extraLeftSlot,
12
12
  rightActionSlot,
13
- menuItems = [],
14
- onCreditsClick
13
+ menuItems = []
15
14
  }) {
16
15
  const { openConfigurations } = useAccountModals();
17
16
  const isGpagesActive = activeApp === "gpages";
@@ -86,7 +85,6 @@ function AppMobileNavBar({
86
85
  side: "bottom",
87
86
  align: "end",
88
87
  contentClassName: "",
89
- onCreditsClick,
90
88
  menuItems
91
89
  }
92
90
  ),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/AppMobileNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode } from \"react\";\nimport Image from \"next/image\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { useAccountModals } from \"../../store/useAccountModals\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\n\nexport interface AppMobileNavBarProps {\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n /** Called when the GreatApps logo is clicked */\n onLogoClick?: () => void;\n /** Called when the app icon (e.g. GreatPages) is clicked */\n onAppIconClick?: () => void;\n /** Extra slot rendered after the app icon (e.g. project selector) */\n extraLeftSlot?: ReactNode;\n /** Required: the right-side action element (toggle button, sheet button, etc.) */\n rightActionSlot: ReactNode;\n menuItems?: ProfileMenuItem[];\n onCreditsClick?: () => void;\n}\n\nexport function AppMobileNavBar({\n activeApp,\n onLogoClick,\n onAppIconClick,\n extraLeftSlot,\n rightActionSlot,\n menuItems = [],\n onCreditsClick,\n}: AppMobileNavBarProps) {\n const { openConfigurations } = useAccountModals();\n\n const isGpagesActive = activeApp === \"gpages\";\n const isGappsActive = activeApp === \"gapps\";\n\n return (\n <div className=\"fixed top-0 left-0 right-0 flex md:hidden items-center justify-between p-4 bg-white z-50 border-b border-gray-200\">\n <div className=\"flex items-center gap-1.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <div\n className={`relative size-10 flex items-center justify-center rounded-lg transition-colors ${onLogoClick ? \"cursor-pointer hover:bg-gray-100\" : \"\"}`}\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great\"\n width={28}\n height={28}\n />\n {isGappsActive && (\n <div className=\"absolute bottom-[-17px] left-1/2 -translate-x-1/2 w-5 h-[3px] bg-gray-950 rounded-t-xl\" />\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">Great</TooltipContent>\n </Tooltip>\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild>\n {isGpagesActive ? (\n <div\n 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 onClick={onAppIconClick}\n >\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n ) : (\n <div\n className={`size-10 flex items-center justify-center rounded-lg transition-colors duration-300 bg-gray-100 ${onAppIconClick ? \"cursor-pointer hover:opacity-80\" : \"\"}`}\n onClick={onAppIconClick}\n >\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=\"bottom\">GreatPages</TooltipContent>\n </Tooltip>\n {isGpagesActive && (\n <div className=\"absolute -bottom-[17px] left-1/2 -translate-x-1/2 w-5 h-[3px] bg-cyan-300 rounded-t-xl\" />\n )}\n </div>\n {extraLeftSlot}\n </div>\n <div className=\"flex items-center gap-1.5\">\n <ProfilePopover\n side=\"bottom\"\n align=\"end\"\n contentClassName=\"\"\n onCreditsClick={onCreditsClick}\n menuItems={menuItems}\n />\n {rightActionSlot}\n </div>\n </div>\n );\n}\n"],"mappings":";AA2CY,SAIE,KAJF;AAxCZ,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AAEjC,SAAS,SAAS,gBAAgB,sBAAsB;AAiBjD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AACF,GAAyB;AACvB,QAAM,EAAE,mBAAmB,IAAI,iBAAiB;AAEhD,QAAM,iBAAiB,cAAc;AACrC,QAAM,gBAAgB,cAAc;AAEpC,SACE,qBAAC,SAAI,WAAU,qHACb;AAAA,yBAAC,SAAI,WAAU,6BACb;AAAA,2BAAC,WACC;AAAA,4BAAC,kBAAe,SAAO,MACrB;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,kFAAkF,cAAc,qCAAqC,EAAE;AAAA,YAClJ,SAAS;AAAA,YAET;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA,cACC,iBACC,oBAAC,SAAI,WAAU,0FAAyF;AAAA;AAAA;AAAA,QAE5G,GACF;AAAA,QACA,oBAAC,kBAAe,MAAK,UAAS,mBAAK;AAAA,SACrC;AAAA,MACA,qBAAC,SAAI,WAAU,YACb;AAAA,6BAAC,WACC;AAAA,8BAAC,kBAAe,SAAO,MACpB,2BACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS;AAAA,cAET;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA;AAAA,UACF,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,kGAAkG,iBAAiB,oCAAoC,EAAE;AAAA,cACpK,SAAS;AAAA,cAET;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA;AAAA,UACF,GAEJ;AAAA,UACA,oBAAC,kBAAe,MAAK,UAAS,wBAAU;AAAA,WAC1C;AAAA,QACC,kBACC,oBAAC,SAAI,WAAU,0FAAyF;AAAA,SAE5G;AAAA,MACC;AAAA,OACH;AAAA,IACA,qBAAC,SAAI,WAAU,6BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAM;AAAA,UACN,kBAAiB;AAAA,UACjB;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MACC;AAAA,OACH;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/AppMobileNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode } from \"react\";\nimport Image from \"next/image\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { useAccountModals } from \"../../store/useAccountModals\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\n\nexport interface AppMobileNavBarProps {\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n /** Called when the GreatApps logo is clicked */\n onLogoClick?: () => void;\n /** Called when the app icon (e.g. GreatPages) is clicked */\n onAppIconClick?: () => void;\n /** Extra slot rendered after the app icon (e.g. project selector) */\n extraLeftSlot?: ReactNode;\n /** Required: the right-side action element (toggle button, sheet button, etc.) */\n rightActionSlot: ReactNode;\n menuItems?: ProfileMenuItem[];\n}\n\nexport function AppMobileNavBar({\n activeApp,\n onLogoClick,\n onAppIconClick,\n extraLeftSlot,\n rightActionSlot,\n menuItems = [],\n}: AppMobileNavBarProps) {\n const { openConfigurations } = useAccountModals();\n\n const isGpagesActive = activeApp === \"gpages\";\n const isGappsActive = activeApp === \"gapps\";\n\n return (\n <div className=\"fixed top-0 left-0 right-0 flex md:hidden items-center justify-between p-4 bg-white z-50 border-b border-gray-200\">\n <div className=\"flex items-center gap-1.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <div\n className={`relative size-10 flex items-center justify-center rounded-lg transition-colors ${onLogoClick ? \"cursor-pointer hover:bg-gray-100\" : \"\"}`}\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great\"\n width={28}\n height={28}\n />\n {isGappsActive && (\n <div className=\"absolute bottom-[-17px] left-1/2 -translate-x-1/2 w-5 h-[3px] bg-gray-950 rounded-t-xl\" />\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">Great</TooltipContent>\n </Tooltip>\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild>\n {isGpagesActive ? (\n <div\n 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 onClick={onAppIconClick}\n >\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n ) : (\n <div\n className={`size-10 flex items-center justify-center rounded-lg transition-colors duration-300 bg-gray-100 ${onAppIconClick ? \"cursor-pointer hover:opacity-80\" : \"\"}`}\n onClick={onAppIconClick}\n >\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=\"bottom\">GreatPages</TooltipContent>\n </Tooltip>\n {isGpagesActive && (\n <div className=\"absolute -bottom-[17px] left-1/2 -translate-x-1/2 w-5 h-[3px] bg-cyan-300 rounded-t-xl\" />\n )}\n </div>\n {extraLeftSlot}\n </div>\n <div className=\"flex items-center gap-1.5\">\n <ProfilePopover\n side=\"bottom\"\n align=\"end\"\n contentClassName=\"\"\n menuItems={menuItems}\n />\n {rightActionSlot}\n </div>\n </div>\n );\n}\n"],"mappings":";AAyCY,SAIE,KAJF;AAtCZ,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AAEjC,SAAS,SAAS,gBAAgB,sBAAsB;AAgBjD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,CAAC;AACf,GAAyB;AACvB,QAAM,EAAE,mBAAmB,IAAI,iBAAiB;AAEhD,QAAM,iBAAiB,cAAc;AACrC,QAAM,gBAAgB,cAAc;AAEpC,SACE,qBAAC,SAAI,WAAU,qHACb;AAAA,yBAAC,SAAI,WAAU,6BACb;AAAA,2BAAC,WACC;AAAA,4BAAC,kBAAe,SAAO,MACrB;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,kFAAkF,cAAc,qCAAqC,EAAE;AAAA,YAClJ,SAAS;AAAA,YAET;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA,cACC,iBACC,oBAAC,SAAI,WAAU,0FAAyF;AAAA;AAAA;AAAA,QAE5G,GACF;AAAA,QACA,oBAAC,kBAAe,MAAK,UAAS,mBAAK;AAAA,SACrC;AAAA,MACA,qBAAC,SAAI,WAAU,YACb;AAAA,6BAAC,WACC;AAAA,8BAAC,kBAAe,SAAO,MACpB,2BACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS;AAAA,cAET;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA;AAAA,UACF,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,kGAAkG,iBAAiB,oCAAoC,EAAE;AAAA,cACpK,SAAS;AAAA,cAET;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA;AAAA,UACF,GAEJ;AAAA,UACA,oBAAC,kBAAe,MAAK,UAAS,wBAAU;AAAA,WAC1C;AAAA,QACC,kBACC,oBAAC,SAAI,WAAU,0FAAyF;AAAA,SAE5G;AAAA,MACC;AAAA,OACH;AAAA,IACA,qBAAC,SAAI,WAAU,6BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAM;AAAA,UACN,kBAAiB;AAAA,UACjB;AAAA;AAAA,MACF;AAAA,MACC;AAAA,OACH;AAAA,KACF;AAEJ;","names":[]}
@@ -4,7 +4,6 @@ import { useRouter } from "next/navigation";
4
4
  import { NavBar } from "./NavBar";
5
5
  import { ProfilePopover } from "./ProfilePopover";
6
6
  import { NotificationsPopover } from "./NotificationsPopover";
7
- import { useAccountModals } from "../../store/useAccountModals";
8
7
  function AppNavBar({
9
8
  onLogoClick,
10
9
  activeApp,
@@ -12,12 +11,10 @@ function AppNavBar({
12
11
  showExpandButton = false,
13
12
  onExpandClick,
14
13
  menuItems = [],
15
- onCreditsClick,
16
14
  onNotificationsViewAll,
17
15
  logoutRedirect
18
16
  }) {
19
17
  const router = useRouter();
20
- const { openConfigurations } = useAccountModals();
21
18
  const handleLogoClick = onLogoClick ?? (() => router.push("/"));
22
19
  const handleAppIconClick = () => router.push(appIconHref);
23
20
  return /* @__PURE__ */ jsxs(
@@ -33,8 +30,6 @@ function AppNavBar({
33
30
  /* @__PURE__ */ jsx(
34
31
  ProfilePopover,
35
32
  {
36
- onEditProfile: () => openConfigurations(),
37
- onCreditsClick,
38
33
  menuItems,
39
34
  logoutRedirect
40
35
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/AppNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { NavBar } from \"./NavBar\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { NotificationsPopover } from \"./NotificationsPopover\";\nimport { useAccountModals } from \"../../store/useAccountModals\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\n\nexport interface AppNavBarProps {\n onLogoClick?: () => void;\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n appIconHref?: string;\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n menuItems?: ProfileMenuItem[];\n onCreditsClick?: () => void;\n onNotificationsViewAll?: () => void;\n logoutRedirect?: string;\n}\n\nexport function AppNavBar({\n onLogoClick,\n activeApp,\n appIconHref = \"/\",\n showExpandButton = false,\n onExpandClick,\n menuItems = [],\n onCreditsClick,\n onNotificationsViewAll,\n logoutRedirect,\n}: AppNavBarProps) {\n const router = useRouter();\n const { openConfigurations } = useAccountModals();\n\n const handleLogoClick = onLogoClick ?? (() => router.push(\"/\"));\n const handleAppIconClick = () => router.push(appIconHref);\n\n return (\n <NavBar\n onLogoClick={handleLogoClick}\n onAppIconClick={handleAppIconClick}\n activeApp={activeApp}\n showExpandButton={showExpandButton}\n onExpandClick={onExpandClick}\n >\n <NotificationsPopover onViewAll={onNotificationsViewAll} />\n <ProfilePopover\n onEditProfile={() => openConfigurations()}\n onCreditsClick={onCreditsClick}\n menuItems={menuItems}\n logoutRedirect={logoutRedirect}\n />\n </NavBar>\n );\n}\n"],"mappings":";AAwCI,SAOE,KAPF;AAtCJ,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AAgB1B,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,SAAS,UAAU;AACzB,QAAM,EAAE,mBAAmB,IAAI,iBAAiB;AAEhD,QAAM,kBAAkB,gBAAgB,MAAM,OAAO,KAAK,GAAG;AAC7D,QAAM,qBAAqB,MAAM,OAAO,KAAK,WAAW;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,4BAAC,wBAAqB,WAAW,wBAAwB;AAAA,QACzD;AAAA,UAAC;AAAA;AAAA,YACC,eAAe,MAAM,mBAAmB;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/AppNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRouter } from \"next/navigation\";\nimport { NavBar } from \"./NavBar\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { NotificationsPopover } from \"./NotificationsPopover\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\n\nexport interface AppNavBarProps {\n onLogoClick?: () => void;\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n appIconHref?: string;\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n menuItems?: ProfileMenuItem[];\n onNotificationsViewAll?: () => void;\n logoutRedirect?: string;\n}\n\nexport function AppNavBar({\n onLogoClick,\n activeApp,\n appIconHref = \"/\",\n showExpandButton = false,\n onExpandClick,\n menuItems = [],\n onNotificationsViewAll,\n logoutRedirect,\n}: AppNavBarProps) {\n const router = useRouter();\n\n const handleLogoClick = onLogoClick ?? (() => router.push(\"/\"));\n const handleAppIconClick = () => router.push(appIconHref);\n\n return (\n <NavBar\n onLogoClick={handleLogoClick}\n onAppIconClick={handleAppIconClick}\n activeApp={activeApp}\n showExpandButton={showExpandButton}\n onExpandClick={onExpandClick}\n >\n <NotificationsPopover onViewAll={onNotificationsViewAll} />\n <ProfilePopover\n menuItems={menuItems}\n logoutRedirect={logoutRedirect}\n />\n </NavBar>\n );\n}\n"],"mappings":";AAoCI,SAOE,KAPF;AAlCJ,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AAe9B,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,SAAS,UAAU;AAEzB,QAAM,kBAAkB,gBAAgB,MAAM,OAAO,KAAK,GAAG;AAC7D,QAAM,qBAAqB,MAAM,OAAO,KAAK,WAAW;AAExD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,4BAAC,wBAAqB,WAAW,wBAAwB;AAAA,QACzD;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -12,12 +12,11 @@ import { LoadingOverlay } from "../ui/feedback/LoadingOverlay";
12
12
  import { useAuth } from "../../providers/auth.provider";
13
13
  import { cn } from "../../infra/utils/clsx";
14
14
  import { useIaCredits } from "../../modules/ia-credits/hooks/ia-credits.hook";
15
+ import { useBuyCreditsModal } from "../../store/useBuyCreditsModal";
15
16
  function ProfilePopover({
16
17
  side = "top",
17
18
  align = "start",
18
19
  contentClassName = "absolute bottom-2 left-[26px]",
19
- onEditProfile,
20
- onCreditsClick,
21
20
  menuItems = [],
22
21
  logoutRedirect = "/login"
23
22
  }) {
@@ -25,6 +24,7 @@ function ProfilePopover({
25
24
  const { user, logout } = useAuth();
26
25
  const [isLoggingOut, setIsLoggingOut] = useState(false);
27
26
  const { summary, subscription, isSubscriptionLoading, isCreditsLoading } = useIaCredits();
27
+ const { openModal: openBuyCreditsModal } = useBuyCreditsModal();
28
28
  const handleLogout = async () => {
29
29
  try {
30
30
  setIsLoggingOut(true);
@@ -89,9 +89,9 @@ function ProfilePopover({
89
89
  {
90
90
  className: cn(
91
91
  "flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors",
92
- onCreditsClick && "cursor-pointer hover:bg-gray-900"
92
+ "cursor-pointer hover:bg-gray-900"
93
93
  ),
94
- onClick: onCreditsClick,
94
+ onClick: () => openBuyCreditsModal(),
95
95
  children: [
96
96
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
97
97
  /* @__PURE__ */ jsx("span", { className: "paragraph-xsmall-semibold text-white truncate", children: "Cr\xE9ditos usados" }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Popover } from \"../ui/overlay/Popover\";\nimport { Progress } from \"../ui/feedback/Progress\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { IconSettings } from \"@tabler/icons-react\";\nimport { NavBarItem } from \"./NavBarItem\";\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { LoadingOverlay } from \"../ui/feedback/LoadingOverlay\";\nimport { useAuth } from \"../../providers/auth.provider\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\n\nexport interface ProfileMenuItem {\n icon?: React.ReactNode;\n label: string;\n onClick: () => void;\n}\n\nexport interface ProfilePopoverProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n onEditProfile?: () => void;\n onCreditsClick?: () => void;\n menuItems?: ProfileMenuItem[];\n logoutRedirect?: string;\n}\n\nfunction ProfilePopover({\n side = \"top\",\n align = \"start\",\n contentClassName = \"absolute bottom-2 left-[26px]\",\n onEditProfile,\n onCreditsClick,\n menuItems = [],\n logoutRedirect = \"/login\",\n}: ProfilePopoverProps) {\n const router = useRouter();\n const { user, logout } = useAuth();\n const [isLoggingOut, setIsLoggingOut] = useState(false);\n\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\n useIaCredits();\n\n const handleLogout = async () => {\n try {\n setIsLoggingOut(true);\n await logout();\n } finally {\n setIsLoggingOut(false);\n if (logoutRedirect !== \"/login\") {\n router.push(logoutRedirect);\n }\n }\n };\n\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\n\n const shouldShowCredits = hasSubscription && subscription.id_wl === 1;\n const creditsPercentage =\n shouldShowCredits && summary.totalCredits > 0\n ? (summary.usedCredits / summary.totalCredits) * 100\n : 0;\n\n return (\n <>\n <LoadingOverlay\n isLoading={isLoggingOut}\n message=\"Saindo da sua conta...\"\n />\n <Popover>\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={40}\n />\n )}\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n className={cn(\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"grid grid-cols-[32px_1fr] items-center gap-3 p-3 w-full\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={32}\n />\n )}\n\n <div className=\"flex flex-col gap-0.5 min-w-0\">\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\n {user?.name || \"\"}\n </span>\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\n {user?.email || \"\"}\n </span>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\n {shouldShowCredits && (\n <div\n className={cn(\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\n onCreditsClick && \"cursor-pointer hover:bg-gray-900\",\n )}\n onClick={onCreditsClick}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\n Créditos usados\n </span>\n <span className=\"paragraph-xsmall-medium text-white/50\">\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\n </span>\n </div>\n <Progress\n className=\"bg-white/10\"\n indicatorColor=\"bg-white\"\n value={creditsPercentage}\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-2\">\n {menuItems.length > 0 && (\n <div className=\"flex flex-col\">\n {menuItems.map((item, index) => (\n <NavBarItem\n key={index}\n icon={item.icon}\n label={item.label}\n onClick={item.onClick}\n />\n ))}\n </div>\n )}\n <Separator />\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </Popover>\n </>\n );\n}\n\nexport { ProfilePopover };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Popover } from \"../ui/overlay/Popover\";\nimport { Progress } from \"../ui/feedback/Progress\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { NavBarItem } from \"./NavBarItem\";\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { LoadingOverlay } from \"../ui/feedback/LoadingOverlay\";\nimport { useAuth } from \"../../providers/auth.provider\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\nimport { useBuyCreditsModal } from \"../../store/useBuyCreditsModal\";\n\nexport interface ProfileMenuItem {\n icon?: React.ReactNode;\n label: string;\n onClick: () => void;\n}\n\nexport interface ProfilePopoverProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n menuItems?: ProfileMenuItem[];\n logoutRedirect?: string;\n}\n\nfunction ProfilePopover({\n side = \"top\",\n align = \"start\",\n contentClassName = \"absolute bottom-2 left-[26px]\",\n menuItems = [],\n logoutRedirect = \"/login\",\n}: ProfilePopoverProps) {\n const router = useRouter();\n const { user, logout } = useAuth();\n const [isLoggingOut, setIsLoggingOut] = useState(false);\n\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\n useIaCredits();\n const { openModal: openBuyCreditsModal } = useBuyCreditsModal();\n\n const handleLogout = async () => {\n try {\n setIsLoggingOut(true);\n await logout();\n } finally {\n setIsLoggingOut(false);\n if (logoutRedirect !== \"/login\") {\n router.push(logoutRedirect);\n }\n }\n };\n\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\n\n const shouldShowCredits = hasSubscription && subscription.id_wl === 1;\n const creditsPercentage =\n shouldShowCredits && summary.totalCredits > 0\n ? (summary.usedCredits / summary.totalCredits) * 100\n : 0;\n\n return (\n <>\n <LoadingOverlay\n isLoading={isLoggingOut}\n message=\"Saindo da sua conta...\"\n />\n <Popover>\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={40}\n />\n )}\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n className={cn(\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"grid grid-cols-[32px_1fr] items-center gap-3 p-3 w-full\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={32}\n />\n )}\n\n <div className=\"flex flex-col gap-0.5 min-w-0\">\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\n {user?.name || \"\"}\n </span>\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\n {user?.email || \"\"}\n </span>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\n {shouldShowCredits && (\n <div\n className={cn(\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\n \"cursor-pointer hover:bg-gray-900\",\n )}\n onClick={() => openBuyCreditsModal()}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\n Créditos usados\n </span>\n <span className=\"paragraph-xsmall-medium text-white/50\">\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\n </span>\n </div>\n <Progress\n className=\"bg-white/10\"\n indicatorColor=\"bg-white\"\n value={creditsPercentage}\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-2\">\n {menuItems.length > 0 && (\n <div className=\"flex flex-col\">\n {menuItems.map((item, index) => (\n <NavBarItem\n key={index}\n icon={item.icon}\n label={item.label}\n onClick={item.onClick}\n />\n ))}\n </div>\n )}\n <Separator />\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </Popover>\n </>\n );\n}\n\nexport { ProfilePopover };\n"],"mappings":"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","names":[]}
@@ -1,16 +1,22 @@
1
1
  import "server-only";
2
2
  import { api } from "../../../infra/api/client";
3
- import { ApiError } from "../../../infra/api/types";
3
+ import {
4
+ ApiError
5
+ } from "../../../infra/api/types";
4
6
  import { buildQueryParams } from "../../../infra/utils/params";
5
7
  import { getUserContext } from "../../auth/utils/get-user-context";
6
- import { SubscriptionSchema } from "../types";
8
+ import {
9
+ SubscriptionSchema
10
+ } from "../types";
7
11
  import {
8
12
  CalculateSubscriptionResponseSchema
9
13
  } from "../types/calculate-subscription.type";
10
14
  class SubscriptionsService {
11
15
  async listSubscriptions(params) {
12
16
  const { id_account } = await getUserContext();
13
- const query = buildQueryParams(params);
17
+ const query = buildQueryParams(
18
+ params
19
+ );
14
20
  const url = `/accounts/${id_account}/subscriptions${query ? `?${query}` : ""}`;
15
21
  const response = await api.apps.get(url);
16
22
  if (response.status === 0) {
@@ -29,10 +35,8 @@ class SubscriptionsService {
29
35
  }
30
36
  async calculateSubscription(data) {
31
37
  const { id_account } = await getUserContext();
32
- const response = await api.apps.post(
33
- `/accounts/${id_account}/subscriptions/action/calculate`,
34
- data
35
- );
38
+ const response = await api.apps.post(`/accounts/${id_account}/subscriptions/action/calculate`, data);
39
+ console.log("Calculate subscription response:", { response, data });
36
40
  if (response.status === 0) {
37
41
  throw new ApiError(
38
42
  response.message || "Erro ao calcular assinatura",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/subscriptions/services/subscriptions.service.ts"],"sourcesContent":["import 'server-only';\r\n\r\nimport { api } from '../../../infra/api/client';\r\nimport { ApiError, ApiActionResult, ApiPaginatedActionResult, PaginatedSuccessResult, SuccessResult } from '../../../infra/api/types';\r\nimport { buildQueryParams } from '../../../infra/utils/params';\r\nimport { getUserContext } from '../../auth/utils/get-user-context';\r\nimport { Subscription, SubscriptionSchema, FindSubscriptionsParams } from '../types';\r\nimport {\r\n type CalculateSubscriptionRequest,\r\n type CalculateSubscriptionResponse,\r\n type UpdateSubscriptionPlanRequest,\r\n CalculateSubscriptionResponseSchema,\r\n} from '../types/calculate-subscription.type';\r\n\r\nclass SubscriptionsService {\r\n async listSubscriptions(\r\n params?: Partial<FindSubscriptionsParams>\r\n ): Promise<PaginatedSuccessResult<Subscription>> {\r\n const { id_account } = await getUserContext();\r\n\r\n const query = buildQueryParams(params as Record<string, string | boolean | undefined>);\r\n const url = `/accounts/${id_account}/subscriptions${query ? `?${query}` : ''}`;\r\n\r\n const response = await api.apps.get<ApiPaginatedActionResult<Subscription>>(url);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao listar assinaturas',\r\n 'LIST_SUBSCRIPTIONS_FAILED',\r\n 400\r\n );\r\n }\r\n\r\n const data = response.data.map((item) => SubscriptionSchema.parse(item));\r\n\r\n return {\r\n data,\r\n total: response.total,\r\n success: true,\r\n } satisfies PaginatedSuccessResult<Subscription>;\r\n }\r\n async calculateSubscription(\r\n data: CalculateSubscriptionRequest\r\n ): Promise<SuccessResult<CalculateSubscriptionResponse>> {\r\n const { id_account } = await getUserContext();\r\n\r\n const response = await api.apps.post<ApiActionResult<CalculateSubscriptionResponse>>(\r\n `/accounts/${id_account}/subscriptions/action/calculate`,\r\n data\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao calcular assinatura',\r\n 'CALCULATE_SUBSCRIPTION_FAILED',\r\n 400\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n data: CalculateSubscriptionResponseSchema.parse(response.data),\r\n };\r\n }\r\n\r\n async updateSubscriptionPlan(\r\n subscriptionId: number | string,\r\n data: UpdateSubscriptionPlanRequest\r\n ): Promise<SuccessResult<void>> {\r\n const { id_account } = await getUserContext();\r\n\r\n const response = await api.apps.put<ApiActionResult<void>>(\r\n `/accounts/${id_account}/subscriptions/${subscriptionId}/action/plan`,\r\n data\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || 'Erro ao atualizar plano',\r\n 'UPDATE_SUBSCRIPTION_PLAN_FAILED',\r\n 400\r\n );\r\n }\r\n\r\n return { success: true };\r\n }\r\n}\r\n\r\nexport const subscriptionsService = new SubscriptionsService();\r\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,WAAW;AACpB,SAAS,gBAAkG;AAC3G,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAC/B,SAAuB,0BAAmD;AAC1E;AAAA,EAIE;AAAA,OACK;AAEP,MAAM,qBAAqB;AAAA,EACzB,MAAM,kBACJ,QAC+C;AAC/C,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAE5C,UAAM,QAAQ,iBAAiB,MAAsD;AACrF,UAAM,MAAM,aAAa,UAAU,iBAAiB,QAAQ,IAAI,KAAK,KAAK,EAAE;AAE5E,UAAM,WAAW,MAAM,IAAI,KAAK,IAA4C,GAAG;AAE/E,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,SAAS,KAAK,IAAI,CAAC,SAAS,mBAAmB,MAAM,IAAI,CAAC;AAEvE,WAAO;AAAA,MACL;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,sBACJ,MACuD;AACvD,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAE5C,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B,aAAa,UAAU;AAAA,MACvB;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM,oCAAoC,MAAM,SAAS,IAAI;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,MAAM,uBACJ,gBACA,MAC8B;AAC9B,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAE5C,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B,aAAa,UAAU,kBAAkB,cAAc;AAAA,MACvD;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AACF;AAEO,MAAM,uBAAuB,IAAI,qBAAqB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/subscriptions/services/subscriptions.service.ts"],"sourcesContent":["import \"server-only\";\r\n\r\nimport { api } from \"../../../infra/api/client\";\r\nimport {\r\n ApiError,\r\n ApiActionResult,\r\n ApiPaginatedActionResult,\r\n PaginatedSuccessResult,\r\n SuccessResult,\r\n} from \"../../../infra/api/types\";\r\nimport { buildQueryParams } from \"../../../infra/utils/params\";\r\nimport { getUserContext } from \"../../auth/utils/get-user-context\";\r\nimport {\r\n Subscription,\r\n SubscriptionSchema,\r\n FindSubscriptionsParams,\r\n} from \"../types\";\r\nimport {\r\n type CalculateSubscriptionRequest,\r\n type CalculateSubscriptionResponse,\r\n type UpdateSubscriptionPlanRequest,\r\n CalculateSubscriptionResponseSchema,\r\n} from \"../types/calculate-subscription.type\";\r\n\r\nclass SubscriptionsService {\r\n async listSubscriptions(\r\n params?: Partial<FindSubscriptionsParams>,\r\n ): Promise<PaginatedSuccessResult<Subscription>> {\r\n const { id_account } = await getUserContext();\r\n\r\n const query = buildQueryParams(\r\n params as Record<string, string | boolean | undefined>,\r\n );\r\n const url = `/accounts/${id_account}/subscriptions${query ? `?${query}` : \"\"}`;\r\n\r\n const response =\r\n await api.apps.get<ApiPaginatedActionResult<Subscription>>(url);\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao listar assinaturas\",\r\n \"LIST_SUBSCRIPTIONS_FAILED\",\r\n 400,\r\n );\r\n }\r\n\r\n const data = response.data.map((item) => SubscriptionSchema.parse(item));\r\n\r\n return {\r\n data,\r\n total: response.total,\r\n success: true,\r\n } satisfies PaginatedSuccessResult<Subscription>;\r\n }\r\n\r\n async calculateSubscription(\r\n data: CalculateSubscriptionRequest,\r\n ): Promise<SuccessResult<CalculateSubscriptionResponse>> {\r\n const { id_account } = await getUserContext();\r\n\r\n const response = await api.apps.post<\r\n ApiActionResult<CalculateSubscriptionResponse>\r\n >(`/accounts/${id_account}/subscriptions/action/calculate`, data);\r\n\r\n console.log(\"Calculate subscription response:\", { response, data });\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao calcular assinatura\",\r\n \"CALCULATE_SUBSCRIPTION_FAILED\",\r\n 400,\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n data: CalculateSubscriptionResponseSchema.parse(response.data),\r\n };\r\n }\r\n\r\n async updateSubscriptionPlan(\r\n subscriptionId: number | string,\r\n data: UpdateSubscriptionPlanRequest,\r\n ): Promise<SuccessResult<void>> {\r\n const { id_account } = await getUserContext();\r\n\r\n const response = await api.apps.put<ApiActionResult<void>>(\r\n `/accounts/${id_account}/subscriptions/${subscriptionId}/action/plan`,\r\n data,\r\n );\r\n\r\n if (response.status === 0) {\r\n throw new ApiError(\r\n response.message || \"Erro ao atualizar plano\",\r\n \"UPDATE_SUBSCRIPTION_PLAN_FAILED\",\r\n 400,\r\n );\r\n }\r\n\r\n return { success: true };\r\n }\r\n}\r\n\r\nexport const subscriptionsService = new SubscriptionsService();\r\n"],"mappings":"AAAA,OAAO;AAEP,SAAS,WAAW;AACpB;AAAA,EACE;AAAA,OAKK;AACP,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAC/B;AAAA,EAEE;AAAA,OAEK;AACP;AAAA,EAIE;AAAA,OACK;AAEP,MAAM,qBAAqB;AAAA,EACzB,MAAM,kBACJ,QAC+C;AAC/C,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAE5C,UAAM,QAAQ;AAAA,MACZ;AAAA,IACF;AACA,UAAM,MAAM,aAAa,UAAU,iBAAiB,QAAQ,IAAI,KAAK,KAAK,EAAE;AAE5E,UAAM,WACJ,MAAM,IAAI,KAAK,IAA4C,GAAG;AAEhE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,SAAS,KAAK,IAAI,CAAC,SAAS,mBAAmB,MAAM,IAAI,CAAC;AAEvE,WAAO;AAAA,MACL;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,sBACJ,MACuD;AACvD,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAE5C,UAAM,WAAW,MAAM,IAAI,KAAK,KAE9B,aAAa,UAAU,mCAAmC,IAAI;AAEhE,YAAQ,IAAI,oCAAoC,EAAE,UAAU,KAAK,CAAC;AAElE,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM,oCAAoC,MAAM,SAAS,IAAI;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,MAAM,uBACJ,gBACA,MAC8B;AAC9B,UAAM,EAAE,WAAW,IAAI,MAAM,eAAe;AAE5C,UAAM,WAAW,MAAM,IAAI,KAAK;AAAA,MAC9B,aAAa,UAAU,kBAAkB,cAAc;AAAA,MACvD;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,SAAS,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AACF;AAEO,MAAM,uBAAuB,IAAI,qBAAqB;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.240",
3
+ "version": "1.1.242",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -19,7 +19,6 @@ export interface AppMobileNavBarProps {
19
19
  /** Required: the right-side action element (toggle button, sheet button, etc.) */
20
20
  rightActionSlot: ReactNode;
21
21
  menuItems?: ProfileMenuItem[];
22
- onCreditsClick?: () => void;
23
22
  }
24
23
 
25
24
  export function AppMobileNavBar({
@@ -29,7 +28,6 @@ export function AppMobileNavBar({
29
28
  extraLeftSlot,
30
29
  rightActionSlot,
31
30
  menuItems = [],
32
- onCreditsClick,
33
31
  }: AppMobileNavBarProps) {
34
32
  const { openConfigurations } = useAccountModals();
35
33
 
@@ -100,7 +98,6 @@ export function AppMobileNavBar({
100
98
  side="bottom"
101
99
  align="end"
102
100
  contentClassName=""
103
- onCreditsClick={onCreditsClick}
104
101
  menuItems={menuItems}
105
102
  />
106
103
  {rightActionSlot}
@@ -4,7 +4,6 @@ import { useRouter } from "next/navigation";
4
4
  import { NavBar } from "./NavBar";
5
5
  import { ProfilePopover } from "./ProfilePopover";
6
6
  import { NotificationsPopover } from "./NotificationsPopover";
7
- import { useAccountModals } from "../../store/useAccountModals";
8
7
  import type { ProfileMenuItem } from "./ProfilePopover";
9
8
 
10
9
  export interface AppNavBarProps {
@@ -15,7 +14,6 @@ export interface AppNavBarProps {
15
14
  showExpandButton?: boolean;
16
15
  onExpandClick?: () => void;
17
16
  menuItems?: ProfileMenuItem[];
18
- onCreditsClick?: () => void;
19
17
  onNotificationsViewAll?: () => void;
20
18
  logoutRedirect?: string;
21
19
  }
@@ -27,12 +25,10 @@ export function AppNavBar({
27
25
  showExpandButton = false,
28
26
  onExpandClick,
29
27
  menuItems = [],
30
- onCreditsClick,
31
28
  onNotificationsViewAll,
32
29
  logoutRedirect,
33
30
  }: AppNavBarProps) {
34
31
  const router = useRouter();
35
- const { openConfigurations } = useAccountModals();
36
32
 
37
33
  const handleLogoClick = onLogoClick ?? (() => router.push("/"));
38
34
  const handleAppIconClick = () => router.push(appIconHref);
@@ -47,8 +43,6 @@ export function AppNavBar({
47
43
  >
48
44
  <NotificationsPopover onViewAll={onNotificationsViewAll} />
49
45
  <ProfilePopover
50
- onEditProfile={() => openConfigurations()}
51
- onCreditsClick={onCreditsClick}
52
46
  menuItems={menuItems}
53
47
  logoutRedirect={logoutRedirect}
54
48
  />
@@ -6,13 +6,13 @@ import * as PopoverPrimitive from "@radix-ui/react-popover";
6
6
  import { Popover } from "../ui/overlay/Popover";
7
7
  import { Progress } from "../ui/feedback/Progress";
8
8
  import { Separator } from "../ui/data-display/Separator";
9
- import { IconSettings } from "@tabler/icons-react";
10
9
  import { NavBarItem } from "./NavBarItem";
11
10
  import { UserAvatar } from "../ui/data-display/UserAvatar";
12
11
  import { LoadingOverlay } from "../ui/feedback/LoadingOverlay";
13
12
  import { useAuth } from "../../providers/auth.provider";
14
13
  import { cn } from "../../infra/utils/clsx";
15
14
  import { useIaCredits } from "../../modules/ia-credits/hooks/ia-credits.hook";
15
+ import { useBuyCreditsModal } from "../../store/useBuyCreditsModal";
16
16
 
17
17
  export interface ProfileMenuItem {
18
18
  icon?: React.ReactNode;
@@ -24,8 +24,6 @@ export interface ProfilePopoverProps {
24
24
  side?: "top" | "bottom" | "left" | "right";
25
25
  align?: "start" | "center" | "end";
26
26
  contentClassName?: string;
27
- onEditProfile?: () => void;
28
- onCreditsClick?: () => void;
29
27
  menuItems?: ProfileMenuItem[];
30
28
  logoutRedirect?: string;
31
29
  }
@@ -34,8 +32,6 @@ function ProfilePopover({
34
32
  side = "top",
35
33
  align = "start",
36
34
  contentClassName = "absolute bottom-2 left-[26px]",
37
- onEditProfile,
38
- onCreditsClick,
39
35
  menuItems = [],
40
36
  logoutRedirect = "/login",
41
37
  }: ProfilePopoverProps) {
@@ -45,6 +41,7 @@ function ProfilePopover({
45
41
 
46
42
  const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =
47
43
  useIaCredits();
44
+ const { openModal: openBuyCreditsModal } = useBuyCreditsModal();
48
45
 
49
46
  const handleLogout = async () => {
50
47
  try {
@@ -119,9 +116,9 @@ function ProfilePopover({
119
116
  <div
120
117
  className={cn(
121
118
  "flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors",
122
- onCreditsClick && "cursor-pointer hover:bg-gray-900",
119
+ "cursor-pointer hover:bg-gray-900",
123
120
  )}
124
- onClick={onCreditsClick}
121
+ onClick={() => openBuyCreditsModal()}
125
122
  >
126
123
  <div className="flex items-center justify-between gap-2">
127
124
  <span className="paragraph-xsmall-semibold text-white truncate">
@@ -1,33 +1,46 @@
1
- import 'server-only';
1
+ import "server-only";
2
2
 
3
- import { api } from '../../../infra/api/client';
4
- import { ApiError, ApiActionResult, ApiPaginatedActionResult, PaginatedSuccessResult, SuccessResult } from '../../../infra/api/types';
5
- import { buildQueryParams } from '../../../infra/utils/params';
6
- import { getUserContext } from '../../auth/utils/get-user-context';
7
- import { Subscription, SubscriptionSchema, FindSubscriptionsParams } from '../types';
3
+ import { api } from "../../../infra/api/client";
4
+ import {
5
+ ApiError,
6
+ ApiActionResult,
7
+ ApiPaginatedActionResult,
8
+ PaginatedSuccessResult,
9
+ SuccessResult,
10
+ } from "../../../infra/api/types";
11
+ import { buildQueryParams } from "../../../infra/utils/params";
12
+ import { getUserContext } from "../../auth/utils/get-user-context";
13
+ import {
14
+ Subscription,
15
+ SubscriptionSchema,
16
+ FindSubscriptionsParams,
17
+ } from "../types";
8
18
  import {
9
19
  type CalculateSubscriptionRequest,
10
20
  type CalculateSubscriptionResponse,
11
21
  type UpdateSubscriptionPlanRequest,
12
22
  CalculateSubscriptionResponseSchema,
13
- } from '../types/calculate-subscription.type';
23
+ } from "../types/calculate-subscription.type";
14
24
 
15
25
  class SubscriptionsService {
16
26
  async listSubscriptions(
17
- params?: Partial<FindSubscriptionsParams>
27
+ params?: Partial<FindSubscriptionsParams>,
18
28
  ): Promise<PaginatedSuccessResult<Subscription>> {
19
29
  const { id_account } = await getUserContext();
20
30
 
21
- const query = buildQueryParams(params as Record<string, string | boolean | undefined>);
22
- const url = `/accounts/${id_account}/subscriptions${query ? `?${query}` : ''}`;
31
+ const query = buildQueryParams(
32
+ params as Record<string, string | boolean | undefined>,
33
+ );
34
+ const url = `/accounts/${id_account}/subscriptions${query ? `?${query}` : ""}`;
23
35
 
24
- const response = await api.apps.get<ApiPaginatedActionResult<Subscription>>(url);
36
+ const response =
37
+ await api.apps.get<ApiPaginatedActionResult<Subscription>>(url);
25
38
 
26
39
  if (response.status === 0) {
27
40
  throw new ApiError(
28
- response.message || 'Erro ao listar assinaturas',
29
- 'LIST_SUBSCRIPTIONS_FAILED',
30
- 400
41
+ response.message || "Erro ao listar assinaturas",
42
+ "LIST_SUBSCRIPTIONS_FAILED",
43
+ 400,
31
44
  );
32
45
  }
33
46
 
@@ -39,21 +52,23 @@ class SubscriptionsService {
39
52
  success: true,
40
53
  } satisfies PaginatedSuccessResult<Subscription>;
41
54
  }
55
+
42
56
  async calculateSubscription(
43
- data: CalculateSubscriptionRequest
57
+ data: CalculateSubscriptionRequest,
44
58
  ): Promise<SuccessResult<CalculateSubscriptionResponse>> {
45
59
  const { id_account } = await getUserContext();
46
60
 
47
- const response = await api.apps.post<ApiActionResult<CalculateSubscriptionResponse>>(
48
- `/accounts/${id_account}/subscriptions/action/calculate`,
49
- data
50
- );
61
+ const response = await api.apps.post<
62
+ ApiActionResult<CalculateSubscriptionResponse>
63
+ >(`/accounts/${id_account}/subscriptions/action/calculate`, data);
64
+
65
+ console.log("Calculate subscription response:", { response, data });
51
66
 
52
67
  if (response.status === 0) {
53
68
  throw new ApiError(
54
- response.message || 'Erro ao calcular assinatura',
55
- 'CALCULATE_SUBSCRIPTION_FAILED',
56
- 400
69
+ response.message || "Erro ao calcular assinatura",
70
+ "CALCULATE_SUBSCRIPTION_FAILED",
71
+ 400,
57
72
  );
58
73
  }
59
74
 
@@ -65,20 +80,20 @@ class SubscriptionsService {
65
80
 
66
81
  async updateSubscriptionPlan(
67
82
  subscriptionId: number | string,
68
- data: UpdateSubscriptionPlanRequest
83
+ data: UpdateSubscriptionPlanRequest,
69
84
  ): Promise<SuccessResult<void>> {
70
85
  const { id_account } = await getUserContext();
71
86
 
72
87
  const response = await api.apps.put<ApiActionResult<void>>(
73
88
  `/accounts/${id_account}/subscriptions/${subscriptionId}/action/plan`,
74
- data
89
+ data,
75
90
  );
76
91
 
77
92
  if (response.status === 0) {
78
93
  throw new ApiError(
79
- response.message || 'Erro ao atualizar plano',
80
- 'UPDATE_SUBSCRIPTION_PLAN_FAILED',
81
- 400
94
+ response.message || "Erro ao atualizar plano",
95
+ "UPDATE_SUBSCRIPTION_PLAN_FAILED",
96
+ 400,
82
97
  );
83
98
  }
84
99