From a519941b81ff48425a56723a3c3b4fb90ba356fb Mon Sep 17 00:00:00 2001 From: Mehul Date: Wed, 15 Nov 2023 15:23:33 +0530 Subject: [PATCH] fix avatar remove button (#12249) --- .../web/pages/settings/my-account/profile.tsx | 35 ++++++------------- packages/lib/checkIfItFallbackImage.ts | 6 ++++ .../loggedInViewer/updateProfile.handler.ts | 2 +- .../image-uploader/ImageUploader.tsx | 14 +++----- 4 files changed, 21 insertions(+), 36 deletions(-) create mode 100644 packages/lib/checkIfItFallbackImage.ts diff --git a/apps/web/pages/settings/my-account/profile.tsx b/apps/web/pages/settings/my-account/profile.tsx index 45393ef6cc..99e2418d80 100644 --- a/apps/web/pages/settings/my-account/profile.tsx +++ b/apps/web/pages/settings/my-account/profile.tsx @@ -9,8 +9,8 @@ import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode"; import OrganizationMemberAvatar from "@calcom/features/ee/organizations/components/OrganizationMemberAvatar"; import SectionBottomActions from "@calcom/features/settings/SectionBottomActions"; import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout"; +import checkIfItFallbackImage from "@calcom/lib/checkIfItFallbackImage"; import { APP_NAME, FULL_NAME_LENGTH_MAX_LIMIT } from "@calcom/lib/constants"; -import { AVATAR_FALLBACK } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { md } from "@calcom/lib/markdownIt"; import turndown from "@calcom/lib/turndownService"; @@ -72,32 +72,24 @@ interface DeleteAccountValues { type FormValues = { username: string; - avatar: string | null; + avatar: string; name: string; email: string; bio: string; }; -const checkIfItFallbackImage = (fetchedImgSrc?: string) => { - return !fetchedImgSrc || fetchedImgSrc.endsWith(AVATAR_FALLBACK); -}; - const ProfileView = () => { const { t } = useLocale(); const utils = trpc.useContext(); const { update } = useSession(); - const [fetchedImgSrc, setFetchedImgSrc] = useState(undefined); + const [fetchedImgSrc, setFetchedImgSrc] = useState(""); const { data: user, isLoading } = trpc.viewer.me.useQuery(undefined, { onSuccess: async (userData) => { try { - if (!userData.organization) { - const res = await fetch(userData.avatar); - if (res.url) setFetchedImgSrc(res.url); - } else { - setFetchedImgSrc(""); - } + const res = await fetch(userData.avatar); + if (res.url) setFetchedImgSrc(res.url); } catch (err) { setFetchedImgSrc(""); } @@ -234,7 +226,7 @@ const ProfileView = () => { const defaultValues = { username: user.username || "", - avatar: user.avatar || "", + avatar: fetchedImgSrc || "", name: user.name || "", email: user.email || "", bio: user.bio || "", @@ -251,8 +243,6 @@ const ProfileView = () => { key={JSON.stringify(defaultValues)} defaultValues={defaultValues} isLoading={updateProfileMutation.isLoading} - isFallbackImg={checkIfItFallbackImage(fetchedImgSrc)} - userAvatar={user.avatar} user={user} userOrganization={user.organization} onSubmit={(values) => { @@ -397,8 +387,6 @@ const ProfileForm = ({ onSubmit, extraField, isLoading = false, - isFallbackImg, - userAvatar, user, userOrganization, }: { @@ -406,8 +394,6 @@ const ProfileForm = ({ onSubmit: (values: FormValues) => void; extraField?: React.ReactNode; isLoading: boolean; - isFallbackImg: boolean; - userAvatar: string; user: RouterOutputs["viewer"]["me"]; userOrganization: RouterOutputs["viewer"]["me"]["organization"]; }) => { @@ -416,7 +402,7 @@ const ProfileForm = ({ const profileFormSchema = z.object({ username: z.string(), - avatar: z.string().nullable(), + avatar: z.string(), name: z .string() .trim() @@ -438,7 +424,6 @@ const ProfileForm = ({ } = formMethods; const isDisabled = isSubmitting || !isDirty; - return (
@@ -447,7 +432,7 @@ const ProfileForm = ({ control={formMethods.control} name="avatar" render={({ field: { value } }) => { - const showRemoveAvatarButton = !isFallbackImg || (value && userAvatar !== value); + const showRemoveAvatarButton = !checkIfItFallbackImage(value); const organization = userOrganization && userOrganization.id ? { @@ -474,7 +459,7 @@ const ProfileForm = ({ handleAvatarChange={(newAvatar) => { formMethods.setValue("avatar", newAvatar, { shouldDirty: true }); }} - imageSrc={value || undefined} + imageSrc={value} triggerButtonColor={showRemoveAvatarButton ? "secondary" : "primary"} /> @@ -482,7 +467,7 @@ const ProfileForm = ({ diff --git a/packages/lib/checkIfItFallbackImage.ts b/packages/lib/checkIfItFallbackImage.ts new file mode 100644 index 0000000000..961d106df7 --- /dev/null +++ b/packages/lib/checkIfItFallbackImage.ts @@ -0,0 +1,6 @@ +import { AVATAR_FALLBACK } from "./constants"; + +const checkIfItFallbackImage = (fetchedImgSrc: string) => { + return !fetchedImgSrc || fetchedImgSrc.endsWith(AVATAR_FALLBACK); +}; +export default checkIfItFallbackImage; diff --git a/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts b/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts index 849e3f253b..4231d45dc2 100644 --- a/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts +++ b/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts @@ -36,7 +36,7 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) const userMetadata = handleUserMetadata({ ctx, input }); const data: Prisma.UserUpdateInput = { ...input, - avatar: await getAvatarToSet(input.avatar), + avatar: input.avatar ? await getAvatarToSet(input.avatar) : null, metadata: userMetadata, }; diff --git a/packages/ui/components/image-uploader/ImageUploader.tsx b/packages/ui/components/image-uploader/ImageUploader.tsx index ea84cd7fe2..c8d13b716e 100644 --- a/packages/ui/components/image-uploader/ImageUploader.tsx +++ b/packages/ui/components/image-uploader/ImageUploader.tsx @@ -3,6 +3,7 @@ import type { FormEvent } from "react"; import { useCallback, useEffect, useState } from "react"; import Cropper from "react-easy-crop"; +import checkIfItFallbackImage from "@calcom/lib/checkIfItFallbackImage"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { ButtonColor } from "../.."; @@ -120,20 +121,15 @@ export default function ImageUploader({ buttonMsg, handleAvatarChange, triggerButtonColor, - ...props + imageSrc, }: ImageUploaderProps) { const { t } = useLocale(); - const [imageSrc, setImageSrc] = useState(null); const [croppedAreaPixels, setCroppedAreaPixels] = useState(null); const [{ result }, setFile] = useFileReader({ method: "readAsDataURL", }); - useEffect(() => { - if (props.imageSrc) setImageSrc(props.imageSrc); - }, [props.imageSrc]); - const onInputFile = (e: FileEvent) => { if (!e.target.files?.length) { return; @@ -157,7 +153,6 @@ export default function ImageUploader({ result as string /* result is always string when using readAsDataUrl */, croppedAreaPixels ); - setImageSrc(croppedImage); handleAvatarChange(croppedImage); } catch (e) { console.error(e); @@ -181,12 +176,11 @@ export default function ImageUploader({
{!result && (
- {!imageSrc && ( + {!imageSrc || checkIfItFallbackImage(imageSrc) ? (

{t("no_target", { target })}

- )} - {imageSrc && ( + ) : ( // eslint-disable-next-line @next/next/no-img-element {target} )}