@greatapps/common 1.1.201 → 1.1.204

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":"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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 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":[]}
@@ -33,20 +33,22 @@ function ProjectSelectorPopover({
33
33
  selectedProject,
34
34
  onSelectProject,
35
35
  onAddProject,
36
- onManageProjects
36
+ onManageProjects,
37
+ children
37
38
  }) {
38
39
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
39
- /* @__PURE__ */ jsx(PopoverTrigger, { className: "cursor-pointer", children: /* @__PURE__ */ jsx(
40
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: children ?? /* @__PURE__ */ jsx("button", { className: "cursor-pointer", children: /* @__PURE__ */ jsx(
40
41
  ChevronDown,
41
42
  {
42
43
  size: 20,
43
44
  className: `transition-transform duration-200 ${open ? "rotate-180 text-gray-950" : "text-gray-400"}`
44
45
  }
45
- ) }),
46
+ ) }) }),
46
47
  /* @__PURE__ */ jsx(
47
48
  PopoverContent,
48
49
  {
49
- className: "absolute right-[-158px] top-2.5 w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200",
50
+ className: "w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200",
51
+ align: "start",
50
52
  sideOffset: 8,
51
53
  onOpenAutoFocus: (e) => e.preventDefault(),
52
54
  onInteractOutside: (event) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/navigation/ProjectSelectorPopover.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { Dispatch, RefObject, SetStateAction } from 'react';\r\nimport Image from 'next/image';\r\nimport {\r\n Button,\r\n Command,\r\n CommandEmpty,\r\n CommandInput,\r\n CommandItem,\r\n CommandList,\r\n Popover,\r\n PopoverContent,\r\n PopoverTrigger,\r\n Tooltip,\r\n TooltipContent,\r\n TooltipTrigger,\r\n} from '../../index';\r\nimport { CheckIcon, ChevronDown, FolderOpen, Plus, Settings } from 'lucide-react';\r\nimport type { NavigationProject } from './types';\r\n\r\ninterface ProjectSelectorPopoverProps {\r\n open: boolean;\r\n setOpen: Dispatch<SetStateAction<boolean>>;\r\n titleRef?: RefObject<HTMLSpanElement | null>;\r\n projects: NavigationProject[];\r\n selectedProject: NavigationProject | null;\r\n onSelectProject: (project: NavigationProject) => void;\r\n onAddProject: () => void;\r\n onManageProjects: () => void;\r\n}\r\n\r\nfunction ProjectItemSkeleton() {\r\n return (\r\n <div className=\"flex items-center justify-between px-2 py-1.5 gap-2\">\r\n <div className=\"flex items-center gap-2 flex-1\">\r\n <div className=\"skeleton size-8 rounded-lg shrink-0\" />\r\n <div className=\"skeleton h-3.5 w-32 rounded\" />\r\n </div>\r\n <div className=\"skeleton size-4 rounded-full shrink-0\" />\r\n </div>\r\n );\r\n}\r\n\r\nexport function ProjectSelectorPopover({\r\n open,\r\n setOpen,\r\n titleRef,\r\n projects,\r\n selectedProject,\r\n onSelectProject,\r\n onAddProject,\r\n onManageProjects,\r\n}: ProjectSelectorPopoverProps) {\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger className=\"cursor-pointer\">\r\n <ChevronDown\r\n size={20}\r\n className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}\r\n />\r\n </PopoverTrigger>\r\n <PopoverContent\r\n className=\"absolute right-[-158px] top-2.5 w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200\"\r\n sideOffset={8}\r\n onOpenAutoFocus={(e: Event) => e.preventDefault()}\r\n onInteractOutside={(event: Event) => {\r\n if (titleRef?.current?.contains(event.target as Node)) {\r\n event.preventDefault();\r\n }\r\n }}\r\n >\r\n <div className=\"flex flex-col p-3 gap-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"paragraph-small-semibold\">Projetos</span>\r\n <div className=\"flex items-center gap-1.5\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"h-8! paragraph-small-semibold text-gray-950\"\r\n onClick={onAddProject}\r\n >\r\n <Plus size={16} />\r\n Adicionar\r\n </Button>\r\n <Tooltip>\r\n <TooltipTrigger asChild>\r\n <Button variant=\"secondary\" className=\"p-0 size-8\" onClick={onManageProjects}>\r\n <Settings size={18} />\r\n </Button>\r\n </TooltipTrigger>\r\n <TooltipContent className=\"z-[1002]\">Visualizar todos projetos</TooltipContent>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n <Command className=\"gap-2\">\r\n <CommandInput placeholder=\"Busque aqui\" />\r\n <CommandList className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\">\r\n {projects.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4\">\r\n <FolderOpen size={28} className=\"text-gray-300\" />\r\n <span className=\"paragraph-small-medium text-center text-gray-500\">\r\n Nenhum projeto encontrado.\r\n <br />\r\n Crie um projeto para começar.\r\n </span>\r\n </div>\r\n ) : (\r\n <>\r\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\r\n {projects.map((project) => {\r\n const isSelected = selectedProject?.id === project.id;\r\n return (\r\n <CommandItem\r\n key={project.id}\r\n value={project.title}\r\n className={isSelected ? 'bg-gray-50' : ''}\r\n onSelect={() => onSelectProject(project)}\r\n >\r\n <div className=\"flex items-center justify-between w-full cursor-pointer\">\r\n <div className=\"flex items-center gap-2 w-full\">\r\n <Image\r\n alt=\"Icon Project\"\r\n src={\r\n project.photo\r\n ? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${project.photo}`\r\n : '/images/Logomark.png'\r\n }\r\n width={32}\r\n height={32}\r\n className=\"rounded-full\"\r\n />\r\n {project.title}\r\n </div>\r\n {isSelected && (\r\n <CheckIcon className=\"size-4 text-gray-950\" />\r\n )}\r\n </div>\r\n </CommandItem>\r\n );\r\n })}\r\n </>\r\n )}\r\n </CommandList>\r\n </Command>\r\n </div>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/navigation/ProjectSelectorPopover.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { Dispatch, RefObject, SetStateAction } from 'react';\r\nimport Image from 'next/image';\r\nimport {\r\n Button,\r\n Command,\r\n CommandEmpty,\r\n CommandInput,\r\n CommandItem,\r\n CommandList,\r\n Popover,\r\n PopoverContent,\r\n PopoverTrigger,\r\n Tooltip,\r\n TooltipContent,\r\n TooltipTrigger,\r\n} from '../../index';\r\nimport { CheckIcon, ChevronDown, FolderOpen, Plus, Settings } from 'lucide-react';\r\nimport type { NavigationProject } from './types';\r\n\r\ninterface ProjectSelectorPopoverProps {\r\n open: boolean;\r\n setOpen: Dispatch<SetStateAction<boolean>>;\r\n titleRef?: RefObject<HTMLSpanElement | null>;\r\n projects: NavigationProject[];\r\n selectedProject: NavigationProject | null;\r\n onSelectProject: (project: NavigationProject) => void;\r\n onAddProject: () => void;\r\n onManageProjects: () => void;\r\n children?: React.ReactNode;\r\n}\r\n\r\nfunction ProjectItemSkeleton() {\r\n return (\r\n <div className=\"flex items-center justify-between px-2 py-1.5 gap-2\">\r\n <div className=\"flex items-center gap-2 flex-1\">\r\n <div className=\"skeleton size-8 rounded-lg shrink-0\" />\r\n <div className=\"skeleton h-3.5 w-32 rounded\" />\r\n </div>\r\n <div className=\"skeleton size-4 rounded-full shrink-0\" />\r\n </div>\r\n );\r\n}\r\n\r\nexport function ProjectSelectorPopover({\r\n open,\r\n setOpen,\r\n titleRef,\r\n projects,\r\n selectedProject,\r\n onSelectProject,\r\n onAddProject,\r\n onManageProjects,\r\n children,\r\n}: ProjectSelectorPopoverProps) {\r\n return (\r\n <Popover open={open} onOpenChange={setOpen}>\r\n <PopoverTrigger asChild>\r\n {children ?? (\r\n <button className=\"cursor-pointer\">\r\n <ChevronDown\r\n size={20}\r\n className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}\r\n />\r\n </button>\r\n )}\r\n </PopoverTrigger>\r\n <PopoverContent\r\n className=\"w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200\"\r\n align=\"start\"\r\n sideOffset={8}\r\n onOpenAutoFocus={(e: Event) => e.preventDefault()}\r\n onInteractOutside={(event: Event) => {\r\n if (titleRef?.current?.contains(event.target as Node)) {\r\n event.preventDefault();\r\n }\r\n }}\r\n >\r\n <div className=\"flex flex-col p-3 gap-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"paragraph-small-semibold\">Projetos</span>\r\n <div className=\"flex items-center gap-1.5\">\r\n <Button\r\n variant=\"secondary\"\r\n className=\"h-8! paragraph-small-semibold text-gray-950\"\r\n onClick={onAddProject}\r\n >\r\n <Plus size={16} />\r\n Adicionar\r\n </Button>\r\n <Tooltip>\r\n <TooltipTrigger asChild>\r\n <Button variant=\"secondary\" className=\"p-0 size-8\" onClick={onManageProjects}>\r\n <Settings size={18} />\r\n </Button>\r\n </TooltipTrigger>\r\n <TooltipContent className=\"z-[1002]\">Visualizar todos projetos</TooltipContent>\r\n </Tooltip>\r\n </div>\r\n </div>\r\n <Command className=\"gap-2\">\r\n <CommandInput placeholder=\"Busque aqui\" />\r\n <CommandList className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\">\r\n {projects.length === 0 ? (\r\n <div className=\"flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4\">\r\n <FolderOpen size={28} className=\"text-gray-300\" />\r\n <span className=\"paragraph-small-medium text-center text-gray-500\">\r\n Nenhum projeto encontrado.\r\n <br />\r\n Crie um projeto para começar.\r\n </span>\r\n </div>\r\n ) : (\r\n <>\r\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\r\n {projects.map((project) => {\r\n const isSelected = selectedProject?.id === project.id;\r\n return (\r\n <CommandItem\r\n key={project.id}\r\n value={project.title}\r\n className={isSelected ? 'bg-gray-50' : ''}\r\n onSelect={() => onSelectProject(project)}\r\n >\r\n <div className=\"flex items-center justify-between w-full cursor-pointer\">\r\n <div className=\"flex items-center gap-2 w-full\">\r\n <Image\r\n alt=\"Icon Project\"\r\n src={\r\n project.photo\r\n ? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${project.photo}`\r\n : '/images/Logomark.png'\r\n }\r\n width={32}\r\n height={32}\r\n className=\"rounded-full\"\r\n />\r\n {project.title}\r\n </div>\r\n {isSelected && (\r\n <CheckIcon className=\"size-4 text-gray-950\" />\r\n )}\r\n </div>\r\n </CommandItem>\r\n );\r\n })}\r\n </>\r\n )}\r\n </CommandList>\r\n </Command>\r\n </div>\r\n </PopoverContent>\r\n </Popover>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
@@ -35,29 +35,29 @@ function ProjectSelector({
35
35
  }, [openProjectList, breakpoint, clearProjectList]);
36
36
  if (breakpoint === "desktop" || breakpoint === "md") {
37
37
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 truncate select-none", ref: titleRef, children: [
39
- isLoading ? /* @__PURE__ */ jsx("div", { className: "skeleton h-4 w-32 rounded" }) : /* @__PURE__ */ jsx(
40
- "span",
41
- {
42
- className: "cursor-pointer paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block",
43
- onClick: () => setIsPopoverOpen((v) => !v),
44
- children: selectedProject?.title
45
- }
46
- ),
47
- /* @__PURE__ */ jsx(
48
- ProjectSelectorPopover,
49
- {
50
- open: isPopoverOpen,
51
- setOpen: setIsPopoverOpen,
52
- titleRef,
53
- projects,
54
- selectedProject,
55
- onSelectProject,
56
- onAddProject,
57
- onManageProjects
58
- }
59
- )
60
- ] }),
38
+ /* @__PURE__ */ jsx(
39
+ ProjectSelectorPopover,
40
+ {
41
+ open: isPopoverOpen,
42
+ setOpen: setIsPopoverOpen,
43
+ titleRef,
44
+ projects,
45
+ selectedProject,
46
+ onSelectProject,
47
+ onAddProject,
48
+ onManageProjects,
49
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 truncate select-none cursor-pointer", ref: titleRef, children: [
50
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "skeleton h-4 w-32 rounded" }) : /* @__PURE__ */ jsx("span", { className: "paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block", children: selectedProject?.title }),
51
+ /* @__PURE__ */ jsx(
52
+ ChevronDown,
53
+ {
54
+ size: 20,
55
+ className: `transition-transform duration-200 ${isPopoverOpen ? "rotate-180 text-gray-950" : "text-gray-400"}`
56
+ }
57
+ )
58
+ ] })
59
+ }
60
+ ),
61
61
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx(UsersSelectorPopover, { projectId: selectedProject?.id }) })
62
62
  ] });
