|
|
|
@ -1,362 +1,77 @@
|
|
|
|
|
import React, { useState } from 'react'
|
|
|
|
|
import ReactDOM from 'react-dom'
|
|
|
|
|
import React, { useState, useEffect } from 'react'
|
|
|
|
|
import axios from 'axios'
|
|
|
|
|
import ReactDOM, { findDOMNode } from 'react-dom'
|
|
|
|
|
|
|
|
|
|
const Country = ({
|
|
|
|
|
country: { name, capital, flag, languages, population, currency },
|
|
|
|
|
}) => {
|
|
|
|
|
const formattedCapital =
|
|
|
|
|
capital.length > 0 ? (
|
|
|
|
|
<>
|
|
|
|
|
<span>Capital: </span>
|
|
|
|
|
{capital}
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
''
|
|
|
|
|
)
|
|
|
|
|
const formattedLanguage = languages.length > 1 ? `Languages` : `Language`
|
|
|
|
|
|
|
|
|
|
const options = [
|
|
|
|
|
{
|
|
|
|
|
value: '',
|
|
|
|
|
label: '-- Select Country--',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: 'Finland',
|
|
|
|
|
label: 'Finland',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: 'Sweden',
|
|
|
|
|
label: 'Sweden',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: 'Norway',
|
|
|
|
|
label: 'Norway',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: 'Denmark',
|
|
|
|
|
label: 'Denmark',
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// mapping the options to list(array) of JSX options
|
|
|
|
|
|
|
|
|
|
const selectOptions = options.map(({ value, label }) => (
|
|
|
|
|
<option key={label} value={value}>
|
|
|
|
|
{' '}
|
|
|
|
|
{label}
|
|
|
|
|
</option>
|
|
|
|
|
))
|
|
|
|
|
return (
|
|
|
|
|
<div className='country'>
|
|
|
|
|
<div className='country_flag'>
|
|
|
|
|
<img src={flag} alt={name} />
|
|
|
|
|
</div>
|
|
|
|
|
<h3 className='country_name'>{name.toUpperCase()}</h3>
|
|
|
|
|
<div class='country_text'>
|
|
|
|
|
<p>{formattedCapital}</p>
|
|
|
|
|
<p>
|
|
|
|
|
<span>{formattedLanguage}: </span>
|
|
|
|
|
{languages.map((language) => language.name).join(', ')}
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
<span>Population: </span>
|
|
|
|
|
{population.toLocaleString()}
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
<span>Currency: </span>
|
|
|
|
|
{currency}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const App = (props) => {
|
|
|
|
|
const initialState = {
|
|
|
|
|
firstName: '',
|
|
|
|
|
lastName: '',
|
|
|
|
|
email: '',
|
|
|
|
|
title: '',
|
|
|
|
|
country: '',
|
|
|
|
|
tel: '',
|
|
|
|
|
dateOfBirth: '',
|
|
|
|
|
favoriteColor: '',
|
|
|
|
|
weight: '',
|
|
|
|
|
gender: '',
|
|
|
|
|
file: '',
|
|
|
|
|
bio: '',
|
|
|
|
|
skills: {
|
|
|
|
|
html: false,
|
|
|
|
|
css: false,
|
|
|
|
|
javascript: false,
|
|
|
|
|
},
|
|
|
|
|
touched: {
|
|
|
|
|
firstName: false,
|
|
|
|
|
lastName: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
const [formData, setFormData] = useState(initialState)
|
|
|
|
|
|
|
|
|
|
const onChange = (e) => {
|
|
|
|
|
/*
|
|
|
|
|
we can get the name and value like: e.target.name, e.target.value
|
|
|
|
|
Wwe can also destructure name and value from e.target
|
|
|
|
|
const name = e.target.name
|
|
|
|
|
const value = e.target.value
|
|
|
|
|
*/
|
|
|
|
|
const { name, value, type, checked } = e.target
|
|
|
|
|
/*
|
|
|
|
|
[variablename] we can make a value stored in a certain variable could be a key for an object, in this case a key for the state
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (type === 'checkbox') {
|
|
|
|
|
setFormData({
|
|
|
|
|
...formData,
|
|
|
|
|
skills: { ...formData.skills, [name]: checked },
|
|
|
|
|
})
|
|
|
|
|
} else if (type === 'file') {
|
|
|
|
|
setFormData({ ...formData, [name]: e.target.files[0] })
|
|
|
|
|
} else {
|
|
|
|
|
setFormData({ ...formData, [name]: value })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const onSubmit = (e) => {
|
|
|
|
|
/*
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
stops the default behavior of form element
|
|
|
|
|
specifically refreshing of page
|
|
|
|
|
*/
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
const {
|
|
|
|
|
firstName,
|
|
|
|
|
lastName,
|
|
|
|
|
title,
|
|
|
|
|
email,
|
|
|
|
|
tel,
|
|
|
|
|
dateOfBirth,
|
|
|
|
|
favoriteColor,
|
|
|
|
|
weight,
|
|
|
|
|
country,
|
|
|
|
|
gender,
|
|
|
|
|
bio,
|
|
|
|
|
file,
|
|
|
|
|
skills,
|
|
|
|
|
} = formData
|
|
|
|
|
|
|
|
|
|
const formattedSkills = []
|
|
|
|
|
for (const key in skills) {
|
|
|
|
|
console.log(key)
|
|
|
|
|
if (skills[key]) {
|
|
|
|
|
formattedSkills.push(key.toUpperCase())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const data = {
|
|
|
|
|
firstName,
|
|
|
|
|
lastName,
|
|
|
|
|
title,
|
|
|
|
|
email,
|
|
|
|
|
tel,
|
|
|
|
|
dateOfBirth,
|
|
|
|
|
favoriteColor,
|
|
|
|
|
weight,
|
|
|
|
|
country,
|
|
|
|
|
gender,
|
|
|
|
|
bio,
|
|
|
|
|
file,
|
|
|
|
|
skills: formattedSkills,
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
the is the place where we connect backend api
|
|
|
|
|
to send the data to the database
|
|
|
|
|
*/
|
|
|
|
|
console.log(data)
|
|
|
|
|
}
|
|
|
|
|
const onBlur = (e) => {
|
|
|
|
|
const { name } = e.target
|
|
|
|
|
setFormData({ ...formData, touched: { ...formData.touched, [name]: true } })
|
|
|
|
|
}
|
|
|
|
|
const validate = () => {
|
|
|
|
|
// Object to collect error feedback and to display on the form
|
|
|
|
|
const errors = {
|
|
|
|
|
firstName: '',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
(formData.touched.firstName && formData.firstName.length < 3) ||
|
|
|
|
|
(formData.touched.firstName && formData.firstName.length > 12)
|
|
|
|
|
) {
|
|
|
|
|
errors.firstName = 'First name must be between 2 and 12'
|
|
|
|
|
// setting initial state and method to update state
|
|
|
|
|
const [data, setData] = useState([])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
fetchData()
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
const fetchData = async () => {
|
|
|
|
|
const url = 'https://restcountries.eu/rest/v2/all'
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(url)
|
|
|
|
|
const data = await response.json()
|
|
|
|
|
setData(data)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error)
|
|
|
|
|
}
|
|
|
|
|
return errors
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// accessing the state value by destrutcturing the state
|
|
|
|
|
const {
|
|
|
|
|
firstName,
|
|
|
|
|
lastName,
|
|
|
|
|
title,
|
|
|
|
|
country,
|
|
|
|
|
email,
|
|
|
|
|
tel,
|
|
|
|
|
dateOfBirth,
|
|
|
|
|
favoriteColor,
|
|
|
|
|
weight,
|
|
|
|
|
gender,
|
|
|
|
|
bio,
|
|
|
|
|
} = formData
|
|
|
|
|
|
|
|
|
|
const errors = validate()
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className='App'>
|
|
|
|
|
<h3>Add Student</h3>
|
|
|
|
|
<form onSubmit={onSubmit}>
|
|
|
|
|
<div className='row'>
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='firstName'>First Name </label>
|
|
|
|
|
<input
|
|
|
|
|
type='text'
|
|
|
|
|
id='firstName'
|
|
|
|
|
name='firstName'
|
|
|
|
|
value={firstName}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
onBlur={onBlur}
|
|
|
|
|
placeholder='First Name'
|
|
|
|
|
/>
|
|
|
|
|
<br />
|
|
|
|
|
{errors.firstName && <small>{errors.firstName}</small>}
|
|
|
|
|
</div>
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='lastName'>Last Name </label>
|
|
|
|
|
<input
|
|
|
|
|
type='text'
|
|
|
|
|
id='lastName'
|
|
|
|
|
name='lastName'
|
|
|
|
|
value={lastName}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
placeholder='Last Name'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='title'>Title </label>
|
|
|
|
|
<input
|
|
|
|
|
type='text'
|
|
|
|
|
id='title'
|
|
|
|
|
name='title'
|
|
|
|
|
placeholder='Title'
|
|
|
|
|
value={title}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='email'>Email </label>
|
|
|
|
|
<input
|
|
|
|
|
type='email'
|
|
|
|
|
id='email'
|
|
|
|
|
name='email'
|
|
|
|
|
value={email}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
placeholder='Email'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='tel'>Telephone </label>
|
|
|
|
|
<input
|
|
|
|
|
type='tel'
|
|
|
|
|
id='tel'
|
|
|
|
|
name='tel'
|
|
|
|
|
value={tel}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
placeholder='Tel'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='dateOfBirth'>Date of birth </label>
|
|
|
|
|
<input
|
|
|
|
|
type='date'
|
|
|
|
|
id='dateOfBirth'
|
|
|
|
|
name='dateOfBirth'
|
|
|
|
|
value={dateOfBirth}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
placeholder='Date of Birth'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='favoriteColor'>Favorite Color</label>
|
|
|
|
|
<input
|
|
|
|
|
type='color'
|
|
|
|
|
id='color'
|
|
|
|
|
name='favoriteColor'
|
|
|
|
|
value={favoriteColor}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
placeholder='Favorite Color'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className='form-group'>
|
|
|
|
|
<label htmlFor='weight'>Weight </label>
|
|
|
|
|
<input
|
|
|
|
|
type='number'
|
|
|
|
|
id='weight'
|
|
|
|
|
name='weight'
|
|
|
|
|
value={weight}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
placeholder='Weight in Kg'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label htmlFor='country'>Country</label> <br />
|
|
|
|
|
<select
|
|
|
|
|
name='country'
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
id='country'
|
|
|
|
|
value={country}
|
|
|
|
|
>
|
|
|
|
|
{selectOptions}
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<p>Gender</p>
|
|
|
|
|
<div>
|
|
|
|
|
<input
|
|
|
|
|
type='radio'
|
|
|
|
|
id='female'
|
|
|
|
|
name='gender'
|
|
|
|
|
value='Female'
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
checked={gender === 'Female'}
|
|
|
|
|
/>
|
|
|
|
|
<label htmlFor='female'>Female</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<input
|
|
|
|
|
id='male'
|
|
|
|
|
type='radio'
|
|
|
|
|
name='gender'
|
|
|
|
|
value='Male'
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
checked={gender === 'Male'}
|
|
|
|
|
/>
|
|
|
|
|
<label htmlFor='male'>Male</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<input
|
|
|
|
|
id='other'
|
|
|
|
|
type='radio'
|
|
|
|
|
name='gender'
|
|
|
|
|
value='Other'
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
checked={gender === 'Other'}
|
|
|
|
|
/>
|
|
|
|
|
<label htmlFor='other'>Other</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<p>Select your skills</p>
|
|
|
|
|
<div>
|
|
|
|
|
<input type='checkbox' id='html' name='html' onChange={onChange} />
|
|
|
|
|
<label htmlFor='html'>HTML</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<input type='checkbox' id='css' name='css' onChange={onChange} />
|
|
|
|
|
<label htmlFor='css'>CSS</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<input
|
|
|
|
|
type='checkbox'
|
|
|
|
|
id='javascript'
|
|
|
|
|
name='javascript'
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
/>
|
|
|
|
|
<label htmlFor='javascript'>JavaScript</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label htmlFor='bio'>Bio</label> <br />
|
|
|
|
|
<textarea
|
|
|
|
|
id='bio'
|
|
|
|
|
name='bio'
|
|
|
|
|
value={bio}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
cols='120'
|
|
|
|
|
rows='10'
|
|
|
|
|
placeholder='Write about yourself ...'
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<input type='file' name='file' onChange={onChange} />
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<button>Submit</button>
|
|
|
|
|
<h1>Fetching Data Using Hook</h1>
|
|
|
|
|
<h1>Calling API</h1>
|
|
|
|
|
<div>
|
|
|
|
|
<p>There are {data.length} countries in the api</p>
|
|
|
|
|
<div className='countries-wrapper'>
|
|
|
|
|
{data.map((country) => (
|
|
|
|
|
<Country country={country} />
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|