App.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import React, {useState, useEffect, useRef} from 'react'
  2. import logoDefault from './logo.svg';
  3. import './App.scss';
  4. import {Provider, connect} from 'react-redux';
  5. import {createStore, combineReducers, applyMiddleware} from 'redux';
  6. import thunk from 'redux-thunk';
  7. const Dots = ({active, count, onDot}) => {
  8. const arr = []
  9. for (let i=0; i<count; i++) {
  10. arr.push(i)
  11. }
  12. return (
  13. <div className='dotParent'>
  14. {arr.map((i) => (i === active) ? <div className='dot red' onClick={() => onDot(i)}></div> : <div className='dot' onClick={() => onDot(i)}></div>)}
  15. </div>
  16. )
  17. }
  18. const Gallery = ({images=[ 'https://upload.wikimedia.org/wikipedia/commons/7/70/Cabbage.jpg',
  19. 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Brassica_%28decorative_cultivar%29_01.jpg/800px-Brassica_%28decorative_cultivar%29_01.jpg',
  20. 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Brassica_oleracea.jpg/800px-Brassica_oleracea.jpg',
  21. 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Growing_Cauliflower.jpg/800px-Growing_Cauliflower.jpg',
  22. 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Brassica_oleracea0.jpg/800px-Brassica_oleracea0.jpg',
  23. 'https://upload.wikimedia.org/wikipedia/commons/c/c5/Cab-spring.jpg']}) => {
  24. const [imgNumber, setImgNumber] = useState(0)
  25. return (
  26. <>
  27. <button onClick={() => setImgNumber(imgNumber => (imgNumber > 0) ? (imgNumber - 1) : (images.length - 1))}>prev</button>
  28. <img src={images[imgNumber]} onClick={() => setImgNumber(imgNumber => (imgNumber < images.length - 1) ? (imgNumber + 1) : (0))}/>
  29. <button onClick={() => setImgNumber(imgNumber => (imgNumber < images.length - 1) ? (imgNumber + 1) : (0))}>next</button>
  30. <Dots active={imgNumber} count={images.length} onDot={(dotIndex) => setImgNumber(dotIndex)}/>
  31. </>
  32. )
  33. }
  34. const countries = {
  35. "AF": "Afghanistan",
  36. "AX": "Aland Islands",
  37. "AL": "Albania",
  38. "DZ": "Algeria",
  39. "AS": "American Samoa",
  40. "AD": "Andorra",
  41. "AO": "Angola",
  42. "AI": "Anguilla",
  43. "AQ": "Antarctica",
  44. "AG": "Antigua And Barbuda",
  45. "AR": "Argentina",
  46. "AM": "Armenia",
  47. "AW": "Aruba",
  48. "AU": "Australia",
  49. "AT": "Austria",
  50. "AZ": "Azerbaijan",
  51. "BS": "Bahamas",
  52. "BH": "Bahrain",
  53. "BD": "Bangladesh",
  54. "BB": "Barbados",
  55. "BY": "Belarus",
  56. "BE": "Belgium",
  57. "BZ": "Belize",
  58. "BJ": "Benin",
  59. "BM": "Bermuda",
  60. "BT": "Bhutan",
  61. "BO": "Bolivia",
  62. "BA": "Bosnia And Herzegovina",
  63. "BW": "Botswana",
  64. "BV": "Bouvet Island",
  65. "BR": "Brazil",
  66. "IO": "British Indian Ocean Territory",
  67. "BN": "Brunei Darussalam",
  68. "BG": "Bulgaria",
  69. "BF": "Burkina Faso",
  70. "BI": "Burundi",
  71. "KH": "Cambodia",
  72. "CM": "Cameroon",
  73. "CA": "Canada",
  74. "CV": "Cape Verde",
  75. "KY": "Cayman Islands",
  76. "CF": "Central African Republic",
  77. "TD": "Chad",
  78. "CL": "Chile",
  79. "CN": "China",
  80. "CX": "Christmas Island",
  81. "CC": "Cocos (Keeling) Islands",
  82. "CO": "Colombia",
  83. "KM": "Comoros",
  84. "CG": "Congo",
  85. "CD": "Congo, Democratic Republic",
  86. "CK": "Cook Islands",
  87. "CR": "Costa Rica",
  88. "CI": "Cote D\"Ivoire",
  89. "HR": "Croatia",
  90. "CU": "Cuba",
  91. "CY": "Cyprus",
  92. "CZ": "Czech Republic",
  93. "DK": "Denmark",
  94. "DJ": "Djibouti",
  95. "DM": "Dominica",
  96. "DO": "Dominican Republic",
  97. "EC": "Ecuador",
  98. "EG": "Egypt",
  99. "SV": "El Salvador",
  100. "GQ": "Equatorial Guinea",
  101. "ER": "Eritrea",
  102. "EE": "Estonia",
  103. "ET": "Ethiopia",
  104. "FK": "Falkland Islands (Malvinas)",
  105. "FO": "Faroe Islands",
  106. "FJ": "Fiji",
  107. "FI": "Finland",
  108. "FR": "France",
  109. "GF": "French Guiana",
  110. "PF": "French Polynesia",
  111. "TF": "French Southern Territories",
  112. "GA": "Gabon",
  113. "GM": "Gambia",
  114. "GE": "Georgia",
  115. "DE": "Germany",
  116. "GH": "Ghana",
  117. "GI": "Gibraltar",
  118. "GR": "Greece",
  119. "GL": "Greenland",
  120. "GD": "Grenada",
  121. "GP": "Guadeloupe",
  122. "GU": "Guam",
  123. "GT": "Guatemala",
  124. "GG": "Guernsey",
  125. "GN": "Guinea",
  126. "GW": "Guinea-Bissau",
  127. "GY": "Guyana",
  128. "HT": "Haiti",
  129. "HM": "Heard Island & Mcdonald Islands",
  130. "VA": "Holy See (Vatican City State)",
  131. "HN": "Honduras",
  132. "HK": "Hong Kong",
  133. "HU": "Hungary",
  134. "IS": "Iceland",
  135. "IN": "India",
  136. "ID": "Indonesia",
  137. "IR": "Iran, Islamic Republic Of",
  138. "IQ": "Iraq",
  139. "IE": "Ireland",
  140. "IM": "Isle Of Man",
  141. "IL": "Israel",
  142. "IT": "Italy",
  143. "JM": "Jamaica",
  144. "JP": "Japan",
  145. "JE": "Jersey",
  146. "JO": "Jordan",
  147. "KZ": "Kazakhstan",
  148. "KE": "Kenya",
  149. "KI": "Kiribati",
  150. "KR": "Korea",
  151. "KP": "North Korea",
  152. "KW": "Kuwait",
  153. "KG": "Kyrgyzstan",
  154. "LA": "Lao People\"s Democratic Republic",
  155. "LV": "Latvia",
  156. "LB": "Lebanon",
  157. "LS": "Lesotho",
  158. "LR": "Liberia",
  159. "LY": "Libyan Arab Jamahiriya",
  160. "LI": "Liechtenstein",
  161. "LT": "Lithuania",
  162. "LU": "Luxembourg",
  163. "MO": "Macao",
  164. "MK": "Macedonia",
  165. "MG": "Madagascar",
  166. "MW": "Malawi",
  167. "MY": "Malaysia",
  168. "MV": "Maldives",
  169. "ML": "Mali",
  170. "MT": "Malta",
  171. "MH": "Marshall Islands",
  172. "MQ": "Martinique",
  173. "MR": "Mauritania",
  174. "MU": "Mauritius",
  175. "YT": "Mayotte",
  176. "MX": "Mexico",
  177. "FM": "Micronesia, Federated States Of",
  178. "MD": "Moldova",
  179. "MC": "Monaco",
  180. "MN": "Mongolia",
  181. "ME": "Montenegro",
  182. "MS": "Montserrat",
  183. "MA": "Morocco",
  184. "MZ": "Mozambique",
  185. "MM": "Myanmar",
  186. "NA": "Namibia",
  187. "NR": "Nauru",
  188. "NP": "Nepal",
  189. "NL": "Netherlands",
  190. "AN": "Netherlands Antilles",
  191. "NC": "New Caledonia",
  192. "NZ": "New Zealand",
  193. "NI": "Nicaragua",
  194. "NE": "Niger",
  195. "NG": "Nigeria",
  196. "NU": "Niue",
  197. "NF": "Norfolk Island",
  198. "MP": "Northern Mariana Islands",
  199. "NO": "Norway",
  200. "OM": "Oman",
  201. "PK": "Pakistan",
  202. "PW": "Palau",
  203. "PS": "Palestinian Territory, Occupied",
  204. "PA": "Panama",
  205. "PG": "Papua New Guinea",
  206. "PY": "Paraguay",
  207. "PE": "Peru",
  208. "PH": "Philippines",
  209. "PN": "Pitcairn",
  210. "PL": "Poland",
  211. "PT": "Portugal",
  212. "PR": "Puerto Rico",
  213. "QA": "Qatar",
  214. "RE": "Reunion",
  215. "RO": "Romania",
  216. "RU": "Russian Federation",
  217. "RW": "Rwanda",
  218. "BL": "Saint Barthelemy",
  219. "SH": "Saint Helena",
  220. "KN": "Saint Kitts And Nevis",
  221. "LC": "Saint Lucia",
  222. "MF": "Saint Martin",
  223. "PM": "Saint Pierre And Miquelon",
  224. "VC": "Saint Vincent And Grenadines",
  225. "WS": "Samoa",
  226. "SM": "San Marino",
  227. "ST": "Sao Tome And Principe",
  228. "SA": "Saudi Arabia",
  229. "SN": "Senegal",
  230. "RS": "Serbia",
  231. "SC": "Seychelles",
  232. "SL": "Sierra Leone",
  233. "SG": "Singapore",
  234. "SK": "Slovakia",
  235. "SI": "Slovenia",
  236. "SB": "Solomon Islands",
  237. "SO": "Somalia",
  238. "ZA": "South Africa",
  239. "GS": "South Georgia And Sandwich Isl.",
  240. "ES": "Spain",
  241. "LK": "Sri Lanka",
  242. "SD": "Sudan",
  243. "SR": "Suriname",
  244. "SJ": "Svalbard And Jan Mayen",
  245. "SZ": "Swaziland",
  246. "SE": "Sweden",
  247. "CH": "Switzerland",
  248. "SY": "Syrian Arab Republic",
  249. "TW": "Taiwan",
  250. "TJ": "Tajikistan",
  251. "TZ": "Tanzania",
  252. "TH": "Thailand",
  253. "TL": "Timor-Leste",
  254. "TG": "Togo",
  255. "TK": "Tokelau",
  256. "TO": "Tonga",
  257. "TT": "Trinidad And Tobago",
  258. "TN": "Tunisia",
  259. "TR": "Turkey",
  260. "TM": "Turkmenistan",
  261. "TC": "Turks And Caicos Islands",
  262. "TV": "Tuvalu",
  263. "UG": "Uganda",
  264. "UA": "Ukraine",
  265. "AE": "United Arab Emirates",
  266. "GB": "United Kingdom",
  267. "US": "United States",
  268. "UM": "United States Outlying Islands",
  269. "UY": "Uruguay",
  270. "UZ": "Uzbekistan",
  271. "VU": "Vanuatu",
  272. "VE": "Venezuela",
  273. "VN": "Vietnam",
  274. "VG": "Virgin Islands, British",
  275. "VI": "Virgin Islands, U.S.",
  276. "WF": "Wallis And Futuna",
  277. "EH": "Western Sahara",
  278. "YE": "Yemen",
  279. "ZM": "Zambia",
  280. "ZW": "Zimbabwe"
  281. }
  282. const MySelect = ({options=countries, value='ZW', onChange}) => (
  283. <select defaultValue={value} onChange={(e) => onChange(e.target.value)}>
  284. {Object.entries(options).map(([key, cont]) => <option value={key}>{key}: {cont}</option> )}
  285. </select>
  286. )
  287. const PhoneBookEntry = ({data={name:'',phone:''}, index, onChange,
  288. onMoveUp,
  289. onMoveDown,
  290. onDelete,
  291. onAdd}) => (
  292. <div>
  293. <input type="text" value={data.name} onChange={(e) => onChange({name: e.target.value, phone: data.phone}, index)} />
  294. <input type="number" value={data.phone} onChange={(e) => onChange({name: data.name, phone: e.target.value}, index)} />
  295. <button onClick={onMoveUp}>^</button>
  296. <button onClick={onMoveDown}>v</button>
  297. <button onClick={onDelete}>x</button>
  298. <button onClick={onAdd}>+</button>
  299. </div>
  300. )
  301. const defaultPeople = [{name: 'Vasya', phone: '101'}, {name: 'Jhon', phone: '102'}, {name: 'Paul', phone: '103'}]
  302. const PhoneBook = ({people=defaultPeople, onSave}) => {
  303. const [ppl, setPpl] = useState(people)
  304. const [keys, setKeys] = useState(people.map(() => Math.random()))
  305. //const {current: keys} = useRef(people.map(() => Math.random()))
  306. useEffect(() => {
  307. setPpl(people)
  308. setKeys(people.map(() => Math.random()))
  309. }, [people])
  310. const onChange = (newData, i) => {
  311. ppl[i] = newData
  312. setPpl([...ppl])
  313. }
  314. const onMoveUp = (i) => {
  315. if (i > 0) {
  316. [ppl[i-1], ppl[i]] = [ppl[i], ppl[i-1]];
  317. [keys[i-1], keys[i]] = [keys[i], keys[i-1]]
  318. }
  319. setPpl([...ppl])
  320. setKeys([...keys])
  321. }
  322. const onMoveDown = (i) => {
  323. if (i < ppl.length - 1) {
  324. [ppl[i], ppl[i+1]] = [ppl[i+1], ppl[i]];
  325. [keys[i], keys[i+1]] = [keys[i+1], keys[i]]
  326. }
  327. setPpl([...ppl])
  328. setKeys([...keys])
  329. }
  330. const onDelete = (i) => {
  331. setPpl(ppl.filter((el, index) => index !== i))
  332. setKeys(keys.filter((el, index) => index !== i))
  333. }
  334. const onAdd = (i) => {
  335. ppl.splice(i+1, 0, {name:'',phone:''})
  336. keys.splice(i+1, 0, Math.random())
  337. setPpl([...ppl])
  338. setKeys([...keys])
  339. }
  340. return (
  341. <>
  342. <button onClick={() => { setPpl([{name:'',phone:''}, ...ppl])
  343. setKeys([Math.random(), ...keys])
  344. } }>+</button>
  345. <div className='PhoneBook'>
  346. {ppl.map((data, i) => (
  347. <PhoneBookEntry data={data} index={i}
  348. onChange={onChange}
  349. onMoveUp={() => onMoveUp(i)}
  350. onMoveDown={() => onMoveDown(i)}
  351. onDelete={() => onDelete(i)}
  352. onAdd={() => onAdd(i)}
  353. />)
  354. )}
  355. </div>
  356. <button onClick={() => onSave(ppl, keys)}>Save</button>
  357. </>
  358. )
  359. }
  360. function App() {
  361. const [country, setCountry] = useState('UA')
  362. console.log(country)
  363. return (
  364. <div className="App">
  365. <Gallery />
  366. <MySelect value={country} onChange={newCountry => setCountry(newCountry)}/>
  367. <PhoneBook onSave={(ppl, keys) => console.log(ppl, keys)}/>
  368. </div>
  369. )
  370. }
  371. export default App;