@greatapps/common 1.1.475 → 1.1.477

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/components/account/sections/MyProfileSection.mjs +2 -1
  2. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  3. package/dist/components/embeds/CrispEmbed.mjs +60 -24
  4. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  5. package/dist/components/embeds/EmbedWidgets.mjs +45 -0
  6. package/dist/components/embeds/EmbedWidgets.mjs.map +1 -0
  7. package/dist/components/embeds/FrillEmbed.mjs +10 -3
  8. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  9. package/dist/components/layouts/ProfilePopover.mjs +2 -1
  10. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  11. package/dist/components/modals/cards/AddCardModal.mjs +10 -6
  12. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  13. package/dist/components/modals/cards/CardFormFields.mjs +47 -15
  14. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  15. package/dist/components/navigation/CancelledSubscriptionBanner.mjs +1 -1
  16. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  17. package/dist/components/navigation/ProjectSelectorPopover.mjs +1 -1
  18. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  19. package/dist/components/navigation/subcomponents/BottomLinks.mjs +2 -2
  20. package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
  21. package/dist/components/navigation/subcomponents/ProjectSelector.mjs +1 -1
  22. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  23. package/dist/components/pages/notifications/Notifications.mjs +27 -17
  24. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  25. package/dist/components/ui/form/Select.mjs +1 -1
  26. package/dist/components/ui/form/Select.mjs.map +1 -1
  27. package/dist/components/ui/overlay/Dialog.mjs +2 -1
  28. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  29. package/dist/components/ui/overlay/Popover.mjs +1 -1
  30. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  31. package/dist/components/ui/overlay/Sheet.mjs +8 -6
  32. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  33. package/dist/components/ui/overlay/Tooltip.mjs +1 -1
  34. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  35. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs +212 -0
  36. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -0
  37. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs +51 -0
  38. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -0
  39. package/dist/components/widgets/ImageUpload/ImageUpload.mjs +122 -0
  40. package/dist/components/widgets/ImageUpload/ImageUpload.mjs.map +1 -0
  41. package/dist/components/widgets/ImageUpload/index.mjs +9 -0
  42. package/dist/components/widgets/ImageUpload/index.mjs.map +1 -0
  43. package/dist/index.mjs +50 -2
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/infra/utils/date.mjs +11 -0
  46. package/dist/infra/utils/date.mjs.map +1 -1
  47. package/dist/modules/auth/services/auth.service.mjs +2 -1
  48. package/dist/modules/auth/services/auth.service.mjs.map +1 -1
  49. package/dist/modules/images/actions/process-image.action.mjs +31 -0
  50. package/dist/modules/images/actions/process-image.action.mjs.map +1 -0
  51. package/dist/modules/images/constants/image.constants.mjs +14 -0
  52. package/dist/modules/images/constants/image.constants.mjs.map +1 -0
  53. package/dist/modules/images/hooks/use-image-upload.hook.mjs +132 -0
  54. package/dist/modules/images/hooks/use-image-upload.hook.mjs.map +1 -0
  55. package/dist/modules/images/services/image-processing.service.mjs +65 -0
  56. package/dist/modules/images/services/image-processing.service.mjs.map +1 -0
  57. package/dist/modules/images/types/image.type.mjs +1 -0
  58. package/dist/modules/images/types/image.type.mjs.map +1 -0
  59. package/dist/modules/images/utils/base64.mjs +24 -0
  60. package/dist/modules/images/utils/base64.mjs.map +1 -0
  61. package/dist/modules/images/utils/compress-image.mjs +17 -0
  62. package/dist/modules/images/utils/compress-image.mjs.map +1 -0
  63. package/dist/modules/images/utils/crop-image.mjs +31 -0
  64. package/dist/modules/images/utils/crop-image.mjs.map +1 -0
  65. package/dist/modules/images/utils/validate-image.mjs +58 -0
  66. package/dist/modules/images/utils/validate-image.mjs.map +1 -0
  67. package/dist/modules/plans/actions/list-plans.action.mjs +17 -0
  68. package/dist/modules/plans/actions/list-plans.action.mjs.map +1 -0
  69. package/dist/modules/plans/hooks/list-plans.hook.mjs +22 -0
  70. package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -0
  71. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs +21 -2
  72. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  73. package/dist/modules/plans/services/plans.service.mjs +71 -10
  74. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  75. package/dist/modules/plans/types/plan.type.mjs +1 -0
  76. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  77. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs +58 -0
  78. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -0
  79. package/dist/modules/subscriptions/types/subscription.type.mjs +31 -1
  80. package/dist/modules/subscriptions/types/subscription.type.mjs.map +1 -1
  81. package/dist/server.mjs +6 -0
  82. package/dist/server.mjs.map +1 -1
  83. package/dist/utils/format/currency.mjs +13 -0
  84. package/dist/utils/format/currency.mjs.map +1 -0
  85. package/package.json +1 -1
  86. package/src/components/navigation/CancelledSubscriptionBanner.tsx +1 -1
  87. package/src/components/ui/overlay/Sheet.tsx +13 -9
@@ -6,6 +6,7 @@ import { useForm } from "react-hook-form";
6
6
  import { zodResolver } from "@hookform/resolvers/zod";
7
7
  import { toast } from "sonner";
8
8
  import { IconUpload, IconTrash } from "@tabler/icons-react";
9
+ import { ACCEPTED_IMAGE_FORMATS_STRING } from "../../../modules/images/constants/image.constants";
9
10
  import { Button } from "../../ui/buttons/Button";
10
11
  import { Separator } from "../../ui/data-display/Separator";
11
12
  import { Toast } from "../../ui/feedback/Toast";
