@movalib/movalib-commons 1.60.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@movalib/movalib-commons",
3
- "version": "1.60.1",
3
+ "version": "1.62.0",
4
4
  "description": "Bibliothèque d'objets communs à l'ensemble des projets React de Movalib",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,4 +1,4 @@
1
- import { DocumentScanner, QrCode2 } from '@mui/icons-material';
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 '@mui/material';
15
- import '../../style/QRCode.css';
16
-
17
- import html2canvas from 'html2canvas';
18
- import QRCodeStyling, { type Options } from 'qr-code-styling';
19
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
20
- import { useReactToPrint } from 'react-to-print';
21
- import { DownloadedQRCode } from '../../DownloadedQRCode';
22
- import QRCodeImage from '../../assets/images/leaf_yellow_small.png';
23
- import { flexCenter } from '../../helpers/Tools';
24
- import { PDFDocument } from 'pdf-lib';
25
- import { PLVComponentV2, PrintSize } from './PLVComponent';
26
- import * as pdfjsLib from 'pdfjs-dist';
27
- pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs';
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 | 'A3' | 'A4' | 'QR_Headless' | 'QR_Google';
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: 'canvas',
48
+ type: "canvas",
49
49
  data: data,
50
50
  image: QRCodeImage,
51
51
  margin: 10,
52
52
  qrOptions: {
53
53
  typeNumber: 0,
54
- mode: 'Byte',
55
- errorCorrectionLevel: 'Q',
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: 'square',
64
+ type: "square",
65
65
  },
66
66
  backgroundOptions: {
67
- color: 'white',
67
+ color: "white",
68
68
  },
69
69
  cornersSquareOptions: {
70
70
  color: darken(theme.palette.secondary.main, 0.2),
71
- type: 'square',
71
+ type: "square",
72
72
  },
73
73
  cornersDotOptions: {
74
74
  color: darken(theme.palette.secondary.main, 0.2),
75
- type: 'square',
75
+ type: "square",
76
76
  },
77
77
  }),
78
- [data, theme.palette],
78
+ [data, theme.palette]
79
79
  );
80
80
 
81
- const qrCode = useMemo(() => new QRCodeStyling(qrCodeOptions), [qrCodeOptions]);
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('A4').then((url) => {
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
- const pdfUrl = `/Movalib_${format}.pdf`;
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 === 'A3'){
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: 'application/pdf' });
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('canvas');
162
- const context = canvas.getContext('2d');
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('image/png');
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: 'png',
184
- name: 'movalib-qr-code',
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 = document.querySelector<HTMLElement>('#qr-code-container');
191
- const qrCodeDiv = qrCodeContainer?.querySelector<HTMLElement>('.qr-code');
192
- const qrCodeCanva = qrCodeDiv?.querySelector('canvas');
193
- const downloadedDiv = document.getElementById('qr-code-downloaded-container');
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 = 'flex';
204
+ tmpRendered.style.display = "flex";
202
205
 
