Skip to content

Commit a6e161d

Browse files
committed
Update comment
1 parent e32e435 commit a6e161d

File tree

8 files changed

+256
-92
lines changed

8 files changed

+256
-92
lines changed

src/components/comments/comment-form.js

+51-90
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { useState } from 'react';
2-
import Error from './error';
32
import validateAndSanitizeCommentsForm from '../../validator/comments';
3+
import TextArea from '../form-elements/text-area';
4+
import Input from '../form-elements/input';
5+
import Checkbox from '../form-elements/checkbox';
46

57
const CommentForm = () => {
68

7-
const [ input, setInput ] = useState( {} );
9+
const [ input, setInput ] = useState( { wp_comment_cookies_consent: false } );
810

911
const handleFormSubmit = ( event ) => {
1012
event.preventDefault();
1113

1214
const commentFormValidationResult = validateAndSanitizeCommentsForm( input );
13-
console.log( 'commentFormValidationResult', commentFormValidationResult, input );
1415

1516
setInput( {
1617
...input,
@@ -34,8 +35,8 @@ const CommentForm = () => {
3435
*/
3536
const handleOnChange = ( event ) => {
3637
const { target } = event || {};
37-
38-
const newState = { ...input, [ target.name ]: target.value };
38+
console.log( 'target.type', target.type );
39+
const newState = 'checkbox' === target.type ? { ...input, [ target.name ]: ! input[target.name] } : { ...input, [ target.name ]: target.value };
3940
setInput( newState );
4041
};
4142

@@ -46,95 +47,55 @@ const CommentForm = () => {
4647
<span id="email-notes">Your email address will not be published.</span>
4748
<span className="required-field-message">Required fields are marked <span className="required">*</span></span>
4849
</p>
49-
<div className="comment-form-comment mb-2">
50-
<label htmlFor="comment" className="block mb-2 font-medium text-gray-900 dark:text-white">
51-
Comment
52-
<span className="required">*</span>
53-
</label>
54-
<textarea
55-
id="comment"
56-
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
57-
name="comment"
58-
cols="45"
59-
rows="5"
60-
maxLength="65525"
61-
required
62-
value={ input?.comment ?? '' }
63-
onChange={ ( event ) => handleOnChange( event ) }
64-
/>
65-
<Error errors={ input?.errors ?? {} } fieldName="comment"/>
66-
</div>
50+
<TextArea
51+
id="comment"
52+
containerClassNames="comment-form-comment mb-2"
53+
name="comment"
54+
label="Comment"
55+
cols="45"
56+
rows="5"
57+
required
58+
textAreaValue={ input?.comment ?? '' }
59+
handleOnChange={ handleOnChange }
60+
errors={ input?.errors ?? {} }
61+
/>
6762
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-2">
68-
<div className="comment-form-author">
69-
<label htmlFor="author" className="block mb-2 font-medium text-gray-900 dark:text-white">
70-
Name
71-
<span className="required">*</span>
72-
</label>
73-
<input
74-
id="author"
75-
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 w-full block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
76-
name="author"
77-
type="text"
78-
size="30"
79-
maxLength="245"
80-
autoComplete="name"
81-
required=""
82-
value={ input?.author ?? '' }
83-
onChange={ ( event ) => handleOnChange( event ) }
84-
/>
85-
<Error errors={ input?.errors ?? {} } fieldName="author"/>
86-
</div>
87-
<div className="comment-form-email border-0 mb-2">
88-
<label htmlFor="email" className="block mb-2 font-medium text-gray-900 dark:text-white">
89-
Email
90-
<span className="required">*</span>
91-
</label>
92-
<input
93-
id="email"
94-
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 w-full block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
95-
name="email"
96-
type="email"
97-
size="30"
98-
maxLength="100"
99-
aria-describedby="email-notes"
100-
autoComplete="email"
101-
required
102-
value={ input?.email ?? '' }
103-
onChange={ ( event ) => handleOnChange( event ) }
104-
/>
105-
<Error errors={ input?.errors ?? {} } fieldName="email"/>
106-
</div>
107-
</div>
108-
<div className="comment-form-url mb-2">
109-
<label htmlFor="url" className="block mb-2 font-medium text-gray-900 dark:text-white">
110-
Website
111-
</label>
112-
<input
113-
id="url"
114-
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
115-
name="url"
116-
type="url"
117-
size="30"
118-
maxLength="200"
119-
autoComplete="url"
120-
value={ input?.url ?? '' }
121-
onChange={ ( event ) => handleOnChange( event ) }
63+
<Input
64+
name="author"
65+
inputValue={ input?.author }
66+
required
67+
handleOnChange={ handleOnChange }
68+
label="Name"
69+
errors={ input?.errors ?? {} }
70+
containerClassNames="comment-form-author"
12271
/>
123-
<Error errors={ input?.errors ?? {} } fieldName="url"/>
124-
</div>
125-
<div className="comment-form-cookies-consent mb-4">
126-
<input
127-
id="wp-comment-cookies-consent"
128-
name="wp_comment_cookies_consent"
129-
type="checkbox"
130-
value="yes"
131-
onChange={ ( event ) => handleOnChange( event ) }
72+
<Input
73+
name="email"
74+
inputValue={ input?.email }
75+
required
76+
handleOnChange={ handleOnChange }
77+
label="Email"
78+
errors={ input?.errors ?? {} }
79+
containerClassNames="comment-form-email mb-2"
13280
/>
133-
<label htmlFor="wp-comment-cookies-consent" className="mb-2 ml-2 font-medium text-gray-900 dark:text-white">
134-
Save my name, email, and website in this browser for the next time I comment.
135-
</label>
136-
<Error errors={ input?.errors ?? {} } fieldName="wp_comment_cookies_consent"/>
13781
</div>
82+
<Input
83+
name="url"
84+
inputValue={ input?.url }
85+
required
86+
handleOnChange={ handleOnChange }
87+
label="Website"
88+
errors={ input?.errors ?? {} }
89+
containerClassNames="comment-form-url mb-2"
90+
/>
91+
<Checkbox
92+
name="wp_comment_cookies_consent"
93+
checked={ input.wp_comment_cookies_consent }
94+
handleOnChange={ handleOnChange }
95+
label="Save my name, email, and website in this browser for the next time I comment."
96+
errors={ input?.errors ?? {} }
97+
containerClassNames="comment-form-url mb-2"
98+
/>
13899
<div className="form-submit">
139100
<input name="submit" type="submit" id="submit" className=" cursor-pointer text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-16px uppercase w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" value="Post Comment"/>
140101
<input type="hidden" name="comment_post_ID" value="377" id="comment_post_ID"/>

src/components/comments/comment.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ const Comment = ( { comment } ) => {
3939
<svg aria-hidden="true" className="mr-1 w-4 h-4" fill="none" stroke="currentColor"
4040
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
4141
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
42-
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"></path>
42+
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z">
43+
</path>
4344
</svg>
4445
Reply
4546
</button>

src/components/form-elements/abbr.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import PropTypes from 'prop-types';
2+
3+
const Abbr = ({required}) => {
4+
if ( !required ) {
5+
return null;
6+
}
7+
8+
return <abbr className="text-red-500" style={{textDecoration: 'none'}} title="required">*</abbr>
9+
}
10+
11+
Abbr.propTypes = {
12+
required: PropTypes.bool
13+
}
14+
15+
Abbr.defaultProps = {
16+
required: false
17+
}
18+
19+
export default Abbr
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import PropTypes from 'prop-types';
2+
import Error from './error';
3+
import Abbr from './abbr';
4+
5+
const Checkbox = ( { handleOnChange, checked, name, errors, required, label, placeholder, containerClassNames, inputValue } ) => {
6+
7+
return (
8+
<div className={ containerClassNames }>
9+
<label className="leading-7 text-md text-gray-700 flex items-center cursor-pointer" htmlFor={ name }>
10+
<input
11+
type="checkbox"
12+
onChange={ handleOnChange }
13+
placeholder={ placeholder }
14+
checked={ checked }
15+
name={ name }
16+
id={ name }
17+
value={ checked }
18+
/>
19+
<span className="ml-2">{ label || '' }</span>
20+
<Abbr required={ required }/>
21+
</label>
22+
<Error errors={ errors } fieldName={ name }/>
23+
</div>
24+
);
25+
};
26+
27+
Checkbox.propTypes = {
28+
handleOnChange: PropTypes.func,
29+
checked: PropTypes.bool,
30+
name: PropTypes.string,
31+
type: PropTypes.string,
32+
errors: PropTypes.object,
33+
label: PropTypes.string,
34+
placeholder: PropTypes.string,
35+
containerClassNames: PropTypes.string,
36+
};
37+
38+
Checkbox.defaultProps = {
39+
handleOnChange: () => null,
40+
checked: false,
41+
name: '',
42+
label: '',
43+
placeholder: '',
44+
errors: {},
45+
containerClassNames: '',
46+
};
47+
48+
export default Checkbox;

src/components/form-elements/error.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const Error = ( { errors, fieldName } ) => {
2+
3+
return(
4+
errors && ( errors.hasOwnProperty( fieldName ) ) ? (
5+
<div className="invalid-feedback d-block text-red-500">{ errors[fieldName] }</div>
6+
) : ''
7+
)
8+
};
9+
10+
export default Error;

src/components/form-elements/input.js

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import Error from './error';
2+
import PropTypes from 'prop-types';
3+
import Abbr from './abbr';
4+
5+
const Input = ( {
6+
handleOnChange,
7+
inputValue,
8+
name,
9+
type,
10+
label,
11+
errors,
12+
placeholder,
13+
required,
14+
containerClassNames,
15+
inputId,
16+
} ) => {
17+
18+
return (
19+
<div className={ containerClassNames }>
20+
<label className="leading-7 text-sm text-gray-700" htmlFor={ inputId }>
21+
{ label || '' }
22+
<Abbr required={ required }/>
23+
</label>
24+
<input
25+
onChange={ handleOnChange }
26+
value={ inputValue || '' }
27+
placeholder={ placeholder || '' }
28+
type={ type || 'text' }
29+
name={ name || '' }
30+
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 w-full block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
31+
id={ inputId || name }
32+
/>
33+
<Error errors={ errors } fieldName={ name }/>
34+
</div>
35+
);
36+
};
37+
38+
Input.propTypes = {
39+
handleOnChange: PropTypes.func,
40+
inputValue: PropTypes.string,
41+
name: PropTypes.string,
42+
type: PropTypes.string,
43+
label: PropTypes.string,
44+
placeholder: PropTypes.string,
45+
errors: PropTypes.object,
46+
required: PropTypes.bool,
47+
containerClassNames: PropTypes.string,
48+
};
49+
50+
Input.defaultProps = {
51+
handleOnChange: () => null,
52+
inputValue: '',
53+
name: '',
54+
type: 'text',
55+
label: '',
56+
placeholder: '',
57+
errors: {},
58+
required: false,
59+
containerClassNames: '',
60+
};
61+
62+
export default Input;
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import Error from './error';
2+
import PropTypes from 'prop-types';
3+
import Abbr from './abbr';
4+
5+
const TextArea = ( {
6+
handleOnChange,
7+
textAreaValue,
8+
name,
9+
label,
10+
errors,
11+
placeholder,
12+
required,
13+
containerClassNames,
14+
textAreaId,
15+
cols,
16+
rows,
17+
maxLength
18+
} ) => {
19+
20+
return (
21+
<div className={ containerClassNames }>
22+
<label className="leading-7 text-sm text-gray-700" htmlFor={ textAreaId }>
23+
{ label || '' }
24+
<Abbr required={ required }/>
25+
</label>
26+
<textarea
27+
onChange={ handleOnChange }
28+
value={ textAreaValue || '' }
29+
placeholder={ placeholder || '' }
30+
cols={ cols || 45 }
31+
rows={ rows || 5 }
32+
maxLength={ maxLength || 65525 }
33+
name={ name || '' }
34+
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
35+
id={ textAreaId || name }
36+
/>
37+
<Error errors={ errors } fieldName={ name }/>
38+
</div>
39+
);
40+
};
41+
42+
TextArea.propTypes = {
43+
handleOnChange: PropTypes.func,
44+
textAreaValue: PropTypes.string,
45+
name: PropTypes.string,
46+
label: PropTypes.string,
47+
placeholder: PropTypes.string,
48+
errors: PropTypes.object,
49+
required: PropTypes.bool,
50+
containerClassNames: PropTypes.string,
51+
};
52+
53+
TextArea.defaultProps = {
54+
handleOnChange: () => null,
55+
textAreaValue: '',
56+
name: '',
57+
label: '',
58+
placeholder: '',
59+
errors: {},
60+
required: false,
61+
containerClassNames: '',
62+
};
63+
64+
export default TextArea;

src/validator/comments.js

-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ const validateAndSanitizeCommentsForm = ( data ) => {
6666
addErrorAndSanitizedData( 'author', 'Author Name', 0, 35, 'string', true );
6767
addErrorAndSanitizedData( 'email', 'Email', 11, 254, 'email', true );
6868
addErrorAndSanitizedData( 'url', 'Site URL', 2, 55, 'url', false );
69-
addErrorAndSanitizedData( 'wp_comment_cookies_consent', '', 0, 3, 'string', false );
7069

7170
return {
7271
sanitizedData,

0 commit comments

Comments
 (0)