|
@@ -0,0 +1,399 @@
|
|
|
+import React, {useState, useEffect, useRef} from 'react'
|
|
|
+import logoDefault from './logo.svg';
|
|
|
+import './App.scss';
|
|
|
+import {Provider, connect} from 'react-redux';
|
|
|
+import {createStore, combineReducers, applyMiddleware} from 'redux';
|
|
|
+import thunk from 'redux-thunk';
|
|
|
+
|
|
|
+
|
|
|
+const Dots = ({active, count, onDot}) => {
|
|
|
+ const arr = []
|
|
|
+ for (let i=0; i<count; i++) {
|
|
|
+ arr.push(i)
|
|
|
+ }
|
|
|
+ return (
|
|
|
+ <div className='dotParent'>
|
|
|
+ {arr.map((i) => (i === active) ? <div className='dot red' onClick={() => onDot(i)}></div> : <div className='dot' onClick={() => onDot(i)}></div>)}
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+const Gallery = ({images=[ 'https://upload.wikimedia.org/wikipedia/commons/7/70/Cabbage.jpg',
|
|
|
+ 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Brassica_%28decorative_cultivar%29_01.jpg/800px-Brassica_%28decorative_cultivar%29_01.jpg',
|
|
|
+ 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Brassica_oleracea.jpg/800px-Brassica_oleracea.jpg',
|
|
|
+ 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Growing_Cauliflower.jpg/800px-Growing_Cauliflower.jpg',
|
|
|
+ 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Brassica_oleracea0.jpg/800px-Brassica_oleracea0.jpg',
|
|
|
+ 'https://upload.wikimedia.org/wikipedia/commons/c/c5/Cab-spring.jpg']}) => {
|
|
|
+
|
|
|
+ const [imgNumber, setImgNumber] = useState(0)
|
|
|
+
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <button onClick={() => setImgNumber(imgNumber => (imgNumber > 0) ? (imgNumber - 1) : (images.length - 1))}>prev</button>
|
|
|
+ <img src={images[imgNumber]} onClick={() => setImgNumber(imgNumber => (imgNumber < images.length - 1) ? (imgNumber + 1) : (0))}/>
|
|
|
+ <button onClick={() => setImgNumber(imgNumber => (imgNumber < images.length - 1) ? (imgNumber + 1) : (0))}>next</button>
|
|
|
+
|
|
|
+ <Dots active={imgNumber} count={images.length} onDot={(dotIndex) => setImgNumber(dotIndex)}/>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const countries = {
|
|
|
+ "AF": "Afghanistan",
|
|
|
+ "AX": "Aland Islands",
|
|
|
+ "AL": "Albania",
|
|
|
+ "DZ": "Algeria",
|
|
|
+ "AS": "American Samoa",
|
|
|
+ "AD": "Andorra",
|
|
|
+ "AO": "Angola",
|
|
|
+ "AI": "Anguilla",
|
|
|
+ "AQ": "Antarctica",
|
|
|
+ "AG": "Antigua And Barbuda",
|
|
|
+ "AR": "Argentina",
|
|
|
+ "AM": "Armenia",
|
|
|
+ "AW": "Aruba",
|
|
|
+ "AU": "Australia",
|
|
|
+ "AT": "Austria",
|
|
|
+ "AZ": "Azerbaijan",
|
|
|
+ "BS": "Bahamas",
|
|
|
+ "BH": "Bahrain",
|
|
|
+ "BD": "Bangladesh",
|
|
|
+ "BB": "Barbados",
|
|
|
+ "BY": "Belarus",
|
|
|
+ "BE": "Belgium",
|
|
|
+ "BZ": "Belize",
|
|
|
+ "BJ": "Benin",
|
|
|
+ "BM": "Bermuda",
|
|
|
+ "BT": "Bhutan",
|
|
|
+ "BO": "Bolivia",
|
|
|
+ "BA": "Bosnia And Herzegovina",
|
|
|
+ "BW": "Botswana",
|
|
|
+ "BV": "Bouvet Island",
|
|
|
+ "BR": "Brazil",
|
|
|
+ "IO": "British Indian Ocean Territory",
|
|
|
+ "BN": "Brunei Darussalam",
|
|
|
+ "BG": "Bulgaria",
|
|
|
+ "BF": "Burkina Faso",
|
|
|
+ "BI": "Burundi",
|
|
|
+ "KH": "Cambodia",
|
|
|
+ "CM": "Cameroon",
|
|
|
+ "CA": "Canada",
|
|
|
+ "CV": "Cape Verde",
|
|
|
+ "KY": "Cayman Islands",
|
|
|
+ "CF": "Central African Republic",
|
|
|
+ "TD": "Chad",
|
|
|
+ "CL": "Chile",
|
|
|
+ "CN": "China",
|
|
|
+ "CX": "Christmas Island",
|
|
|
+ "CC": "Cocos (Keeling) Islands",
|
|
|
+ "CO": "Colombia",
|
|
|
+ "KM": "Comoros",
|
|
|
+ "CG": "Congo",
|
|
|
+ "CD": "Congo, Democratic Republic",
|
|
|
+ "CK": "Cook Islands",
|
|
|
+ "CR": "Costa Rica",
|
|
|
+ "CI": "Cote D\"Ivoire",
|
|
|
+ "HR": "Croatia",
|
|
|
+ "CU": "Cuba",
|
|
|
+ "CY": "Cyprus",
|
|
|
+ "CZ": "Czech Republic",
|
|
|
+ "DK": "Denmark",
|
|
|
+ "DJ": "Djibouti",
|
|
|
+ "DM": "Dominica",
|
|
|
+ "DO": "Dominican Republic",
|
|
|
+ "EC": "Ecuador",
|
|
|
+ "EG": "Egypt",
|
|
|
+ "SV": "El Salvador",
|
|
|
+ "GQ": "Equatorial Guinea",
|
|
|
+ "ER": "Eritrea",
|
|
|
+ "EE": "Estonia",
|
|
|
+ "ET": "Ethiopia",
|
|
|
+ "FK": "Falkland Islands (Malvinas)",
|
|
|
+ "FO": "Faroe Islands",
|
|
|
+ "FJ": "Fiji",
|
|
|
+ "FI": "Finland",
|
|
|
+ "FR": "France",
|
|
|
+ "GF": "French Guiana",
|
|
|
+ "PF": "French Polynesia",
|
|
|
+ "TF": "French Southern Territories",
|
|
|
+ "GA": "Gabon",
|
|
|
+ "GM": "Gambia",
|
|
|
+ "GE": "Georgia",
|
|
|
+ "DE": "Germany",
|
|
|
+ "GH": "Ghana",
|
|
|
+ "GI": "Gibraltar",
|
|
|
+ "GR": "Greece",
|
|
|
+ "GL": "Greenland",
|
|
|
+ "GD": "Grenada",
|
|
|
+ "GP": "Guadeloupe",
|
|
|
+ "GU": "Guam",
|
|
|
+ "GT": "Guatemala",
|
|
|
+ "GG": "Guernsey",
|
|
|
+ "GN": "Guinea",
|
|
|
+ "GW": "Guinea-Bissau",
|
|
|
+ "GY": "Guyana",
|
|
|
+ "HT": "Haiti",
|
|
|
+ "HM": "Heard Island & Mcdonald Islands",
|
|
|
+ "VA": "Holy See (Vatican City State)",
|
|
|
+ "HN": "Honduras",
|
|
|
+ "HK": "Hong Kong",
|
|
|
+ "HU": "Hungary",
|
|
|
+ "IS": "Iceland",
|
|
|
+ "IN": "India",
|
|
|
+ "ID": "Indonesia",
|
|
|
+ "IR": "Iran, Islamic Republic Of",
|
|
|
+ "IQ": "Iraq",
|
|
|
+ "IE": "Ireland",
|
|
|
+ "IM": "Isle Of Man",
|
|
|
+ "IL": "Israel",
|
|
|
+ "IT": "Italy",
|
|
|
+ "JM": "Jamaica",
|
|
|
+ "JP": "Japan",
|
|
|
+ "JE": "Jersey",
|
|
|
+ "JO": "Jordan",
|
|
|
+ "KZ": "Kazakhstan",
|
|
|
+ "KE": "Kenya",
|
|
|
+ "KI": "Kiribati",
|
|
|
+ "KR": "Korea",
|
|
|
+ "KP": "North Korea",
|
|
|
+ "KW": "Kuwait",
|
|
|
+ "KG": "Kyrgyzstan",
|
|
|
+ "LA": "Lao People\"s Democratic Republic",
|
|
|
+ "LV": "Latvia",
|
|
|
+ "LB": "Lebanon",
|
|
|
+ "LS": "Lesotho",
|
|
|
+ "LR": "Liberia",
|
|
|
+ "LY": "Libyan Arab Jamahiriya",
|
|
|
+ "LI": "Liechtenstein",
|
|
|
+ "LT": "Lithuania",
|
|
|
+ "LU": "Luxembourg",
|
|
|
+ "MO": "Macao",
|
|
|
+ "MK": "Macedonia",
|
|
|
+ "MG": "Madagascar",
|
|
|
+ "MW": "Malawi",
|
|
|
+ "MY": "Malaysia",
|
|
|
+ "MV": "Maldives",
|
|
|
+ "ML": "Mali",
|
|
|
+ "MT": "Malta",
|
|
|
+ "MH": "Marshall Islands",
|
|
|
+ "MQ": "Martinique",
|
|
|
+ "MR": "Mauritania",
|
|
|
+ "MU": "Mauritius",
|
|
|
+ "YT": "Mayotte",
|
|
|
+ "MX": "Mexico",
|
|
|
+ "FM": "Micronesia, Federated States Of",
|
|
|
+ "MD": "Moldova",
|
|
|
+ "MC": "Monaco",
|
|
|
+ "MN": "Mongolia",
|
|
|
+ "ME": "Montenegro",
|
|
|
+ "MS": "Montserrat",
|
|
|
+ "MA": "Morocco",
|
|
|
+ "MZ": "Mozambique",
|
|
|
+ "MM": "Myanmar",
|
|
|
+ "NA": "Namibia",
|
|
|
+ "NR": "Nauru",
|
|
|
+ "NP": "Nepal",
|
|
|
+ "NL": "Netherlands",
|
|
|
+ "AN": "Netherlands Antilles",
|
|
|
+ "NC": "New Caledonia",
|
|
|
+ "NZ": "New Zealand",
|
|
|
+ "NI": "Nicaragua",
|
|
|
+ "NE": "Niger",
|
|
|
+ "NG": "Nigeria",
|
|
|
+ "NU": "Niue",
|
|
|
+ "NF": "Norfolk Island",
|
|
|
+ "MP": "Northern Mariana Islands",
|
|
|
+ "NO": "Norway",
|
|
|
+ "OM": "Oman",
|
|
|
+ "PK": "Pakistan",
|
|
|
+ "PW": "Palau",
|
|
|
+ "PS": "Palestinian Territory, Occupied",
|
|
|
+ "PA": "Panama",
|
|
|
+ "PG": "Papua New Guinea",
|
|
|
+ "PY": "Paraguay",
|
|
|
+ "PE": "Peru",
|
|
|
+ "PH": "Philippines",
|
|
|
+ "PN": "Pitcairn",
|
|
|
+ "PL": "Poland",
|
|
|
+ "PT": "Portugal",
|
|
|
+ "PR": "Puerto Rico",
|
|
|
+ "QA": "Qatar",
|
|
|
+ "RE": "Reunion",
|
|
|
+ "RO": "Romania",
|
|
|
+ "RU": "Russian Federation",
|
|
|
+ "RW": "Rwanda",
|
|
|
+ "BL": "Saint Barthelemy",
|
|
|
+ "SH": "Saint Helena",
|
|
|
+ "KN": "Saint Kitts And Nevis",
|
|
|
+ "LC": "Saint Lucia",
|
|
|
+ "MF": "Saint Martin",
|
|
|
+ "PM": "Saint Pierre And Miquelon",
|
|
|
+ "VC": "Saint Vincent And Grenadines",
|
|
|
+ "WS": "Samoa",
|
|
|
+ "SM": "San Marino",
|
|
|
+ "ST": "Sao Tome And Principe",
|
|
|
+ "SA": "Saudi Arabia",
|
|
|
+ "SN": "Senegal",
|
|
|
+ "RS": "Serbia",
|
|
|
+ "SC": "Seychelles",
|
|
|
+ "SL": "Sierra Leone",
|
|
|
+ "SG": "Singapore",
|
|
|
+ "SK": "Slovakia",
|
|
|
+ "SI": "Slovenia",
|
|
|
+ "SB": "Solomon Islands",
|
|
|
+ "SO": "Somalia",
|
|
|
+ "ZA": "South Africa",
|
|
|
+ "GS": "South Georgia And Sandwich Isl.",
|
|
|
+ "ES": "Spain",
|
|
|
+ "LK": "Sri Lanka",
|
|
|
+ "SD": "Sudan",
|
|
|
+ "SR": "Suriname",
|
|
|
+ "SJ": "Svalbard And Jan Mayen",
|
|
|
+ "SZ": "Swaziland",
|
|
|
+ "SE": "Sweden",
|
|
|
+ "CH": "Switzerland",
|
|
|
+ "SY": "Syrian Arab Republic",
|
|
|
+ "TW": "Taiwan",
|
|
|
+ "TJ": "Tajikistan",
|
|
|
+ "TZ": "Tanzania",
|
|
|
+ "TH": "Thailand",
|
|
|
+ "TL": "Timor-Leste",
|
|
|
+ "TG": "Togo",
|
|
|
+ "TK": "Tokelau",
|
|
|
+ "TO": "Tonga",
|
|
|
+ "TT": "Trinidad And Tobago",
|
|
|
+ "TN": "Tunisia",
|
|
|
+ "TR": "Turkey",
|
|
|
+ "TM": "Turkmenistan",
|
|
|
+ "TC": "Turks And Caicos Islands",
|
|
|
+ "TV": "Tuvalu",
|
|
|
+ "UG": "Uganda",
|
|
|
+ "UA": "Ukraine",
|
|
|
+ "AE": "United Arab Emirates",
|
|
|
+ "GB": "United Kingdom",
|
|
|
+ "US": "United States",
|
|
|
+ "UM": "United States Outlying Islands",
|
|
|
+ "UY": "Uruguay",
|
|
|
+ "UZ": "Uzbekistan",
|
|
|
+ "VU": "Vanuatu",
|
|
|
+ "VE": "Venezuela",
|
|
|
+ "VN": "Vietnam",
|
|
|
+ "VG": "Virgin Islands, British",
|
|
|
+ "VI": "Virgin Islands, U.S.",
|
|
|
+ "WF": "Wallis And Futuna",
|
|
|
+ "EH": "Western Sahara",
|
|
|
+ "YE": "Yemen",
|
|
|
+ "ZM": "Zambia",
|
|
|
+ "ZW": "Zimbabwe"
|
|
|
+}
|
|
|
+
|
|
|
+const MySelect = ({options=countries, value='ZW', onChange}) => (
|
|
|
+ <select defaultValue={value} onChange={(e) => onChange(e.target.value)}>
|
|
|
+ {Object.entries(options).map(([key, cont]) => <option value={key}>{key}: {cont}</option> )}
|
|
|
+ </select>
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const PhoneBookEntry = ({data={name:'',phone:''}, index, onChange,
|
|
|
+ onMoveUp,
|
|
|
+ onMoveDown,
|
|
|
+ onDelete,
|
|
|
+ onAdd}) => (
|
|
|
+ <div>
|
|
|
+ <input type="text" value={data.name} onChange={(e) => onChange({name: e.target.value, phone: data.phone}, index)} />
|
|
|
+ <input type="number" value={data.phone} onChange={(e) => onChange({name: data.name, phone: e.target.value}, index)} />
|
|
|
+ <button onClick={onMoveUp}>^</button>
|
|
|
+ <button onClick={onMoveDown}>v</button>
|
|
|
+ <button onClick={onDelete}>x</button>
|
|
|
+ <button onClick={onAdd}>+</button>
|
|
|
+ </div>
|
|
|
+)
|
|
|
+
|
|
|
+const defaultPeople = [{name: 'Vasya', phone: '101'}, {name: 'Jhon', phone: '102'}, {name: 'Paul', phone: '103'}]
|
|
|
+
|
|
|
+const PhoneBook = ({people=defaultPeople, onSave}) => {
|
|
|
+ const [ppl, setPpl] = useState(people)
|
|
|
+ const [keys, setKeys] = useState(people.map(() => Math.random()))
|
|
|
+ //const {current: keys} = useRef(people.map(() => Math.random()))
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ setPpl(people)
|
|
|
+ setKeys(people.map(() => Math.random()))
|
|
|
+ }, [people])
|
|
|
+
|
|
|
+ const onChange = (newData, i) => {
|
|
|
+ ppl[i] = newData
|
|
|
+ setPpl([...ppl])
|
|
|
+ }
|
|
|
+ const onMoveUp = (i) => {
|
|
|
+ if (i > 0) {
|
|
|
+ [ppl[i-1], ppl[i]] = [ppl[i], ppl[i-1]];
|
|
|
+ [keys[i-1], keys[i]] = [keys[i], keys[i-1]]
|
|
|
+ }
|
|
|
+ setPpl([...ppl])
|
|
|
+ setKeys([...keys])
|
|
|
+ }
|
|
|
+ const onMoveDown = (i) => {
|
|
|
+ if (i < ppl.length - 1) {
|
|
|
+ [ppl[i], ppl[i+1]] = [ppl[i+1], ppl[i]];
|
|
|
+ [keys[i], keys[i+1]] = [keys[i+1], keys[i]]
|
|
|
+ }
|
|
|
+ setPpl([...ppl])
|
|
|
+ setKeys([...keys])
|
|
|
+ }
|
|
|
+ const onDelete = (i) => {
|
|
|
+ setPpl(ppl.filter((el, index) => index !== i))
|
|
|
+ setKeys(keys.filter((el, index) => index !== i))
|
|
|
+ }
|
|
|
+ const onAdd = (i) => {
|
|
|
+ ppl.splice(i+1, 0, {name:'',phone:''})
|
|
|
+ keys.splice(i+1, 0, Math.random())
|
|
|
+ setPpl([...ppl])
|
|
|
+ setKeys([...keys])
|
|
|
+ }
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <button onClick={() => { setPpl([{name:'',phone:''}, ...ppl])
|
|
|
+ setKeys([Math.random(), ...keys])
|
|
|
+ } }>+</button>
|
|
|
+ <div className='PhoneBook'>
|
|
|
+ {ppl.map((data, i) => (
|
|
|
+ <PhoneBookEntry data={data} index={i}
|
|
|
+ onChange={onChange}
|
|
|
+ onMoveUp={() => onMoveUp(i)}
|
|
|
+ onMoveDown={() => onMoveDown(i)}
|
|
|
+ onDelete={() => onDelete(i)}
|
|
|
+ onAdd={() => onAdd(i)}
|
|
|
+ />)
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ <button onClick={() => onSave(ppl, keys)}>Save</button>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+function App() {
|
|
|
+ const [country, setCountry] = useState('UA')
|
|
|
+ console.log(country)
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="App">
|
|
|
+
|
|
|
+ <Gallery />
|
|
|
+
|
|
|
+ <MySelect value={country} onChange={newCountry => setCountry(newCountry)}/>
|
|
|
+
|
|
|
+ <PhoneBook onSave={(ppl, keys) => console.log(ppl, keys)}/>
|
|
|
+
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+export default App;
|