Przeglądaj źródła

Create PersonalInformation component. Add basic form and interactions

Tatiana Inama 6 lat temu
rodzic
commit
44246f613a
4 zmienionych plików z 328 dodań i 114 usunięć
  1. 124 0
      package-lock.json
  2. 2 0
      package.json
  3. 28 114
      src/App.tsx
  4. 174 0
      src/PersonalInformation.tsx

+ 124 - 0
package-lock.json

@@ -1766,6 +1766,15 @@
         "@types/react": "*"
       }
     },
+    "@types/reactstrap": {
+      "version": "8.4.2",
+      "resolved": "https://registry.npmjs.org/@types/reactstrap/-/reactstrap-8.4.2.tgz",
+      "integrity": "sha512-ag4hfFqBZaeoNSSTKjCtedvdcO68QqqlBrFd3obg94JSmhgNTmHz50BvNJkf9NjSzx1yGTW4l/OyP/khLPKqww==",
+      "requires": {
+        "@types/react": "*",
+        "popper.js": "^1.14.1"
+      }
+    },
     "@types/stack-utils": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
@@ -2901,6 +2910,15 @@
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
       "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow=="
     },
+    "bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "optional": true,
+      "requires": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
     "bluebird": {
       "version": "3.7.2",
       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
@@ -3404,6 +3422,11 @@
         }
       }
     },
+    "classnames": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+      "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+    },
     "clean-css": {
       "version": "4.2.3",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
@@ -3804,6 +3827,15 @@
         "sha.js": "^2.4.8"
       }
     },
+    "create-react-context": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz",
+      "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==",
+      "requires": {
+        "gud": "^1.0.0",
+        "warning": "^4.0.3"
+      }
+    },
     "cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -4404,6 +4436,14 @@
         "utila": "~0.4"
       }
     },
+    "dom-helpers": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
+      "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
+      "requires": {
+        "@babel/runtime": "^7.1.2"
+      }
+    },
     "dom-serializer": {
       "version": "0.2.2",
       "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
@@ -5562,6 +5602,12 @@
         "schema-utils": "^2.5.0"
       }
     },
+    "file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "optional": true
+    },
     "filesize": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.0.1.tgz",
@@ -6009,6 +6055,11 @@
       "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
       "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE="
     },
+    "gud": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
+      "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
+    },
     "gzip-size": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
@@ -7139,6 +7190,8 @@
           "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
           "optional": true,
           "requires": {
+            "bindings": "^1.5.0",
+            "nan": "^2.12.1",
             "node-pre-gyp": "*"
           },
           "dependencies": {
@@ -8699,6 +8752,12 @@
       "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
       "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
     },
+    "nan": {
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+      "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+      "optional": true
+    },
     "nanomatch": {
       "version": "1.2.13",
       "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -9480,6 +9539,11 @@
         "ts-pnp": "^1.1.2"
       }
     },
+    "popper.js": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
+    },
     "portfinder": {
       "version": "1.0.25",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
@@ -10904,6 +10968,25 @@
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
       "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
     },
+    "react-lifecycles-compat": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+      "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+    },
+    "react-popper": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz",
+      "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==",
+      "requires": {
+        "@babel/runtime": "^7.1.2",
+        "create-react-context": "^0.3.0",
+        "deep-equal": "^1.1.1",
+        "popper.js": "^1.14.4",
+        "prop-types": "^15.6.1",
+        "typed-styles": "^0.0.7",
+        "warning": "^4.0.2"
+      }
+    },
     "react-scripts": {
       "version": "3.4.0",
       "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.0.tgz",
@@ -10964,6 +11047,30 @@
         "workbox-webpack-plugin": "4.3.1"
       }
     },
+    "react-transition-group": {
+      "version": "2.9.0",
+      "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
+      "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
+      "requires": {
+        "dom-helpers": "^3.4.0",
+        "loose-envify": "^1.4.0",
+        "prop-types": "^15.6.2",
+        "react-lifecycles-compat": "^3.0.4"
+      }
+    },
+    "reactstrap": {
+      "version": "8.4.1",
+      "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-8.4.1.tgz",
+      "integrity": "sha512-oAjp9PYYUGKl7SLXwrQ1oRIrYw0MqfO2mUqYgGapFKHG2uwjEtLip5rYxtMujkGx3COjH5FX1WtcfNU4oqpH0Q==",
+      "requires": {
+        "@babel/runtime": "^7.2.0",
+        "classnames": "^2.2.3",
+        "prop-types": "^15.5.8",
+        "react-lifecycles-compat": "^3.0.4",
+        "react-popper": "^1.3.6",
+        "react-transition-group": "^2.3.1"
+      }
+    },
     "read-pkg": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@@ -12817,6 +12924,11 @@
         "mime-types": "~2.1.24"
       }
     },
