Skip to content

Commit 20bfe32

Browse files
authored
Merge pull request #9 from epythonlab/react
Update api data
2 parents bcff9e2 + 584c646 commit 20bfe32

File tree

9 files changed

+262
-83
lines changed

9 files changed

+262
-83
lines changed

nodejs/routes/applicant.routes.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,25 @@ router.get('/list-applicants', (req, res) => {
3434

3535
// url: http://localhost:4000/applicants/list-applicants
3636

37+
/* Update applicant data
38+
First: get a single applicant data by ID
39+
*/
40+
router.get('/update-applicant/:id', (req, res) =>{
41+
// findById() takes a single parameter, the document id.
42+
// it returns a promise that resolves to the Mongoose document
43+
// if MongoDB found a document with the given id
44+
// or null if no document was found.
45+
applicantSchema.findById(req.params.id)
46+
.then(data => res.json(data))
47+
.catch(err => res.status(404).json({dataError: 'Data not found in this id'}))
48+
});
49+
// url: http://localhost:4000/applicants/update-applicant/document_id
50+
51+
// update a specified applicant data
52+
router.put('/update-applicant/:id', (req, res) => {
53+
applicantSchema.findByIdAndUpdate(req.params.id, req.body)
54+
.then(data => res.json({ msg: 'Data updated successfully' }))
55+
.catch(err => res.status(400).json({ error: 'Unable to update this data' }));
56+
});
3757
// export the router
3858
module.exports = router

react/reactapp/src/App.css

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,22 @@
3636
transform: rotate(360deg);
3737
}
3838
}
39+
.container {
40+
display: block;
41+
max-width: 90%;
42+
width: 100%;
43+
margin: 50px auto;
44+
padding: 10px;
45+
border-radius: 0 #8c6a55;
46+
height: 100%;
47+
48+
}
49+
50+
@media (max-width: 767px) {
3951

40-
.container{
41-
padding: 20px;
52+
.container{
53+
min-width: 100%;
54+
min-height: 100%;
55+
margin: 20px auto;
56+
}
4257
}

react/reactapp/src/App2.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import './App.css';
1010
import Login from './components/login/Login'; // Login component from components
1111
import Dashboard from './components/Dashboard/Dashboard' // import Dashboard component
1212
import UseToken from './components/useToken';
13+
import Navbar from './components/Header/Navbar'
1314
import ApplicationForm from './components/Dashboard/ApplicationForm'
1415
import ShowApplicants from './components/Dashboard/ShowApplicants'
15-
import Navbar from './components/Header/Navbar'
16+
import EditApplicant from './components/Dashboard/EditApplicant'
1617

1718
/* Add BrowserRouter, then add a Routes component as a child
1819
in the return method
@@ -29,18 +30,23 @@ function App() {
2930
<div className="container">
3031

3132
<BrowserRouter>
32-
<Routes>
33-
<Route path="/" element={<ApplicationForm />}>
34-
</Route>
35-
</Routes>
36-
<Routes>
37-
<Route path="/application" element={<ApplicationForm />}>
38-
</Route>
39-
</Routes>
40-
<Routes>
41-
<Route path="/list-applicants" element={<ShowApplicants />}>
42-
</Route>
43-
</Routes>
33+
<Routes>
34+
<Route path="/" element={<ApplicationForm />}>
35+
</Route>
36+
</Routes>
37+
<Routes>
38+
<Route path="/application" element={<ApplicationForm />}>
39+
</Route>
40+
</Routes>
41+
<Routes>
42+
<Route path="/list-applicants" element={<ShowApplicants />}>
43+
</Route>
44+
</Routes>
45+
46+
<Routes>
47+
<Route path="/edit-applicant/:id" element={<EditApplicant />}>
48+
</Route>
49+
</Routes>
4450
</BrowserRouter>
4551
</div>
4652
</>

react/reactapp/src/components/Dashboard/ApplicationForm.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ function ApplicationForm(){
5858
//console.log({formValues})
5959
// return the form layout
6060
return (
61-
<div className="form-container">
62-
<div className="title">Application Form</div>
61+
<div className='form-wraper'>
62+
<div className="form-container">
63+
<div className="title">Application Form</div>
6364
<form onSubmit={handleSubmit} >
6465
<div className="user__details">
6566
<div className="input__box">
@@ -103,6 +104,7 @@ function ApplicationForm(){
103104
<input type="submit" value='Apply' />
104105
</div>
105106
</form>
107+
</div>
106108
</div>
107109
);
108110
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import {useState, useEffect} from 'react';
2+
import {useParams, useNavigate} from 'react-router-dom'
3+
import axios from 'axios';
4+
/* edit applicant data with id */
5+
6+
function EditApplicant(){
7+
8+
// define states
9+
const [applicant, setApplicant] = useState([])
10+
const {id} = useParams();
11+
/* useParams is one of the several react hooks in ract router
12+
it used to retreive route paramaters from the component
13+
rendered by the matching route
14+
*/
15+
// add title
16+
useEffect(() =>{
17+
document.title ='Aplicants List';
18+
})
19+
20+
// API: get a single applicant data by ID
21+
useEffect(() =>{
22+
// string formatting: template literals are enclosed in backticks
23+
axios.get(`http://localhost:4000/applicants/update-applicant/${id}`)
24+
.then((res) =>{
25+
setApplicant(res.data);
26+
})
27+
.catch((err) =>{
28+
console.log("Error:" + err.message)
29+
});
30+
}, [id]);
31+
32+
//console.log(applicant)
33+
34+
/* handle onChange and onSubmit to update the specified applicant data */
35+
// Define the state with useState hook
36+
const navigate = useNavigate();
37+
const [formValues, setFormValues] = useState({})
38+
39+
// define onChange to get form values
40+
const handleChange = (event) => {
41+
const name = event.target.name;
42+
const value = event.target.value;
43+
44+
setFormValues(values => ({...values, [name]: value}))
45+
}
46+
//define form submit handler
47+
48+
const handleSubmit = (event) => {
49+
event.preventDefault();
50+
axios.put(
51+
`http://localhost:4000/applicants/update-applicant/${id}`, formValues)
52+
.then(res => {
53+
if(res.status ===200){
54+
alert('A record successfuly updated')
55+
// Push to /
56+
navigate('/list-applicants')
57+
}else{
58+
Promise.reject()
59+
}
60+
})
61+
.catch(err => alert('Something went wrong! ' +err.message))
62+
// Push to /
63+
navigate('/list-applicants')
64+
}
65+
66+
67+
return (
68+
<div className='form-wraper'>
69+
<div className="form-container">
70+
<div className="title">Application Form</div>
71+
<form onSubmit={handleSubmit} >
72+
<div className="user__details">
73+
<div className="input__box">
74+
<span className="details">First Name</span>
75+
<input type="text" name='first_name' placeholder="E.g: Asibeh"
76+
defaultValue = {applicant.first_name} onChange={handleChange} required />
77+
</div>
78+
<div className="input__box">
79+
<span className="details">Last Name</span>
80+
<input type="text" name='last_name' placeholder="E.g: Tenager"
81+
defaultValue={applicant.last_name} onChange={handleChange} required />
82+
</div>
83+
84+
<div className="input__box">
85+
<span className="details">Email</span>
86+
<input type="email" name='email' placeholder="asibeh@gmail.com"
87+
defaultValue= {applicant.email} onChange={handleChange} required />
88+
</div>
89+
<div className="input__box">
90+
<span className="details">Phone Number</span>
91+
<input type="tel" name='phone_number' pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
92+
defaultValue= {applicant.phone_number} placeholder="092-345-6787"
93+
onChange={handleChange} required />
94+
</div>
95+
</div>
96+
<div className="gender__details" onChange={handleChange}>
97+
<input type="radio" name="gender" id="dot-1" value='Male'/>
98+
<input type="radio" name="gender" id="dot-2" value='Female'/>
99+
<span className="gender__title">Gender</span>
100+
<div className="category">
101+
<label htmlFor="dot-1">
102+
<span className="dot one"></span>
103+
<span>Male</span>
104+
</label>
105+
<label htmlFor="dot-2">
106+
<span className="dot two"></span>
107+
<span>Female</span>
108+
</label>
109+
</div>
110+
</div>
111+
<div className="button">
112+
<input type="submit" value='Update' />
113+
</div>
114+
</form>
115+
</div>
116+
</div>
117+
)
118+
}
119+
export default EditApplicant;

react/reactapp/src/components/Dashboard/ShowApplicants.js

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,26 @@ import {Link} from 'react-router-dom'
99

1010
function ShowApplicants(){
1111

12-
/
12+
// define state variable to store data from api
13+
const [applicants, setApplicants] = useState([]);
14+
15+
// add title
16+
useEffect(() =>{
17+
document.title ='Aplicants List';
18+
})
19+
20+
// API: get data from mongoDB database
21+
useEffect(() =>{
22+
axios.get('http://localhost:4000/applicants/list-applicants')
23+
.then((res) =>{
24+
setApplicants(res.data); // set api data to useState as an array
25+
})
26+
.catch(err => { // catch error message
27+
console.log('Data not found.' +err.message)
28+
});
29+
}, []);
30+
31+
//console.log(applicants)
1332

1433
return (
1534

@@ -24,7 +43,7 @@ function ShowApplicants(){
2443
<th>Gender</th>
2544
<th>Phone Number</th>
2645
<th>Email</th>
27-
<th>Updated Date</th>
46+
<th>Last Updated</th>
2847
<th>Action</th>
2948
</tr>
3049
</thead>
@@ -36,10 +55,26 @@ function ShowApplicants(){
3655
3756
add a unique key to the returned component of each tr as prop
3857
*/}
39-
<tbody>
40-
41-
{/* here will display data in a table row */}
42-
</tbody>
58+
{applicants.map((data, i) =>(
59+
<tr key={data._id}>
60+
<td>{++i}</td>
61+
<td>{data.first_name}</td>
62+
<td>{data.last_name}</td>
63+
<td>{data.gender}</td>
64+
<td>{data.phone_number}</td>
65+
<td>{data.email}</td>
66+
<td>{data.date_updated}</td>
67+
<td>
68+
<Link className="edit-link" to={`/edit-applicant/${data._id}`}>
69+
<i className="fa-solid fa-pen-to-square"></i></Link>
70+
&nbsp;&nbsp;&nbsp;&nbsp;
71+
<Link className="edit-link" to={"/delete-applicant/" + data._id}>
72+
<i className="fa-sharp fa-solid fa-trash" style={{color:'#f41032'}}></i>
73+
</Link>
74+
</td>
75+
</tr>
76+
))}
77+
</tbody>
4378
</table>
4479
</div>
4580
)

react/reactapp/src/components/Dashboard/formStyle.css

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,22 @@
1717

1818

1919
/* form-container and form */
20+
.form-wraper {
21+
display: flex;
22+
align-items: center;
23+
justify-content: center;
24+
height: 100vh;
25+
min-width: 100%;
26+
padding: 10px;
27+
}
2028
.form-container {
2129
max-width: 700px;
2230
width: 100%;
2331
background: #fff;
2432
padding: 25px 30px;
2533
border-radius: 5px;
34+
margin-bottom: 50px;
35+
background-color: #f2f2f2;
2636
}
2737
.form-container .title {
2838
font-size: 25px;
@@ -140,8 +150,8 @@ form .button input:hover {
140150
@media only screen and (max-width: 584px) {
141151
.form-container {
142152
max-width: 100%;
143-
height: 90%;
144-
margin-top: 35%;
153+
height: 77%;
154+
margin-top: 5%;
145155
margin-bottom: 25%;
146156
}
147157

0 commit comments

Comments
 (0)