@greatapps/common 1.1.178 → 1.1.180
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/account/sections/MyProfileSection.mjs +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/layouts/AppMobileNavBar.mjs +6 -20
- package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
- package/dist/components/layouts/NavBar.mjs +7 -27
- package/dist/components/layouts/NavBar.mjs.map +1 -1
- package/dist/components/ui/form/PhoneInput.mjs +1 -1
- package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/account/sections/MyProfileSection.tsx +1 -1
- package/src/components/layouts/AppMobileNavBar.tsx +7 -21
- package/src/components/layouts/NavBar.tsx +7 -23
- package/src/components/ui/form/PhoneInput.tsx +1 -1
|
@@ -223,7 +223,7 @@ function MyProfileSection({ onClose, storageUrl }) {
|
|
|
223
223
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
224
224
|
/* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-600", children: "Dados de acesso" }),
|
|
225
225
|
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
226
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
226
|
+
/* @__PURE__ */ jsx("div", { className: "cursor-not-allowed", children: /* @__PURE__ */ jsx(
|
|
227
227
|
FormField,
|
|
228
228
|
{
|
|
229
229
|
label: "E-mail",
|
|
@@ -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=\"opacity-50\">\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":[]}
|
|
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":"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","names":[]}
|
|
@@ -45,29 +45,15 @@ function AppMobileNavBar({
|
|
|
45
45
|
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: isGpagesActive ? /* @__PURE__ */ jsx(
|
|
46
46
|
"div",
|
|
47
47
|
{
|
|
48
|
-
className: "size-10 rounded-
|
|
49
|
-
style: {
|
|
50
|
-
border: "1.5px solid rgba(153,234,255,0.75)",
|
|
51
|
-
background: "white",
|
|
52
|
-
boxShadow: "0 0 8px rgba(153,234,255,0.5), 0 0 18px rgba(153,234,255,0.2)"
|
|
53
|
-
},
|
|
48
|
+
className: "size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-50 border-2 border-white ring-2 ring-cyan-50",
|
|
54
49
|
onClick: onAppIconClick,
|
|
55
50
|
children: /* @__PURE__ */ jsx(
|
|
56
|
-
|
|
51
|
+
Image,
|
|
57
52
|
{
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
children: /* @__PURE__ */ jsx(
|
|
63
|
-
Image,
|
|
64
|
-
{
|
|
65
|
-
src: "/icons/icon-navbar.svg",
|
|
66
|
-
alt: "GreatPages",
|
|
67
|
-
width: 24,
|
|
68
|
-
height: 24
|
|
69
|
-
}
|
|
70
|
-
)
|
|
53
|
+
src: "/icons/icon-navbar.svg",
|
|
54
|
+
alt: "GreatPages",
|
|
55
|
+
width: 24,
|
|
56
|
+
height: 24
|
|
71
57
|
}
|
|
72
58
|
)
|
|
73
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/layouts/AppMobileNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode } from \"react\";\nimport Image from \"next/image\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { useAccountModals } from \"../../store/useAccountModals\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\n\nexport interface AppMobileNavBarProps {\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n /** Called when the GreatApps logo is clicked */\n onLogoClick?: () => void;\n /** Called when the app icon (e.g. GreatPages) is clicked */\n onAppIconClick?: () => void;\n /** Extra slot rendered after the app icon (e.g. project selector) */\n extraLeftSlot?: ReactNode;\n /** Required: the right-side action element (toggle button, sheet button, etc.) */\n rightActionSlot: ReactNode;\n menuItems?: ProfileMenuItem[];\n onCreditsClick?: () => void;\n}\n\nexport function AppMobileNavBar({\n activeApp,\n onLogoClick,\n onAppIconClick,\n extraLeftSlot,\n rightActionSlot,\n menuItems = [],\n onCreditsClick,\n}: AppMobileNavBarProps) {\n const { openConfigurations } = useAccountModals();\n\n const isGpagesActive = activeApp === \"gpages\";\n const isGappsActive = activeApp === \"gapps\";\n\n return (\n <div className=\"fixed top-0 left-0 right-0 flex md:hidden items-center justify-between p-4 bg-white z-50 border-b border-gray-200\">\n <div className=\"flex items-center gap-1.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <div\n className={`relative size-10 flex items-center justify-center rounded-lg transition-colors ${onLogoClick ? \"cursor-pointer hover:bg-gray-100\" : \"\"}`}\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"GreatApps\"\n width={28}\n height={28}\n />\n {isGappsActive && (\n <div className=\"absolute bottom-[-17px] left-1/2 -translate-x-1/2 w-5 h-[3px] bg-gray-950 rounded-t-xl\" />\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">GreatApps</TooltipContent>\n </Tooltip>\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild>\n {isGpagesActive ? (\n <div\n className=\"size-10 rounded-
|
|
1
|
+
{"version":3,"sources":["../../../src/components/layouts/AppMobileNavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode } from \"react\";\nimport Image from \"next/image\";\nimport { ProfilePopover } from \"./ProfilePopover\";\nimport { useAccountModals } from \"../../store/useAccountModals\";\nimport type { ProfileMenuItem } from \"./ProfilePopover\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\n\nexport interface AppMobileNavBarProps {\n /** Which app is currently active — controls which icon gets the indicator */\n activeApp?: \"gapps\" | \"gpages\";\n /** Called when the GreatApps logo is clicked */\n onLogoClick?: () => void;\n /** Called when the app icon (e.g. GreatPages) is clicked */\n onAppIconClick?: () => void;\n /** Extra slot rendered after the app icon (e.g. project selector) */\n extraLeftSlot?: ReactNode;\n /** Required: the right-side action element (toggle button, sheet button, etc.) */\n rightActionSlot: ReactNode;\n menuItems?: ProfileMenuItem[];\n onCreditsClick?: () => void;\n}\n\nexport function AppMobileNavBar({\n activeApp,\n onLogoClick,\n onAppIconClick,\n extraLeftSlot,\n rightActionSlot,\n menuItems = [],\n onCreditsClick,\n}: AppMobileNavBarProps) {\n const { openConfigurations } = useAccountModals();\n\n const isGpagesActive = activeApp === \"gpages\";\n const isGappsActive = activeApp === \"gapps\";\n\n return (\n <div className=\"fixed top-0 left-0 right-0 flex md:hidden items-center justify-between p-4 bg-white z-50 border-b border-gray-200\">\n <div className=\"flex items-center gap-1.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <div\n className={`relative size-10 flex items-center justify-center rounded-lg transition-colors ${onLogoClick ? \"cursor-pointer hover:bg-gray-100\" : \"\"}`}\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"GreatApps\"\n width={28}\n height={28}\n />\n {isGappsActive && (\n <div className=\"absolute bottom-[-17px] left-1/2 -translate-x-1/2 w-5 h-[3px] bg-gray-950 rounded-t-xl\" />\n )}\n </div>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">GreatApps</TooltipContent>\n </Tooltip>\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild>\n {isGpagesActive ? (\n <div\n className=\"size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-50 border-2 border-white ring-2 ring-cyan-50\"\n onClick={onAppIconClick}\n >\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n ) : (\n <div\n className={`size-10 flex items-center justify-center rounded-lg transition-colors duration-300 bg-gray-100 ${onAppIconClick ? \"cursor-pointer hover:opacity-80\" : \"\"}`}\n onClick={onAppIconClick}\n >\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">GreatPages</TooltipContent>\n </Tooltip>\n {isGpagesActive && (\n <div className=\"absolute -bottom-[17px] left-1/2 -translate-x-1/2 w-5 h-[3px] rounded-t-xl\" style={{ backgroundColor: \"#6ADCFF\" }} />\n )}\n </div>\n {extraLeftSlot}\n </div>\n <div className=\"flex items-center gap-1.5\">\n <ProfilePopover\n side=\"bottom\"\n align=\"end\"\n contentClassName=\"\"\n onEditProfile={() => openConfigurations()}\n onCreditsClick={onCreditsClick}\n menuItems={menuItems}\n />\n {rightActionSlot}\n </div>\n </div>\n );\n}\n"],"mappings":";AA2CY,SAIE,KAJF;AAxCZ,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AAEjC,SAAS,SAAS,gBAAgB,sBAAsB;AAiBjD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,CAAC;AAAA,EACb;AACF,GAAyB;AACvB,QAAM,EAAE,mBAAmB,IAAI,iBAAiB;AAEhD,QAAM,iBAAiB,cAAc;AACrC,QAAM,gBAAgB,cAAc;AAEpC,SACE,qBAAC,SAAI,WAAU,qHACb;AAAA,yBAAC,SAAI,WAAU,6BACb;AAAA,2BAAC,WACC;AAAA,4BAAC,kBAAe,SAAO,MACrB;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,kFAAkF,cAAc,qCAAqC,EAAE;AAAA,YAClJ,SAAS;AAAA,YAET;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA,cACC,iBACC,oBAAC,SAAI,WAAU,0FAAyF;AAAA;AAAA;AAAA,QAE5G,GACF;AAAA,QACA,oBAAC,kBAAe,MAAK,UAAS,uBAAS;AAAA,SACzC;AAAA,MACA,qBAAC,SAAI,WAAU,YACb;AAAA,6BAAC,WACC;AAAA,8BAAC,kBAAe,SAAO,MACpB,2BACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS;AAAA,cAET;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA;AAAA,UACF,IAEA;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,kGAAkG,iBAAiB,oCAAoC,EAAE;AAAA,cACpK,SAAS;AAAA,cAET;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV;AAAA;AAAA,UACF,GAEJ;AAAA,UACA,oBAAC,kBAAe,MAAK,UAAS,wBAAU;AAAA,WAC1C;AAAA,QACC,kBACC,oBAAC,SAAI,WAAU,8EAA6E,OAAO,EAAE,iBAAiB,UAAU,GAAG;AAAA,SAEvI;AAAA,MACC;AAAA,OACH;AAAA,IACA,qBAAC,SAAI,WAAU,6BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAM;AAAA,UACN,kBAAiB;AAAA,UACjB,eAAe,MAAM,mBAAmB;AAAA,UACxC;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MACC;AAAA,OACH;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -70,35 +70,15 @@ function NavBar({
|
|
|
70
70
|
] }),
|
|
71
71
|
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
72
72
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
73
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, onClick: onAppIconClick, children: activeApp === "gpages" ? /* @__PURE__ */ jsx(
|
|
74
|
-
|
|
73
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, onClick: onAppIconClick, children: activeApp === "gpages" ? /* @__PURE__ */ jsx("div", { className: "size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-50 border-2 border-white ring-2 ring-cyan-50", children: /* @__PURE__ */ jsx(
|
|
74
|
+
Image,
|
|
75
75
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
boxShadow: "0 0 8px rgba(153,234,255,0.5), 0 0 18px rgba(153,234,255,0.2)"
|
|
81
|
-
},
|
|
82
|
-
children: /* @__PURE__ */ jsx(
|
|
83
|
-
"div",
|
|
84
|
-
{
|
|
85
|
-
className: "w-full h-full rounded-lg flex items-center justify-center",
|
|
86
|
-
style: {
|
|
87
|
-
background: "radial-gradient(circle at center, rgba(255,255,255,0.95) 0%, rgba(153,234,255,0.45) 100%)"
|
|
88
|
-
},
|
|
89
|
-
children: /* @__PURE__ */ jsx(
|
|
90
|
-
Image,
|
|
91
|
-
{
|
|
92
|
-
src: "/icons/icon-navbar.svg",
|
|
93
|
-
alt: "GreatPages",
|
|
94
|
-
width: 24,
|
|
95
|
-
height: 24
|
|
96
|
-
}
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
)
|
|
76
|
+
src: "/icons/icon-navbar.svg",
|
|
77
|
+
alt: "GreatPages",
|
|
78
|
+
width: 24,
|
|
79
|
+
height: 24
|
|
100
80
|
}
|
|
101
|
-
) : /* @__PURE__ */ jsx("div", { className: "size-10 flex items-center justify-center rounded-lg cursor-pointer hover:bg-gray-100 transition-colors duration-300", children: /* @__PURE__ */ jsx(
|
|
81
|
+
) }) : /* @__PURE__ */ jsx("div", { className: "size-10 flex items-center justify-center rounded-lg cursor-pointer hover:bg-gray-100 transition-colors duration-300", children: /* @__PURE__ */ jsx(
|
|
102
82
|
Image,
|
|
103
83
|
{
|
|
104
84
|
src: "/icons/icon-navbar.svg",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/layouts/NavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport Image from \"next/image\";\nimport { ChevronRight } from \"lucide-react\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\nimport { cn } from \"../../infra/utils/clsx\";\n\ntype NavBarProps = {\n onLogoClick: () => void;\n onAppIconClick?: () => void;\n activeApp?: \"gapps\" | \"gpages\";\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n children?: React.ReactNode;\n className?: string;\n};\n\nfunction NavBar({\n onLogoClick,\n onAppIconClick,\n activeApp,\n showExpandButton = false,\n onExpandClick,\n children,\n className,\n}: NavBarProps) {\n return (\n <div\n className={cn(\n \"hidden md:flex flex-col justify-between h-screen p-4 border-r border-gray-200 overflow-visible z-40 bg-white\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-4 items-center mt-[6.5px]\">\n {/* GreatApps logo */}\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger\n className=\"cursor-pointer\"\n asChild\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great Icon\"\n width={28}\n height={28}\n />\n </TooltipTrigger>\n <TooltipContent side=\"right\">GreatApps</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-[22px] top-1/2 -translate-y-1/2 w-[3px] h-5 bg-gray-950 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gapps\" ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n </div>\n\n <div className=\"relative w-full mt-[7.5px]\">\n <Separator />\n {showExpandButton && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={onExpandClick}\n className=\"lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10\"\n >\n <ChevronRight size={16} className=\"text-gray-500\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Expandir menu</TooltipContent>\n </Tooltip>\n )}\n </div>\n\n {/* GreatPages icon */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild onClick={onAppIconClick}>\n {activeApp === \"gpages\" ? (\n <div
|
|
1
|
+
{"version":3,"sources":["../../../src/components/layouts/NavBar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport Image from \"next/image\";\nimport { ChevronRight } from \"lucide-react\";\nimport { Separator } from \"../ui/data-display/Separator\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"../ui/overlay/Tooltip\";\nimport { cn } from \"../../infra/utils/clsx\";\n\ntype NavBarProps = {\n onLogoClick: () => void;\n onAppIconClick?: () => void;\n activeApp?: \"gapps\" | \"gpages\";\n showExpandButton?: boolean;\n onExpandClick?: () => void;\n children?: React.ReactNode;\n className?: string;\n};\n\nfunction NavBar({\n onLogoClick,\n onAppIconClick,\n activeApp,\n showExpandButton = false,\n onExpandClick,\n children,\n className,\n}: NavBarProps) {\n return (\n <div\n className={cn(\n \"hidden md:flex flex-col justify-between h-screen p-4 border-r border-gray-200 overflow-visible z-40 bg-white\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-4 items-center mt-[6.5px]\">\n {/* GreatApps logo */}\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger\n className=\"cursor-pointer\"\n asChild\n onClick={onLogoClick}\n >\n <Image\n src=\"/icons/great-icon.svg\"\n alt=\"Great Icon\"\n width={28}\n height={28}\n />\n </TooltipTrigger>\n <TooltipContent side=\"right\">GreatApps</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-[22px] top-1/2 -translate-y-1/2 w-[3px] h-5 bg-gray-950 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gapps\" ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n </div>\n\n <div className=\"relative w-full mt-[7.5px]\">\n <Separator />\n {showExpandButton && (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n onClick={onExpandClick}\n className=\"lg:hidden absolute top-1/2 -translate-y-1/2 right-0 translate-x-[calc(50%+1rem)] size-8 flex items-center justify-center rounded-full border border-gray-200 bg-white hover:bg-gray-100 cursor-pointer transition-colors z-10\"\n >\n <ChevronRight size={16} className=\"text-gray-500\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"right\">Expandir menu</TooltipContent>\n </Tooltip>\n )}\n </div>\n\n {/* GreatPages icon */}\n <div className=\"flex flex-col gap-2\">\n <div className=\"relative\">\n <Tooltip>\n <TooltipTrigger asChild onClick={onAppIconClick}>\n {activeApp === \"gpages\" ? (\n <div className=\"size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-50 border-2 border-white ring-2 ring-cyan-50\">\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={24}\n height={24}\n />\n </div>\n ) : (\n <div className=\"size-10 flex items-center justify-center rounded-lg cursor-pointer hover:bg-gray-100 transition-colors duration-300\">\n <Image\n src=\"/icons/icon-navbar.svg\"\n alt=\"GreatPages\"\n width={28}\n height={28}\n />\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent side=\"right\">GreatPages</TooltipContent>\n </Tooltip>\n <div\n className={cn(\n \"absolute -left-[22px] top-1/2 -translate-y-1/2 w-[3px] h-5 rounded-r-xl transition-opacity duration-300\",\n activeApp === \"gpages\" ? \"opacity-100\" : \"opacity-0\",\n )}\n style={{ backgroundColor: \"#6ADCFF\" }}\n />\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-col items-center gap-2\">{children}</div>\n </div>\n );\n}\n\nexport { NavBar };\nexport type { NavBarProps };\n"],"mappings":";AAsCU,SAMI,KANJ;AAnCV,OAAO,WAAW;AAClB,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,UAAU;AAYnB,SAAS,OAAO;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAAgB;AACd,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEA;AAAA,6BAAC,SAAI,WAAU,+CAEb;AAAA,+BAAC,SAAI,WAAU,YACb;AAAA,iCAAC,WACC;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,SAAO;AAAA,kBACP,SAAS;AAAA,kBAET;AAAA,oBAAC;AAAA;AAAA,sBACC,KAAI;AAAA,sBACJ,KAAI;AAAA,sBACJ,OAAO;AAAA,sBACP,QAAQ;AAAA;AAAA,kBACV;AAAA;AAAA,cACF;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,uBAAS;AAAA,eACxC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,cAAc,UAAU,gBAAgB;AAAA,gBAC1C;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,8BACb;AAAA,gCAAC,aAAU;AAAA,YACV,oBACC,qBAAC,WACC;AAAA,kCAAC,kBAAe,SAAO,MACrB;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS;AAAA,kBACT,WAAU;AAAA,kBAEV,8BAAC,gBAAa,MAAM,IAAI,WAAU,iBAAgB;AAAA;AAAA,cACpD,GACF;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,2BAAa;AAAA,eAC5C;AAAA,aAEJ;AAAA,UAGA,oBAAC,SAAI,WAAU,uBACb,+BAAC,SAAI,WAAU,YACb;AAAA,iCAAC,WACC;AAAA,kCAAC,kBAAe,SAAO,MAAC,SAAS,gBAC9B,wBAAc,WACb,oBAAC,SAAI,WAAU,2HACb;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV,GACF,IAEA,oBAAC,SAAI,WAAU,uHACb;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAI;AAAA,kBACJ,KAAI;AAAA,kBACJ,OAAO;AAAA,kBACP,QAAQ;AAAA;AAAA,cACV,GACF,GAEJ;AAAA,cACA,oBAAC,kBAAe,MAAK,SAAQ,wBAAU;AAAA,eACzC;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,cAAc,WAAW,gBAAgB;AAAA,gBAC3C;AAAA,gBACA,OAAO,EAAE,iBAAiB,UAAU;AAAA;AAAA,YACtC;AAAA,aACF,GACF;AAAA,WACF;AAAA,QAEA,oBAAC,SAAI,WAAU,oCAAoC,UAAS;AAAA;AAAA;AAAA,EAC9D;AAEJ;","names":[]}
|
|
@@ -90,7 +90,7 @@ function PhoneInput({
|
|
|
90
90
|
className: cn(
|
|
91
91
|
"flex gap-2 items-center border rounded-lg h-10 transition-colors",
|
|
92
92
|
error ? "border-red-600 hover:border-red-700" : "border-zinc-200 hover:border-zinc-400 focus-within:border-zinc-950",
|
|
93
|
-
disabled && "
|
|
93
|
+
disabled && "cursor-not-allowed",
|
|
94
94
|
classnameContainer
|
|
95
95
|
),
|
|
96
96
|
children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ui/form/PhoneInput.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useRef } from 'react';\nimport { AsYouType, CountryCode } from 'libphonenumber-js';\nimport { Input, Separator, Popover, PopoverTrigger, PopoverContent, cn } from '@greatapps/common';\nimport { IconChevronDown, IconSearch } from '@tabler/icons-react';\nimport { COUNTRIES, Country, flagUrl, parsePhoneValue } from '../../../utils/countries';\n\nfunction formatNational(digits: string, iso: string): string {\n const raw = digits.replace(/\\D/g, '');\n if (!raw) return '';\n return new AsYouType(iso as CountryCode).input(raw);\n}\n\ninterface PhoneInputProps {\n value?: string;\n onChange?: (value: string) => void;\n label?: string;\n optional?: boolean;\n required?: boolean;\n hintMessage?: string;\n error?: boolean;\n errorMessage?: string;\n placeholder?: string;\n disabled?: boolean;\n classnameContainer?: string;\n className?: string;\n}\n\nexport default function PhoneInput({\n value,\n onChange,\n label,\n optional = false,\n required = false,\n hintMessage,\n error = false,\n errorMessage,\n placeholder,\n disabled = false,\n classnameContainer,\n className,\n}: PhoneInputProps) {\n const parsed = parsePhoneValue(value ?? '');\n const [selectedCountry, setSelectedCountry] = useState<Country>(parsed.country);\n const [phoneNumber, setPhoneNumber] = useState(parsed.number);\n const [search, setSearch] = useState('');\n const [open, setOpen] = useState(false);\n const prevValueRef = useRef(value);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (value !== prevValueRef.current) {\n prevValueRef.current = value;\n const p = parsePhoneValue(value ?? '');\n setSelectedCountry(p.country);\n setPhoneNumber(formatNational(p.number, p.country.iso));\n }\n }, [value]);\n\n const emit = (country: Country, number: string) => {\n onChange?.(`${country.dial} ${number}`);\n };\n\n const handleCountrySelect = (country: Country) => {\n const reformatted = formatNational(phoneNumber, country.iso);\n setSelectedCountry(country);\n setPhoneNumber(reformatted);\n setOpen(false);\n setSearch('');\n emit(country, reformatted);\n };\n\n const handleNumberChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const rawInput = e.target.value;\n const cursorPos = e.target.selectionStart ?? rawInput.length;\n const digitsBeforeCursor = rawInput.slice(0, cursorPos).replace(/\\D/g, '').length;\n\n const formatted = formatNational(rawInput, selectedCountry.iso);\n setPhoneNumber(formatted);\n emit(selectedCountry, formatted);\n\n requestAnimationFrame(() => {\n if (!inputRef.current) return;\n let digitCount = 0;\n let newPos = formatted.length;\n for (let i = 0; i < formatted.length; i++) {\n if (/\\d/.test(formatted[i])) {\n digitCount++;\n if (digitCount === digitsBeforeCursor) {\n newPos = i + 1;\n break;\n }\n }\n }\n inputRef.current.setSelectionRange(newPos, newPos);\n });\n };\n\n const filtered = COUNTRIES.filter(\n (c) =>\n c.name.toLowerCase().includes(search.toLowerCase()) ||\n c.dial.includes(search) ||\n c.iso.toLowerCase().includes(search.toLowerCase())\n );\n\n const finalMessage = error && errorMessage ? errorMessage : hintMessage;\n const showMessage = finalMessage && finalMessage.trim() !== '';\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n {label && (\n <div className=\"flex items-center gap-1 paragraph-xsmall-semibold\">\n <span className=\"text-zinc-600\">{label}</span>\n {optional && <span className=\"text-zinc-500\">(Opcional)</span>}\n {required && <span className=\"text-red-600\">*</span>}\n </div>\n )}\n\n <div\n className={cn(\n 'flex gap-2 items-center border rounded-lg h-10 transition-colors',\n error\n ? 'border-red-600 hover:border-red-700'\n : 'border-zinc-200 hover:border-zinc-400 focus-within:border-zinc-950',\n disabled && 'opacity-50 cursor-not-allowed',\n classnameContainer\n )}\n >\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"flex items-center gap-1.5 px-3 h-full shrink-0 focus:outline-none\"\n disabled={disabled}\n >\n <img src={flagUrl(selectedCountry.iso)} alt={selectedCountry.iso} className=\"w-5 h-5 rounded-full\" />\n <span className=\"paragraph-small-regular text-zinc-950\">{selectedCountry.dial}</span>\n <IconChevronDown size={14} className={cn(\"text-zinc-500 transition-transform duration-200\", open && \"rotate-180\")} />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-72 p-0 z-[1010]\" align=\"start\" side=\"top\">\n <div className=\"flex items-center gap-2 p-2 border-b border-zinc-100\">\n <IconSearch size={14} className=\"text-zinc-400 shrink-0\" />\n <input\n type=\"text\"\n className=\"flex-1 text-sm outline-none placeholder:text-zinc-400\"\n placeholder=\"Buscar país...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n autoFocus\n />\n </div>\n <div className=\"max-h-60 overflow-y-auto overscroll-contain\" onTouchMove={(e) => e.stopPropagation()} onWheel={(e) => e.stopPropagation()}>\n {filtered.map((country) => (\n <button\n key={country.iso}\n type=\"button\"\n className={cn(\n 'flex items-center gap-2.5 w-full px-3 py-2 text-left hover:bg-zinc-50 transition-colors',\n selectedCountry.iso === country.iso && 'bg-zinc-100'\n )}\n onClick={() => handleCountrySelect(country)}\n >\n <img src={flagUrl(country.iso)} alt={country.iso} className=\"w-5 h-5 rounded-full shrink-0\" />\n <span className=\"paragraph-small-regular text-zinc-950 flex-1 truncate\">\n {country.name}\n </span>\n <span className=\"paragraph-small-regular text-zinc-500 shrink-0\">\n {country.dial}\n </span>\n </button>\n ))}\n {filtered.length === 0 && (\n <p className=\"text-sm text-zinc-500 p-3 text-center\">Nenhum país encontrado</p>\n )}\n </div>\n </PopoverContent>\n </Popover>\n\n <Separator orientation=\"vertical\" />\n\n <Input\n ref={inputRef}\n type=\"tel\"\n value={phoneNumber}\n onChange={handleNumberChange}\n placeholder={placeholder}\n disabled={disabled}\n className={cn(\n 'paragraph-small-medium w-full h-full text-zinc-950 border-0 focus-visible:ring-0 focus-visible:ring-offset-0',\n disabled && 'cursor-not-allowed',\n className\n )}\n />\n </div>\n\n {showMessage && (\n <span className={cn('paragraph-xsmall-medium', error ? 'text-red-600' : 'text-zinc-600')}>\n {finalMessage}\n </span>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ui/form/PhoneInput.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useRef } from 'react';\nimport { AsYouType, CountryCode } from 'libphonenumber-js';\nimport { Input, Separator, Popover, PopoverTrigger, PopoverContent, cn } from '@greatapps/common';\nimport { IconChevronDown, IconSearch } from '@tabler/icons-react';\nimport { COUNTRIES, Country, flagUrl, parsePhoneValue } from '../../../utils/countries';\n\nfunction formatNational(digits: string, iso: string): string {\n const raw = digits.replace(/\\D/g, '');\n if (!raw) return '';\n return new AsYouType(iso as CountryCode).input(raw);\n}\n\ninterface PhoneInputProps {\n value?: string;\n onChange?: (value: string) => void;\n label?: string;\n optional?: boolean;\n required?: boolean;\n hintMessage?: string;\n error?: boolean;\n errorMessage?: string;\n placeholder?: string;\n disabled?: boolean;\n classnameContainer?: string;\n className?: string;\n}\n\nexport default function PhoneInput({\n value,\n onChange,\n label,\n optional = false,\n required = false,\n hintMessage,\n error = false,\n errorMessage,\n placeholder,\n disabled = false,\n classnameContainer,\n className,\n}: PhoneInputProps) {\n const parsed = parsePhoneValue(value ?? '');\n const [selectedCountry, setSelectedCountry] = useState<Country>(parsed.country);\n const [phoneNumber, setPhoneNumber] = useState(parsed.number);\n const [search, setSearch] = useState('');\n const [open, setOpen] = useState(false);\n const prevValueRef = useRef(value);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (value !== prevValueRef.current) {\n prevValueRef.current = value;\n const p = parsePhoneValue(value ?? '');\n setSelectedCountry(p.country);\n setPhoneNumber(formatNational(p.number, p.country.iso));\n }\n }, [value]);\n\n const emit = (country: Country, number: string) => {\n onChange?.(`${country.dial} ${number}`);\n };\n\n const handleCountrySelect = (country: Country) => {\n const reformatted = formatNational(phoneNumber, country.iso);\n setSelectedCountry(country);\n setPhoneNumber(reformatted);\n setOpen(false);\n setSearch('');\n emit(country, reformatted);\n };\n\n const handleNumberChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const rawInput = e.target.value;\n const cursorPos = e.target.selectionStart ?? rawInput.length;\n const digitsBeforeCursor = rawInput.slice(0, cursorPos).replace(/\\D/g, '').length;\n\n const formatted = formatNational(rawInput, selectedCountry.iso);\n setPhoneNumber(formatted);\n emit(selectedCountry, formatted);\n\n requestAnimationFrame(() => {\n if (!inputRef.current) return;\n let digitCount = 0;\n let newPos = formatted.length;\n for (let i = 0; i < formatted.length; i++) {\n if (/\\d/.test(formatted[i])) {\n digitCount++;\n if (digitCount === digitsBeforeCursor) {\n newPos = i + 1;\n break;\n }\n }\n }\n inputRef.current.setSelectionRange(newPos, newPos);\n });\n };\n\n const filtered = COUNTRIES.filter(\n (c) =>\n c.name.toLowerCase().includes(search.toLowerCase()) ||\n c.dial.includes(search) ||\n c.iso.toLowerCase().includes(search.toLowerCase())\n );\n\n const finalMessage = error && errorMessage ? errorMessage : hintMessage;\n const showMessage = finalMessage && finalMessage.trim() !== '';\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n {label && (\n <div className=\"flex items-center gap-1 paragraph-xsmall-semibold\">\n <span className=\"text-zinc-600\">{label}</span>\n {optional && <span className=\"text-zinc-500\">(Opcional)</span>}\n {required && <span className=\"text-red-600\">*</span>}\n </div>\n )}\n\n <div\n className={cn(\n 'flex gap-2 items-center border rounded-lg h-10 transition-colors',\n error\n ? 'border-red-600 hover:border-red-700'\n : 'border-zinc-200 hover:border-zinc-400 focus-within:border-zinc-950',\n disabled && 'cursor-not-allowed',\n classnameContainer\n )}\n >\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"flex items-center gap-1.5 px-3 h-full shrink-0 focus:outline-none\"\n disabled={disabled}\n >\n <img src={flagUrl(selectedCountry.iso)} alt={selectedCountry.iso} className=\"w-5 h-5 rounded-full\" />\n <span className=\"paragraph-small-regular text-zinc-950\">{selectedCountry.dial}</span>\n <IconChevronDown size={14} className={cn(\"text-zinc-500 transition-transform duration-200\", open && \"rotate-180\")} />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-72 p-0 z-[1010]\" align=\"start\" side=\"top\">\n <div className=\"flex items-center gap-2 p-2 border-b border-zinc-100\">\n <IconSearch size={14} className=\"text-zinc-400 shrink-0\" />\n <input\n type=\"text\"\n className=\"flex-1 text-sm outline-none placeholder:text-zinc-400\"\n placeholder=\"Buscar país...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n autoFocus\n />\n </div>\n <div className=\"max-h-60 overflow-y-auto overscroll-contain\" onTouchMove={(e) => e.stopPropagation()} onWheel={(e) => e.stopPropagation()}>\n {filtered.map((country) => (\n <button\n key={country.iso}\n type=\"button\"\n className={cn(\n 'flex items-center gap-2.5 w-full px-3 py-2 text-left hover:bg-zinc-50 transition-colors',\n selectedCountry.iso === country.iso && 'bg-zinc-100'\n )}\n onClick={() => handleCountrySelect(country)}\n >\n <img src={flagUrl(country.iso)} alt={country.iso} className=\"w-5 h-5 rounded-full shrink-0\" />\n <span className=\"paragraph-small-regular text-zinc-950 flex-1 truncate\">\n {country.name}\n </span>\n <span className=\"paragraph-small-regular text-zinc-500 shrink-0\">\n {country.dial}\n </span>\n </button>\n ))}\n {filtered.length === 0 && (\n <p className=\"text-sm text-zinc-500 p-3 text-center\">Nenhum país encontrado</p>\n )}\n </div>\n </PopoverContent>\n </Popover>\n\n <Separator orientation=\"vertical\" />\n\n <Input\n ref={inputRef}\n type=\"tel\"\n value={phoneNumber}\n onChange={handleNumberChange}\n placeholder={placeholder}\n disabled={disabled}\n className={cn(\n 'paragraph-small-medium w-full h-full text-zinc-950 border-0 focus-visible:ring-0 focus-visible:ring-offset-0',\n disabled && 'cursor-not-allowed',\n className\n )}\n />\n </div>\n\n {showMessage && (\n <span className={cn('paragraph-xsmall-medium', error ? 'text-red-600' : 'text-zinc-600')}>\n {finalMessage}\n </span>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -233,7 +233,7 @@ export function MyProfileSection({ onClose, storageUrl }: MyProfileSectionProps)
|
|
|
233
233
|
<div className="flex flex-col gap-4">
|
|
234
234
|
<span className="paragraph-medium-semibold text-gray-600">Dados de acesso</span>
|
|
235
235
|
<div className="relative">
|
|
236
|
-
<div className=
|
|
236
|
+
<div className='cursor-not-allowed'>
|
|
237
237
|
<FormField
|
|
238
238
|
label="E-mail"
|
|
239
239
|
value={user?.email ?? ''}
|
|
@@ -63,29 +63,15 @@ export function AppMobileNavBar({
|
|
|
63
63
|
<TooltipTrigger asChild>
|
|
64
64
|
{isGpagesActive ? (
|
|
65
65
|
<div
|
|
66
|
-
className="size-10 rounded-
|
|
67
|
-
style={{
|
|
68
|
-
border: "1.5px solid rgba(153,234,255,0.75)",
|
|
69
|
-
background: "white",
|
|
70
|
-
boxShadow:
|
|
71
|
-
"0 0 8px rgba(153,234,255,0.5), 0 0 18px rgba(153,234,255,0.2)",
|
|
72
|
-
}}
|
|
66
|
+
className="size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-50 border-2 border-white ring-2 ring-cyan-50"
|
|
73
67
|
onClick={onAppIconClick}
|
|
74
68
|
>
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
>
|
|
82
|
-
<Image
|
|
83
|
-
src="/icons/icon-navbar.svg"
|
|
84
|
-
alt="GreatPages"
|
|
85
|
-
width={24}
|
|
86
|
-
height={24}
|
|
87
|
-
/>
|
|
88
|
-
</div>
|
|
69
|
+
<Image
|
|
70
|
+
src="/icons/icon-navbar.svg"
|
|
71
|
+
alt="GreatPages"
|
|
72
|
+
width={24}
|
|
73
|
+
height={24}
|
|
74
|
+
/>
|
|
89
75
|
</div>
|
|
90
76
|
) : (
|
|
91
77
|
<div
|
|
@@ -82,29 +82,13 @@ function NavBar({
|
|
|
82
82
|
<Tooltip>
|
|
83
83
|
<TooltipTrigger asChild onClick={onAppIconClick}>
|
|
84
84
|
{activeApp === "gpages" ? (
|
|
85
|
-
<div
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
<div
|
|
95
|
-
className="w-full h-full rounded-lg flex items-center justify-center"
|
|
96
|
-
style={{
|
|
97
|
-
background:
|
|
98
|
-
"radial-gradient(circle at center, rgba(255,255,255,0.95) 0%, rgba(153,234,255,0.45) 100%)",
|
|
99
|
-
}}
|
|
100
|
-
>
|
|
101
|
-
<Image
|
|
102
|
-
src="/icons/icon-navbar.svg"
|
|
103
|
-
alt="GreatPages"
|
|
104
|
-
width={24}
|
|
105
|
-
height={24}
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
85
|
+
<div className="size-10 rounded-lg cursor-pointer flex items-center justify-center bg-cyan-50 border-2 border-white ring-2 ring-cyan-50">
|
|
86
|
+
<Image
|
|
87
|
+
src="/icons/icon-navbar.svg"
|
|
88
|
+
alt="GreatPages"
|
|
89
|
+
width={24}
|
|
90
|
+
height={24}
|
|
91
|
+
/>
|
|
108
92
|
</div>
|
|
109
93
|
) : (
|
|
110
94
|
<div className="size-10 flex items-center justify-center rounded-lg cursor-pointer hover:bg-gray-100 transition-colors duration-300">
|
|
@@ -123,7 +123,7 @@ export default function PhoneInput({
|
|
|
123
123
|
error
|
|
124
124
|
? 'border-red-600 hover:border-red-700'
|
|
125
125
|
: 'border-zinc-200 hover:border-zinc-400 focus-within:border-zinc-950',
|
|
126
|
-
disabled && '
|
|
126
|
+
disabled && 'cursor-not-allowed',
|
|
127
127
|
classnameContainer
|
|
128
128
|
)}
|
|
129
129
|
>
|