From 30a7a079b16e1d17e8cc920d2fb3338f79767432 Mon Sep 17 00:00:00 2001
From: Blaster4385 <venkateshchaturvedi12@gmail.com>
Date: Fri, 12 Aug 2022 08:44:33 +0530
Subject: Add form validators and country api

---
 client/src/pages/Enrollment/FormOne/FormOne.jsx | 1 +
 1 file changed, 1 insertion(+)

(limited to 'client/src/pages/Enrollment/FormOne/FormOne.jsx')

diff --git a/client/src/pages/Enrollment/FormOne/FormOne.jsx b/client/src/pages/Enrollment/FormOne/FormOne.jsx
index ed83a6f..e9bff62 100644
--- a/client/src/pages/Enrollment/FormOne/FormOne.jsx
+++ b/client/src/pages/Enrollment/FormOne/FormOne.jsx
@@ -47,6 +47,7 @@ const FormOne = () => {
         value={fullName}
         onChange={(e) => setFullName(e.target.value)}
         placeholder="Enter your full name"
+        pattern="[a-zA-z]+"
       />
 
       <div className={styles.formone__gender}>
-- 
cgit 


From 87a343644592e9b425e7fa0805988ad8e7ee8778 Mon Sep 17 00:00:00 2001
From: Blaster4385 <venkateshchaturvedi12@gmail.com>
Date: Fri, 12 Aug 2022 11:23:48 +0530
Subject: Refactor code and switch to a multi-step form setup

---
 client/src/App.js                               | 179 +++++++++++++++++++++-
 client/src/components/Card/Card.jsx             |   4 +-
 client/src/components/RegEx/RegEx.jsx           |   9 ++
 client/src/pages/Enrollment/Address/Address.jsx | 128 +++++++++-------
 client/src/pages/Enrollment/FormOne/FormOne.jsx | 189 ++++++++++++++----------
 client/src/pages/Enrollment/FormTwo/FormTwo.jsx |  52 +++----
 client/src/pages/Home/Home.jsx                  |   7 +-
 7 files changed, 395 insertions(+), 173 deletions(-)
 create mode 100644 client/src/components/RegEx/RegEx.jsx

(limited to 'client/src/pages/Enrollment/FormOne/FormOne.jsx')

diff --git a/client/src/App.js b/client/src/App.js
index c39f14e..e7ab247 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -1,10 +1,183 @@
-import React from 'react'
-import Index from './routes'
+import React, { useState } from 'react'
+import Address from './pages/Enrollment/Address/Address'
+import Agreement from './pages/Enrollment/Agreement/Agreement'
+import DocumentScanner from './pages/Enrollment/DocumentScanner/DocumentScanner'
+import FinalSlip from './pages/Enrollment/FinalSlip/FinalSlip'
+import Fingerprint from './pages/Enrollment/Fingerprint/Fingerprint'
+import FormTwo from './pages/Enrollment/FormTwo/FormTwo'
+import IrisScan from './pages/Enrollment/IrisScan/IrisScan'
+import PhotoCapture from './pages/Enrollment/PhotoCapture/PhotoCapture'
+import SubmitButton from './components/SubmitButton/SubmitButton'
+import FormOne from './pages/Enrollment/FormOne/FormOne'
+import { validEmail, validMobileNumber, validPincode } from './components/RegEx/RegEx'
+import Home from './pages/Home/Home'
 
 const App = () => {
+  const [page, setPage] = useState(9)
+
+  const [formData, setFormData] = useState({
+    indianResident: '',
+    name: '',
+    gender: '',
+    dob: new Date().toISOString().slice(0, 10),
+    mobile: '',
+    email: '',
+    country: '',
+    state: '',
+    district: '',
+    village: '',
+    houseNo: '',
+    street: '',
+    locality: '',
+    postOffice: '',
+    landmark: '',
+    pincode: '',
+    address: ''
+  })
+
+  function handleSubmit () {
+    if (page === 0) {
+      if (formData.indianResident === '') {
+        return alert('Please select your residency')
+      } else if (formData.name === '' || formData.name.length < 1) {
+        return alert('Please enter your name')
+      } else if (formData.gender === '') {
+        return alert('Please select your gender')
+      } else {
+        setPage(page + 1)
+      }
+    } else if (page === 1) {
+      if (formData.mobile === '') {
+        return alert('Please enter your mobile number')
+      } else if (!validMobileNumber.test(formData.mobile)) {
+        return alert('Please enter valid mobile number')
+      } else if (formData.email === '') {
+        return alert('Please enter your email')
+      } else if (!validEmail.test(formData.email)) {
+        return alert('Please enter valid email')
+      } else {
+        setPage(page + 1)
+      }
+    } else if (page === 2) {
+      if (formData.country === '') {
+        return alert('Please select your country')
+      } else if (formData.state === '') {
+        return alert('Please select your state')
+      } else if (formData.district === '') {
+        return alert('Please select your district')
+      } else if (formData.village === '') {
+        return alert('Please enter your village')
+      } else if (formData.houseNo === '') {
+        return alert('Please enter your house number')
+      } else if (formData.street === '') {
+        return alert('Please enter your street')
+      } else if (formData.locality === '') {
+        return alert('Please enter your locality')
+      } else if (formData.postOffice === '') {
+        return alert('Please enter your post office')
+      } else if (formData.landmark === '') {
+        return alert('Please enter your landmark')
+      } else if (formData.pincode === '') {
+        return alert('Please enter your pincode')
+      } else if (!validPincode.test(formData.pincode)) {
+        return alert('Please enter valid pincode')
+      } else {
+        setFormData({
+          ...formData,
+          address: `${formData.houseNo} ${formData.street}, ${formData.locality}, ${formData.landmark}, ${formData.village}, ${formData.district.label}, ${formData.country.label} ${formData.pincode}`
+        })
+        setPage(page + 1)
+      }
+    } else if (page === 3) {
+      setPage(page + 1)
+    } else if (page === 4) {
+      setPage(page + 1)
+    } else if (page === 5) {
+      setPage(page + 1)
+    } else if (page === 6) {
+      setPage(page + 1)
+    } else if (page === 7) {
+      setPage(page + 1)
+    } else if (page === 8) {
+      setPage(page + 1)
+    } else if (page === 9) {
+      setPage(page + 1)
+    } else setPage(page + 1)
+  }
+
+  const conditionalComponent = () => {
+    switch (page) {
+      case 0:
+        return <FormOne formData={formData} setFormData={setFormData} />
+      case 1:
+        return <FormTwo formData={formData} setFormData={setFormData} />
+      case 2:
+        return <Address formData={formData} setFormData={setFormData} />
+      case 3:
+        return <DocumentScanner formData={formData} setFormData={setFormData} />
+      case 4:
+        return <PhotoCapture formData={formData} setFormData={setFormData} />
+      case 5:
+        return <IrisScan formData={formData} setFormData={setFormData} />
+      case 6:
+        return <Fingerprint formData={formData} setFormData={setFormData} />
+      case 7:
+        return <Agreement formData={formData} setFormData={setFormData} />
+      case 8:
+        return <FinalSlip formData={formData} setFormData={setFormData} />
+      default:
+        return <Home page={page} setPage={setPage} />
+    }
+  }
+
+  const conditionalButton = () => {
+    switch (page) {
+      case 0:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 1:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 2:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 3:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 4:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 5:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 6:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+      case 7:
+        return <SubmitButton onClick={handleSubmit}>
+            Submit
+          </SubmitButton>
+      case 8:
+        return <SubmitButton onClick={handleSubmit}>
+            Exit
+          </SubmitButton>
+      default:
+        return <SubmitButton onClick={handleSubmit}>
+            Next
+          </SubmitButton>
+    }
+  }
   return (
     <>
-      <Index />
+      {conditionalComponent()}
+      {conditionalButton()}
     </>
   )
 }
diff --git a/client/src/components/Card/Card.jsx b/client/src/components/Card/Card.jsx
index 3d66067..9460955 100644
--- a/client/src/components/Card/Card.jsx
+++ b/client/src/components/Card/Card.jsx
@@ -1,9 +1,9 @@
 import React from 'react'
 import styles from './Card.module.css'
 
-const Card = ({ title, image }) => {
+const Card = ({ title, image, onClick }) => {
   return (
-    <div className={styles.card}>
+    <div onClick={ onClick } className={styles.card}>
       <img className={styles.card__image} src={image} alt="" />
       <h2 className={styles.card__title}>{title}</h2>
     </div>
diff --git a/client/src/components/RegEx/RegEx.jsx b/client/src/components/RegEx/RegEx.jsx
new file mode 100644
index 0000000..2df4266
--- /dev/null
+++ b/client/src/components/RegEx/RegEx.jsx
@@ -0,0 +1,9 @@
+export const validString = /^[a-zA-Z]+$/
+
+export const validMobileNumber = /^[0-9]{10}$/
+
+export const validNumber = /^[0-9]+$/
+
+export const validPincode = /^[0-9]{6}$/
+
+export const validEmail = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/
diff --git a/client/src/pages/Enrollment/Address/Address.jsx b/client/src/pages/Enrollment/Address/Address.jsx
index 4acd0e6..d4ffe81 100644
--- a/client/src/pages/Enrollment/Address/Address.jsx
+++ b/client/src/pages/Enrollment/Address/Address.jsx
@@ -1,35 +1,12 @@
-import React, { useState } from 'react'
-import { useNavigate } from 'react-router-dom'
+import React from 'react'
 import Header from '../../../components/Header/Header'
 import Input from '../../../components/Input/Input'
-import SubmitButton from '../../../components/SubmitButton/SubmitButton'
 import { Country, State, City } from 'country-state-city'
 import Select from 'react-select'
 
 import styles from './Address.module.css'
 
-const Address = () => {
-  const [address, setAddress] = useState('')
-  const [houseNo, setHouseNo] = useState('')
-  const [locality, setLocality] = useState('')
-  const [postOffice, setPostOffice] = useState('')
-  const [street, setStreet] = useState('')
-  const [landmark, setLandmark] = useState('')
-  const [town, setTown] = useState('')
-  const [pincode, setPincode] = useState('')
-  const [state, setState] = useState('')
-  const [country, setCountry] = useState('')
-  const [city, setCity] = useState('')
-
-  const navigate = useNavigate()
-
-  const handleSubmit = () => {
-    navigate('/enrollment/photo')
-    const add = `${houseNo} ${locality} ${postOffice} ${street} ${landmark} ${town} ${city} ${state} ${countries} ${pincode}`
-    setAddress({ add })
-    console.log(address)
-  }
-
+const Address = ({ formData, setFormData }) => {
   const countries = Country.getAllCountries()
 
   const updatedCountries = countries.map((country) => ({
@@ -67,10 +44,12 @@ const Address = () => {
         })
       }
 
+      console.log(formData.country, formData.state, formData.district, formData.village)
+
   return (
     <>
       <Header subheading="Enrollment" />
-      <form onSubmit={() => handleSubmit()} className={styles.address}>
+      <div className={styles.address}>
         <div className={styles.address__container}>
       <div className={styles.input}>
       <div className={styles.input__container}>
@@ -80,8 +59,13 @@ const Address = () => {
           name="country"
           label="country"
           options={updatedCountries}
-          value={country}
-          onChange={setCountry}
+          value={formData.country}
+          onChange={e => {
+            setFormData({
+              ...formData,
+              country: e
+            })
+          }}
           styles={customStyles}
         />
       </div>
@@ -92,9 +76,14 @@ const Address = () => {
       <Select
           id="state"
           name="state"
-          options={updatedStates(country.isoCode)}
-          value={state}
-          onChange={setState}
+          options={updatedStates(formData.country.isoCode)}
+          value={formData.state}
+          onChange={e => {
+            setFormData({
+              ...formData,
+              state: e
+            })
+          }}
           styles={customStyles}
         />
       </div>
@@ -105,9 +94,14 @@ const Address = () => {
       <Select
           id="city"
           name="city"
-          options={updatedCities(country.isoCode, state.isoCode)}
-          value={city}
-          onChange={setCity}
+          options={updatedCities(formData.country.isoCode, formData.state.isoCode)}
+          value={formData.district}
+          onChange={e => {
+            setFormData({
+              ...formData,
+              district: e
+            })
+          }}
           styles={customStyles}
         />
       </div>
@@ -115,9 +109,14 @@ const Address = () => {
     <Input
       id="town"
       label="Village / Town"
-      value={town}
+      value={formData.village}
       type="text"
-      onChange={(e) => setTown(e.target.value)}
+      onChange={(e) => {
+        setFormData({
+          ...formData,
+          village: e.target.value
+        })
+      }}
       placeholder="Enter your Village / Town"
       />
             </div>
@@ -125,33 +124,53 @@ const Address = () => {
           <Input
             id="houseNo"
             label="House Number/ Apartment"
-            value={houseNo}
+            value={formData.houseNo}
             type="text"
-            onChange={(e) => setHouseNo(e.target.value)}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                houseNo: e.target.value
+              })
+            }}
             placeholder="Enter your House Number / Apartment"
           />
           <Input
             id="street"
             label="Street / Road"
-            value={street}
+            value={formData.street}
             type="text"
-            onChange={(e) => setStreet(e.target.value)}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                street: e.target.value
+              })
+            }}
             placeholder="Enter the Street / Road"
           />
           <Input
             id="locality"
             label="Area / Locality"
-            value={locality}
+            value={formData.locality}
             type="text"
-            onChange={(e) => setLocality(e.target.value)}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                locality: e.target.value
+              })
+            }}
             placeholder="Enter your Area / Locality"
           />
           <Input
             id="postOffice"
             label="Post Office"
-            value={postOffice}
+            value={formData.postOffice}
             type="text"
-            onChange={(e) => setPostOffice(e.target.value)}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                postOffice: e.target.value
+              })
+            }}
             placeholder="Enter your Village / Town"
           />
           </div>
