Skip to content

Commit

Permalink
fix(image): prevent console.log error
Browse files Browse the repository at this point in the history
  • Loading branch information
NicoSerranoP committed Dec 17, 2024
1 parent 7d5670e commit d8e1199
Showing 1 changed file with 74 additions and 62 deletions.
136 changes: 74 additions & 62 deletions packages/interface/src/components/ImageUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,94 @@
import { useMutation } from "@tanstack/react-query";
import clsx from "clsx";
import { ImageIcon } from "lucide-react";
import { type ComponentProps, useRef, useCallback } from "react";
import { type ComponentProps, ElementType, forwardRef, useRef, useCallback } from "react";
import { Controller, useFormContext } from "react-hook-form";
import { toast } from "sonner";

import { IconButton } from "~/components/ui/Button";

import { PolymorphicRef } from "./ui";

export interface IImageUploadProps extends ComponentProps<"img"> {
name?: string;
maxSize?: number;
}

export const ImageUpload = ({
name = "",
maxSize = 1024 * 1024, // 1 MB
className,
}: IImageUploadProps): JSX.Element => {
const ref = useRef<HTMLInputElement>(null);
const { control } = useFormContext();

const select = useMutation({
mutationFn: async (file: File) => {
if (file.size >= maxSize) {
toast.error("Image too large", {
description: `The image to selected is: ${(file.size / 1024).toFixed(2)} / ${(maxSize / 1024).toFixed(2)} kb`,
});
throw new Error("IMAGE_TOO_LARGE");
}
export const ImageUpload = forwardRef(
(
{
name = "",
maxSize = 1024 * 1024, // 1 MB
className,
}: IImageUploadProps,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
ref: PolymorphicRef<ElementType>,
): JSX.Element => {
const internalRef = useRef<HTMLInputElement>(null);
const { control } = useFormContext();

return Promise.resolve(URL.createObjectURL(file));
},
});
const select = useMutation({
mutationFn: async (file: File) => {
if (file.size >= maxSize) {
toast.error("Image too large", {
description: `The image to selected is: ${(file.size / 1024).toFixed(2)} / ${(maxSize / 1024).toFixed(2)} kb`,
});
throw new Error("IMAGE_TOO_LARGE");
}

const onClickIconButton = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
}, []);
return Promise.resolve(URL.createObjectURL(file));
},
});

return (
<Controller
control={control}
name={name}
render={({ field: { value, onChange, ...field } }) => (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
<div
className={clsx("relative cursor-pointer overflow-hidden", className)}
onClick={() => ref.current?.click()}
>
<IconButton className="absolute bottom-1 right-1" icon={ImageIcon} onClick={onClickIconButton} />
const onClickIconButton = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
}, []);

return (
<Controller
control={control}
name={name}
render={({ field: { value, onChange, ...field } }) => (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
<div
className={clsx("h-full rounded-xl bg-gray-200 bg-cover bg-center bg-no-repeat")}
style={{
backgroundImage: select.data ? `url("${value}")` : "none",
className={clsx("relative cursor-pointer overflow-hidden", className)}
onClick={() => {
internalRef.current?.click();
}}
/>
>
<IconButton className="absolute bottom-1 right-1" icon={ImageIcon} onClick={onClickIconButton} />

<input
{...field}
ref={ref}
accept="image/png, image/jpeg"
className="hidden"
type="file"
// value={value?.[name]}
onChange={(event) => {
const [file] = event.target.files ?? [];
if (file) {
select.mutate(file, {
onSuccess: (objectUrl) => {
onChange(objectUrl);
},
});
}
}}
/>
</div>
)}
rules={{ required: "Recipe picture is required" }}
/>
);
};
<div
className={clsx("h-full rounded-xl bg-gray-200 bg-cover bg-center bg-no-repeat")}
style={{
backgroundImage: select.data ? `url("${value}")` : "none",
}}
/>

<input
{...field}
ref={internalRef}
accept="image/png, image/jpeg"
className="hidden"
type="file"
// value={value?.[name]}
onChange={(event) => {
const [file] = event.target.files ?? [];
if (file) {
select.mutate(file, {
onSuccess: (objectUrl) => {
onChange(objectUrl);
},
});
}
}}
/>
</div>
)}
rules={{ required: "Recipe picture is required" }}
/>
);
},
);

ImageUpload.displayName = "ImageUpload";

0 comments on commit d8e1199

Please sign in to comment.