aboutsummaryrefslogtreecommitdiff
path: root/src/components/FormHandling.jsx
diff options
context:
space:
mode:
authorAndrew Lee <alee14498@protonmail.com>2024-06-29 08:38:44 -0400
committerAndrew Lee <alee14498@protonmail.com>2024-06-29 08:38:44 -0400
commitbeb54b0acb7721068bc36da6906bd615eb01fb8c (patch)
tree2a5b92b3273a3ac8376bbd54f91f28721ca82c6e /src/components/FormHandling.jsx
parentfd1d608df8544873f8f8325e0507db1c59723549 (diff)
downloadpersonal-website-beb54b0acb7721068bc36da6906bd615eb01fb8c.tar.gz
personal-website-beb54b0acb7721068bc36da6906bd615eb01fb8c.tar.bz2
personal-website-beb54b0acb7721068bc36da6906bd615eb01fb8c.zip
Merged Guestbook and Blog Comments into HOC
Diffstat (limited to 'src/components/FormHandling.jsx')
-rw-r--r--src/components/FormHandling.jsx111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/components/FormHandling.jsx b/src/components/FormHandling.jsx
new file mode 100644
index 0000000..8f7f688
--- /dev/null
+++ b/src/components/FormHandling.jsx
@@ -0,0 +1,111 @@
+import { Component } from 'preact';
+import { marked } from 'marked';
+import DOMPurify from 'dompurify';
+
+const withFormHandling = (WrappedComponent, getApiUrl, initialState) => {
+ return class extends Component {
+ state = {
+ ...initialState,
+ isMessageSent: false,
+ errorMessage: '',
+ turnstileToken: ''
+ };
+
+ 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 message.',
+ });
+ return;
+ }
+
+ try {
+ const messageKey = this.state.comment !== undefined ? 'comment' : 'message';
+ const messageHtml = marked(DOMPurify.sanitize(this.state[messageKey]));
+ const { isMessageSent, errorMessage, ...messageData } = this.state; // Exclude isMessageSent and errorMessage from the data
+
+ messageData[messageKey] = messageHtml;
+
+ const response = await fetch(getApiUrl(this.props), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(messageData),
+ });
+
+ 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 message.<br>Details:<br>${errorMessage}`,
+ isMessageSent: false,
+ });
+ return;
+ }
+
+ const responseBody = await response.json();
+
+ this.setState({
+ ...initialState,
+ isMessageSent: true,
+ errorMessage: '',
+ [messageKey === 'comment' ? 'commentId' : 'messageId']: 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,
+ });
+ }
+ }
+
+ render() {
+ return (
+ <WrappedComponent
+ {...this.props}
+ state={this.state}
+ handleChange={this.handleChange}
+ handleSubmit={this.handleSubmit}
+ />
+ );
+ }
+ };
+};
+
+export default withFormHandling;