@movalib/movalib-commons 1.60.0 → 1.62.0
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/src/MovaLogin.d.ts +2 -2
- package/dist/src/MovaLogin.js +22 -18
- package/dist/src/helpers/Tools.d.ts +4 -3
- package/dist/src/helpers/Tools.js +120 -50
- package/dist/src/helpers/Validator.js +3 -2
- package/package.json +1 -1
- package/src/components/QrCodePLVContainer/QrCodePLVContainer.tsx +135 -103
- package/src/helpers/Enums.ts +8 -0
- package/src/helpers/Tools.ts +214 -124
- package/src/helpers/Validator.ts +28 -26
- package/src/models/Document.ts +17 -2
- package/src/models/Event.ts +65 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DocumentScanner, QrCode2 } from
|
|
1
|
+
import { DocumentScanner, QrCode2 } from "@mui/icons-material";
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
4
|
Button,
|
|
@@ -11,48 +11,48 @@ import {
|
|
|
11
11
|
type SelectProps,
|
|
12
12
|
darken,
|
|
13
13
|
useTheme,
|
|
14
|
-
} from
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
import html2canvas from
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import
|
|
23
|
-
import {
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
26
|
-
import
|
|
27
|
-
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
|
14
|
+
} from "@mui/material";
|
|
15
|
+
import "../../style/QRCode.css";
|
|
16
|
+
|
|
17
|
+
import html2canvas from "html2canvas";
|
|
18
|
+
import { PDFDocument } from "pdf-lib";
|
|
19
|
+
import * as pdfjsLib from "pdfjs-dist";
|
|
20
|
+
import QRCodeStyling, { type Options } from "qr-code-styling";
|
|
21
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
22
|
+
import { useReactToPrint } from "react-to-print";
|
|
23
|
+
import { DownloadedQRCode } from "../../DownloadedQRCode";
|
|
24
|
+
import QRCodeImage from "../../assets/images/leaf_yellow_small.png";
|
|
25
|
+
import { flexCenter } from "../../helpers/Tools";
|
|
26
|
+
import { PLVComponentV2, PrintSize } from "./PLVComponent";
|
|
27
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = "/pdf.worker.min.mjs";
|
|
28
28
|
export const getPdfDocument = (url: string) => {
|
|
29
29
|
return pdfjsLib.getDocument(url);
|
|
30
30
|
};
|
|
31
|
-
type SelectChoice = null |
|
|
31
|
+
type SelectChoice = null | "A3" | "A4" | "QR_Headless" | "QR_Google";
|
|
32
32
|
export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
33
33
|
const [selectedChoice, setSelectedChoice] = useState<SelectChoice>(null);
|
|
34
|
-
const [urlA4, setUrlA4] = useState<string>(
|
|
35
|
-
const [urlA3, setUrlA3] = useState<string>(
|
|
34
|
+
const [urlA4, setUrlA4] = useState<string>("");
|
|
35
|
+
const [urlA3, setUrlA3] = useState<string>("");
|
|
36
36
|
const [isReady, setIsReady] = useState(false);
|
|
37
37
|
|
|
38
38
|
const qrCodeRef = useRef<HTMLDivElement>(null);
|
|
39
39
|
const theme = useTheme();
|
|
40
40
|
const PLVrefA4 = useRef<PLVComponentV2>(null);
|
|
41
41
|
const PLVrefA3 = useRef<PLVComponentV2>(null);
|
|
42
|
-
//si sur l'impression des PLV en A4 ou A3 le Qrcode est flou,
|
|
42
|
+
//si sur l'impression des PLV en A4 ou A3 le Qrcode est flou,
|
|
43
43
|
//il faut modifier la width et height, imageSize du qrCodeOptions et mettre les mêmes valeurs que dans le optionQrcode de la fonction printPLV
|
|
44
44
|
const qrCodeOptions: Options = useMemo(
|
|
45
45
|
() => ({
|
|
46
46
|
width: 300,
|
|
47
47
|
height: 300,
|
|
48
|
-
type:
|
|
48
|
+
type: "canvas",
|
|
49
49
|
data: data,
|
|
50
50
|
image: QRCodeImage,
|
|
51
51
|
margin: 10,
|
|
52
52
|
qrOptions: {
|
|
53
53
|
typeNumber: 0,
|
|
54
|
-
mode:
|
|
55
|
-
errorCorrectionLevel:
|
|
54
|
+
mode: "Byte",
|
|
55
|
+
errorCorrectionLevel: "Q",
|
|
56
56
|
},
|
|
57
57
|
imageOptions: {
|
|
58
58
|
hideBackgroundDots: true,
|
|
@@ -61,24 +61,27 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
61
61
|
},
|
|
62
62
|
dotsOptions: {
|
|
63
63
|
color: darken(theme.palette.primary.main, 0.4),
|
|
64
|
-
type:
|
|
64
|
+
type: "square",
|
|
65
65
|
},
|
|
66
66
|
backgroundOptions: {
|
|
67
|
-
color:
|
|
67
|
+
color: "white",
|
|
68
68
|
},
|
|
69
69
|
cornersSquareOptions: {
|
|
70
70
|
color: darken(theme.palette.secondary.main, 0.2),
|
|
71
|
-
type:
|
|
71
|
+
type: "square",
|
|
72
72
|
},
|
|
73
73
|
cornersDotOptions: {
|
|
74
74
|
color: darken(theme.palette.secondary.main, 0.2),
|
|
75
|
-
type:
|
|
75
|
+
type: "square",
|
|
76
76
|
},
|
|
77
77
|
}),
|
|
78
|
-
[data, theme.palette]
|
|
78
|
+
[data, theme.palette]
|
|
79
79
|
);
|
|
80
80
|
|
|
81
|
-
const qrCode = useMemo(
|
|
81
|
+
const qrCode = useMemo(
|
|
82
|
+
() => new QRCodeStyling(qrCodeOptions),
|
|
83
|
+
[qrCodeOptions]
|
|
84
|
+
);
|
|
82
85
|
|
|
83
86
|
useEffect(() => {
|
|
84
87
|
if (qrCodeRef.current) {
|
|
@@ -87,18 +90,16 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
87
90
|
}, [qrCode]);
|
|
88
91
|
|
|
89
92
|
useEffect(() => {
|
|
90
|
-
const urlA4 = printPLV(
|
|
93
|
+
const urlA4 = printPLV("A4").then((url) => {
|
|
91
94
|
setUrlA4(url);
|
|
92
95
|
});
|
|
93
96
|
}, [data]);
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
|
|
97
98
|
async function printPLV(format: string) {
|
|
98
99
|
setIsReady(false);
|
|
99
100
|
|
|
100
101
|
// Chemin du fichier PDF
|
|
101
|
-
|
|
102
|
+
const pdfUrl = `/Movalib_${format}.pdf`;
|
|
102
103
|
// Récupérer le fichier PDF depuis le serveur
|
|
103
104
|
const response = await fetch(pdfUrl);
|
|
104
105
|
const existingPdfBytes = await response.arrayBuffer();
|
|
@@ -118,20 +119,20 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
118
119
|
const { width, height } = firstPage.getSize();
|
|
119
120
|
|
|
120
121
|
let optionQrcode = {};
|
|
121
|
-
if(format ===
|
|
122
|
+
if (format === "A3") {
|
|
122
123
|
optionQrcode = {
|
|
123
|
-
x: width - 427,
|
|
124
|
+
x: width - 427,
|
|
124
125
|
y: 88,
|
|
125
126
|
width: 349,
|
|
126
|
-
height: 349
|
|
127
|
-
}
|
|
127
|
+
height: 349,
|
|
128
|
+
};
|
|
128
129
|
} else {
|
|
129
130
|
optionQrcode = {
|
|
130
131
|
x: width - 303,
|
|
131
132
|
y: 54,
|
|
132
133
|
width: 245,
|
|
133
134
|
height: 245,
|
|
134
|
-
}
|
|
135
|
+
};
|
|
135
136
|
}
|
|
136
137
|
// AJouter le QR code à la première page du PDF
|
|
137
138
|
firstPage.drawImage(qrImage, optionQrcode);
|
|
@@ -140,7 +141,7 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
140
141
|
const modifiedPdfBytes = await pdfDoc.save();
|
|
141
142
|
|
|
142
143
|
// Convertir les bytes en Blob puis en URL
|
|
143
|
-
const blob = new Blob([modifiedPdfBytes], { type:
|
|
144
|
+
const blob = new Blob([modifiedPdfBytes], { type: "application/pdf" });
|
|
144
145
|
const url = URL.createObjectURL(blob);
|
|
145
146
|
|
|
146
147
|
// étape nécesssaire pour utiliser reactToPrint pour pouvoir nommer le document
|
|
@@ -148,49 +149,51 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
148
149
|
// donc il faut convertir le PDF en image
|
|
149
150
|
// puis convertir l'image en URL
|
|
150
151
|
// et enfin integrer l'image dans le HTML via la balise <img>
|
|
151
|
-
|
|
152
152
|
|
|
153
153
|
// Convertir le PDF en image
|
|
154
154
|
const loadingTask = getPdfDocument(url);
|
|
155
155
|
const pdf = await loadingTask.promise;
|
|
156
|
-
|
|
156
|
+
|
|
157
157
|
// Récupérer la première page
|
|
158
158
|
const page = await pdf.getPage(1);
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
// Créer un canvas pour afficher la page
|
|
161
|
-
const canvas = document.createElement(
|
|
162
|
-
const context = canvas.getContext(
|
|
163
|
-
|
|
164
|
-
const viewport = page.getViewport({ scale: 3});
|
|
161
|
+
const canvas = document.createElement("canvas");
|
|
162
|
+
const context = canvas.getContext("2d");
|
|
163
|
+
|
|
164
|
+
const viewport = page.getViewport({ scale: 3 });
|
|
165
165
|
canvas.width = viewport.width;
|
|
166
166
|
canvas.height = viewport.height;
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
// Rendu de la page dans le canvas
|
|
169
169
|
const renderContext = {
|
|
170
170
|
canvasContext: context!,
|
|
171
171
|
viewport: viewport,
|
|
172
172
|
};
|
|
173
173
|
await page.render(renderContext).promise;
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
// Convertir le canvas en URL d'image (data URL)
|
|
176
|
-
const imageUrl = canvas.toDataURL(
|
|
176
|
+
const imageUrl = canvas.toDataURL("image/png");
|
|
177
177
|
setIsReady(true);
|
|
178
178
|
return imageUrl;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
const downloadQRCodeHeadless = useCallback(() => {
|
|
182
182
|
qrCode.download({
|
|
183
|
-
extension:
|
|
184
|
-
name:
|
|
183
|
+
extension: "png",
|
|
184
|
+
name: "movalib-qr-code",
|
|
185
185
|
});
|
|
186
186
|
}, [qrCode.download]);
|
|
187
187
|
|
|
188
188
|
const downloadQrCodeWithCTA = useCallback(() => {
|
|
189
189
|
// Check if we have everything we need
|
|
190
|
-
const qrCodeContainer =
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
const
|
|
190
|
+
const qrCodeContainer =
|
|
191
|
+
document.querySelector<HTMLElement>("#qr-code-container");
|
|
192
|
+
const qrCodeDiv = qrCodeContainer?.querySelector<HTMLElement>(".qr-code");
|
|
193
|
+
const qrCodeCanva = qrCodeDiv?.querySelector("canvas");
|
|
194
|
+
const downloadedDiv = document.getElementById(
|
|
195
|
+
"qr-code-downloaded-container"
|
|
196
|
+
);
|
|
194
197
|
|
|
195
198
|
// If we don't have the QR Code, we can't download it
|
|
196
199
|
if (!(qrCodeContainer && qrCodeDiv && qrCodeCanva && downloadedDiv)) {
|
|
@@ -198,9 +201,11 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
198
201
|
}
|
|
199
202
|
|
|
200
203
|
const tmpRendered = downloadedDiv.cloneNode(true) as HTMLElement;
|
|
201
|
-
tmpRendered.style.display =
|
|
204
|
+
tmpRendered.style.display = "flex";
|
|
202
205
|
|
|
203
|
-
const downloadedQrCodeImgContainer = tmpRendered.querySelector<HTMLElement>(
|
|
206
|
+
const downloadedQrCodeImgContainer = tmpRendered.querySelector<HTMLElement>(
|
|
207
|
+
"#qr-code-img-container"
|
|
208
|
+
)!;
|
|
204
209
|
|
|
205
210
|
downloadedQrCodeImgContainer.append(qrCodeCanva);
|
|
206
211
|
// add it to the document to be able to download it
|
|
@@ -208,9 +213,9 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
208
213
|
|
|
209
214
|
// create the canva of the tmpRendered div and download it
|
|
210
215
|
html2canvas(tmpRendered).then((canvas) => {
|
|
211
|
-
const a = document.createElement(
|
|
212
|
-
a.download =
|
|
213
|
-
a.href = canvas.toDataURL(
|
|
216
|
+
const a = document.createElement("a");
|
|
217
|
+
a.download = "movalib-qr-code.png";
|
|
218
|
+
a.href = canvas.toDataURL("image/png");
|
|
214
219
|
a.click();
|
|
215
220
|
});
|
|
216
221
|
|
|
@@ -221,89 +226,116 @@ export const QrCodePLVContainer = ({ data }: { data: string }) => {
|
|
|
221
226
|
qrCode.append(qrCodeRef.current!);
|
|
222
227
|
}, [qrCode.append]);
|
|
223
228
|
|
|
224
|
-
const onChangeSelectedChoice: SelectProps<SelectChoice>[
|
|
225
|
-
if(e.target.value ===
|
|
226
|
-
printPLV(
|
|
229
|
+
const onChangeSelectedChoice: SelectProps<SelectChoice>["onChange"] = (e) => {
|
|
230
|
+
if (e.target.value === "A3" && !urlA3) {
|
|
231
|
+
printPLV("A3").then((url) => {
|
|
227
232
|
setUrlA3(url);
|
|
228
233
|
});
|
|
229
234
|
}
|
|
230
235
|
setSelectedChoice(e.target.value as SelectChoice);
|
|
231
236
|
};
|
|
232
|
-
|
|
237
|
+
|
|
233
238
|
const printA3PLV = useReactToPrint({
|
|
234
239
|
content: () => PLVrefA3.current,
|
|
235
|
-
documentTitle:
|
|
240
|
+
documentTitle: "Movalib_PLV_A3",
|
|
236
241
|
});
|
|
237
242
|
|
|
238
243
|
const printA4PLV = useReactToPrint({
|
|
239
244
|
content: () => PLVrefA4.current,
|
|
240
|
-
documentTitle:
|
|
245
|
+
documentTitle: "Movalib_PLV_A4",
|
|
241
246
|
});
|
|
242
247
|
|
|
243
248
|
const onClickDownload = useMemo(() => {
|
|
244
249
|
switch (selectedChoice) {
|
|
245
|
-
case
|
|
250
|
+
case "A3":
|
|
246
251
|
return printA3PLV;
|
|
247
|
-
case
|
|
252
|
+
case "A4":
|
|
248
253
|
return printA4PLV;
|
|
249
|
-
case
|
|
254
|
+
case "QR_Headless":
|
|
250
255
|
return downloadQRCodeHeadless;
|
|
251
|
-
case
|
|
256
|
+
case "QR_Google":
|
|
252
257
|
return downloadQrCodeWithCTA;
|
|
253
258
|
default:
|
|
254
259
|
return () => {};
|
|
255
260
|
}
|
|
256
|
-
}, [
|
|
261
|
+
}, [
|
|
262
|
+
selectedChoice,
|
|
263
|
+
downloadQRCodeHeadless,
|
|
264
|
+
downloadQrCodeWithCTA,
|
|
265
|
+
printA3PLV,
|
|
266
|
+
printA4PLV,
|
|
267
|
+
]);
|
|
257
268
|
return (
|
|
258
|
-
<Box display=
|
|
259
|
-
{urlA4 &&
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
269
|
+
<Box display="flex" flexDirection="column" alignItems="center" gap="24px">
|
|
270
|
+
{urlA4 && (
|
|
271
|
+
<PLVComponentV2 ref={PLVrefA4} url={urlA4} printSize={PrintSize.A4} />
|
|
272
|
+
)}
|
|
273
|
+
{urlA3 && (
|
|
274
|
+
<PLVComponentV2 ref={PLVrefA3} url={urlA3} printSize={PrintSize.A3} />
|
|
275
|
+
)}
|
|
276
|
+
|
|
277
|
+
<Grid container justifyContent="center" alignItems="center">
|
|
263
278
|
<Grid item xs={7}>
|
|
264
|
-
<FormControl fullWidth size=
|
|
265
|
-
<InputLabel id=
|
|
279
|
+
<FormControl fullWidth size="small">
|
|
280
|
+
<InputLabel id="qrcode-plv-select">
|
|
281
|
+
Choisissez votre support
|
|
282
|
+
</InputLabel>
|
|
266
283
|
<Select
|
|
267
|
-
labelId=
|
|
268
|
-
label=
|
|
269
|
-
id=
|
|
284
|
+
labelId="qrcode-plv-select"
|
|
285
|
+
label="Choisissez votre support"
|
|
286
|
+
id="qrcode-plv-select"
|
|
270
287
|
onChange={onChangeSelectedChoice}
|
|
271
288
|
value={selectedChoice}
|
|
272
289
|
>
|
|
273
|
-
<MenuItem value={
|
|
274
|
-
<MenuItem value={
|
|
275
|
-
<MenuItem value={
|
|
276
|
-
|
|
290
|
+
<MenuItem value={"A4"}>🧾 PLV format A4</MenuItem>
|
|
291
|
+
<MenuItem value={"A3"}>🧾 PLV format A3</MenuItem>
|
|
292
|
+
<MenuItem value={"QR_Google"}>
|
|
293
|
+
QR Code format GoogleMyBusiness
|
|
294
|
+
</MenuItem>
|
|
295
|
+
<MenuItem value={"QR_Headless"}>QR Code seul</MenuItem>
|
|
277
296
|
</Select>
|
|
278
297
|
</FormControl>
|
|
279
298
|
</Grid>
|
|
280
299
|
<Grid item xs={4} marginLeft={3}>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
300
|
+
{(selectedChoice === "A3" || selectedChoice === "A4") && !isReady ? (
|
|
301
|
+
<CircularProgress />
|
|
302
|
+
) : (
|
|
303
|
+
<Button
|
|
304
|
+
startIcon={
|
|
305
|
+
selectedChoice === "A3" || selectedChoice === "A4" ? (
|
|
306
|
+
<DocumentScanner />
|
|
307
|
+
) : (
|
|
308
|
+
<QrCode2 />
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
onClick={onClickDownload}
|
|
312
|
+
variant="outlined"
|
|
313
|
+
disabled={
|
|
314
|
+
!selectedChoice ||
|
|
315
|
+
((selectedChoice === "A3" || selectedChoice === "A4") &&
|
|
316
|
+
!isReady)
|
|
317
|
+
}
|
|
318
|
+
sx={{
|
|
319
|
+
color: darken(theme.palette.primary.main, 0.2),
|
|
320
|
+
borderRadius: "10rem",
|
|
321
|
+
}}
|
|
322
|
+
>
|
|
323
|
+
{selectedChoice === "A3" || selectedChoice === "A4"
|
|
324
|
+
? "Imprimer"
|
|
325
|
+
: "Télécharger"}
|
|
293
326
|
</Button>
|
|
294
|
-
|
|
295
|
-
|
|
327
|
+
)}
|
|
296
328
|
</Grid>
|
|
297
329
|
</Grid>
|
|
298
|
-
<div id=
|
|
330
|
+
<div id="qr-code-container" style={flexCenter}>
|
|
299
331
|
<div
|
|
300
332
|
ref={qrCodeRef}
|
|
301
333
|
style={{
|
|
302
|
-
height:
|
|
303
|
-
width:
|
|
304
|
-
maxWidth:
|
|
334
|
+
height: "300px",
|
|
335
|
+
width: "300px",
|
|
336
|
+
maxWidth: "300px !important",
|
|
305
337
|
}}
|
|
306
|
-
className=
|
|
338
|
+
className="qr-code"
|
|
307
339
|
/>
|
|
308
340
|
</div>
|
|
309
341
|
<DownloadedQRCode />
|
package/src/helpers/Enums.ts
CHANGED
|
@@ -213,6 +213,7 @@ export enum EventType {
|
|
|
213
213
|
NOTE = "NOTE",
|
|
214
214
|
PENDING_APPOINTMENT = "PENDING_APPOINTMENT",
|
|
215
215
|
WAITING_VEHICLE = "WAITING_VEHICLE",
|
|
216
|
+
QUOTE = "QUOTE",
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
export enum DayOfWeek {
|
|
@@ -231,6 +232,13 @@ export enum DocumentState {
|
|
|
231
232
|
REJECTED = "REJECTED",
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
export enum QuoteState {
|
|
236
|
+
QUOTE_DRAFT = "QUOTE_DRAFT",
|
|
237
|
+
QUOTE_SENT = "QUOTE_SENT",
|
|
238
|
+
QUOTE_ACCEPTED = "QUOTE_ACCEPTED",
|
|
239
|
+
QUOTE_REJECTED = "QUOTE_REJECTED",
|
|
240
|
+
}
|
|
241
|
+
|
|
234
242
|
export enum DocumentType {
|
|
235
243
|
USER_BANK_DETAILS = "USER_BANK_DETAILS",
|
|
236
244
|
USER_APPOINTMENT_QUOTE = "USER_APPOINTMENT_QUOTE",
|