203
- const downloadedQrCodeImgContainer = tmpRendered.querySelector<HTMLElement>('#qr-code-img-container')!;
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('a');
212
- a.download = 'movalib-qr-code.png';
213
- a.href = canvas.toDataURL('image/png');
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>['onChange'] = (e) => {
225
- if(e.target.value === 'A3' && !urlA3){
226
- printPLV('A3').then((url) => {
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: 'Movalib_PLV_A3',
240
+ documentTitle: "Movalib_PLV_A3",
236
241
  });
237
242
 
238
243
  const printA4PLV = useReactToPrint({
239
244
  content: () => PLVrefA4.current,
240
- documentTitle: 'Movalib_PLV_A4',
245
+ documentTitle: "Movalib_PLV_A4",
241
246
  });
242
247
 
243
248
  const onClickDownload = useMemo(() => {
244
249
  switch (selectedChoice) {
245
- case 'A3':
250
+ case "A3":
246
251
  return printA3PLV;
247
- case 'A4':
252
+ case "A4":
248
253
  return printA4PLV;
249
- case 'QR_Headless':
254
+ case "QR_Headless":
250
255
  return downloadQRCodeHeadless;
251
- case 'QR_Google':
256
+ case "QR_Google":
252
257
  return downloadQrCodeWithCTA;
253
258
  default:
254
259
  return () => {};
255
260
  }
256
- }, [selectedChoice, downloadQRCodeHeadless, downloadQrCodeWithCTA, printA3PLV, printA4PLV]);
261
+ }, [
262
+ selectedChoice,
263
+ downloadQRCodeHeadless,
264
+ downloadQrCodeWithCTA,
265
+ printA3PLV,
266
+ printA4PLV,
267
+ ]);
257
268
  return (
258
- <Box display='flex' flexDirection='column' alignItems='center' gap='24px'>
259
- {urlA4 && <PLVComponentV2 ref={PLVrefA4} url={urlA4} printSize={PrintSize.A4} />}
260
- {urlA3 && <PLVComponentV2 ref={PLVrefA3} url={urlA3} printSize={PrintSize.A3} />}
261
-
262
- <Grid container justifyContent='center' alignItems='center'>
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='small'>
265
- <InputLabel id='qrcode-plv-select'>Choisissez votre support</InputLabel>
279
+ <FormControl fullWidth size="small">
280
+ <InputLabel id="qrcode-plv-select">
281
+ Choisissez votre support
282
+ </InputLabel>
266
283
  <Select
267
- labelId='qrcode-plv-select'
268
- label='Choisissez votre support'
269
- id='qrcode-plv-select'
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={'A4'}>🧾&nbsp;&nbsp;PLV format A4</MenuItem>
274
- <MenuItem value={'A3'}>🧾&nbsp;&nbsp;PLV format A3</MenuItem>
275
- <MenuItem value={'QR_Google'}>QR Code format GoogleMyBusiness</MenuItem>
276
- <MenuItem value={'QR_Headless'}>QR Code seul</MenuItem>
290
+ <MenuItem value={"A4"}>🧾&nbsp;&nbsp;PLV format A4</MenuItem>
291
+ <MenuItem value={"A3"}>🧾&nbsp;&nbsp;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
- {(selectedChoice === 'A3' || selectedChoice === 'A4') && !isReady ? (
283
- <CircularProgress />
284
- ) : (
285
- <Button
286
- startIcon={selectedChoice === 'A3' || selectedChoice === 'A4' ? <DocumentScanner /> : <QrCode2 />}
287
- onClick={onClickDownload}
288
- variant='outlined'
289
- disabled={!selectedChoice || ((selectedChoice === 'A3' || selectedChoice === 'A4') && !isReady)}
290
- sx={{ color: darken(theme.palette.primary.main, 0.2), borderRadius: '10rem' }}
291
- >
292
- {selectedChoice === 'A3' || selectedChoice === 'A4' ? 'Imprimer' : 'Télécharger'}
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='qr-code-container' style={flexCenter}>
330
+ <div id="qr-code-container" style={flexCenter}>
299
331
  <div
300
332
  ref={qrCodeRef}
301
333
  style={{
302
- height: '300px',
303
- width: '300px',
304
- maxWidth: '300px !important',
334
+ height: "300px",
335
+ width: "300px",
336
+ maxWidth: "300px !important",
305
337
  }}
306
- className='qr-code'
338
+ className="qr-code"
307
339
  />
308
340
  </div>
309
341
  <DownloadedQRCode />
@@ -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",
@@ -15,7 +15,10 @@ export default class Document {
15
15
  reference?: string;
16
16
  rejectReason?: string;
17
17
  validateToken?: string;
18
-
18
+ remindersCount?: number;
19
+ totalAmountInclVat?: number;
20
+ lastSendingTime?: Date;
21
+ firstSendingTime?: Date;
19
22
  constructor(
20
23
  id: string,
21
24
  ownerId: number,
@@ -28,7 +31,11 @@ export default class Document {
28
31
  creationDate?: Date,
29
32
  updateDate?: Date,
30
33
  reference?: string,
31
- validateToken?: string
34
+ validateToken?: string,
35
+ remindersCount?: number,
36
+ totalAmountInclVat?: number,
37
+ lastSendingTime?: Date,
38
+ firstSendingTime?: Date
32
39
  ) {
33
40
  this.id = id;
34
41
  this.state = state;
@@ -42,6 +49,14 @@ export default class Document {
42
49
  this.updateDate = updateDate;
43
50
  this.reference = reference;
44
51
  this.validateToken = validateToken;
52
+ this.remindersCount = remindersCount;
53
+ this.totalAmountInclVat = totalAmountInclVat;
54
+ this.lastSendingTime = lastSendingTime
55
+ ? new Date(lastSendingTime)
56
+ : undefined;
57
+ this.firstSendingTime = firstSendingTime
58
+ ? new Date(firstSendingTime)
59
+ : undefined;
45
60
  }
46
61
 
47
62
  static findByTypeAndReference(
@@ -1,4 +1,11 @@
1
- import { EventState, EventType, OrderPreference } from "../helpers/Enums";
1
+ import {
2
+ DocumentState,
3
+ DocumentType,
4
+ EventState,
5
+ EventType,
6
+ OrderPreference,
7
+ QuoteState,
8
+ } from "../helpers/Enums";
2
9
  import Address from "./Address";
3
10
  import Customer from "./Customer";
4
11
  import Document from "./Document";
@@ -82,7 +89,10 @@ export default class Event {
82
89
  origin?: string;
83
90
  quoteLastSendingTime?: Date;
84
91
  invoiceSendingDate?: Date;
85
-
92
+ creationDate?: Date;
93
+ updatedDate?: Date;
94
+ quoteFirstSendingTime?: Date;
95
+ lastQuoteCreationDate?: Date;
86
96
  constructor(
87
97
  id: string,
88
98
  ownerId: number,
@@ -111,7 +121,11 @@ export default class Event {
111
121
  interventionEndTime?: Date,
112
122
  quoteLastSendingTime?: Date,
113
123
  invoiceSendingDate?: Date,
114
- orders?: order[]
124
+ orders?: order[],
125
+ creationDate?: Date,
126
+ updatedDate?: Date,
127
+ lastQuoteCreationDate?: Date,
128
+ quoteFirstSendingTime?: Date
115
129
  ) {
116
130
  this.id = id;
117
131
  this.notes = notes;
@@ -149,6 +163,14 @@ export default class Event {
149
163
  ? new Date(invoiceSendingDate)
150
164
  : undefined;
151
165
  this.orders = orders;
166
+ this.creationDate = creationDate ? new Date(creationDate) : undefined;
167
+ this.updatedDate = updatedDate ? new Date(updatedDate) : undefined;
168
+ this.lastQuoteCreationDate = lastQuoteCreationDate
169
+ ? new Date(lastQuoteCreationDate)
170
+ : undefined;
171
+ this.quoteFirstSendingTime = quoteFirstSendingTime
172
+ ? new Date(quoteFirstSendingTime)
173
+ : undefined;
152
174
  }
153
175
 
154
176
  static getPrestationsList(event: Event): string[] {
@@ -158,4 +180,44 @@ export default class Event {
158
180
 
159
181
  return [];
160
182
  }
183
+ static getCurrentQuote(event: Event): Document | null {
184
+ if (event.documents) {
185
+ const quoteDocument = event.documents.filter(
186
+ (doc) => doc.type === DocumentType.USER_APPOINTMENT_QUOTE
187
+ );
188
+ if (event.type === EventType.QUOTE) {
189
+ const state = event.state as unknown as QuoteState;
190
+ if (
191
+ state === QuoteState.QUOTE_DRAFT ||
192
+ state === QuoteState.QUOTE_SENT
193
+ ) {
194
+ return (
195
+ quoteDocument.find((doc) => doc.state === DocumentState.PENDING) ??
196
+ null
197
+ );
198
+ } else if (state === QuoteState.QUOTE_REJECTED) {
199
+ return (
200
+ quoteDocument
201
+ .filter((doc) => doc.state === DocumentState.REJECTED)
202
+ .sort(
203
+ (a, b) =>
204
+ new Date(b.creationDate!).getTime() -
205
+ new Date(a.creationDate!).getTime()
206
+ )[0] ?? null
207
+ );
208
+ } else if (state === QuoteState.QUOTE_ACCEPTED) {
209
+ return (
210
+ quoteDocument.find((doc) => doc.state === DocumentState.APPROVED) ??
211
+ null
212
+ );
213
+ }
214
+ } else {
215
+ return (
216
+ quoteDocument.find((doc) => doc.state === DocumentState.APPROVED) ??
217
+ null
218
+ );
219
+ }
220
+ }
221
+ return null;
222
+ }
161
223
  }