@greatapps/common 1.1.202 → 1.1.205

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.
@@ -42,6 +42,7 @@ function MyProfileSection({ onClose, storageUrl }) {
42
42
  mode: "onChange",
43
43
  defaultValues: {
44
44
  name: user?.name ?? "",
45
+ last_name: user?.last_name ?? "",
45
46
  gender: GENDER_OPTIONS.find((g) => g.apiValue === user?.gender)?.value ?? ""
46
47
  }
47
48
  });
@@ -89,6 +90,7 @@ function MyProfileSection({ onClose, storageUrl }) {
89
90
  try {
90
91
  await updateAccountUser.mutateAsync({
91
92
  name: data.name,
93
+ last_name: data.last_name,
92
94
  gender: GENDER_OPTIONS.find((g) => g.value === data.gender)?.apiValue,
93
95
  ...selectedPhoto ? { photo: selectedPhoto } : {},
94
96
  ...photoRemoved ? { photo: "" } : {}
@@ -177,16 +179,28 @@ function MyProfileSection({ onClose, storageUrl }) {
177
179
  ] }),
178
180
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
179
181
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
180
- /* @__PURE__ */ jsx(
181
- FormField,
182
- {
183
- label: "Nome completo",
184
- placeholder: "Digite seu nome",
185
- error: !!errors.name,
186
- errorMessage: errors.name?.message,
187
- ...register("name")
188
- }
189
- ),
182
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
183
+ /* @__PURE__ */ jsx(
184
+ FormField,
185
+ {
186
+ label: "Nome",
187
+ placeholder: "Digite seu nome",
188
+ error: !!errors.name,
189
+ errorMessage: errors.name?.message,
190
+ ...register("name")
191
+ }
192
+ ),
193
+ /* @__PURE__ */ jsx(
194
+ FormField,
195
+ {
196
+ label: "Sobrenome",
197
+ placeholder: "Digite seu sobrenome",
198
+ error: !!errors.last_name,
199
+ errorMessage: errors.last_name?.message,
200
+ ...register("last_name")
201
+ }
202
+ )
203
+ ] }),
190
204
  /* @__PURE__ */ jsx(
191
205
  SelectField,
192
206
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/account/sections/MyProfileSection.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useRef } from 'react';\r\nimport Image from 'next/image';\r\nimport { useForm } from 'react-hook-form';\r\nimport { zodResolver } from '@hookform/resolvers/zod';\r\nimport { toast } from 'sonner';\r\nimport { Upload, Trash } from 'lucide-react';\r\nimport { Button } from '../../ui/buttons/Button';\r\nimport { Separator } from '../../ui/data-display/Separator';\r\nimport { Toast } from '../../ui/feedback/Toast';\r\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\r\nimport { FormField } from '../../ui/form/FormField';\r\nimport { SelectField } from '../../ui/form/SelectField';\r\nimport PhoneInput from '../../ui/form/PhoneInput';\r\nimport { useAuth } from '../../../providers/auth.provider';\r\nimport { UserProfile } from '../../../modules/users/schema';\r\nimport { myProfileSchema, type MyProfileFormData } from '../../../utils/validators/account';\r\nimport {\r\n useUpdateAccountUser,\r\n useDeleteAccount,\r\n useDeleteAccountUser,\r\n} from '../../../modules/accounts/hooks/useAccountManagement';\r\nimport { GENDER_OPTIONS } from '../constants';\r\nimport { ChangePhoneModal } from './ChangePhoneModal';\r\nimport { ChangeEmailModal } from './ChangeEmailModal';\r\n\r\ninterface MyProfileSectionProps {\r\n onClose: () => void;\r\n storageUrl?: string;\r\n}\r\n\r\nexport function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps) {\r\n const { user, logout } = useAuth();\r\n const updateAccountUser = useUpdateAccountUser();\r\n const deleteAccount = useDeleteAccount();\r\n const deleteAccountUser = useDeleteAccountUser();\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const [selectedPhoto, setSelectedPhoto] = useState<File | null>(null);\r\n const [photoRemoved, setPhotoRemoved] = useState(false);\r\n const [changePhoneOpen, setChangePhoneOpen] = useState(false);\r\n const [changeEmailOpen, setChangeEmailOpen] = useState(false);\r\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\r\n\r\n const isOwner = user?.profile === UserProfile.owner;\r\n const isDeleting = deleteAccount.isPending || deleteAccountUser.isPending;\r\n\r\n const form = useForm<MyProfileFormData>({\r\n resolver: zodResolver(myProfileSchema),\r\n mode: 'onChange',\r\n defaultValues: {\r\n name: user?.name ?? '',\r\n gender: GENDER_OPTIONS.find((g) => g.apiValue === user?.gender)?.value ?? '',\r\n },\r\n });\r\n\r\n const {\r\n register,\r\n handleSubmit,\r\n watch,\r\n setValue,\r\n formState: { errors, isSubmitting },\r\n } = form;\r\n\r\n const baseStorageUrl = storageUrl ?? process.env.NEXT_PUBLIC_STORAGE_URL ?? '';\r\n\r\n const avatarPreview = selectedPhoto\r\n ? URL.createObjectURL(selectedPhoto)\r\n : !photoRemoved && user?.photo\r\n ? `${baseStorageUrl}/${user.photo}`\r\n : null;\r\n\r\n const handlePhotoChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0] ?? null;\r\n if (file) {\r\n setSelectedPhoto(file);\r\n setPhotoRemoved(false);\r\n }\r\n };\r\n\r\n const handleRemovePhoto = () => {\r\n setSelectedPhoto(null);\r\n setPhotoRemoved(true);\r\n };\r\n\r\n const handleDelete = async () => {\r\n try {\r\n if (isOwner) {\r\n await deleteAccount.mutateAsync();\r\n } else {\r\n await deleteAccountUser.mutateAsync(user!.id);\r\n }\r\n await logout();\r\n } catch (error) {\r\n toast.custom((t) => (\r\n <Toast\r\n variant=\"error\"\r\n message={error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.'}\r\n toastId={t}\r\n />\r\n ));\r\n setDeleteConfirmOpen(false);\r\n }\r\n };\r\n\r\n const onSubmit = async (data: MyProfileFormData) => {\r\n try {\r\n await updateAccountUser.mutateAsync({\r\n name: data.name,\r\n gender: GENDER_OPTIONS.find((g) => g.value === data.gender)?.apiValue,\r\n ...(selectedPhoto ? { photo: selectedPhoto } : {}),\r\n ...(photoRemoved ? { photo: '' } : {}),\r\n });\r\n\r\n form.reset(data);\r\n setSelectedPhoto(null);\r\n setPhotoRemoved(false);\r\n toast.custom((t) => (\r\n <Toast variant=\"success\" message=\"Perfil atualizado com sucesso\" toastId={t} />\r\n ));\r\n onClose();\r\n } catch (error) {\r\n toast.custom((t) => (\r\n <Toast\r\n variant=\"error\"\r\n message={error instanceof Error ? error.message : 'Erro ao atualizar perfil'}\r\n toastId={t}\r\n />\r\n ));\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <form onSubmit={handleSubmit(onSubmit)} className=\"lg:h-full lg:flex lg:flex-col\">\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n className=\"hidden\"\r\n onChange={handlePhotoChange}\r\n />\r\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\">\r\n <span className=\"paragraph-medium-semibold text-gray-950 hidden lg:block\">\r\n Meu perfil\r\n </span>\r\n <div className=\"flex flex-col gap-5\">\r\n <div className=\"flex items-center gap-4\">\r\n {avatarPreview ? (\r\n <Image\r\n src={avatarPreview}\r\n alt=\"Foto do usuário\"\r\n width={48}\r\n height={48}\r\n className=\"size-12 rounded-full object-cover cursor-pointer\"\r\n onClick={() => fileInputRef.current?.click()}\r\n />\r\n ) : (\r\n <div\r\n className=\"size-12 rounded-full bg-gray-50 border border-dashed border-gray-200 flex items-center justify-center cursor-pointer\"\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n <Upload size={20} className=\"text-gray-400\" />\r\n </div>\r\n )}\r\n {avatarPreview ? (\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"w-fit h-8!\"\r\n type=\"button\"\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n Alterar foto\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n className=\"h-8!\"\r\n onClick={handleRemovePhoto}\r\n >\r\n <Trash size={16} className=\"text-gray-500\" />\r\n </Button>\r\n </div>\r\n ) : (\r\n <Button\r\n variant=\"secondary\"\r\n className=\"w-fit h-8!\"\r\n type=\"button\"\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n Alterar foto\r\n </Button>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex flex-col gap-8\">\r\n <div className=\"flex flex-col gap-4\">\r\n <FormField\r\n label=\"Nome completo\"\r\n placeholder=\"Digite seu nome\"\r\n error={!!errors.name}\r\n errorMessage={errors.name?.message}\r\n {...register('name')}\r\n />\r\n <SelectField\r\n label=\"Gênero\"\r\n placeholder=\"Selecione seu gênero\"\r\n options={GENDER_OPTIONS}\r\n value={watch('gender')}\r\n className=\"h-10!\"\r\n onChange={(value) => setValue('gender', value as string)}\r\n />\r\n <div className=\"relative\">\r\n <PhoneInput\r\n label=\"Telefone\"\r\n value={user?.phone ?? ''}\r\n disabled\r\n classnameContainer=\"bg-gray-50 border-0!\"\r\n />\r\n <button\r\n type=\"button\"\r\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\r\n onClick={() => setChangePhoneOpen(true)}\r\n >\r\n Alterar\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <Separator />\r\n\r\n <div className=\"flex flex-col gap-4\">\r\n <span className=\"paragraph-medium-semibold text-gray-600\">Dados de acesso</span>\r\n <div className=\"relative\">\r\n <div className='cursor-not-allowed'>\r\n <FormField\r\n label=\"E-mail\"\r\n value={user?.email ?? ''}\r\n disabled\r\n classnameContainer=\"bg-gray-50 border-0!\"\r\n />\r\n </div>\r\n <button\r\n type=\"button\"\r\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\r\n onClick={() => setChangeEmailOpen(true)}\r\n >\r\n Alterar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\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\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"h-10!\"\r\n type=\"button\"\r\n disabled={isSubmitting}\r\n onClick={() => {\r\n form.reset();\r\n setSelectedPhoto(null);\r\n setPhotoRemoved(false);\r\n onClose();\r\n }}\r\n >\r\n Cancelar\r\n </Button>\r\n <Button className=\"h-10! cursor-pointer\" type=\"submit\" disabled={isSubmitting}>\r\n {isSubmitting ? 'Salvando...' : 'Salvar alterações'}\r\n </Button>\r\n </div>\r\n </form>\r\n\r\n <ChangePhoneModal open={changePhoneOpen} onClose={() => setChangePhoneOpen(false)} />\r\n <ChangeEmailModal open={changeEmailOpen} onClose={() => setChangeEmailOpen(false)} />\r\n\r\n <Dialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>\r\n <DialogContent className=\"max-w-sm! gap-5\">\r\n <DialogHeader>\r\n <DialogTitle className=\"paragraph-large-semibold text-gray-950\">\r\n {isOwner ? 'Excluir conta' : 'Excluir usuário'}\r\n </DialogTitle>\r\n </DialogHeader>\r\n <p className=\"paragraph-small-regular text-gray-600\">\r\n {isOwner\r\n ? 'Tem certeza que deseja excluir sua conta? Todos os dados serão apagados permanentemente e essa ação não pode ser desfeita.'\r\n : 'Tem certeza que deseja excluir seu usuário? Você perderá acesso a esta conta permanentemente.'}\r\n </p>\r\n <div className=\"flex items-center gap-3 justify-end\">\r\n <Button\r\n type=\"button\"\r\n variant=\"secondary\"\r\n className=\"h-10!\"\r\n disabled={isDeleting}\r\n onClick={() => setDeleteConfirmOpen(false)}\r\n >\r\n Cancelar\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n className=\"h-10! bg-red-600 hover:bg-red-700 text-white border-0!\"\r\n disabled={isDeleting}\r\n onClick={handleDelete}\r\n >\r\n {isDeleting ? 'Excluindo...' : 'Confirmar exclusão'}\r\n </Button>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n </>\r\n );\r\n}\r\n"],"mappings":";AA+FQ,SAsCJ,UAtCI,KAuEQ,YAvER;AA7FR,SAAS,UAAU,cAAc;AACjC,OAAO,WAAW;AAClB,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,aAAa;AACtB,SAAS,QAAQ,aAAa;AAC9B,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AACtB,SAAS,QAAQ,eAAe,cAAc,mBAAmB;AACjE,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,OAAO,gBAAgB;AACvB,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,uBAA+C;AACxD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AAO1B,SAAS,iBAAiB,EAAE,SAAS,WAAW,GAA0B;AAC/E,QAAM,EAAE,MAAM,OAAO,IAAI,QAAQ;AACjC,QAAM,oBAAoB,qBAAqB;AAC/C,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,oBAAoB,qBAAqB;AAC/C,QAAM,eAAe,OAAyB,IAAI;AAClD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAsB,IAAI;AACpE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAC5D,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAC5D,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAEhE,QAAM,UAAU,MAAM,YAAY,YAAY;AAC9C,QAAM,aAAa,cAAc,aAAa,kBAAkB;AAEhE,QAAM,OAAO,QAA2B;AAAA,IACtC,UAAU,YAAY,eAAe;AAAA,IACrC,MAAM;AAAA,IACN,eAAe;AAAA,MACb,MAAM,MAAM,QAAQ;AAAA,MACpB,QAAQ,eAAe,KAAK,CAAC,MAAM,EAAE,aAAa,MAAM,MAAM,GAAG,SAAS;AAAA,IAC5E;AAAA,EACF,CAAC;AAED,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,EAAE,QAAQ,aAAa;AAAA,EACpC,IAAI;AAEJ,QAAM,iBAAiB,cAAc,QAAQ,IAAI,2BAA2B;AAE5E,QAAM,gBAAgB,gBAClB,IAAI,gBAAgB,aAAa,IACjC,CAAC,gBAAgB,MAAM,QACrB,GAAG,cAAc,IAAI,KAAK,KAAK,KAC/B;AAEN,QAAM,oBAAoB,CAAC,MAA2C;AACpE,UAAM,OAAO,EAAE,OAAO,QAAQ,CAAC,KAAK;AACpC,QAAI,MAAM;AACR,uBAAiB,IAAI;AACrB,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,oBAAoB,MAAM;AAC9B,qBAAiB,IAAI;AACrB,oBAAgB,IAAI;AAAA,EACtB;AAEA,QAAM,eAAe,YAAY;AAC/B,QAAI;AACF,UAAI,SAAS;AACX,cAAM,cAAc,YAAY;AAAA,MAClC,OAAO;AACL,cAAM,kBAAkB,YAAY,KAAM,EAAE;AAAA,MAC9C;AACA,YAAM,OAAO;AAAA,IACf,SAAS,OAAO;AACd,YAAM,OAAO,CAAC,MACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAClD,SAAS;AAAA;AAAA,MACX,CACD;AACD,2BAAqB,KAAK;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,WAAW,OAAO,SAA4B;AAClD,QAAI;AACF,YAAM,kBAAkB,YAAY;AAAA,QAClC,MAAM,KAAK;AAAA,QACX,QAAQ,eAAe,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,GAAG;AAAA,QAC7D,GAAI,gBAAgB,EAAE,OAAO,cAAc,IAAI,CAAC;AAAA,QAChD,GAAI,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;AAAA,MACtC,CAAC;AAED,WAAK,MAAM,IAAI;AACf,uBAAiB,IAAI;AACrB,sBAAgB,KAAK;AACrB,YAAM,OAAO,CAAC,MACZ,oBAAC,SAAM,SAAQ,WAAU,SAAQ,iCAAgC,SAAS,GAAG,CAC9E;AACD,cAAQ;AAAA,IACV,SAAS,OAAO;AACd,YAAM,OAAO,CAAC,MACZ;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAClD,SAAS;AAAA;AAAA,MACX,CACD;AAAA,IACH;AAAA,EACF;AAEA,SACE,iCACE;AAAA,yBAAC,UAAK,UAAU,aAAa,QAAQ,GAAG,WAAU,iCAChD;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL,QAAO;AAAA,UACP,WAAU;AAAA,UACV,UAAU;AAAA;AAAA,MACZ;AAAA,MACA,qBAAC,SAAI,WAAU,wJACb;AAAA,4BAAC,UAAK,WAAU,2DAA0D,wBAE1E;AAAA,QACA,qBAAC,SAAI,WAAU,uBACb;AAAA,+BAAC,SAAI,WAAU,2BACZ;AAAA,4BACC;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK;AAAA,gBACL,KAAI;AAAA,gBACJ,OAAO;AAAA,gBACP,QAAQ;AAAA,gBACR,WAAU;AAAA,gBACV,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA;AAAA,YAC7C,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,gBAE3C,8BAAC,UAAO,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,YAC9C;AAAA,YAED,gBACC,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,kBAC5C;AAAA;AAAA,cAED;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,SAAS;AAAA,kBAET,8BAAC,SAAM,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,cAC7C;AAAA,eACF,IAEA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,WAAU;AAAA,gBACV,MAAK;AAAA,gBACL,SAAS,MAAM,aAAa,SAAS,MAAM;AAAA,gBAC5C;AAAA;AAAA,YAED;AAAA,aAEJ;AAAA,UAEA,qBAAC,SAAI,WAAU,uBACb;AAAA,iCAAC,SAAI,WAAU,uBACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAM;AAAA,kBACN,aAAY;AAAA,kBACZ,OAAO,CAAC,CAAC,OAAO;AAAA,kBAChB,cAAc,OAAO,MAAM;AAAA,kBAC1B,GAAG,SAAS,MAAM;AAAA;AAAA,cACrB;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAM;AAAA,kBACN,aAAY;AAAA,kBACZ,SAAS;AAAA,kBACT,OAAO,MAAM,QAAQ;AAAA,kBACrB,WAAU;AAAA,kBACV,UAAU,CAAC,UAAU,SAAS,UAAU,KAAe;AAAA;AAAA,cACzD;AAAA,cACA,qBAAC,SAAI,WAAU,YACb;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,OAAO,MAAM,SAAS;AAAA,oBACtB,UAAQ;AAAA,oBACR,oBAAmB;AAAA;AAAA,gBACrB;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,WAAU;AAAA,oBACV,SAAS,MAAM,mBAAmB,IAAI;AAAA,oBACvC;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,eACF;AAAA,YAEA,oBAAC,aAAU;AAAA,YAEX,qBAAC,SAAI,WAAU,uBACb;AAAA,kCAAC,UAAK,WAAU,2CAA0C,6BAAe;AAAA,cACzE,qBAAC,SAAI,WAAU,YACb;AAAA,oCAAC,SAAI,WAAU,sBACb;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,OAAO,MAAM,SAAS;AAAA,oBACtB,UAAQ;AAAA,oBACR,oBAAmB;AAAA;AAAA,gBACrB,GACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,WAAU;AAAA,oBACV,SAAS,MAAM,mBAAmB,IAAI;AAAA,oBACvC;AAAA;AAAA,gBAED;AAAA,iBACF;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA,SACF;AAAA,MAEA,qBAAC,SAAI,WAAU,sIACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,MAAK;AAAA,YACL,UAAU;AAAA,YACV,SAAS,MAAM;AACb,mBAAK,MAAM;AACX,+BAAiB,IAAI;AACrB,8BAAgB,KAAK;AACrB,sBAAQ;AAAA,YACV;AAAA,YACD;AAAA;AAAA,QAED;AAAA,QACA,oBAAC,UAAO,WAAU,wBAAuB,MAAK,UAAS,UAAU,cAC9D,yBAAe,gBAAgB,2BAClC;AAAA,SACF;AAAA,OACF;AAAA,IAEA,oBAAC,oBAAiB,MAAM,iBAAiB,SAAS,MAAM,mBAAmB,KAAK,GAAG;AAAA,IACnF,oBAAC,oBAAiB,MAAM,iBAAiB,SAAS,MAAM,mBAAmB,KAAK,GAAG;AAAA,IAEnF,oBAAC,UAAO,MAAM,mBAAmB,cAAc,sBAC7C,+BAAC,iBAAc,WAAU,mBACvB;AAAA,0BAAC,gBACC,8BAAC,eAAY,WAAU,0CACpB,oBAAU,kBAAkB,sBAC/B,GACF;AAAA,MACA,oBAAC,OAAE,WAAU,yCACV,oBACG,2IACA,0GACN;AAAA,MACA,qBAAC,SAAI,WAAU,uCACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,UAAU;AAAA,YACV,SAAS,MAAM,qBAAqB,KAAK;AAAA,YAC1C;AAAA;AAAA,QAED;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,UAAU;AAAA,YACV,SAAS;AAAA,YAER,uBAAa,iBAAiB;AAAA;AAAA,QACjC;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/account/sections/MyProfileSection.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useRef } from 'react';\r\nimport Image from 'next/image';\r\nimport { useForm } from 'react-hook-form';\r\nimport { zodResolver } from '@hookform/resolvers/zod';\r\nimport { toast } from 'sonner';\r\nimport { Upload, Trash } from 'lucide-react';\r\nimport { Button } from '../../ui/buttons/Button';\r\nimport { Separator } from '../../ui/data-display/Separator';\r\nimport { Toast } from '../../ui/feedback/Toast';\r\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\r\nimport { FormField } from '../../ui/form/FormField';\r\nimport { SelectField } from '../../ui/form/SelectField';\r\nimport PhoneInput from '../../ui/form/PhoneInput';\r\nimport { useAuth } from '../../../providers/auth.provider';\r\nimport { UserProfile } from '../../../modules/users/schema';\r\nimport { myProfileSchema, type MyProfileFormData } from '../../../utils/validators/account';\r\nimport {\r\n useUpdateAccountUser,\r\n useDeleteAccount,\r\n useDeleteAccountUser,\r\n} from '../../../modules/accounts/hooks/useAccountManagement';\r\nimport { GENDER_OPTIONS } from '../constants';\r\nimport { ChangePhoneModal } from './ChangePhoneModal';\r\nimport { ChangeEmailModal } from './ChangeEmailModal';\r\n\r\ninterface MyProfileSectionProps {\r\n onClose: () => void;\r\n storageUrl?: string;\r\n}\r\n\r\nexport function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps) {\r\n const { user, logout } = useAuth();\r\n const updateAccountUser = useUpdateAccountUser();\r\n const deleteAccount = useDeleteAccount();\r\n const deleteAccountUser = useDeleteAccountUser();\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const [selectedPhoto, setSelectedPhoto] = useState<File | null>(null);\r\n const [photoRemoved, setPhotoRemoved] = useState(false);\r\n const [changePhoneOpen, setChangePhoneOpen] = useState(false);\r\n const [changeEmailOpen, setChangeEmailOpen] = useState(false);\r\n const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);\r\n\r\n const isOwner = user?.profile === UserProfile.owner;\r\n const isDeleting = deleteAccount.isPending || deleteAccountUser.isPending;\r\n\r\n const form = useForm<MyProfileFormData>({\r\n resolver: zodResolver(myProfileSchema),\r\n mode: 'onChange',\r\n defaultValues: {\r\n name: user?.name ?? '',\r\n last_name: user?.last_name ?? '',\r\n gender: GENDER_OPTIONS.find((g) => g.apiValue === user?.gender)?.value ?? '',\r\n },\r\n });\r\n\r\n const {\r\n register,\r\n handleSubmit,\r\n watch,\r\n setValue,\r\n formState: { errors, isSubmitting },\r\n } = form;\r\n\r\n const baseStorageUrl = storageUrl ?? process.env.NEXT_PUBLIC_STORAGE_URL ?? '';\r\n\r\n const avatarPreview = selectedPhoto\r\n ? URL.createObjectURL(selectedPhoto)\r\n : !photoRemoved && user?.photo\r\n ? `${baseStorageUrl}/${user.photo}`\r\n : null;\r\n\r\n const handlePhotoChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0] ?? null;\r\n if (file) {\r\n setSelectedPhoto(file);\r\n setPhotoRemoved(false);\r\n }\r\n };\r\n\r\n const handleRemovePhoto = () => {\r\n setSelectedPhoto(null);\r\n setPhotoRemoved(true);\r\n };\r\n\r\n const handleDelete = async () => {\r\n try {\r\n if (isOwner) {\r\n await deleteAccount.mutateAsync();\r\n } else {\r\n await deleteAccountUser.mutateAsync(user!.id);\r\n }\r\n await logout();\r\n } catch (error) {\r\n toast.custom((t) => (\r\n <Toast\r\n variant=\"error\"\r\n message={error instanceof Error ? error.message : 'Erro ao excluir. Tente novamente.'}\r\n toastId={t}\r\n />\r\n ));\r\n setDeleteConfirmOpen(false);\r\n }\r\n };\r\n\r\n const onSubmit = async (data: MyProfileFormData) => {\r\n try {\r\n await updateAccountUser.mutateAsync({\r\n name: data.name,\r\n last_name: data.last_name,\r\n gender: GENDER_OPTIONS.find((g) => g.value === data.gender)?.apiValue,\r\n ...(selectedPhoto ? { photo: selectedPhoto } : {}),\r\n ...(photoRemoved ? { photo: '' } : {}),\r\n });\r\n\r\n form.reset(data);\r\n setSelectedPhoto(null);\r\n setPhotoRemoved(false);\r\n toast.custom((t) => (\r\n <Toast variant=\"success\" message=\"Perfil atualizado com sucesso\" toastId={t} />\r\n ));\r\n onClose();\r\n } catch (error) {\r\n toast.custom((t) => (\r\n <Toast\r\n variant=\"error\"\r\n message={error instanceof Error ? error.message : 'Erro ao atualizar perfil'}\r\n toastId={t}\r\n />\r\n ));\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <form onSubmit={handleSubmit(onSubmit)} className=\"lg:h-full lg:flex lg:flex-col\">\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n className=\"hidden\"\r\n onChange={handlePhotoChange}\r\n />\r\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\">\r\n <span className=\"paragraph-medium-semibold text-gray-950 hidden lg:block\">\r\n Meu perfil\r\n </span>\r\n <div className=\"flex flex-col gap-5\">\r\n <div className=\"flex items-center gap-4\">\r\n {avatarPreview ? (\r\n <Image\r\n src={avatarPreview}\r\n alt=\"Foto do usuário\"\r\n width={48}\r\n height={48}\r\n className=\"size-12 rounded-full object-cover cursor-pointer\"\r\n onClick={() => fileInputRef.current?.click()}\r\n />\r\n ) : (\r\n <div\r\n className=\"size-12 rounded-full bg-gray-50 border border-dashed border-gray-200 flex items-center justify-center cursor-pointer\"\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n <Upload size={20} className=\"text-gray-400\" />\r\n </div>\r\n )}\r\n {avatarPreview ? (\r\n <div className=\"flex items-center gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"w-fit h-8!\"\r\n type=\"button\"\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n Alterar foto\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n variant=\"ghost\"\r\n className=\"h-8!\"\r\n onClick={handleRemovePhoto}\r\n >\r\n <Trash size={16} className=\"text-gray-500\" />\r\n </Button>\r\n </div>\r\n ) : (\r\n <Button\r\n variant=\"secondary\"\r\n className=\"w-fit h-8!\"\r\n type=\"button\"\r\n onClick={() => fileInputRef.current?.click()}\r\n >\r\n Alterar foto\r\n </Button>\r\n )}\r\n </div>\r\n\r\n <div className=\"flex flex-col gap-8\">\r\n <div className=\"flex flex-col gap-4\">\r\n <div className=\"flex gap-4\">\r\n <FormField\r\n label=\"Nome\"\r\n placeholder=\"Digite seu nome\"\r\n error={!!errors.name}\r\n errorMessage={errors.name?.message}\r\n {...register('name')}\r\n />\r\n <FormField\r\n label=\"Sobrenome\"\r\n placeholder=\"Digite seu sobrenome\"\r\n error={!!errors.last_name}\r\n errorMessage={errors.last_name?.message}\r\n {...register('last_name')}\r\n />\r\n </div>\r\n <SelectField\r\n label=\"Gênero\"\r\n placeholder=\"Selecione seu gênero\"\r\n options={GENDER_OPTIONS}\r\n value={watch('gender')}\r\n className=\"h-10!\"\r\n onChange={(value) => setValue('gender', value as string)}\r\n />\r\n <div className=\"relative\">\r\n <PhoneInput\r\n label=\"Telefone\"\r\n value={user?.phone ?? ''}\r\n disabled\r\n classnameContainer=\"bg-gray-50 border-0!\"\r\n />\r\n <button\r\n type=\"button\"\r\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\r\n onClick={() => setChangePhoneOpen(true)}\r\n >\r\n Alterar\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <Separator />\r\n\r\n <div className=\"flex flex-col gap-4\">\r\n <span className=\"paragraph-medium-semibold text-gray-600\">Dados de acesso</span>\r\n <div className=\"relative\">\r\n <div className='cursor-not-allowed'>\r\n <FormField\r\n label=\"E-mail\"\r\n value={user?.email ?? ''}\r\n disabled\r\n classnameContainer=\"bg-gray-50 border-0!\"\r\n />\r\n </div>\r\n <button\r\n type=\"button\"\r\n className=\"absolute right-3 top-5.5 h-10 flex items-center paragraph-xsmall-semibold text-gray-950 underline cursor-pointer\"\r\n onClick={() => setChangeEmailOpen(true)}\r\n >\r\n Alterar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\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\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"h-10!\"\r\n type=\"button\"\r\n disabled={isSubmitting}\r\n onClick={() => {\r\n form.reset();\r\n setSelectedPhoto(null);\r\n setPhotoRemoved(false);\r\n onClose();\r\n }}\r\n >\r\n Cancelar\r\n </Button>\r\n <Button className=\"h-10! cursor-pointer\" type=\"submit\" disabled={isSubmitting}>\r\n {isSubmitting ? 'Salvando...' : 'Salvar alterações'}\r\n </Button>\r\n </div>\r\n </form>\r\n\r\n <ChangePhoneModal open={changePhoneOpen} onClose={() => setChangePhoneOpen(false)} />\r\n <ChangeEmailModal open={changeEmailOpen} onClose={() => setChangeEmailOpen(false)} />\r\n\r\n <Dialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>\r\n <DialogContent className=\"max-w-sm! gap-5\">\r\n <DialogHeader>\r\n <DialogTitle className=\"paragraph-large-semibold text-gray-950\">\r\n {isOwner ? 'Excluir conta' : 'Excluir usuário'}\r\n </DialogTitle>\r\n </DialogHeader>\r\n <p className=\"paragraph-small-regular text-gray-600\">\r\n {isOwner\r\n ? 'Tem certeza que deseja excluir sua conta? Todos os dados serão apagados permanentemente e essa ação não pode ser desfeita.'\r\n : 'Tem certeza que deseja excluir seu usuário? Você perderá acesso a esta conta permanentemente.'}\r\n </p>\r\n <div className=\"flex items-center gap-3 justify-end\">\r\n <Button\r\n type=\"button\"\r\n variant=\"secondary\"\r\n className=\"h-10!\"\r\n disabled={isDeleting}\r\n onClick={() => setDeleteConfirmOpen(false)}\r\n >\r\n Cancelar\r\n </Button>\r\n <Button\r\n type=\"button\"\r\n className=\"h-10! bg-red-600 hover:bg-red-700 text-white border-0!\"\r\n disabled={isDeleting}\r\n onClick={handleDelete}\r\n >\r\n {isDeleting ? 'Excluindo...' : 'Confirmar exclusão'}\r\n </Button>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n </>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
@@ -7,20 +7,21 @@ const V4_WHITELABEL_ID = 367568;
7
7
  const CRISP_WEBSITE_ID = "3339a3ec-b4c6-4aac-8b86-45668fb7655c";
8
8
  const CRISP_SCRIPT_URL = "https://client.crisp.chat/l.js";
9
9
  const CRISP_LOAD_DELAY = 800;
10
- function openCrispHelpdesk() {
11
- if (typeof window !== "undefined" && window.$crisp) {
12
- window.$crisp.push(["do", "helpdesk:search"]);
10
+ function safeCrispPush(args) {
11
+ try {
12
+ const $crisp = window?.$crisp;
13
+ if ($crisp) $crisp.push(args);
14
+ } catch {
13
15
  }
14
16
  }
17
+ function openCrispHelpdesk() {
18
+ safeCrispPush(["do", "helpdesk:search"]);
19
+ }
15
20
  function hideCrisp() {
16
- if (typeof window !== "undefined" && window.$crisp) {
17
- window.$crisp.push(["do", "chat:hide"]);
18
- }
21
+ safeCrispPush(["do", "chat:hide"]);
19
22
  }
20
23
  function showCrisp() {
21
- if (typeof window !== "undefined" && window.$crisp) {
22
- window.$crisp.push(["do", "chat:show"]);
23
- }
24
+ safeCrispPush(["do", "chat:show"]);
24
25
  }
25
26
  function CrispEmbed() {
26
27
  const { user, account } = useAuth();
@@ -31,41 +32,50 @@ function CrispEmbed() {
31
32
  const isV4 = whitelabel?.id === V4_WHITELABEL_ID;
32
33
  useEffect(() => {
33
34
  if (!user || scriptLoadedRef.current) return;
34
- const win = window;
35
- win.$crisp = [];
36
- win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;
37
- win.$crisp.push(["config", "container:index", [100]]);
38
- const timeout = setTimeout(() => {
39
- if (document.querySelector(`script[src="${CRISP_SCRIPT_URL}"]`)) return;
40
- const s = document.createElement("script");
41
- s.src = CRISP_SCRIPT_URL;
42
- s.async = true;
43
- document.head.appendChild(s);
44
- scriptLoadedRef.current = true;
45
- }, CRISP_LOAD_DELAY);
46
- return () => clearTimeout(timeout);
35
+ try {
36
+ const win = window;
37
+ win.$crisp = [];
38
+ win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;
39
+ win.$crisp.push(["config", "container:index", [100]]);
40
+ const timeout = setTimeout(() => {
41
+ try {
42
+ if (document.querySelector(`script[src="${CRISP_SCRIPT_URL}"]`)) return;
43
+ const s = document.createElement("script");
44
+ s.src = CRISP_SCRIPT_URL;
45
+ s.async = true;
46
+ document.head.appendChild(s);
47
+ scriptLoadedRef.current = true;
48
+ } catch {
49
+ }
50
+ }, CRISP_LOAD_DELAY);
51
+ return () => clearTimeout(timeout);
52
+ } catch {
53
+ }
47
54
  }, [user]);
48
55
  useEffect(() => {
49
- const $crisp = window.$crisp;
50
- if (!user || !$crisp) return;
51
- if (user.email) $crisp.push(["set", "user:email", user.email]);
52
- const fullName = `${user.name ?? ""} ${user.last_name ?? ""}`.trim();
53
- if (fullName) $crisp.push(["set", "user:nickname", fullName]);
54
- if (account?.name) $crisp.push(["set", "user:company", account.name]);
55
- const phone = `${user.ddi ?? ""}${user.phone ?? ""}`.trim();
56
- if (phone) $crisp.push(["set", "user:phone", phone]);
57
- if (user.photo && user.photo.startsWith("http")) {
58
- $crisp.push(["set", "user:avatar", user.photo]);
59
- }
60
- if (isV4) {
61
- $crisp.push(["set", "session:segments", [["company_v4"]]]);
62
- $crisp.push(["set", "session:data", [[["Company", "V4"]]]]);
63
- } else {
64
- const planName = subscription?.plan_name ?? "";
65
- if (planName) $crisp.push(["set", "session:segments", [[`plano_${planName}`]]]);
66
- if (user.profile) $crisp.push(["set", "session:segments", [[`usuario_${user.profile}`]]]);
67
- if (planName) $crisp.push(["set", "session:data", [[["Plano", planName]]]]);
68
- if (user.profile) $crisp.push(["set", "session:data", [[["Usuario", user.profile]]]]);
56
+ 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
+ }
68
+ if (isV4) {
69
+ $crisp.push(["set", "session:segments", [["company_v4"]]]);
70
+ $crisp.push(["set", "session:data", [[["Company", "V4"]]]]);
71
+ } else {
72
+ 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]]]]);
77
+ }
78
+ } catch {
69
79
  }
70
80
  }, [user, account, isV4, subscription?.plan_name]);
71
81
  return null;
@@ -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\nexport function openCrispHelpdesk() {\n if (typeof window !== 'undefined' && (window as any).$crisp) {\n (window as any).$crisp.push(['do', 'helpdesk:search']);\n }\n}\n\nexport function hideCrisp() {\n if (typeof window !== 'undefined' && (window as any).$crisp) {\n (window as any).$crisp.push(['do', 'chat:hide']);\n }\n}\n\nexport function showCrisp() {\n if (typeof window !== 'undefined' && (window as any).$crisp) {\n (window as any).$crisp.push(['do', 'chat:show']);\n }\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 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 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 }, CRISP_LOAD_DELAY);\n\n return () => clearTimeout(timeout);\n }, [user]);\n\n // Identify user\n useEffect(() => {\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 }, [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 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":[]}
@@ -12,39 +12,45 @@ const WIDGETS = [
12
12
  { key: "720c0912-e6a4-495c-835e-3ff1f59d6dfc" }
13
13
  ];
