@greatapps/common 1.1.363 → 1.1.364
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/sections/ChangeEmailModal.mjs +1 -1
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs +2 -1
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/pages/notifications/Notifications.mjs +1 -1
- package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
- package/dist/components/ui/buttons/Button.mjs +1 -1
- package/dist/components/ui/buttons/Button.mjs.map +1 -1
- package/dist/components/ui/feedback/Toast.mjs +1 -1
- package/dist/components/ui/feedback/Toast.mjs.map +1 -1
- package/dist/components/widgets/notifications/NotificationCard.mjs +1 -1
- package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs +9 -0
- package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
- package/dist/store/useDesktopSidebarStore.mjs +18 -7
- package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/layouts/NavBar.tsx +2 -1
- package/src/components/navigation/ProjectSelectorPopover.tsx +13 -14
- package/src/store/useDesktopSidebarStore.ts +21 -8
|
@@ -92,7 +92,7 @@ function ChangeEmailModal({ open, onClose }) {
|
|
|
92
92
|
)
|
|
93
93
|
] })
|
|
94
94
|
] }),
|
|
95
|
-
/* @__PURE__ */ jsx("div", { className: `${showVerification ? "w-full" : "w-1/2"} h-0.75 bg-
|
|
95
|
+
/* @__PURE__ */ jsx("div", { className: `${showVerification ? "w-full" : "w-1/2"} h-0.75 bg-pages-300` }),
|
|
96
96
|
showVerification ? /* @__PURE__ */ jsxs(
|
|
97
97
|
"form",
|
|
98
98
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/sections/ChangeEmailModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconChevronLeft, IconX, IconMail } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/form/InputOtp';\nimport { FormField } from '../../ui/form/FormField';\nimport { formatTimer } from '../../../utils/format/masks';\nimport { OTP_CODE_LENGTH } from '../../../utils/validators/account';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';\nimport { confirmEmailChangeAction } from '../../../modules/accounts/actions/account-management.action';\nimport useChangeEmailForm from '../hooks/useChangeEmailForm';\nimport useOtpVerification from '../hooks/useOtpVerification';\n\ninterface ChangeEmailModalProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {\n const { user } = useAuth();\n const invalidateUser = useInvalidateUser();\n\n const {\n showVerification,\n emailToVerify,\n isSubmitting,\n errors,\n register,\n handleContinue,\n handleBack,\n resetForm,\n } = useChangeEmailForm();\n\n const handleSuccess = () => {\n invalidateUser();\n resetForm();\n onClose();\n };\n\n const {\n code,\n isLoading,\n hasError,\n timer,\n canResend,\n isValidLength,\n handleCodeChange,\n handleValidate,\n handleResend,\n reset: resetOtp,\n } = useOtpVerification({\n onSuccess: handleSuccess,\n successMessage: 'E-mail alterado com sucesso',\n validateFn: async (token) => {\n const result = await confirmEmailChangeAction(token, emailToVerify);\n return result.success;\n },\n resendFn: async () => {\n const { requestEmailChangeAction } = await import('../../../modules/accounts/actions/account-management.action');\n const result = await requestEmailChangeAction(emailToVerify);\n if (!result.success) {\n throw new Error(result.error);\n }\n },\n });\n\n const handleClose = () => {\n resetForm();\n resetOtp();\n onClose();\n };\n\n const handleBackFromVerification = () => {\n resetOtp();\n handleBack();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n overlayClassName=\"z-[1002]\"\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-125 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] z-[1003]\"\n >\n {showVerification ? (\n <DialogHeader className=\"flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0\">\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleBackFromVerification}>\n <IconChevronLeft size={20} className=\"text-gray-950\" />\n </Button>\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950 text-center flex-1\">\n Alterar e-mail\n </DialogTitle>\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleClose}>\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </DialogHeader>\n ) : (\n <>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Alterar e-mail</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n Alterar e-mail\n </span>\n <Button\n variant=\"ghost\"\n className=\"absolute right-2 size-8! p-0\"\n onClick={handleClose}\n >\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </div>\n </>\n )}\n\n <div className={`${showVerification ? 'w-full' : 'w-1/2'} h-0.75 bg-cyan-300`} />\n\n {showVerification ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleValidate();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200\">\n <IconMail size={20} className=\"text-gray-950\" />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"paragraph-medium-semibold text-gray-950\">Código de validação</h3>\n <p className=\"paragraph-small-regular text-gray-600\">\n Enviamos um código de validação para o E-mail{' '}\n <span className=\"font-semibold text-gray-950 break-all\">{user?.email}.</span>\n </p>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <InputOTP maxLength={OTP_CODE_LENGTH} value={code} onChange={handleCodeChange}>\n <InputOTPGroup className=\"flex flex-row gap-2\">\n {[...Array(OTP_CODE_LENGTH)].map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className={`uppercase text-2xl font-medium w-11 lg:w-12 h-13 lg:h-14 rounded-lg border bg-white shadow-none [&_div.animate-caret-blink]:bg-gray-950 ${hasError ? 'border-red-500' : 'border-gray-200'}`}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {hasError && (\n <p className=\"paragraph-small-regular text-red-500\">Código incorreto</p>\n )}\n </div>\n\n {canResend ? (\n <button\n type=\"button\"\n onClick={handleResend}\n className=\"paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit\"\n >\n Reenviar código\n </button>\n ) : (\n <p className=\"paragraph-small-regular text-gray-500\">\n Reenviar em{' '}\n <span className=\"paragraph-small-semibold text-gray-950\">\n {formatTimer(timer)}\n </span>\n </p>\n )}\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={!isValidLength || isLoading}>\n {isLoading ? 'Validando...' : 'Alterar e-mail'}\n </Button>\n </div>\n </form>\n ) : (\n <form onSubmit={handleContinue} className=\"flex flex-col flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n Atualizar E-mail de contato\n </span>\n <span className=\"paragraph-small-regular text-gray-600\">\n Informe o seu novo E-mail para manter seu contato atualizado.\n </span>\n </div>\n\n <FormField\n label=\"Novo e-mail\"\n placeholder=\"Digite seu novo e-mail\"\n type=\"email\"\n {...register('email')}\n error={!!errors.email}\n errorMessage={errors.email?.message}\n leftIcon={IconMail}\n />\n </div>\n\n <div className=\"flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? 'Enviando...' : 'Continuar'}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/sections/ChangeEmailModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconChevronLeft, IconX, IconMail } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/form/InputOtp';\nimport { FormField } from '../../ui/form/FormField';\nimport { formatTimer } from '../../../utils/format/masks';\nimport { OTP_CODE_LENGTH } from '../../../utils/validators/account';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';\nimport { confirmEmailChangeAction } from '../../../modules/accounts/actions/account-management.action';\nimport useChangeEmailForm from '../hooks/useChangeEmailForm';\nimport useOtpVerification from '../hooks/useOtpVerification';\n\ninterface ChangeEmailModalProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ChangeEmailModal({ open, onClose }: ChangeEmailModalProps) {\n const { user } = useAuth();\n const invalidateUser = useInvalidateUser();\n\n const {\n showVerification,\n emailToVerify,\n isSubmitting,\n errors,\n register,\n handleContinue,\n handleBack,\n resetForm,\n } = useChangeEmailForm();\n\n const handleSuccess = () => {\n invalidateUser();\n resetForm();\n onClose();\n };\n\n const {\n code,\n isLoading,\n hasError,\n timer,\n canResend,\n isValidLength,\n handleCodeChange,\n handleValidate,\n handleResend,\n reset: resetOtp,\n } = useOtpVerification({\n onSuccess: handleSuccess,\n successMessage: 'E-mail alterado com sucesso',\n validateFn: async (token) => {\n const result = await confirmEmailChangeAction(token, emailToVerify);\n return result.success;\n },\n resendFn: async () => {\n const { requestEmailChangeAction } = await import('../../../modules/accounts/actions/account-management.action');\n const result = await requestEmailChangeAction(emailToVerify);\n if (!result.success) {\n throw new Error(result.error);\n }\n },\n });\n\n const handleClose = () => {\n resetForm();\n resetOtp();\n onClose();\n };\n\n const handleBackFromVerification = () => {\n resetOtp();\n handleBack();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n overlayClassName=\"z-[1002]\"\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-125 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] z-[1003]\"\n >\n {showVerification ? (\n <DialogHeader className=\"flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0\">\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleBackFromVerification}>\n <IconChevronLeft size={20} className=\"text-gray-950\" />\n </Button>\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950 text-center flex-1\">\n Alterar e-mail\n </DialogTitle>\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleClose}>\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </DialogHeader>\n ) : (\n <>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>Alterar e-mail</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n Alterar e-mail\n </span>\n <Button\n variant=\"ghost\"\n className=\"absolute right-2 size-8! p-0\"\n onClick={handleClose}\n >\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </div>\n </>\n )}\n\n <div className={`${showVerification ? 'w-full' : 'w-1/2'} h-0.75 bg-pages-300`} />\n\n {showVerification ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleValidate();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200\">\n <IconMail size={20} className=\"text-gray-950\" />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"paragraph-medium-semibold text-gray-950\">Código de validação</h3>\n <p className=\"paragraph-small-regular text-gray-600\">\n Enviamos um código de validação para o E-mail{' '}\n <span className=\"font-semibold text-gray-950 break-all\">{user?.email}.</span>\n </p>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <InputOTP maxLength={OTP_CODE_LENGTH} value={code} onChange={handleCodeChange}>\n <InputOTPGroup className=\"flex flex-row gap-2\">\n {[...Array(OTP_CODE_LENGTH)].map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className={`uppercase text-2xl font-medium w-11 lg:w-12 h-13 lg:h-14 rounded-lg border bg-white shadow-none [&_div.animate-caret-blink]:bg-gray-950 ${hasError ? 'border-red-500' : 'border-gray-200'}`}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {hasError && (\n <p className=\"paragraph-small-regular text-red-500\">Código incorreto</p>\n )}\n </div>\n\n {canResend ? (\n <button\n type=\"button\"\n onClick={handleResend}\n className=\"paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit\"\n >\n Reenviar código\n </button>\n ) : (\n <p className=\"paragraph-small-regular text-gray-500\">\n Reenviar em{' '}\n <span className=\"paragraph-small-semibold text-gray-950\">\n {formatTimer(timer)}\n </span>\n </p>\n )}\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={!isValidLength || isLoading}>\n {isLoading ? 'Validando...' : 'Alterar e-mail'}\n </Button>\n </div>\n </form>\n ) : (\n <form onSubmit={handleContinue} className=\"flex flex-col flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n Atualizar E-mail de contato\n </span>\n <span className=\"paragraph-small-regular text-gray-600\">\n Informe o seu novo E-mail para manter seu contato atualizado.\n </span>\n </div>\n\n <FormField\n label=\"Novo e-mail\"\n placeholder=\"Digite seu novo e-mail\"\n type=\"email\"\n {...register('email')}\n error={!!errors.email}\n errorMessage={errors.email?.message}\n leftIcon={IconMail}\n />\n </div>\n\n <div className=\"flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? 'Enviando...' : 'Continuar'}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -104,7 +104,7 @@ function ChangePhoneModal({ open, onClose }) {
|
|
|
104
104
|
)
|
|
105
105
|
] })
|
|
106
106
|
] }),
|
|
107
|
-
/* @__PURE__ */ jsx("div", { className: `${showVerification || !hasExistingPhone ? "w-full" : "w-1/2"} h-0.75 bg-
|
|
107
|
+
/* @__PURE__ */ jsx("div", { className: `${showVerification || !hasExistingPhone ? "w-full" : "w-1/2"} h-0.75 bg-pages-300` }),
|
|
108
108
|
showVerification ? /* @__PURE__ */ jsxs(
|
|
109
109
|
"form",
|
|
110
110
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/account/sections/ChangePhoneModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconChevronLeft, IconX, IconMessage } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/form/InputOtp';\nimport PhoneInput from '../../ui/form/PhoneInput';\nimport { formatTimer, formatPhone } from '../../../utils/format/masks';\nimport { OTP_CODE_LENGTH } from '../../../utils/validators/account';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';\nimport { confirmPhoneChangeAction } from '../../../modules/accounts/actions/account-management.action';\nimport useChangePhoneForm from '../hooks/useChangePhoneForm';\nimport useOtpVerification from '../hooks/useOtpVerification';\n\ninterface ChangePhoneModalProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {\n const { user } = useAuth();\n const invalidateUser = useInvalidateUser();\n\n const hasExistingPhone = !!user?.phone;\n\n const currentPhoneDisplay = user?.phone\n ? formatPhone(\n user.ddi && user.phone.startsWith(user.ddi) ? user.phone.slice(user.ddi.length) : user.phone\n )\n : '';\n\n const handleDirectUpdateSuccess = () => {\n invalidateUser();\n onClose();\n };\n\n const {\n showVerification,\n phoneValue,\n phoneError,\n isSubmitting,\n submittedPhone,\n handlePhoneChange,\n handleContinue,\n handleBack,\n resetForm,\n } = useChangePhoneForm({\n hasExistingPhone,\n onDirectUpdateSuccess: handleDirectUpdateSuccess,\n });\n\n const handleSuccess = () => {\n invalidateUser();\n resetForm();\n onClose();\n };\n\n const {\n code,\n isLoading,\n hasError,\n timer,\n canResend,\n isValidLength,\n handleCodeChange,\n handleValidate,\n handleResend,\n reset: resetOtp,\n } = useOtpVerification({\n onSuccess: handleSuccess,\n successMessage: 'Telefone alterado',\n validateFn: async (token) => {\n const result = await confirmPhoneChangeAction(token, submittedPhone.local, submittedPhone.ddi);\n return result.success;\n },\n resendFn: async () => {\n const { requestPhoneChangeAction } = await import('../../../modules/accounts/actions/account-management.action');\n const result = await requestPhoneChangeAction(submittedPhone.local, submittedPhone.ddi);\n if (!result.success) {\n throw new Error(result.error);\n }\n },\n });\n\n const handleClose = () => {\n resetForm();\n resetOtp();\n onClose();\n };\n\n const handleBackFromVerification = () => {\n resetOtp();\n handleBack();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n overlayClassName=\"z-[1002]\"\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-125 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] z-[1003]\"\n >\n {showVerification ? (\n <DialogHeader className=\"flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0\">\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleBackFromVerification}>\n <IconChevronLeft size={20} className=\"text-gray-950\" />\n </Button>\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950 text-center flex-1\">\n Alterar telefone\n </DialogTitle>\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleClose}>\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </DialogHeader>\n ) : (\n <>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{hasExistingPhone ? 'Alterar telefone' : 'Adicionar telefone'}</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {hasExistingPhone ? 'Alterar telefone' : 'Adicionar telefone'}\n </span>\n <Button\n variant=\"ghost\"\n className=\"absolute right-2 size-8! p-0\"\n onClick={handleClose}\n >\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </div>\n </>\n )}\n\n <div className={`${showVerification || !hasExistingPhone ? 'w-full' : 'w-1/2'} h-0.75 bg-cyan-300`} />\n\n {showVerification ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleValidate();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200\">\n <IconMessage size={20} className=\"text-gray-950\" />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"paragraph-medium-semibold text-gray-950\">Código de validação</h3>\n <p className=\"paragraph-small-regular text-gray-600\">\n Enviamos um código de validação para o número atual{' '}\n <span className=\"font-semibold text-gray-950\">{currentPhoneDisplay}.</span>\n </p>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <InputOTP maxLength={OTP_CODE_LENGTH} value={code} onChange={handleCodeChange}>\n <InputOTPGroup className=\"flex flex-row gap-2\">\n {[...Array(OTP_CODE_LENGTH)].map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className={`uppercase text-2xl font-medium w-11 lg:w-12 h-13 lg:h-14 rounded-lg border bg-white shadow-none [&_div.animate-caret-blink]:bg-gray-950 ${hasError ? 'border-red-500' : 'border-gray-200'}`}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {hasError && (\n <p className=\"paragraph-small-regular text-red-500\">Código incorreto</p>\n )}\n </div>\n\n {canResend ? (\n <button\n type=\"button\"\n onClick={handleResend}\n className=\"paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit\"\n >\n Reenviar código\n </button>\n ) : (\n <p className=\"paragraph-small-regular text-gray-500\">\n Reenviar em{' '}\n <span className=\"paragraph-small-semibold text-gray-950\">\n {formatTimer(timer)}\n </span>\n </p>\n )}\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={!isValidLength || isLoading}>\n {isLoading ? 'Validando...' : 'Alterar telefone'}\n </Button>\n </div>\n </form>\n ) : (\n <form onSubmit={handleContinue} className=\"flex flex-col flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n {hasExistingPhone ? 'Atualizar telefone de contato' : 'Adicionar telefone de contato'}\n </span>\n <span className=\"paragraph-small-regular text-gray-600\">\n {hasExistingPhone\n ? 'Informe o novo número para manter seu contato atualizado.'\n : 'Informe seu número de telefone para contato.'}\n </span>\n </div>\n\n <PhoneInput\n label={hasExistingPhone ? 'Novo número' : 'Número de telefone'}\n placeholder=\"(00) 0 0000-0000\"\n value={phoneValue}\n onChange={handlePhoneChange}\n error={!!phoneError}\n errorMessage={phoneError}\n />\n </div>\n\n <div className=\"flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting\n ? (hasExistingPhone ? 'Enviando...' : 'Salvando...')\n : (hasExistingPhone ? 'Continuar' : 'Salvar')}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/account/sections/ChangePhoneModal.tsx"],"sourcesContent":["'use client';\n\nimport { IconChevronLeft, IconX, IconMessage } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { InputOTP, InputOTPGroup, InputOTPSlot } from '../../ui/form/InputOtp';\nimport PhoneInput from '../../ui/form/PhoneInput';\nimport { formatTimer, formatPhone } from '../../../utils/format/masks';\nimport { OTP_CODE_LENGTH } from '../../../utils/validators/account';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { useInvalidateUser } from '../../../modules/auth/hooks/useUserQuery';\nimport { confirmPhoneChangeAction } from '../../../modules/accounts/actions/account-management.action';\nimport useChangePhoneForm from '../hooks/useChangePhoneForm';\nimport useOtpVerification from '../hooks/useOtpVerification';\n\ninterface ChangePhoneModalProps {\n open: boolean;\n onClose: () => void;\n}\n\nexport function ChangePhoneModal({ open, onClose }: ChangePhoneModalProps) {\n const { user } = useAuth();\n const invalidateUser = useInvalidateUser();\n\n const hasExistingPhone = !!user?.phone;\n\n const currentPhoneDisplay = user?.phone\n ? formatPhone(\n user.ddi && user.phone.startsWith(user.ddi) ? user.phone.slice(user.ddi.length) : user.phone\n )\n : '';\n\n const handleDirectUpdateSuccess = () => {\n invalidateUser();\n onClose();\n };\n\n const {\n showVerification,\n phoneValue,\n phoneError,\n isSubmitting,\n submittedPhone,\n handlePhoneChange,\n handleContinue,\n handleBack,\n resetForm,\n } = useChangePhoneForm({\n hasExistingPhone,\n onDirectUpdateSuccess: handleDirectUpdateSuccess,\n });\n\n const handleSuccess = () => {\n invalidateUser();\n resetForm();\n onClose();\n };\n\n const {\n code,\n isLoading,\n hasError,\n timer,\n canResend,\n isValidLength,\n handleCodeChange,\n handleValidate,\n handleResend,\n reset: resetOtp,\n } = useOtpVerification({\n onSuccess: handleSuccess,\n successMessage: 'Telefone alterado',\n validateFn: async (token) => {\n const result = await confirmPhoneChangeAction(token, submittedPhone.local, submittedPhone.ddi);\n return result.success;\n },\n resendFn: async () => {\n const { requestPhoneChangeAction } = await import('../../../modules/accounts/actions/account-management.action');\n const result = await requestPhoneChangeAction(submittedPhone.local, submittedPhone.ddi);\n if (!result.success) {\n throw new Error(result.error);\n }\n },\n });\n\n const handleClose = () => {\n resetForm();\n resetOtp();\n onClose();\n };\n\n const handleBackFromVerification = () => {\n resetOtp();\n handleBack();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n overlayClassName=\"z-[1002]\"\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-125 lg:h-auto lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] z-[1003]\"\n >\n {showVerification ? (\n <DialogHeader className=\"flex flex-row items-center justify-between px-4 py-3 border-b border-gray-200 lg:border-b-0\">\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleBackFromVerification}>\n <IconChevronLeft size={20} className=\"text-gray-950\" />\n </Button>\n <DialogTitle className=\"paragraph-medium-semibold text-gray-950 text-center flex-1\">\n Alterar telefone\n </DialogTitle>\n <Button variant=\"ghost\" className=\"size-8! p-0\" onClick={handleClose}>\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </DialogHeader>\n ) : (\n <>\n <DialogHeader className=\"sr-only\">\n <DialogTitle>{hasExistingPhone ? 'Alterar telefone' : 'Adicionar telefone'}</DialogTitle>\n </DialogHeader>\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-gray-200 lg:border-b-0\">\n <span className=\"paragraph-medium-semibold text-gray-950 text-center\">\n {hasExistingPhone ? 'Alterar telefone' : 'Adicionar telefone'}\n </span>\n <Button\n variant=\"ghost\"\n className=\"absolute right-2 size-8! p-0\"\n onClick={handleClose}\n >\n <IconX size={18} className=\"text-gray-500\" />\n </Button>\n </div>\n </>\n )}\n\n <div className={`${showVerification || !hasExistingPhone ? 'w-full' : 'w-1/2'} h-0.75 bg-pages-300`} />\n\n {showVerification ? (\n <form\n onSubmit={(e) => {\n e.preventDefault();\n handleValidate();\n }}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"px-4 lg:px-5 py-5 lg:py-6 flex flex-col gap-4 flex-1 lg:flex-none\">\n <div className=\"flex items-center justify-center size-12 bg-white rounded-lg shadow-xs border border-gray-200\">\n <IconMessage size={20} className=\"text-gray-950\" />\n </div>\n\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"paragraph-medium-semibold text-gray-950\">Código de validação</h3>\n <p className=\"paragraph-small-regular text-gray-600\">\n Enviamos um código de validação para o número atual{' '}\n <span className=\"font-semibold text-gray-950\">{currentPhoneDisplay}.</span>\n </p>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <InputOTP maxLength={OTP_CODE_LENGTH} value={code} onChange={handleCodeChange}>\n <InputOTPGroup className=\"flex flex-row gap-2\">\n {[...Array(OTP_CODE_LENGTH)].map((_, i) => (\n <InputOTPSlot\n key={i}\n index={i}\n className={`uppercase text-2xl font-medium w-11 lg:w-12 h-13 lg:h-14 rounded-lg border bg-white shadow-none [&_div.animate-caret-blink]:bg-gray-950 ${hasError ? 'border-red-500' : 'border-gray-200'}`}\n />\n ))}\n </InputOTPGroup>\n </InputOTP>\n {hasError && (\n <p className=\"paragraph-small-regular text-red-500\">Código incorreto</p>\n )}\n </div>\n\n {canResend ? (\n <button\n type=\"button\"\n onClick={handleResend}\n className=\"paragraph-small-medium text-gray-950 underline cursor-pointer hover:text-gray-700 w-fit\"\n >\n Reenviar código\n </button>\n ) : (\n <p className=\"paragraph-small-regular text-gray-500\">\n Reenviar em{' '}\n <span className=\"paragraph-small-semibold text-gray-950\">\n {formatTimer(timer)}\n </span>\n </p>\n )}\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between px-4 lg:px-5 py-4 lg:py-5 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={!isValidLength || isLoading}>\n {isLoading ? 'Validando...' : 'Alterar telefone'}\n </Button>\n </div>\n </form>\n ) : (\n <form onSubmit={handleContinue} className=\"flex flex-col flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-5 lg:gap-6 px-4 lg:px-5 py-5 lg:py-6 flex-1 lg:flex-none\">\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-medium-semibold text-gray-950\">\n {hasExistingPhone ? 'Atualizar telefone de contato' : 'Adicionar telefone de contato'}\n </span>\n <span className=\"paragraph-small-regular text-gray-600\">\n {hasExistingPhone\n ? 'Informe o novo número para manter seu contato atualizado.'\n : 'Informe seu número de telefone para contato.'}\n </span>\n </div>\n\n <PhoneInput\n label={hasExistingPhone ? 'Novo número' : 'Número de telefone'}\n placeholder=\"(00) 0 0000-0000\"\n value={phoneValue}\n onChange={handlePhoneChange}\n error={!!phoneError}\n errorMessage={phoneError}\n />\n </div>\n\n <div className=\"flex items-center justify-between p-4 lg:p-5 border-t border-gray-200 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" className=\"h-10!\" type=\"button\" onClick={handleClose}>\n Cancelar\n </Button>\n <Button className=\"h-10!\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting\n ? (hasExistingPhone ? 'Enviando...' : 'Salvando...')\n : (hasExistingPhone ? 'Continuar' : 'Salvar')}\n </Button>\n </div>\n </form>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,7 +4,7 @@ import Image from "next/image";
|
|
|
4
4
|
import { IconChevronRight } from "@tabler/icons-react";
|
|
5
5
|
import { Separator } from "../ui/data-display/Separator";
|
|
6
6
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
|
|
7
|
-
import { useDesktopSidebarStore } from "../../store/useDesktopSidebarStore";
|
|
7
|
+
import { useDesktopSidebarStore, useDesktopSidebarHydration } from "../../store/useDesktopSidebarStore";
|
|
8
8
|
import { useWhitelabel } from "../../providers/whitelabel.provider";
|
|
9
9
|
import { cn } from "../../infra/utils/clsx";
|
|
10
10
|
function NavBar({
|
|
@@ -17,6 +17,7 @@ function NavBar({
|
|
|
17
17
|
className
|
|
18
18
|
}) {
|
|
19
19
|
const { isExpanded: isDesktopExpanded, toggle: toggleDesktop } = useDesktopSidebarStore();
|
|
20
|
+
useDesktopSidebarHydration();
|
|
20
21
|
const { whitelabel } = useWhitelabel();
|
|
21
22
|
const isDefaultWl = !whitelabel || whitelabel.id === 1;
|
|
22
23
|
const primaryColor = whitelabel?.general?.primary_color;
|
|
@@ -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 { useDesktopSidebarStore } from \"../../store/useDesktopSidebarStore\";\nimport { useWhitelabel } from \"../../providers/whitelabel.provider\";\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 const { isExpanded: isDesktopExpanded, toggle: toggleDesktop } =\n useDesktopSidebarStore();\n const { whitelabel } = useWhitelabel();\n const isDefaultWl = !whitelabel || whitelabel.id === 1;\n const primaryColor = whitelabel?.general?.primary_color;\n const wlName = whitelabel?.name || 'Great';\n\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 {isDefaultWl ? (\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great Icon\"\n width={28}\n height={28}\n />\n ) : (\n <div\n className={cn(\"size-10 rounded-lg flex items-center justify-center transition-opacity duration-300\", activeApp !== \"gapps\" && \"opacity-20\")}\n style={{ backgroundColor: primaryColor }}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n <path d=\"M14 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n <path d=\"M4 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n <path d=\"M14 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n </svg>\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent side=\"right\">{wlName}</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 rounded-r-xl transition-opacity duration-300\",\n isDefaultWl ? \"bg-gray-950\" : \"\",\n activeApp === \"gapps\" ? \"opacity-100\" : \"opacity-0\",\n )}\n style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}\n />\n </div>\n\n <div className=\"relative w-full mt-[7.5px]\">\n <Separator />\n {/* Md expand button */}\n {showExpandButton && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={onExpandClick}\n className=\"hidden md:flex lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 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 {/* Desktop expand button */}\n {!isDesktopExpanded && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={toggleDesktop}\n className=\"hidden lg:flex absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 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 <div\n className={cn(\n \"size-10 rounded-lg cursor-pointer flex items-center justify-center border-2 ring-2 transition-colors duration-300\",\n activeApp === \"gpages\"\n ? isDefaultWl\n ? \"bg-cyan-100 border-white ring-cyan-300\"\n : \"border-white ring-transparent\"\n : isDefaultWl\n ? \"hover:bg-gray-100 border-transparent ring-transparent\"\n : \"border-transparent ring-transparent\",\n )}\n style={!isDefaultWl ? { backgroundColor: primaryColor, boxShadow: activeApp === \"gpages\" ? `0 0 0 2px ${primaryColor}40` : undefined, opacity: activeApp !== \"gpages\" ? 0.2 : undefined } : undefined}\n >\n {isDefaultWl ? (\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 8h16\" />\n <path d=\"M4 6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12\" />\n <path d=\"M8 4v4\" />\n </svg>\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"right\">{isDefaultWl ? 'GreatPages' : 'Páginas'}</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 rounded-r-xl transition-opacity duration-300\",\n isDefaultWl ? \"bg-cyan-300\" : \"\",\n activeApp === \"gpages\" ? \"opacity-100\" : \"opacity-0\",\n )}\n style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}\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":"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","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 { useDesktopSidebarStore, useDesktopSidebarHydration } from \"../../store/useDesktopSidebarStore\";\nimport { useWhitelabel } from \"../../providers/whitelabel.provider\";\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 const { isExpanded: isDesktopExpanded, toggle: toggleDesktop } =\n useDesktopSidebarStore();\n useDesktopSidebarHydration();\n const { whitelabel } = useWhitelabel();\n const isDefaultWl = !whitelabel || whitelabel.id === 1;\n const primaryColor = whitelabel?.general?.primary_color;\n const wlName = whitelabel?.name || 'Great';\n\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 {isDefaultWl ? (\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great Icon\"\n width={28}\n height={28}\n />\n ) : (\n <div\n className={cn(\"size-10 rounded-lg flex items-center justify-center transition-opacity duration-300\", activeApp !== \"gapps\" && \"opacity-20\")}\n style={{ backgroundColor: primaryColor }}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n <path d=\"M14 5a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n <path d=\"M4 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n <path d=\"M14 15a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v4a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1l0 -4\" />\n </svg>\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent side=\"right\">{wlName}</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 rounded-r-xl transition-opacity duration-300\",\n isDefaultWl ? \"bg-gray-950\" : \"\",\n activeApp === \"gapps\" ? \"opacity-100\" : \"opacity-0\",\n )}\n style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}\n />\n </div>\n\n <div className=\"relative w-full mt-[7.5px]\">\n <Separator />\n {/* Md expand button */}\n {showExpandButton && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={onExpandClick}\n className=\"hidden md:flex lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 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 {/* Desktop expand button */}\n {!isDesktopExpanded && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={toggleDesktop}\n className=\"hidden lg:flex absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 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 <div\n className={cn(\n \"size-10 rounded-lg cursor-pointer flex items-center justify-center border-2 ring-2 transition-colors duration-300\",\n activeApp === \"gpages\"\n ? isDefaultWl\n ? \"bg-cyan-100 border-white ring-cyan-300\"\n : \"border-white ring-transparent\"\n : isDefaultWl\n ? \"hover:bg-gray-100 border-transparent ring-transparent\"\n : \"border-transparent ring-transparent\",\n )}\n style={!isDefaultWl ? { backgroundColor: primaryColor, boxShadow: activeApp === \"gpages\" ? `0 0 0 2px ${primaryColor}40` : undefined, opacity: activeApp !== \"gpages\" ? 0.2 : undefined } : undefined}\n >\n {isDefaultWl ? (\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 8h16\" />\n <path d=\"M4 6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12\" />\n <path d=\"M8 4v4\" />\n </svg>\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"right\">{isDefaultWl ? 'GreatPages' : 'Páginas'}</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 rounded-r-xl transition-opacity duration-300\",\n isDefaultWl ? \"bg-cyan-300\" : \"\",\n activeApp === \"gpages\" ? \"opacity-100\" : \"opacity-0\",\n )}\n style={!isDefaultWl ? { backgroundColor: primaryColor } : undefined}\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":"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","names":[]}
|
|
@@ -39,7 +39,7 @@ function NotificationsList({
|
|
|
39
39
|
NotificationCard,
|
|
40
40
|
{
|
|
41
41
|
icon: /* @__PURE__ */ jsx(IconBell, { size: 20, className: "text-pages-600" }),
|
|
42
|
-
iconBgColor: "bg-
|
|
42
|
+
iconBgColor: "bg-pages-100",
|
|
43
43
|
title: notification.subject,
|
|
44
44
|
description: notification.message,
|
|
45
45
|
gapPx: 8,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/pages/notifications/Notifications.tsx"],"sourcesContent":["'use client';\n\nimport { IconBell, IconCheck, IconLoader2 } from '@tabler/icons-react';\nimport { Button } from \"../../ui/buttons/Button\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../ui/data-display/Tabs\";\nimport { useInfiniteMessages, useMarkAllMessagesAsRead } from \"../../../modules/users/hooks/messages.hook\";\nimport NotificationCard from \"../../widgets/notifications/NotificationCard\";\nimport { Toast } from \"../../ui/feedback/Toast\";\nimport { formatDistanceToNow } from \"date-fns\";\nimport { ptBR } from \"date-fns/locale\";\nimport { toast } from \"sonner\";\nimport React from \"react\";\n\nfunction NotificationsList({\n pages,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n}: {\n pages: ReturnType<typeof useInfiniteMessages>[\"data\"];\n isFetchingNextPage: boolean;\n hasNextPage: boolean;\n fetchNextPage: () => void;\n}) {\n const notifications = pages?.pages.flatMap((p) => p.data) ?? [];\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 (hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n };\n\n return (\n <div\n className=\"flex flex-col border border-gray-200 rounded-lg w-full bg-white max-h-[70vh] overflow-y-auto custom-scrollbar\"\n onScroll={handleScroll}\n >\n {notifications.map((notification, index) => (\n <NotificationCard\n key={notification.id}\n icon={<IconBell size={20} className=\"text-pages-600\" />}\n iconBgColor=\"bg-
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/pages/notifications/Notifications.tsx"],"sourcesContent":["'use client';\n\nimport { IconBell, IconCheck, IconLoader2 } from '@tabler/icons-react';\nimport { Button } from \"../../ui/buttons/Button\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../ui/data-display/Tabs\";\nimport { useInfiniteMessages, useMarkAllMessagesAsRead } from \"../../../modules/users/hooks/messages.hook\";\nimport NotificationCard from \"../../widgets/notifications/NotificationCard\";\nimport { Toast } from \"../../ui/feedback/Toast\";\nimport { formatDistanceToNow } from \"date-fns\";\nimport { ptBR } from \"date-fns/locale\";\nimport { toast } from \"sonner\";\nimport React from \"react\";\n\nfunction NotificationsList({\n pages,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n}: {\n pages: ReturnType<typeof useInfiniteMessages>[\"data\"];\n isFetchingNextPage: boolean;\n hasNextPage: boolean;\n fetchNextPage: () => void;\n}) {\n const notifications = pages?.pages.flatMap((p) => p.data) ?? [];\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 (hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n };\n\n return (\n <div\n className=\"flex flex-col border border-gray-200 rounded-lg w-full bg-white max-h-[70vh] overflow-y-auto custom-scrollbar\"\n onScroll={handleScroll}\n >\n {notifications.map((notification, index) => (\n <NotificationCard\n key={notification.id}\n icon={<IconBell size={20} className=\"text-pages-600\" />}\n iconBgColor=\"bg-pages-100\"\n title={notification.subject}\n description={notification.message}\n gapPx={8}\n time={formatDistanceToNow(new Date(notification.datetime_add), {\n addSuffix: true,\n locale: ptBR,\n })}\n isUnread={notification.status === 1}\n showBorder={index < notifications.length - 1}\n />\n ))}\n {isFetchingNextPage && (\n <div className=\"flex items-center justify-center py-4\">\n <IconLoader2 size={20} className=\"animate-spin text-gray-400\" />\n </div>\n )}\n </div>\n );\n}\n\nexport function NotificationPageContent() {\n const unreadNotifications = useInfiniteMessages({\n readed: false,\n type: \"notification\",\n order: \"desc\",\n });\n const allNotifications = useInfiniteMessages({\n type: \"notification\",\n order: \"desc\",\n });\n\n const totalAll = allNotifications.data?.pages[0]?.total ?? 0;\n const totalUnread = unreadNotifications.data?.pages[0]?.total ?? 0;\n\n const { mutate: markAllAsRead, isPending: isMarkingAll } = useMarkAllMessagesAsRead();\n\n const handleMarkAllAsRead = () => {\n markAllAsRead(undefined, {\n onSuccess: () => {\n toast.custom((t) => (\n <Toast variant=\"success\" message=\"Todas as notificações foram marcadas como lidas\" toastId={t} />\n ));\n },\n onError: () => {\n toast.custom((t) => (\n <Toast variant=\"error\" message=\"Erro ao marcar notificações como lidas\" toastId={t} />\n ));\n },\n });\n };\n\n return (\n <div className=\"flex flex-col gap-6 lg:gap-8\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"flex flex-col gap-2\">\n <h1 className=\"title-large-semibold text-gray-950\">\n Notificações\n </h1>\n <p className=\"paragraph-small-regular text-gray-600 hidden lg:block\">\n Tenha controle total sobre páginas, experiências e conversões.\n </p>\n </div>\n <Button\n variant={\"secondary\"}\n className=\"h-10! lg:h-12! shrink-0\"\n onClick={handleMarkAllAsRead}\n disabled={isMarkingAll || totalUnread === 0}\n >\n {isMarkingAll ? <IconLoader2 size={20} className=\"animate-spin\" /> : <IconCheck size={20} />}\n <span className=\"lg:block hidden\">Marcar todos como lidos</span>\n <span className=\"lg:hidden\">Marcar como lidos</span>\n </Button>\n </div>\n <Tabs\n defaultValue=\"all\"\n className=\"flex flex-col w-full bg-transparent gap-6 lg:gap-8\"\n >\n <TabsList className=\"h-auto pb-0 bg-transparent\">\n <TabsTrigger className=\"gap-2\" value=\"all\">\n Todas as notificações{\" \"}\n <span className=\"text-gray-500\">({totalAll})</span>\n </TabsTrigger>\n <TabsTrigger className=\"gap-2\" value=\"unreads\" disabled={totalUnread === 0}>\n Não lidas{\" \"}\n <span className=\"text-gray-500\">({totalUnread})</span>\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"all\">\n <NotificationsList\n pages={allNotifications.data}\n isFetchingNextPage={allNotifications.isFetchingNextPage}\n hasNextPage={allNotifications.hasNextPage}\n fetchNextPage={allNotifications.fetchNextPage}\n />\n </TabsContent>\n\n <TabsContent value=\"unreads\">\n <NotificationsList\n pages={unreadNotifications.data}\n isFetchingNextPage={unreadNotifications.isFetchingNextPage}\n hasNextPage={unreadNotifications.hasNextPage}\n fetchNextPage={unreadNotifications.fetchNextPage}\n />\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -11,7 +11,7 @@ const buttonVariants = cva(
|
|
|
11
11
|
default: " bg-gray-950 text-white hover:bg-gray-950/90",
|
|
12
12
|
secondary: "bg-white text-gray-950 border-gray-200 hover:border-gray-400 border",
|
|
13
13
|
ghost: "text-gray-600 hover:bg-accent hover:text-gray-950 dark:hover:bg-accent/50",
|
|
14
|
-
brand: "bg-
|
|
14
|
+
brand: "bg-pages-300 hover:bg-pages-200 text-gray-950"
|
|
15
15
|
},
|
|
16
16
|
size: {
|
|
17
17
|
default: "h-12 px-4 py-2 has-[>svg]:px-3",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ui/buttons/Button.tsx"],"sourcesContent":["'use client';\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../../infra/utils/clsx\"\n\nconst buttonVariants = cva(\n \"paragraph-small-semibold cursor-pointer flex items-center justify-center gap-1.5 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \" bg-gray-950 text-white hover:bg-gray-950/90\",\n secondary:\n \"bg-white text-gray-950 border-gray-200 hover:border-gray-400 border\",\n ghost:\n \"text-gray-600 hover:bg-accent hover:text-gray-950 dark:hover:bg-accent/50\",\n brand: \"bg-
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/buttons/Button.tsx"],"sourcesContent":["'use client';\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"../../../infra/utils/clsx\"\n\nconst buttonVariants = cva(\n \"paragraph-small-semibold cursor-pointer flex items-center justify-center gap-1.5 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \" bg-gray-950 text-white hover:bg-gray-950/90\",\n secondary:\n \"bg-white text-gray-950 border-gray-200 hover:border-gray-400 border\",\n ghost:\n \"text-gray-600 hover:bg-accent hover:text-gray-950 dark:hover:bg-accent/50\",\n brand: \"bg-pages-300 hover:bg-pages-200 text-gray-950\",\n },\n size: {\n default: \"h-12 px-4 py-2 has-[>svg]:px-3\",\n sm: \"rounded-md gap-1.5 px-2 py-2 has-[>svg]:px-2.5\",\n lg: \"rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant,\n size,\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n"],"mappings":";AAgDI;AA7CJ,SAAS,YAAY;AACrB,SAAS,WAA8B;AACvC,SAAS,UAAU;AAEnB,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,WACE;AAAA,QACF,OACE;AAAA,QACF,OAAO;AAAA,MACT;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,WAAW;AAAA,QACX,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,GAAG;AACL,GAGK;AACH,QAAM,OAAO,UAAU,OAAO;AAE9B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,eAAe,EAAE,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,MACzD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
@@ -30,7 +30,7 @@ const toastIconContainerVariants = cva(
|
|
|
30
30
|
success: "bg-green-50 text-green-500",
|
|
31
31
|
error: "bg-red-50 text-red-500",
|
|
32
32
|
warning: "bg-yellow-50 text-yellow-400",
|
|
33
|
-
info: "bg-
|
|
33
|
+
info: "bg-pages-50 text-pages-500",
|
|
34
34
|
default: "bg-gray-50 text-gray-950"
|
|
35
35
|
}
|
|
36
36
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ui/feedback/Toast.tsx"],"sourcesContent":["'use client';\n\n\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { IconCircleCheck, IconCircleX, IconAlertCircle, IconInfoCircle, IconCircle, IconX } from \"@tabler/icons-react\"\nimport { toast } from \"sonner\"\nimport { cn } from \"../../../infra/utils/clsx\"\nimport { Button } from \"../buttons/Button\"\n\nconst toastVariants = cva(\n \"w-full bg-white rounded-lg p-4 shadow-lg backdrop-blur-sm transition-all\",\n {\n variants: {\n variant: {\n success: \"\",\n error: \"\",\n warning: \"\",\n info: \"\",\n default: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nconst toastIconContainerVariants = cva(\n \"size-10 rounded-lg flex items-center justify-center shrink-0\",\n {\n variants: {\n variant: {\n success: \"bg-green-50 text-green-500\",\n error: \"bg-red-50 text-red-500\",\n warning: \"bg-yellow-50 text-yellow-400\",\n info: \"bg-
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/feedback/Toast.tsx"],"sourcesContent":["'use client';\n\n\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { IconCircleCheck, IconCircleX, IconAlertCircle, IconInfoCircle, IconCircle, IconX } from \"@tabler/icons-react\"\nimport { toast } from \"sonner\"\nimport { cn } from \"../../../infra/utils/clsx\"\nimport { Button } from \"../buttons/Button\"\n\nconst toastVariants = cva(\n \"w-full bg-white rounded-lg p-4 shadow-lg backdrop-blur-sm transition-all\",\n {\n variants: {\n variant: {\n success: \"\",\n error: \"\",\n warning: \"\",\n info: \"\",\n default: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nconst toastIconContainerVariants = cva(\n \"size-10 rounded-lg flex items-center justify-center shrink-0\",\n {\n variants: {\n variant: {\n success: \"bg-green-50 text-green-500\",\n error: \"bg-red-50 text-red-500\",\n warning: \"bg-yellow-50 text-yellow-400\",\n info: \"bg-pages-50 text-pages-500\",\n default: \"bg-gray-50 text-gray-950\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nconst TOAST_ICONS = {\n success: IconCircleCheck,\n error: IconCircleX,\n warning: IconAlertCircle,\n info: IconInfoCircle,\n default: IconCircle,\n} as const\n\ninterface ToastProps extends VariantProps<typeof toastIconContainerVariants> {\n message?: React.ReactNode\n icon?: React.ReactNode\n children?: React.ReactNode\n className?: string\n toastId?: string | number\n}\n\nfunction Toast({\n variant = \"default\",\n message,\n icon,\n children,\n className,\n toastId,\n}: ToastProps) {\n const Icon = variant ? TOAST_ICONS[variant] : null\n\n return (\n <div data-slot=\"toast\" className={cn(toastVariants({ variant }), className, \"md:min-w-[310px] lg:min-w-[310px]\")}>\n {children ? (\n children\n ) : (\n <div className=\"flex items-center gap-3 flex-1 min-w-0\">\n <div className={cn(toastIconContainerVariants({ variant }))}>\n {icon || (Icon && <Icon size={16} />)}\n </div>\n\n <span className=\"w-full text-gray-600 paragraph-small-medium\">\n {message}\n </span>\n <Button\n variant={\"ghost\"}\n className=\"size-8 rounded-full\"\n onClick={() => toastId && toast.dismiss(toastId)}\n >\n <IconX size={18} />\n </Button>\n </div>\n )}\n </div>\n )\n}\n\nexport { Toast, toastVariants, toastIconContainerVariants }\nexport type { ToastProps }\n"],"mappings":";AA8EQ,SAEsB,KAFtB;AAzER,SAAS,WAA8B;AACvC,SAAS,iBAAiB,aAAa,iBAAiB,gBAAgB,YAAY,aAAa;AACjG,SAAS,aAAa;AACtB,SAAS,UAAU;AACnB,SAAS,cAAc;AAEvB,MAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAEA,MAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAEA,MAAM,cAAc;AAAA,EAClB,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX;AAUA,SAAS,MAAM;AAAA,EACb,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAe;AACb,QAAM,OAAO,UAAU,YAAY,OAAO,IAAI;AAE9C,SACE,oBAAC,SAAI,aAAU,SAAQ,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,WAAW,mCAAmC,GAC5G,qBACC,WAEA,qBAAC,SAAI,WAAU,0CACb;AAAA,wBAAC,SAAI,WAAW,GAAG,2BAA2B,EAAE,QAAQ,CAAC,CAAC,GACvD,kBAAS,QAAQ,oBAAC,QAAK,MAAM,IAAI,GACpC;AAAA,IAEA,oBAAC,UAAK,WAAU,+CACb,mBACH;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,SAAS,MAAM,WAAW,MAAM,QAAQ,OAAO;AAAA,QAE/C,8BAAC,SAAM,MAAM,IAAI;AAAA;AAAA,IACnB;AAAA,KACF,GAEJ;AAEJ;","names":[]}
|
|
@@ -43,7 +43,7 @@ function NotificationCard({
|
|
|
43
43
|
] }),
|
|
44
44
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: actions })
|
|
45
45
|
] }),
|
|
46
|
-
isUnread && /* @__PURE__ */ jsx("div", { className: "size-2 bg-
|
|
46
|
+
isUnread && /* @__PURE__ */ jsx("div", { className: "size-2 bg-pages-400 rounded-full shrink-0 mt-1" })
|
|
47
47
|
]
|
|
48
48
|
}
|
|
49
49
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/widgets/notifications/NotificationCard.tsx"],"sourcesContent":["import { IconClock } from '@tabler/icons-react';\nimport { ReactNode } from 'react';\nimport { cn } from '../../../infra/utils/clsx';\n\ntype NotificationCardProps = {\n icon: ReactNode;\n iconBgColor?: string;\n title: string;\n description?: string;\n time: string;\n actions?: ReactNode;\n isUnread?: boolean;\n showBorder?: boolean;\n className?: string;\n gapPx: number;\n};\n\nexport default function NotificationCard({\n icon,\n iconBgColor,\n title,\n description,\n time,\n actions,\n isUnread = false,\n showBorder = true,\n className,\n gapPx = 16\n}: NotificationCardProps) {\n return (\n <div\n className={cn(\n 'flex flex-col lg:flex-row items-start p-4 lg:p-5 gap-3 lg:gap-4 relative',\n showBorder && 'border-b border-gray-200',\n className\n )}\n >\n <div\n className={cn(\n 'flex items-center justify-center size-10 rounded-full shrink-0',\n iconBgColor\n )}\n >\n {icon}\n </div>\n\n <div className=\"flex flex-col flex-1\" style={{ gap: `${gapPx}px` }}>\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-small-semibold text-gray-950\">{title}</span>\n {description && (\n <span className=\"paragraph-small-regular text-gray-600\">{description}</span>\n )}\n </div>\n\n <div className=\"flex items-center gap-1.5\">\n <IconClock size={14} className=\"text-gray-400\" />\n <span className=\"paragraph-xsmall-medium text-gray-600\">{time}</span>\n </div>\n\n {actions && <div className=\"flex items-center gap-2\">{actions}</div>}\n </div>\n\n {isUnread && <div className=\"size-2 bg-
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/widgets/notifications/NotificationCard.tsx"],"sourcesContent":["import { IconClock } from '@tabler/icons-react';\nimport { ReactNode } from 'react';\nimport { cn } from '../../../infra/utils/clsx';\n\ntype NotificationCardProps = {\n icon: ReactNode;\n iconBgColor?: string;\n title: string;\n description?: string;\n time: string;\n actions?: ReactNode;\n isUnread?: boolean;\n showBorder?: boolean;\n className?: string;\n gapPx: number;\n};\n\nexport default function NotificationCard({\n icon,\n iconBgColor,\n title,\n description,\n time,\n actions,\n isUnread = false,\n showBorder = true,\n className,\n gapPx = 16\n}: NotificationCardProps) {\n return (\n <div\n className={cn(\n 'flex flex-col lg:flex-row items-start p-4 lg:p-5 gap-3 lg:gap-4 relative',\n showBorder && 'border-b border-gray-200',\n className\n )}\n >\n <div\n className={cn(\n 'flex items-center justify-center size-10 rounded-full shrink-0',\n iconBgColor\n )}\n >\n {icon}\n </div>\n\n <div className=\"flex flex-col flex-1\" style={{ gap: `${gapPx}px` }}>\n <div className=\"flex flex-col gap-1\">\n <span className=\"paragraph-small-semibold text-gray-950\">{title}</span>\n {description && (\n <span className=\"paragraph-small-regular text-gray-600\">{description}</span>\n )}\n </div>\n\n <div className=\"flex items-center gap-1.5\">\n <IconClock size={14} className=\"text-gray-400\" />\n <span className=\"paragraph-xsmall-medium text-gray-600\">{time}</span>\n </div>\n\n {actions && <div className=\"flex items-center gap-2\">{actions}</div>}\n </div>\n\n {isUnread && <div className=\"size-2 bg-pages-400 rounded-full shrink-0 mt-1\" />}\n </div>\n );\n}\n\nexport type { NotificationCardProps };\n"],"mappings":"AAqCM,cAUE,YAVF;AArCN,SAAS,iBAAiB;AAE1B,SAAS,UAAU;AAeJ,SAAR,iBAAkC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb;AAAA,EACA,QAAQ;AACV,GAA0B;AACxB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,cAAc;AAAA,QACd;AAAA,MACF;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA;AAAA,YACF;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QAEA,qBAAC,SAAI,WAAU,wBAAuB,OAAO,EAAE,KAAK,GAAG,KAAK,KAAK,GAC/D;AAAA,+BAAC,SAAI,WAAU,uBACb;AAAA,gCAAC,UAAK,WAAU,0CAA0C,iBAAM;AAAA,YAC/D,eACC,oBAAC,UAAK,WAAU,yCAAyC,uBAAY;AAAA,aAEzE;AAAA,UAEA,qBAAC,SAAI,WAAU,6BACb;AAAA,gCAAC,aAAU,MAAM,IAAI,WAAU,iBAAgB;AAAA,YAC/C,oBAAC,UAAK,WAAU,yCAAyC,gBAAK;AAAA,aAChE;AAAA,UAEC,WAAW,oBAAC,SAAI,WAAU,2BAA2B,mBAAQ;AAAA,WAChE;AAAA,QAEC,YAAY,oBAAC,SAAI,WAAU,kDAAiD;AAAA;AAAA;AAAA,EAC/E;AAEJ;","names":[]}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { safeServerAction } from "../../../utils/safeServerAction";
|
|
3
3
|
import { subscriptionsService } from "../services/subscriptions.service";
|
|
4
|
+
import { resolvePlanExtrasPrices } from "../utils/resolve-plan-extras-prices";
|
|
4
5
|
async function updateSubscriptionPlanAction(subscriptionId, data) {
|
|
5
6
|
return safeServerAction(async () => {
|
|
7
|
+
if (data.plan_extras?.length) {
|
|
8
|
+
const { data: subscriptions } = await subscriptionsService.listSubscriptions({ active: true });
|
|
9
|
+
const subscription = subscriptions.find((s) => String(s.id) === String(subscriptionId)) ?? subscriptions[0];
|
|
10
|
+
data = {
|
|
11
|
+
...data,
|
|
12
|
+
plan_extras: resolvePlanExtrasPrices(data.plan_extras, subscription?.items ?? [])
|
|
13
|
+
};
|
|
14
|
+
}
|
|
6
15
|
return subscriptionsService.updateSubscriptionPlan(subscriptionId, data);
|
|
7
16
|
});
|
|
8
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/subscriptions/actions/update-subscription-plan.action.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/subscriptions/actions/update-subscription-plan.action.ts"],"sourcesContent":["'use server';\n\nimport { safeServerAction } from '../../../utils/safeServerAction';\nimport type { UpdateSubscriptionPlanRequest } from '../types/calculate-subscription.type';\nimport { subscriptionsService } from '../services/subscriptions.service';\nimport { resolvePlanExtrasPrices } from '../utils/resolve-plan-extras-prices';\n\nexport async function updateSubscriptionPlanAction(\n subscriptionId: number | string,\n data: UpdateSubscriptionPlanRequest\n) {\n return safeServerAction(async () => {\n if (data.plan_extras?.length) {\n const { data: subscriptions } = await subscriptionsService.listSubscriptions({ active: true });\n const subscription =\n subscriptions.find((s) => String(s.id) === String(subscriptionId)) ?? subscriptions[0];\n\n data = {\n ...data,\n plan_extras: resolvePlanExtrasPrices(data.plan_extras, subscription?.items ?? []),\n };\n }\n\n return subscriptionsService.updateSubscriptionPlan(subscriptionId, data);\n });\n}\n"],"mappings":";AAEA,SAAS,wBAAwB;AAEjC,SAAS,4BAA4B;AACrC,SAAS,+BAA+B;AAExC,eAAsB,6BACpB,gBACA,MACA;AACA,SAAO,iBAAiB,YAAY;AAClC,QAAI,KAAK,aAAa,QAAQ;AAC5B,YAAM,EAAE,MAAM,cAAc,IAAI,MAAM,qBAAqB,kBAAkB,EAAE,QAAQ,KAAK,CAAC;AAC7F,YAAM,eACJ,cAAc,KAAK,CAAC,MAAM,OAAO,EAAE,EAAE,MAAM,OAAO,cAAc,CAAC,KAAK,cAAc,CAAC;AAEvF,aAAO;AAAA,QACL,GAAG;AAAA,QACH,aAAa,wBAAwB,KAAK,aAAa,cAAc,SAAS,CAAC,CAAC;AAAA,MAClF;AAAA,IACF;AAEA,WAAO,qBAAqB,uBAAuB,gBAAgB,IAAI;AAAA,EACzE,CAAC;AACH;","names":[]}
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { create } from "zustand";
|
|
2
|
+
import { useEffect } from "react";
|
|
2
3
|
const STORAGE_KEY = "desktop-sidebar-expanded";
|
|
3
|
-
function getInitialState() {
|
|
4
|
-
if (typeof window === "undefined") return true;
|
|
5
|
-
const stored = localStorage.getItem(STORAGE_KEY);
|
|
6
|
-
if (stored === null) return true;
|
|
7
|
-
return stored === "true";
|
|
8
|
-
}
|
|
9
4
|
const useDesktopSidebarStore = create((set) => ({
|
|
10
|
-
isExpanded:
|
|
5
|
+
isExpanded: true,
|
|
6
|
+
_hydrated: false,
|
|
11
7
|
toggle: () => set((state) => {
|
|
12
8
|
const next = !state.isExpanded;
|
|
13
9
|
localStorage.setItem(STORAGE_KEY, String(next));
|
|
@@ -20,9 +16,24 @@ const useDesktopSidebarStore = create((set) => ({
|
|
|
20
16
|
collapse: () => {
|
|
21
17
|
localStorage.setItem(STORAGE_KEY, "false");
|
|
22
18
|
return set({ isExpanded: false });
|
|
19
|
+
},
|
|
20
|
+
_hydrate: () => {
|
|
21
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
22
|
+
const value = stored === null ? true : stored === "true";
|
|
23
|
+
set({ isExpanded: value, _hydrated: true });
|
|
23
24
|
}
|
|
24
25
|
}));
|
|
26
|
+
function useDesktopSidebarHydration() {
|
|
27
|
+
const hydrate = useDesktopSidebarStore((s) => s._hydrate);
|
|
28
|
+
const hydrated = useDesktopSidebarStore((s) => s._hydrated);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!hydrated) {
|
|
31
|
+
hydrate();
|
|
32
|
+
}
|
|
33
|
+
}, [hydrate, hydrated]);
|
|
34
|
+
}
|
|
25
35
|
export {
|
|
36
|
+
useDesktopSidebarHydration,
|
|
26
37
|
useDesktopSidebarStore
|
|
27
38
|
};
|
|
28
39
|
//# sourceMappingURL=useDesktopSidebarStore.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/store/useDesktopSidebarStore.ts"],"sourcesContent":["import { create } from \"zustand\";\
|
|
1
|
+
{"version":3,"sources":["../../src/store/useDesktopSidebarStore.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport { useEffect } from \"react\";\n\nconst STORAGE_KEY = \"desktop-sidebar-expanded\";\n\ntype DesktopSidebarStore = {\n isExpanded: boolean;\n _hydrated: boolean;\n toggle: () => void;\n expand: () => void;\n collapse: () => void;\n _hydrate: () => void;\n};\n\nexport const useDesktopSidebarStore = create<DesktopSidebarStore>((set) => ({\n isExpanded: true,\n _hydrated: false,\n toggle: () => set((state) => {\n const next = !state.isExpanded;\n localStorage.setItem(STORAGE_KEY, String(next));\n return { isExpanded: next };\n }),\n expand: () => {\n localStorage.setItem(STORAGE_KEY, \"true\");\n return set({ isExpanded: true });\n },\n collapse: () => {\n localStorage.setItem(STORAGE_KEY, \"false\");\n return set({ isExpanded: false });\n },\n _hydrate: () => {\n const stored = localStorage.getItem(STORAGE_KEY);\n const value = stored === null ? true : stored === \"true\";\n set({ isExpanded: value, _hydrated: true });\n },\n}));\n\nexport function useDesktopSidebarHydration() {\n const hydrate = useDesktopSidebarStore((s) => s._hydrate);\n const hydrated = useDesktopSidebarStore((s) => s._hydrated);\n\n useEffect(() => {\n if (!hydrated) {\n hydrate();\n }\n }, [hydrate, hydrated]);\n}\n"],"mappings":"AAAA,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAE1B,MAAM,cAAc;AAWb,MAAM,yBAAyB,OAA4B,CAAC,SAAS;AAAA,EACxE,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ,MAAM,IAAI,CAAC,UAAU;AACzB,UAAM,OAAO,CAAC,MAAM;AACpB,iBAAa,QAAQ,aAAa,OAAO,IAAI,CAAC;AAC9C,WAAO,EAAE,YAAY,KAAK;AAAA,EAC9B,CAAC;AAAA,EACD,QAAQ,MAAM;AACV,iBAAa,QAAQ,aAAa,MAAM;AACxC,WAAO,IAAI,EAAE,YAAY,KAAK,CAAC;AAAA,EACnC;AAAA,EACA,UAAU,MAAM;AACZ,iBAAa,QAAQ,aAAa,OAAO;AACzC,WAAO,IAAI,EAAE,YAAY,MAAM,CAAC;AAAA,EACpC;AAAA,EACA,UAAU,MAAM;AACZ,UAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,UAAM,QAAQ,WAAW,OAAO,OAAO,WAAW;AAClD,QAAI,EAAE,YAAY,OAAO,WAAW,KAAK,CAAC;AAAA,EAC9C;AACJ,EAAE;AAEK,SAAS,6BAA6B;AACzC,QAAM,UAAU,uBAAuB,CAAC,MAAM,EAAE,QAAQ;AACxD,QAAM,WAAW,uBAAuB,CAAC,MAAM,EAAE,SAAS;AAE1D,YAAU,MAAM;AACZ,QAAI,CAAC,UAAU;AACX,cAAQ;AAAA,IACZ;AAAA,EACJ,GAAG,CAAC,SAAS,QAAQ,CAAC;AAC1B;","names":[]}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ import Image from "next/image";
|
|
|
5
5
|
import { IconChevronRight } from "@tabler/icons-react";
|
|
6
6
|
import { Separator } from "../ui/data-display/Separator";
|
|
7
7
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
|
|
8
|
-
import { useDesktopSidebarStore } from "../../store/useDesktopSidebarStore";
|
|
8
|
+
import { useDesktopSidebarStore, useDesktopSidebarHydration } from "../../store/useDesktopSidebarStore";
|
|
9
9
|
import { useWhitelabel } from "../../providers/whitelabel.provider";
|
|
10
10
|
import { cn } from "../../infra/utils/clsx";
|
|
11
11
|
|
|
@@ -30,6 +30,7 @@ function NavBar({
|
|
|
30
30
|
}: NavBarProps) {
|
|
31
31
|
const { isExpanded: isDesktopExpanded, toggle: toggleDesktop } =
|
|
32
32
|
useDesktopSidebarStore();
|
|
33
|
+
useDesktopSidebarHydration();
|
|
33
34
|
const { whitelabel } = useWhitelabel();
|
|
34
35
|
const isDefaultWl = !whitelabel || whitelabel.id === 1;
|
|
35
36
|
const primaryColor = whitelabel?.general?.primary_color;
|
|
@@ -13,12 +13,9 @@ import {
|
|
|
13
13
|
Popover,
|
|
14
14
|
PopoverContent,
|
|
15
15
|
PopoverTrigger,
|
|
16
|
-
Tooltip,
|
|
17
|
-
TooltipContent,
|
|
18
|
-
TooltipTrigger,
|
|
19
16
|
UserAvatar,
|
|
20
17
|
} from '../../index';
|
|
21
|
-
import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus
|
|
18
|
+
import { IconCheck, IconChevronDown, IconFolderOpen, IconPlus } from '@tabler/icons-react';
|
|
22
19
|
import type { NavigationProject } from './types';
|
|
23
20
|
|
|
24
21
|
interface ProjectSelectorPopoverProps {
|
|
@@ -96,16 +93,6 @@ export function ProjectSelectorPopover({
|
|
|
96
93
|
Adicionar
|
|
97
94
|
</Button>
|
|
98
95
|
)}
|
|
99
|
-
{onManageProjects && (
|
|
100
|
-
<Tooltip>
|
|
101
|
-
<TooltipTrigger asChild>
|
|
102
|
-
<Button variant="secondary" className="p-0 size-8" onClick={onManageProjects}>
|
|
103
|
-
<IconSettings size={18} />
|
|
104
|
-
</Button>
|
|
105
|
-
</TooltipTrigger>
|
|
106
|
-
<TooltipContent className="z-[1002]">Visualizar todos projetos</TooltipContent>
|
|
107
|
-
</Tooltip>
|
|
108
|
-
)}
|
|
109
96
|
</div>
|
|
110
97
|
)}
|
|
111
98
|
</div>
|
|
@@ -154,6 +141,18 @@ export function ProjectSelectorPopover({
|
|
|
154
141
|
)}
|
|
155
142
|
</CommandList>
|
|
156
143
|
</Command>
|
|
144
|
+
{onManageProjects && (
|
|
145
|
+
<>
|
|
146
|
+
<div className="border-t border-gray-200" />
|
|
147
|
+
<button
|
|
148
|
+
type="button"
|
|
149
|
+
className="paragraph-small-medium text-violet-700 underline cursor-pointer py-1 text-center"
|
|
150
|
+
onClick={onManageProjects}
|
|
151
|
+
>
|
|
152
|
+
Gerenciar projetos
|
|
153
|
+
</button>
|
|
154
|
+
</>
|
|
155
|
+
)}
|
|
157
156
|
</div>
|
|
158
157
|
</PopoverContent>
|
|
159
158
|
</Popover>
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import { create } from "zustand";
|
|
2
|
+
import { useEffect } from "react";
|
|
2
3
|
|
|
3
4
|
const STORAGE_KEY = "desktop-sidebar-expanded";
|
|
4
5
|
|
|
5
|
-
function getInitialState(): boolean {
|
|
6
|
-
if (typeof window === "undefined") return true;
|
|
7
|
-
const stored = localStorage.getItem(STORAGE_KEY);
|
|
8
|
-
if (stored === null) return true;
|
|
9
|
-
return stored === "true";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
6
|
type DesktopSidebarStore = {
|
|
13
7
|
isExpanded: boolean;
|
|
8
|
+
_hydrated: boolean;
|
|
14
9
|
toggle: () => void;
|
|
15
10
|
expand: () => void;
|
|
16
11
|
collapse: () => void;
|
|
12
|
+
_hydrate: () => void;
|
|
17
13
|
};
|
|
18
14
|
|
|
19
15
|
export const useDesktopSidebarStore = create<DesktopSidebarStore>((set) => ({
|
|
20
|
-
isExpanded:
|
|
16
|
+
isExpanded: true,
|
|
17
|
+
_hydrated: false,
|
|
21
18
|
toggle: () => set((state) => {
|
|
22
19
|
const next = !state.isExpanded;
|
|
23
20
|
localStorage.setItem(STORAGE_KEY, String(next));
|
|
@@ -31,4 +28,20 @@ export const useDesktopSidebarStore = create<DesktopSidebarStore>((set) => ({
|
|
|
31
28
|
localStorage.setItem(STORAGE_KEY, "false");
|
|
32
29
|
return set({ isExpanded: false });
|
|
33
30
|
},
|
|
31
|
+
_hydrate: () => {
|
|
32
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
33
|
+
const value = stored === null ? true : stored === "true";
|
|
34
|
+
set({ isExpanded: value, _hydrated: true });
|
|
35
|
+
},
|
|
34
36
|
}));
|
|
37
|
+
|
|
38
|
+
export function useDesktopSidebarHydration() {
|
|
39
|
+
const hydrate = useDesktopSidebarStore((s) => s._hydrate);
|
|
40
|
+
const hydrated = useDesktopSidebarStore((s) => s._hydrated);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!hydrated) {
|
|
44
|
+
hydrate();
|
|
45
|
+
}
|
|
46
|
+
}, [hydrate, hydrated]);
|
|
47
|
+
}
|