placementt-core 1.20.217 → 11.0.803

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.
Files changed (86) hide show
  1. package/.eslintrc.js +40 -40
  2. package/.gitattributes +2 -2
  3. package/lib/constants.js +10 -1
  4. package/lib/constants.js.map +1 -1
  5. package/lib/features/config.d.ts +133 -133
  6. package/lib/features/config.js +35 -35
  7. package/lib/features/contacts/contacts.d.ts +75 -75
  8. package/lib/features/contacts/contacts.js +105 -105
  9. package/lib/features/downtime/useDowntime.d.ts +11 -11
  10. package/lib/features/downtime/useDowntime.js +22 -22
  11. package/lib/features/placements/studentPlacements/studentPlacementsSlice.d.ts +63 -63
  12. package/lib/features/placements/studentPlacements/studentPlacementsSlice.js +81 -81
  13. package/lib/features/providerPlacements/providerPlacementsSlice.d.ts +19 -19
  14. package/lib/features/providerPlacements/providerPlacementsSlice.js +24 -24
  15. package/lib/features/studentPlacements/studentPlacementsSlice.d.ts +62 -62
  16. package/lib/features/studentPlacements/studentPlacementsSlice.js +87 -87
  17. package/lib/features/studentPlacements/useStudentPlacements.d.ts +6 -6
  18. package/lib/features/studentPlacements/useStudentPlacements.js +18 -18
  19. package/lib/features/userSlice.d.ts +26 -26
  20. package/lib/features/userSlice.js +23 -23
  21. package/lib/features/users/useUserFunctions.d.ts +25 -25
  22. package/lib/features/users/useUserFunctions.js +124 -124
  23. package/lib/features/users/userSlice.d.ts +46 -46
  24. package/lib/features/users/userSlice.js +48 -48
  25. package/lib/firebase/firebase.d.ts +1 -1
  26. package/lib/firebase/firebase.js +6 -2
  27. package/lib/firebase/firebase.js.map +1 -1
  28. package/lib/firebase/readDatabase.js +3 -1
  29. package/lib/firebase/readDatabase.js.map +1 -1
  30. package/lib/hooks.d.ts +33 -5
  31. package/lib/hooks.js +143 -107
  32. package/lib/hooks.js.map +1 -1
  33. package/lib/images/GatsbyBenchmarks.d.ts +1 -2
  34. package/lib/reduxHooks.d.ts +1 -66
  35. package/lib/reduxHooks.js +9 -69
  36. package/lib/reduxHooks.js.map +1 -1
  37. package/lib/tasksAndTips.d.ts +2 -2
  38. package/lib/tasksAndTips.js +37 -6
  39. package/lib/tasksAndTips.js.map +1 -1
  40. package/lib/typeDefinitions.d.ts +50 -5
  41. package/lib/util.d.ts +1 -1
  42. package/lib/util.js +12 -1
  43. package/lib/util.js.map +1 -1
  44. package/package.json +52 -56
  45. package/src/DatabaseDefinitions.ts +18 -18
  46. package/src/apiCalls.ts +128 -128
  47. package/src/config.ts +50 -50
  48. package/src/constants.ts +796 -787
  49. package/src/databaseTypes.ts +42 -42
  50. package/src/features/analytics/useAnalytics.tsx +63 -63
  51. package/src/features/contacts/contactsSlice.ts +147 -147
  52. package/src/features/contacts/useContacts.tsx +73 -73
  53. package/src/features/dropdown/useDropdown.tsx +52 -52
  54. package/src/features/global/downtime/useDowntime.tsx +23 -23
  55. package/src/features/global/users/useUserFunctions.tsx +132 -132
  56. package/src/features/jobs/jobsSlice.ts +71 -71
  57. package/src/features/placements/studentPlacements/activePlacement.ts +68 -68
  58. package/src/features/placements/studentPlacements/completedStudentPlacementsSlice.ts +97 -97
  59. package/src/features/placements/studentPlacements/upcomingStudentPlacementsSlice.ts +108 -108
  60. package/src/features/placements/studentPlacements/useStudentPlacements.tsx +9 -9
  61. package/src/features/placements/types.ts +10 -10
  62. package/src/features/referrals/useReferrals.tsx +56 -56
  63. package/src/features/updates/useUpdates.tsx +38 -38
  64. package/src/firebase/firebase.tsx +149 -145
  65. package/src/firebase/firebaseConfig.tsx +45 -45
  66. package/src/firebase/firebaseQuery.tsx +151 -151
  67. package/src/firebase/persistence.ts +84 -84
  68. package/src/firebase/readDatabase.tsx +236 -235
  69. package/src/firebase/util.tsx +352 -352
  70. package/src/firebase/writeDatabase.tsx +77 -77
  71. package/src/hooks.tsx +4353 -4323
  72. package/src/images/GatsbyBenchmarks.tsx +711 -711
  73. package/src/images/LogFuturePlacement.jsx +64 -64
  74. package/src/images/LogPreviousPlacement.jsx +228 -228
  75. package/src/images/gatsby_benchmarks.svg +466 -466
  76. package/src/images/log_future_placement.svg +114 -114
  77. package/src/images/log_previous_placement.svg +199 -199
  78. package/src/index.ts +34 -34
  79. package/src/readDatabase.tsx +3 -3
  80. package/src/reduxHooks.ts +232 -297
  81. package/src/tasksAndTips.ts +1209 -1177
  82. package/src/tutorialTips.ts +58 -58
  83. package/src/typeDefinitions.ts +1003 -958
  84. package/src/util.ts +160 -150
  85. package/tsconfig.dev.json +5 -5
  86. package/tsconfig.json +21 -22
