aboutsummaryrefslogtreecommitdiff
path: root/src/components/FormHandling.jsx
blob: 5210bdfa4b54f4ed924b664364ec5791957445db (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { Component } from 'react';
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;