Survey applications are software that companies use to get feedback from customers or employees on how well their products or services are performing. Because organizations can obtain customer or employee reviews of their services, survey applications play an important role in organization service analysis. The company will then work on the collected feedback to provide the best services that suit the expectations of the customers.
Many companies use surveys because it is one of the easiest ways to collect information from the outside world. Whether your company wants to collect opinions or wants you to complete a feedback form, a web survey is a good way to go.
Surveys can show you the problems your service solves (and the ones it doesn't) and give you insight into what you need to be doing to satisfy your customers. They'll show you more about your pricing schemes and tell you how you can improve based on what your customers say. In short, surveys should be built into every organization's strategy to get feedback from customers and prospects as well as a way to build trust with them.
In this tutorial, I'll walk you through the steps of creating a survey app with React.js using Strapi as the backend tool. Here's what it'll look like:
To follow this tutorial, you should have:
node -v
command. Strapi is an open-source Content API Framework that is used to build content-oriented applications. It can be used to build a simple blog or used to build complex e-commerce platforms like Shopify.
Strapi is written in Node.js and uses MongoDB as its database. It provides a rich set of features, including authentication and authorization, content management, data import/export, performance monitoring, etc.
React.js is a library for creating user interfaces. It's a declarative, component-based UI library. It allows you to create reusable UI components that render using data models to describe how the component should be rendered.
React aims to address one problem: building large applications with data that changes over time. We want our apps to be fast and responsive no matter how much data they display or how many things happen on the page at once, so we need an efficient way of updating the view when data changes.
There are many reasons why developers need to use surveys. 1. They can get feedback from their customers about their products. 2. They can know what features people want and how they want them implemented. 3. It helps them improve the quality of their product and make changes accordingly. 4. It also gives them an idea about the market share of their product, which will help them decide whether it is worth investing more time into the development process or not.
The survey application that we will create will have the following features:
Let's kick-start with our installation. Open the command line, and enter one of the following commands:
yarn create strapi-app survey-app --quickstart
Or
npx create-strapi-app survey-app --quickstart
The above command will install all the needed packages for the project. After the installation, the Strapi app will automatically be launched in the browser. Register with your details and it will take you to your dashboard page as shown below:
Creating a React app is easy. The first step is to run the following commands on the terminal:
npx create-react-app my-app
cd my-app
npm start
The above command will create a directory for your new project and initialize it as a package. The React app must be installed under the my-project
folder.
Now that we have done all the prep, let's dive right into building our survey app.
In this simple survey app, we’ll create two content types named survey and response.
This collection type will contain all the survey questions with their options so that users can choose that response. We’ll also use an internationalization plugin to translate the survey questions into different languages.
Before we create the survey collection, let's add a new locale language to our application. To do this is simple. From your dashboard menu, click on Settings. Then, under the global settings sub-menu, click on internationalization.
To add the new language, click on the "add new locale" button and then select the language and save it. But for our survey application we’ll only add French (Canada) fr-CA, as shown below:
Now, let's create the survey collection type. From your dashboard menu, click on Content-Type Builder, then click on Create New Collection Type. Enter the display name for the collection type and then click on advanced settings. Under advanced settings, make sure that you enable international and click on continue.
After that, we’ll add the necessary fields for the survey content type. The survey content type fills in the following fields: i. question: (Text - Long Text) ii. a: (Text - Short Text) iii. b: (Text - Short Text) iv. c: (Text - Short Text)
This collection type is where all the survey responses will be stored. The response collection type will contain the following fields: Email, surveyQuestion, surveyResponse. To create the response collection type, follow the same steps as used in the survey collection type above.
Let's add some of the survey questions to the survey collection type. To do this is simple. From the content manager menu, click on survey and then click the "Create new entry" button. Fill in the survey questions and their response options, then save it and click on publish. You can add as many survey questions as you like.
To add locale content for the survey collection type, on the survey collection page, click on the edit icon for each question. From the left-hand side, click on locale and select your preferred language. Fill in the survey question in the selected language, save and publish it.
Before we move to frontend design, we need to ensure that survey and response content types are available via API call. Go to Settings, click Roles, and edit Public. Select all and click on save for both survey and response respectively.
Now we can make requests to survey and response collection types using http://localhost:1337/api/surveys/ and http://localhost:1337/api/responses/ restful endpoint from the front-end interface.
In this tutorial, we’ll not focus on the styling, but from your React project, open app.css and replace the styling with the following code:
1 // src/App.css
2 .App {
3 text-align: center;
4 }
5
6 .main {
7 width: 99%;
8 height: 500px;
9 background-color: #e7e7e7;
10 border-radius: 10px;
11 margin-top: 70px;
12 border: 4px solid #f3f3f3
13 }
14
15 .bar1 {
16 width: 100%;
17 height: 70px;
18 border-top-right-radius: 10px;
19 border-top-left-radius: 10px;
20 }
21
22 .bar2 {
23 width: 70%;
24 height: 27px;
25 background-color: white;
26 border-radius: 10px;
27 }
28
29 .bar3 {
30 width: 100%;
31 height: 27px;
32 background-color: #f68e56;
33 float: left;
34 border-radius: 10px;
35 color: white;
36 }
37
38 #surv {
39
40 width: 90%;
41 height: 380px;
42 background-color: #f3f3f3;
43 border-top-right-radius: 10px;
44 border-top-left-radius: 10px;
45 margin-left: 70px;
46 }
47
48 .divid1 {
49 height: 200px;
50 width: 440px;
51 float: left;
52 margin-left: 200px;
53 }
54
55 .divid2 {
56 height: 200px;
57 width: 440px;
58 float: right;
59 }
60
61 .input {
62 border: 2px solid #d5d5d5;
63 font-size: 17px;
64 background: #fbfbfb;
65 height: 20px;
66 padding: 8px;
67 width: 400px;
68 }
69
70 .radio_option {
71 width: 1100px;
72 height: 430px;
73 margin-left: 100px;
74 }
75
76 .radio {
77 border: 2px solid #d5d5d5;
78 font-size: 17px;
79 background: #fbfbfb;
80 height: 24px;
81 padding: 8px;
82 width: 24px;
83 }
84 .checkbox {
85 border: 2px solid #d5d5d5;
86 font-size: 17px;
87 background: #fbfbfb;
88 height: 24px;
89 padding: 8px;
90 width: 24px;
91 }
92
93 .container {
94 width: 1100px;
95 height: 430px;
96 }
97
98 .hid {
99 display: none;
100 width: 90%;
101 height: 380px;
102 background-color: #f3f3f3;
103 border-top-right-radius: 10px;
104 border-top-left-radius: 10px;
105 margin-left: 70px
106 }
107
108 .view {
109 display: inherit;
110 width: 90%;
111 height: 380px;
112 background-color: #f3f3f3;
113 border-top-right-radius: 10px;
114 border-top-left-radius: 10px;
115 margin-left: 70px
116 }
117
118 .btn {
119 width: 100px;
120 height: 32px;
121 background-color: #f68e56;
122 border-radius: 100px;
123 }
Axios is a tool to make HTTP requests and handle the responses. It's written on top of the Promise API and can be used in both the browser and on the server. It's fast, simple, and supports features like caching, timeout, and authentication.
We'll be using Axios to make requests to our Strapi project endpoint because of its capabilities and features. Let's get Axios up and running in our React app.
To install Axios, navigate to your React project folder in the terminal and run the command below.
npm install Axios
To add functionality to our project, open app.js in your code editor and paste in the following code, then save it.
1 // src/App.js
2 import React, { useState, useEffect } from 'react';
3 import axios from 'axios';
4 import './App.css';
5
6 function App() {
7 const [email, setemail] = useState('2');
8 const [gender, setgender] = useState('3');
9 const [question1, setQuestion1] = useState("");
10 const [question2, setQuestion2] = useState("");
11 const [question3, setQuestion3] = useState("");
12 const [response1, setResponse1] = useState("");
13 const [response2, setResponse2] = useState("");
14 const [response3, setResponse3] = useState("");
15 const [lang, setLang] = useState("en");
16 const [QuestionNum1, setQuestionNum1] = useState(1);
17 const [QuestionNum2, setQuestionNum2] = useState(2);
18 const [button, setButton] = useState("Start Survey");
19 const getsurvey = async (value) => {
20
21 let Tasks = await axios.get('http://localhost:1337/api/surveys?locale=' + value);
22 setQuestion1(Tasks.data.data\[0\]["attributes"]);
23 setQuestion2(Tasks.data.data\[QuestionNum1\]["attributes"]);
24 setQuestion3(Tasks.data.data\[QuestionNum2\]["attributes"]);
25 setQuestionNum1(prev => QuestionNum1 + 2);
26 setQuestionNum2(prev => QuestionNum2 + 2);
27 }
28
29
30
31 const load = (value) => {
32 getsurvey(value);
33 }
34
35 const [checkbox, setCheckbox] = useState({ box1: "", box2: "",box3: ""});
36
37
38 const updateBox = (box, value) => {
39 if (box === "1") {
40 if (checkbox.box1 === value) {
41 value = ""
42 }
43 setCheckbox(previousState => {
44
45 return { ...previousState, box1: value }
46
47 });
48
49 }
50
51 if (box === "2") {
52 if (checkbox.box2 === value) {
53 value = ""
54 }
55 setCheckbox(previousState => {
56 return { ...previousState, box2: value }
57 });
58 }
59 if (box === "3") {
60 if (checkbox.box3 === value) {
61 value = ""
62 }
63 setCheckbox(previousState => {
64 return { ...previousState, box3: value }
65 });
66 }
67 }
68
69
70
71 const [page, setpage] = useState(0);
72 const [page0, set0page] = useState('view');
73 const [page1, set1page] = useState('hid');
74 const [page2, set2page] = useState('hid');
75 const [page3, set3page] = useState('hid');
76 const [page4, set4page] = useState('hid');
77
78 const addTask = async (quest, valu) => {
79 let res = await axios
80 .post("http://localhost:1337/api/responses/", {
81
82 "data": { "Email": email, "surveyQuestion": quest, "surveyResponse": valu}
83 })
84
85 .catch((err) => console.log(err));
86
87 };
88
89 useEffect(() => {
90 setResponse3(prev => checkbox.box1 + "," + checkbox.box2 + "," + checkbox.box3);
91 }, [checkbox])
92
93
94 const next = () => {
95 if (page === 0) {
96 set0page(prev => "hid");
97 set1page(prev => "view");
98 setpage(prev => page + 1);
99 setButton(prev => "Next Question");
100 }
101 if (page === 1) {
102 set1page(prev => "hid");
103 set2page(prev => "view");
104 setpage(prev => page + 1);
105 setButton(prev => "Next Question");
106 }
107 if (page === 2) {
108 set2page(prev => "hid");
109 set3page(prev => "view");
110 setpage(prev => page + 1);
111 setButton(prev => "Submit");
112 }
113 if (page === 3) {
114 set3page(prev => "hid");
115 set4page(prev => "view");
116 setpage(prev => 4);
117 setButton(prev => "New Survey");
118 addTask(question1.question, response1);
119 addTask(question2.question, response2);
120 addTask(question3.question, response3);
121 getsurvey(lang);
122 }
123 if (page === 4) {
124 set4page(prev => "hid");
125 set2page(prev => "view");
126 setpage(prev => 2);
127 setButton(prev => "Next Question");
128 }
129 }
130 return (
131 <div className="App" >
132 <div className="main">
133 <div className="bar1">
134 <center>
135 <span>Progress</span>
136 <div className="bar2">
137 <div className="bar3" >
138 {page}/3
139 </div>
140 </div>
141 </center>
142 </div>
143 <div id="surv" className={page0}>
144
145 <br />
146 <h2>welcome to my survey app</h2>
147 <div className="container">
148 <div className="divid1">
149 <br />
150 <input type="text" className="input" name="" placeholder="Email address" onChange={(event) => setemail(event.target.value)} />
151 <br /><br />
152 <label>Select Language</label>
153 <select className="input" onChange={(event) => load(event.target.value)} placeholder="Select Language">
154 <option>Select Language</option>
155 <option value="en">English </option>
156 <option value="fr-CA">French</option>
157 </select>
158 <br />
159 <br />
160 </div>
161 <div className="divid2">
162 <br />
163 <input type="text" className="input" name="" placeholder="Gender" onChange={(event) => setgender(event.target.value)} />
164 <br /><br />
165 </div>
166 </div>
167 </div>
168 <div id="surv" className={page1}>
169 <br />
170 <h2>{question1.question}</h2>
171 <div className="container">
172 <div className="divid1">
173 <br />
174 <input type="text" className="input" name="" placeholder="Fullname" onChange={(event) => setResponse1(event.target.value)} />
175 <br />
176 <br />
177 </div>
178 </div>
179 </div>
180 <div id="surv" className={page2} hidden>
181 <br />
182 <h2>{question2.question}</h2>
183 <div className="radio_option">
184 <input type="radio" value="22" onClick={(event) => setResponse2(question2.a)} name="r" className="radio" />
185 <label className="font1">{question2.a}</label>
186 <br /><br />
187 <input type="radio" value="22" name="r" className="radio" onClick={(event) => setResponse2(question2.b)} />
188 <label className="font1">{question2.b}</label>
189 <br /> <br />
190 <input type="radio" value="ww" name="r" className="radio" onClick={(event) => setResponse2(question2.c)} />
191 <label className="font1 magin1">{question2.c}</label>
192 <br /><br />
193 </div>
194 </div>
195 <div id="surv" className={page3} hidden>
196 <br />
197 <h2>{question3.question}</h2>
198 <div className="radio_option">
199 <input type="checkbox" name="e" className="checkbox" onClick={(event) => updateBox('1', question3.a)} />
200 <label className="font1">{question3.a}</label>
201 <br />
202 <br />
203 <input type="checkbox" onClick={(event) => updateBox('2', question3.b)} value="22" name="e" className="checkbox" />
204 <label className="font1">{question3.b}</label>
205 <br />
206 <br />
207 <input type="checkbox" onClick={(event) => updateBox('3', question3.c)} value="." name="r" className="checkbox" />
208 <label className="font1">{question3.c}</label>
209 <br />
210 <br />
211 </div>
212 </div>
213 <div id="surv" className={page4}>
214 <br />
215 <h2>Survey completed</h2>
216 <div className="container">
217 <b> start another survey now</b>
218 </div>
219 </div>
220 <button className="btn" onClick={() => next()} > {button} </button>
221 </div>
222 </div>
223 );
224
225 }
226 export default App;
If you followed all the steps from the beginning, you should have your survey application running now.
Let’s explain how the code above works to get a better understanding of the application.
1 const getsurvey = async (value) => {
2
3 let Tasks = await axios.get('http://localhost:1337/api/surveys?locale=' + value);
4 setQuestion1(Tasks.data.data\[0\]["attributes"]);
5 setQuestion2(Tasks.data.data\[QuestionNum1\]["attributes"]);
6 setQuestion3(Tasks.data.data\[QuestionNum2\]["attributes"]);
7 setQuestionNum1(prev => QuestionNum1 + 2);
8 setQuestionNum2(prev => QuestionNum2 + 2);
9 }
From the above code, what the getsurvey() method does is that it uses Axios to make requests to the backend. The internationalization language to get from the Strapi backend is specified by the variable value parameter.
When the user clicks on the Start Survey button, then the survey questions are loaded from strapi based on the language selected by the user. If the language selected by the user is French, then the survey questions will be in French by making use of strapi internationalization plugin.
1 const addTask = async (quest, valu) => {
2 let res = await axios
3 .post("http://localhost:1337/api/responses/", {
4
5 "data": { "Email": email, "surveyQuestion": quest, "surveyResponse": valu}
6 })
7
8 .catch((err) => console.log(err));
9
10 };
We use the addTask() method to store the user responses to the backend. Whenever the user is through with a set of survey questions, and when the user clicks on the submit button, addTask() will be triggered to send the responses to the backend.
1 useEffect(() => {
2 setResponse3(prev => checkbox.box1 + "," + checkbox.box2 + "," + checkbox.box3);
3 }, [checkbox])
We use the useEffect hook to update the values for multiple option questions. Whenever the box is checked or unchecked, we then update it with the corresponding value.
Congratulations! You have successfully created a survey application from scratch.
In this tutorial, you learned how to set up Strapi for a survey application using the React.js library for the front end. We also learned how to use internationalization in Strapi to offer content in different languages.