placementt-core 1.20.196 → 11.0.533

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 (135) hide show
  1. package/.eslintrc.js +40 -40
  2. package/.gitattributes +2 -2
  3. package/lib/config.d.ts +0 -1
  4. package/lib/constants.d.ts +5 -2
  5. package/lib/constants.js +130 -136
  6. package/lib/constants.js.map +1 -1
  7. package/lib/features/analytics/useAnalytics.d.ts +0 -1
  8. package/lib/features/analytics/useAnalytics.js +3 -4
  9. package/lib/features/analytics/useAnalytics.js.map +1 -1
  10. package/lib/features/config.d.ts +133 -133
  11. package/lib/features/config.js +35 -35
  12. package/lib/features/contacts/contacts.d.ts +75 -75
  13. package/lib/features/contacts/contacts.js +105 -105
  14. package/lib/features/contacts/contactsSlice.d.ts +5 -5
  15. package/lib/features/contacts/useContacts.js +1 -2
  16. package/lib/features/contacts/useContacts.js.map +1 -1
  17. package/lib/features/downtime/useDowntime.d.ts +11 -11
  18. package/lib/features/downtime/useDowntime.js +22 -22
  19. package/lib/features/dropdown/useDropdown.d.ts +2 -3
  20. package/lib/features/dropdown/useDropdown.js +1 -2
  21. package/lib/features/dropdown/useDropdown.js.map +1 -1
  22. package/lib/features/global/downtime/useDowntime.d.ts +0 -1
  23. package/lib/features/global/downtime/useDowntime.js +3 -2
  24. package/lib/features/global/downtime/useDowntime.js.map +1 -1
  25. package/lib/features/global/users/useUserFunctions.d.ts +0 -1
  26. package/lib/features/global/users/useUserFunctions.js +6 -7
  27. package/lib/features/global/users/useUserFunctions.js.map +1 -1
  28. package/lib/features/placements/studentPlacements/activePlacement.d.ts +1 -1
  29. package/lib/features/placements/studentPlacements/activePlacement.js +1 -1
  30. package/lib/features/placements/studentPlacements/activePlacement.js.map +1 -1
  31. package/lib/features/placements/studentPlacements/completedStudentPlacementsSlice.d.ts +4 -5
  32. package/lib/features/placements/studentPlacements/completedStudentPlacementsSlice.js +1 -4
  33. package/lib/features/placements/studentPlacements/completedStudentPlacementsSlice.js.map +1 -1
  34. package/lib/features/placements/studentPlacements/studentPlacementsSlice.d.ts +63 -63
  35. package/lib/features/placements/studentPlacements/studentPlacementsSlice.js +81 -81
  36. package/lib/features/placements/studentPlacements/upcomingStudentPlacementsSlice.d.ts +4 -4
  37. package/lib/features/placements/studentPlacements/upcomingStudentPlacementsSlice.js +1 -1
  38. package/lib/features/placements/studentPlacements/upcomingStudentPlacementsSlice.js.map +1 -1
  39. package/lib/features/placements/studentPlacements/useStudentPlacements.d.ts +0 -1
  40. package/lib/features/placements/studentPlacements/useStudentPlacements.js +1 -2
  41. package/lib/features/placements/studentPlacements/useStudentPlacements.js.map +1 -1
  42. package/lib/features/providerPlacements/providerPlacementsSlice.d.ts +19 -19
  43. package/lib/features/providerPlacements/providerPlacementsSlice.js +24 -24
  44. package/lib/features/referrals/useReferrals.d.ts +0 -1
  45. package/lib/features/referrals/useReferrals.js +1 -2
  46. package/lib/features/referrals/useReferrals.js.map +1 -1
  47. package/lib/features/studentPlacements/studentPlacementsSlice.d.ts +62 -62
  48. package/lib/features/studentPlacements/studentPlacementsSlice.js +87 -87
  49. package/lib/features/studentPlacements/useStudentPlacements.d.ts +6 -6
  50. package/lib/features/studentPlacements/useStudentPlacements.js +18 -18
  51. package/lib/features/updates/useUpdates.js +1 -2
  52. package/lib/features/updates/useUpdates.js.map +1 -1
  53. package/lib/features/userSlice.d.ts +26 -26
  54. package/lib/features/userSlice.js +23 -23
  55. package/lib/features/users/useUserFunctions.d.ts +25 -25
  56. package/lib/features/users/useUserFunctions.js +124 -124
  57. package/lib/features/users/userSlice.d.ts +46 -46
  58. package/lib/features/users/userSlice.js +48 -48
  59. package/lib/firebase/firebase.d.ts +1 -1
  60. package/lib/firebase/firebase.js +9 -4
  61. package/lib/firebase/firebase.js.map +1 -1
  62. package/lib/firebase/firebaseConfig.js +3 -0
  63. package/lib/firebase/firebaseConfig.js.map +1 -1
  64. package/lib/firebase/firebaseQuery.js +3 -0
  65. package/lib/firebase/firebaseQuery.js.map +1 -1
  66. package/lib/firebase/persistence.js +2 -2
  67. package/lib/firebase/persistence.js.map +1 -1
  68. package/lib/firebase/readDatabase.d.ts +9 -6
  69. package/lib/firebase/readDatabase.js +16 -6
  70. package/lib/firebase/readDatabase.js.map +1 -1
  71. package/lib/firebase/util.d.ts +3 -4
  72. package/lib/firebase/util.js +49 -4
  73. package/lib/firebase/util.js.map +1 -1
  74. package/lib/firebase/writeDatabase.d.ts +3 -3
  75. package/lib/firebase/writeDatabase.js +7 -1
  76. package/lib/firebase/writeDatabase.js.map +1 -1
  77. package/lib/hooks.d.ts +384 -23
  78. package/lib/hooks.js +1342 -223
  79. package/lib/hooks.js.map +1 -1
  80. package/lib/images/GatsbyBenchmarks.d.ts +0 -1
  81. package/lib/images/GatsbyBenchmarks.js +1 -1
  82. package/lib/images/GatsbyBenchmarks.js.map +1 -1
  83. package/lib/reduxHooks.d.ts +11 -20
  84. package/lib/reduxHooks.js +28 -18
  85. package/lib/reduxHooks.js.map +1 -1
  86. package/lib/tasksAndTips.d.ts +25 -5
  87. package/lib/tasksAndTips.js +346 -48
  88. package/lib/tasksAndTips.js.map +1 -1
  89. package/lib/typeDefinitions.d.ts +478 -53
  90. package/lib/util.d.ts +1 -0
  91. package/lib/util.js +78 -6
  92. package/lib/util.js.map +1 -1
  93. package/package.json +52 -49
  94. package/src/DatabaseDefinitions.ts +18 -18
  95. package/src/apiCalls.ts +128 -128
  96. package/src/config.ts +50 -50
  97. package/src/constants.ts +708 -707
  98. package/src/databaseTypes.ts +42 -42
  99. package/src/features/analytics/useAnalytics.tsx +55 -55
  100. package/src/features/contacts/contactsSlice.ts +147 -147
  101. package/src/features/contacts/useContacts.tsx +73 -73
  102. package/src/features/dropdown/useDropdown.tsx +52 -52
  103. package/src/features/global/downtime/useDowntime.tsx +19 -18
  104. package/src/features/global/users/useUserFunctions.tsx +132 -132
  105. package/src/features/jobs/jobsSlice.ts +65 -65
  106. package/src/features/placements/studentPlacements/activePlacement.ts +63 -63
  107. package/src/features/placements/studentPlacements/completedStudentPlacementsSlice.ts +94 -97
  108. package/src/features/placements/studentPlacements/upcomingStudentPlacementsSlice.ts +108 -108
  109. package/src/features/placements/studentPlacements/useStudentPlacements.tsx +33 -33
  110. package/src/features/placements/types.ts +10 -10
  111. package/src/features/referrals/useReferrals.tsx +56 -56
  112. package/src/features/updates/useUpdates.tsx +36 -36
  113. package/src/firebase/firebase.tsx +142 -138
  114. package/src/firebase/firebaseConfig.tsx +45 -42
  115. package/src/firebase/firebaseQuery.tsx +143 -140
  116. package/src/firebase/persistence.ts +84 -84
  117. package/src/firebase/readDatabase.tsx +208 -197
  118. package/src/firebase/util.tsx +352 -308
  119. package/src/firebase/writeDatabase.tsx +75 -68
  120. package/src/hooks.tsx +3395 -1943
  121. package/src/images/GatsbyBenchmarks.tsx +711 -711
  122. package/src/images/LogFuturePlacement.jsx +64 -64
  123. package/src/images/LogPreviousPlacement.jsx +228 -228
  124. package/src/images/gatsby_benchmarks.svg +466 -466
  125. package/src/images/log_future_placement.svg +114 -114
  126. package/src/images/log_previous_placement.svg +199 -199
  127. package/src/index.ts +34 -34
  128. package/src/readDatabase.tsx +3 -3
  129. package/src/reduxHooks.ts +183 -170
  130. package/src/tasksAndTips.ts +744 -410
  131. package/src/tutorialTips.ts +58 -58
  132. package/src/typeDefinitions.ts +899 -503
  133. package/src/util.ts +132 -47
  134. package/tsconfig.dev.json +5 -5
  135. package/tsconfig.json +21 -21
@@ -1,308 +1,352 @@
1
- import {Timestamp} from "firebase/firestore";
2
- import {Address, 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: string[]) => {
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
- };
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
+ */