Kaynağa Gözat

Use Typescript. Add basic sections

Tatiana Inama 6 yıl önce
ebeveyn
işleme
c14ec41109
7 değiştirilmiş dosya ile 330 ekleme ve 29 silme
  1. 116 0
      package-lock.json
  2. 8 2
      package.json
  3. 1 1
      src/App.css
  4. 0 26
      src/App.js
  5. 179 0
      src/App.tsx
  6. 1 0
      src/react-app-env.d.ts
  7. 25 0
      tsconfig.json

+ 116 - 0
package-lock.json

@@ -1613,6 +1613,112 @@
         "@types/istanbul-lib-report": "*"
       }
     },
+    "@types/jest": {
+      "version": "25.1.4",
+      "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.1.4.tgz",
+      "integrity": "sha512-QDDY2uNAhCV7TMCITrxz+MRk1EizcsevzfeS6LykIlq2V1E5oO4wXG8V2ZEd9w7Snxeeagk46YbMgZ8ESHx3sw==",
+      "requires": {
+        "jest-diff": "^25.1.0",
+        "pretty-format": "^25.1.0"
+      },
+      "dependencies": {
+        "@jest/types": {
+          "version": "25.1.0",
+          "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz",
+          "integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==",
+          "requires": {
+            "@types/istanbul-lib-coverage": "^2.0.0",
+            "@types/istanbul-reports": "^1.1.1",
+            "@types/yargs": "^15.0.0",
+            "chalk": "^3.0.0"
+          }
+        },
+        "@types/yargs": {
+          "version": "15.0.4",
+          "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz",
+          "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==",
+          "requires": {
+            "@types/yargs-parser": "*"
+          }
+        },
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "diff-sequences": {
+          "version": "25.1.0",
+          "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.1.0.tgz",
+          "integrity": "sha512-nFIfVk5B/NStCsJ+zaPO4vYuLjlzQ6uFvPxzYyHlejNZ/UGa7G/n7peOXVrVNvRuyfstt+mZQYGpjxg9Z6N8Kw=="
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+        },
+        "jest-diff": {
+          "version": "25.1.0",
+          "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.1.0.tgz",
+          "integrity": "sha512-nepXgajT+h017APJTreSieh4zCqnSHEJ1iT8HDlewu630lSJ4Kjjr9KNzm+kzGwwcpsDE6Snx1GJGzzsefaEHw==",
+          "requires": {
+            "chalk": "^3.0.0",
+            "diff-sequences": "^25.1.0",
+            "jest-get-type": "^25.1.0",
+            "pretty-format": "^25.1.0"
+          }
+        },
+        "jest-get-type": {
+          "version": "25.1.0",
+          "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.1.0.tgz",
+          "integrity": "sha512-yWkBnT+5tMr8ANB6V+OjmrIJufHtCAqI5ic2H40v+tRqxDmE0PGnIiTyvRWFOMtmVHYpwRqyazDbTnhpjsGvLw=="
+        },
+        "pretty-format": {
+          "version": "25.1.0",
+          "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.1.0.tgz",
+          "integrity": "sha512-46zLRSGLd02Rp+Lhad9zzuNZ+swunitn8zIpfD2B4OPCRLXbM87RJT2aBLBWYOznNUML/2l/ReMyWNC80PJBUQ==",
+          "requires": {
+            "@jest/types": "^25.1.0",
+            "ansi-regex": "^5.0.0",
+            "ansi-styles": "^4.0.0",
+            "react-is": "^16.12.0"
+          }
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
     "@types/json-schema": {
       "version": "7.0.4",
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
@@ -2865,6 +2971,11 @@
       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
     },
+    "bootstrap": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
+      "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA=="
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -12711,6 +12822,11 @@
       "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
     },
+    "typescript": {
+      "version": "3.8.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
+      "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w=="
+    },
     "unicode-canonical-property-names-ecmascript": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",

+ 8 - 2
package.json

@@ -6,12 +6,18 @@
     "@testing-library/jest-dom": "^4.2.4",
     "@testing-library/react": "^9.5.0",
     "@testing-library/user-event": "^7.2.1",
+    "@types/jest": "^25.1.4",
+    "@types/node": "^13.9.2",
+    "@types/react": "^16.9.23",
+    "@types/react-dom": "^16.9.5",
+    "bootstrap": "^4.4.1",
     "react": "^16.13.1",
     "react-dom": "^16.13.1",
-    "react-scripts": "3.4.0"
+    "react-scripts": "3.4.0",
+    "typescript": "^3.8.3"
   },
   "scripts": {
-    "start": "react-scripts start",
+    "start": "PORT=8080 react-scripts start",
     "build": "react-scripts build",
     "test": "react-scripts test",
     "eject": "react-scripts eject"

+ 1 - 1
src/App.css

@@ -1,5 +1,5 @@
 .App {
-  text-align: center;
+  height: 100vh;
 }
 
 .App-logo {

+ 0 - 26
src/App.js

@@ -1,26 +0,0 @@
-import React from 'react';
-import logo from './logo.svg';
-import './App.css';
-
-function App() {
-  return (
-    <div className="App">
-      <header className="App-header">
-        <img src={logo} className="App-logo" alt="logo" />
-        <p>
-          Edit <code>src/App.js</code> and save to reload.
-        </p>
-        <a
-          className="App-link"
-          href="https://reactjs.org"
-          target="_blank"
-          rel="noopener noreferrer"
-        >
-          Learn React
-        </a>
-      </header>
-    </div>
-  );
-}
-
-export default App;

+ 179 - 0
src/App.tsx

@@ -0,0 +1,179 @@
+import React, { useState } from 'react';
+import './App.css';
+import 'bootstrap/dist/css/bootstrap.css';
+
+type SectionComponentProps = {
+  changePage: () => void
+}
+const Introduction: React.FunctionComponent<SectionComponentProps> = ({ changePage }) => (
+  <section id="introduction">
+    <div className="jumbotron">
+      <h2>Accent and dialect form</h2>
+      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit voluptatum corporis minima, eius officiis magnam quae vero praesentium odio facilis minus illo ut atque accusamus esse deserunt. Fuga, autem molestiae!</p>
+      <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quos impedit natus dolorem ipsam rem cum mollitia, cumque sapiente omnis ea sed nobis ullam, asperiores dignissimos. Unde dolore iure quisquam aut.</p>
+      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quaerat suscipit fugiat, iste, odio tempora dolor, voluptatum assumenda enim aspernatur rem ipsam animi corrupti sapiente labore repellat quam amet. Ipsa, aspernatur!</p>
+      <button type="button" onClick={() => changePage()} className="btn btn-primary">Start</button>
+    </div>
+  </section>
+);
+
+const TermsAndConditions: React.FunctionComponent<SectionComponentProps> = ({ changePage }) => {
+  const [ agreement, setAgreement ] = useState(false);
+  return (
+    <section id="terms-and-legals">
+      <form id="terms-and-conditions-form" className="needs-validation">
+        <h2>Terms and Conditions</h2>
+        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati dolore magni aspernatur error totam exercitationem sequi illum. Ex voluptas in, eius provident laudantium quidem quod esse corrupti quas vitae aliquam!</p>
+        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quidem culpa soluta, voluptatibus quam magni sapiente corporis debitis ad illo voluptas odio! Adipisci facere ad molestiae ullam vero iure minus mollitia.</p>
+        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum commodi consectetur aperiam. Obcaecati quisquam possimus et facilis quas, doloremque minima rerum reprehenderit fugiat ipsam dolorum placeat velit! Exercitationem, eveniet obcaecati.</p>
+        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus quidem quisquam suscipit! Excepturi deserunt quaerat, odio recusandae molestiae assumenda voluptatem possimus id alias quas voluptatibus non quis vitae incidunt veritatis!</p>
+        <div className="form-group form-check">
+          <input type="checkbox" className="form-check-input" id="agreement" checked={agreement} onChange={(e) => { setAgreement(e.target.checked)}} required />
+          <label className="form-check-label" htmlFor="agreement">I agree with the termns and conditions</label>
+        </div>
+        <button type="button" className="btn btn-primary" onClick={() => changePage()} disabled={!agreement}>next</button>
+      </form>
+    </section>
+  );
+}
+
+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>
+  );
+}
+
+const App = () => {
+  const [ currentPage, setCurrentPage ] = useState(0);
+  const sections = [
+    Introduction({
+      changePage: () => {setCurrentPage(currentPage + 1)}
+    }),
+    TermsAndConditions({
+      changePage: () => {setCurrentPage(currentPage + 1)}
+    }),
+    PersonalInformation(),
+  ];
+  console.log("currentPage", currentPage);
+  return (
+    <div className="App bg-light">
+      <div className="container">
+        {
+          sections[currentPage]
+        }
+      </div>
+    </div>
+  )
+};
+
+export default App;

+ 1 - 0
src/react-app-env.d.ts

@@ -0,0 +1 @@
+/// <reference types="react-scripts" />

+ 25 - 0
tsconfig.json

@@ -0,0 +1,25 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "lib": [
+      "dom",
+      "dom.iterable",
+      "esnext"
+    ],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "strict": true,
+    "forceConsistentCasingInFileNames": true,
+    "module": "esnext",
+    "moduleResolution": "node",
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "react"
+  },
+  "include": [
+    "src"
+  ]
+}