@@ -1,352 +1,352 @@
1
- import {Timestamp} from "firebase/firestore";
2
- import {Address, ProviderUserPermissions, StaffUserPermissions, UserData} from "../typeDefinitions";
3
- import * as geoHash from "ngeohash";
4
-
5
- export const getProviderId = async () => {/*
6
- let user = await getDoc(doc(db, 'users', auth.currentUser.uid))
7
- return user.data().bi*/
8
- };
9
-
10
- export const getRandomNumber = (min = 0, max:number) => {
11
- return Math.random() * (max - min) + min;
12
- };
13
-
14
- export const getUniqueId = (object:object): number => {
15
- const id = Math.round(getRandomNumber(0, 1000000));
16
-
17
- if (!object) {
18
- return id;
19
- }
20
-
21
- if (Array.isArray(object)) {
22
- return object.some((el) => el.id === id) ? getUniqueId(object) : id;
23
- }
24
-
25
- return (Object.keys(object) as any[]).some((el) => el === id) ? getUniqueId(object) : id;
26
- };
27
-
28
- export const capitalise = (s="") => {
29
- const nS = s.toString().replace("_", " ");
30
- return nS.charAt(0).toUpperCase() + nS.slice(1);
31
- };
32
-
33
- export const capitaliseWords = (s="") => {
34
- return s.replace(/(^|\s)\S/g, (l) => l.toUpperCase());
35
- };
36
-
37
- export const snakeCase = (s="") => {
38
- const nS = s.toString().replace(" ", "_");
39
- return nS.toLowerCase();
40
- };
41
-
42
- export const validateEmail = (email: string) => {
43
- console.log(email);
44
- return email.match(
45
- /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
46
- );
47
- };
48
-
49
- export const getAccess = (user:UserData, ...perms: (keyof StaffUserPermissions | keyof ProviderUserPermissions)[]) => {
50
- // If the user has the permission given, grant access
51
- const finalPerms: {[key: string]: any} = {};
52
- perms.forEach((perm) => {
53
- finalPerms[perm] = (user.userGroup === "admin" || (user.groupData as object)?.[perm] || false);
54
- });
55
- // Otherwise, deny access
56
- return Object.keys(finalPerms).length > 1 ? finalPerms : Object.values(finalPerms)[0];
57
- };
58
-
59
- export const dateToString = (date:Date) => {
60
- const y = date.getFullYear();
61
- const m = ("0"+(date.getMonth() + 1)).slice(-2);
62
- const d = ("0"+(date.getDate())).slice(-2);
63
- return [y, m, d].join("-");
64
- };
65
-
66
- export const getPlacementDateArray = (start:string, end:string) => {
67
- const dates = [start];
68
- let currentDate = start;
69
-
70
- while (currentDate !== end) {
71
- const dateObj = new Date(currentDate);
72
- dateObj.setDate(dateObj.getDate()+1);
73
- const dateObjString = dateToString(dateObj);
74
- dates.push(dateObjString);
75
- currentDate = dateObjString;
76
- }
77
-
78
- return dates;
79
- };
80
-
81
- export const reformatDate = (date: Date|string) => {
82
- if (!date) {
83
- return;
84
- }
85
- return date.toString().split("-").reverse().join(".");
86
- };
87
-
88
- export const convertDate = (date?: string|Date, output: "dbstring"|"date"|"visual" = "date") => {
89
- // dbstring = yyyy-MM-dd
90
- // visual = dd MMM yyyy
91
- // date = Date
92
- if (!date) return;
93
-
94
- let year:number;
95
- let month:number;
96
- let day:number;
97
-
98
- const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
99
-
100
- if (typeof date === "string") {
101
- const dateType = date.includes(" ") ? "visual" : "dbstring";
102
- const dateArray = date.split(dateType === "visual" ? " " : "-");
103
-
104
- year = parseInt(dateArray[dateType === "visual" ? 2 : 0]);
105
- month = dateType === "visual" ? months.indexOf(dateArray[1]) : parseInt(dateArray[1]) - 1;
106
- day = parseInt(dateArray[dateType === "visual" ? 0 : 2]);
107
- } else {
108
- year = date.getFullYear();
109
- month = date.getMonth();
110
- day = date.getDate();
111
- }
112
-
113
- switch (output) {
114
- case "date":
115
- return new Date(year, month, day);
116
- case "dbstring":
117
- return [year, month+1 < 10 ? `0${month+1}` : month+1, day < 10 ? `0${day}` : day].join("-");
118
- case "visual":
119
- return [day, months[month], year].join(" ");
120
- }
121
- };
122
-
123
- export const getDateDiff = (start: Date, end:Date): number => {
124
- return (Math.round((new Date(dateToString(end)).getTime() - new Date(dateToString(start)).getTime()) / (1000 * 60 * 60 * 24)));
125
- };
126
-
127
- export const reformatDateTime = (timestamp: string|Timestamp) => {
128
- if (typeof timestamp === "string") {
129
- return `${timestamp.split("T")[1].substring(0, 8)} ${(timestamp.split("T")[0]).split("-").reverse().join(".")}`;
130
- }
131
-
132
- try {
133
- const created = new Date(timestamp.seconds * 1000).toISOString();
134
- return `${created.split("T")[1].substring(0, 8)} ${(created.split("T")[0]).split("-").reverse().join(".")}`;
135
- } catch (e) {
136
- return null;
137
- }
138
- };
139
-
140
- export function stringToDate(date: string) {
141
- const formatItems= date.split("/").map((i) => parseInt(i));
142
- console.log("date array", formatItems);
143
- return new Date(formatItems[2], formatItems[1]-1, formatItems[0]);
144
- }
145
-
146
- export const editNestedObject = (loc:(string|number)[], data:any[]|{[key: string|number]: unknown}, value:any, objectId=false) => {
147
- if (!data || !(Array.isArray(data) || typeof data === "object")) {
148
- console.error("Error editing nested JSON. Invalid type");
149
- return;
150
- }
151
-
152
- type IndexType = typeof data extends any[] ? number : number|string
153
-
154
- const prevData: typeof data = Array.isArray(data) ? [...data] : {...data};
155
- const locationIndex:IndexType = objectId && Array.isArray(data) ? (prevData as any[]).findIndex((x) => x.id === loc[0]) : loc[0];
156
-
157
- if (loc.length > 1) {
158
- prevData[locationIndex as any] = editNestedObject(loc.slice(1), data[locationIndex as any] || {}, value, objectId);
159
- } else {
160
- if (value === undefined) {
161
- Array.isArray(prevData) ? prevData.splice(locationIndex as number, 1) : delete prevData[locationIndex];
162
- } else {
163
- prevData[locationIndex as any] = value;
164
- }
165
- }
166
-
167
- return prevData;
168
- };
169
-
170
- export const getItemInNestedObject = (path:string[], object) => {
171
- if (path.length === 0) return;
172
-
173
- const item = object[path.shift() as string];
174
- if (path.length > 0) {
175
- return getItemInNestedObject(path, item);
176
- }
177
- return item;
178
- };
179
-
180
- export const camelCaseToNormal = (string="") => {
181
- return string.replace(/([A-Z])/g, " $1").toLowerCase().trim().replace(/^./, function(str) {
182
- return str.toUpperCase();
183
- });
184
- };
185
-
186
- export const camelCase = (string="") => {
187
- return string.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
188
- };
189
-
190
- export const isJson = (item:any) => {
191
- item = typeof item !== "string" ?
192
- JSON.stringify(item) :
193
- item;
194
-
195
- try {
196
- item = JSON.parse(item);
197
- } catch (e) {
198
- return false;
199
- }
200
-
201
- return (typeof item === "object" && item !== null);
202
- };
203
-
204
- export const sortByReverseStringLength = (array: string[]) => {
205
- return array.sort(function(a, b) {
206
- return b.length - a.length;
207
- });
208
- };
209
-
210
- export const pathToArr = (path: any[]|any) => Array.isArray(path) ? path : [path];
211
-
212
- export const arraysEqual = (a:any[], b:any[]) => {
213
- if (a === b) return true;
214
- if (a == null || b == null) return false;
215
- if (a.length !== b.length) return false;
216
-
217
- return a.every((val, idx) => val === b[idx]);
218
- };
219
-
220
-
221
- export const objectsEqual = (x:object, y:object):boolean => {
222
- const ok = Object.keys; const tx = typeof x; const ty = typeof y;
223
- return x && y && tx === "object" && tx === ty ? (
224
- ok(x).length === ok(y).length &&
225
- ok(x).every((key) => objectsEqual(x[key as keyof typeof x], y[key as keyof typeof x]))
226
- ) : (x === y);
227
- };
228
-
229
- export const arrayUniqueValues = (array:unknown[]) => {
230
- return array.filter((value, index, self) => self.indexOf(value) === index);
231
- };
232
-
233
-
234
- export const flattenObject = (obj) => {
235
- const flattened = {};
236
-
237
- Object.keys(obj).forEach((key) => {
238
- const value = obj[key];
239
-
240
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
241
- Object.assign(flattened, flattenObject(value));
242
- } else {
243
- flattened[key] = value;
244
- }
245
- });
246
-
247
- return flattened;
248
- };
249
-
250
-
251
- export const getGeoHash = async (data:Address) => {
252
- const address = data["address-line1"] + " " + data["address-line2"] +
253
- " " + data.locality + " " + data.postal_code + " " + data.country;
254
- address.replace(" ", "+");
255
- const apiQuery = "https://maps.googleapis.com/maps/api/geocode/json?address=" +
256
- address + "&key=AIzaSyBOSSi4iHxOoAS9tLAJUAC_46HlZ6-D5Ss";
257
-
258
- const location = await fetch(apiQuery)
259
- .then(async (res) =>
260
- await res.json() as {results: {geometry: {location: unknown}}[]})
261
- .then((res: {results: {geometry: {location: unknown}}[]}) => {
262
- return res;
263
- }, (error: Error) => {
264
- return error;
265
- });
266
-
267
- if (location instanceof Error || !location.results.length) {
268
- return;
269
- }
270
-
271
- const result = location.results[0].geometry.location as {lat:number, lng:number};
272
-
273
- return geoHash.encode(result.lat, result.lng, 12);
274
- };
275
-
276
- export const decodeGeoHash = (g: string) => {
277
- console.log("g", g);
278
- if (!g) return;
279
- return geoHash.decode(g);
280
- };
281
-
282
- export const randomPassword = () => {
283
- let text = "";
284
- const c = "ABCDEFGHIJKLMNNOPQRSTUVWXYZ" +
285
- "abcdefghijklmnopqrstuvwxyz0123456789";
286
-
287
- for (let i = 0; i < 12; i++) {
288
- text += c.charAt(Math.floor(Math.random() * c.length));
289
- }
290
- return text;
291
- };
292
-
293
- export const arrayEquals = (a:unknown, b:unknown) => {
294
- return Array.isArray(a) &&
295
- Array.isArray(b) &&
296
- a.length === b.length &&
297
- a.every((val, index) => val === b[index]);
298
- };
299
-
300
- export const average = (arr: number[]) => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
301
-
302
- export const readingTime = (text: string) => {
303
- if (!text) return;
304
- const wpm = 225;
305
- const words = text.trim().split(/\s+/).length;
306
- const time = Math.ceil(words / wpm);
307
- return `${time} minute${(time > 1) ? "s" : ""}`;
308
- };
309
- /*
310
- export const imageToPdf = async (image: File):Promise<string> => {
311
- const doc = PDFDocument;
312
-
313
- const imgStream = await image.arrayBuffer();
314
-
315
- doc.image(imgStream, {
316
- fit: [500, 400],
317
- align: 'center',
318
- valign: 'center'
319
- });
320
-
321
- doc.end(); // will trigger the stream to end
322
-
323
- return await pdfToBase64(doc);
324
- }
325
-
326
- function pdfToBase64(doc): Promise<string> {
327
- return new Promise<string>((resolve, reject) => {
328
- // Create a buffer
329
- const buffers: Buffer[] = [];
330
- doc.on('data', (chunk: Buffer) => {
331
- buffers.push(chunk);
332
- });
333
- doc.on('end', () => {
334
- // Concatenate all the buffers to form a single buffer
335
- const pdfBuffer = Buffer.concat(buffers);
336
-
337
- // Convert the buffer to a base64 string
338
- const base64String = pdfBuffer.toString('base64');
339
-
340
- resolve(base64String);
341
- });
342
-
343
- // Handle errors
344
- doc.on('error', (error: Error) => {
345
- reject(error);
346
- });
347
-
348
- // End the document
349
- doc.end();
350
- });
351
- }
352
- */
1
+ import {Timestamp} from "firebase/firestore";
2
+ import {Address, ProviderUserPermissions, StaffUserPermissions, UserData} from "../typeDefinitions";
3
+ import * as geoHash from "ngeohash";
4
+
5
+ export const getProviderId = async () => {/*
6
+ let user = await getDoc(doc(db, 'users', auth.currentUser.uid))
7
+ return user.data().bi*/
8
+ };
9
+
10
+ export const getRandomNumber = (min = 0, max:number) => {
11
+ return Math.random() * (max - min) + min;
12
+ };
13
+
14
+ export const getUniqueId = (object:object): number => {
15
+ const id = Math.round(getRandomNumber(0, 1000000));
16
+
17
+ if (!object) {
18
+ return id;
19
+ }
20
+
21
+ if (Array.isArray(object)) {
22
+ return object.some((el) => el.id === id) ? getUniqueId(object) : id;
23
+ }
24
+
25
+ return (Object.keys(object) as any[]).some((el) => el === id) ? getUniqueId(object) : id;
26
+ };
27
+
28
+ export const capitalise = (s="") => {
29
+ const nS = s.toString().replace("_", " ");
30
+ return nS.charAt(0).toUpperCase() + nS.slice(1);
31
+ };
32
+
33
+ export const capitaliseWords = (s="") => {
34
+ return s.replace(/(^|\s)\S/g, (l) => l.toUpperCase());
35
+ };
36
+
37
+ export const snakeCase = (s="") => {
38
+ const nS = s.toString().replace(" ", "_");
39
+ return nS.toLowerCase();
40
+ };
41
+
42
+ export const validateEmail = (email: string) => {
43
+ console.log(email);
44
+ return email.match(
45
+ /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
46
+ );
47
+ };
48
+
49
+ export const getAccess = (user:UserData, ...perms: (keyof StaffUserPermissions | keyof ProviderUserPermissions)[]) => {
50
+ // If the user has the permission given, grant access
51
+ const finalPerms: {[key: string]: any} = {};
52
+ perms.forEach((perm) => {
53
+ finalPerms[perm] = (user.userGroup === "admin" || (user.groupData as object)?.[perm] || false);
54
+ });
55
+ // Otherwise, deny access
56
+ return Object.keys(finalPerms).length > 1 ? finalPerms : Object.values(finalPerms)[0];
57
+ };
58
+
59
+ export const dateToString = (date:Date) => {
60
+ const y = date.getFullYear();
61
+ const m = ("0"+(date.getMonth() + 1)).slice(-2);
62
+ const d = ("0"+(date.getDate())).slice(-2);
63
+ return [y, m, d].join("-");
64
+ };
65
+
66
+ export const getPlacementDateArray = (start:string, end:string) => {
67
+ const dates = [start];
68
+ let currentDate = start;
69
+
70
+ while (currentDate !== end) {
71
+ const dateObj = new Date(currentDate);
72
+ dateObj.setDate(dateObj.getDate()+1);
73
+ const dateObjString = dateToString(dateObj);
74
+ dates.push(dateObjString);
75
+ currentDate = dateObjString;
76
+ }
77
+
78
+ return dates;
79
+ };
80
+
81
+ export const reformatDate = (date: Date|string) => {
82
+ if (!date) {
83
+ return;
84
+ }
85
+ return date.toString().split("-").reverse().join(".");
86
+ };
87
+
88
+ export const convertDate = (date?: string|Date, output: "dbstring"|"date"|"visual" = "date") => {
89
+ // dbstring = yyyy-MM-dd
90
+ // visual = dd MMM yyyy
91
+ // date = Date
92
+ if (!date) return;
93
+
94
+ let year:number;
95
+ let month:number;
96
+ let day:number;
97
+
98
+ const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
99
+
100
+ if (typeof date === "string") {
101
+ const dateType = date.includes(" ") ? "visual" : "dbstring";
102
+ const dateArray = date.split(dateType === "visual" ? " " : "-");
103
+
104
+ year = parseInt(dateArray[dateType === "visual" ? 2 : 0]);
105
+ month = dateType === "visual" ? months.indexOf(dateArray[1]) : parseInt(dateArray[1]) - 1;
106
+ day = parseInt(dateArray[dateType === "visual" ? 0 : 2]);
107
+ } else {
108
+ year = date.getFullYear();
109
+ month = date.getMonth();
110
+ day = date.getDate();
111
+ }
112
+
113
+ switch (output) {
114
+ case "date":
115
+ return new Date(year, month, day);
116
+ case "dbstring":
117
+ return [year, month+1 < 10 ? `0${month+1}` : month+1, day < 10 ? `0${day}` : day].join("-");
118
+ case "visual":
119
+ return [day, months[month], year].join(" ");
120
+ }
121
+ };
122
+
123
+ export const getDateDiff = (start: Date, end:Date): number => {
124
+ return (Math.round((new Date(dateToString(end)).getTime() - new Date(dateToString(start)).getTime()) / (1000 * 60 * 60 * 24)));
125
+ };
126
+
127
+ export const reformatDateTime = (timestamp: string|Timestamp) => {
128
+ if (typeof timestamp === "string") {
129
+ return `${timestamp.split("T")[1].substring(0, 8)} ${(timestamp.split("T")[0]).split("-").reverse().join(".")}`;
130
+ }
131
+
132
+ try {
133
+ const created = new Date(timestamp.seconds * 1000).toISOString();
134
+ return `${created.split("T")[1].substring(0, 8)} ${(created.split("T")[0]).split("-").reverse().join(".")}`;
135
+ } catch (e) {
136
+ return null;
137
+ }
138
+ };
139
+
140
+ export function stringToDate(date: string) {
141
+ const formatItems= date.split("/").map((i) => parseInt(i));
142
+ console.log("date array", formatItems);
143
+ return new Date(formatItems[2], formatItems[1]-1, formatItems[0]);
144
+ }
145
+
146
+ export const editNestedObject = (loc:(string|number)[], data:any[]|{[key: string|number]: unknown}, value:any, objectId=false) => {
147
+ if (!data || !(Array.isArray(data) || typeof data === "object")) {
148
+ console.error("Error editing nested JSON. Invalid type");
149
+ return;
150
+ }
151
+
152
+ type IndexType = typeof data extends any[] ? number : number|string
153
+
154
+ const prevData: typeof data = Array.isArray(data) ? [...data] : {...data};
155
+ const locationIndex:IndexType = objectId && Array.isArray(data) ? (prevData as any[]).findIndex((x) => x.id === loc[0]) : loc[0];
156
+
157
+ if (loc.length > 1) {
158
+ prevData[locationIndex as any] = editNestedObject(loc.slice(1), data[locationIndex as any] || {}, value, objectId);
159
+ } else {
160
+ if (value === undefined) {
161
+ Array.isArray(prevData) ? prevData.splice(locationIndex as number, 1) : delete prevData[locationIndex];
162
+ } else {
163
+ prevData[locationIndex as any] = value;
164
+ }
165
+ }
166
+
167
+ return prevData;
168
+ };
169
+
170
+ export const getItemInNestedObject = (path:string[], object) => {
171
+ if (path.length === 0) return;
172
+
173
+ const item = object[path.shift() as string];
174
+ if (path.length > 0) {
175
+ return getItemInNestedObject(path, item);
176
+ }
177
+ return item;
178
+ };
179
+
180
+ export const camelCaseToNormal = (string="") => {
181
+ return string.replace(/([A-Z])/g, " $1").toLowerCase().trim().replace(/^./, function(str) {
182
+ return str.toUpperCase();
183
+ });
184
+ };
185
+
186
+ export const camelCase = (string="") => {
187
+ return string.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());
188
+ };
189
+
190
+ export const isJson = (item:any) => {
191
+ item = typeof item !== "string" ?
192
+ JSON.stringify(item) :
193
+ item;
194
+
195
+ try {
196
+ item = JSON.parse(item);
197
+ } catch (e) {
198
+ return false;
199
+ }
200
+
201
+ return (typeof item === "object" && item !== null);
202
+ };
203
+
204
+ export const sortByReverseStringLength = (array: string[]) => {
205
+ return array.sort(function(a, b) {
206
+ return b.length - a.length;
207
+ });
208
+ };
209
+
210
+ export const pathToArr = (path: any[]|any) => Array.isArray(path) ? path : [path];
211
+
212
+ export const arraysEqual = (a:any[], b:any[]) => {
213
+ if (a === b) return true;
214
+ if (a == null || b == null) return false;
215
+ if (a.length !== b.length) return false;
216
+
217
+ return a.every((val, idx) => val === b[idx]);
218
+ };
219
+
220
+
221
+ export const objectsEqual = (x:object, y:object):boolean => {
222
+ const ok = Object.keys; const tx = typeof x; const ty = typeof y;
223
+ return x && y && tx === "object" && tx === ty ? (
224
+ ok(x).length === ok(y).length &&
225
+ ok(x).every((key) => objectsEqual(x[key as keyof typeof x], y[key as keyof typeof x]))
226
+ ) : (x === y);
227
+ };
228
+
229
+ export const arrayUniqueValues = (array:unknown[]) => {
230
+ return array.filter((value, index, self) => self.indexOf(value) === index);
231
+ };
232
+
233
+
234
+ export const flattenObject = (obj) => {
235
+ const flattened = {};
236
+
237
+ Object.keys(obj).forEach((key) => {
238
+ const value = obj[key];
239
+
240
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
241
+ Object.assign(flattened, flattenObject(value));
242
+ } else {
243
+ flattened[key] = value;
244
+ }
245
+ });
246
+
247
+ return flattened;
248
+ };
249
+
250
+
251
+ export const getGeoHash = async (data:Address) => {
252
+ const address = data["address-line1"] + " " + data["address-line2"] +
253
+ " " + data.locality + " " + data.postal_code + " " + data.country;
254
+ address.replace(" ", "+");
255
+ const apiQuery = "https://maps.googleapis.com/maps/api/geocode/json?address=" +
256
+ address + "&key=AIzaSyBOSSi4iHxOoAS9tLAJUAC_46HlZ6-D5Ss";
257
+
258
+ const location = await fetch(apiQuery)
259
+ .then(async (res) =>
260
+ await res.json() as {results: {geometry: {location: unknown}}[]})
261
+ .then((res: {results: {geometry: {location: unknown}}[]}) => {
262
+ return res;
263
+ }, (error: Error) => {
264
+ return error;
265
+ });
266
+
267
+ if (location instanceof Error || !location.results.length) {
268
+ return;
269
+ }
270
+
271
+ const result = location.results[0].geometry.location as {lat:number, lng:number};
272
+
273
+ return geoHash.encode(result.lat, result.lng, 12);
274
+ };
275
+
276
+ export const decodeGeoHash = (g: string) => {
277
+ console.log("g", g);
278
+ if (!g) return;
279
+ return geoHash.decode(g);
280
+ };
281
+
282
+ export const randomPassword = () => {
283
+ let text = "";
284
+ const c = "ABCDEFGHIJKLMNNOPQRSTUVWXYZ" +
285
+ "abcdefghijklmnopqrstuvwxyz0123456789";
286
+
287
+ for (let i = 0; i < 12; i++) {
288
+ text += c.charAt(Math.floor(Math.random() * c.length));
289
+ }
290
+ return text;
291
+ };
292
+
293
+ export const arrayEquals = (a:unknown, b:unknown) => {
294
+ return Array.isArray(a) &&
295
+ Array.isArray(b) &&
296
+ a.length === b.length &&
297
+ a.every((val, index) => val === b[index]);
298
+ };
299
+
300
+ export const average = (arr: number[]) => arr.reduce( ( p, c ) => p + c, 0 ) / arr.length;
301
+
302
+ export const readingTime = (text: string) => {
303
+ if (!text) return;
304
+ const wpm = 225;
305
+ const words = text.trim().split(/\s+/).length;
306
+ const time = Math.ceil(words / wpm);
307
+ return `${time} minute${(time > 1) ? "s" : ""}`;
308
+ };
309
+ /*
310
+ export const imageToPdf = async (image: File):Promise<string> => {
311
+ const doc = PDFDocument;
312
+
313
+ const imgStream = await image.arrayBuffer();
314
+
315
+ doc.image(imgStream, {
316
+ fit: [500, 400],
317
+ align: 'center',
318
+ valign: 'center'
319
+ });
320
+
321
+ doc.end(); // will trigger the stream to end
322
+
323
+ return await pdfToBase64(doc);
324
+ }
325
+
326
+ function pdfToBase64(doc): Promise<string> {
327
+ return new Promise<string>((resolve, reject) => {
328
+ // Create a buffer
329
+ const buffers: Buffer[] = [];
330
+ doc.on('data', (chunk: Buffer) => {
331
+ buffers.push(chunk);
332
+ });
333
+ doc.on('end', () => {
334
+ // Concatenate all the buffers to form a single buffer
335
+ const pdfBuffer = Buffer.concat(buffers);
336
+
337
+ // Convert the buffer to a base64 string
338
+ const base64String = pdfBuffer.toString('base64');
339
+
340
+ resolve(base64String);
341
+ });
342
+
343
+ // Handle errors
344
+ doc.on('error', (error: Error) => {
345
+ reject(error);
346
+ });
347
+
348
+ // End the document
349
+ doc.end();
350
+ });
351
+ }
352
+ */