aboutsummaryrefslogtreecommitdiff
path: root/src/components/BlogCommentsForm.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/BlogCommentsForm.jsx')
-rw-r--r--src/components/BlogCommentsForm.jsx150
1 files changed, 31 insertions, 119 deletions
diff --git a/src/components/BlogCommentsForm.jsx b/src/components/BlogCommentsForm.jsx
index b48236e..d0c585c 100644
--- a/src/components/BlogCommentsForm.jsx
+++ b/src/components/BlogCommentsForm.jsx
@@ -1,124 +1,36 @@
-import { Component } from 'preact';
+import { h } from 'preact';
+import withFormHandling from './FormHandling';
import '../styles/Form.css';
-import { marked } from "marked";
-import DOMPurify from 'dompurify';
-class BlogCommentsForm extends Component {
- state = {
- author: '',
- comment: '',
- isMessageSent: false,
- commentId: ''
- };
-
- componentDidMount() {
- // Ensure the Turnstile script is loaded with explicit rendering
- const script = document.createElement('script');
- script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=onloadTurnstileCallback';
- script.defer = true;
- document.body.appendChild(script);
-
- // Callback function to handle Turnstile token
- window.onloadTurnstileCallback = () => {
- window.turnstile.render('#turnstile-container', {
- sitekey: '0x4AAAAAAAdb4uvxFFzNEDxB',
- callback: (token) => {
- // Here you can handle the token, e.g., by storing it in a hidden form field
- this.setState({turnstileToken: token});
- },
- });
- };
-
- // Cleanup function to remove the script when the component unmounts
- return () => {
- document.body.removeChild(script);
- };
- }
-
- handleChange = (e) => {
- this.setState({ [e.target.name]: e.target.value });
- }
-
- handleSubmit = async (e) => {
- e.preventDefault();
-
- if (this.state.isMessageSent) {
- this.setState({
- errorMessage: 'You have already sent a comment.',
- });
- return;
- }
-
- try {
- const messageHtml = marked(DOMPurify.sanitize(this.state.comment));
- const { isMessageSent, errorMessage, ...messageData } = this.state; // Exclude isMessageSent from the data
-
- const response = await fetch(`${import.meta.env.PUBLIC_API_URL}/comments/${this.props.slug}`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({ ...messageData, comment: messageHtml }),
- });
-
- if (!response.ok) {
- const errorBody = await response.json();
- const errorMessage = `HTTP Error ${response.status}: ${response.statusText}<br>${errorBody.message}`;
-
- this.setState({
- errorMessage: `There was an error submitting your comment.<br>Details:<br>${errorMessage}`,
- isMessageSent: false,
- });
- return;
- }
-
- const responseBody = await response.json();
-
- this.setState({
- author: '',
- comment: '',
- isMessageSent: true,
- errorMessage: '',
- commentId: responseBody.id,
- });
-
- if (this.props.onMessageSent) {
- this.props.onMessageSent();
- }
- } catch (error) {
- this.setState({
- errorMessage: `There was an error submitting your message.<br>Details:<br>${error.message}<br>Check the console for more details.`,
- isMessageSent: false,
- });
+const BlogCommentsForm = ({ state, handleChange, handleSubmit }) => (
+ <div className="card">
+ <form onSubmit={handleSubmit}>
+ <h2>Submit Comment</h2>
+ <label htmlFor="author">Author *</label>
+ <input type="text" name="author" placeholder="John Doe" required value={state.author} onChange={handleChange} disabled={state.isMessageSent}/>
+ <label htmlFor="comment">Comment * (Supports <a href="https://www.markdownguide.org/cheat-sheet/" target="_blank">Markdown</a>)</label>
+ <textarea name="comment" placeholder="Enter your comment here." required value={state.comment}
+ onChange={handleChange} disabled={state.isMessageSent}></textarea>
+ <div id="turnstile-container"></div>
+ <button className="button" type="submit" disabled={state.isMessageSent}>Send</button>
+ </form>
+ {state.errorMessage && <p dangerouslySetInnerHTML={{__html: state.errorMessage}}/>}
+ {state.isMessageSent && !state.errorMessage &&
+ <div>
+ <p>Sent successfully!</p>
+ <p>(Optional)</p>
+ <p>Save this message ID: {state.commentId}</p>
+ <p>Then send it to me, to verify that you sent this comment.</p>
+ <p><a href="mailto:andrew@alee14.me">Email me</a> or tag/message me on these <a href="/contacts">platforms</a>.</p>
+ </div>
}
- }
+ </div>
+);
- render() {
- return (
- <div className="card">
- <form onSubmit={this.handleSubmit}>
- <h2>Submit Comment</h2>
- <label htmlFor="author">Author *</label>
- <input type="text" name="author" placeholder="John Doe" required value={this.state.author} onChange={this.handleChange} disabled={this.state.isMessageSent}/>
- <label htmlFor="comment">Comment * (Supports <a href="https://www.markdownguide.org/cheat-sheet/" target="_blank">Markdown</a>)</label>
- <textarea name="comment" placeholder="Enter your comment here." required value={this.state.comment}
- onChange={this.handleChange} disabled={this.state.isMessageSent}></textarea>
- <div id="turnstile-container"></div>
- <button class="button" type="submit" disabled={this.state.isMessageSent}>Send</button>
- </form>
- {this.state.errorMessage && <p dangerouslySetInnerHTML={{__html: this.state.errorMessage}}/>}
- {this.state.isMessageSent && !this.state.errorMessage &&
- <div>
- <p>Sent successfully!</p>
- <p>(Optional)</p>
- <p>Save this message ID: {this.state.commentId}</p>
- <p>Then send it to me, to verify that you sent this comment.</p>
- <p><a href="mailto:andrew@alee14.me">Email me</a> or tag/message me on these <a href="/contacts">platforms</a>.</p>
- </div>
- }
- </div>
- );
- }
-}
+const getBlogCommentsApiUrl = (props) => `${import.meta.env.PUBLIC_API_URL}/comments/${props.slug}`;
-export default BlogCommentsForm;
+export default withFormHandling(BlogCommentsForm, getBlogCommentsApiUrl, {
+ author: '',
+ comment: '',
+ commentId: ''
+});