goobs-frontend 0.7.64 → 0.7.65
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 +14 -14
- package/src/components/Button/hook/useHelperFooter.tsx +174 -201
- package/src/components/Button/index.tsx +208 -162
- package/src/components/ConfirmationCodeInput/index.tsx +7 -9
- package/src/components/Nav/HorizontalVariant/index.tsx +13 -39
- package/src/components/StyledComponent/hooks/useInputHelperFooter.tsx +567 -0
- package/src/components/StyledComponent/hooks/useRequiredFieldsValidator.tsx +137 -0
- package/src/components/StyledComponent/index.tsx +26 -31
- package/src/components/TransferList/index.tsx +12 -4
- package/src/components/StyledComponent/helperfooter/useHelperFooter.tsx +0 -638
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "goobs-frontend",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.65",
|
|
4
4
|
"description": "A comprehensive React-based UI library built on Material-UI, offering a wide range of customizable components including grids, typography, buttons, cards, forms, navigation, pricing tables, steppers, tooltips, accordions, and more. Designed for building responsive and consistent user interfaces with advanced features like form validation, theming, and code syntax highlighting.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -22,32 +22,32 @@
|
|
|
22
22
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@emotion/cache": "^11.
|
|
26
|
-
"@emotion/react": "^11.
|
|
27
|
-
"@emotion/styled": "^11.
|
|
28
|
-
"@mui/icons-material": "^5.16.
|
|
29
|
-
"@mui/material": "^5.16.
|
|
30
|
-
"@types/lodash": "^4.17.
|
|
31
|
-
"goobs-cache": "^1.4
|
|
25
|
+
"@emotion/cache": "^11.13.1",
|
|
26
|
+
"@emotion/react": "^11.13.0",
|
|
27
|
+
"@emotion/styled": "^11.13.0",
|
|
28
|
+
"@mui/icons-material": "^5.16.6",
|
|
29
|
+
"@mui/material": "^5.16.6",
|
|
30
|
+
"@types/lodash": "^4.17.7",
|
|
31
|
+
"goobs-cache": "^1.6.4",
|
|
32
32
|
"highlight.js": "^11.10.0",
|
|
33
33
|
"lodash": "^4.17.21",
|
|
34
34
|
"next": "14.2.5"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@next/eslint-plugin-next": "^14.2.5",
|
|
38
|
-
"@types/node": "^
|
|
38
|
+
"@types/node": "^22.1.0",
|
|
39
39
|
"@types/react": "18.3.3",
|
|
40
40
|
"@types/react-dom": "^18.3.0",
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
42
|
-
"@typescript-eslint/parser": "^
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
|
42
|
+
"@typescript-eslint/parser": "^8.0.1",
|
|
43
43
|
"eslint": "^8.57.0",
|
|
44
44
|
"eslint-config-next": "^14.2.5",
|
|
45
45
|
"eslint-config-prettier": "^9.1.0",
|
|
46
|
-
"eslint-plugin-prettier": "^5.1
|
|
47
|
-
"prettier": "^3.3.
|
|
46
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
47
|
+
"prettier": "^3.3.3",
|
|
48
48
|
"react": "^18.3.1",
|
|
49
49
|
"react-dom": "^18.3.1",
|
|
50
|
-
"typescript": "^5.5.
|
|
50
|
+
"typescript": "^5.5.4"
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
"src"
|
|
@@ -1,251 +1,224 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useCallback, useMemo } from 'react'
|
|
2
|
+
import { session } from 'goobs-cache'
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Represents the structure of a helper footer message.
|
|
6
|
-
* @interface HelperFooterMessage
|
|
7
|
-
*/
|
|
8
4
|
export interface HelperFooterMessage {
|
|
9
|
-
|
|
10
|
-
status: 'error' | 'success'
|
|
11
|
-
/** A message describing the status. */
|
|
5
|
+
status: 'error' | 'success' | 'emptyAndRequired'
|
|
12
6
|
statusMessage: string
|
|
13
|
-
/** A message to be displayed to the user. */
|
|
14
7
|
spreadMessage: string
|
|
15
|
-
/** A number indicating the priority of the message. Lower numbers indicate higher priority. */
|
|
16
8
|
spreadMessagePriority: number
|
|
17
|
-
/** The name of the form associated with this message. */
|
|
18
|
-
formname: string
|
|
19
|
-
/** Indicates whether this message is required to be addressed. */
|
|
20
9
|
required: boolean
|
|
10
|
+
hasInput?: boolean
|
|
21
11
|
}
|
|
22
12
|
|
|
23
|
-
/**
|
|
24
|
-
* A type definition for the interval ID returned by setInterval.
|
|
25
|
-
*/
|
|
26
|
-
type IntervalID = ReturnType<typeof setInterval>
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A custom hook for managing helper footer messages and form validation.
|
|
30
|
-
*
|
|
31
|
-
* @param {string} [initialFormname] - The initial name of the form to fetch helper footers for.
|
|
32
|
-
* @returns {Object} An object containing the current error message, form validity state, and functions to update and fetch form validation.
|
|
33
|
-
*/
|
|
34
13
|
const useHelperFooter = (initialFormname?: string) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const [errorMessage, setErrorMessage] = useState<string | undefined>(
|
|
39
|
-
undefined
|
|
14
|
+
console.log(
|
|
15
|
+
'useHelperFooter: Hook called with initialFormname:',
|
|
16
|
+
initialFormname
|
|
40
17
|
)
|
|
41
18
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Ref for storing the previous error message to compare against.
|
|
59
|
-
*/
|
|
60
|
-
const prevErrorMessage = useRef<string | undefined>(undefined)
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Ref for storing the previous form validity to compare against.
|
|
64
|
-
*/
|
|
65
|
-
const prevIsFormValid = useRef<boolean>(true)
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Ref for storing the interval ID for periodic helper footer fetching.
|
|
69
|
-
*/
|
|
70
|
-
const intervalIdRef = useRef<IntervalID | null>(null)
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Fetches helper footer messages from the cache.
|
|
74
|
-
*
|
|
75
|
-
* @param {string} [formname] - The name of the form to fetch helper footers for.
|
|
76
|
-
* @returns {Promise<HelperFooterMessage[]>} A promise that resolves to an array of HelperFooterMessage objects.
|
|
77
|
-
*/
|
|
78
|
-
const fetchHelperFooters = useCallback(
|
|
79
|
-
async (formname?: string): Promise<HelperFooterMessage[]> => {
|
|
80
|
-
const currentFormname = formname || initialFormname
|
|
81
|
-
if (!currentFormname) {
|
|
82
|
-
return []
|
|
83
|
-
}
|
|
19
|
+
const helperFooterAtom = session.atom<Record<
|
|
20
|
+
string,
|
|
21
|
+
HelperFooterMessage
|
|
22
|
+
> | null>(null)
|
|
23
|
+
const currentErrorIndexAtom = session.atom<number>(0)
|
|
24
|
+
|
|
25
|
+
const fetchHelperFooters = useCallback(async (): Promise<Record<
|
|
26
|
+
string,
|
|
27
|
+
HelperFooterMessage
|
|
28
|
+
> | null> => {
|
|
29
|
+
console.log('useHelperFooter: fetchHelperFooters called')
|
|
30
|
+
if (!initialFormname) {
|
|
31
|
+
console.log('useHelperFooter: No formname provided, returning null')
|
|
32
|
+
return null
|
|
33
|
+
}
|
|
84
34
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
35
|
+
const [helperFooters, setHelperFooters] = session.useAtom(helperFooterAtom)
|
|
36
|
+
|
|
37
|
+
if (helperFooters === null) {
|
|
38
|
+
const [helperFooterResult] = session.useAtom(
|
|
39
|
+
session.atom(`helperfooter:${initialFormname}`)
|
|
89
40
|
)
|
|
41
|
+
console.log('useHelperFooter: helperFooterResult:', helperFooterResult)
|
|
90
42
|
|
|
91
43
|
if (
|
|
92
44
|
helperFooterResult &&
|
|
93
45
|
typeof helperFooterResult === 'object' &&
|
|
94
|
-
|
|
95
|
-
helperFooterResult.type === 'json' &&
|
|
96
|
-
'value' in helperFooterResult &&
|
|
97
|
-
typeof helperFooterResult.value === 'object' &&
|
|
98
|
-
helperFooterResult.value !== null
|
|
46
|
+
helperFooterResult !== null
|
|
99
47
|
) {
|
|
100
|
-
const fetchedHelperFooters =
|
|
101
|
-
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
48
|
+
const fetchedHelperFooters: Record<string, HelperFooterMessage> = {}
|
|
49
|
+
|
|
50
|
+
for (const [key, value] of Object.entries(helperFooterResult)) {
|
|
51
|
+
if (
|
|
52
|
+
typeof value === 'object' &&
|
|
53
|
+
value !== null &&
|
|
54
|
+
'status' in value &&
|
|
55
|
+
'statusMessage' in value &&
|
|
56
|
+
'spreadMessage' in value &&
|
|
57
|
+
'spreadMessagePriority' in value &&
|
|
58
|
+
'required' in value &&
|
|
59
|
+
'hasInput' in value
|
|
60
|
+
) {
|
|
61
|
+
fetchedHelperFooters[key] = {
|
|
62
|
+
status: value.status as 'error' | 'success' | 'emptyAndRequired',
|
|
63
|
+
statusMessage: String(value.statusMessage),
|
|
64
|
+
spreadMessage: String(value.spreadMessage),
|
|
65
|
+
spreadMessagePriority: Number(value.spreadMessagePriority),
|
|
66
|
+
required: Boolean(value.required),
|
|
67
|
+
hasInput: Boolean(value.hasInput),
|
|
121
68
|
}
|
|
122
|
-
|
|
123
|
-
})
|
|
124
|
-
.filter((value): value is HelperFooterMessage => value !== null)
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
JSON.stringify(fetchedHelperFooters) !==
|
|
128
|
-
JSON.stringify(prevHelperFooters.current)
|
|
129
|
-
) {
|
|
130
|
-
setHelperFooters(fetchedHelperFooters)
|
|
131
|
-
prevHelperFooters.current = fetchedHelperFooters
|
|
69
|
+
}
|
|
132
70
|
}
|
|
71
|
+
|
|
72
|
+
console.log(
|
|
73
|
+
'useHelperFooter: Fetched helper footers:',
|
|
74
|
+
fetchedHelperFooters
|
|
75
|
+
)
|
|
76
|
+
setHelperFooters(fetchedHelperFooters)
|
|
133
77
|
return fetchedHelperFooters
|
|
134
78
|
}
|
|
135
79
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
},
|
|
142
|
-
[initialFormname, helperFooters]
|
|
143
|
-
)
|
|
80
|
+
console.log(
|
|
81
|
+
'useHelperFooter: Invalid helper footer result, returning null'
|
|
82
|
+
)
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
144
85
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
*
|
|
148
|
-
* @param {string} [formname] - The name of the form to update validation for.
|
|
149
|
-
* @returns {Promise<boolean>} A promise that resolves to a boolean indicating whether the form is valid.
|
|
150
|
-
*/
|
|
151
|
-
const updateFormValidation = useCallback(
|
|
152
|
-
async (formname?: string): Promise<boolean> => {
|
|
153
|
-
const fetchedHelperFooters = await fetchHelperFooters(formname)
|
|
154
|
-
|
|
155
|
-
if (fetchedHelperFooters.length === 0) {
|
|
156
|
-
setErrorMessage(undefined)
|
|
157
|
-
setIsFormValid(true)
|
|
158
|
-
return true
|
|
159
|
-
}
|
|
86
|
+
return helperFooters
|
|
87
|
+
}, [initialFormname, helperFooterAtom])
|
|
160
88
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
89
|
+
const updateFormValidation = useCallback(async (): Promise<boolean> => {
|
|
90
|
+
console.log('useHelperFooter: updateFormValidation called')
|
|
91
|
+
const fetchedHelperFooters = await fetchHelperFooters()
|
|
164
92
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
setErrorMessage(highestPriorityError.spreadMessage)
|
|
172
|
-
setIsFormValid(false)
|
|
173
|
-
return false
|
|
174
|
-
}
|
|
93
|
+
if (fetchedHelperFooters) {
|
|
94
|
+
const errorFooters = Object.values(fetchedHelperFooters).filter(
|
|
95
|
+
footer =>
|
|
96
|
+
(footer.status === 'error' || footer.status === 'emptyAndRequired') &&
|
|
97
|
+
footer.required
|
|
98
|
+
)
|
|
175
99
|
|
|
176
|
-
|
|
177
|
-
setIsFormValid(true)
|
|
178
|
-
return true
|
|
179
|
-
},
|
|
180
|
-
[fetchHelperFooters]
|
|
181
|
-
)
|
|
100
|
+
console.log('useHelperFooter: Error footers:', errorFooters)
|
|
182
101
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}, [initialFormname, updateFormValidation])
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Effect to set up periodic helper footer fetching.
|
|
192
|
-
*/
|
|
193
|
-
useEffect(() => {
|
|
194
|
-
if (initialFormname) {
|
|
195
|
-
const fetchAndUpdateHelperFooters = async () => {
|
|
196
|
-
await updateFormValidation(initialFormname)
|
|
102
|
+
if (errorFooters.length === 0) {
|
|
103
|
+
const [, setCurrentErrorIndex] = session.useAtom(currentErrorIndexAtom)
|
|
104
|
+
setCurrentErrorIndex(0)
|
|
105
|
+
console.log('useHelperFooter: No errors found, returning true')
|
|
106
|
+
return true
|
|
197
107
|
}
|
|
198
108
|
|
|
199
|
-
|
|
200
|
-
|
|
109
|
+
errorFooters.sort(
|
|
110
|
+
(a, b) => a.spreadMessagePriority - b.spreadMessagePriority
|
|
111
|
+
)
|
|
201
112
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
113
|
+
const [currentErrorIndex, setCurrentErrorIndex] = session.useAtom(
|
|
114
|
+
currentErrorIndexAtom
|
|
115
|
+
)
|
|
116
|
+
if (currentErrorIndex >= errorFooters.length) {
|
|
117
|
+
setCurrentErrorIndex(0)
|
|
206
118
|
}
|
|
119
|
+
|
|
120
|
+
console.log('useHelperFooter: Errors found, returning false')
|
|
121
|
+
return false
|
|
207
122
|
}
|
|
208
|
-
}, [initialFormname, updateFormValidation])
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Effect to update refs when error message or form validity changes.
|
|
212
|
-
*/
|
|
213
|
-
useEffect(() => {
|
|
214
|
-
if (
|
|
215
|
-
errorMessage !== prevErrorMessage.current ||
|
|
216
|
-
isFormValid !== prevIsFormValid.current
|
|
217
|
-
) {
|
|
218
|
-
prevErrorMessage.current = errorMessage
|
|
219
|
-
prevIsFormValid.current = isFormValid
|
|
220
|
-
}
|
|
221
|
-
}, [errorMessage, isFormValid])
|
|
222
123
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
124
|
+
console.log('useHelperFooter: No helper footers, returning true')
|
|
125
|
+
return true
|
|
126
|
+
}, [fetchHelperFooters, currentErrorIndexAtom])
|
|
127
|
+
|
|
128
|
+
const checkFormStatus = useCallback(async () => {
|
|
129
|
+
console.log('useHelperFooter: checkFormStatus called')
|
|
130
|
+
const fetchedHelperFooters = await fetchHelperFooters()
|
|
131
|
+
const status = fetchedHelperFooters
|
|
132
|
+
? Object.values(fetchedHelperFooters).every(
|
|
133
|
+
value => !value.required || (value.required && value.hasInput)
|
|
134
|
+
)
|
|
135
|
+
: true
|
|
136
|
+
console.log('useHelperFooter: Form status:', status)
|
|
137
|
+
return status
|
|
138
|
+
}, [fetchHelperFooters])
|
|
139
|
+
|
|
140
|
+
const getEmptyRequiredFields = useCallback(async () => {
|
|
141
|
+
console.log('useHelperFooter: getEmptyRequiredFields called')
|
|
142
|
+
const fetchedHelperFooters = await fetchHelperFooters()
|
|
143
|
+
if (!fetchedHelperFooters) return []
|
|
144
|
+
const emptyFields = Object.entries(fetchedHelperFooters)
|
|
145
|
+
.filter(([, value]) => value.required && !value.hasInput)
|
|
146
|
+
.map(([key]) => key)
|
|
147
|
+
console.log('useHelperFooter: Empty required fields:', emptyFields)
|
|
148
|
+
return emptyFields
|
|
149
|
+
}, [fetchHelperFooters])
|
|
150
|
+
|
|
151
|
+
const getCurrentErrorMessage = useCallback(async () => {
|
|
152
|
+
console.log('useHelperFooter: getCurrentErrorMessage called')
|
|
153
|
+
const fetchedHelperFooters = await fetchHelperFooters()
|
|
154
|
+
if (!fetchedHelperFooters) return undefined
|
|
155
|
+
const errorFooters = Object.values(fetchedHelperFooters).filter(
|
|
156
|
+
footer =>
|
|
157
|
+
(footer.status === 'error' || footer.status === 'emptyAndRequired') &&
|
|
158
|
+
footer.required
|
|
159
|
+
)
|
|
160
|
+
if (errorFooters.length === 0) return undefined
|
|
161
|
+
const [currentErrorIndex] = session.useAtom(currentErrorIndexAtom)
|
|
162
|
+
const message = errorFooters[currentErrorIndex]?.spreadMessage
|
|
163
|
+
console.log('useHelperFooter: Current error message:', message)
|
|
164
|
+
return message
|
|
165
|
+
}, [fetchHelperFooters, currentErrorIndexAtom])
|
|
166
|
+
|
|
167
|
+
const isFormValid = useCallback(async () => {
|
|
168
|
+
const fetchedHelperFooters = await fetchHelperFooters()
|
|
169
|
+
if (!fetchedHelperFooters) return true
|
|
170
|
+
const valid = Object.values(fetchedHelperFooters).every(
|
|
171
|
+
footer =>
|
|
172
|
+
footer.status !== 'error' && footer.status !== 'emptyAndRequired'
|
|
173
|
+
)
|
|
174
|
+
console.log('useHelperFooter: isFormValid:', valid)
|
|
175
|
+
return valid
|
|
176
|
+
}, [fetchHelperFooters])
|
|
177
|
+
|
|
178
|
+
const nextError = useCallback(async () => {
|
|
179
|
+
console.log('useHelperFooter: nextError called')
|
|
180
|
+
const fetchedHelperFooters = await fetchHelperFooters()
|
|
181
|
+
if (!fetchedHelperFooters) return
|
|
182
|
+
const errorFooters = Object.values(fetchedHelperFooters).filter(
|
|
183
|
+
footer =>
|
|
184
|
+
(footer.status === 'error' || footer.status === 'emptyAndRequired') &&
|
|
185
|
+
footer.required
|
|
186
|
+
)
|
|
187
|
+
if (errorFooters.length > 0) {
|
|
188
|
+
const [currentErrorIndex, setCurrentErrorIndex] = session.useAtom(
|
|
189
|
+
currentErrorIndexAtom
|
|
190
|
+
)
|
|
191
|
+
setCurrentErrorIndex((currentErrorIndex + 1) % errorFooters.length)
|
|
192
|
+
console.log(
|
|
193
|
+
'useHelperFooter: New error index:',
|
|
194
|
+
(currentErrorIndex + 1) % errorFooters.length
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
}, [fetchHelperFooters, currentErrorIndexAtom])
|
|
227
198
|
|
|
228
|
-
|
|
229
|
-
* Memoized return value of the hook to prevent unnecessary re-renders.
|
|
230
|
-
*/
|
|
231
|
-
const returnValue = useMemo(
|
|
199
|
+
const result = useMemo(
|
|
232
200
|
() => ({
|
|
233
|
-
errorMessage,
|
|
201
|
+
errorMessage: getCurrentErrorMessage,
|
|
234
202
|
isFormValid,
|
|
235
203
|
updateFormValidation,
|
|
236
204
|
fetchHelperFooters,
|
|
237
|
-
|
|
205
|
+
nextError,
|
|
206
|
+
checkFormStatus,
|
|
207
|
+
getEmptyRequiredFields,
|
|
238
208
|
}),
|
|
239
209
|
[
|
|
240
|
-
|
|
210
|
+
getCurrentErrorMessage,
|
|
241
211
|
isFormValid,
|
|
242
212
|
updateFormValidation,
|
|
243
213
|
fetchHelperFooters,
|
|
244
|
-
|
|
214
|
+
nextError,
|
|
215
|
+
checkFormStatus,
|
|
216
|
+
getEmptyRequiredFields,
|
|
245
217
|
]
|
|
246
218
|
)
|
|
247
219
|
|
|
248
|
-
|
|
220
|
+
console.log('useHelperFooter: Returning result:', result)
|
|
221
|
+
return result
|
|
249
222
|
}
|
|
250
223
|
|
|
251
224
|
export default useHelperFooter
|