@bjsdistribution/dms-client-return 0.1.11-prod → 0.1.12-prod
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.
- package/dist/dms-client-return.cjs.development.js +91 -50
- package/dist/dms-client-return.cjs.development.js.map +1 -1
- package/dist/dms-client-return.cjs.production.min.js +1 -1
- package/dist/dms-client-return.cjs.production.min.js.map +1 -1
- package/dist/dms-client-return.esm.js +91 -50
- package/dist/dms-client-return.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/order-view/order-actions/actions/add-resources/DocFileUpload.tsx +92 -72
- package/src/components/order-view/order-actions/actions/add-resources/index.tsx +27 -10
package/package.json
CHANGED
|
@@ -1,51 +1,75 @@
|
|
|
1
1
|
import React, { useRef, useState } from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
|
-
import { Button } from '@bjsdistribution/dms-component-library';
|
|
3
|
+
import { Button, CrossIcon } from '@bjsdistribution/dms-component-library';
|
|
4
4
|
import UploadIcon from '../../../../../assets/icons/UploadIcon';
|
|
5
5
|
import { atom, useAtom } from 'jotai';
|
|
6
6
|
import { notification } from 'antd';
|
|
7
|
-
|
|
7
|
+
// Store uploaded files
|
|
8
8
|
export const uploadedFilesAtom = atom<File[]>([]);
|
|
9
9
|
|
|
10
|
-
// Allowed photo
|
|
11
|
-
const
|
|
10
|
+
// Allowed photo MIME types
|
|
11
|
+
const allowedFileTypes = ['image/jpeg', 'image/png'];
|
|
12
12
|
|
|
13
13
|
function DocFileUpload() {
|
|
14
14
|
const [uploadedFiles, setUploadedFiles] = useAtom(uploadedFilesAtom);
|
|
15
15
|
const [dragging, setDragging] = useState(false);
|
|
16
16
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
17
17
|
|
|
18
|
+
const isDuplicate = (file: File) =>
|
|
19
|
+
uploadedFiles?.some(
|
|
20
|
+
existing =>
|
|
21
|
+
existing?.name === file?.name &&
|
|
22
|
+
existing?.size === file?.size &&
|
|
23
|
+
existing?.lastModified === file?.lastModified
|
|
24
|
+
);
|
|
25
|
+
|
|
18
26
|
const handleFileUpload = (files: FileList | null) => {
|
|
19
|
-
if (files)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
if (!files) return;
|
|
28
|
+
|
|
29
|
+
const validFiles: File[] = [];
|
|
30
|
+
const rejectedFiles: File[] = [];
|
|
31
|
+
|
|
32
|
+
Array.from(files).forEach(file => {
|
|
33
|
+
const isValidType = allowedFileTypes?.includes(file.type);
|
|
34
|
+
const isNew = !isDuplicate(file);
|
|
23
35
|
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
validFiles.forEach(file => {
|
|
27
|
-
notification.success({
|
|
28
|
-
message: 'Success',
|
|
29
|
-
description: `${file.name} added successfully.`,
|
|
30
|
-
});
|
|
31
|
-
});
|
|
36
|
+
if (isValidType && isNew) {
|
|
37
|
+
validFiles?.push(file);
|
|
32
38
|
} else {
|
|
33
|
-
|
|
34
|
-
message: 'Error',
|
|
35
|
-
description: 'Only photos (JPEG, PNG) and videos (MP4) are allowed.',
|
|
36
|
-
});
|
|
39
|
+
rejectedFiles?.push(file);
|
|
37
40
|
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (validFiles?.length > 0) {
|
|
44
|
+
setUploadedFiles(prev => [...prev, ...validFiles]);
|
|
45
|
+
validFiles?.forEach(file =>
|
|
46
|
+
notification.success({
|
|
47
|
+
message: 'Success',
|
|
48
|
+
description: `${file.name} added successfully.`,
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (rejectedFiles?.length > 0) {
|
|
54
|
+
notification.error({
|
|
55
|
+
message: 'Some files were not added',
|
|
56
|
+
description: 'Either they were duplicates or not JPEG/PNG format.',
|
|
57
|
+
});
|
|
38
58
|
}
|
|
39
59
|
};
|
|
40
60
|
|
|
61
|
+
const handleRemoveFile = (indexToRemove: number) => {
|
|
62
|
+
const updated = uploadedFiles?.filter((_, i) => i !== indexToRemove);
|
|
63
|
+
setUploadedFiles(updated);
|
|
64
|
+
notification.info({ message: 'File Removed' });
|
|
65
|
+
};
|
|
66
|
+
|
|
41
67
|
const handleDragOver = (e: React.DragEvent) => {
|
|
42
68
|
e.preventDefault();
|
|
43
69
|
setDragging(true);
|
|
44
70
|
};
|
|
45
71
|
|
|
46
|
-
const handleDragLeave = () =>
|
|
47
|
-
setDragging(false);
|
|
48
|
-
};
|
|
72
|
+
const handleDragLeave = () => setDragging(false);
|
|
49
73
|
|
|
50
74
|
const handleDrop = (e: React.DragEvent) => {
|
|
51
75
|
e.preventDefault();
|
|
@@ -55,13 +79,10 @@ function DocFileUpload() {
|
|
|
55
79
|
|
|
56
80
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
57
81
|
handleFileUpload(e.target.files);
|
|
82
|
+
e.target.value = ''; // Allow re-upload of same file
|
|
58
83
|
};
|
|
59
84
|
|
|
60
|
-
const handleButtonClick = () =>
|
|
61
|
-
if (fileInputRef.current) {
|
|
62
|
-
fileInputRef.current.click();
|
|
63
|
-
}
|
|
64
|
-
};
|
|
85
|
+
const handleButtonClick = () => fileInputRef.current?.click();
|
|
65
86
|
|
|
66
87
|
return (
|
|
67
88
|
<MainContainer>
|
|
@@ -73,7 +94,7 @@ function DocFileUpload() {
|
|
|
73
94
|
>
|
|
74
95
|
<Container>
|
|
75
96
|
<UploadButton
|
|
76
|
-
|
|
97
|
+
type="button"
|
|
77
98
|
shape="rounded"
|
|
78
99
|
onClick={handleButtonClick}
|
|
79
100
|
>
|
|
@@ -81,30 +102,32 @@ function DocFileUpload() {
|
|
|
81
102
|
</UploadButton>
|
|
82
103
|
<FileInput
|
|
83
104
|
type="file"
|
|
84
|
-
|
|
105
|
+
accept={allowedFileTypes.join(',')}
|
|
85
106
|
multiple
|
|
86
107
|
onChange={handleInputChange}
|
|
87
|
-
accept="image/jpeg, image/png, video/mp4"
|
|
88
108
|
ref={fileInputRef}
|
|
89
109
|
/>
|
|
90
110
|
<IconContainer>
|
|
91
111
|
<UploadIcon />
|
|
92
112
|
</IconContainer>
|
|
93
113
|
<TextContainer>
|
|
94
|
-
<Text1>or drag and drop your
|
|
95
|
-
<Text2>Photos (JPEG, PNG)
|
|
114
|
+
<Text1>or drag and drop your files</Text1>
|
|
115
|
+
<Text2>Photos (JPEG, PNG) Only</Text2>
|
|
96
116
|
</TextContainer>
|
|
97
117
|
</Container>
|
|
98
118
|
</DraggerContainer>
|
|
99
119
|
|
|
100
|
-
{/* Uploaded Files List */}
|
|
101
120
|
{uploadedFiles.length > 0 && (
|
|
102
121
|
<UploadedFilesContainer>
|
|
103
122
|
<FilesTitle>Uploaded Files:</FilesTitle>
|
|
104
123
|
<FilesList>
|
|
105
|
-
{uploadedFiles
|
|
106
|
-
<FileItem key={index}>
|
|
124
|
+
{uploadedFiles?.map((file, index) => (
|
|
125
|
+
<FileItem key={`${file.name}-${index}`}>
|
|
107
126
|
{file.name} - {(file.size / 1024).toFixed(2)} KB
|
|
127
|
+
<CrossIcon
|
|
128
|
+
style={{ cursor: 'pointer', marginLeft: 8 }}
|
|
129
|
+
onClick={() => handleRemoveFile(index)}
|
|
130
|
+
/>
|
|
108
131
|
</FileItem>
|
|
109
132
|
))}
|
|
110
133
|
</FilesList>
|
|
@@ -129,30 +152,24 @@ const DraggerContainer = styled.div<{ dragging: boolean }>`
|
|
|
129
152
|
cursor: pointer;
|
|
130
153
|
`;
|
|
131
154
|
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
text-transform: lowercase;
|
|
140
|
-
padding: 0;
|
|
141
|
-
margin: 0;
|
|
155
|
+
const Container = styled.div`
|
|
156
|
+
display: flex;
|
|
157
|
+
gap: 8px;
|
|
158
|
+
padding: 6px;
|
|
159
|
+
align-items: center;
|
|
160
|
+
border-radius: 30px;
|
|
161
|
+
background: #fff;
|
|
142
162
|
`;
|
|
143
163
|
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
const Text1 = styled.p`
|
|
147
|
-
color: #aea9a1;
|
|
148
|
-
text-align: left;
|
|
149
|
-
font-family: 'Roboto', sans-serif;
|
|
164
|
+
const UploadButton = styled(Button)`
|
|
150
165
|
font-size: 14px;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
166
|
+
padding: 7px 20px;
|
|
167
|
+
height: auto;
|
|
168
|
+
border-radius: 20px;
|
|
169
|
+
`;
|
|
170
|
+
|
|
171
|
+
const FileInput = styled.input`
|
|
172
|
+
display: none;
|
|
156
173
|
`;
|
|
157
174
|
|
|
158
175
|
const IconContainer = styled.div`
|
|
@@ -162,24 +179,22 @@ const IconContainer = styled.div`
|
|
|
162
179
|
align-items: center;
|
|
163
180
|
`;
|
|
164
181
|
|
|
165
|
-
const
|
|
166
|
-
height: 16px;
|
|
167
|
-
font-size: 14px;
|
|
168
|
-
padding: 7px 20px;
|
|
169
|
-
`;
|
|
182
|
+
const TextContainer = styled.div``;
|
|
170
183
|
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
border-radius: 30px;
|
|
178
|
-
background: #fff;
|
|
184
|
+
const Text1 = styled.p`
|
|
185
|
+
color: #aea9a1;
|
|
186
|
+
font-family: 'Roboto', sans-serif;
|
|
187
|
+
font-size: 14px;
|
|
188
|
+
font-weight: 500;
|
|
189
|
+
margin: 0;
|
|
179
190
|
`;
|
|
180
191
|
|
|
181
|
-
const
|
|
182
|
-
|
|
192
|
+
const Text2 = styled.p`
|
|
193
|
+
color: #bcbab7;
|
|
194
|
+
font-family: 'Roboto', sans-serif;
|
|
195
|
+
font-size: 13px;
|
|
196
|
+
font-weight: 400;
|
|
197
|
+
margin: 0;
|
|
183
198
|
`;
|
|
184
199
|
|
|
185
200
|
const UploadedFilesContainer = styled.div`
|
|
@@ -195,6 +210,8 @@ const FilesTitle = styled.h4`
|
|
|
195
210
|
`;
|
|
196
211
|
|
|
197
212
|
const FilesList = styled.ul`
|
|
213
|
+
overflow: auto;
|
|
214
|
+
max-height: 200px;
|
|
198
215
|
list-style-type: none;
|
|
199
216
|
padding: 0;
|
|
200
217
|
`;
|
|
@@ -204,6 +221,9 @@ const FileItem = styled.li`
|
|
|
204
221
|
font-size: 14px;
|
|
205
222
|
color: #333;
|
|
206
223
|
margin: 5px 0;
|
|
224
|
+
display: flex;
|
|
225
|
+
justify-content: space-between;
|
|
226
|
+
align-items: center;
|
|
207
227
|
`;
|
|
208
228
|
|
|
209
229
|
export default DocFileUpload;
|
|
@@ -66,38 +66,55 @@ function AddResources() {
|
|
|
66
66
|
setSelectedType(selectedOption.value);
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
const handleSubmit = async () => {
|
|
71
|
-
if (!uploadedFiles) {
|
|
71
|
+
if (!uploadedFiles || uploadedFiles.length === 0) {
|
|
72
72
|
notification.error({ message: 'No files selected' });
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const formData = new FormData();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
});
|
|
81
|
-
}
|
|
77
|
+
uploadedFiles.forEach(file => {
|
|
78
|
+
formData.append('files', file); // Adjust key as per API
|
|
79
|
+
});
|
|
82
80
|
|
|
83
81
|
try {
|
|
84
|
-
|
|
82
|
+
const response = (await callResourcesAPI({
|
|
85
83
|
payload: formData,
|
|
86
84
|
})) as {
|
|
87
85
|
code: number | null;
|
|
88
86
|
error?: string | null | undefined;
|
|
89
87
|
[key: string]: any;
|
|
90
88
|
};
|
|
89
|
+
|
|
91
90
|
console.log('Upload successful:', response);
|
|
92
91
|
notification.success({ message: 'Files uploaded successfully' });
|
|
93
|
-
|
|
92
|
+
|
|
93
|
+
onClose(); // Close modal
|
|
94
94
|
setResources(false);
|
|
95
95
|
|
|
96
96
|
setTimeout(() => {
|
|
97
97
|
setResources(true);
|
|
98
98
|
}, 1000);
|
|
99
99
|
} catch (error) {
|
|
100
|
-
|
|
100
|
+
const err = error as any;
|
|
101
|
+
const status = err?.response?.status;
|
|
102
|
+
const rawError = err?.response?.data?.error || '';
|
|
103
|
+
|
|
104
|
+
let errMsg = 'An unexpected error occurred.';
|
|
105
|
+
|
|
106
|
+
if (status === 413) {
|
|
107
|
+
errMsg = 'File is too large. Please upload a smaller file.';
|
|
108
|
+
} else if (rawError.includes('413')) {
|
|
109
|
+
errMsg = 'File size exceeds the allowed limit.';
|
|
110
|
+
} else if (err?.message) {
|
|
111
|
+
errMsg = err.message;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
notification.error({
|
|
115
|
+
message: 'Upload Failed',
|
|
116
|
+
description: errMsg,
|
|
117
|
+
});
|
|
101
118
|
}
|
|
102
119
|
};
|
|
103
120
|
|