1
- import { useEffect } from 'react' ;
1
+ import { Dispatch , useEffect } from 'react' ;
2
2
import { styled } from 'styled-components' ;
3
3
4
4
import CameraIcon from '@/assets/svg/camera_icon.svg' ;
5
5
import DefaultDogIcon from '@/assets/svg/dog_icon.svg' ;
6
6
import { usePetAdditionContext } from '@/context/petProfile/PetAdditionContext' ;
7
7
import { useImageUpload } from '@/hooks/@common/useImageUpload' ;
8
8
9
- const PetProfileImageUploader = ( ) => {
9
+ import LoadingSpinner from '../@common/LoadingSpinner/LoadingSpinner' ;
10
+
11
+ interface PetProfileImageUploaderProps {
12
+ updateIsValid ?: Dispatch < React . SetStateAction < boolean > > ;
13
+ }
14
+
15
+ const PetProfileImageUploader = ( props : PetProfileImageUploaderProps ) => {
16
+ const { updateIsValid } = props ;
10
17
const { petProfile, updatePetProfile } = usePetAdditionContext ( ) ;
11
- const { previewImage, imageUrl, uploadImage } = useImageUpload ( ) ;
18
+ const {
19
+ imageUrl,
20
+ previewImage,
21
+ compressionPercentage,
22
+ isImageBeingUploaded,
23
+ isImageBeingCompressed,
24
+ uploadCompressedImage,
25
+ } = useImageUpload ( ) ;
12
26
13
27
useEffect ( ( ) => {
14
28
if ( imageUrl ) updatePetProfile ( { imageUrl } ) ;
15
29
} , [ imageUrl ] ) ;
16
30
31
+ useEffect ( ( ) => {
32
+ if ( updateIsValid ) updateIsValid ( ! isImageBeingUploaded && ! isImageBeingCompressed ) ;
33
+ } , [ isImageBeingCompressed , isImageBeingUploaded , updateIsValid ] ) ;
34
+
17
35
return (
18
36
< ImageUploadLabel aria-label = "사진 업로드하기" >
19
- < input type = "file" accept = "image/*" onChange = { uploadImage } />
37
+ < input type = "file" accept = "image/*" onChange = { uploadCompressedImage } />
20
38
< PreviewImageWrapper >
21
- < PreviewImage src = { petProfile . imageUrl || previewImage || DefaultDogIcon } alt = "" />
39
+ { isImageBeingCompressed && (
40
+ < ProgressTracker >
41
+ < p > 이미지 압축 중({ compressionPercentage } %)</ p >
42
+ </ ProgressTracker >
43
+ ) }
44
+ < PreviewImage src = { previewImage || petProfile . imageUrl || DefaultDogIcon } alt = "" />
22
45
</ PreviewImageWrapper >
23
46
< CameraIconWrapper >
24
47
< img src = { CameraIcon } alt = "" />
25
48
</ CameraIconWrapper >
49
+ { isImageBeingUploaded && < LoadingSpinner /> }
26
50
</ ImageUploadLabel >
27
51
) ;
28
52
} ;
@@ -38,9 +62,33 @@ const PreviewImageWrapper = styled.div`
38
62
height: 16rem;
39
63
40
64
border: none;
65
+ border: 1px solid ${ ( { theme } ) => theme . color . grey300 } ;
41
66
border-radius: 50%;
42
67
` ;
43
68
69
+ const ProgressTracker = styled . div `
70
+ position: absolute;
71
+ z-index: 100;
72
+ top: 0;
73
+ left: 0;
74
+
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: center;
78
+
79
+ width: inherit;
80
+ height: inherit;
81
+
82
+ opacity: 0.7;
83
+ background-color: ${ ( { theme } ) => theme . color . grey200 } ;
84
+
85
+ & > p {
86
+ font-size: 1.6rem;
87
+
88
+ opacity: 1;
89
+ }
90
+ ` ;
91
+
44
92
const PreviewImage = styled . img `
45
93
position: absolute;
46
94
top: 0;
@@ -69,7 +117,6 @@ const ImageUploadLabel = styled.label`
69
117
background-repeat: no-repeat;
70
118
background-position: center;
71
119
background-size: cover;
72
- border: 1px solid ${ ( { theme } ) => theme . color . grey300 } ;
73
120
border-radius: 50%;
74
121
75
122
& > input {
@@ -79,6 +126,7 @@ const ImageUploadLabel = styled.label`
79
126
80
127
const CameraIconWrapper = styled . div `
81
128
position: absolute;
129
+ z-index: 200;
82
130
right: 0;
83
131
bottom: 0;
84
132
0 commit comments