Empathy: Add support for submitting answers to a prompy
authorCarl Worth <cworth@cworth.org>
Wed, 10 Jun 2020 02:46:28 +0000 (19:46 -0700)
committerCarl Worth <cworth@cworth.org>
Wed, 10 Jun 2020 02:53:00 +0000 (19:53 -0700)
For this we convert ActivePrompt from a function to a class-based
React component. Then we use the "uncontrolled components" technique
again to arrange for an array to hold the form values.

Finally, when answers are submitted successfully we display a simple,
static message. Eventually, we'll want to display some dynamic updates
as other players vote, (but for that, we'll also need the server to
give us that information).

empathy/empathy.jsx

index 0771bbe3d46e04071927e93de3b01ad3f38910b7..39461898cf5efd9d7478a2acd68a333c791be74c 100644 (file)
@@ -291,51 +291,97 @@ const LetsPlay = React.memo(props => {
   );
 });
 
-const ActivePrompt = React.memo(props => {
+class ActivePrompt extends React.PureComponent {
 
-  function handle_submit(event) {
+  constructor(props) {
+    super(props);
+    const items = props.prompt.items;
+
+    this.state = {
+      submitted: false
+    };
+
+    this.answers = [...Array(items)].map(() => React.createRef());
+    this.handle_submit = this.handle_submit.bind(this);
+  }
+
+  async handle_submit(event) {
+    const form = event.currentTarget;
 
     /* Prevent the default page-changing form-submission behavior. */
     event.preventDefault();
+
+    const response = await fetch_post_json(`answer/${this.props.prompt.id}`, {
+      answers: this.answers.map(r => r.current.value)
+    });
+    if (response.status == 200) {
+      const result = await response.json();
+      if (! result.valid) {
+        add_message("danger", result.message);
+        return;
+      }
+    } else {
+      add_message("danger", "An error occurred submitting your answers");
+      return;
+    }
+
+    /* Everything worked. Server is happy with our answers. */
+    form.reset();
+    this.setState({
+        submitted: true
+    });
   }
 
-  return (
-    <div className="active-prompt">
-      <h2>The Game of Empathy</h2>
-      <p>
-        Remember, you're trying to match your answers with
-        what the other players submit.
-        Give {props.prompt.items} responses for the following prompt:
-      </p>
-      <h2>{props.prompt.prompt}</h2>
-      <form onSubmit={handle_submit}>
-        {Array(props.prompt.items).fill(null).map((whocares,i) => {
-          return (
-            <div
-              key={i}
-              className="form-field large">
-              <input
-                type="text"
-                name={`response_${i}`}
-                required
-                autoComplete="off"
-              />
-            </div>
-          );
-        })}
-
-        <div
-          key="submit-button"
-          className="form-field large">
-          <button type="submit">
-            Send
-          </button>
+  render() {
+    if (this.state.submitted)
+      return (
+        <div className="please-wait">
+          <h2>Answers submitted</h2>
+          <p>
+            Please wait for the rest of the players to submit their answers.
+          </p>
         </div>
+      );
 
-      </form>
-    </div>
-  );
-});
+    return (
+      <div className="active-prompt">
+        <h2>The Game of Empathy</h2>
+        <p>
+          Remember, you're trying to match your answers with
+          what the other players submit.
+          Give {this.props.prompt.items} answers for the following prompt:
+        </p>
+        <h2>{this.props.prompt.prompt}</h2>
+        <form onSubmit={this.handle_submit}>
+          {Array(this.props.prompt.items).fill(null).map((whocares,i) => {
+            return (
+              <div
+                key={i}
+                className="form-field large">
+                <input
+                  type="text"
+                  name={`answer_${i}`}
+                  required
+                  autoComplete="off"
+                  ref={this.answers[i]}
+                />
+              </div>
+            );
+          })}
+
+          <div
+            key="submit-button"
+            className="form-field large">
+            <button type="submit">
+              Send
+            </button>
+          </div>
+
+        </form>
+      </div>
+    );
+  }
+}
 
 class Game extends React.PureComponent {
   constructor(props) {