@greatapps/common 1.1.510 → 1.1.512
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/account/ConfigurationsMyAccountModal.mjs +7 -1
- package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
- package/dist/components/account/sections/TokenSection.mjs +65 -0
- package/dist/components/account/sections/TokenSection.mjs.map +1 -0
- package/dist/enums/AccountSectionType.mjs +1 -0
- package/dist/enums/AccountSectionType.mjs.map +1 -1
- package/dist/modules/plans/types/plan.type.mjs.map +1 -1
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +20 -10
- package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/account/ConfigurationsMyAccountModal.tsx +15 -1
- package/src/components/account/sections/TokenSection.tsx +63 -0
- package/src/enums/AccountSectionType.ts +1 -0
- package/src/modules/accounts/types.ts +1 -0
- package/src/modules/plans/types/plan.type.ts +1 -1
- package/src/modules/plans/utils/map-api-plan-to-ui.ts +46 -37
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { IconLock, IconSettings2, IconX } from "@tabler/icons-react";
|
|
3
|
+
import { IconKey, IconLock, IconSettings2, IconX } from "@tabler/icons-react";
|
|
4
4
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/overlay/Dialog";
|
|
5
5
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "../ui/data-display/Tabs";
|
|
6
6
|
import { cn } from "../../infra/utils/clsx";
|
|
7
7
|
import { AccountSectionType } from "../../enums/AccountSectionType";
|
|
8
8
|
import { PreferencesSection } from "./sections/PreferencesSection";
|
|
9
9
|
import { ChangePasswordSection } from "./sections/ChangePasswordSection";
|
|
10
|
+
import { TokenSection } from "./sections/TokenSection";
|
|
10
11
|
import { SecuritySection } from "./sections/SecuritySection";
|
|
11
12
|
import useConfigurationsModal from "./hooks/useConfigurationsModal";
|
|
12
13
|
import useIsMobile from "../../hooks/useIsMobile";
|
|
@@ -94,6 +95,10 @@ function ConfigurationsMyAccountModal() {
|
|
|
94
95
|
/* @__PURE__ */ jsx(IconSettings2, { size: 20, className: "shrink-0" }),
|
|
95
96
|
/* @__PURE__ */ jsx("span", { className: "paragraph-small-medium", children: "Prefer\xEAncias" })
|
|
96
97
|
] }),
|
|
98
|
+
isOwner && /* @__PURE__ */ jsxs(TabsTrigger, { value: AccountSectionType.TOKEN, className: tabTriggerClasses, children: [
|
|
99
|
+
/* @__PURE__ */ jsx(IconKey, { size: 20, className: "shrink-0" }),
|
|
100
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-small-medium", children: "Token da conta" })
|
|
101
|
+
] }),
|
|
97
102
|
isOwner && /* @__PURE__ */ jsxs(TabsTrigger, { value: AccountSectionType.SECURITY, className: tabTriggerClasses, children: [
|
|
98
103
|
/* @__PURE__ */ jsx(IconLock, { size: 20, className: "shrink-0" }),
|
|
99
104
|
/* @__PURE__ */ jsx("span", { className: "paragraph-small-medium", children: "Seguran\xE7a" })
|
|
@@ -104,6 +109,7 @@ function ConfigurationsMyAccountModal() {
|
|
|
104
109
|
),
|
|
105
110
|
/* @__PURE__ */ jsxs("div", { className: "w-full flex-1 min-h-0 lg:h-full overflow-hidden lg:overflow-visible relative flex flex-col", children: [
|
|
106
111
|
/* @__PURE__ */ jsx(TabsContent, { value: AccountSectionType.PREFERENCES, className: "h-full! relative overflow-hidden", children: /* @__PURE__ */ jsx(PreferencesSection, { onClose: close }) }),
|
|
112
|
+
isOwner && /* @__PURE__ */ jsx(TabsContent, { value: AccountSectionType.TOKEN, className: "h-full! relative overflow-hidden", children: /* @__PURE__ */ jsx(TokenSection, {}) }),
|
|
107
113
|
isOwner && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
108
114
|
/* @__PURE__ */ jsx(TabsContent, { value: AccountSectionType.SECURITY, className: "h-full! relative overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
109
115
|
SecuritySection,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/account/ConfigurationsMyAccountModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconLock, IconSettings2, IconX } from '@tabler/icons-react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/data-display/Tabs';\nimport { cn } from '../../infra/utils/clsx';\nimport { AccountSectionType } from '../../enums/AccountSectionType';\nimport { PreferencesSection } from './sections/PreferencesSection';\nimport { ChangePasswordSection } from './sections/ChangePasswordSection';\nimport { SecuritySection } from './sections/SecuritySection';\nimport useConfigurationsModal from './hooks/useConfigurationsModal';\nimport useIsMobile from '../../hooks/useIsMobile';\nimport { useAccountModals } from '../../store/useAccountModals';\nimport { useAuth } from '../../providers/auth.provider';\nimport { UserProfile } from '../../modules/users/schema';\n\nexport default function ConfigurationsMyAccountModal() {\n const {\n activeModal,\n config,\n openDeleteAccount,\n openIsntPossibleDelete,\n close,\n } = useAccountModals();\n\n const open = activeModal === 'configurations';\n const { hasActiveSubscription } = config;\n\n const { user } = useAuth();\n const isOwner = user?.profile === UserProfile.owner;\n\n const isMobile = useIsMobile();\n const { activeSection, setActiveSection } = useConfigurationsModal({\n isOpen: open,\n });\n\n const handleDeleteAccount = () => {\n close();\n if (hasActiveSubscription) {\n openIsntPossibleDelete();\n } else {\n openDeleteAccount();\n }\n };\n\n const tabTriggerClasses = cn(\n 'border-0! px-0 py-0',\n\n 'lg:rounded-md lg:flex lg:items-center lg:gap-2 lg:p-3 lg:justify-start lg:w-full',\n 'lg:bg-white lg:hover:bg-gray-100 lg:active:bg-gray-50 lg:border-0',\n 'lg:data-[state=active]:bg-gray-50',\n\n 'flex items-center gap-1.5 px-3 py-3 justify-center whitespace-nowrap',\n 'border-b-2 border-transparent',\n 'data-[state=active]:bg-gray-50 rounded-lg',\n\n 'text-gray-500 data-[state=active]:text-gray-950',\n 'hover:text-gray-900 transition-colors'\n );\n\n return (\n <Dialog open={open} onOpenChange={close}>\n <DialogContent\n showCloseButton={!isMobile}\n overlayClassName=\"bg-black/20 lg:bg-black/50\"\n className=\"\n flex flex-col p-0 gap-0 max-w-full sm:max-w-full overflow-x-hidden border-0\n rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0\n lg:flex-row lg:w-[892px] lg:max-w-[892px] lg:h-[626px] lg:rounded-lg lg:border\n lg:top-[50%] lg:bottom-auto lg:left-[50%] lg:right-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\"\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Configurações</DialogTitle>\n </DialogHeader>\n <div className=\"md:hidden flex items-center justify-between px-5 py-3 border-b border-gray-200\">\n <span className=\"text-gray-950 paragraph-medium-semibold\">Configurações</span>\n <button\n type=\"button\"\n className=\"size-8 flex items-center justify-center text-gray-500 cursor-pointer\"\n onClick={close}\n >\n <IconX size={18} />\n </button>\n </div>\n <Tabs\n value={activeSection}\n onValueChange={(value) => setActiveSection(value as AccountSectionType)}\n orientation=\"vertical\"\n className=\"flex lg:flex-row flex-col w-full h-full flex-1 lg:h-full lg:pt-0 lg:gap-0\"\n >\n <TabsList\n className={cn(\n 'flex gap-0 bg-transparent border-b-0',\n\n 'lg:flex-col lg:items-stretch lg:justify-start lg:w-auto lg:min-w-60',\n 'lg:border-r lg:border-gray-200 lg:pl-5 lg:pr-5 lg:pt-5 lg:gap-5 lg:overflow-x-visible lg:self-stretch',\n\n 'flex-row items-center justify-start w-full overflow-x-auto scrollbar-hide shrink-0',\n 'px-4 py-3',\n '[mask-image:linear-gradient(to_right,transparent,black_16px,black_calc(100%-24px),transparent)] lg:[mask-image:none]'\n )}\n >\n <span className=\"hidden lg:block paragraph-medium-semibold text-gray-950 mb-0\">\n Configurações\n </span>\n\n <div className=\"lg:flex lg:flex-col flex flex-row lg:gap-0 gap-0 lg:w-full\">\n <TabsTrigger value={AccountSectionType.PREFERENCES} className={tabTriggerClasses}>\n <IconSettings2 size={20} className=\"shrink-0\" />\n <span className=\"paragraph-small-medium\">Preferências</span>\n </TabsTrigger>\n\n {isOwner && (\n <TabsTrigger value={AccountSectionType.SECURITY} className={tabTriggerClasses}>\n <IconLock size={20} className=\"shrink-0\" />\n <span className=\"paragraph-small-medium\">Segurança</span>\n </TabsTrigger>\n )}\n </div>\n </TabsList>\n\n <div className=\"w-full flex-1 min-h-0 lg:h-full overflow-hidden lg:overflow-visible relative flex flex-col\">\n <TabsContent value={AccountSectionType.PREFERENCES} className=\"h-full! relative overflow-hidden\">\n <PreferencesSection onClose={close} />\n </TabsContent>\n\n {isOwner && (\n <>\n <TabsContent value={AccountSectionType.SECURITY} className=\"h-full! relative overflow-hidden\">\n <SecuritySection\n setActiveSection={setActiveSection}\n onClose={close}\n onDeleteAccount={handleDeleteAccount}\n />\n </TabsContent>\n\n <TabsContent value={AccountSectionType.CHANGE_PASSWORD} className=\"h-full! relative overflow-hidden\">\n <ChangePasswordSection onBack={() => setActiveSection(AccountSectionType.SECURITY)} />\n </TabsContent>\n </>\n )}\n </div>\n </Tabs>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../../src/components/account/ConfigurationsMyAccountModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconKey, IconLock, IconSettings2, IconX } from '@tabler/icons-react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/data-display/Tabs';\nimport { cn } from '../../infra/utils/clsx';\nimport { AccountSectionType } from '../../enums/AccountSectionType';\nimport { PreferencesSection } from './sections/PreferencesSection';\nimport { ChangePasswordSection } from './sections/ChangePasswordSection';\nimport { TokenSection } from './sections/TokenSection';\nimport { SecuritySection } from './sections/SecuritySection';\nimport useConfigurationsModal from './hooks/useConfigurationsModal';\nimport useIsMobile from '../../hooks/useIsMobile';\nimport { useAccountModals } from '../../store/useAccountModals';\nimport { useAuth } from '../../providers/auth.provider';\nimport { UserProfile } from '../../modules/users/schema';\n\nexport default function ConfigurationsMyAccountModal() {\n const {\n activeModal,\n config,\n openDeleteAccount,\n openIsntPossibleDelete,\n close,\n } = useAccountModals();\n\n const open = activeModal === 'configurations';\n const { hasActiveSubscription } = config;\n\n const { user } = useAuth();\n const isOwner = user?.profile === UserProfile.owner;\n\n const isMobile = useIsMobile();\n const { activeSection, setActiveSection } = useConfigurationsModal({\n isOpen: open,\n });\n\n const handleDeleteAccount = () => {\n close();\n if (hasActiveSubscription) {\n openIsntPossibleDelete();\n } else {\n openDeleteAccount();\n }\n };\n\n const tabTriggerClasses = cn(\n 'border-0! px-0 py-0',\n\n 'lg:rounded-md lg:flex lg:items-center lg:gap-2 lg:p-3 lg:justify-start lg:w-full',\n 'lg:bg-white lg:hover:bg-gray-100 lg:active:bg-gray-50 lg:border-0',\n 'lg:data-[state=active]:bg-gray-50',\n\n 'flex items-center gap-1.5 px-3 py-3 justify-center whitespace-nowrap',\n 'border-b-2 border-transparent',\n 'data-[state=active]:bg-gray-50 rounded-lg',\n\n 'text-gray-500 data-[state=active]:text-gray-950',\n 'hover:text-gray-900 transition-colors'\n );\n\n return (\n <Dialog open={open} onOpenChange={close}>\n <DialogContent\n showCloseButton={!isMobile}\n overlayClassName=\"bg-black/20 lg:bg-black/50\"\n className=\"\n flex flex-col p-0 gap-0 max-w-full sm:max-w-full overflow-x-hidden border-0\n rounded-t-2xl rounded-b-none h-[100dvh] top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0\n lg:flex-row lg:w-[892px] lg:max-w-[892px] lg:h-[626px] lg:rounded-lg lg:border\n lg:top-[50%] lg:bottom-auto lg:left-[50%] lg:right-auto lg:translate-x-[-50%] lg:translate-y-[-50%]\"\n >\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Configurações</DialogTitle>\n </DialogHeader>\n <div className=\"md:hidden flex items-center justify-between px-5 py-3 border-b border-gray-200\">\n <span className=\"text-gray-950 paragraph-medium-semibold\">Configurações</span>\n <button\n type=\"button\"\n className=\"size-8 flex items-center justify-center text-gray-500 cursor-pointer\"\n onClick={close}\n >\n <IconX size={18} />\n </button>\n </div>\n <Tabs\n value={activeSection}\n onValueChange={(value) => setActiveSection(value as AccountSectionType)}\n orientation=\"vertical\"\n className=\"flex lg:flex-row flex-col w-full h-full flex-1 lg:h-full lg:pt-0 lg:gap-0\"\n >\n <TabsList\n className={cn(\n 'flex gap-0 bg-transparent border-b-0',\n\n 'lg:flex-col lg:items-stretch lg:justify-start lg:w-auto lg:min-w-60',\n 'lg:border-r lg:border-gray-200 lg:pl-5 lg:pr-5 lg:pt-5 lg:gap-5 lg:overflow-x-visible lg:self-stretch',\n\n 'flex-row items-center justify-start w-full overflow-x-auto scrollbar-hide shrink-0',\n 'px-4 py-3',\n '[mask-image:linear-gradient(to_right,transparent,black_16px,black_calc(100%-24px),transparent)] lg:[mask-image:none]'\n )}\n >\n <span className=\"hidden lg:block paragraph-medium-semibold text-gray-950 mb-0\">\n Configurações\n </span>\n\n <div className=\"lg:flex lg:flex-col flex flex-row lg:gap-0 gap-0 lg:w-full\">\n <TabsTrigger value={AccountSectionType.PREFERENCES} className={tabTriggerClasses}>\n <IconSettings2 size={20} className=\"shrink-0\" />\n <span className=\"paragraph-small-medium\">Preferências</span>\n </TabsTrigger>\n\n {isOwner && (\n <TabsTrigger value={AccountSectionType.TOKEN} className={tabTriggerClasses}>\n <IconKey size={20} className=\"shrink-0\" />\n <span className=\"paragraph-small-medium\">Token da conta</span>\n </TabsTrigger>\n )}\n\n {isOwner && (\n <TabsTrigger value={AccountSectionType.SECURITY} className={tabTriggerClasses}>\n <IconLock size={20} className=\"shrink-0\" />\n <span className=\"paragraph-small-medium\">Segurança</span>\n </TabsTrigger>\n )}\n </div>\n </TabsList>\n\n <div className=\"w-full flex-1 min-h-0 lg:h-full overflow-hidden lg:overflow-visible relative flex flex-col\">\n <TabsContent value={AccountSectionType.PREFERENCES} className=\"h-full! relative overflow-hidden\">\n <PreferencesSection onClose={close} />\n </TabsContent>\n\n {isOwner && (\n <TabsContent value={AccountSectionType.TOKEN} className=\"h-full! relative overflow-hidden\">\n <TokenSection />\n </TabsContent>\n )}\n\n {isOwner && (\n <>\n <TabsContent value={AccountSectionType.SECURITY} className=\"h-full! relative overflow-hidden\">\n <SecuritySection\n setActiveSection={setActiveSection}\n onClose={close}\n onDeleteAccount={handleDeleteAccount}\n />\n </TabsContent>\n\n <TabsContent value={AccountSectionType.CHANGE_PASSWORD} className=\"h-full! relative overflow-hidden\">\n <ChangePasswordSection onBack={() => setActiveSection(AccountSectionType.SECURITY)} />\n </TabsContent>\n </>\n )}\n </div>\n </Tabs>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { IconCheck, IconCopy } from "@tabler/icons-react";
|
|
4
|
+
import { toast } from "sonner";
|
|
5
|
+
import { Toast } from "../../ui/feedback/Toast";
|
|
6
|
+
import { Button } from "../../ui/buttons/Button";
|
|
7
|
+
import { FormField } from "../../ui/form/FormField";
|
|
8
|
+
import useCopyToClipboard from "../../../hooks/copy-to-clipboard.hook";
|
|
9
|
+
import { useAuth } from "../../../providers/auth.provider";
|
|
10
|
+
function TokenSection() {
|
|
11
|
+
const { account } = useAuth();
|
|
12
|
+
const token = account?.token ?? "";
|
|
13
|
+
const { isCopied, copy } = useCopyToClipboard({
|
|
14
|
+
onSuccess: () => {
|
|
15
|
+
toast.custom((t) => /* @__PURE__ */ jsx(Toast, { variant: "success", message: "Token copiado com sucesso", toastId: t }));
|
|
16
|
+
},
|
|
17
|
+
onError: () => {
|
|
18
|
+
toast.custom((t) => /* @__PURE__ */ jsx(Toast, { variant: "error", message: "N\xE3o foi poss\xEDvel copiar o token", toastId: t }));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return /* @__PURE__ */ jsxs("div", { className: "h-full overflow-y-auto overscroll-contain px-4 pb-20 lg:p-5 lg:pt-5 flex flex-col gap-5 lg:gap-6 lg:pb-31 lg:overscroll-auto", children: [
|
|
22
|
+
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-950", children: "Token da conta" }),
|
|
23
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
24
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-3", children: [
|
|
25
|
+
/* @__PURE__ */ jsx(
|
|
26
|
+
FormField,
|
|
27
|
+
{
|
|
28
|
+
label: "Token",
|
|
29
|
+
value: token,
|
|
30
|
+
disabled: true,
|
|
31
|
+
readOnly: true,
|
|
32
|
+
classnameContainer: "cursor-default opacity-100!"
|
|
33
|
+
}
|
|
34
|
+
),
|
|
35
|
+
/* @__PURE__ */ jsxs(
|
|
36
|
+
Button,
|
|
37
|
+
{
|
|
38
|
+
type: "button",
|
|
39
|
+
variant: "secondary",
|
|
40
|
+
className: "h-10! shrink-0 gap-2",
|
|
41
|
+
onClick: () => copy(token),
|
|
42
|
+
children: [
|
|
43
|
+
isCopied ? /* @__PURE__ */ jsx(IconCheck, { size: 16 }) : /* @__PURE__ */ jsx(IconCopy, { size: 16 }),
|
|
44
|
+
isCopied ? "Copiado" : "Copiar token"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
] }),
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
"a",
|
|
51
|
+
{
|
|
52
|
+
href: "https://documenter.getpostman.com/view/4861938/2sAYdoDmj4",
|
|
53
|
+
target: "_blank",
|
|
54
|
+
rel: "noopener noreferrer",
|
|
55
|
+
className: "paragraph-small-medium text-gray-500 underline hover:text-gray-700 transition-colors w-fit",
|
|
56
|
+
children: "Acessar a documenta\xE7\xE3o"
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
] })
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
TokenSection
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=TokenSection.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/sections/TokenSection.tsx"],"sourcesContent":["'use client';\n\nimport { IconCheck, IconCopy } from '@tabler/icons-react';\nimport { toast } from 'sonner';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { Button } from '../../ui/buttons/Button';\nimport { FormField } from '../../ui/form/FormField';\nimport useCopyToClipboard from '../../../hooks/copy-to-clipboard.hook';\nimport { useAuth } from '../../../providers/auth.provider';\n\nexport function TokenSection() {\n const { account } = useAuth();\n const token = account?.token ?? '';\n\n const { isCopied, copy } = useCopyToClipboard({\n onSuccess: () => {\n toast.custom((t) => (\n <Toast variant=\"success\" message=\"Token copiado com sucesso\" toastId={t} />\n ));\n },\n onError: () => {\n toast.custom((t) => (\n <Toast variant=\"error\" message=\"Não foi possível copiar o token\" toastId={t} />\n ));\n },\n });\n\n return (\n <div className=\"h-full overflow-y-auto overscroll-contain px-4 pb-20 lg:p-5 lg:pt-5 flex flex-col gap-5 lg:gap-6 lg:pb-31 lg:overscroll-auto\">\n <span className=\"paragraph-medium-semibold text-gray-950\">Token da conta</span>\n\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-end gap-3\">\n <FormField\n label=\"Token\"\n value={token}\n disabled\n readOnly\n classnameContainer=\"cursor-default opacity-100!\"\n />\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-10! shrink-0 gap-2\"\n onClick={() => copy(token)}\n >\n {isCopied ? <IconCheck size={16} /> : <IconCopy size={16} />}\n {isCopied ? 'Copiado' : 'Copiar token'}\n </Button>\n </div>\n\n <a\n href=\"https://documenter.getpostman.com/view/4861938/2sAYdoDmj4\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"paragraph-small-medium text-gray-500 underline hover:text-gray-700 transition-colors w-fit\"\n >\n Acessar a documentação\n </a>\n </div>\n </div>\n );\n}\n"],"mappings":";AAiBQ,cAuBE,YAvBF;AAfR,SAAS,WAAW,gBAAgB;AACpC,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,OAAO,wBAAwB;AAC/B,SAAS,eAAe;AAEjB,SAAS,eAAe;AAC7B,QAAM,EAAE,QAAQ,IAAI,QAAQ;AAC5B,QAAM,QAAQ,SAAS,SAAS;AAEhC,QAAM,EAAE,UAAU,KAAK,IAAI,mBAAmB;AAAA,IAC5C,WAAW,MAAM;AACf,YAAM,OAAO,CAAC,MACZ,oBAAC,SAAM,SAAQ,WAAU,SAAQ,6BAA4B,SAAS,GAAG,CAC1E;AAAA,IACH;AAAA,IACA,SAAS,MAAM;AACb,YAAM,OAAO,CAAC,MACZ,oBAAC,SAAM,SAAQ,SAAQ,SAAQ,yCAAkC,SAAS,GAAG,CAC9E;AAAA,IACH;AAAA,EACF,CAAC;AAED,SACE,qBAAC,SAAI,WAAU,gIACb;AAAA,wBAAC,UAAK,WAAU,2CAA0C,4BAAc;AAAA,IAExE,qBAAC,SAAI,WAAU,uBACb;AAAA,2BAAC,SAAI,WAAU,wBACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,OAAO;AAAA,YACP,UAAQ;AAAA,YACR,UAAQ;AAAA,YACR,oBAAmB;AAAA;AAAA,QACrB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,SAAS,MAAM,KAAK,KAAK;AAAA,YAExB;AAAA,yBAAW,oBAAC,aAAU,MAAM,IAAI,IAAK,oBAAC,YAAS,MAAM,IAAI;AAAA,cACzD,WAAW,YAAY;AAAA;AAAA;AAAA,QAC1B;AAAA,SACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,QAAO;AAAA,UACP,KAAI;AAAA,UACJ,WAAU;AAAA,UACX;AAAA;AAAA,MAED;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -2,6 +2,7 @@ var AccountSectionType = /* @__PURE__ */ ((AccountSectionType2) => {
|
|
|
2
2
|
AccountSectionType2["MY_PROFILE"] = "my-profile";
|
|
3
3
|
AccountSectionType2["SECURITY"] = "security";
|
|
4
4
|
AccountSectionType2["PREFERENCES"] = "preferences";
|
|
5
|
+
AccountSectionType2["TOKEN"] = "token";
|
|
5
6
|
AccountSectionType2["CHANGE_PASSWORD"] = "change-password";
|
|
6
7
|
return AccountSectionType2;
|
|
7
8
|
})(AccountSectionType || {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/enums/AccountSectionType.ts"],"sourcesContent":["export enum AccountSectionType {\r\n MY_PROFILE = 'my-profile',\r\n SECURITY = 'security',\r\n PREFERENCES = 'preferences',\r\n CHANGE_PASSWORD = 'change-password',\r\n}\r\n"],"mappings":"AAAO,IAAK,qBAAL,kBAAKA,wBAAL;AACL,EAAAA,oBAAA,gBAAa;AACb,EAAAA,oBAAA,cAAW;AACX,EAAAA,oBAAA,iBAAc;AACd,EAAAA,oBAAA,qBAAkB;
|
|
1
|
+
{"version":3,"sources":["../../src/enums/AccountSectionType.ts"],"sourcesContent":["export enum AccountSectionType {\r\n MY_PROFILE = 'my-profile',\r\n SECURITY = 'security',\r\n PREFERENCES = 'preferences',\r\n TOKEN = 'token',\r\n CHANGE_PASSWORD = 'change-password',\r\n}\r\n"],"mappings":"AAAO,IAAK,qBAAL,kBAAKA,wBAAL;AACL,EAAAA,oBAAA,gBAAa;AACb,EAAAA,oBAAA,cAAW;AACX,EAAAA,oBAAA,iBAAc;AACd,EAAAA,oBAAA,WAAQ;AACR,EAAAA,oBAAA,qBAAkB;AALR,SAAAA;AAAA,GAAA;","names":["AccountSectionType"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/plans/types/plan.type.ts"],"sourcesContent":["import z from 'zod';\nimport type { BillingPeriod } from '../../subscriptions/types/billing-period.type';\n\nexport const PlanItemSchema = z.object({\n id_addon: z.number(),\n quantity: z.number(),\n value: z.number(),\n});\n\nexport type PlanItem = z.infer<typeof PlanItemSchema>;\n\nexport const PlanSchema = z.object({\n id: z.number(),\n id_plan: z.number().optional(),\n name: z.string(),\n value: z.number().default(0),\n type: z.string().optional(),\n discount_semester: z.number().default(0),\n discount_annual: z.number().default(0),\n items: z.array(PlanItemSchema).optional().default([]),\n});\n\nexport type Plan = z.infer<typeof PlanSchema>;\n\n// ── UI Plan types (used by list-plans action and consumers) ──\n\nexport type PlanFeature = {\n icon: 'check' | 'x';\n text: string;\n disabled?: boolean;\n tooltip?: keyof PlanTooltips;\n};\n\nexport type PlanMainFeatures = {\n pages: string;\n domains: string;\n users: string;\n};\n\n/** Preços mensais equivalentes por período de cobrança (já com desconto aplicado). */\nexport type PlanPricingByPeriod = {\n monthly: number;\n semiannual: number;\n annual: number;\n};\n\nexport type UiPlan = {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/plans/types/plan.type.ts"],"sourcesContent":["import z from 'zod';\nimport type { BillingPeriod } from '../../subscriptions/types/billing-period.type';\n\nexport const PlanItemSchema = z.object({\n id_addon: z.number(),\n quantity: z.number(),\n value: z.number(),\n});\n\nexport type PlanItem = z.infer<typeof PlanItemSchema>;\n\nexport const PlanSchema = z.object({\n id: z.number(),\n id_plan: z.number().optional(),\n name: z.string(),\n value: z.number().default(0),\n type: z.string().optional(),\n discount_semester: z.number().default(0),\n discount_annual: z.number().default(0),\n items: z.array(PlanItemSchema).optional().default([]),\n});\n\nexport type Plan = z.infer<typeof PlanSchema>;\n\n// ── UI Plan types (used by list-plans action and consumers) ──\n\nexport type PlanFeature = {\n icon: 'check' | 'x';\n text: string;\n disabled?: boolean;\n tooltip?: keyof PlanTooltips;\n};\n\nexport type PlanMainFeatures = {\n pages: string;\n domains: string;\n users: string;\n};\n\n/** Preços mensais equivalentes por período de cobrança (já com desconto aplicado). */\nexport type PlanPricingByPeriod = {\n monthly: number;\n semiannual: number;\n annual: number;\n};\n\nexport type UiPlan = {\n planId: number;\n name: string;\n isPopular?: boolean;\n isCurrentPlan?: boolean;\n currentPeriodicity?: BillingPeriod | null;\n mainFeatures: PlanMainFeatures;\n features: PlanFeature[];\n originalPrice: string;\n price: string;\n pricingByPeriod?: PlanPricingByPeriod;\n buttonVariant?: 'brand' | 'default';\n items: PlanItem[];\n};\n\nexport type PlanTooltips = {\n domains: string;\n users: string;\n sharePages: string;\n projectManagement: string;\n};\n"],"mappings":"AAAA,OAAO,OAAO;AAGP,MAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,UAAU,EAAE,OAAO;AAAA,EACnB,UAAU,EAAE,OAAO;AAAA,EACnB,OAAO,EAAE,OAAO;AAClB,CAAC;AAIM,MAAM,aAAa,EAAE,OAAO;AAAA,EACjC,IAAI,EAAE,OAAO;AAAA,EACb,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAM,EAAE,OAAO;AAAA,EACf,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EAC3B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,mBAAmB,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EACvC,iBAAiB,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EACrC,OAAO,EAAE,MAAM,cAAc,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;","names":[]}
|
|
@@ -28,28 +28,38 @@ function computePricingByPeriod(apiPlan) {
|
|
|
28
28
|
annual: round2(monthly * (1 - apiPlan.discount_annual / 100))
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
-
function mapApiPlanToUiPlan(
|
|
32
|
-
const
|
|
33
|
-
const
|
|
31
|
+
function mapApiPlanToUiPlan(plan) {
|
|
32
|
+
const popular = plan.id === 2 || plan.id_plan === 2;
|
|
33
|
+
const buttonVariant = popular ? "brand" : "default";
|
|
34
|
+
const pricingByPeriod = computePricingByPeriod(plan);
|
|
34
35
|
const monthlyFinal = pricingByPeriod.monthly;
|
|
35
|
-
const lowerName =
|
|
36
|
+
const lowerName = plan.name.toLowerCase();
|
|
36
37
|
const hasProjectAndOnboarding = lowerName.includes("ag\xEAncia") || lowerName.includes("agencia");
|
|
37
38
|
const features = [
|
|
38
39
|
...BASE_FEATURES,
|
|
39
40
|
hasProjectAndOnboarding ? { icon: "check", text: "Reuni\xE3o de Onboarding" } : { icon: "x", text: "Reuni\xE3o de Onboarding", disabled: true },
|
|
40
|
-
hasProjectAndOnboarding ? {
|
|
41
|
+
hasProjectAndOnboarding ? {
|
|
42
|
+
icon: "check",
|
|
43
|
+
text: "Gest\xE3o de projetos",
|
|
44
|
+
tooltip: "projectManagement"
|
|
45
|
+
} : {
|
|
46
|
+
icon: "x",
|
|
47
|
+
text: "Gest\xE3o de projetos",
|
|
48
|
+
disabled: true,
|
|
49
|
+
tooltip: "projectManagement"
|
|
50
|
+
}
|
|
41
51
|
];
|
|
42
52
|
return {
|
|
43
|
-
|
|
44
|
-
name:
|
|
45
|
-
isPopular,
|
|
53
|
+
planId: plan.id,
|
|
54
|
+
name: plan.name,
|
|
55
|
+
isPopular: popular,
|
|
46
56
|
buttonVariant,
|
|
47
|
-
mainFeatures: buildMainFeaturesFromItems(
|
|
57
|
+
mainFeatures: buildMainFeaturesFromItems(plan.items),
|
|
48
58
|
features,
|
|
49
59
|
originalPrice: formatCurrencyNumber(monthlyFinal),
|
|
50
60
|
price: formatCurrencyNumber(monthlyFinal),
|
|
51
61
|
pricingByPeriod,
|
|
52
|
-
items:
|
|
62
|
+
items: plan.items
|
|
53
63
|
};
|
|
54
64
|
}
|
|
55
65
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/plans/utils/map-api-plan-to-ui.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/plans/utils/map-api-plan-to-ui.ts"],"sourcesContent":["import type {\n Plan,\n PlanFeature,\n PlanMainFeatures,\n PlanPricingByPeriod,\n UiPlan,\n} from \"../types/plan.type\";\nimport { ADDON_IDS } from \"../../subscriptions/constants/addons.constants\";\nimport { formatCurrencyNumber } from \"../../../utils/format/currency\";\n\nexport type PlanBillingPeriod = \"monthly\" | \"semiannual\" | \"annual\";\n\nconst BASE_FEATURES: PlanFeature[] = [\n { icon: \"check\", text: \"Visitas ilimitadas\" },\n { icon: \"check\", text: \"Leads ilimitadas\" },\n { icon: \"check\", text: \"Compartilhar páginas\", tooltip: \"sharePages\" },\n { icon: \"check\", text: \"Hospedagem inclusa\" },\n { icon: \"check\", text: \"SSL (HTTPS) + CDN\" },\n { icon: \"check\", text: \"Templates Free\" },\n];\n\nfunction buildMainFeaturesFromItems(items: Plan[\"items\"]): PlanMainFeatures {\n const pagesItem = items.find((i) => i.id_addon === ADDON_IDS.PAGES);\n const domainsItem = items.find((i) => i.id_addon === ADDON_IDS.DOMAINS);\n\n const pagesQty = pagesItem?.quantity ?? 0;\n const domainsQty = domainsItem?.quantity ?? 1;\n\n return {\n pages:\n pagesQty === 0\n ? \"Páginas ilimitadas\"\n : pagesQty === 1\n ? \"1 página\"\n : `${pagesQty} páginas`,\n domains:\n domainsQty >= 999\n ? \"Domínios ilimitados\"\n : domainsQty === 1\n ? \"1 domínio externo\"\n : `${domainsQty} domínios externos`,\n users: \"Usuários ilimitados\",\n };\n}\n\nfunction computePricingByPeriod(apiPlan: Plan): PlanPricingByPeriod {\n const monthly = apiPlan.value;\n const round2 = (n: number) => Math.round(n * 100) / 100;\n return {\n monthly,\n semiannual: round2(monthly * (1 - apiPlan.discount_semester / 100)),\n annual: round2(monthly * (1 - apiPlan.discount_annual / 100)),\n };\n}\n\nexport function mapApiPlanToUiPlan(plan: Plan): UiPlan {\n const popular = plan.id === 2 || plan.id_plan === 2;\n const buttonVariant = popular ? \"brand\" : \"default\";\n\n const pricingByPeriod = computePricingByPeriod(plan);\n const monthlyFinal = pricingByPeriod.monthly;\n\n const lowerName = plan.name.toLowerCase();\n const hasProjectAndOnboarding =\n lowerName.includes(\"agência\") || lowerName.includes(\"agencia\");\n\n const features: PlanFeature[] = [\n ...BASE_FEATURES,\n hasProjectAndOnboarding\n ? { icon: \"check\", text: \"Reunião de Onboarding\" }\n : { icon: \"x\", text: \"Reunião de Onboarding\", disabled: true },\n hasProjectAndOnboarding\n ? {\n icon: \"check\",\n text: \"Gestão de projetos\",\n tooltip: \"projectManagement\",\n }\n : {\n icon: \"x\",\n text: \"Gestão de projetos\",\n disabled: true,\n tooltip: \"projectManagement\",\n },\n ];\n\n return {\n planId: plan.id,\n name: plan.name,\n isPopular: popular,\n buttonVariant,\n mainFeatures: buildMainFeaturesFromItems(plan.items),\n features,\n originalPrice: formatCurrencyNumber(monthlyFinal),\n price: formatCurrencyNumber(monthlyFinal),\n pricingByPeriod,\n items: plan.items,\n };\n}\n"],"mappings":"AAOA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AAIrC,MAAM,gBAA+B;AAAA,EACnC,EAAE,MAAM,SAAS,MAAM,qBAAqB;AAAA,EAC5C,EAAE,MAAM,SAAS,MAAM,mBAAmB;AAAA,EAC1C,EAAE,MAAM,SAAS,MAAM,2BAAwB,SAAS,aAAa;AAAA,EACrE,EAAE,MAAM,SAAS,MAAM,qBAAqB;AAAA,EAC5C,EAAE,MAAM,SAAS,MAAM,oBAAoB;AAAA,EAC3C,EAAE,MAAM,SAAS,MAAM,iBAAiB;AAC1C;AAEA,SAAS,2BAA2B,OAAwC;AAC1E,QAAM,YAAY,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,KAAK;AAClE,QAAM,cAAc,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,UAAU,OAAO;AAEtE,QAAM,WAAW,WAAW,YAAY;AACxC,QAAM,aAAa,aAAa,YAAY;AAE5C,SAAO;AAAA,IACL,OACE,aAAa,IACT,0BACA,aAAa,IACX,gBACA,GAAG,QAAQ;AAAA,IACnB,SACE,cAAc,MACV,2BACA,eAAe,IACb,yBACA,GAAG,UAAU;AAAA,IACrB,OAAO;AAAA,EACT;AACF;AAEA,SAAS,uBAAuB,SAAoC;AAClE,QAAM,UAAU,QAAQ;AACxB,QAAM,SAAS,CAAC,MAAc,KAAK,MAAM,IAAI,GAAG,IAAI;AACpD,SAAO;AAAA,IACL;AAAA,IACA,YAAY,OAAO,WAAW,IAAI,QAAQ,oBAAoB,IAAI;AAAA,IAClE,QAAQ,OAAO,WAAW,IAAI,QAAQ,kBAAkB,IAAI;AAAA,EAC9D;AACF;AAEO,SAAS,mBAAmB,MAAoB;AACrD,QAAM,UAAU,KAAK,OAAO,KAAK,KAAK,YAAY;AAClD,QAAM,gBAAgB,UAAU,UAAU;AAE1C,QAAM,kBAAkB,uBAAuB,IAAI;AACnD,QAAM,eAAe,gBAAgB;AAErC,QAAM,YAAY,KAAK,KAAK,YAAY;AACxC,QAAM,0BACJ,UAAU,SAAS,YAAS,KAAK,UAAU,SAAS,SAAS;AAE/D,QAAM,WAA0B;AAAA,IAC9B,GAAG;AAAA,IACH,0BACI,EAAE,MAAM,SAAS,MAAM,2BAAwB,IAC/C,EAAE,MAAM,KAAK,MAAM,4BAAyB,UAAU,KAAK;AAAA,IAC/D,0BACI;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IACX,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACN;AAEA,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA,cAAc,2BAA2B,KAAK,KAAK;AAAA,IACnD;AAAA,IACA,eAAe,qBAAqB,YAAY;AAAA,IAChD,OAAO,qBAAqB,YAAY;AAAA,IACxC;AAAA,IACA,OAAO,KAAK;AAAA,EACd;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { IconLock, IconSettings2, IconX } from '@tabler/icons-react';
|
|
3
|
+
import { IconKey, IconLock, IconSettings2, IconX } from '@tabler/icons-react';
|
|
4
4
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/overlay/Dialog';
|
|
5
5
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from '../ui/data-display/Tabs';
|
|
6
6
|
import { cn } from '../../infra/utils/clsx';
|
|
7
7
|
import { AccountSectionType } from '../../enums/AccountSectionType';
|
|
8
8
|
import { PreferencesSection } from './sections/PreferencesSection';
|
|
9
9
|
import { ChangePasswordSection } from './sections/ChangePasswordSection';
|
|
10
|
+
import { TokenSection } from './sections/TokenSection';
|
|
10
11
|
import { SecuritySection } from './sections/SecuritySection';
|
|
11
12
|
import useConfigurationsModal from './hooks/useConfigurationsModal';
|
|
12
13
|
import useIsMobile from '../../hooks/useIsMobile';
|
|
@@ -110,6 +111,13 @@ export default function ConfigurationsMyAccountModal() {
|
|
|
110
111
|
<span className="paragraph-small-medium">Preferências</span>
|
|
111
112
|
</TabsTrigger>
|
|
112
113
|
|
|
114
|
+
{isOwner && (
|
|
115
|
+
<TabsTrigger value={AccountSectionType.TOKEN} className={tabTriggerClasses}>
|
|
116
|
+
<IconKey size={20} className="shrink-0" />
|
|
117
|
+
<span className="paragraph-small-medium">Token da conta</span>
|
|
118
|
+
</TabsTrigger>
|
|
119
|
+
)}
|
|
120
|
+
|
|
113
121
|
{isOwner && (
|
|
114
122
|
<TabsTrigger value={AccountSectionType.SECURITY} className={tabTriggerClasses}>
|
|
115
123
|
<IconLock size={20} className="shrink-0" />
|
|
@@ -124,6 +132,12 @@ export default function ConfigurationsMyAccountModal() {
|
|
|
124
132
|
<PreferencesSection onClose={close} />
|
|
125
133
|
</TabsContent>
|
|
126
134
|
|
|
135
|
+
{isOwner && (
|
|
136
|
+
<TabsContent value={AccountSectionType.TOKEN} className="h-full! relative overflow-hidden">
|
|
137
|
+
<TokenSection />
|
|
138
|
+
</TabsContent>
|
|
139
|
+
)}
|
|
140
|
+
|
|
127
141
|
{isOwner && (
|
|
128
142
|
<>
|
|
129
143
|
<TabsContent value={AccountSectionType.SECURITY} className="h-full! relative overflow-hidden">
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { IconCheck, IconCopy } from '@tabler/icons-react';
|
|
4
|
+
import { toast } from 'sonner';
|
|
5
|
+
import { Toast } from '../../ui/feedback/Toast';
|
|
6
|
+
import { Button } from '../../ui/buttons/Button';
|
|
7
|
+
import { FormField } from '../../ui/form/FormField';
|
|
8
|
+
import useCopyToClipboard from '../../../hooks/copy-to-clipboard.hook';
|
|
9
|
+
import { useAuth } from '../../../providers/auth.provider';
|
|
10
|
+
|
|
11
|
+
export function TokenSection() {
|
|
12
|
+
const { account } = useAuth();
|
|
13
|
+
const token = account?.token ?? '';
|
|
14
|
+
|
|
15
|
+
const { isCopied, copy } = useCopyToClipboard({
|
|
16
|
+
onSuccess: () => {
|
|
17
|
+
toast.custom((t) => (
|
|
18
|
+
<Toast variant="success" message="Token copiado com sucesso" toastId={t} />
|
|
19
|
+
));
|
|
20
|
+
},
|
|
21
|
+
onError: () => {
|
|
22
|
+
toast.custom((t) => (
|
|
23
|
+
<Toast variant="error" message="Não foi possível copiar o token" toastId={t} />
|
|
24
|
+
));
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="h-full overflow-y-auto overscroll-contain px-4 pb-20 lg:p-5 lg:pt-5 flex flex-col gap-5 lg:gap-6 lg:pb-31 lg:overscroll-auto">
|
|
30
|
+
<span className="paragraph-medium-semibold text-gray-950">Token da conta</span>
|
|
31
|
+
|
|
32
|
+
<div className="flex flex-col gap-3">
|
|
33
|
+
<div className="flex items-end gap-3">
|
|
34
|
+
<FormField
|
|
35
|
+
label="Token"
|
|
36
|
+
value={token}
|
|
37
|
+
disabled
|
|
38
|
+
readOnly
|
|
39
|
+
classnameContainer="cursor-default opacity-100!"
|
|
40
|
+
/>
|
|
41
|
+
<Button
|
|
42
|
+
type="button"
|
|
43
|
+
variant="secondary"
|
|
44
|
+
className="h-10! shrink-0 gap-2"
|
|
45
|
+
onClick={() => copy(token)}
|
|
46
|
+
>
|
|
47
|
+
{isCopied ? <IconCheck size={16} /> : <IconCopy size={16} />}
|
|
48
|
+
{isCopied ? 'Copiado' : 'Copiar token'}
|
|
49
|
+
</Button>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<a
|
|
53
|
+
href="https://documenter.getpostman.com/view/4861938/2sAYdoDmj4"
|
|
54
|
+
target="_blank"
|
|
55
|
+
rel="noopener noreferrer"
|
|
56
|
+
className="paragraph-small-medium text-gray-500 underline hover:text-gray-700 transition-colors w-fit"
|
|
57
|
+
>
|
|
58
|
+
Acessar a documentação
|
|
59
|
+
</a>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type {
|
|
2
|
+
Plan,
|
|
3
|
+
PlanFeature,
|
|
4
|
+
PlanMainFeatures,
|
|
5
|
+
PlanPricingByPeriod,
|
|
6
|
+
UiPlan,
|
|
7
|
+
} from "../types/plan.type";
|
|
8
|
+
import { ADDON_IDS } from "../../subscriptions/constants/addons.constants";
|
|
9
|
+
import { formatCurrencyNumber } from "../../../utils/format/currency";
|
|
4
10
|
|
|
5
|
-
export type PlanBillingPeriod =
|
|
11
|
+
export type PlanBillingPeriod = "monthly" | "semiannual" | "annual";
|
|
6
12
|
|
|
7
13
|
const BASE_FEATURES: PlanFeature[] = [
|
|
8
|
-
{ icon:
|
|
9
|
-
{ icon:
|
|
10
|
-
{ icon:
|
|
11
|
-
{ icon:
|
|
12
|
-
{ icon:
|
|
13
|
-
{ icon:
|
|
14
|
+
{ icon: "check", text: "Visitas ilimitadas" },
|
|
15
|
+
{ icon: "check", text: "Leads ilimitadas" },
|
|
16
|
+
{ icon: "check", text: "Compartilhar páginas", tooltip: "sharePages" },
|
|
17
|
+
{ icon: "check", text: "Hospedagem inclusa" },
|
|
18
|
+
{ icon: "check", text: "SSL (HTTPS) + CDN" },
|
|
19
|
+
{ icon: "check", text: "Templates Free" },
|
|
14
20
|
];
|
|
15
21
|
|
|
16
|
-
function buildMainFeaturesFromItems(items: Plan[
|
|
22
|
+
function buildMainFeaturesFromItems(items: Plan["items"]): PlanMainFeatures {
|
|
17
23
|
const pagesItem = items.find((i) => i.id_addon === ADDON_IDS.PAGES);
|
|
18
24
|
const domainsItem = items.find((i) => i.id_addon === ADDON_IDS.DOMAINS);
|
|
19
25
|
|
|
@@ -23,17 +29,17 @@ function buildMainFeaturesFromItems(items: Plan['items']): PlanMainFeatures {
|
|
|
23
29
|
return {
|
|
24
30
|
pages:
|
|
25
31
|
pagesQty === 0
|
|
26
|
-
?
|
|
32
|
+
? "Páginas ilimitadas"
|
|
27
33
|
: pagesQty === 1
|
|
28
|
-
?
|
|
34
|
+
? "1 página"
|
|
29
35
|
: `${pagesQty} páginas`,
|
|
30
36
|
domains:
|
|
31
37
|
domainsQty >= 999
|
|
32
|
-
?
|
|
38
|
+
? "Domínios ilimitados"
|
|
33
39
|
: domainsQty === 1
|
|
34
|
-
?
|
|
40
|
+
? "1 domínio externo"
|
|
35
41
|
: `${domainsQty} domínios externos`,
|
|
36
|
-
users:
|
|
42
|
+
users: "Usuários ilimitados",
|
|
37
43
|
};
|
|
38
44
|
}
|
|
39
45
|
|
|
@@ -47,43 +53,46 @@ function computePricingByPeriod(apiPlan: Plan): PlanPricingByPeriod {
|
|
|
47
53
|
};
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
export function mapApiPlanToUiPlan(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
planId: number;
|
|
54
|
-
isPopular?: boolean;
|
|
55
|
-
buttonVariant?: 'brand' | 'default';
|
|
56
|
-
}
|
|
57
|
-
): UiPlan {
|
|
58
|
-
const { planId, isPopular, buttonVariant } = options;
|
|
56
|
+
export function mapApiPlanToUiPlan(plan: Plan): UiPlan {
|
|
57
|
+
const popular = plan.id === 2 || plan.id_plan === 2;
|
|
58
|
+
const buttonVariant = popular ? "brand" : "default";
|
|
59
59
|
|
|
60
|
-
const pricingByPeriod = computePricingByPeriod(
|
|
60
|
+
const pricingByPeriod = computePricingByPeriod(plan);
|
|
61
61
|
const monthlyFinal = pricingByPeriod.monthly;
|
|
62
62
|
|
|
63
|
-
const lowerName =
|
|
63
|
+
const lowerName = plan.name.toLowerCase();
|
|
64
64
|
const hasProjectAndOnboarding =
|
|
65
|
-
lowerName.includes(
|
|
65
|
+
lowerName.includes("agência") || lowerName.includes("agencia");
|
|
66
66
|
|
|
67
67
|
const features: PlanFeature[] = [
|
|
68
68
|
...BASE_FEATURES,
|
|
69
69
|
hasProjectAndOnboarding
|
|
70
|
-
? { icon:
|
|
71
|
-
: { icon:
|
|
70
|
+
? { icon: "check", text: "Reunião de Onboarding" }
|
|
71
|
+
: { icon: "x", text: "Reunião de Onboarding", disabled: true },
|
|
72
72
|
hasProjectAndOnboarding
|
|
73
|
-
? {
|
|
74
|
-
|
|
73
|
+
? {
|
|
74
|
+
icon: "check",
|
|
75
|
+
text: "Gestão de projetos",
|
|
76
|
+
tooltip: "projectManagement",
|
|
77
|
+
}
|
|
78
|
+
: {
|
|
79
|
+
icon: "x",
|
|
80
|
+
text: "Gestão de projetos",
|
|
81
|
+
disabled: true,
|
|
82
|
+
tooltip: "projectManagement",
|
|
83
|
+
},
|
|
75
84
|
];
|
|
76
85
|
|
|
77
86
|
return {
|
|
78
|
-
|
|
79
|
-
name:
|
|
80
|
-
isPopular,
|
|
87
|
+
planId: plan.id,
|
|
88
|
+
name: plan.name,
|
|
89
|
+
isPopular: popular,
|
|
81
90
|
buttonVariant,
|
|
82
|
-
mainFeatures: buildMainFeaturesFromItems(
|
|
91
|
+
mainFeatures: buildMainFeaturesFromItems(plan.items),
|
|
83
92
|
features,
|
|
84
93
|
originalPrice: formatCurrencyNumber(monthlyFinal),
|
|
85
94
|
price: formatCurrencyNumber(monthlyFinal),
|
|
86
95
|
pricingByPeriod,
|
|
87
|
-
items:
|
|
96
|
+
items: plan.items,
|
|
88
97
|
};
|
|
89
98
|
}
|