@@ -159,23 +178,32 @@ const Address = () => {
           <Input
             id="landmark"
             label="Landmark"
-            value={landmark}
+            value={formData.landmark}
             type="text"
-            onChange={(e) => setLandmark(e.target.value)}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                landmark: e.target.value
+              })
+            }}
             placeholder="Enter the Landmark"
           />
           <Input
             id="pincode"
             label="Pincode"
-            value={pincode}
+            value={formData.pincode}
             type="text"
-            onChange={(e) => setPincode(e.target.value)}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                pincode: e.target.value
+              })
+            }}
             placeholder="Enter your area Pincode"
             pattern="[0-9]+"
           />
         </div>
-        <SubmitButton />
-      </form>
+      </div>
     </>
   )
 }
diff --git a/client/src/pages/Enrollment/FormOne/FormOne.jsx b/client/src/pages/Enrollment/FormOne/FormOne.jsx
index e9bff62..d245faf 100644
--- a/client/src/pages/Enrollment/FormOne/FormOne.jsx
+++ b/client/src/pages/Enrollment/FormOne/FormOne.jsx
@@ -1,95 +1,122 @@
-import React, { useState } from 'react'
+import React from 'react'
+import Header from '../../../components/Header/Header'
 import Input from '../../../components/Input/Input'
 import LabelCard from '../../../components/LabelCard/LabelCard'
 import styles from './FormOne.module.css'
 
