goobs-frontend 0.7.61 → 0.7.63
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 +2 -2
- package/src/components/Button/index.tsx +103 -65
- package/src/components/ConfirmationCodeInput/index.tsx +2 -2
- package/src/components/Content/index.tsx +13 -7
- package/src/components/Form/Popup/index.tsx +29 -10
- package/src/components/Icons/ShowHideEye.tsx +8 -2
- package/src/components/Nav/HorizontalVariant/index.tsx +11 -4
- package/src/components/Nav/index.tsx +2 -14
- package/src/components/StyledComponent/adornment/index.tsx +6 -8
- package/src/components/StyledComponent/helperfooter/useHelperFooter.tsx +383 -340
- package/src/components/StyledComponent/hooks/useDropdown.tsx +48 -5
- package/src/components/StyledComponent/hooks/usePhoneNumber.tsx +53 -27
- package/src/components/StyledComponent/index.tsx +109 -18
- package/src/components/StyledComponent/hooks/usePassword.tsx +0 -23
|
@@ -2,186 +2,152 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useState, useMemo, useRef, useEffect } from 'react'
|
|
4
4
|
import { debounce } from 'lodash'
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Validates if the given string is a valid email format.
|
|
10
|
-
*
|
|
11
|
-
* @param {string} email - The email string to validate.
|
|
12
|
-
* @returns {boolean} True if the email is valid, false otherwise.
|
|
13
|
-
*/
|
|
5
|
+
import { get, set, StringValue, JSONValue } from 'goobs-cache'
|
|
6
|
+
|
|
14
7
|
const isValidEmailFormat = (email: string): boolean => {
|
|
15
8
|
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
|
|
16
9
|
return emailRegex.test(email)
|
|
17
10
|
}
|
|
18
11
|
|
|
19
|
-
/**
|
|
20
|
-
* Represents a message for the helper footer.
|
|
21
|
-
*
|
|
22
|
-
* @interface HelperFooterMessage
|
|
23
|
-
* @property {('error' | 'success')} status - The status of the message.
|
|
24
|
-
* @property {string} statusMessage - The detailed status message.
|
|
25
|
-
* @property {string} spreadMessage - A condensed version of the message for spreading.
|
|
26
|
-
* @property {number} spreadMessagePriority - The priority of the spread message.
|
|
27
|
-
* @property {string} formname - The name of the form this message is associated with.
|
|
28
|
-
* @property {boolean} required - Indicates if the field associated with this message is required.
|
|
29
|
-
*/
|
|
30
12
|
export interface HelperFooterMessage {
|
|
31
|
-
status: 'error' | 'success'
|
|
13
|
+
status: 'error' | 'success' | 'emptyAndRequired'
|
|
32
14
|
statusMessage: string
|
|
33
15
|
spreadMessage: string
|
|
34
16
|
spreadMessagePriority: number
|
|
35
|
-
formname: string
|
|
36
17
|
required: boolean
|
|
37
18
|
}
|
|
38
19
|
|
|
39
|
-
/**
|
|
40
|
-
* A custom hook for managing form validation and helper messages.
|
|
41
|
-
*
|
|
42
|
-
* @returns {Object} An object containing validation functions and helper footer state.
|
|
43
|
-
*/
|
|
44
20
|
export const useHelperFooter = () => {
|
|
45
21
|
const [helperFooterValue, setHelperFooterValue] = useState<
|
|
46
22
|
Record<string, HelperFooterMessage>
|
|
47
23
|
>({})
|
|
48
24
|
const helperFooterRef = useRef<Record<string, HelperFooterMessage>>({})
|
|
49
25
|
|
|
50
|
-
/**
|
|
51
|
-
* Handles creation of generic error messages for form fields.
|
|
52
|
-
*
|
|
53
|
-
* @param {FormData} formData - The form data to validate.
|
|
54
|
-
* @param {string} name - The name of the form field.
|
|
55
|
-
* @param {string} label - The label of the form field.
|
|
56
|
-
* @param {boolean} required - Whether the field is required.
|
|
57
|
-
* @param {string} formname - The name of the form.
|
|
58
|
-
* @returns {HelperFooterMessage | undefined} An error message object if there's an error, undefined otherwise.
|
|
59
|
-
*/
|
|
60
26
|
const handleGenericErrorCreation = useCallback(
|
|
61
|
-
(
|
|
27
|
+
async (
|
|
62
28
|
formData: FormData,
|
|
63
29
|
name: string,
|
|
64
30
|
label: string,
|
|
65
31
|
required: boolean,
|
|
66
32
|
formname: string
|
|
67
|
-
): HelperFooterMessage | undefined => {
|
|
68
|
-
console.log(`Handling generic error creation for ${name}`)
|
|
33
|
+
): Promise<HelperFooterMessage | undefined> => {
|
|
69
34
|
const value = formData.get(name) as string
|
|
70
35
|
if (required && (!value || !value.trim())) {
|
|
71
|
-
|
|
72
|
-
return {
|
|
36
|
+
const message: HelperFooterMessage = {
|
|
73
37
|
status: 'error',
|
|
74
38
|
statusMessage: `${label} is required. Please enter a ${label.toLowerCase()}.`,
|
|
75
39
|
spreadMessage: `${label} is required.`,
|
|
76
40
|
spreadMessagePriority: 1,
|
|
77
|
-
formname,
|
|
78
41
|
required,
|
|
79
42
|
}
|
|
43
|
+
const jsonValue: JSONValue = {
|
|
44
|
+
type: 'json',
|
|
45
|
+
value: {
|
|
46
|
+
[name]: {
|
|
47
|
+
status: message.status,
|
|
48
|
+
statusMessage: message.statusMessage,
|
|
49
|
+
spreadMessage: message.spreadMessage,
|
|
50
|
+
spreadMessagePriority: message.spreadMessagePriority,
|
|
51
|
+
required: message.required,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
await set('helperfooter', formname, jsonValue, 'client')
|
|
56
|
+
console.log(
|
|
57
|
+
`Stored helper footer for ${name}:`,
|
|
58
|
+
message,
|
|
59
|
+
`storeName: ${formname}`
|
|
60
|
+
)
|
|
61
|
+
return message
|
|
80
62
|
}
|
|
81
|
-
console.log(`No error for ${name}`)
|
|
82
63
|
return undefined
|
|
83
64
|
},
|
|
84
65
|
[]
|
|
85
66
|
)
|
|
86
67
|
|
|
87
|
-
/**
|
|
88
|
-
* Handles creation of email-specific error messages.
|
|
89
|
-
*
|
|
90
|
-
* @param {FormData} formData - The form data to validate.
|
|
91
|
-
* @param {boolean} required - Whether the email field is required.
|
|
92
|
-
* @param {string} formname - The name of the form.
|
|
93
|
-
* @returns {HelperFooterMessage | undefined} An error or success message object, or undefined if no message is needed.
|
|
94
|
-
*/
|
|
95
68
|
const handleEmailErrorCreation = useCallback(
|
|
96
|
-
(
|
|
69
|
+
async (
|
|
97
70
|
formData: FormData,
|
|
98
71
|
required: boolean,
|
|
99
72
|
formname: string
|
|
100
|
-
): HelperFooterMessage | undefined => {
|
|
101
|
-
console.log('Handling email error creation')
|
|
73
|
+
): Promise<HelperFooterMessage | undefined> => {
|
|
102
74
|
const email = formData.get('email') as string
|
|
75
|
+
let message: HelperFooterMessage | undefined
|
|
76
|
+
|
|
103
77
|
if (required && (!email || !email.trim())) {
|
|
104
|
-
|
|
105
|
-
return {
|
|
78
|
+
message = {
|
|
106
79
|
status: 'error',
|
|
107
80
|
statusMessage: 'Please enter an email address.',
|
|
108
81
|
spreadMessage: 'Email is required.',
|
|
109
82
|
spreadMessagePriority: 1,
|
|
110
|
-
formname,
|
|
111
83
|
required,
|
|
112
84
|
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (email && !isValidEmailFormat(email)) {
|
|
116
|
-
console.log('Error: Invalid email format')
|
|
117
|
-
return {
|
|
85
|
+
} else if (email && !isValidEmailFormat(email)) {
|
|
86
|
+
message = {
|
|
118
87
|
status: 'error',
|
|
119
88
|
statusMessage: 'Please enter a valid email address.',
|
|
120
89
|
spreadMessage: 'Invalid email format.',
|
|
121
90
|
spreadMessagePriority: 1,
|
|
122
|
-
|
|
91
|
+
required,
|
|
92
|
+
}
|
|
93
|
+
} else if (email) {
|
|
94
|
+
message = {
|
|
95
|
+
status: 'success',
|
|
96
|
+
statusMessage: 'Email is valid.',
|
|
97
|
+
spreadMessage: 'Email is valid.',
|
|
98
|
+
spreadMessagePriority: 1,
|
|
123
99
|
required,
|
|
124
100
|
}
|
|
125
101
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
102
|
+
|
|
103
|
+
if (message) {
|
|
104
|
+
const jsonValue: JSONValue = {
|
|
105
|
+
type: 'json',
|
|
106
|
+
value: {
|
|
107
|
+
email: {
|
|
108
|
+
status: message.status,
|
|
109
|
+
statusMessage: message.statusMessage,
|
|
110
|
+
spreadMessage: message.spreadMessage,
|
|
111
|
+
spreadMessagePriority: message.spreadMessagePriority,
|
|
112
|
+
required: message.required,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
await set('helperfooter', formname, jsonValue, 'client')
|
|
117
|
+
console.log(
|
|
118
|
+
`Stored helper footer for email:`,
|
|
119
|
+
message,
|
|
120
|
+
`storeName: ${formname}`
|
|
121
|
+
)
|
|
134
122
|
}
|
|
123
|
+
|
|
124
|
+
return message
|
|
135
125
|
},
|
|
136
126
|
[]
|
|
137
127
|
)
|
|
138
128
|
|
|
139
|
-
/**
|
|
140
|
-
* Handles creation of password-specific error messages and stores the password in the client cache.
|
|
141
|
-
*
|
|
142
|
-
* @param {FormData} formData - The form data to validate.
|
|
143
|
-
* @param {boolean} required - Whether the password field is required.
|
|
144
|
-
* @param {string} formname - The name of the form.
|
|
145
|
-
* @returns {HelperFooterMessage | undefined} An error or success message object, or undefined if no message is needed.
|
|
146
|
-
*/
|
|
147
129
|
const handlePasswordErrorCreation = useCallback(
|
|
148
|
-
(
|
|
130
|
+
async (
|
|
149
131
|
formData: FormData,
|
|
150
132
|
required: boolean,
|
|
151
133
|
formname: string
|
|
152
|
-
): HelperFooterMessage | undefined => {
|
|
153
|
-
console.log('Handling password error creation')
|
|
134
|
+
): Promise<HelperFooterMessage | undefined> => {
|
|
154
135
|
const password = formData.get('verifyPassword') as string
|
|
155
|
-
console.log('Password
|
|
136
|
+
console.log('handlePasswordErrorCreation - Password:', password)
|
|
156
137
|
|
|
157
138
|
const debouncedPasswordStorage = debounce(async () => {
|
|
158
|
-
console.log('Attempting to store password in goobs-cache client store')
|
|
159
139
|
try {
|
|
160
140
|
if (password) {
|
|
161
|
-
console.log('
|
|
141
|
+
console.log('Storing password in goobs-cache...')
|
|
162
142
|
await set(
|
|
163
|
-
'
|
|
143
|
+
'validate',
|
|
144
|
+
formname,
|
|
164
145
|
{ type: 'string', value: password } as StringValue,
|
|
165
|
-
new Date(Date.now() + 30 * 60 * 1000),
|
|
166
146
|
'client'
|
|
167
147
|
)
|
|
168
|
-
console.log('Password
|
|
169
|
-
|
|
170
|
-
// Immediately retrieve the password to verify it was stored
|
|
171
|
-
console.log('Attempting to retrieve password from client store')
|
|
172
|
-
const storedPassword = await get('verifyPassword', 'client')
|
|
173
|
-
console.log('Raw stored password result:', storedPassword)
|
|
174
|
-
|
|
175
|
-
if (storedPassword && storedPassword.value) {
|
|
176
|
-
console.log(
|
|
177
|
-
'Immediately retrieved password from client store:',
|
|
178
|
-
storedPassword.value
|
|
179
|
-
)
|
|
180
|
-
} else {
|
|
181
|
-
console.log('Retrieved password is null or undefined')
|
|
182
|
-
}
|
|
148
|
+
console.log('Password stored successfully')
|
|
183
149
|
} else {
|
|
184
|
-
console.log('
|
|
150
|
+
console.log('No password to store')
|
|
185
151
|
}
|
|
186
152
|
} catch (error) {
|
|
187
153
|
console.error('Error interacting with goobs-cache:', error)
|
|
@@ -190,217 +156,286 @@ export const useHelperFooter = () => {
|
|
|
190
156
|
|
|
191
157
|
debouncedPasswordStorage()
|
|
192
158
|
|
|
159
|
+
let message: HelperFooterMessage | undefined
|
|
160
|
+
|
|
193
161
|
if (required && (!password || !password.trim())) {
|
|
194
|
-
|
|
195
|
-
return {
|
|
162
|
+
message = {
|
|
196
163
|
status: 'error',
|
|
197
164
|
statusMessage: 'Password is required.',
|
|
198
165
|
spreadMessage: 'Password is required.',
|
|
199
166
|
spreadMessagePriority: 4,
|
|
200
|
-
formname,
|
|
201
167
|
required,
|
|
202
168
|
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
169
|
+
} else if (password) {
|
|
170
|
+
const passwordRegex =
|
|
171
|
+
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
|
|
172
|
+
const passwordComplexityStatus: 'error' | 'success' =
|
|
173
|
+
passwordRegex.test(password) ? 'success' : 'error'
|
|
174
|
+
|
|
175
|
+
if (passwordComplexityStatus === 'error') {
|
|
176
|
+
message = {
|
|
177
|
+
status: 'error',
|
|
178
|
+
statusMessage:
|
|
179
|
+
'Password must include at least 8 characters, one uppercase letter, one lowercase letter, one number, and one special character.',
|
|
180
|
+
spreadMessage: 'Invalid password.',
|
|
181
|
+
spreadMessagePriority: 1,
|
|
182
|
+
required,
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
message = {
|
|
186
|
+
status: 'success',
|
|
187
|
+
statusMessage: 'Password meets all requirements.',
|
|
188
|
+
spreadMessage: 'Password is valid.',
|
|
189
|
+
spreadMessagePriority: 1,
|
|
190
|
+
required,
|
|
191
|
+
}
|
|
222
192
|
}
|
|
223
193
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
194
|
+
|
|
195
|
+
if (message) {
|
|
196
|
+
const jsonValue: JSONValue = {
|
|
197
|
+
type: 'json',
|
|
198
|
+
value: {
|
|
199
|
+
verifyPassword: {
|
|
200
|
+
status: message.status,
|
|
201
|
+
statusMessage: message.statusMessage,
|
|
202
|
+
spreadMessage: message.spreadMessage,
|
|
203
|
+
spreadMessagePriority: message.spreadMessagePriority,
|
|
204
|
+
required: message.required,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
}
|
|
208
|
+
await set('helperfooter', formname, jsonValue, 'client')
|
|
209
|
+
console.log(
|
|
210
|
+
`Stored helper footer for verifyPassword:`,
|
|
211
|
+
message,
|
|
212
|
+
`storeName: ${formname}`
|
|
213
|
+
)
|
|
232
214
|
}
|
|
215
|
+
|
|
216
|
+
return message
|
|
233
217
|
},
|
|
234
218
|
[]
|
|
235
219
|
)
|
|
236
220
|
|
|
237
|
-
/**
|
|
238
|
-
* Handles creation of confirm password error messages by comparing with the stored password.
|
|
239
|
-
*
|
|
240
|
-
* @param {FormData} formData - The form data to validate.
|
|
241
|
-
* @param {boolean} required - Whether the confirm password field is required.
|
|
242
|
-
* @param {string} formname - The name of the form.
|
|
243
|
-
* @returns {Promise<HelperFooterMessage | undefined>} A promise that resolves to an error or success message object, or undefined if no message is needed.
|
|
244
|
-
*/
|
|
245
221
|
const handleConfirmPasswordErrorCreation = useCallback(
|
|
246
222
|
async (
|
|
247
223
|
formData: FormData,
|
|
248
224
|
required: boolean,
|
|
249
225
|
formname: string
|
|
250
226
|
): Promise<HelperFooterMessage | undefined> => {
|
|
251
|
-
console.log('Handling confirm password error creation')
|
|
252
227
|
const confirmPassword = formData.get('confirmPassword') as string
|
|
253
|
-
console.log(
|
|
228
|
+
console.log(
|
|
229
|
+
'handleConfirmPasswordErrorCreation - Confirm Password:',
|
|
230
|
+
confirmPassword
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
let message: HelperFooterMessage | undefined
|
|
254
234
|
|
|
255
235
|
if (required && (!confirmPassword || !confirmPassword.trim())) {
|
|
256
|
-
|
|
257
|
-
return {
|
|
236
|
+
message = {
|
|
258
237
|
status: 'error',
|
|
259
238
|
statusMessage: 'Please confirm your password.',
|
|
260
239
|
spreadMessage: 'Password confirmation is required.',
|
|
261
240
|
spreadMessagePriority: 4,
|
|
262
|
-
formname,
|
|
263
241
|
required,
|
|
264
242
|
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
console.log('Retrieved verify password result:', verifyPasswordResult)
|
|
275
|
-
} catch (error) {
|
|
276
|
-
console.error('Error retrieving password from goobs-cache:', error)
|
|
277
|
-
}
|
|
243
|
+
} else if (confirmPassword) {
|
|
244
|
+
let verifyPasswordResult
|
|
245
|
+
try {
|
|
246
|
+
console.log('Retrieving password from goobs-cache...')
|
|
247
|
+
verifyPasswordResult = await get('validate', formname, 'client')
|
|
248
|
+
console.log('Retrieved password result:', verifyPasswordResult)
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error('Error retrieving password from goobs-cache:', error)
|
|
251
|
+
}
|
|
278
252
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
)
|
|
294
|
-
}
|
|
253
|
+
let verifyPassword: string | undefined
|
|
254
|
+
if (
|
|
255
|
+
verifyPasswordResult &&
|
|
256
|
+
typeof verifyPasswordResult === 'object' &&
|
|
257
|
+
'type' in verifyPasswordResult &&
|
|
258
|
+
verifyPasswordResult.type === 'string' &&
|
|
259
|
+
'value' in verifyPasswordResult &&
|
|
260
|
+
typeof verifyPasswordResult.value === 'string'
|
|
261
|
+
) {
|
|
262
|
+
verifyPassword = verifyPasswordResult.value
|
|
263
|
+
console.log('Verify password retrieved:', verifyPassword)
|
|
264
|
+
} else {
|
|
265
|
+
console.log('Invalid or missing verify password result')
|
|
266
|
+
}
|
|
295
267
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
268
|
+
if (!verifyPassword) {
|
|
269
|
+
message = {
|
|
270
|
+
status: 'error',
|
|
271
|
+
statusMessage: 'Please enter your password first.',
|
|
272
|
+
spreadMessage: 'Password not set.',
|
|
273
|
+
spreadMessagePriority: 4,
|
|
274
|
+
required,
|
|
275
|
+
}
|
|
276
|
+
} else if (confirmPassword !== verifyPassword) {
|
|
277
|
+
message = {
|
|
278
|
+
status: 'error',
|
|
279
|
+
statusMessage: 'Passwords do not match.',
|
|
280
|
+
spreadMessage: 'Passwords do not match.',
|
|
281
|
+
spreadMessagePriority: 4,
|
|
282
|
+
required,
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
message = {
|
|
286
|
+
status: 'success',
|
|
287
|
+
statusMessage: 'Passwords match.',
|
|
288
|
+
spreadMessage: 'Passwords match.',
|
|
289
|
+
spreadMessagePriority: 4,
|
|
290
|
+
required,
|
|
291
|
+
}
|
|
305
292
|
}
|
|
306
293
|
}
|
|
307
294
|
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
295
|
+
if (message) {
|
|
296
|
+
const jsonValue: JSONValue = {
|
|
297
|
+
type: 'json',
|
|
298
|
+
value: {
|
|
299
|
+
confirmPassword: {
|
|
300
|
+
status: message.status,
|
|
301
|
+
statusMessage: message.statusMessage,
|
|
302
|
+
spreadMessage: message.spreadMessage,
|
|
303
|
+
spreadMessagePriority: message.spreadMessagePriority,
|
|
304
|
+
required: message.required,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
317
307
|
}
|
|
308
|
+
await set('helperfooter', formname, jsonValue, 'client')
|
|
309
|
+
console.log(
|
|
310
|
+
`Stored helper footer for confirmPassword:`,
|
|
311
|
+
message,
|
|
312
|
+
`storeName: ${formname}`
|
|
313
|
+
)
|
|
318
314
|
}
|
|
319
315
|
|
|
320
|
-
|
|
321
|
-
return {
|
|
322
|
-
status: 'success',
|
|
323
|
-
statusMessage: 'Passwords match.',
|
|
324
|
-
spreadMessage: 'Passwords match.',
|
|
325
|
-
spreadMessagePriority: 4,
|
|
326
|
-
formname,
|
|
327
|
-
required,
|
|
328
|
-
}
|
|
316
|
+
return message
|
|
329
317
|
},
|
|
330
318
|
[]
|
|
331
319
|
)
|
|
332
320
|
|
|
333
|
-
/**
|
|
334
|
-
* Handles creation of phone number error messages.
|
|
335
|
-
*
|
|
336
|
-
* @param {FormData} formData - The form data to validate.
|
|
337
|
-
* @param {boolean} required - Whether the phone number field is required.
|
|
338
|
-
* @param {string} formname - The name of the form.
|
|
339
|
-
* @returns {HelperFooterMessage | undefined} An error or success message object, or undefined if no message is needed.
|
|
340
|
-
*/
|
|
341
321
|
const handlePhoneNumberErrorCreation = useCallback(
|
|
342
|
-
(
|
|
322
|
+
async (
|
|
343
323
|
formData: FormData,
|
|
344
324
|
required: boolean,
|
|
345
325
|
formname: string
|
|
346
|
-
): HelperFooterMessage | undefined => {
|
|
347
|
-
console.log('Handling phone number error creation')
|
|
326
|
+
): Promise<HelperFooterMessage | undefined> => {
|
|
348
327
|
const phoneNumber = formData.get('phoneNumber') as string
|
|
328
|
+
let message: HelperFooterMessage | undefined
|
|
329
|
+
|
|
349
330
|
if (required && (!phoneNumber || !phoneNumber.trim())) {
|
|
350
|
-
|
|
351
|
-
return {
|
|
331
|
+
message = {
|
|
352
332
|
status: 'error',
|
|
353
333
|
statusMessage:
|
|
354
334
|
'Phone number is required. Please enter a phone number.',
|
|
355
335
|
spreadMessage: 'Phone number is required.',
|
|
356
336
|
spreadMessagePriority: 1,
|
|
357
|
-
formname,
|
|
358
337
|
required,
|
|
359
338
|
}
|
|
339
|
+
} else if (phoneNumber) {
|
|
340
|
+
const digitsOnly = phoneNumber.replace(/[^\d]/g, '')
|
|
341
|
+
const length = digitsOnly.length
|
|
342
|
+
if (
|
|
343
|
+
(length === 10 && !digitsOnly.startsWith('1')) ||
|
|
344
|
+
(length === 11 && digitsOnly.startsWith('1'))
|
|
345
|
+
) {
|
|
346
|
+
message = {
|
|
347
|
+
status: 'success',
|
|
348
|
+
statusMessage: 'Phone number is valid.',
|
|
349
|
+
spreadMessage: 'Phone number is valid.',
|
|
350
|
+
spreadMessagePriority: 1,
|
|
351
|
+
required,
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
message = {
|
|
355
|
+
status: 'error',
|
|
356
|
+
statusMessage:
|
|
357
|
+
'Please enter a valid 10-digit phone number or a 10-digit number starting with 1.',
|
|
358
|
+
spreadMessage: 'Invalid phone number format.',
|
|
359
|
+
spreadMessagePriority: 1,
|
|
360
|
+
required,
|
|
361
|
+
}
|
|
362
|
+
}
|
|
360
363
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
formname,
|
|
375
|
-
required,
|
|
364
|
+
|
|
365
|
+
if (message) {
|
|
366
|
+
const jsonValue: JSONValue = {
|
|
367
|
+
type: 'json',
|
|
368
|
+
value: {
|
|
369
|
+
phoneNumber: {
|
|
370
|
+
status: message.status,
|
|
371
|
+
statusMessage: message.statusMessage,
|
|
372
|
+
spreadMessage: message.spreadMessage,
|
|
373
|
+
spreadMessagePriority: message.spreadMessagePriority,
|
|
374
|
+
required: message.required,
|
|
375
|
+
},
|
|
376
|
+
},
|
|
376
377
|
}
|
|
377
|
-
|
|
378
|
-
console.log(
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
378
|
+
await set('helperfooter', formname, jsonValue, 'client')
|
|
379
|
+
console.log(
|
|
380
|
+
`Stored helper footer for phoneNumber:`,
|
|
381
|
+
message,
|
|
382
|
+
`storeName: ${formname}`
|
|
383
|
+
)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return message
|
|
387
|
+
},
|
|
388
|
+
[]
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
const updateHelperFooter = useCallback(
|
|
392
|
+
(name: string, validationResult: HelperFooterMessage | undefined): void => {
|
|
393
|
+
if (validationResult) {
|
|
394
|
+
helperFooterRef.current = {
|
|
395
|
+
...helperFooterRef.current,
|
|
396
|
+
[name]: validationResult,
|
|
387
397
|
}
|
|
398
|
+
} else {
|
|
399
|
+
const newHelperFooter: Record<string, HelperFooterMessage> = {}
|
|
400
|
+
Object.keys(helperFooterRef.current).forEach(key => {
|
|
401
|
+
if (key !== name) {
|
|
402
|
+
newHelperFooter[key] = helperFooterRef.current[key]
|
|
403
|
+
}
|
|
404
|
+
})
|
|
405
|
+
helperFooterRef.current = newHelperFooter
|
|
388
406
|
}
|
|
407
|
+
|
|
408
|
+
setHelperFooterValue({ ...helperFooterRef.current })
|
|
389
409
|
},
|
|
390
410
|
[]
|
|
391
411
|
)
|
|
392
412
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
413
|
+
const initializeRequiredFields = useCallback(
|
|
414
|
+
async (formname: string) => {
|
|
415
|
+
console.log(`Initializing required fields for ${formname}`)
|
|
416
|
+
const fields = await get('helperfooter', formname, 'client')
|
|
417
|
+
if (
|
|
418
|
+
fields &&
|
|
419
|
+
typeof fields === 'object' &&
|
|
420
|
+
'type' in fields &&
|
|
421
|
+
fields.type === 'json' &&
|
|
422
|
+
'value' in fields
|
|
423
|
+
) {
|
|
424
|
+
Object.entries(fields.value as Record<string, unknown>).forEach(
|
|
425
|
+
([field, message]) => {
|
|
426
|
+
if (message && typeof message === 'object' && 'status' in message) {
|
|
427
|
+
updateHelperFooter(field, message as HelperFooterMessage)
|
|
428
|
+
console.log(`Initialized required field ${field}:`, message)
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
)
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
[updateHelperFooter]
|
|
435
|
+
)
|
|
436
|
+
|
|
402
437
|
const validateField = useCallback(
|
|
403
|
-
(
|
|
438
|
+
async (
|
|
404
439
|
name: string,
|
|
405
440
|
formData: FormData,
|
|
406
441
|
label: string,
|
|
@@ -408,54 +443,49 @@ export const useHelperFooter = () => {
|
|
|
408
443
|
formname: string
|
|
409
444
|
) => {
|
|
410
445
|
console.log(`Validating field: ${name}`)
|
|
411
|
-
|
|
412
|
-
let validationResult: HelperFooterMessage | undefined
|
|
413
|
-
switch (name) {
|
|
414
|
-
case 'email':
|
|
415
|
-
validationResult = handleEmailErrorCreation(
|
|
416
|
-
formData,
|
|
417
|
-
required,
|
|
418
|
-
formname
|
|
419
|
-
)
|
|
420
|
-
break
|
|
421
|
-
case 'verifyPassword':
|
|
422
|
-
validationResult = handlePasswordErrorCreation(
|
|
423
|
-
formData,
|
|
424
|
-
required,
|
|
425
|
-
formname
|
|
426
|
-
)
|
|
427
|
-
break
|
|
428
|
-
case 'confirmPassword':
|
|
429
|
-
handleConfirmPasswordErrorCreation(
|
|
430
|
-
formData,
|
|
431
|
-
required,
|
|
432
|
-
formname
|
|
433
|
-
).then(result => {
|
|
434
|
-
validationResult = result
|
|
435
|
-
updateHelperFooter(name, validationResult)
|
|
436
|
-
})
|
|
437
|
-
return
|
|
438
|
-
case 'phoneNumber':
|
|
439
|
-
validationResult = handlePhoneNumberErrorCreation(
|
|
440
|
-
formData,
|
|
441
|
-
required,
|
|
442
|
-
formname
|
|
443
|
-
)
|
|
444
|
-
break
|
|
445
|
-
default:
|
|
446
|
-
validationResult = handleGenericErrorCreation(
|
|
447
|
-
formData,
|
|
448
|
-
name,
|
|
449
|
-
label,
|
|
450
|
-
required,
|
|
451
|
-
formname
|
|
452
|
-
)
|
|
453
|
-
}
|
|
446
|
+
let validationResult: HelperFooterMessage | undefined
|
|
454
447
|
|
|
455
|
-
|
|
448
|
+
switch (name) {
|
|
449
|
+
case 'email':
|
|
450
|
+
validationResult = await handleEmailErrorCreation(
|
|
451
|
+
formData,
|
|
452
|
+
required,
|
|
453
|
+
formname
|
|
454
|
+
)
|
|
455
|
+
break
|
|
456
|
+
case 'verifyPassword':
|
|
457
|
+
validationResult = await handlePasswordErrorCreation(
|
|
458
|
+
formData,
|
|
459
|
+
required,
|
|
460
|
+
formname
|
|
461
|
+
)
|
|
462
|
+
break
|
|
463
|
+
case 'confirmPassword':
|
|
464
|
+
validationResult = await handleConfirmPasswordErrorCreation(
|
|
465
|
+
formData,
|
|
466
|
+
required,
|
|
467
|
+
formname
|
|
468
|
+
)
|
|
469
|
+
break
|
|
470
|
+
case 'phoneNumber':
|
|
471
|
+
validationResult = await handlePhoneNumberErrorCreation(
|
|
472
|
+
formData,
|
|
473
|
+
required,
|
|
474
|
+
formname
|
|
475
|
+
)
|
|
476
|
+
break
|
|
477
|
+
default:
|
|
478
|
+
validationResult = await handleGenericErrorCreation(
|
|
479
|
+
formData,
|
|
480
|
+
name,
|
|
481
|
+
label,
|
|
482
|
+
required,
|
|
483
|
+
formname
|
|
484
|
+
)
|
|
456
485
|
}
|
|
457
486
|
|
|
458
|
-
|
|
487
|
+
updateHelperFooter(name, validationResult)
|
|
488
|
+
console.log(`Validation result for ${name}:`, validationResult)
|
|
459
489
|
},
|
|
460
490
|
[
|
|
461
491
|
handleEmailErrorCreation,
|
|
@@ -463,46 +493,17 @@ export const useHelperFooter = () => {
|
|
|
463
493
|
handleConfirmPasswordErrorCreation,
|
|
464
494
|
handlePhoneNumberErrorCreation,
|
|
465
495
|
handleGenericErrorCreation,
|
|
496
|
+
updateHelperFooter,
|
|
466
497
|
]
|
|
467
498
|
)
|
|
468
499
|
|
|
469
|
-
const updateHelperFooter = (
|
|
470
|
-
name: string,
|
|
471
|
-
validationResult: HelperFooterMessage | undefined
|
|
472
|
-
) => {
|
|
473
|
-
if (validationResult) {
|
|
474
|
-
helperFooterRef.current = {
|
|
475
|
-
...helperFooterRef.current,
|
|
476
|
-
[name]: validationResult,
|
|
477
|
-
}
|
|
478
|
-
} else {
|
|
479
|
-
helperFooterRef.current = Object.fromEntries(
|
|
480
|
-
Object.entries(helperFooterRef.current).filter(([key]) => key !== name)
|
|
481
|
-
)
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
console.log('Updated helperFooterRef:', helperFooterRef.current)
|
|
485
|
-
setHelperFooterValue({ ...helperFooterRef.current })
|
|
486
|
-
console.log('Helper footer updated in state')
|
|
487
|
-
}
|
|
488
|
-
|
|
489
500
|
const validateRequiredField = useCallback(
|
|
490
501
|
(required: boolean, formname: string, name: string, label: string) => {
|
|
491
|
-
console.log(
|
|
492
|
-
required,
|
|
493
|
-
formname,
|
|
494
|
-
name,
|
|
495
|
-
label,
|
|
496
|
-
})
|
|
502
|
+
console.log(`Validating required field: ${name}`)
|
|
497
503
|
if (required && formname && name && label) {
|
|
498
|
-
console.log('validateRequiredField: Validating required field')
|
|
499
504
|
const emptyFormData = new FormData()
|
|
500
505
|
emptyFormData.append(name, '')
|
|
501
506
|
validateField(name, emptyFormData, label, required, formname)
|
|
502
|
-
} else {
|
|
503
|
-
console.log(
|
|
504
|
-
'validateRequiredField: Not validating (missing required props)'
|
|
505
|
-
)
|
|
506
507
|
}
|
|
507
508
|
},
|
|
508
509
|
[validateField]
|
|
@@ -511,27 +512,69 @@ export const useHelperFooter = () => {
|
|
|
511
512
|
const useShowErrorEffect = (
|
|
512
513
|
formSubmitted: boolean,
|
|
513
514
|
hasInput: boolean,
|
|
514
|
-
isFocused: boolean
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
isFocused: boolean
|
|
516
|
+
): boolean => {
|
|
517
|
+
const [showError, setShowError] = useState<boolean>(false)
|
|
518
|
+
|
|
517
519
|
useEffect(() => {
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
setShowError(showError)
|
|
525
|
-
}, [formSubmitted, hasInput, isFocused, setShowError])
|
|
520
|
+
const shouldShowError = formSubmitted || (hasInput && !isFocused)
|
|
521
|
+
setShowError(shouldShowError)
|
|
522
|
+
console.log('Show error state updated:', shouldShowError)
|
|
523
|
+
}, [formSubmitted, hasInput, isFocused])
|
|
524
|
+
|
|
525
|
+
return showError
|
|
526
526
|
}
|
|
527
527
|
|
|
528
|
+
const fetchHelperFooters = useCallback(
|
|
529
|
+
async (formname: string): Promise<HelperFooterMessage[]> => {
|
|
530
|
+
console.log(`Fetching helper footers for ${formname}`)
|
|
531
|
+
const helperFooters = await get('helperfooter', formname, 'client')
|
|
532
|
+
if (
|
|
533
|
+
helperFooters &&
|
|
534
|
+
typeof helperFooters === 'object' &&
|
|
535
|
+
'type' in helperFooters &&
|
|
536
|
+
helperFooters.type === 'json' &&
|
|
537
|
+
'value' in helperFooters &&
|
|
538
|
+
typeof helperFooters.value === 'object' &&
|
|
539
|
+
helperFooters.value !== null
|
|
540
|
+
) {
|
|
541
|
+
const value = helperFooters.value as Record<string, unknown>
|
|
542
|
+
return Object.values(value).filter(
|
|
543
|
+
(item): item is HelperFooterMessage => {
|
|
544
|
+
return (
|
|
545
|
+
typeof item === 'object' &&
|
|
546
|
+
item !== null &&
|
|
547
|
+
'status' in item &&
|
|
548
|
+
'statusMessage' in item &&
|
|
549
|
+
'spreadMessage' in item &&
|
|
550
|
+
'spreadMessagePriority' in item &&
|
|
551
|
+
'required' in item
|
|
552
|
+
)
|
|
553
|
+
}
|
|
554
|
+
)
|
|
555
|
+
}
|
|
556
|
+
return []
|
|
557
|
+
},
|
|
558
|
+
[]
|
|
559
|
+
)
|
|
560
|
+
|
|
528
561
|
return useMemo(
|
|
529
562
|
() => ({
|
|
530
563
|
validateField,
|
|
531
564
|
validateRequiredField,
|
|
532
565
|
helperFooterValue,
|
|
533
566
|
useShowErrorEffect,
|
|
567
|
+
initializeRequiredFields,
|
|
568
|
+
fetchHelperFooters,
|
|
534
569
|
}),
|
|
535
|
-
[
|
|
570
|
+
[
|
|
571
|
+
validateField,
|
|
572
|
+
validateRequiredField,
|
|
573
|
+
helperFooterValue,
|
|
574
|
+
initializeRequiredFields,
|
|
575
|
+
fetchHelperFooters,
|
|
576
|
+
]
|
|
536
577
|
)
|
|
537
578
|
}
|
|
579
|
+
|
|
580
|
+
export default useHelperFooter
|