Skip to content

Commit f4c067f

Browse files
Merge pull request #5082 from OneCommunityGlobal/development
Frontend Release to Main [4.83]
2 parents fc2c32d + db55395 commit f4c067f

43 files changed

Lines changed: 2378 additions & 1325 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
"html2canvas": "^1.4.1",
6666
"jest": "^30.2.0",
6767
"jquery": "^3.7.1",
68-
"jspdf": "^4.2.0",
68+
"jspdf": "^4.2.1",
6969
"jwt-decode": "^2.2.0",
7070
"leaflet": "^1.9.4",
7171
"leaflet.heat": "^0.2.0",

src/actions/allTeamsAction.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export const deleteTeam = teamId => {
182182
* updating the team status
183183
*/
184184
export const updateTeam = (teamName, teamId, isActive, teamCode) => {
185-
const requestData = { teamName, isActive, teamCode };
185+
const requestData = { teamName, isActive, teamCode: teamCode || '' };
186186
const url = ENDPOINTS.TEAM_DATA(teamId);
187187
return async dispatch => {
188188
try {
@@ -236,10 +236,12 @@ export const addTeamMember = (teamId, userId) => {
236236
const requestData = { userId, operation: 'Assign' };
237237
return async dispatch => {
238238
const res = await axios.post(ENDPOINTS.TEAM_USERS(teamId), requestData);
239-
dispatch(teamMemberAddAction({
240-
...res.data.newMember,
241-
addDateTime: new Date().toISOString() //newMember data doesn't have the date - required to update the Date Added column
242-
}));
239+
dispatch(
240+
teamMemberAddAction({
241+
...res.data.newMember,
242+
addDateTime: new Date().toISOString(), //newMember data doesn't have the date - required to update the Date Added column
243+
}),
244+
);
243245
return res.data; // return so caller can await
244246
};
245247
};
@@ -249,7 +251,7 @@ export const updateTeamMemeberVisibility = (teamId, userId, visibility) => {
249251
const updateVisibilityPromise = axios.put(ENDPOINTS.TEAM, updateData);
250252

251253
return async dispatch => {
252-
updateVisibilityPromise
254+
return updateVisibilityPromise
253255
.then(() => {
254256
dispatch(updateVisibilityAction(visibility, userId, teamId));
255257
})
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
import React from 'react';
2+
import { v4 as uuidv4 } from 'uuid';
3+
import styles from './FormPreviewModal.module.css';
4+
5+
/**
6+
* FormPreviewModal Component
7+
* Displays a read-only preview of the form as it will appear to applicants
8+
*
9+
* @param {Object} props - Component props
10+
* @param {boolean} props.isOpen - Whether the modal is open
11+
* @param {Function} props.onClose - Callback to close the modal
12+
* @param {Array} props.formFields - Array of form field objects to display
13+
* @param {string} props.jobTitle - The job title for the form
14+
* @param {boolean} props.darkMode - Dark mode flag
15+
*/
16+
function FormPreviewModal({ isOpen, onClose, formFields, jobTitle, darkMode }) {
17+
if (!isOpen) return null;
18+
19+
// Filter to show only visible fields
20+
const visibleFields = formFields.filter(field => field.visible !== false);
21+
22+
const renderField = (field, index) => {
23+
const { questionText, questionType, options } = field;
24+
25+
switch (questionType) {
26+
case 'textbox':
27+
return (
28+
<div key={uuidv4()} className={styles.previewField}>
29+
<label className={styles.previewLabel}>{questionText}</label>
30+
<input
31+
type="text"
32+
placeholder="Enter text here"
33+
disabled
34+
className={styles.previewInput}
35+
/>
36+
</div>
37+
);
38+
39+
case 'textarea':
40+
return (
41+
<div key={uuidv4()} className={styles.previewField}>
42+
<label className={styles.previewLabel}>{questionText}</label>
43+
<textarea placeholder="Enter text here" disabled className={styles.previewTextarea} />
44+
</div>
45+
);
46+
47+
case 'date':
48+
return (
49+
<div key={uuidv4()} className={styles.previewField}>
50+
<label className={styles.previewLabel}>{questionText}</label>
51+
<input type="date" disabled className={styles.previewInput} />
52+
</div>
53+
);
54+
55+
case 'checkbox':
56+
return (
57+
<div key={uuidv4()} className={styles.previewField}>
58+
<label className={styles.previewLabel}>{questionText}</label>
59+
<div className={styles.previewOptions}>
60+
{options &&
61+
options.map((option, optIdx) => (
62+
<div key={uuidv4()} className={styles.previewOptionItem}>
63+
<input
64+
type="checkbox"
65+
disabled
66+
id={`checkbox-${index}-${optIdx}`}
67+
className={styles.previewCheckbox}
68+
/>
69+
<label
70+
htmlFor={`checkbox-${index}-${optIdx}`}
71+
className={styles.previewOptionLabel}
72+
>
73+
{option}
74+
</label>
75+
</div>
76+
))}
77+
</div>
78+
</div>
79+
);
80+
81+
case 'radio':
82+
return (
83+
<div key={uuidv4()} className={styles.previewField}>
84+
<label className={styles.previewLabel}>{questionText}</label>
85+
<div className={styles.previewOptions}>
86+
{options &&
87+
options.map((option, optIdx) => (
88+
<div key={uuidv4()} className={styles.previewOptionItem}>
89+
<input
90+
type="radio"
91+
disabled
92+
id={`radio-${index}-${optIdx}`}
93+
name={`radio-${index}`}
94+
className={styles.previewRadio}
95+
/>
96+
<label
97+
htmlFor={`radio-${index}-${optIdx}`}
98+
className={styles.previewOptionLabel}
99+
>
100+
{option}
101+
</label>
102+
</div>
103+
))}
104+
</div>
105+
</div>
106+
);
107+
108+
case 'dropdown':
109+
return (
110+
<div key={uuidv4()} className={styles.previewField}>
111+
<label className={styles.previewLabel}>{questionText}</label>
112+
<select disabled className={styles.previewSelect}>
113+
<option>Select an option</option>
114+
{options &&
115+
options.map(option => (
116+
<option key={uuidv4()} value={option}>
117+
{option}
118+
</option>
119+
))}
120+
</select>
121+
</div>
122+
);
123+
124+
default:
125+
return null;
126+
}
127+
};
128+
129+
// Close only when clicking directly on the overlay, not inside the modal container
130+
const handleOverlayClick = event => {
131+
if (event.target === event.currentTarget) {
132+
onClose();
133+
}
134+
};
135+
136+
// Keyboard support for accessibility
137+
const handleOverlayKeyDown = event => {
138+
if (event.key === 'Enter' || event.key === ' ') {
139+
event.preventDefault();
140+
onClose();
141+
}
142+
143+
if (event.key === 'Escape') {
144+
event.preventDefault();
145+
onClose();
146+
}
147+
};
148+
149+
return (
150+
<div
151+
className={`${styles.modalOverlay} ${darkMode ? styles.darkMode : ''}`}
152+
onClick={handleOverlayClick}
153+
onKeyDown={handleOverlayKeyDown}
154+
role="button"
155+
tabIndex={0}
156+
aria-label="Close form preview"
157+
>
158+
<div
159+
className={styles.modalContainer}
160+
role="dialog"
161+
aria-modal="true"
162+
aria-label="Form preview dialog"
163+
>
164+
{/* Modal Header */}
165+
<div className={styles.modalHeader}>
166+
<h2 className={styles.modalTitle}>Preview Form</h2>
167+
<button
168+
className={styles.modalCloseBtn}
169+
onClick={onClose}
170+
aria-label="Close preview"
171+
type="button"
172+
>
173+
&times;
174+
</button>
175+
</div>
176+
177+
{/* Modal Content */}
178+
<div className={styles.modalContent}>
179+
<div className={styles.previewForm}>
180+
<h3 className={styles.previewFormTitle}>
181+
{jobTitle?.toUpperCase() || 'PLEASE CHOOSE AN OPTION'}
182+
</h3>
183+
<p className={styles.previewFormSubtitle}>
184+
This is a preview of how the form will appear to applicants.
185+
</p>
186+
187+
{visibleFields.length === 0 ? (
188+
<div className={styles.previewEmptyMessage}>
189+
<p>No visible fields to display. Please add and enable questions.</p>
190+
</div>
191+
) : (
192+
<div className={styles.previewFieldsContainer}>
193+
{visibleFields.map((field, index) => renderField(field, index))}
194+
</div>
195+
)}
196+
</div>
197+
</div>
198+
199+
{/* Modal Footer */}
200+
<div className={styles.modalFooter}>
201+
<button type="button" className={styles.modalActionBtn} onClick={onClose}>
202+
Close Preview
203+
</button>
204+
<p className={styles.modalFooterNote}>Review the layout, text, and field order above.</p>
205+
</div>
206+
</div>
207+
</div>
208+
);
209+
}
210+
211+
export default FormPreviewModal;

0 commit comments

Comments
 (0)