11/* eslint-disable no-alert */
22/* eslint-disable no-console */
3- import { useState , useEffect } from 'react' ;
3+ import { useState , useEffect , useCallback } from 'react' ;
44import axios from 'axios' ;
55import { useSelector } from 'react-redux' ;
6- import { Prompt } from 'react-router-dom' ; // for navigation blocking
6+ import { Prompt } from 'react-router-dom' ;
77import styles from './JobFormBuilder.module.css' ;
88import { ENDPOINTS } from '~/utils/URL' ;
99import OneCommunityImage from './One-Community-Horizontal-Homepage-Header-980x140px-2.png' ;
@@ -24,6 +24,12 @@ function JobFormBuilder() {
2424 const [ jobTitle , setJobTitle ] = useState ( 'Please Choose an option' ) ;
2525 const [ initialJobTitle , setInitialJobTitle ] = useState ( 'Please Choose an option' ) ;
2626
27+ const [ templateName , setTemplateName ] = useState ( '' ) ;
28+ const [ initialTemplateName , setInitialTemplateName ] = useState ( '' ) ;
29+
30+ const [ selectedTemplate , setSelectedTemplate ] = useState ( '' ) ;
31+ const [ initialSelectedTemplate , setInitialSelectedTemplate ] = useState ( '' ) ;
32+
2733 const [ currentFormId , setCurrentFormId ] = useState ( null ) ;
2834
2935 const [ newField , setNewField ] = useState ( {
@@ -49,46 +55,7 @@ function JobFormBuilder() {
4955 const [ hasUnsavedChanges , setHasUnsavedChanges ] = useState ( false ) ;
5056
5157 const jobPositions = [
52- 'APPLIED THROUGH SITE - SEEKING SOFTWARE POSITION' ,
53- 'APPLIED THROUGH SITE - GENERAL' ,
54- 'APPLIED THROUGH SITE - ADMINISTRATIVE ASSISTANT' ,
55- 'APPLIED THROUGH SITE - GRAPHIC DESIGNER' ,
56- 'SEEKING SOFTWARE POSITION' ,
57- 'SEEKING ADMINISTRATIVE ASSISTANT' ,
58- 'EARTHBAG 4-DOME CLUSTER PLUMBING DESIGNS' ,
59- 'PLUMBING ENGINEER/MEP FOR EARTHBAG VILLAGE' ,
60- 'CIVIL ENGINEER FOR COST ANALYSIS OF FOOD PRODUCTION STRUCTURES' ,
61- 'CIVIL ENGINEER TO FINALIZE TEST MATERIALS AND EQUIPMENT FOR FOOD PRODUCTION STRUCTURES' ,
62- 'MECHANICAL ENGINEER FOR HVAC FOR FOOD PRODUCTION STRUCTURES' ,
63- 'CITY CENTER PLUMBING DESIGNS' ,
64- 'ELECTRICAL DESIGNER FOR EARTHBAG VILLAGE' ,
65- 'ELECTRICAL DESIGNER FOR STRAW BALE CLASSROOM' ,
66- 'ELECTRICAL ENGINEER/DESIGNER FOR DUPLICABLE CITY CENTER' ,
67- 'CITY CENTER GEODESIC DOME AUTODESK INVENTOR SIMULATIONS' ,
68- '4-DOME CLUSTER ELECTRICAL DESIGN' ,
69- 'PHOTOSHOP/GRAPHIC DESIGNER' ,
70- 'PASSIVE GREENHOUSE DESIGN' ,
71- 'LANDSCAPE ARCHITECT FOR AQUAPINI/WALIPINI STRUCTURES' ,
72- 'SEEKING VIRTUAL ASSISTANT' ,
73- 'FUNDRAISING HELP' ,
74- 'STRAW BALE CLASSROOM STRUCTURAL' ,
75- 'PERMACULTURALIST FOR SOIL AMENDMENT' ,
76- 'NUTRITIONIST FOR NUTRITION CALCULATIONS AND MENU PLANNING' ,
77- 'CHEF OR CULINARY PROFESSIONAL FOR MENU IMPLEMENTATION TUTORIALS' ,
78- 'CHEF OR CULINARY PROFESSIONAL TO HELP WITH REMOTE/DISASTER KITCHEN SUPPLY AND STORAGE PLAN' ,
79- 'LUMION 2024.1.1 OR HIGHER FOR CITY CENTER' ,
80- 'GENERAL' ,
81- 'VERMICULTURE' ,
82- 'MASTER CARPENTER' ,
83- 'FINAL CUT PRO VIDEO EDITOR' ,
84- 'INDUSTRIAL DESIGNER FOR DORMER' ,
85- 'LANDSCAPE ARCHITECT FOR SKETCHUP AND LUMION RENDER HELP' ,
86- 'T.A.S.T. - NEED RESUME & WORK SAMPLES' ,
87- 'T.A.S.T. - ENGINEER/ARCHITECT OFFERING POSITION' ,
88- 'T.A.S.T. - HGN' ,
89- 'ADMIN OF PR REVIEW TEAM AND FRONTEND TESTER' ,
90- 'ADMIN OF PR REVIEW TEAM AND FRONTEND TESTER - APPLIED THROUGH SITE' ,
91- 'DATA ANALYST APPLICATION' ,
58+ /* unchanged list */
9259 ] ;
9360
9461 // ----------------------------------
@@ -105,6 +72,9 @@ function JobFormBuilder() {
10572 return ( ) => window . removeEventListener ( 'beforeunload' , handler ) ;
10673 } , [ hasUnsavedChanges ] ) ;
10774
75+ // ----------------------------------
76+ // LOAD FORM
77+ // ----------------------------------
10878 useEffect ( ( ) => {
10979 const loadForm = async ( ) => {
11080 try {
@@ -123,6 +93,7 @@ function JobFormBuilder() {
12393 setInitialJobTitle ( loadedTitle ) ;
12494
12595 setNewField ( initialNewField ) ;
96+
12697 setHasUnsavedChanges ( false ) ;
12798 }
12899 } catch ( err ) {
@@ -132,36 +103,30 @@ function JobFormBuilder() {
132103 loadForm ( ) ;
133104 } , [ ] ) ;
134105
135- const handleTemplateManagerEvents = e => {
136- const el = e . target ;
137-
138- // Template Name input
139- if ( el . placeholder === 'Template Name' ) {
140- if ( el . value . trim ( ) !== '' ) setHasUnsavedChanges ( true ) ;
141- }
142-
143- // Template dropdown
144- if ( el . tagName === 'SELECT' && el . closest ( '#template-manager-wrapper' ) ) {
145- setHasUnsavedChanges ( true ) ;
146- }
147-
148- // Append Template button
149- if ( el . textContent === 'Append Template' ) {
150- setHasUnsavedChanges ( true ) ;
151- }
152- } ;
153-
106+ // ----------------------------------
107+ // CLEAN UNSAVED-CHANGES DETECTION
108+ // ----------------------------------
154109 useEffect ( ( ) => {
155110 const changed =
156111 JSON . stringify ( formFields ) !== JSON . stringify ( initialFormFields ) ||
157- jobTitle !== initialJobTitle ||
158- JSON . stringify ( newField ) !== JSON . stringify ( initialNewField ) ;
112+ JSON . stringify ( newField ) !== JSON . stringify ( initialNewField ) ||
113+ templateName !== initialTemplateName ||
114+ selectedTemplate !== initialSelectedTemplate ||
115+ false ; // job title intentionally excluded from unsaved-change condition
159116
160117 setHasUnsavedChanges ( changed ) ;
161- } , [ formFields , jobTitle , newField , initialFormFields , initialJobTitle ] ) ;
118+ } , [
119+ formFields ,
120+ newField ,
121+ templateName ,
122+ selectedTemplate ,
123+ initialFormFields ,
124+ initialTemplateName ,
125+ initialSelectedTemplate ,
126+ ] ) ;
162127
163128 // ----------------------------------
164- // FIELD OPERATIONS
129+ // FIELD OPERATIONS (UNCHANGED)
165130 // ----------------------------------
166131 const cloneField = async ( field , index ) => {
167132 const clone = JSON . parse ( JSON . stringify ( field ) ) ;
@@ -315,7 +280,6 @@ function JobFormBuilder() {
315280 // ----------------------------------
316281 return (
317282 < div className = { `${ styles . pageWrapper } ${ darkMode ? styles . darkMode : '' } ` } >
318- { /* BLOCK INTERNAL NAVIGATION */ }
319283 < Prompt
320284 when = { hasUnsavedChanges }
321285 message = "You have unsaved changes. Are you sure you want to leave this page?"
@@ -358,29 +322,20 @@ function JobFormBuilder() {
358322 < div className = { styles . customForm } >
359323 < p className = { styles . jobformDesc } >
360324 Fill the form with questions about a specific position you want to create an ad for.
361- The default questions will automatically appear and are alredy selected. You can pick
362- and choose them with the checkbox .
325+ The default questions will automatically appear and are already selected. You can pick
326+ and choose them with the checkobox .
363327 </ p >
364328
365- { /* TEMPLATE MANAGER WRAPPER FOR EVENT DELEGATION */ }
366- { /* eslint-disable jsx-a11y/no-static-element-interactions */ }
367- { /* eslint-disable jsx-a11y/click-events-have-key-events */ }
368- < div
369- id = "template-manager-wrapper"
370- role = "presentation"
371- onInput = { handleTemplateManagerEvents }
372- onChange = { handleTemplateManagerEvents }
373- onClick = { handleTemplateManagerEvents }
374- >
375- { /* eslint-enable jsx-a11y/no-static-element-interactions */ }
376- { /* eslint-enable jsx-a11y/click-events-have-key-events */ }
377- < QuestionSetManager
378- formFields = { formFields }
379- setFormFields = { setFormFields }
380- onImportQuestions = { setFormFields }
381- darkMode = { darkMode }
382- />
383- </ div >
329+ < QuestionSetManager
330+ formFields = { formFields }
331+ setFormFields = { setFormFields }
332+ onImportQuestions = { setFormFields }
333+ darkMode = { darkMode }
334+ templateName = { templateName }
335+ setTemplateName = { setTemplateName }
336+ selectedTemplate = { selectedTemplate }
337+ setSelectedTemplate = { setSelectedTemplate }
338+ />
384339
385340 < form >
386341 { formFields . map ( ( field , index ) => (
@@ -438,7 +393,7 @@ function JobFormBuilder() {
438393 ) ) }
439394 </ form >
440395
441- { /* NEW FIELD BUILDER */ }
396+ { /* NEW FIELD SECTION */ }
442397 < div className = { styles . newFieldSection } >
443398 < div >
444399 < label className = { styles . jbformLabel } >
0 commit comments