Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import { InformationCircleIcon } from "@heroicons/react/24/outline";
2import { TRANSFORMS } from "@hey/data/constants";
3import sanitizeDStorageUrl from "@hey/helpers/sanitizeDStorageUrl";
4import type { SyntheticEvent } from "react";
5import Cropper from "react-easy-crop";
6import ChooseFile from "@/components/Shared/ChooseFile";
7import { Button, Image, Modal } from "@/components/Shared/UI";
8import useImageCropUpload from "@/hooks/useImageCropUpload";
9
10interface CoverUploadProps {
11 src: string;
12 setSrc: (src: string) => void;
13}
14
15const CoverUpload = ({ src, setSrc }: CoverUploadProps) => {
16 const {
17 pictureSrc,
18 crop,
19 setCrop,
20 zoom,
21 setZoom,
22 showModal,
23 uploading,
24 uploadedPicture,
25 renderPictureUrl,
26 onFileChange,
27 onCropComplete,
28 handleUploadAndSave,
29 handleModalClose
30 } = useImageCropUpload({
31 aspect: 1350 / 350,
32 label: "cover",
33 setSrc,
34 src,
35 transform: TRANSFORMS.COVER
36 });
37
38 return (
39 <>
40 <div className="space-y-1.5">
41 <div className="label">Cover</div>
42 <div className="space-y-3">
43 <div>
44 <Image
45 alt="Cover picture crop preview"
46 className="h-[175px] w-[675px] rounded-lg object-cover"
47 onError={(event: SyntheticEvent<HTMLImageElement>) => {
48 const target = event.currentTarget;
49 target.src = sanitizeDStorageUrl(src);
50 }}
51 src={uploadedPicture || renderPictureUrl}
52 />
53 </div>
54 <ChooseFile onChange={(event) => onFileChange(event)} />
55 </div>
56 </div>
57 <Modal
58 onClose={handleModalClose}
59 show={showModal}
60 size="lg"
61 title="Crop cover picture"
62 >
63 <div className="space-y-5 p-5">
64 <div className="relative flex size-64 w-full">
65 <Cropper
66 aspect={1350 / 350}
67 crop={crop}
68 image={pictureSrc}
69 onCropChange={setCrop}
70 onCropComplete={onCropComplete}
71 onZoomChange={setZoom}
72 zoom={zoom}
73 />
74 </div>
75 <div className="flex w-full flex-wrap items-center justify-between gap-y-3">
76 <div className="flex items-center space-x-1 text-left text-gray-500 text-sm dark:text-gray-200">
77 <InformationCircleIcon className="size-4" />
78 <div>
79 Optimal cover picture size is <b>1350x350</b>
80 </div>
81 </div>
82 <Button
83 disabled={uploading || !pictureSrc}
84 loading={uploading}
85 onClick={handleUploadAndSave}
86 type="submit"
87 >
88 Upload
89 </Button>
90 </div>
91 </div>
92 </Modal>
93 </>
94 );
95};
96
97export default CoverUpload;