-const FormOne = () => {
-  const [indianResident, setIndianResident] = useState(true)
-  const [fullName, setFullName] = useState('')
-  const [gender, setGender] = useState('')
-  const [dateOfBirth, setDateOfBirth] = useState(
-    new Date().toISOString().slice(0, 10)
-  )
+const FormOne = ({ formData, setFormData }) => {
+  console.log(formData.indianResident, formData.name, formData.dob, formData.gender)
 
-  console.log(fullName, indianResident, gender, dateOfBirth)
+  const handleSubmit = () => {
+  }
 
   return (
-    <div className={styles.formone}>
-      <div className={styles.formone__radio}>
-        <span className={styles.formone__resident}>
-          <input
-            type="radio"
-            id="indian"
-            name="resident"
-            value={indianResident}
-            onChange={() => setIndianResident(true)}
-            required
-          />
-          <label htmlFor="indian">Indian Resident</label>
-        </span>
-        <span className={styles.formone__resident}>
-          <input
-            type="radio"
-            id="indian"
-            name="resident"
-            value="Indian Resident"
-            onChange={() => setIndianResident(false)}
-            required
-          />
-          <label htmlFor="indian">Non-Residential Indian</label>
-        </span>
-      </div>
+    <><Header subheading="Enrollment" /><form onSubmit={() => handleSubmit()}>
+      <div className={styles.formone}>
+        <div className={styles.formone__radio}>
+          <span className={styles.formone__resident}>
+            <input
+              type="radio"
+              id="indian"
+              name="resident"
+              value={formData.indianResident}
+              onChange={() => {
+                setFormData({
+                  ...formData,
+                  indianResident: true
+                })
+              }}
+              required />
+            <label htmlFor="indian">Indian Resident</label>
+          </span>
+          <span className={styles.formone__resident}>
+            <input
+              type="radio"
+              id="indian"
+              name="resident"
+              value={formData.indianResident}
+              onChange={() => {
+                setFormData({
+                  ...formData,
+                  indianResident: false
+                })
+              }}
+              required />
+            <label htmlFor="indian">Non-Residential Indian</label>
+          </span>
+        </div>
 
-      <Input
-        type="text"
-        id="fullName"
-        label="Full Name"
-        value={fullName}
-        onChange={(e) => setFullName(e.target.value)}
-        placeholder="Enter your full name"
-        pattern="[a-zA-z]+"
-      />
+        <Input
+          type="text"
+          id="fullName"
+          label="Full Name"
+          value={formData.name}
+          onChange={(e) => {
+            setFormData({
+              ...formData,
+              name: e.target.value
+            })
+          }}
+          placeholder="Enter your full name"
+          pattern="[a-zA-z]+" />
 
-      <div className={styles.formone__gender}>
-        <LabelCard
-          id="male"
-          name="gender"
-          title="Male"
-          value={gender}
-          onChange={() => setGender('male')}
-          image={`${process.env.PUBLIC_URL}/assets/images/male.svg`}
-        />
-        <LabelCard
-          id="female"
-          name="gender"
-          value={gender}
-          title="Female"
-          onChange={() => setGender('female')}
-          image={`${process.env.PUBLIC_URL}/assets/images/female.svg`}
-        />
-        <LabelCard
-          id="trans"
-          name="gender"
-          value={gender}
-          title="Transgender"
-          onChange={() => setGender('transgender')}
-          image={`${process.env.PUBLIC_URL}/assets/images/trans.svg`}
-        />
-      </div>
+        <div className={styles.formone__gender}>
+          <LabelCard
+            id="male"
+            name="gender"
+            title="Male"
+            value={formData.gender}
+            onChange={() => {
+              setFormData({
+                ...formData,
+                gender: 'Male'
+              })
+            }}
+            image={`${process.env.PUBLIC_URL}/assets/images/male.svg`} />
+          <LabelCard
+            id="female"
+            name="gender"
+            value={formData.gender}
+            title="Female"
+            onChange={() => {
+              setFormData({
+                ...formData,
+                gender: 'Female'
+              })
+            }}
+            image={`${process.env.PUBLIC_URL}/assets/images/female.svg`} />
+          <LabelCard
+            id="trans"
+            name="gender"
+            value={formData.gender}
+            title="Transgender"
+            onChange={() => {
+              setFormData({
+                ...formData,
+                gender: 'Transgender'
+              })
+            }}
+            image={`${process.env.PUBLIC_URL}/assets/images/trans.svg`} />
+        </div>
 
-      <div className={styles.formone__dob}>
-        <label htmlFor="dob">Date of Birth</label>
-        <input
-          className={styles.formone__dob_input}
-          type="date"
-          id="dob"
-          name="dob"
-          value={dateOfBirth}
-          onChange={(e) => setDateOfBirth(e.target.value)}
-          required
-        />
+        <div className={styles.formone__dob}>
+          <label htmlFor="dob">Date of Birth</label>
+          <input
+            className={styles.formone__dob_input}
+            type="date"
+            id="dob"
+            name="dob"
+            value={formData.dob}
+            onChange={(e) => {
+              setFormData({
+                ...formData,
+                dob: e.target.value
+              })
+            }}
+            required />
+        </div>
       </div>
-    </div>
+    </form></>
   )
 }
 
diff --git a/client/src/pages/Enrollment/FormTwo/FormTwo.jsx b/client/src/pages/Enrollment/FormTwo/FormTwo.jsx
index a0aebcf..91d8f6b 100644
--- a/client/src/pages/Enrollment/FormTwo/FormTwo.jsx
+++ b/client/src/pages/Enrollment/FormTwo/FormTwo.jsx
@@ -1,44 +1,23 @@
-import React, { useState, useEffect } from 'react'
-import { useNavigate } from 'react-router-dom'
+import React from 'react'
 import Input from '../../../components/Input/Input'
 import Header from '../../../components/Header/Header'
 import SubmitButton from '../../../components/SubmitButton/SubmitButton'
 
-const FormTwo = () => {
-  const [mobileNumber, setMobileNumber] = useState('')
-  const [email, setEmail] = useState('')
-
-  const navigate = useNavigate()
-
-  const handleSubmit = () => {
-    navigate('/enrollment/address')
-  }
-
-  useEffect(() => {
-    const eMail = document.getElementById('email')
-    function emailValidator () {
-      if (eMail.validity.patternMismatch) {
-        eMail.setCustomValidity('Email must contain @')
-      } else {
-        eMail.setCustomValidity('')
-      }
-    }
-    console.log(eMail)
-    eMail.addEventListener('input', emailValidator)
-    return () => {
-      eMail.removeEventListener('input', emailValidator)
-    }
-  }, [])
-
+const FormTwo = ({ formData, setFormData }) => {
   return (
-    <form onSubmit={() => handleSubmit()} className="formtwo">
+    <div className="formtwo">
       <Header subheading="Enrollment" />
       <Input
         id="mobile"
-        value={mobileNumber}
+        value={formData.mobile}
         label="Mobile"
         type="text"
-        onChange={(e) => setMobileNumber(e.target.value)}
+        onChange={(e) => {
+          setFormData({
+            ...formData,
+            mobile: e.target.value
+          })
+        }}
         placeholder="Enter your Mobile Number"
         pattern="[0-9]+"
         maxLength="10"
@@ -46,15 +25,20 @@ const FormTwo = () => {
       />
       <Input
         id="email"
-        value={email}
+        value={formData.email}
         label="Email"
         type="email"
-        onChange={(e) => setEmail(e.target.value)}
+        onChange={(e) => {
+          setFormData({
+            ...formData,
+            email: e.target.value
+          })
+        }}
         placeholder="Enter your Email ID"
         pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
       />
       <SubmitButton />
-    </form>
+    </div>
   )
 }
 
diff --git a/client/src/pages/Home/Home.jsx b/client/src/pages/Home/Home.jsx
index b132f12..1c638b1 100644
--- a/client/src/pages/Home/Home.jsx
+++ b/client/src/pages/Home/Home.jsx
@@ -5,17 +5,18 @@ import Card from '../../components/Card/Card'
 import Header from '../../components/Header/Header'
 import styles from './Home.module.css'
 
-const Home = () => {
+const Home = ({ page, setPage }) => {
   return (
     <>
       <Header subheading="Mera Aadhaar Meri Pehchan" />
       <div className={styles.card__container}>
-        <Link to="/enrollment">
           <Card
             title="Enrollment"
             image={`${process.env.PUBLIC_URL}/assets/images/enrollment.svg`}
+            onClick={(e) => {
+              setPage(0)
+            }}
           />
-        </Link>
         <Link to="/update">
           <Card
             title="Update"
-- 
cgit 