+    "typed-styles": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz",
+      "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q=="
+    },
     "typedarray": {
       "version": "0.0.6",
       "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -13113,6 +13225,14 @@
         "makeerror": "1.0.x"
       }
     },
+    "warning": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+      "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "watchpack": {
       "version": "1.6.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
@@ -13153,6 +13273,8 @@
           "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
           "optional": true,
           "requires": {
+            "bindings": "^1.5.0",
+            "nan": "^2.12.1",
             "node-pre-gyp": "*"
           },
           "dependencies": {
@@ -13927,6 +14049,8 @@
           "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==",
           "optional": true,
           "requires": {
+            "bindings": "^1.5.0",
+            "nan": "^2.12.1",
             "node-pre-gyp": "*"
           },
           "dependencies": {

+ 2 - 0
package.json

@@ -10,10 +10,12 @@
     "@types/node": "^13.9.2",
     "@types/react": "^16.9.23",
     "@types/react-dom": "^16.9.5",
+    "@types/reactstrap": "^8.4.2",
     "bootstrap": "^4.4.1",
     "react": "^16.13.1",
     "react-dom": "^16.13.1",
     "react-scripts": "3.4.0",
+    "reactstrap": "^8.4.1",
     "typescript": "^3.8.3"
   },
   "scripts": {

+ 28 - 114
src/App.tsx

@@ -2,6 +2,8 @@ import React, { useState } from 'react';
 import './App.css';
 import 'bootstrap/dist/css/bootstrap.css';
 
+import PersonalInformation, { PersonalInformationValues } from './PersonalInformation';
+
 type SectionComponentProps = {
   changePage: () => void
 }
@@ -37,124 +39,27 @@ const TermsAndConditions: React.FunctionComponent<SectionComponentProps> = ({ ch
   );
 }
 
-type PersonalInformationValues = {
-  age: string,
-  gender: string,
-  genderCustom: string,
-  ethnicity: string,
-  ethnicityCustom: string,
-  birthPlace: string,
-  currentPlace: string
-};
-
-const PersonalInformation = () => {
-  const [ values, setValue ] = useState({
-    age: '',
-    gender: '',
-    genderCustom: '',
-    ethnicity: '',
-    ethnicityCustom: '',
-    birthPlace: '',
-    currentPlace: ''
-  });
 
-  const handleSelect = (value: keyof PersonalInformationValues ) => (e: React.ChangeEvent<HTMLSelectElement|HTMLInputElement>) => {
-    setValue({
-      ...values,
-      [value]: e.target.value
-    });
-  };
 
-  console.log(values);
-  return (
-    <section id="personal-information" className="content page page-2">
-      <h2>Personal Information</h2>
-      <p>All fields are required</p>
-      <form id="personal-information-form" className="needs-validation">
-        <div className="form-group">
-          <label htmlFor="age-range">Age</label>
-          <select id="age-range" className="custom-select form-control" value={values.age} onChange={handleSelect('age')} required>
-            <option value="" disabled>Please select an option</option>
-            <option value="1">11 - 17</option>
-            <option value="2">18 - 29</option>
-            <option value="3">30 - 45</option>
-            <option value="4">46 - 59</option>
-            <option value="5">60 - 69</option>
-            <option value="6">70+</option>
-          </select>
-        </div>
-        <div className="form-group">
-          <label htmlFor="gender">Gender</label>
-          <select className="form-control custom-select" id="gender" value={values.gender} onChange={handleSelect('gender')} required>
-            <option value="" disabled>Please select an option</option>
-            <option value="male">Male</option>
-            <option value="female">Female</option>
-            <option value="other">Neither, I identify as follows</option>
-          </select>
-          {
-            values.gender === 'other' && (
-              <input type="text" id="gender-custom" className="form-control mt-2" value={values.genderCustom} onChange={handleSelect('genderCustom')} required/>
-            )
-          }
-        </div>
-        <div className="form-group">
-          <label htmlFor="ethnicity">Ethnicity</label>
-          <select id="ethnicity" className="form-control" value={values.ethnicity} onChange={handleSelect('ethnicity')} required>
-            <option value="" disabled>Please select an option</option>
-            <optgroup label="White">
-              <option value="English/Welsh/Scottish/Northern Irish/British">English/Welsh/Scottish/Northern Irish/British</option>
-              <option value="Irish">Irish</option>
-              <option value="Gypsy or Irish Traveller">Gypsy or Irish Traveller</option>
-            </optgroup>
-            <optgroup label="Mixed/multiple ethnic groups">
-              <option value="White and Black Caribbean">White and Black Caribbean</option>
-              <option value="White and Black African">White and Black African</option>
-              <option value="White and Asian">White and Asian</option>
-            </optgroup>
-            <optgroup label="Asian/Asian British">
-              <option value="Indian">Indian</option>
-              <option value="Pakistani">Pakistani</option>
-              <option value="Bangladeshi">Bangladeshi</option>
-              <option value="Chinese">Chinese</option>
-            </optgroup>
-            <optgroup label="Black/African/Caribbean/Black British">
-              <option value="African">African</option>
-              <option value="Caribbean">Caribbean</option>
-            </optgroup>
-            <optgroup label="Other ethnic group">
-              <option value="Arab">Arab</option>
-              <option value="other">None of the above. I identify as follows:</option>
-            </optgroup>
-          </select>
-          {
-            values.ethnicity === 'other' && (
-              <input type="text" id="ethnicity-custom" className="form-control mt-2" required/>
-            )
-          }
-          <small className="form-text text-muted">
-            The options above are taken from the 2011 UK Census. You can also define yours selecting the 'None of the above' option and typing in the text box
-          </small>
-        </div>
-        <div className="form-group">
-          <label htmlFor="town-birth">Town of birth</label>
-          <input id="town-birth" type="text" className="form-control" required/>
-        </div>
-        <div className="form-group">
-          <label htmlFor="postal-code">Current postal code</label>
-          <input id="postal-code" type="text" className="form-control" required/>
-          <div className="form-group form-check">
-            <input type="checkbox" className="form-check-input" id="long-time-resident" />
-            <label className="form-check-label" htmlFor="long-time-resident">I have lived in the area for 1/2 years</label>
-          </div>
-        </div>
-        <button type="button" onClick={()=>{}} className="btn btn-primary">Next</button>
-      </form>
-    </section>
-  );
-}
+type AnswersData = {
+  personalInformation: PersonalInformationValues,
+};
 
 const App = () => {
   const [ currentPage, setCurrentPage ] = useState(0);
+  const [ answers, saveAnswers ] = useState<AnswersData>({
+    personalInformation: {
+      age: '',
+      ageAuthorized: false,
+      gender: '',
+      genderCustom: '',
+      ethnicity: '',
+      ethnicityCustom: '',
+      birthPlace: '',
+      currentPlace: '',
+      nonNative: '',
+    }
+  });  
   const sections = [
     Introduction({
       changePage: () => {setCurrentPage(currentPage + 1)}
@@ -162,7 +67,16 @@ const App = () => {
     TermsAndConditions({
       changePage: () => {setCurrentPage(currentPage + 1)}
     }),
-    PersonalInformation(),
+    PersonalInformation({
+      changePage: () => {setCurrentPage(currentPage + 1)},
+      closeApp: () => {alert('thank you for your interest, but permission from your parent/guardian is required before you are able to participate.')},
+      saveData: (data: PersonalInformationValues) => {
+        saveAnswers({
+          ...answers,
+          personalInformation: data
+        })
+      }
+    }),
   ];
   console.log("currentPage", currentPage);
   return (

+ 174 - 0
src/PersonalInformation.tsx

@@ -0,0 +1,174 @@
+import React, {useState} from 'react';
+import { Button, Modal, ModalBody, ModalFooter } from 'reactstrap';
+
+export type PersonalInformationValues = {
+  age: string,
+  ageAuthorized: boolean,
+  gender: string,
+  genderCustom: string,
+  ethnicity: string,
+  ethnicityCustom: string,
+  birthPlace: string,
+  currentPlace: string,
+  nonNative: string
+};
+
+type PersonalInformationProps = {
+  changePage: () => void,
+  closeApp: () => void,
+  saveData: (data: PersonalInformationValues) => void
+};
+
+export const PersonalInformation: React.FunctionComponent<PersonalInformationProps> = ({ changePage, closeApp, saveData }) => {
+  const [ values, setValue ] = useState<PersonalInformationValues>({
+    age: '',
+    ageAuthorized: false,
+    gender: '',
+    genderCustom: '',
+    ethnicity: '',
+    ethnicityCustom: '',
+    birthPlace: '',
+    currentPlace: '',
+    nonNative: '',
+  });
+
+  const [ openModal, toggleModal ] = useState(false);
+
+  const setAgeAuthorization = (authorized: boolean) => {
+    setValue({
+      ...values,
+      ageAuthorized: authorized
+    })
+  };
+
+  const handleSelect = (value: keyof PersonalInformationValues ) => (e: React.ChangeEvent<HTMLSelectElement|HTMLInputElement>) => {
+    setValue({
+      ...values,
+      [value]: e.target.value
+    });
+  };
+
+  return (
+    <section id="personal-information" className="content page page-2">
+      <h2>Personal Information</h2>
+      <p>All fields are required</p>
+      <form id="personal-information-form" className="needs-validation">
+        <div className="form-group">
+          <label htmlFor="age-range">Age</label>
+          <select id="age-range" className="custom-select form-control" value={values.age} onChange={e => {
+            if (e.target.value === '1') {
+              toggleModal(true);
+            } else {
+              handleSelect('age')(e)
+            }
+          }} required>
+            <option value="" disabled>Please chooose</option>
+            <option value="1">11 - 17</option>
+            <option value="2">18 - 25</option>
+            <option value="3">26 - 45</option>
+            <option value="4">46 - 65</option>
+            <option value="5">66 - 75</option>
+            <option value="6">75+</option>
+          </select>
+          <Modal isOpen={openModal} onClosed={() => {
+            if (values.ageAuthorized) {
+              setValue({
+                ...values,
+                age: '1'
+              })
+            } else {
+              closeApp();
+              console.log("go away kiddo")
+            }
+          }}>
+            <ModalBody>
+              I have permission from my parent(s)/guardian(s) to participate in this study
+            </ModalBody>
+            <ModalFooter>
+              <Button onClick={() => { setAgeAuthorization(false); toggleModal(false)}}>No</Button>
+              <Button color="primary" onClick={() => { setAgeAuthorization(true); toggleModal(false)}}>Yes</Button>
+            </ModalFooter>
+          </Modal>
+        </div>
+        <div className="form-group">
+          <label htmlFor="gender">Gender</label>
+          <select className="form-control custom-select" id="gender" value={values.gender} onChange={handleSelect('gender')} required>
+            <option value="" disabled>Please choose</option>
+            <option value="male">Male</option>
+            <option value="female">Female</option>
+            <option value="other">Neither, I identify as follows</option>
+          </select>
+          {
+            values.gender === 'other' && (
+              <input type="text" id="gender-custom" className="form-control mt-2" value={values.genderCustom} onChange={handleSelect('genderCustom')} required/>
+            )
+          }
+        </div>
+        <div className="form-group">
+          <label htmlFor="ethnicity">
+            Ethnicity
+            <small className="form-text text-muted">
+              The following options are taken from the 2011 UK Census. You can also define yours selecting the 'None of the above' option.
+            </small>  
+          </label>
+          <select id="ethnicity" className="form-control" value={values.ethnicity} onChange={handleSelect('ethnicity')} required>
+            <option value="" disabled>Please choose</option>
+            <optgroup label="White">
+              <option value="English/Welsh/Scottish/Northern Irish/British">English/Welsh/Scottish/Northern Irish/British</option>
+              <option value="Irish">Irish</option>
+              <option value="Gypsy or Irish Traveller">Gypsy or Irish Traveller</option>
+            </optgroup>
+            <optgroup label="Mixed/multiple ethnic groups">
+              <option value="White and Black Caribbean">White and Black Caribbean</option>
+              <option value="White and Black African">White and Black African</option>
+              <option value="White and Asian">White and Asian</option>
+            </optgroup>
+            <optgroup label="Asian/Asian British">
+              <option value="Indian">Indian</option>
+              <option value="Pakistani">Pakistani</option>
+              <option value="Bangladeshi">Bangladeshi</option>
+              <option value="Chinese">Chinese</option>
+            </optgroup>
+            <optgroup label="Black/African/Caribbean/Black British">
+              <option value="African">African</option>
+              <option value="Caribbean">Caribbean</option>
+            </optgroup>
+            <optgroup label="Other ethnic group">
+              <option value="Arab">Arab</option>
+              <option value="other">None of the above. I identify as follows:</option>
+            </optgroup>
+          </select>
+          {
+            values.ethnicity === 'other' && (
+              <input type="text" id="ethnicity-custom" className="form-control mt-2" required/>
+            )
+          }
+        </div>
+        <div className="form-group">
+          <label htmlFor="place-birth">Place of birth (Town/city and country)</label>
+          <input id="place-birth" type="text" className="form-control" required/>
+        </div>
+        <div className="form-group">
+          <label htmlFor="post-code">Current place of residence (postcode)</label>
+          <input id="post-code" type="text" className="form-control" required/>
+        </div>
+        <div className="form-group">
+          <label>If you were <b>not</b> born in Merseyside, please choose from the following options</label>
+          <select className="form-control" id="resident" value={values.nonNative} onChange={handleSelect('nonNative')}>
+            <option value="" disabled>Please choose</option>
+            <option value="1">Less than two years</option>
+            <option value="2">3-5 years</option>
+            <option value="3">6-10 years</option>
+            <option value="4">10+ years</option>
+          </select>
+        </div>
+        <button type="button" onClick={() => {
+          console.log(values);
+          saveData(values);
+        }} className="btn btn-primary">Next</button>
+      </form>
+    </section>
+  );
+};
+
+export default PersonalInformation;