63
63
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/navigation/subcomponents/ProjectSelector.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useRef, useEffect, RefObject } from 'react';\r\nimport { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';\r\nimport Image from 'next/image';\r\nimport { useAppNavigationContext } from '../AppNavigationContext';\r\nimport { ProjectSelectorPopover } from '../ProjectSelectorPopover';\r\nimport { UsersSelectorPopover } from '../../layouts/UsersSelectorPopover';\r\nimport { Button, Command, CommandEmpty, CommandInput, CommandItem, CommandList } from '../../../index';\r\nimport { ChevronDown, Plus, Settings } from 'lucide-react';\r\nimport type { NavigationProject } from '../types';\r\n\r\nexport interface ProjectSelectorProps {\r\n projects: NavigationProject[];\r\n selectedProject: NavigationProject | null;\r\n isLoading?: boolean;\r\n onSelectProject: (project: NavigationProject) => void;\r\n onAddProject: () => void;\r\n onManageProjects: () => void;\r\n}\r\n\r\nfunction ProjectItemSkeleton() {\r\n return (\r\n <div className=\"flex items-center gap-2 p-2\">\r\n <div className=\"skeleton size-8 rounded-lg shrink-0\" />\r\n <div className=\"skeleton h-3.5 w-32 rounded\" />\r\n </div>\r\n );\r\n}\r\n\r\nexport function ProjectSelector({\r\n projects,\r\n selectedProject,\r\n isLoading,\r\n onSelectProject,\r\n onAddProject,\r\n onManageProjects,\r\n}: ProjectSelectorProps) {\r\n const { breakpoint } = useAppNavigationContext();\r\n const [isPopoverOpen, setIsPopoverOpen] = useState(false);\r\n const [activeSection, setActiveSection] = useState<'projects' | null>(null);\r\n const titleRef = useRef<HTMLDivElement>(null);\r\n const { openProjectList, clearProjectList } = useMobileNavbarSheet();\r\n\r\n useEffect(() => {\r\n if (openProjectList && breakpoint === 'mobile') {\r\n setActiveSection('projects');\r\n clearProjectList();\r\n }\r\n }, [openProjectList, breakpoint, clearProjectList]);\r\n\r\n // Desktop and md: title + popover + users selector (same visual as current gpages sidebars)\r\n if (breakpoint === 'desktop' || breakpoint === 'md') {\r\n return (\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-2 truncate select-none\" ref={titleRef}>\r\n {isLoading ? (\r\n <div className=\"skeleton h-4 w-32 rounded\" />\r\n ) : (\r\n <span\r\n className=\"cursor-pointer paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block\"\r\n onClick={() => setIsPopoverOpen((v) => !v)}\r\n >\r\n {selectedProject?.title}\r\n </span>\r\n )}\r\n <ProjectSelectorPopover\r\n open={isPopoverOpen}\r\n setOpen={setIsPopoverOpen}\r\n titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}\r\n projects={projects}\r\n selectedProject={selectedProject}\r\n onSelectProject={onSelectProject}\r\n onAddProject={onAddProject}\r\n onManageProjects={onManageProjects}\r\n />\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <UsersSelectorPopover projectId={selectedProject?.id} />\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Mobile: inline collapsible accordion\r\n return (\r\n <div className=\"flex flex-col gap-2.5\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-1\">\r\n <span className=\"paragraph-medium-semibold text-gray-600\">{selectedProject?.title}</span>\r\n <ChevronDown\r\n size={20}\r\n onClick={() => setActiveSection(activeSection === 'projects' ? null : 'projects')}\r\n className={`transition-transform duration-200 cursor-pointer ${\r\n activeSection === 'projects' ? 'rotate-180 text-gray-950' : 'text-gray-400'\r\n }`}\r\n />\r\n </div>\r\n <UsersSelectorPopover projectId={selectedProject?.id} />\r\n </div>\r\n {activeSection === 'projects' && (\r\n <div className=\"flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"paragraph-small-semibold\">Projetos</span>\r\n <div className=\"flex items-center gap-1.5\">\r\n <Button variant=\"secondary\" className=\"h-8! paragraph-small-semibold text-gray-950\" onClick={onAddProject}>\r\n <Plus size={16} />\r\n Adicionar\r\n </Button>\r\n <Button variant=\"secondary\" className=\"p-0 size-8\" onClick={onManageProjects}>\r\n <Settings size={18} />\r\n </Button>\r\n </div>\r\n </div>\r\n <Command className=\"gap-2\">\r\n <CommandInput placeholder=\"Busque aqui\" />\r\n <CommandList className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\">\r\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\r\n {isLoading ? (\r\n <>\r\n <ProjectItemSkeleton />\r\n <ProjectItemSkeleton />\r\n </>\r\n ) : (\r\n projects.map((project) => (\r\n <CommandItem\r\n key={project.id}\r\n value={project.title}\r\n className={selectedProject?.id === project.id ? 'bg-gray-50' : ''}\r\n onSelect={() => { onSelectProject(project); setActiveSection(null); }}\r\n >\r\n <Image\r\n alt=\"Icon Project\"\r\n src={\r\n project.photo\r\n ? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${project.photo}`\r\n : '/images/Logomark.png'\r\n }\r\n width={32}\r\n height={32}\r\n className=\"rounded-full\"\r\n />\r\n {project.title}\r\n </CommandItem>\r\n ))\r\n )}\r\n </CommandList>\r\n </Command>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/navigation/subcomponents/ProjectSelector.tsx"],"sourcesContent":["'use client';\r\n\r\nimport { useState, useRef, useEffect, RefObject } from 'react';\r\nimport { useMobileNavbarSheet } from '../../../store/useMobileNavbarSheet';\r\nimport Image from 'next/image';\r\nimport { useAppNavigationContext } from '../AppNavigationContext';\r\nimport { ProjectSelectorPopover } from '../ProjectSelectorPopover';\r\nimport { UsersSelectorPopover } from '../../layouts/UsersSelectorPopover';\r\nimport { Button, Command, CommandEmpty, CommandInput, CommandItem, CommandList } from '../../../index';\r\nimport { ChevronDown, Plus, Settings } from 'lucide-react';\r\nimport type { NavigationProject } from '../types';\r\n\r\nexport interface ProjectSelectorProps {\r\n projects: NavigationProject[];\r\n selectedProject: NavigationProject | null;\r\n isLoading?: boolean;\r\n onSelectProject: (project: NavigationProject) => void;\r\n onAddProject: () => void;\r\n onManageProjects: () => void;\r\n}\r\n\r\nfunction ProjectItemSkeleton() {\r\n return (\r\n <div className=\"flex items-center gap-2 p-2\">\r\n <div className=\"skeleton size-8 rounded-lg shrink-0\" />\r\n <div className=\"skeleton h-3.5 w-32 rounded\" />\r\n </div>\r\n );\r\n}\r\n\r\nexport function ProjectSelector({\r\n projects,\r\n selectedProject,\r\n isLoading,\r\n onSelectProject,\r\n onAddProject,\r\n onManageProjects,\r\n}: ProjectSelectorProps) {\r\n const { breakpoint } = useAppNavigationContext();\r\n const [isPopoverOpen, setIsPopoverOpen] = useState(false);\r\n const [activeSection, setActiveSection] = useState<'projects' | null>(null);\r\n const titleRef = useRef<HTMLDivElement>(null);\r\n const { openProjectList, clearProjectList } = useMobileNavbarSheet();\r\n\r\n useEffect(() => {\r\n if (openProjectList && breakpoint === 'mobile') {\r\n setActiveSection('projects');\r\n clearProjectList();\r\n }\r\n }, [openProjectList, breakpoint, clearProjectList]);\r\n\r\n // Desktop and md: title + popover + users selector (same visual as current gpages sidebars)\r\n if (breakpoint === 'desktop' || breakpoint === 'md') {\r\n return (\r\n <div className=\"flex items-center justify-between\">\r\n <ProjectSelectorPopover\r\n open={isPopoverOpen}\r\n setOpen={setIsPopoverOpen}\r\n titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}\r\n projects={projects}\r\n selectedProject={selectedProject}\r\n onSelectProject={onSelectProject}\r\n onAddProject={onAddProject}\r\n onManageProjects={onManageProjects}\r\n >\r\n <div className=\"flex items-center gap-2 truncate select-none cursor-pointer\" ref={titleRef}>\r\n {isLoading ? (\r\n <div className=\"skeleton h-4 w-32 rounded\" />\r\n ) : (\r\n <span className=\"paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block\">\r\n {selectedProject?.title}\r\n </span>\r\n )}\r\n <ChevronDown\r\n size={20}\r\n className={`transition-transform duration-200 ${isPopoverOpen ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}\r\n />\r\n </div>\r\n </ProjectSelectorPopover>\r\n <div className=\"flex items-center gap-2\">\r\n <UsersSelectorPopover projectId={selectedProject?.id} />\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Mobile: inline collapsible accordion\r\n return (\r\n <div className=\"flex flex-col gap-2.5\">\r\n <div className=\"flex items-center justify-between\">\r\n <div className=\"flex items-center gap-1\">\r\n <span className=\"paragraph-medium-semibold text-gray-600\">{selectedProject?.title}</span>\r\n <ChevronDown\r\n size={20}\r\n onClick={() => setActiveSection(activeSection === 'projects' ? null : 'projects')}\r\n className={`transition-transform duration-200 cursor-pointer ${\r\n activeSection === 'projects' ? 'rotate-180 text-gray-950' : 'text-gray-400'\r\n }`}\r\n />\r\n </div>\r\n <UsersSelectorPopover projectId={selectedProject?.id} />\r\n </div>\r\n {activeSection === 'projects' && (\r\n <div className=\"flex flex-col p-3 gap-2 border border-gray-200 rounded-lg animate-in fade-in duration-400\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"paragraph-small-semibold\">Projetos</span>\r\n <div className=\"flex items-center gap-1.5\">\r\n <Button variant=\"secondary\" className=\"h-8! paragraph-small-semibold text-gray-950\" onClick={onAddProject}>\r\n <Plus size={16} />\r\n Adicionar\r\n </Button>\r\n <Button variant=\"secondary\" className=\"p-0 size-8\" onClick={onManageProjects}>\r\n <Settings size={18} />\r\n </Button>\r\n </div>\r\n </div>\r\n <Command className=\"gap-2\">\r\n <CommandInput placeholder=\"Busque aqui\" />\r\n <CommandList className=\"custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]\">\r\n <CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>\r\n {isLoading ? (\r\n <>\r\n <ProjectItemSkeleton />\r\n <ProjectItemSkeleton />\r\n </>\r\n ) : (\r\n projects.map((project) => (\r\n <CommandItem\r\n key={project.id}\r\n value={project.title}\r\n className={selectedProject?.id === project.id ? 'bg-gray-50' : ''}\r\n onSelect={() => { onSelectProject(project); setActiveSection(null); }}\r\n >\r\n <Image\r\n alt=\"Icon Project\"\r\n src={\r\n project.photo\r\n ? `${process.env.NEXT_PUBLIC_STORAGE_URL}/${project.photo}`\r\n : '/images/Logomark.png'\r\n }\r\n width={32}\r\n height={32}\r\n className=\"rounded-full\"\r\n />\r\n {project.title}\r\n </CommandItem>\r\n ))\r\n )}\r\n </CommandList>\r\n </Command>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","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.201",
3
+ "version": "1.1.204",
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"
@@ -28,6 +28,7 @@ interface ProjectSelectorPopoverProps {
28
28
  onSelectProject: (project: NavigationProject) => void;
29
29
  onAddProject: () => void;
30
30
  onManageProjects: () => void;
31
+ children?: React.ReactNode;
31
32
  }
32
33
 
33
34
  function ProjectItemSkeleton() {
@@ -51,17 +52,23 @@ export function ProjectSelectorPopover({
51
52
  onSelectProject,
52
53
  onAddProject,
53
54
  onManageProjects,
55
+ children,
54
56
  }: ProjectSelectorPopoverProps) {
55
57
  return (
56
58
  <Popover open={open} onOpenChange={setOpen}>
57
- <PopoverTrigger className="cursor-pointer">
58
- <ChevronDown
59
- size={20}
60
- className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
61
- />
59
+ <PopoverTrigger asChild>
60
+ {children ?? (
61
+ <button className="cursor-pointer">
62
+ <ChevronDown
63
+ size={20}
64
+ className={`transition-transform duration-200 ${open ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
65
+ />
66
+ </button>
67
+ )}
62
68
  </PopoverTrigger>
63
69
  <PopoverContent
64
- className="absolute right-[-158px] top-2.5 w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
70
+ className="w-[296px] p-0 bg-white rounded-2xl shadow-md border border-gray-200"
71
+ align="start"
65
72
  sideOffset={8}
66
73
  onOpenAutoFocus={(e: Event) => e.preventDefault()}
67
74
  onInteractOutside={(event: Event) => {
@@ -53,28 +53,30 @@ export function ProjectSelector({
53
53
  if (breakpoint === 'desktop' || breakpoint === 'md') {
54
54
  return (
55
55
  <div className="flex items-center justify-between">
56
- <div className="flex items-center gap-2 truncate select-none" ref={titleRef}>
57
- {isLoading ? (
58
- <div className="skeleton h-4 w-32 rounded" />
59
- ) : (
60
- <span
61
- className="cursor-pointer paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block"
62
- onClick={() => setIsPopoverOpen((v) => !v)}
63
- >
64
- {selectedProject?.title}
65
- </span>
66
- )}
67
- <ProjectSelectorPopover
68
- open={isPopoverOpen}
69
- setOpen={setIsPopoverOpen}
70
- titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}
71
- projects={projects}
72
- selectedProject={selectedProject}
73
- onSelectProject={onSelectProject}
74
- onAddProject={onAddProject}
75
- onManageProjects={onManageProjects}
76
- />
77
- </div>
56
+ <ProjectSelectorPopover
57
+ open={isPopoverOpen}
58
+ setOpen={setIsPopoverOpen}
59
+ titleRef={titleRef as unknown as RefObject<HTMLSpanElement | null>}
60
+ projects={projects}
61
+ selectedProject={selectedProject}
62
+ onSelectProject={onSelectProject}
63
+ onAddProject={onAddProject}
64
+ onManageProjects={onManageProjects}
65
+ >
66
+ <div className="flex items-center gap-2 truncate select-none cursor-pointer" ref={titleRef}>
67
+ {isLoading ? (
68
+ <div className="skeleton h-4 w-32 rounded" />
69
+ ) : (
70
+ <span className="paragraph-medium-semibold text-gray-600 truncate max-w-[120px] inline-block">
71
+ {selectedProject?.title}
72
+ </span>
73
+ )}
74
+ <ChevronDown
75
+ size={20}
76
+ className={`transition-transform duration-200 ${isPopoverOpen ? 'rotate-180 text-gray-950' : 'text-gray-400'}`}
77
+ />
78
+ </div>
79
+ </ProjectSelectorPopover>
78
80
  <div className="flex items-center gap-2">
79
81
  <UsersSelectorPopover projectId={selectedProject?.id} />
80
82
  </div>
@@ -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