@@ -118,7 +119,7 @@ function MyProfileSection({ onClose, storageUrl }) {
118
119
  {
119
120
  ref: fileInputRef,
120
121
  type: "file",
121
- accept: "image/*",
122
+ accept: ACCEPTED_IMAGE_FORMATS_STRING,
122
123
  className: "hidden",
123
124
  onChange: handlePhotoChange
124
125
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/account/sections/MyProfileSection.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useRef } from 'react';\nimport Image from 'next/image';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { toast } from 'sonner';\nimport { IconUpload, IconTrash } from '@tabler/icons-react';\nimport { Button } from '../../ui/buttons/Button';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { FormField } from '../../ui/form/FormField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport PhoneInput from '../../ui/form/PhoneInput';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { UserProfile } from '../../../modules/users/schema';\nimport { myProfileSchema, type MyProfileFormData } from '../../../utils/validators/account';\nimport {\n useUpdateAccountUser,\n useDeleteAccount,\n useDeleteAccountUser,\n} from '../../../modules/accounts/hooks/useAccountManagement';\nimport { GENDER_OPTIONS } from '../constants';\nimport { ChangePhoneModal } from './ChangePhoneModal';\nimport { ChangeEmailModal } from './ChangeEmailModal';\n\ninterface MyProfileSectionProps {\n onClose: () => void;\n storageUrl?: string;\n}\n\nexport function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps) {\n const { user, logout } = useAuth();\n const updateAccountUser = useUpdateAccountUser();\n const deleteAccount = useDeleteAccount();\n const deleteAccountUser = useDeleteAccountUser();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [selectedPhoto, setSelectedPhoto] = useState<File | null>(null);\n const [photoRemoved, setPhotoRemoved] = useState(false);\n const [changePhoneOpen, setChangePhoneOpen] = useState(false);\n const [changeEmailOpen, setChangeEmailOpen] = useState(false);\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\n\n const isOwner = user?.profile === UserProfile.owner;\n const isDeleting = deleteAccount.isPending || deleteAccountUser.isPending;\n\n const form = useForm<MyProfileFormData>({\n resolver: zodResolver(myProfileSchema),\n mode: 'onChange',\n defaultValues: {\n name: user?.name ?? '',\n last_name: user?.last_name ?? '',\n gender: GENDER_OPTIONS.find((g) => g.apiValue === user?.gender)?.value ?? '',\n },\n });\n\n const {\n register,\n handleSubmit,\n watch,\n setValue,\n formState: { errors, isSubmitting },\n } = form;\n\n const baseStorageUrl = storageUrl ?? process.env.NEXT_PUBLIC_STORAGE_URL ?? '';\n\n const avatarPreview = selectedPhoto\n ? URL.createObjectURL(selectedPhoto)\n : !photoRemoved && user?.photo\n ? `${baseStorageUrl}/${user.photo}`\n : null;\n\n const handlePhotoChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0] ?? null;\n if (file) {\n setSelectedPhoto(file);\n setPhotoRemoved(false);\n }\n };\n\n const handleRemovePhoto = () => {\n setSelectedPhoto(null);\n setPhotoRemoved(true);\n };\n\n const handleDelete = async () => {\n try {\n if (isOwner) {\n await deleteAccount.mutateAsync();\n } else {\n await deleteAccountUser.mutateAsync(user!.id);\n }\n await logout();\n } catch (error) {\n toast.custom((t) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.'}\n toastId={t}\n />\n ));\n setDeleteConfirmOpen(false);\n }\n };\n\n const onSubmit = async (data: MyProfileFormData) => {\n try {\n await updateAccountUser.mutateAsync({\n name: data.name,\n last_name: data.last_name,\n gender: GENDER_OPTIONS.find((g) => g.value === data.gender)?.apiValue,\n ...(selectedPhoto ? { photo: selectedPhoto } : {}),\n ...(photoRemoved ? { photo: '' } : {}),\n });\n\n form.reset(data);\n setSelectedPhoto(null);\n setPhotoRemoved(false);\n toast.custom((t) => (\n <Toast variant=\"success\" message=\"Perfil atualizado com sucesso\" toastId={t} />\n ));\n onClose();\n } catch (error) {\n toast.custom((t) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : 'Erro ao atualizar perfil'}\n toastId={t}\n />\n ));\n }\n };\n\n return (\n <>\n <form onSubmit={handleSubmit(onSubmit)} className=\"lg:h-full lg:flex lg:flex-col\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n className=\"hidden\"\n onChange={handlePhotoChange}\n />\n <div className=\"absolute inset-0 overflow-y-auto overscroll-contain px-4 pb-20 lg:p-5 lg:static lg:flex-1 lg:min-h-0 lg:overscroll-auto flex flex-col gap-5 lg:gap-6\">\n <span className=\"paragraph-medium-semibold text-gray-950 hidden lg:block\">\n Meu perfil\n </span>\n <div className=\"flex flex-col gap-5\">\n <div className=\"flex items-center gap-4\">\n {avatarPreview ? (\n <Image\n src={avatarPreview}\n alt=\"Foto do usuário\"\n width={48}\n height={48}\n className=\"size-12 rounded-full object-cover cursor-pointer\"\n onClick={() => fileInputRef.current?.click()}\n />\n ) : (\n <div\n className=\"size-12 rounded-full bg-gray-50 border border-dashed border-gray-200 flex items-center justify-center cursor-pointer\"\n onClick={() => fileInputRef.current?.click()}\n >\n <IconUpload size={20} className=\"text-gray-400\" />\n </div>\n )}\n {avatarPreview ? (\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"secondary\"\n className=\"w-fit h-8!\"\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n >\n Alterar foto\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-8!\"\n onClick={handleRemovePhoto}\n >\n <IconTrash size={16} className=\"text-gray-500\" />\n </Button>\n </div>\n ) : (\n <Button\n variant=\"secondary\"\n className=\"w-fit h-8!\"\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n >\n Alterar foto\n </Button>\n )}\n </div>\n\n <div className=\"flex flex-col gap-8\">\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex gap-4\">\n <FormField\n label=\"Nome\"\n placeholder=\"Digite seu nome\"\n error={!!errors.name}\n errorMessage={errors.name?.message}\n {...register('name')}\n />\n <FormField\n label=\"Sobrenome\"\n placeholder=\"Digite seu sobrenome\"\n error={!!errors.last_name}\n errorMessage={errors.last_name?.message}\n {...register('last_name')}\n />\n </div>\n <SelectField\n label=\"Gênero\"\n placeholder=\"Selecione seu gênero\"\n options={GENDER_OPTIONS}\n value={watch('gender')}\n className=\"h-10!\"\n onChange={(value) => setValue('gender', value as string)}\n />\n <div className=\"relative\">\n <PhoneInput\n label=\"Telefone\"\n value={user?.phone ?? ''}\n disabled\n classnameContainer=\"bg-gray-50 border-0!\"\n />\n <button\n type=\"button\"\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\n onClick={() => setChangePhoneOpen(true)}\n >\n Alterar\n </button>\n </div>\n </div>\n\n <Separator />\n\n <div className=\"flex flex-col gap-4\">\n <span className=\"paragraph-medium-semibold text-gray-600\">Dados de acesso</span>\n <div className=\"relative\">\n <div className='cursor-not-allowed'>\n <FormField\n label=\"E-mail\"\n value={user?.email ?? ''}\n disabled\n classnameContainer=\"bg-gray-50 border-0!\"\n />\n </div>\n <button\n type=\"button\"\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\n onClick={() => setChangeEmailOpen(true)}\n >\n Alterar\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"fixed bottom-0 left-0 right-0 lg:static flex items-center h-20 px-4 lg:px-5 border-t border-gray-200 justify-between bg-white z-10\">\n <Button\n variant=\"secondary\"\n className=\"h-10!\"\n type=\"button\"\n disabled={isSubmitting}\n onClick={() => {\n form.reset();\n setSelectedPhoto(null);\n setPhotoRemoved(false);\n onClose();\n }}\n >\n Cancelar\n </Button>\n <Button className=\"h-10! cursor-pointer\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? 'Salvando...' : 'Salvar alterações'}\n </Button>\n </div>\n </form>\n\n <ChangePhoneModal open={changePhoneOpen} onClose={() => setChangePhoneOpen(false)} />\n <ChangeEmailModal open={changeEmailOpen} onClose={() => setChangeEmailOpen(false)} />\n\n <Dialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>\n <DialogContent className=\"max-w-sm! gap-5\">\n <DialogHeader>\n <DialogTitle className=\"paragraph-large-semibold text-gray-950\">\n {isOwner ? 'Excluir conta' : 'Excluir usuário'}\n </DialogTitle>\n </DialogHeader>\n <p className=\"paragraph-small-regular text-gray-600\">\n {isOwner\n ? 'Tem certeza que deseja excluir sua conta? Todos os dados serão apagados permanentemente e essa ação não pode ser desfeita.'\n : 'Tem certeza que deseja excluir seu usuário? Você perderá acesso a esta conta permanentemente.'}\n </p>\n <div className=\"flex items-center gap-3 justify-end\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-10!\"\n disabled={isDeleting}\n onClick={() => setDeleteConfirmOpen(false)}\n >\n Cancelar\n </Button>\n <Button\n type=\"button\"\n className=\"h-10! bg-red-600 hover:bg-red-700 text-white border-0!\"\n disabled={isDeleting}\n onClick={handleDelete}\n >\n {isDeleting ? 'Excluindo...' : 'Confirmar exclusão'}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/account/sections/MyProfileSection.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useRef } from 'react';\nimport Image from 'next/image';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { toast } from 'sonner';\nimport { IconUpload, IconTrash } from '@tabler/icons-react';\nimport { ACCEPTED_IMAGE_FORMATS_STRING } from '../../../modules/images/constants/image.constants';\nimport { Button } from '../../ui/buttons/Button';\nimport { Separator } from '../../ui/data-display/Separator';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { FormField } from '../../ui/form/FormField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport PhoneInput from '../../ui/form/PhoneInput';\nimport { useAuth } from '../../../providers/auth.provider';\nimport { UserProfile } from '../../../modules/users/schema';\nimport { myProfileSchema, type MyProfileFormData } from '../../../utils/validators/account';\nimport {\n useUpdateAccountUser,\n useDeleteAccount,\n useDeleteAccountUser,\n} from '../../../modules/accounts/hooks/useAccountManagement';\nimport { GENDER_OPTIONS } from '../constants';\nimport { ChangePhoneModal } from './ChangePhoneModal';\nimport { ChangeEmailModal } from './ChangeEmailModal';\n\ninterface MyProfileSectionProps {\n onClose: () => void;\n storageUrl?: string;\n}\n\nexport function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps) {\n const { user, logout } = useAuth();\n const updateAccountUser = useUpdateAccountUser();\n const deleteAccount = useDeleteAccount();\n const deleteAccountUser = useDeleteAccountUser();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [selectedPhoto, setSelectedPhoto] = useState<File | null>(null);\n const [photoRemoved, setPhotoRemoved] = useState(false);\n const [changePhoneOpen, setChangePhoneOpen] = useState(false);\n const [changeEmailOpen, setChangeEmailOpen] = useState(false);\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\n\n const isOwner = user?.profile === UserProfile.owner;\n const isDeleting = deleteAccount.isPending || deleteAccountUser.isPending;\n\n const form = useForm<MyProfileFormData>({\n resolver: zodResolver(myProfileSchema),\n mode: 'onChange',\n defaultValues: {\n name: user?.name ?? '',\n last_name: user?.last_name ?? '',\n gender: GENDER_OPTIONS.find((g) => g.apiValue === user?.gender)?.value ?? '',\n },\n });\n\n const {\n register,\n handleSubmit,\n watch,\n setValue,\n formState: { errors, isSubmitting },\n } = form;\n\n const baseStorageUrl = storageUrl ?? process.env.NEXT_PUBLIC_STORAGE_URL ?? '';\n\n const avatarPreview = selectedPhoto\n ? URL.createObjectURL(selectedPhoto)\n : !photoRemoved && user?.photo\n ? `${baseStorageUrl}/${user.photo}`\n : null;\n\n const handlePhotoChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0] ?? null;\n if (file) {\n setSelectedPhoto(file);\n setPhotoRemoved(false);\n }\n };\n\n const handleRemovePhoto = () => {\n setSelectedPhoto(null);\n setPhotoRemoved(true);\n };\n\n const handleDelete = async () => {\n try {\n if (isOwner) {\n await deleteAccount.mutateAsync();\n } else {\n await deleteAccountUser.mutateAsync(user!.id);\n }\n await logout();\n } catch (error) {\n toast.custom((t) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.'}\n toastId={t}\n />\n ));\n setDeleteConfirmOpen(false);\n }\n };\n\n const onSubmit = async (data: MyProfileFormData) => {\n try {\n await updateAccountUser.mutateAsync({\n name: data.name,\n last_name: data.last_name,\n gender: GENDER_OPTIONS.find((g) => g.value === data.gender)?.apiValue,\n ...(selectedPhoto ? { photo: selectedPhoto } : {}),\n ...(photoRemoved ? { photo: '' } : {}),\n });\n\n form.reset(data);\n setSelectedPhoto(null);\n setPhotoRemoved(false);\n toast.custom((t) => (\n <Toast variant=\"success\" message=\"Perfil atualizado com sucesso\" toastId={t} />\n ));\n onClose();\n } catch (error) {\n toast.custom((t) => (\n <Toast\n variant=\"error\"\n message={error instanceof Error ? error.message : 'Erro ao atualizar perfil'}\n toastId={t}\n />\n ));\n }\n };\n\n return (\n <>\n <form onSubmit={handleSubmit(onSubmit)} className=\"lg:h-full lg:flex lg:flex-col\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={ACCEPTED_IMAGE_FORMATS_STRING}\n className=\"hidden\"\n onChange={handlePhotoChange}\n />\n <div className=\"absolute inset-0 overflow-y-auto overscroll-contain px-4 pb-20 lg:p-5 lg:static lg:flex-1 lg:min-h-0 lg:overscroll-auto flex flex-col gap-5 lg:gap-6\">\n <span className=\"paragraph-medium-semibold text-gray-950 hidden lg:block\">\n Meu perfil\n </span>\n <div className=\"flex flex-col gap-5\">\n <div className=\"flex items-center gap-4\">\n {avatarPreview ? (\n <Image\n src={avatarPreview}\n alt=\"Foto do usuário\"\n width={48}\n height={48}\n className=\"size-12 rounded-full object-cover cursor-pointer\"\n onClick={() => fileInputRef.current?.click()}\n />\n ) : (\n <div\n className=\"size-12 rounded-full bg-gray-50 border border-dashed border-gray-200 flex items-center justify-center cursor-pointer\"\n onClick={() => fileInputRef.current?.click()}\n >\n <IconUpload size={20} className=\"text-gray-400\" />\n </div>\n )}\n {avatarPreview ? (\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"secondary\"\n className=\"w-fit h-8!\"\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n >\n Alterar foto\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"h-8!\"\n onClick={handleRemovePhoto}\n >\n <IconTrash size={16} className=\"text-gray-500\" />\n </Button>\n </div>\n ) : (\n <Button\n variant=\"secondary\"\n className=\"w-fit h-8!\"\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n >\n Alterar foto\n </Button>\n )}\n </div>\n\n <div className=\"flex flex-col gap-8\">\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex gap-4\">\n <FormField\n label=\"Nome\"\n placeholder=\"Digite seu nome\"\n error={!!errors.name}\n errorMessage={errors.name?.message}\n {...register('name')}\n />\n <FormField\n label=\"Sobrenome\"\n placeholder=\"Digite seu sobrenome\"\n error={!!errors.last_name}\n errorMessage={errors.last_name?.message}\n {...register('last_name')}\n />\n </div>\n <SelectField\n label=\"Gênero\"\n placeholder=\"Selecione seu gênero\"\n options={GENDER_OPTIONS}\n value={watch('gender')}\n className=\"h-10!\"\n onChange={(value) => setValue('gender', value as string)}\n />\n <div className=\"relative\">\n <PhoneInput\n label=\"Telefone\"\n value={user?.phone ?? ''}\n disabled\n classnameContainer=\"bg-gray-50 border-0!\"\n />\n <button\n type=\"button\"\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\n onClick={() => setChangePhoneOpen(true)}\n >\n Alterar\n </button>\n </div>\n </div>\n\n <Separator />\n\n <div className=\"flex flex-col gap-4\">\n <span className=\"paragraph-medium-semibold text-gray-600\">Dados de acesso</span>\n <div className=\"relative\">\n <div className='cursor-not-allowed'>\n <FormField\n label=\"E-mail\"\n value={user?.email ?? ''}\n disabled\n classnameContainer=\"bg-gray-50 border-0!\"\n />\n </div>\n <button\n type=\"button\"\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\n onClick={() => setChangeEmailOpen(true)}\n >\n Alterar\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"fixed bottom-0 left-0 right-0 lg:static flex items-center h-20 px-4 lg:px-5 border-t border-gray-200 justify-between bg-white z-10\">\n <Button\n variant=\"secondary\"\n className=\"h-10!\"\n type=\"button\"\n disabled={isSubmitting}\n onClick={() => {\n form.reset();\n setSelectedPhoto(null);\n setPhotoRemoved(false);\n onClose();\n }}\n >\n Cancelar\n </Button>\n <Button className=\"h-10! cursor-pointer\" type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? 'Salvando...' : 'Salvar alterações'}\n </Button>\n </div>\n </form>\n\n <ChangePhoneModal open={changePhoneOpen} onClose={() => setChangePhoneOpen(false)} />\n <ChangeEmailModal open={changeEmailOpen} onClose={() => setChangeEmailOpen(false)} />\n\n <Dialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>\n <DialogContent className=\"max-w-sm! gap-5\">\n <DialogHeader>\n <DialogTitle className=\"paragraph-large-semibold text-gray-950\">\n {isOwner ? 'Excluir conta' : 'Excluir usuário'}\n </DialogTitle>\n </DialogHeader>\n <p className=\"paragraph-small-regular text-gray-600\">\n {isOwner\n ? 'Tem certeza que deseja excluir sua conta? Todos os dados serão apagados permanentemente e essa ação não pode ser desfeita.'\n : 'Tem certeza que deseja excluir seu usuário? Você perderá acesso a esta conta permanentemente.'}\n </p>\n <div className=\"flex items-center gap-3 justify-end\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"h-10!\"\n disabled={isDeleting}\n onClick={() => setDeleteConfirmOpen(false)}\n >\n Cancelar\n </Button>\n <Button\n type=\"button\"\n className=\"h-10! bg-red-600 hover:bg-red-700 text-white border-0!\"\n disabled={isDeleting}\n onClick={handleDelete}\n >\n {isDeleting ? 'Excluindo...' : 'Confirmar exclusão'}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n"],"mappings":"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","names":[]}
@@ -4,6 +4,12 @@ import { useAuth } from "../../providers/auth.provider";
4
4
  import { useWhitelabel } from "../../providers/whitelabel.provider";
5
5
  import { useActiveSubscription } from "../../modules/subscriptions/hooks/find-active-subscription.hook";
6
6
  const V4_WHITELABEL_ID = 367568;
7
+ const PROFILE_LABELS = {
8
+ owner: "Propriet\xE1rio",
9
+ admin: "Administrador",
10
+ editor: "Colaborador",
11
+ viewer: "Visualizador"
12
+ };
7
13
  const CRISP_WEBSITE_ID = "3339a3ec-b4c6-4aac-8b86-45668fb7655c";
8
14
  const CRISP_SCRIPT_URL = "https://client.crisp.chat/l.js";
9
15
  const CRISP_LOAD_DELAY = 800;
@@ -14,14 +20,37 @@ function safeCrispPush(args) {
14
20
  } catch {
15
21
  }
16
22
  }
23
+ function crispDo(action) {
24
+ safeCrispPush(["do", action]);
25
+ }
26
+ function crispSegment(segment) {
27
+ safeCrispPush(["set", "session:segments", [[segment]]]);
28
+ }
29
+ function crispSessionData(key, value) {
30
+ safeCrispPush(["set", "session:data", [[[key, value]]]]);
31
+ }
17
32
  function openCrispHelpdesk() {
18
- safeCrispPush(["do", "helpdesk:search"]);
33
+ crispDo("helpdesk:search");
19
34
  }
20
35
  function hideCrisp() {
21
- safeCrispPush(["do", "chat:hide"]);
36
+ crispDo("chat:hide");
22
37
  }
23
38
  function showCrisp() {
24
- safeCrispPush(["do", "chat:show"]);
39
+ crispDo("chat:show");
40
+ }
41
+ function updateCrispUser(data) {
42
+ try {
43
+ if (data.email) safeCrispPush(["set", "user:email", data.email]);
44
+ const fullName = `${data.name ?? ""} ${data.lastName ?? ""}`.trim();
45
+ if (fullName) safeCrispPush(["set", "user:nickname", fullName]);
46
+ if (data.company) safeCrispPush(["set", "user:company", data.company]);
47
+ const phone = `${data.ddi ?? ""}${data.phone ?? ""}`.trim();
48
+ if (phone) safeCrispPush(["set", "user:phone", phone]);
49
+ if (data.photo?.startsWith("http")) {
50
+ safeCrispPush(["set", "user:avatar", data.photo]);
51
+ }
52
+ } catch {
53
+ }
25
54
  }
26
55
  function CrispEmbed() {
27
56
  const { user, account } = useAuth();
@@ -34,9 +63,15 @@ function CrispEmbed() {
34
63
  if (!user || scriptLoadedRef.current) return;
35
64
  try {
36
65
  const win = window;
37
- win.$crisp = [];
38
- win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;
39
- win.$crisp.push(["config", "container:index", [100]]);
66
+ if (!win.$crisp) {
67
+ win.$crisp = [];
68
+ win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;
69
+ win.$crisp.push(["config", "container:index", [100]]);
70
+ }
71
+ if (document.querySelector(`script[src="${CRISP_SCRIPT_URL}"]`)) {
72
+ scriptLoadedRef.current = true;
73
+ return;
74
+ }
40
75
  const timeout = setTimeout(() => {
41
76
  try {
42
77
  if (document.querySelector(`script[src="${CRISP_SCRIPT_URL}"]`)) return;
@@ -54,26 +89,26 @@ function CrispEmbed() {
54
89
  }, [user]);
55
90
  useEffect(() => {
56
91
  try {
57
- const $crisp = window?.$crisp;
58
- if (!user || !$crisp) return;
59
- if (user.email) $crisp.push(["set", "user:email", user.email]);
60
- const fullName = `${user.name ?? ""} ${user.last_name ?? ""}`.trim();
61
- if (fullName) $crisp.push(["set", "user:nickname", fullName]);
62
- if (account?.name) $crisp.push(["set", "user:company", account.name]);
63
- const phone = `${user.ddi ?? ""}${user.phone ?? ""}`.trim();
64
- if (phone) $crisp.push(["set", "user:phone", phone]);
65
- if (user.photo && user.photo.startsWith("http")) {
66
- $crisp.push(["set", "user:avatar", user.photo]);
67
- }
92
+ if (!user || !window?.$crisp) return;
93
+ updateCrispUser({
94
+ email: user.email,
95
+ name: user.name,
96
+ lastName: user.last_name,
97
+ company: account?.name,
98
+ ddi: user.ddi,
99
+ phone: user.phone,
100
+ photo: user.photo ?? void 0
101
+ });
68
102
  if (isV4) {
69
- $crisp.push(["set", "session:segments", [["company_v4"]]]);
70
- $crisp.push(["set", "session:data", [[["Company", "V4"]]]]);
103
+ crispSegment("company_v4");
104
+ crispSessionData("Company", "V4");
71
105
  } else {
72
106
  const planName = subscription?.plan_name ?? "";
73
- if (planName) $crisp.push(["set", "session:segments", [[`plano_${planName}`]]]);
74
- if (user.profile) $crisp.push(["set", "session:segments", [[`usuario_${user.profile}`]]]);
75
- if (planName) $crisp.push(["set", "session:data", [[["Plano", planName]]]]);
76
- if (user.profile) $crisp.push(["set", "session:data", [[["Usuario", user.profile]]]]);
107
+ const profileLabel = PROFILE_LABELS[user.profile ?? ""] ?? user.profile ?? "";
108
+ if (planName) crispSegment(`plano_${planName}`);
109
+ if (profileLabel) crispSegment(`usuario_${profileLabel}`);
110
+ if (planName) crispSessionData("Plano", planName);
111
+ if (profileLabel) crispSessionData("Usuario", profileLabel);
77
112
  }
78
113
  } catch {
79
114
  }
@@ -84,6 +119,7 @@ export {
84
119
  CrispEmbed,
85
120
  hideCrisp,
86
121
  openCrispHelpdesk,
87
- showCrisp
122
+ showCrisp,
123
+ updateCrispUser
88
124
  };
89
125
  //# sourceMappingURL=CrispEmbed.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/embeds/CrispEmbed.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useAuth } from '../../providers/auth.provider';\nimport { useWhitelabel } from '../../providers/whitelabel.provider';\nimport { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';\n\nconst V4_WHITELABEL_ID = 367568;\n\nconst CRISP_WEBSITE_ID = '3339a3ec-b4c6-4aac-8b86-45668fb7655c';\nconst CRISP_SCRIPT_URL = 'https://client.crisp.chat/l.js';\nconst CRISP_LOAD_DELAY = 800;\n\nfunction safeCrispPush(args: any[]) {\n try {\n const $crisp = (window as any)?.$crisp;\n if ($crisp) $crisp.push(args);\n } catch {}\n}\n\nexport function openCrispHelpdesk() {\n safeCrispPush(['do', 'helpdesk:search']);\n}\n\nexport function hideCrisp() {\n safeCrispPush(['do', 'chat:hide']);\n}\n\nexport function showCrisp() {\n safeCrispPush(['do', 'chat:show']);\n}\n\nexport function CrispEmbed() {\n const { user, account } = useAuth();\n const { whitelabel } = useWhitelabel();\n const { data: subscriptionData } = useActiveSubscription();\n const scriptLoadedRef = useRef(false);\n\n const subscription = subscriptionData?.data?.[0] ?? null;\n const isV4 = whitelabel?.id === V4_WHITELABEL_ID;\n\n // Load Crisp script (once, with 800ms delay)\n useEffect(() => {\n if (!user || scriptLoadedRef.current) return;\n\n try {\n const win = window as any;\n win.$crisp = [];\n win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;\n win.$crisp.push(['config', 'container:index', [100]]);\n\n const timeout = setTimeout(() => {\n try {\n if (document.querySelector(`script[src=\"${CRISP_SCRIPT_URL}\"]`)) return;\n const s = document.createElement('script');\n s.src = CRISP_SCRIPT_URL;\n s.async = true;\n document.head.appendChild(s);\n scriptLoadedRef.current = true;\n } catch {}\n }, CRISP_LOAD_DELAY);\n\n return () => clearTimeout(timeout);\n } catch {}\n }, [user]);\n\n // Identify user\n useEffect(() => {\n try {\n const $crisp = (window as any)?.$crisp;\n if (!user || !$crisp) return;\n\n if (user.email) $crisp.push(['set', 'user:email', user.email]);\n\n const fullName = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();\n if (fullName) $crisp.push(['set', 'user:nickname', fullName]);\n\n if (account?.name) $crisp.push(['set', 'user:company', account.name]);\n\n const phone = `${user.ddi ?? ''}${user.phone ?? ''}`.trim();\n if (phone) $crisp.push(['set', 'user:phone', phone]);\n\n if (user.photo && user.photo.startsWith('http')) {\n $crisp.push(['set', 'user:avatar', user.photo]);\n }\n\n if (isV4) {\n $crisp.push(['set', 'session:segments', [['company_v4']]]);\n $crisp.push(['set', 'session:data', [[['Company', 'V4']]]]);\n } else {\n const planName = subscription?.plan_name ?? '';\n if (planName) $crisp.push(['set', 'session:segments', [[`plano_${planName}`]]]);\n if (user.profile) $crisp.push(['set', 'session:segments', [[`usuario_${user.profile}`]]]);\n if (planName) $crisp.push(['set', 'session:data', [[['Plano', planName]]]]);\n if (user.profile) $crisp.push(['set', 'session:data', [[['Usuario', user.profile]]]]);\n }\n } catch {}\n }, [user, account, isV4, subscription?.plan_name]);\n\n return null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/embeds/CrispEmbed.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useAuth } from '../../providers/auth.provider';\nimport { useWhitelabel } from '../../providers/whitelabel.provider';\nimport { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';\n\nconst V4_WHITELABEL_ID = 367568;\n\nconst PROFILE_LABELS: Record<string, string> = {\n owner: 'Proprietário',\n admin: 'Administrador',\n editor: 'Colaborador',\n viewer: 'Visualizador',\n};\n\nconst CRISP_WEBSITE_ID = '3339a3ec-b4c6-4aac-8b86-45668fb7655c';\nconst CRISP_SCRIPT_URL = 'https://client.crisp.chat/l.js';\nconst CRISP_LOAD_DELAY = 800;\n\n// ── Crisp helpers ──────────────────────────────────────────────\n\nfunction safeCrispPush(args: unknown[]) {\n try {\n const $crisp = (window as any)?.$crisp;\n if ($crisp) $crisp.push(args);\n } catch {}\n}\n\nfunction crispDo(action: string) {\n safeCrispPush(['do', action]);\n}\n\nfunction crispSegment(segment: string) {\n safeCrispPush(['set', 'session:segments', [[segment]]]);\n}\n\nfunction crispSessionData(key: string, value: string) {\n safeCrispPush(['set', 'session:data', [[[key, value]]]]);\n}\n\n// ── Public API ─────────────────────────────────────────────────\n\nexport function openCrispHelpdesk() {\n crispDo('helpdesk:search');\n}\n\nexport function hideCrisp() {\n crispDo('chat:hide');\n}\n\nexport function showCrisp() {\n crispDo('chat:show');\n}\n\nexport function updateCrispUser(data: {\n email?: string;\n name?: string;\n lastName?: string;\n company?: string;\n ddi?: string;\n phone?: string;\n photo?: string;\n}) {\n try {\n if (data.email) safeCrispPush(['set', 'user:email', data.email]);\n\n const fullName = `${data.name ?? ''} ${data.lastName ?? ''}`.trim();\n if (fullName) safeCrispPush(['set', 'user:nickname', fullName]);\n\n if (data.company) safeCrispPush(['set', 'user:company', data.company]);\n\n const phone = `${data.ddi ?? ''}${data.phone ?? ''}`.trim();\n if (phone) safeCrispPush(['set', 'user:phone', phone]);\n\n if (data.photo?.startsWith('http')) {\n safeCrispPush(['set', 'user:avatar', data.photo]);\n }\n } catch {}\n}\n\n// ── Component ──────────────────────────────────────────────────\n\nexport function CrispEmbed() {\n const { user, account } = useAuth();\n const { whitelabel } = useWhitelabel();\n const { data: subscriptionData } = useActiveSubscription();\n const scriptLoadedRef = useRef(false);\n\n const subscription = subscriptionData?.data?.[0] ?? null;\n const isV4 = whitelabel?.id === V4_WHITELABEL_ID;\n\n // Load Crisp script (once, with 800ms delay)\n useEffect(() => {\n if (!user || scriptLoadedRef.current) return;\n\n try {\n const win = window as any;\n\n if (!win.$crisp) {\n win.$crisp = [];\n win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;\n win.$crisp.push(['config', 'container:index', [100]]);\n }\n\n if (document.querySelector(`script[src=\"${CRISP_SCRIPT_URL}\"]`)) {\n scriptLoadedRef.current = true;\n return;\n }\n\n const timeout = setTimeout(() => {\n try {\n if (document.querySelector(`script[src=\"${CRISP_SCRIPT_URL}\"]`)) return;\n const s = document.createElement('script');\n s.src = CRISP_SCRIPT_URL;\n s.async = true;\n document.head.appendChild(s);\n scriptLoadedRef.current = true;\n } catch {}\n }, CRISP_LOAD_DELAY);\n\n return () => clearTimeout(timeout);\n } catch {}\n }, [user]);\n\n // Identify user\n useEffect(() => {\n try {\n if (!user || !(window as any)?.$crisp) return;\n\n updateCrispUser({\n email: user.email,\n name: user.name,\n lastName: user.last_name,\n company: account?.name,\n ddi: user.ddi,\n phone: user.phone,\n photo: user.photo ?? undefined,\n });\n\n if (isV4) {\n crispSegment('company_v4');\n crispSessionData('Company', 'V4');\n } else {\n const planName = subscription?.plan_name ?? '';\n const profileLabel = PROFILE_LABELS[user.profile ?? ''] ?? user.profile ?? '';\n if (planName) crispSegment(`plano_${planName}`);\n if (profileLabel) crispSegment(`usuario_${profileLabel}`);\n if (planName) crispSessionData('Plano', planName);\n if (profileLabel) crispSessionData('Usuario', profileLabel);\n }\n } catch {}\n }, [user, account, isV4, subscription?.plan_name]);\n\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect } from "react";
4
+ import { usePathname } from "next/navigation";
5
+ import { FrillEmbed } from "./FrillEmbed";
6
+ import { CrispEmbed } from "./CrispEmbed";
7
+ const EXCLUDED_ROUTES = ["/login", "/forgot-password", "/register"];
8
+ function getCrisp() {
9
+ try {
10
+ const key = "$crisp";
11
+ if (!(key in window)) return null;
12
+ const value = window[key];
13
+ return Array.isArray(value) ? value : null;
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function useHideCrispOnExcludedRoutes(isExcluded) {
19
+ useEffect(() => {
20
+ try {
21
+ const $crisp = getCrisp();
22
+ if (!$crisp) return;
23
+ if (isExcluded) {
24
+ $crisp.push(["do", "chat:hide"]);
25
+ } else {
26
+ $crisp.push(["do", "chat:show"]);
27
+ }
28
+ } catch {
29
+ }
30
+ }, [isExcluded]);
31
+ }
32
+ function EmbedWidgets() {
33
+ const pathname = usePathname();
34
+ const isExcluded = EXCLUDED_ROUTES.some((route) => pathname.startsWith(route));
35
+ useHideCrispOnExcludedRoutes(isExcluded);
36
+ if (isExcluded) return null;
37
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
38
+ /* @__PURE__ */ jsx(FrillEmbed, {}),
39
+ /* @__PURE__ */ jsx(CrispEmbed, {})
40
+ ] });
41
+ }
42
+ export {
43
+ EmbedWidgets
44
+ };
45
+ //# sourceMappingURL=EmbedWidgets.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/embeds/EmbedWidgets.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\nimport { usePathname } from 'next/navigation';\nimport { FrillEmbed } from './FrillEmbed';\nimport { CrispEmbed } from './CrispEmbed';\n\nconst EXCLUDED_ROUTES = ['/login', '/forgot-password', '/register'];\n\nfunction getCrisp(): unknown[] | null {\n try {\n const key = '$crisp';\n if (!(key in window)) return null;\n const value = window[key];\n return Array.isArray(value) ? value : null;\n } catch {\n return null;\n }\n}\n\nfunction useHideCrispOnExcludedRoutes(isExcluded: boolean) {\n useEffect(() => {\n try {\n const $crisp = getCrisp();\n if (!$crisp) return;\n\n if (isExcluded) {\n $crisp.push(['do', 'chat:hide']);\n } else {\n $crisp.push(['do', 'chat:show']);\n }\n } catch {}\n }, [isExcluded]);\n}\n\nexport function EmbedWidgets() {\n const pathname = usePathname();\n const isExcluded = EXCLUDED_ROUTES.some((route) => pathname.startsWith(route));\n\n useHideCrispOnExcludedRoutes(isExcluded);\n\n if (isExcluded) return null;\n\n return (\n <>\n <FrillEmbed />\n <CrispEmbed />\n </>\n );\n}\n"],"mappings":";AA4CI,mBACE,KADF;AA1CJ,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAE3B,MAAM,kBAAkB,CAAC,UAAU,oBAAoB,WAAW;AAElE,SAAS,WAA6B;AACpC,MAAI;AACF,UAAM,MAAM;AACZ,QAAI,EAAE,OAAO,QAAS,QAAO;AAC7B,UAAM,QAAQ,OAAO,GAAG;AACxB,WAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,6BAA6B,YAAqB;AACzD,YAAU,MAAM;AACd,QAAI;AACF,YAAM,SAAS,SAAS;AACxB,UAAI,CAAC,OAAQ;AAEb,UAAI,YAAY;AACd,eAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AAAA,MACjC,OAAO;AACL,eAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AAAA,MACjC;AAAA,IACF,QAAQ;AAAA,IAAC;AAAA,EACX,GAAG,CAAC,UAAU,CAAC;AACjB;AAEO,SAAS,eAAe;AAC7B,QAAM,WAAW,YAAY;AAC7B,QAAM,aAAa,gBAAgB,KAAK,CAAC,UAAU,SAAS,WAAW,KAAK,CAAC;AAE7E,+BAA6B,UAAU;AAEvC,MAAI,WAAY,QAAO;AAEvB,SACE,iCACE;AAAA,wBAAC,cAAW;AAAA,IACZ,oBAAC,cAAW;AAAA,KACd;AAEJ;","names":[]}
@@ -4,6 +4,12 @@ import { useAuth } from "../../providers/auth.provider";
4
4
  import { useWhitelabel } from "../../providers/whitelabel.provider";
5
5
  import { useActiveSubscription } from "../../modules/subscriptions/hooks/find-active-subscription.hook";
6
6
  const V4_WHITELABEL_ID = 367568;
7
+ const PROFILE_LABELS = {
8
+ owner: "Propriet\xE1rio",
9
+ admin: "Administrador",
10
+ editor: "Colaborador",
11
+ viewer: "Visualizador"
12
+ };
7
13
  const FRILL_SCRIPT_URL = "https://widget.frill.co/v2/container.js";
8
14
  const FRILL_KEY = "2f77f232-a120-438e-8ef6-01912ffd1b99";
9
15
  const SURVEYS = [{ key: "7f59dbf6-b665-458a-80e2-778de47efe1c" }];
@@ -61,6 +67,7 @@ function FrillEmbed() {
61
67
  const isV4 = whitelabel?.id === V4_WHITELABEL_ID;
62
68
  useEffect(() => {
63
69
  if (!user) return;
70
+ let containerPromise = null;
64
71
  try {
65
72
  initFrillLoader();
66
73
  if (document.readyState === "complete" || document.readyState === "interactive") {
@@ -75,14 +82,14 @@ function FrillEmbed() {
75
82
  if (user.name || user.last_name) {
76
83
  userData.name = `${user.name ?? ""} ${user.last_name ?? ""}`.trim();
77
84
  }
78
- userData.attributes = isV4 ? { company: "V4" } : { profile: user.profile ?? "", plan: subscription?.plan_name ?? "" };
85
+ userData.attributes = isV4 ? { company: "V4" } : { profile: PROFILE_LABELS[user.profile ?? ""] ?? user.profile ?? "", plan: subscription?.plan_name ?? "" };
79
86
  const config = { key: FRILL_KEY, user: userData };
80
87
  if (!isV4) {
81
88
  config.surveys = SURVEYS;
82
89
  config.widgets = WIDGETS;
83
90
  }
84
91
  const win = window;
85
- const containerPromise = win.Frill("container", config);
92
+ containerPromise = win.Frill("container", config);
86
93
  win.Frill("identify", userData);
87
94
  containerPromise.then((widget) => {
88
95
  containerRef.current = widget;
@@ -92,7 +99,7 @@ function FrillEmbed() {
92
99
  }
93
100
  return () => {
94
101
  try {
95
- containerRef.current?.destroy();
102
+ containerPromise?.destroy();
96
103
  containerRef.current = null;
97
104
  document.removeEventListener("DOMContentLoaded", loadFrillScript);
98
105
  } catch {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/embeds/FrillEmbed.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useAuth } from '../../providers/auth.provider';\nimport { useWhitelabel } from '../../providers/whitelabel.provider';\nimport { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';\n\nconst V4_WHITELABEL_ID = 367568;\n\nconst FRILL_SCRIPT_URL = 'https://widget.frill.co/v2/container.js';\nconst FRILL_KEY = '2f77f232-a120-438e-8ef6-01912ffd1b99';\n\nconst SURVEYS = [{ key: '7f59dbf6-b665-458a-80e2-778de47efe1c' }];\nconst WIDGETS = [\n { key: '4a5ba13b-1150-49fe-aa15-f9a2da0ba909' },\n { key: '720c0912-e6a4-495c-835e-3ff1f59d6dfc' },\n];\n\nfunction initFrillLoader() {\n try {\n const win = window as any;\n if (win.Frill) return;\n\n let counter = 0;\n const queue: Record<number, any> = {};\n\n win.Frill = function (action: string, params: any) {\n let instance: any;\n const id = counter++;\n const promise: any = new Promise((resolve, reject) => {\n queue[id] = {\n params: [action, params],\n resolve: (f: any) => {\n instance = f;\n resolve(f);\n },\n reject,\n };\n });\n promise.destroy = () => {\n delete queue[id];\n instance?.destroy();\n };\n return promise;\n };\n win.Frill.q = queue;\n } catch {}\n}\n\nfunction loadFrillScript() {\n try {\n if (document.querySelector(`script[src=\"${FRILL_SCRIPT_URL}\"]`)) return;\n const anchor = document.getElementsByTagName('script')[0];\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.async = true;\n script.src = FRILL_SCRIPT_URL;\n anchor?.parentNode?.insertBefore(script, anchor);\n } catch {}\n}\n\nexport function FrillEmbed() {\n const { user } = useAuth();\n const { whitelabel } = useWhitelabel();\n const { data: subscriptionData } = useActiveSubscription();\n const containerRef = useRef<any>(null);\n\n const subscription = subscriptionData?.data?.[0] ?? null;\n const isV4 = whitelabel?.id === V4_WHITELABEL_ID;\n\n useEffect(() => {\n if (!user) return;\n\n try {\n initFrillLoader();\n\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n loadFrillScript();\n } else {\n document.addEventListener('DOMContentLoaded', loadFrillScript);\n }\n\n const userData: Record<string, any> = {\n id: String(user.id ?? ''),\n };\n if (user.email) userData.email = user.email;\n if (user.name || user.last_name) {\n userData.name = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();\n }\n userData.attributes = isV4\n ? { company: 'V4' }\n : { profile: user.profile ?? '', plan: subscription?.plan_name ?? '' };\n\n const config: Record<string, any> = { key: FRILL_KEY, user: userData };\n if (!isV4) {\n config.surveys = SURVEYS;\n config.widgets = WIDGETS;\n }\n\n const win = window as any;\n const containerPromise = win.Frill('container', config);\n win.Frill('identify', userData);\n\n containerPromise.then((widget: any) => {\n containerRef.current = widget;\n }).catch(() => {});\n } catch {}\n\n return () => {\n try {\n containerRef.current?.destroy();\n containerRef.current = null;\n document.removeEventListener('DOMContentLoaded', loadFrillScript);\n } catch {}\n };\n }, [user, isV4, subscription?.plan_name]);\n\n return null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/embeds/FrillEmbed.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useAuth } from '../../providers/auth.provider';\nimport { useWhitelabel } from '../../providers/whitelabel.provider';\nimport { useActiveSubscription } from '../../modules/subscriptions/hooks/find-active-subscription.hook';\n\nconst V4_WHITELABEL_ID = 367568;\n\nconst PROFILE_LABELS: Record<string, string> = {\n owner: 'Proprietário',\n admin: 'Administrador',\n editor: 'Colaborador',\n viewer: 'Visualizador',\n};\n\nconst FRILL_SCRIPT_URL = 'https://widget.frill.co/v2/container.js';\nconst FRILL_KEY = '2f77f232-a120-438e-8ef6-01912ffd1b99';\n\nconst SURVEYS = [{ key: '7f59dbf6-b665-458a-80e2-778de47efe1c' }];\nconst WIDGETS = [\n { key: '4a5ba13b-1150-49fe-aa15-f9a2da0ba909' },\n { key: '720c0912-e6a4-495c-835e-3ff1f59d6dfc' },\n];\n\nfunction initFrillLoader() {\n try {\n const win = window as any;\n if (win.Frill) return;\n\n let counter = 0;\n const queue: Record<number, any> = {};\n\n win.Frill = function (action: string, params: any) {\n let instance: any;\n const id = counter++;\n const promise: any = new Promise((resolve, reject) => {\n queue[id] = {\n params: [action, params],\n resolve: (f: any) => {\n instance = f;\n resolve(f);\n },\n reject,\n };\n });\n promise.destroy = () => {\n delete queue[id];\n instance?.destroy();\n };\n return promise;\n };\n win.Frill.q = queue;\n } catch {}\n}\n\nfunction loadFrillScript() {\n try {\n if (document.querySelector(`script[src=\"${FRILL_SCRIPT_URL}\"]`)) return;\n const anchor = document.getElementsByTagName('script')[0];\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.async = true;\n script.src = FRILL_SCRIPT_URL;\n anchor?.parentNode?.insertBefore(script, anchor);\n } catch {}\n}\n\nexport function FrillEmbed() {\n const { user } = useAuth();\n const { whitelabel } = useWhitelabel();\n const { data: subscriptionData } = useActiveSubscription();\n const containerRef = useRef<any>(null);\n\n const subscription = subscriptionData?.data?.[0] ?? null;\n const isV4 = whitelabel?.id === V4_WHITELABEL_ID;\n\n useEffect(() => {\n if (!user) return;\n\n let containerPromise: any = null;\n\n try {\n initFrillLoader();\n\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n loadFrillScript();\n } else {\n document.addEventListener('DOMContentLoaded', loadFrillScript);\n }\n\n const userData: Record<string, any> = {\n id: String(user.id ?? ''),\n };\n if (user.email) userData.email = user.email;\n if (user.name || user.last_name) {\n userData.name = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();\n }\n userData.attributes = isV4\n ? { company: 'V4' }\n : { profile: PROFILE_LABELS[user.profile ?? ''] ?? user.profile ?? '', plan: subscription?.plan_name ?? '' };\n\n const config: Record<string, any> = { key: FRILL_KEY, user: userData };\n if (!isV4) {\n config.surveys = SURVEYS;\n config.widgets = WIDGETS;\n }\n\n const win = window as any;\n containerPromise = win.Frill('container', config);\n win.Frill('identify', userData);\n\n containerPromise.then((widget: any) => {\n containerRef.current = widget;\n }).catch(() => {});\n } catch {}\n\n return () => {\n try {\n // Destroy via promise — handles both pending and resolved containers\n containerPromise?.destroy();\n containerRef.current = null;\n document.removeEventListener('DOMContentLoaded', loadFrillScript);\n } catch {}\n };\n }, [user, isV4, subscription?.plan_name]);\n\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -34,7 +34,8 @@ function ProfilePopover({
34
34
  await logout();
35
35
  };
36
36
  const hasSubscription = !isSubscriptionLoading && subscription !== null;
37
- const shouldShowCredits = hasSubscription && subscription.id_wl === 1;
37
+ const isApiPlan = hasSubscription && subscription.id_plan === 411;
38
+ const shouldShowCredits = hasSubscription && subscription.id_wl === 1 && !isApiPlan;
38
39
  const creditsPercentage = shouldShowCredits && summary.totalCredits > 0 ? summary.usedCredits / summary.totalCredits * 100 : 0;
39
40
  return /* @__PURE__ */ jsxs(Fragment, { children: [
40
41
  /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Popover } from \"../ui/overlay/Popover\";\nimport { Button } from \"../ui/buttons/Button\";\nimport { Progress } from \"../ui/feedback/Progress\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { NavBarItem } from \"./NavBarItem\";\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { LoadingOverlay } from \"../ui/feedback/LoadingOverlay\";\nimport { useAuth } from \"../../providers/auth.provider\";\nimport { useWhitelabelUrls } from \"../../providers/whitelabel.provider\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\nimport { useBuyCreditsModal } from \"../../store/useBuyCreditsModal\";\n\nexport interface ProfileMenuItem {\n icon?: React.ReactNode;\n label: string;\n onClick: () => void;\n}\n\nexport interface ProfilePopoverProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n menuItems?: ProfileMenuItem[];\n}\n\nfunction ProfilePopover({\n side = \"top\",\n align = \"start\",\n contentClassName = \"absolute bottom-2 left-[26px]\",\n menuItems = [],\n}: ProfilePopoverProps) {\n const { user, logout } = useAuth();\n const [isLoggingOut, setIsLoggingOut] = useState(false);\n const [popoverOpen, setPopoverOpen] = useState(false);\n\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\n useIaCredits();\n const { openModal: openBuyCreditsModal } = useBuyCreditsModal();\n const { accountsUrl } = useWhitelabelUrls();\n const router = useRouter();\n\n const handleLogout = async () => {\n setPopoverOpen(false);\n setIsLoggingOut(true);\n await logout();\n };\n\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\n\n const shouldShowCredits = hasSubscription && subscription.id_wl === 1;\n const creditsPercentage =\n shouldShowCredits && summary.totalCredits > 0\n ? (summary.usedCredits / summary.totalCredits) * 100\n : 0;\n\n return (\n <>\n <LoadingOverlay\n isLoading={isLoggingOut}\n message=\"Saindo da sua conta...\"\n />\n <Popover open={popoverOpen} onOpenChange={setPopoverOpen}>\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={40}\n />\n )}\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n className={cn(\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={32}\n />\n )}\n\n <div className=\"flex flex-col gap-0.5 min-w-0\">\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\n {user?.name || \"\"}\n </span>\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\n {user?.email || \"\"}\n </span>\n </div>\n\n <Button\n variant=\"secondary\"\n className=\"h-8! px-3! paragraph-xsmall-semibold\"\n onClick={() => {\n const isSameOrigin = accountsUrl.startsWith(window.location.origin);\n if (isSameOrigin) {\n setPopoverOpen(false);\n router.push(`${window.location.pathname}?openProfile=true`);\n } else {\n window.location.href = `${accountsUrl}?openProfile=true`;\n }\n }}\n >\n Editar\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\n {shouldShowCredits && (\n <div\n className={cn(\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\n \"cursor-pointer hover:bg-gray-950/90\",\n )}\n onClick={() => openBuyCreditsModal()}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\n Créditos usados\n </span>\n <span className=\"paragraph-xsmall-medium text-white/50\">\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\n </span>\n </div>\n <Progress\n className=\"bg-white/10\"\n indicatorColor=\"bg-white\"\n value={creditsPercentage}\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-col\">\n {menuItems.map((item, index) => (\n <NavBarItem\n key={index}\n icon={item.icon}\n label={item.label}\n onClick={item.onClick}\n />\n ))}\n </div>\n <Separator />\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </Popover>\n </>\n );\n}\n\nexport { ProfilePopover };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/layouts/ProfilePopover.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { useRouter } from \"next/navigation\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Popover } from \"../ui/overlay/Popover\";\nimport { Button } from \"../ui/buttons/Button\";\nimport { Progress } from \"../ui/feedback/Progress\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { NavBarItem } from \"./NavBarItem\";\nimport { UserAvatar } from \"../ui/data-display/UserAvatar\";\nimport { LoadingOverlay } from \"../ui/feedback/LoadingOverlay\";\nimport { useAuth } from \"../../providers/auth.provider\";\nimport { useWhitelabelUrls } from \"../../providers/whitelabel.provider\";\nimport { cn } from \"../../infra/utils/clsx\";\nimport { useIaCredits } from \"../../modules/ia-credits/hooks/ia-credits.hook\";\nimport { useBuyCreditsModal } from \"../../store/useBuyCreditsModal\";\n\nexport interface ProfileMenuItem {\n icon?: React.ReactNode;\n label: string;\n onClick: () => void;\n}\n\nexport interface ProfilePopoverProps {\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n align?: \"start\" | \"center\" | \"end\";\n contentClassName?: string;\n menuItems?: ProfileMenuItem[];\n}\n\nfunction ProfilePopover({\n side = \"top\",\n align = \"start\",\n contentClassName = \"absolute bottom-2 left-[26px]\",\n menuItems = [],\n}: ProfilePopoverProps) {\n const { user, logout } = useAuth();\n const [isLoggingOut, setIsLoggingOut] = useState(false);\n const [popoverOpen, setPopoverOpen] = useState(false);\n\n const { summary, subscription, isSubscriptionLoading, isCreditsLoading } =\n useIaCredits();\n const { openModal: openBuyCreditsModal } = useBuyCreditsModal();\n const { accountsUrl } = useWhitelabelUrls();\n const router = useRouter();\n\n const handleLogout = async () => {\n setPopoverOpen(false);\n setIsLoggingOut(true);\n await logout();\n };\n\n const hasSubscription = !isSubscriptionLoading && subscription !== null;\n\n const isApiPlan = hasSubscription && subscription.id_plan === 411;\n const shouldShowCredits = hasSubscription && subscription.id_wl === 1 && !isApiPlan;\n const creditsPercentage =\n shouldShowCredits && summary.totalCredits > 0\n ? (summary.usedCredits / summary.totalCredits) * 100\n : 0;\n\n return (\n <>\n <LoadingOverlay\n isLoading={isLoggingOut}\n message=\"Saindo da sua conta...\"\n />\n <Popover open={popoverOpen} onOpenChange={setPopoverOpen}>\n <PopoverPrimitive.Trigger className=\"cursor-pointer\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={40}\n />\n )}\n </PopoverPrimitive.Trigger>\n\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n className={cn(\n \"w-64.75 p-0 bg-white rounded-2xl shadow-md border border-gray-200 z-99\",\n contentClassName,\n )}\n side={side}\n align={align}\n sideOffset={8}\n >\n <div className=\"grid grid-cols-[32px_1fr_auto] items-center gap-3 p-3 w-full\">\n {user && (\n <UserAvatar\n key={user.id}\n photo={user.photo}\n name={user.name}\n size={32}\n />\n )}\n\n <div className=\"flex flex-col gap-0.5 min-w-0\">\n <span className=\"paragraph-small-semibold text-gray-950 truncate\">\n {user?.name || \"\"}\n </span>\n <span className=\"paragraph-xsmall-medium text-gray-500 truncate\">\n {user?.email || \"\"}\n </span>\n </div>\n\n <Button\n variant=\"secondary\"\n className=\"h-8! px-3! paragraph-xsmall-semibold\"\n onClick={() => {\n const isSameOrigin = accountsUrl.startsWith(window.location.origin);\n if (isSameOrigin) {\n setPopoverOpen(false);\n router.push(`${window.location.pathname}?openProfile=true`);\n } else {\n window.location.href = `${accountsUrl}?openProfile=true`;\n }\n }}\n >\n Editar\n </Button>\n </div>\n\n <div className=\"flex flex-col gap-2 border-t border-gray-200 rounded-2xl p-1.5\">\n {shouldShowCredits && (\n <div\n className={cn(\n \"flex flex-col bg-gray-950 rounded-lg gap-4 w-full p-4 transition-colors\",\n \"cursor-pointer hover:bg-gray-950/90\",\n )}\n onClick={() => openBuyCreditsModal()}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"paragraph-xsmall-semibold text-white truncate\">\n Créditos usados\n </span>\n <span className=\"paragraph-xsmall-medium text-white/50\">\n {summary.usedCredits.toLocaleString(\"pt-BR\")}/\n {summary.totalCredits.toLocaleString(\"pt-BR\")}\n </span>\n </div>\n <Progress\n className=\"bg-white/10\"\n indicatorColor=\"bg-white\"\n value={creditsPercentage}\n />\n </div>\n )}\n\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-col\">\n {menuItems.map((item, index) => (\n <NavBarItem\n key={index}\n icon={item.icon}\n label={item.label}\n onClick={item.onClick}\n />\n ))}\n </div>\n <Separator />\n <NavBarItem label=\"Sair\" onClick={handleLogout} />\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </Popover>\n </>\n );\n}\n\nexport { ProfilePopover };\n"],"mappings":"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","names":[]}
@@ -8,7 +8,7 @@ import { useModalManager } from "../../../store/useModalManager";
8
8
  import { useCreateCard } from "../../../modules/cards/hooks/create-card.hook";
9
9
  import { useUpdateAccount } from "../../../modules/accounts/hooks/useAccountManagement";
10
10
  import { CardFormFields, BillingFormFields, cardFormSchema } from "./CardFormFields";
11
- import { IconX } from "@tabler/icons-react";
11
+ import { IconLoader2, IconX } from "@tabler/icons-react";
12
12
  import { useForm } from "react-hook-form";
13
13
  import { zodResolver } from "@hookform/resolvers/zod";
14
14
  import { CardNumberElement, useElements, useStripe } from "@stripe/react-stripe-js";
@@ -63,7 +63,7 @@ function AddCardModal() {
63
63
  setStripeErrors(newStripeErrors);
64
64
  const stripeValid = stripeStatus.cardNumber && stripeStatus.cardExpiry && stripeStatus.cardCvc;
65
65
  if (rhfValid && stripeValid) {
66
- form.clearErrors(["fullName", "cep", "street", "streetNumber", "city", "state"]);
66
+ form.clearErrors(["fullName", "cep", "street", "streetNumber", "neighborhood", "city", "state"]);
67
67
  setCurrentStep(2);
68
68
  }
69
69
  }, [form, stripeStatus]);
@@ -114,6 +114,7 @@ function AddCardModal() {
114
114
  address: data.street,
115
115
  address_number: data.streetNumber,
116
116
  address_complement: data.complement || "",
117
+ neighborhood: data.neighborhood,
117
118
  city: data.city,
118
119
  state: data.state
119
120
  })
@@ -141,10 +142,10 @@ function AddCardModal() {
141
142
  }
142
143
  }
143
144
  const isSubmitting = createCardMutation.isPending || updateAccountMutation.isPending || form.formState.isSubmitting;
144
- const watchedValues = form.watch(["name", "country", "personType", "cpf", "cnpj", "fullName", "cep", "street", "streetNumber", "city", "state"]);
145
- const [name, country, personType, cpf, cnpj, fullName, cep, street, streetNumber, city, state] = watchedValues;
145
+ const watchedValues = form.watch(["name", "country", "personType", "cpf", "cnpj", "fullName", "cep", "street", "streetNumber", "neighborhood", "city", "state"]);
146
+ const [name, country, personType, cpf, cnpj, fullName, cep, street, streetNumber, neighborhood, city, state] = watchedValues;
146
147
  const isStep1Valid = !!name && !!country && !!personType && (personType === "pf" ? !!cpf && cpf.length >= 14 : !!cnpj && cnpj.length >= 18) && stripeStatus.cardNumber && stripeStatus.cardExpiry && stripeStatus.cardCvc;
147
- const isStep2Valid = !!fullName && !!cep && cep.length >= 9 && !!street && !!streetNumber && !!city && !!state;
148
+ const isStep2Valid = !!fullName && !!cep && cep.length >= 9 && !!street && !!streetNumber && !!neighborhood && !!city && !!state;
148
149
  return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(
149
150
  DialogContent,
150
151
  {
@@ -200,7 +201,10 @@ function AddCardModal() {
200
201
  )
201
202
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
202
203
  /* @__PURE__ */ jsx(Button, { variant: "secondary", type: "button", onClick: handleBack, className: "h-10!", children: "Voltar" }),
203
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "h-10!", disabled: isSubmitting || !isStep2Valid, children: isSubmitting ? "Adicionando cart\xE3o..." : "Adicionar cart\xE3o" })
204
+ /* @__PURE__ */ jsxs(Button, { type: "submit", className: "h-10!", disabled: isSubmitting || !isStep2Valid, children: [
205
+ isSubmitting && /* @__PURE__ */ jsx(IconLoader2, { className: "size-4 animate-spin" }),
206
+ isSubmitting ? "Adicionando cart\xE3o..." : "Adicionar cart\xE3o"
207
+ ] })
204
208
  ] }) })
205
209
  ]
206
210
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/modals/cards/AddCardModal.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useState } from 'react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Button } from '../../ui/buttons/Button';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { useModalManager } from '../../../store/useModalManager';\nimport { useCreateCard } from '../../../modules/cards/hooks/create-card.hook';\nimport { useUpdateAccount } from '../../../modules/accounts/hooks/useAccountManagement';\nimport { CardFormFields, BillingFormFields, cardFormSchema } from './CardFormFields';\nimport type { CardFormData, StripeElementsStatus } from './CardFormFields';\nimport { IconX } from '@tabler/icons-react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { CardNumberElement, useElements, useStripe } from '@stripe/react-stripe-js';\nimport { toast } from 'sonner';\n\nconst INITIAL_STRIPE_STATUS: StripeElementsStatus = {\n cardNumber: false,\n cardExpiry: false,\n cardCvc: false,\n};\n\nexport default function AddCardModal() {\n const { activeModal, modalData, closeModal } = useModalManager();\n const isOpen = activeModal === 'addCardModal';\n const [currentStep, setCurrentStep] = useState(1);\n const [stripeStatus, setStripeStatus] = useState<StripeElementsStatus>(INITIAL_STRIPE_STATUS);\n const [stripeErrors, setStripeErrors] = useState<Record<string, string | undefined>>({});\n\n const onCardAdded = modalData.onCardAdded as ((cardId: string) => void) | undefined;\n\n const createCardMutation = useCreateCard();\n const updateAccountMutation = useUpdateAccount();\n const elements = useElements();\n const stripe = useStripe();\n\n const form = useForm<CardFormData>({\n resolver: zodResolver(cardFormSchema),\n mode: 'onSubmit',\n reValidateMode: 'onChange',\n defaultValues: {\n country: 'BR',\n personType: 'pf',\n },\n });\n\n const handleClose = useCallback(() => {\n form.reset();\n setCurrentStep(1);\n setStripeStatus(INITIAL_STRIPE_STATUS);\n setStripeErrors({});\n closeModal();\n }, [form, closeModal]);\n\n const handleStripeChange = useCallback(\n (field: keyof StripeElementsStatus, complete: boolean) => {\n setStripeStatus((prev) => ({ ...prev, [field]: complete }));\n if (complete) {\n setStripeErrors((prev) => ({ ...prev, [field]: undefined }));\n }\n },\n []\n );\n\n const handleContinue = useCallback(async () => {\n const rhfValid = await form.trigger(['name', 'country', 'personType', 'cpf', 'cnpj']);\n\n const newStripeErrors: Record<string, string | undefined> = {};\n if (!stripeStatus.cardNumber) newStripeErrors.cardNumber = 'Número do cartão é obrigatório';\n if (!stripeStatus.cardExpiry) newStripeErrors.cardExpiry = 'Data de validade é obrigatória';\n if (!stripeStatus.cardCvc) newStripeErrors.cardCvc = 'Código de segurança é obrigatório';\n setStripeErrors(newStripeErrors);\n\n const stripeValid = stripeStatus.cardNumber && stripeStatus.cardExpiry && stripeStatus.cardCvc;\n\n if (rhfValid && stripeValid) {\n form.clearErrors(['fullName', 'cep', 'street', 'streetNumber', 'city', 'state']);\n setCurrentStep(2);\n }\n }, [form, stripeStatus]);\n\n const handleBack = useCallback(() => {\n setCurrentStep(1);\n }, []);\n\n async function handleSubmit(data: CardFormData) {\n if (!stripe || !elements) return;\n\n const cardElement = elements.getElement(CardNumberElement);\n if (!cardElement) return;\n\n const { error, paymentMethod } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardElement,\n billing_details: {\n name: data.fullName,\n address: {\n country: data.country,\n postal_code: data.cep,\n line1: `${data.street}, ${data.streetNumber}`,\n line2: data.complement || undefined,\n city: data.city,\n state: data.state,\n },\n },\n });\n\n if (error) {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível adicionar o cartão na Stripe, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n return;\n }\n\n try {\n const [cardResult] = await Promise.all([\n createCardMutation.mutateAsync({ payment_method_id: paymentMethod.id }),\n updateAccountMutation.mutateAsync({\n financial_document_type: data.personType === 'pf' ? 1 : 2,\n financial_document: data.personType === 'pf' ? data.cpf : data.cnpj,\n financial_name: data.fullName,\n zipcode: data.cep,\n address: data.street,\n address_number: data.streetNumber,\n address_complement: data.complement || '',\n city: data.city,\n state: data.state,\n }),\n ]);\n\n if (cardResult.success && cardResult.data?.id != null) {\n onCardAdded?.(cardResult.data.id.toString());\n }\n\n toast.custom(\n (t) => <Toast variant=\"success\" message=\"Cartão adicionado com sucesso.\" toastId={t} />,\n { duration: 5000 }\n );\n handleClose();\n } catch {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível salvar o seu novo cartão, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n }\n }\n\n const isSubmitting =\n createCardMutation.isPending ||\n updateAccountMutation.isPending ||\n form.formState.isSubmitting;\n\n const watchedValues = form.watch(['name', 'country', 'personType', 'cpf', 'cnpj', 'fullName', 'cep', 'street', 'streetNumber', 'city', 'state']);\n const [name, country, personType, cpf, cnpj, fullName, cep, street, streetNumber, city, state] = watchedValues;\n const isStep1Valid =\n !!name &&\n !!country &&\n !!personType &&\n (personType === 'pf' ? !!cpf && cpf.length >= 14 : !!cnpj && cnpj.length >= 18) &&\n stripeStatus.cardNumber &&\n stripeStatus.cardExpiry &&\n stripeStatus.cardCvc;\n const isStep2Valid =\n !!fullName &&\n !!cep && cep.length >= 9 &&\n !!street &&\n !!streetNumber &&\n !!city &&\n !!state;\n\n return (\n <Dialog open={isOpen} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\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-[470px] lg:h-auto lg:max-h-[90vh] 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%] overflow-y-auto\"\n >\n <DialogHeader className=\"p-0\">\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-zinc-200 lg:border-b-0\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950 text-center\">\n {currentStep === 1 ? 'Adicionar cartão' : 'Dados de cobrança'}\n </DialogTitle>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n </DialogHeader>\n\n {/* Progress bar */}\n <div className=\"h-1 bg-zinc-100 w-full\">\n <div\n className=\"h-full bg-cyan-400 transition-all duration-300 ease-in-out\"\n style={{ width: currentStep === 1 ? '50%' : '100%' }}\n />\n </div>\n\n <form\n onSubmit={form.handleSubmit(handleSubmit)}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className={`flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none ${currentStep !== 1 ? 'hidden' : ''}`}>\n <CardFormFields\n form={form}\n onStripeChange={handleStripeChange}\n stripeErrors={stripeErrors}\n />\n </div>\n <div className={`flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none ${currentStep !== 2 ? 'hidden' : ''}`}>\n <BillingFormFields form={form} />\n </div>\n\n <div className=\"flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0\">\n {currentStep === 1 ? (\n <>\n <Button variant=\"secondary\" type=\"button\" onClick={handleClose} className=\"h-10!\">\n Cancelar\n </Button>\n <Button\n type=\"button\"\n className=\"h-10!\"\n onClick={handleContinue}\n disabled={!isStep1Valid}\n >\n Continuar\n </Button>\n </>\n ) : (\n <>\n <Button variant=\"secondary\" type=\"button\" onClick={handleBack} className=\"h-10!\">\n Voltar\n </Button>\n <Button type=\"submit\" className=\"h-10!\" disabled={isSubmitting || !isStep2Valid}>\n {isSubmitting ? 'Adicionando cartão...' : 'Adicionar cartão'}\n </Button>\n </>\n )}\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/modals/cards/AddCardModal.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useState } from 'react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Button } from '../../ui/buttons/Button';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { useModalManager } from '../../../store/useModalManager';\nimport { useCreateCard } from '../../../modules/cards/hooks/create-card.hook';\nimport { useUpdateAccount } from '../../../modules/accounts/hooks/useAccountManagement';\nimport { CardFormFields, BillingFormFields, cardFormSchema } from './CardFormFields';\nimport type { CardFormData, StripeElementsStatus } from './CardFormFields';\nimport { IconLoader2, IconX } from '@tabler/icons-react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { CardNumberElement, useElements, useStripe } from '@stripe/react-stripe-js';\nimport { toast } from 'sonner';\n\nconst INITIAL_STRIPE_STATUS: StripeElementsStatus = {\n cardNumber: false,\n cardExpiry: false,\n cardCvc: false,\n};\n\nexport default function AddCardModal() {\n const { activeModal, modalData, closeModal } = useModalManager();\n const isOpen = activeModal === 'addCardModal';\n const [currentStep, setCurrentStep] = useState(1);\n const [stripeStatus, setStripeStatus] = useState<StripeElementsStatus>(INITIAL_STRIPE_STATUS);\n const [stripeErrors, setStripeErrors] = useState<Record<string, string | undefined>>({});\n\n const onCardAdded = modalData.onCardAdded as ((cardId: string) => void) | undefined;\n\n const createCardMutation = useCreateCard();\n const updateAccountMutation = useUpdateAccount();\n const elements = useElements();\n const stripe = useStripe();\n\n const form = useForm<CardFormData>({\n resolver: zodResolver(cardFormSchema),\n mode: 'onSubmit',\n reValidateMode: 'onChange',\n defaultValues: {\n country: 'BR',\n personType: 'pf',\n },\n });\n\n const handleClose = useCallback(() => {\n form.reset();\n setCurrentStep(1);\n setStripeStatus(INITIAL_STRIPE_STATUS);\n setStripeErrors({});\n closeModal();\n }, [form, closeModal]);\n\n const handleStripeChange = useCallback(\n (field: keyof StripeElementsStatus, complete: boolean) => {\n setStripeStatus((prev) => ({ ...prev, [field]: complete }));\n if (complete) {\n setStripeErrors((prev) => ({ ...prev, [field]: undefined }));\n }\n },\n []\n );\n\n const handleContinue = useCallback(async () => {\n const rhfValid = await form.trigger(['name', 'country', 'personType', 'cpf', 'cnpj']);\n\n const newStripeErrors: Record<string, string | undefined> = {};\n if (!stripeStatus.cardNumber) newStripeErrors.cardNumber = 'Número do cartão é obrigatório';\n if (!stripeStatus.cardExpiry) newStripeErrors.cardExpiry = 'Data de validade é obrigatória';\n if (!stripeStatus.cardCvc) newStripeErrors.cardCvc = 'Código de segurança é obrigatório';\n setStripeErrors(newStripeErrors);\n\n const stripeValid = stripeStatus.cardNumber && stripeStatus.cardExpiry && stripeStatus.cardCvc;\n\n if (rhfValid && stripeValid) {\n form.clearErrors(['fullName', 'cep', 'street', 'streetNumber', 'neighborhood', 'city', 'state']);\n setCurrentStep(2);\n }\n }, [form, stripeStatus]);\n\n const handleBack = useCallback(() => {\n setCurrentStep(1);\n }, []);\n\n async function handleSubmit(data: CardFormData) {\n if (!stripe || !elements) return;\n\n const cardElement = elements.getElement(CardNumberElement);\n if (!cardElement) return;\n\n const { error, paymentMethod } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardElement,\n billing_details: {\n name: data.fullName,\n address: {\n country: data.country,\n postal_code: data.cep,\n line1: `${data.street}, ${data.streetNumber}`,\n line2: data.complement || undefined,\n city: data.city,\n state: data.state,\n },\n },\n });\n\n if (error) {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível adicionar o cartão na Stripe, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n return;\n }\n\n try {\n const [cardResult] = await Promise.all([\n createCardMutation.mutateAsync({ payment_method_id: paymentMethod.id }),\n updateAccountMutation.mutateAsync({\n financial_document_type: data.personType === 'pf' ? 1 : 2,\n financial_document: data.personType === 'pf' ? data.cpf : data.cnpj,\n financial_name: data.fullName,\n zipcode: data.cep,\n address: data.street,\n address_number: data.streetNumber,\n address_complement: data.complement || '',\n neighborhood: data.neighborhood,\n city: data.city,\n state: data.state,\n }),\n ]);\n\n if (cardResult.success && cardResult.data?.id != null) {\n onCardAdded?.(cardResult.data.id.toString());\n }\n\n toast.custom(\n (t) => <Toast variant=\"success\" message=\"Cartão adicionado com sucesso.\" toastId={t} />,\n { duration: 5000 }\n );\n handleClose();\n } catch {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível salvar o seu novo cartão, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n }\n }\n\n const isSubmitting =\n createCardMutation.isPending ||\n updateAccountMutation.isPending ||\n form.formState.isSubmitting;\n\n const watchedValues = form.watch(['name', 'country', 'personType', 'cpf', 'cnpj', 'fullName', 'cep', 'street', 'streetNumber', 'neighborhood', 'city', 'state']);\n const [name, country, personType, cpf, cnpj, fullName, cep, street, streetNumber, neighborhood, city, state] = watchedValues;\n const isStep1Valid =\n !!name &&\n !!country &&\n !!personType &&\n (personType === 'pf' ? !!cpf && cpf.length >= 14 : !!cnpj && cnpj.length >= 18) &&\n stripeStatus.cardNumber &&\n stripeStatus.cardExpiry &&\n stripeStatus.cardCvc;\n const isStep2Valid =\n !!fullName &&\n !!cep && cep.length >= 9 &&\n !!street &&\n !!streetNumber &&\n !!neighborhood &&\n !!city &&\n !!state;\n\n return (\n <Dialog open={isOpen} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\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-[470px] lg:h-auto lg:max-h-[90vh] 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%] overflow-y-auto\"\n >\n <DialogHeader className=\"p-0\">\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-zinc-200 lg:border-b-0\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950 text-center\">\n {currentStep === 1 ? 'Adicionar cartão' : 'Dados de cobrança'}\n </DialogTitle>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n </DialogHeader>\n\n {/* Progress bar */}\n <div className=\"h-1 bg-zinc-100 w-full\">\n <div\n className=\"h-full bg-cyan-400 transition-all duration-300 ease-in-out\"\n style={{ width: currentStep === 1 ? '50%' : '100%' }}\n />\n </div>\n\n <form\n onSubmit={form.handleSubmit(handleSubmit)}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className={`flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none ${currentStep !== 1 ? 'hidden' : ''}`}>\n <CardFormFields\n form={form}\n onStripeChange={handleStripeChange}\n stripeErrors={stripeErrors}\n />\n </div>\n <div className={`flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none ${currentStep !== 2 ? 'hidden' : ''}`}>\n <BillingFormFields form={form} />\n </div>\n\n <div className=\"flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0\">\n {currentStep === 1 ? (\n <>\n <Button variant=\"secondary\" type=\"button\" onClick={handleClose} className=\"h-10!\">\n Cancelar\n </Button>\n <Button\n type=\"button\"\n className=\"h-10!\"\n onClick={handleContinue}\n disabled={!isStep1Valid}\n >\n Continuar\n </Button>\n </>\n ) : (\n <>\n <Button variant=\"secondary\" type=\"button\" onClick={handleBack} className=\"h-10!\">\n Voltar\n </Button>\n <Button type=\"submit\" className=\"h-10!\" disabled={isSubmitting || !isStep2Valid}>\n {isSubmitting && <IconLoader2 className=\"size-4 animate-spin\" />}\n {isSubmitting ? 'Adicionando cartão...' : 'Adicionar cartão'}\n </Button>\n </>\n )}\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}