14
14
  function initFrillLoader() {
15
- const win = window;
16
- if (win.Frill) return;
17
- let counter = 0;
18
- const queue = {};
19
- win.Frill = function(action, params) {
20
- let instance;
21
- const id = counter++;
22
- const promise = new Promise((resolve, reject) => {
23
- queue[id] = {
24
- params: [action, params],
25
- resolve: (f) => {
26
- instance = f;
27
- resolve(f);
28
- },
29
- reject
15
+ try {
16
+ const win = window;
17
+ if (win.Frill) return;
18
+ let counter = 0;
19
+ const queue = {};
20
+ win.Frill = function(action, params) {
21
+ let instance;
22
+ const id = counter++;
23
+ const promise = new Promise((resolve, reject) => {
24
+ queue[id] = {
25
+ params: [action, params],
26
+ resolve: (f) => {
27
+ instance = f;
28
+ resolve(f);
29
+ },
30
+ reject
31
+ };
32
+ });
33
+ promise.destroy = () => {
34
+ delete queue[id];
35
+ instance?.destroy();
30
36
  };
31
- });
32
- promise.destroy = () => {
33
- delete queue[id];
34
- instance?.destroy();
37
+ return promise;
35
38
  };
36
- return promise;
37
- };
38
- win.Frill.q = queue;
39
+ win.Frill.q = queue;
40
+ } catch {
41
+ }
39
42
  }
40
43
  function loadFrillScript() {
41
- if (document.querySelector(`script[src="${FRILL_SCRIPT_URL}"]`)) return;
42
- const anchor = document.getElementsByTagName("script")[0];
43
- const script = document.createElement("script");
44
- script.type = "text/javascript";
45
- script.async = true;
46
- script.src = FRILL_SCRIPT_URL;
47
- anchor?.parentNode?.insertBefore(script, anchor);
44
+ try {
45
+ if (document.querySelector(`script[src="${FRILL_SCRIPT_URL}"]`)) return;
46
+ const anchor = document.getElementsByTagName("script")[0];
47
+ const script = document.createElement("script");
48
+ script.type = "text/javascript";
49
+ script.async = true;
50
+ script.src = FRILL_SCRIPT_URL;
51
+ anchor?.parentNode?.insertBefore(script, anchor);
52
+ } catch {
53
+ }
48
54
  }
49
55
  function FrillEmbed() {
50
56
  const { user } = useAuth();
@@ -55,36 +61,42 @@ function FrillEmbed() {
55
61
  const isV4 = whitelabel?.id === V4_WHITELABEL_ID;
56
62
  useEffect(() => {
57
63
  if (!user) return;
58
- initFrillLoader();
59
- if (document.readyState === "complete" || document.readyState === "interactive") {
60
- loadFrillScript();
61
- } else {
62
- document.addEventListener("DOMContentLoaded", loadFrillScript);
63
- }
64
- const userData = {
65
- id: String(user.id ?? "")
66
- };
67
- if (user.email) userData.email = user.email;
68
- if (user.name || user.last_name) {
69
- userData.name = `${user.name ?? ""} ${user.last_name ?? ""}`.trim();
70
- }
71
- userData.attributes = isV4 ? { company: "V4" } : { profile: user.profile ?? "", plan: subscription?.plan_name ?? "" };
72
- const config = { key: FRILL_KEY, user: userData };
73
- if (!isV4) {
74
- config.surveys = SURVEYS;
75
- config.widgets = WIDGETS;
64
+ try {
65
+ initFrillLoader();
66
+ if (document.readyState === "complete" || document.readyState === "interactive") {
67
+ loadFrillScript();
68
+ } else {
69
+ document.addEventListener("DOMContentLoaded", loadFrillScript);
70
+ }
71
+ const userData = {
72
+ id: String(user.id ?? "")
73
+ };
74
+ if (user.email) userData.email = user.email;
75
+ if (user.name || user.last_name) {
76
+ userData.name = `${user.name ?? ""} ${user.last_name ?? ""}`.trim();
77
+ }
78
+ userData.attributes = isV4 ? { company: "V4" } : { profile: user.profile ?? "", plan: subscription?.plan_name ?? "" };
79
+ const config = { key: FRILL_KEY, user: userData };
80
+ if (!isV4) {
81
+ config.surveys = SURVEYS;
82
+ config.widgets = WIDGETS;
83
+ }
84
+ const win = window;
85
+ const containerPromise = win.Frill("container", config);
86
+ win.Frill("identify", userData);
87
+ containerPromise.then((widget) => {
88
+ containerRef.current = widget;
89
+ }).catch(() => {
90
+ });
91
+ } catch {
76
92
  }
77
- const win = window;
78
- const containerPromise = win.Frill("container", config);
79
- win.Frill("identify", userData);
80
- containerPromise.then((widget) => {
81
- containerRef.current = widget;
82
- }).catch(() => {
83
- });
84
93
  return () => {
85
- containerRef.current?.destroy();
86
- containerRef.current = null;
87
- document.removeEventListener("DOMContentLoaded", loadFrillScript);
94
+ try {
95
+ containerRef.current?.destroy();
96
+ containerRef.current = null;
97
+ document.removeEventListener("DOMContentLoaded", loadFrillScript);
98
+ } catch {
99
+ }
88
100
  };
89
101
  }, [user, isV4, subscription?.plan_name]);
90
102
  return null;
@@ -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 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}\n\nfunction loadFrillScript() {\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}\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 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\n return () => {\n containerRef.current?.destroy();\n containerRef.current = null;\n document.removeEventListener('DOMContentLoaded', loadFrillScript);\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 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":";AAEA,SAAS,WAAW,cAAc;AAClC,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AAEtC,MAAM,mBAAmB;AAEzB,MAAM,mBAAmB;AACzB,MAAM,YAAY;AAElB,MAAM,UAAU,CAAC,EAAE,KAAK,uCAAuC,CAAC;AAChE,MAAM,UAAU;AAAA,EACd,EAAE,KAAK,uCAAuC;AAAA,EAC9C,EAAE,KAAK,uCAAuC;AAChD;AAEA,SAAS,kBAAkB;AACzB,MAAI;AACF,UAAM,MAAM;AACZ,QAAI,IAAI,MAAO;AAEf,QAAI,UAAU;AACd,UAAM,QAA6B,CAAC;AAEpC,QAAI,QAAQ,SAAU,QAAgB,QAAa;AACjD,UAAI;AACJ,YAAM,KAAK;AACX,YAAM,UAAe,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpD,cAAM,EAAE,IAAI;AAAA,UACV,QAAQ,CAAC,QAAQ,MAAM;AAAA,UACvB,SAAS,CAAC,MAAW;AACnB,uBAAW;AACX,oBAAQ,CAAC;AAAA,UACX;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AACD,cAAQ,UAAU,MAAM;AACtB,eAAO,MAAM,EAAE;AACf,kBAAU,QAAQ;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AACA,QAAI,MAAM,IAAI;AAAA,EAChB,QAAQ;AAAA,EAAC;AACX;AAEA,SAAS,kBAAkB;AACzB,MAAI;AACF,QAAI,SAAS,cAAc,eAAe,gBAAgB,IAAI,EAAG;AACjE,UAAM,SAAS,SAAS,qBAAqB,QAAQ,EAAE,CAAC;AACxD,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,OAAO;AACd,WAAO,QAAQ;AACf,WAAO,MAAM;AACb,YAAQ,YAAY,aAAa,QAAQ,MAAM;AAAA,EACjD,QAAQ;AAAA,EAAC;AACX;AAEO,SAAS,aAAa;AAC3B,QAAM,EAAE,KAAK,IAAI,QAAQ;AACzB,QAAM,EAAE,WAAW,IAAI,cAAc;AACrC,QAAM,EAAE,MAAM,iBAAiB,IAAI,sBAAsB;AACzD,QAAM,eAAe,OAAY,IAAI;AAErC,QAAM,eAAe,kBAAkB,OAAO,CAAC,KAAK;AACpD,QAAM,OAAO,YAAY,OAAO;AAEhC,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AAEX,QAAI;AACF,sBAAgB;AAEhB,UAAI,SAAS,eAAe,cAAc,SAAS,eAAe,eAAe;AAC/E,wBAAgB;AAAA,MAClB,OAAO;AACL,iBAAS,iBAAiB,oBAAoB,eAAe;AAAA,MAC/D;AAEA,YAAM,WAAgC;AAAA,QACpC,IAAI,OAAO,KAAK,MAAM,EAAE;AAAA,MAC1B;AACA,UAAI,KAAK,MAAO,UAAS,QAAQ,KAAK;AACtC,UAAI,KAAK,QAAQ,KAAK,WAAW;AAC/B,iBAAS,OAAO,GAAG,KAAK,QAAQ,EAAE,IAAI,KAAK,aAAa,EAAE,GAAG,KAAK;AAAA,MACpE;AACA,eAAS,aAAa,OAClB,EAAE,SAAS,KAAK,IAChB,EAAE,SAAS,KAAK,WAAW,IAAI,MAAM,cAAc,aAAa,GAAG;AAEvE,YAAM,SAA8B,EAAE,KAAK,WAAW,MAAM,SAAS;AACrE,UAAI,CAAC,MAAM;AACT,eAAO,UAAU;AACjB,eAAO,UAAU;AAAA,MACnB;AAEA,YAAM,MAAM;AACZ,YAAM,mBAAmB,IAAI,MAAM,aAAa,MAAM;AACtD,UAAI,MAAM,YAAY,QAAQ;AAE9B,uBAAiB,KAAK,CAAC,WAAgB;AACrC,qBAAa,UAAU;AAAA,MACzB,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB,QAAQ;AAAA,IAAC;AAET,WAAO,MAAM;AACX,UAAI;AACF,qBAAa,SAAS,QAAQ;AAC9B,qBAAa,UAAU;AACvB,iBAAS,oBAAoB,oBAAoB,eAAe;AAAA,MAClE,QAAQ;AAAA,MAAC;AAAA,IACX;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,cAAc,SAAS,CAAC;AAExC,SAAO;AACT;","names":[]}
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  const myProfileSchema = z.object({
3
3
  name: z.string().min(1, "Nome \xE9 obrigat\xF3rio"),
4
+ last_name: z.string().min(1, "Sobrenome \xE9 obrigat\xF3rio"),
4
5
  gender: z.string().optional()
5
6
  });
6
7
  const changePasswordSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/validators/account.ts"],"sourcesContent":["import { z } from 'zod';\r\n\r\nexport const myProfileSchema = z.object({\r\n name: z.string().min(1, 'Nome é obrigatório'),\r\n gender: z.string().optional(),\r\n});\r\n\r\nexport type MyProfileFormData = z.infer<typeof myProfileSchema>;\r\n\r\nexport const changePasswordSchema = z.object({\r\n currentPassword: z.string().min(1, 'Senha atual é obrigatória'),\r\n newPassword: z\r\n .string()\r\n .min(1, 'Nova senha é obrigatória')\r\n .min(8, 'Nova senha deve ter no mínimo 8 caracteres'),\r\n});\r\n\r\nexport type ChangePasswordFormData = z.infer<typeof changePasswordSchema>;\r\n\r\nexport const changePhoneSchema = z.object({\r\n phone: z\r\n .string()\r\n .min(1, 'Número de telefone é obrigatório')\r\n .regex(/^\\(\\d{2}\\) (\\d \\d{4}|\\d{4})-\\d{4}$/, 'Número de telefone inválido'),\r\n});\r\n\r\nexport type ChangePhoneFormData = z.infer<typeof changePhoneSchema>;\r\n\r\nexport const changeEmailSchema = z.object({\r\n email: z.string().min(1, 'E-mail é obrigatório').email('E-mail inválido'),\r\n});\r\n\r\nexport type ChangeEmailFormData = z.infer<typeof changeEmailSchema>;\r\n\r\nexport const OTP_CODE_LENGTH = 5;\r\nexport const VALID_OTP_CODE = '12345';\r\n"],"mappings":"AAAA,SAAS,SAAS;AAEX,MAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,0BAAoB;AAAA,EAC5C,QAAQ,EAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAIM,MAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,iBAAiB,EAAE,OAAO,EAAE,IAAI,GAAG,iCAA2B;AAAA,EAC9D,aAAa,EACV,OAAO,EACP,IAAI,GAAG,gCAA0B,EACjC,IAAI,GAAG,+CAA4C;AACxD,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,OAAO,EACJ,OAAO,EACP,IAAI,GAAG,2CAAkC,EACzC,MAAM,sCAAsC,mCAA6B;AAC9E,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,4BAAsB,EAAE,MAAM,oBAAiB;AAC1E,CAAC;AAIM,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/validators/account.ts"],"sourcesContent":["import { z } from 'zod';\r\n\r\nexport const myProfileSchema = z.object({\r\n name: z.string().min(1, 'Nome é obrigatório'),\r\n last_name: z.string().min(1, 'Sobrenome é obrigatório'),\r\n gender: z.string().optional(),\r\n});\r\n\r\nexport type MyProfileFormData = z.infer<typeof myProfileSchema>;\r\n\r\nexport const changePasswordSchema = z.object({\r\n currentPassword: z.string().min(1, 'Senha atual é obrigatória'),\r\n newPassword: z\r\n .string()\r\n .min(1, 'Nova senha é obrigatória')\r\n .min(8, 'Nova senha deve ter no mínimo 8 caracteres'),\r\n});\r\n\r\nexport type ChangePasswordFormData = z.infer<typeof changePasswordSchema>;\r\n\r\nexport const changePhoneSchema = z.object({\r\n phone: z\r\n .string()\r\n .min(1, 'Número de telefone é obrigatório')\r\n .regex(/^\\(\\d{2}\\) (\\d \\d{4}|\\d{4})-\\d{4}$/, 'Número de telefone inválido'),\r\n});\r\n\r\nexport type ChangePhoneFormData = z.infer<typeof changePhoneSchema>;\r\n\r\nexport const changeEmailSchema = z.object({\r\n email: z.string().min(1, 'E-mail é obrigatório').email('E-mail inválido'),\r\n});\r\n\r\nexport type ChangeEmailFormData = z.infer<typeof changeEmailSchema>;\r\n\r\nexport const OTP_CODE_LENGTH = 5;\r\nexport const VALID_OTP_CODE = '12345';\r\n"],"mappings":"AAAA,SAAS,SAAS;AAEX,MAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,0BAAoB;AAAA,EAC5C,WAAW,EAAE,OAAO,EAAE,IAAI,GAAG,+BAAyB;AAAA,EACtD,QAAQ,EAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAIM,MAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,iBAAiB,EAAE,OAAO,EAAE,IAAI,GAAG,iCAA2B;AAAA,EAC9D,aAAa,EACV,OAAO,EACP,IAAI,GAAG,gCAA0B,EACjC,IAAI,GAAG,+CAA4C;AACxD,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,OAAO,EACJ,OAAO,EACP,IAAI,GAAG,2CAAkC,EACzC,MAAM,sCAAsC,mCAA6B;AAC9E,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,4BAAsB,EAAE,MAAM,oBAAiB;AAC1E,CAAC;AAIM,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.202",
3
+ "version": "1.1.205",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -50,6 +50,7 @@ export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps)
50
50
  mode: 'onChange',
51
51
  defaultValues: {
52
52
  name: user?.name ?? '',
53
+ last_name: user?.last_name ?? '',
53
54
  gender: GENDER_OPTIONS.find((g) => g.apiValue === user?.gender)?.value ?? '',
54
55
  },
55
56
  });
@@ -107,6 +108,7 @@ export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps)
107
108
  try {
108
109
  await updateAccountUser.mutateAsync({
109
110
  name: data.name,
111
+ last_name: data.last_name,
110
112
  gender: GENDER_OPTIONS.find((g) => g.value === data.gender)?.apiValue,
111
113
  ...(selectedPhoto ? { photo: selectedPhoto } : {}),
112
114
  ...(photoRemoved ? { photo: '' } : {}),
@@ -196,13 +198,22 @@ export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps)
196
198
 
197
199
  <div className="flex flex-col gap-8">
198
200
  <div className="flex flex-col gap-4">
199
- <FormField
200
- label="Nome completo"
201
- placeholder="Digite seu nome"
202
- error={!!errors.name}
203
- errorMessage={errors.name?.message}
204
- {...register('name')}
205
- />
201
+ <div className="flex gap-4">
202
+ <FormField
203
+ label="Nome"
204
+ placeholder="Digite seu nome"
205
+ error={!!errors.name}
206
+ errorMessage={errors.name?.message}
207
+ {...register('name')}
208
+ />
209
+ <FormField
210
+ label="Sobrenome"
211
+ placeholder="Digite seu sobrenome"
212
+ error={!!errors.last_name}
213
+ errorMessage={errors.last_name?.message}
214
+ {...register('last_name')}
215
+ />
216
+ </div>
206
217
  <SelectField
207
218
  label="Gênero"
208
219
  placeholder="Selecione seu gênero"
@@ -11,22 +11,23 @@ const CRISP_WEBSITE_ID = '3339a3ec-b4c6-4aac-8b86-45668fb7655c';
11
11
  const CRISP_SCRIPT_URL = 'https://client.crisp.chat/l.js';
12
12
  const CRISP_LOAD_DELAY = 800;
13
13
 
14
+ function safeCrispPush(args: any[]) {
15
+ try {
16
+ const $crisp = (window as any)?.$crisp;
17
+ if ($crisp) $crisp.push(args);
18
+ } catch {}
19
+ }
20
+
14
21
  export function openCrispHelpdesk() {
15
- if (typeof window !== 'undefined' && (window as any).$crisp) {
16
- (window as any).$crisp.push(['do', 'helpdesk:search']);
17
- }
22
+ safeCrispPush(['do', 'helpdesk:search']);
18
23
  }
19
24
 
20
25
  export function hideCrisp() {
21
- if (typeof window !== 'undefined' && (window as any).$crisp) {
22
- (window as any).$crisp.push(['do', 'chat:hide']);
23
- }
26
+ safeCrispPush(['do', 'chat:hide']);
24
27
  }
25
28
 
26
29
  export function showCrisp() {
27
- if (typeof window !== 'undefined' && (window as any).$crisp) {
28
- (window as any).$crisp.push(['do', 'chat:show']);
29
- }
30
+ safeCrispPush(['do', 'chat:show']);
30
31
  }
31
32
 
32
33
  export function CrispEmbed() {
@@ -42,52 +43,58 @@ export function CrispEmbed() {
42
43
  useEffect(() => {
43
44
  if (!user || scriptLoadedRef.current) return;
44
45
 
45
- const win = window as any;
46
- win.$crisp = [];
47
- win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;
48
- win.$crisp.push(['config', 'container:index', [100]]);
49
-
50
- const timeout = setTimeout(() => {
51
- if (document.querySelector(`script[src="${CRISP_SCRIPT_URL}"]`)) return;
52
- const s = document.createElement('script');
53
- s.src = CRISP_SCRIPT_URL;
54
- s.async = true;
55
- document.head.appendChild(s);
56
- scriptLoadedRef.current = true;
57
- }, CRISP_LOAD_DELAY);
58
-
59
- return () => clearTimeout(timeout);
46
+ try {
47
+ const win = window as any;
48
+ win.$crisp = [];
49
+ win.CRISP_WEBSITE_ID = CRISP_WEBSITE_ID;
50
+ win.$crisp.push(['config', 'container:index', [100]]);
51
+
52
+ const timeout = setTimeout(() => {
53
+ try {
54
+ if (document.querySelector(`script[src="${CRISP_SCRIPT_URL}"]`)) return;
55
+ const s = document.createElement('script');
56
+ s.src = CRISP_SCRIPT_URL;
57
+ s.async = true;
58
+ document.head.appendChild(s);
59
+ scriptLoadedRef.current = true;
60
+ } catch {}
61
+ }, CRISP_LOAD_DELAY);
62
+
63
+ return () => clearTimeout(timeout);
64
+ } catch {}
60
65
  }, [user]);
61
66
 
62
67
  // Identify user
63
68
  useEffect(() => {
64
- const $crisp = (window as any).$crisp;
65
- if (!user || !$crisp) return;
66
-
67
- if (user.email) $crisp.push(['set', 'user:email', user.email]);
68
-
69
- const fullName = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();
70
- if (fullName) $crisp.push(['set', 'user:nickname', fullName]);
71
-
72
- if (account?.name) $crisp.push(['set', 'user:company', account.name]);
73
-
74
- const phone = `${user.ddi ?? ''}${user.phone ?? ''}`.trim();
75
- if (phone) $crisp.push(['set', 'user:phone', phone]);
76
-
77
- if (user.photo && user.photo.startsWith('http')) {
78
- $crisp.push(['set', 'user:avatar', user.photo]);
79
- }
80
-
81
- if (isV4) {
82
- $crisp.push(['set', 'session:segments', [['company_v4']]]);
83
- $crisp.push(['set', 'session:data', [[['Company', 'V4']]]]);
84
- } else {
85
- const planName = subscription?.plan_name ?? '';
86
- if (planName) $crisp.push(['set', 'session:segments', [[`plano_${planName}`]]]);
87
- if (user.profile) $crisp.push(['set', 'session:segments', [[`usuario_${user.profile}`]]]);
88
- if (planName) $crisp.push(['set', 'session:data', [[['Plano', planName]]]]);
89
- if (user.profile) $crisp.push(['set', 'session:data', [[['Usuario', user.profile]]]]);
90
- }
69
+ try {
70
+ const $crisp = (window as any)?.$crisp;
71
+ if (!user || !$crisp) return;
72
+
73
+ if (user.email) $crisp.push(['set', 'user:email', user.email]);
74
+
75
+ const fullName = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();
76
+ if (fullName) $crisp.push(['set', 'user:nickname', fullName]);
77
+
78
+ if (account?.name) $crisp.push(['set', 'user:company', account.name]);
79
+
80
+ const phone = `${user.ddi ?? ''}${user.phone ?? ''}`.trim();
81
+ if (phone) $crisp.push(['set', 'user:phone', phone]);
82
+
83
+ if (user.photo && user.photo.startsWith('http')) {
84
+ $crisp.push(['set', 'user:avatar', user.photo]);
85
+ }
86
+
87
+ if (isV4) {
88
+ $crisp.push(['set', 'session:segments', [['company_v4']]]);
89
+ $crisp.push(['set', 'session:data', [[['Company', 'V4']]]]);
90
+ } else {
91
+ const planName = subscription?.plan_name ?? '';
92
+ if (planName) $crisp.push(['set', 'session:segments', [[`plano_${planName}`]]]);
93
+ if (user.profile) $crisp.push(['set', 'session:segments', [[`usuario_${user.profile}`]]]);
94
+ if (planName) $crisp.push(['set', 'session:data', [[['Plano', planName]]]]);
95
+ if (user.profile) $crisp.push(['set', 'session:data', [[['Usuario', user.profile]]]]);
96
+ }
97
+ } catch {}
91
98
  }, [user, account, isV4, subscription?.plan_name]);
92
99
 
93
100
  return null;
@@ -17,42 +17,46 @@ const WIDGETS = [
17
17
  ];
18
18
 
19
19
  function initFrillLoader() {
20
- const win = window as any;
21
- if (win.Frill) return;
22
-
23
- let counter = 0;
24
- const queue: Record<number, any> = {};
25
-
26
- win.Frill = function (action: string, params: any) {
27
- let instance: any;
28
- const id = counter++;
29
- const promise: any = new Promise((resolve, reject) => {
30
- queue[id] = {
31
- params: [action, params],
32
- resolve: (f: any) => {
33
- instance = f;
34
- resolve(f);
35
- },
36
- reject,
20
+ try {
21
+ const win = window as any;
22
+ if (win.Frill) return;
23
+
24
+ let counter = 0;
25
+ const queue: Record<number, any> = {};
26
+
27
+ win.Frill = function (action: string, params: any) {
28
+ let instance: any;
29
+ const id = counter++;
30
+ const promise: any = new Promise((resolve, reject) => {
31
+ queue[id] = {
32
+ params: [action, params],
33
+ resolve: (f: any) => {
34
+ instance = f;
35
+ resolve(f);
36
+ },
37
+ reject,
38
+ };
39
+ });
40
+ promise.destroy = () => {
41
+ delete queue[id];
42
+ instance?.destroy();
37
43
  };
38
- });
39
- promise.destroy = () => {
40
- delete queue[id];
41
- instance?.destroy();
44
+ return promise;
42
45
  };
43
- return promise;
44
- };
45
- win.Frill.q = queue;
46
+ win.Frill.q = queue;
47
+ } catch {}
46
48
  }
47
49
 
48
50
  function loadFrillScript() {
49
- if (document.querySelector(`script[src="${FRILL_SCRIPT_URL}"]`)) return;
50
- const anchor = document.getElementsByTagName('script')[0];
51
- const script = document.createElement('script');
52
- script.type = 'text/javascript';
53
- script.async = true;
54
- script.src = FRILL_SCRIPT_URL;
55
- anchor?.parentNode?.insertBefore(script, anchor);
51
+ try {
52
+ if (document.querySelector(`script[src="${FRILL_SCRIPT_URL}"]`)) return;
53
+ const anchor = document.getElementsByTagName('script')[0];
54
+ const script = document.createElement('script');
55
+ script.type = 'text/javascript';
56
+ script.async = true;
57
+ script.src = FRILL_SCRIPT_URL;
58
+ anchor?.parentNode?.insertBefore(script, anchor);
59
+ } catch {}
56
60
  }
57
61
 
58
62
  export function FrillEmbed() {
@@ -67,43 +71,47 @@ export function FrillEmbed() {
67
71
  useEffect(() => {
68
72
  if (!user) return;
69
73
 
70
- initFrillLoader();
71
-
72
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
73
- loadFrillScript();
74
- } else {
75
- document.addEventListener('DOMContentLoaded', loadFrillScript);
76
- }
77
-
78
- const userData: Record<string, any> = {
79
- id: String(user.id ?? ''),
80
- };
81
- if (user.email) userData.email = user.email;
82
- if (user.name || user.last_name) {
83
- userData.name = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();
84
- }
85
- userData.attributes = isV4
86
- ? { company: 'V4' }
87
- : { profile: user.profile ?? '', plan: subscription?.plan_name ?? '' };
88
-
89
- const config: Record<string, any> = { key: FRILL_KEY, user: userData };
90
- if (!isV4) {
91
- config.surveys = SURVEYS;
92
- config.widgets = WIDGETS;
93
- }
74
+ try {
75
+ initFrillLoader();
94
76
 
95
- const win = window as any;
96
- const containerPromise = win.Frill('container', config);
97
- win.Frill('identify', userData);
77
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
78
+ loadFrillScript();
79
+ } else {
80
+ document.addEventListener('DOMContentLoaded', loadFrillScript);
81
+ }
98
82
 
99
- containerPromise.then((widget: any) => {
100
- containerRef.current = widget;
101
- }).catch(() => {});
83
+ const userData: Record<string, any> = {
84
+ id: String(user.id ?? ''),
85
+ };
86
+ if (user.email) userData.email = user.email;
87
+ if (user.name || user.last_name) {
88
+ userData.name = `${user.name ?? ''} ${user.last_name ?? ''}`.trim();
89
+ }
90
+ userData.attributes = isV4
91
+ ? { company: 'V4' }
92
+ : { profile: user.profile ?? '', plan: subscription?.plan_name ?? '' };
93
+
94
+ const config: Record<string, any> = { key: FRILL_KEY, user: userData };
95
+ if (!isV4) {
96
+ config.surveys = SURVEYS;
97
+ config.widgets = WIDGETS;
98
+ }
99
+
100
+ const win = window as any;
101
+ const containerPromise = win.Frill('container', config);
102
+ win.Frill('identify', userData);
103
+
104
+ containerPromise.then((widget: any) => {
105
+ containerRef.current = widget;
106
+ }).catch(() => {});
107
+ } catch {}
102
108
 
103
109
  return () => {
104
- containerRef.current?.destroy();
105
- containerRef.current = null;
106
- document.removeEventListener('DOMContentLoaded', loadFrillScript);
110
+ try {
111
+ containerRef.current?.destroy();
112
+ containerRef.current = null;
113
+ document.removeEventListener('DOMContentLoaded', loadFrillScript);
114
+ } catch {}
107
115
  };
108
116
  }, [user, isV4, subscription?.plan_name]);
109
117
 
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
 
3
3
  export const myProfileSchema = z.object({
4
4
  name: z.string().min(1, 'Nome é obrigatório'),
5
+ last_name: z.string().min(1, 'Sobrenome é obrigatório'),
5
6
  gender: z.string().optional(),
6
7
  });
7
8