Browse Source

hw react 6

Vika 2 years ago
parent
commit
41b1ea62d5
3 changed files with 247 additions and 4 deletions
  1. 59 0
      react5/my-app/package-lock.json
  2. 1 0
      react5/my-app/package.json
  3. 187 4
      react5/my-app/src/App.js

+ 59 - 0
react5/my-app/package-lock.json

@@ -13,6 +13,7 @@
         "@testing-library/user-event": "^13.5.0",
         "react": "^17.0.2",
         "react-dom": "^17.0.2",
+        "react-dropzone": "^11.5.1",
         "react-scripts": "5.0.0",
         "web-vitals": "^2.1.2"
       }
@@ -4228,6 +4229,14 @@
         "node": ">= 4.5.0"
       }
     },
+    "node_modules/attr-accept": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
+      "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/autoprefixer": {
       "version": "10.4.0",
       "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz",
@@ -7178,6 +7187,17 @@
         "webpack": "^4.0.0 || ^5.0.0"
       }
     },
+    "node_modules/file-selector": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.2.4.tgz",
+      "integrity": "sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==",
+      "dependencies": {
+        "tslib": "^2.0.3"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
     "node_modules/filelist": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
@@ -13171,6 +13191,22 @@
         "react": "17.0.2"
       }
     },
+    "node_modules/react-dropzone": {
+      "version": "11.5.1",
+      "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.1.tgz",
+      "integrity": "sha512-eNhttdq4ZDe3eKbXAe54Opt+sbtqmNK5NWTHf/l5d+1TdZqShJ8gMjBrya00qx5zkI//TYxRhu1d9pemTgaWwg==",
+      "dependencies": {
+        "attr-accept": "^2.2.1",
+        "file-selector": "^0.2.2",
+        "prop-types": "^15.7.2"
+      },
+      "engines": {
+        "node": ">= 10"
+      },
+      "peerDependencies": {
+        "react": ">= 16.8"
+      }
+    },
     "node_modules/react-error-overlay": {
       "version": "6.0.10",
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
@@ -19035,6 +19071,11 @@
       "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
       "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
     },
+    "attr-accept": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
+      "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg=="
+    },
     "autoprefixer": {
       "version": "10.4.0",
       "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz",
@@ -21223,6 +21264,14 @@
         "schema-utils": "^3.0.0"
       }
     },
+    "file-selector": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.2.4.tgz",
+      "integrity": "sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==",
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
     "filelist": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
@@ -25384,6 +25433,16 @@
         "scheduler": "^0.20.2"
       }
     },
+    "react-dropzone": {
+      "version": "11.5.1",
+      "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-11.5.1.tgz",
+      "integrity": "sha512-eNhttdq4ZDe3eKbXAe54Opt+sbtqmNK5NWTHf/l5d+1TdZqShJ8gMjBrya00qx5zkI//TYxRhu1d9pemTgaWwg==",
+      "requires": {
+        "attr-accept": "^2.2.1",
+        "file-selector": "^0.2.2",
+        "prop-types": "^15.7.2"
+      }
+    },
     "react-error-overlay": {
       "version": "6.0.10",
       "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",

+ 1 - 0
react5/my-app/package.json

@@ -8,6 +8,7 @@
     "@testing-library/user-event": "^13.5.0",
     "react": "^17.0.2",
     "react-dom": "^17.0.2",
+    "react-dropzone": "^11.5.1",
     "react-scripts": "5.0.0",
     "web-vitals": "^2.1.2"
   },

+ 187 - 4
react5/my-app/src/App.js

@@ -1,5 +1,7 @@
 import './App.css';
-import {useState } from 'react';
+import {useState, useEffect } from 'react';
+import React, {useCallback} from 'react'
+import {useDropzone} from 'react-dropzone'
 
 const Dots = ({count,active, onChange}) =>{
   let arrImg = []; 
@@ -51,11 +53,192 @@ const Gallery = ({images = ['https://kot-pes.com/wp-content/uploads/2018/12/post
   )
 }
 
-function App() {
+const countries ={
+  "AF": "Afghanistan",
+  "AX": "Åland Islands",
+  "AL": "Albania",
+  "DZ": "Algeria",
+  "AS": "American Samoa",
+  "AD": "AndorrA",
+  "AO": "Angola",
+  "AI": "Anguilla",
+  "AQ": "Antarctica",
+}
+
+const MySelect = ({options=countries, value='AX', onChange }) => {
+  const newCountry = Object.entries(options);
+
+  return (
+    <select value = {value} onChange = {(e) => onChange(e.target.value)} >
+    {newCountry.map((item) => <option key = {item[0]} value = {item[0]} > {item[1]}</option>)}
+
+    </select>
+  )
+}
+
+
+const PhoneBookEntry = ({data:{name, phone}={name: '', phone: ''}, 
+                                onChange,  //по изменению
+                                onMoveUp,  //сдвинуть вверх
+                                onMoveDown,//сдвинуть вниз
+                                onDelete,  //удалить этот
+                                onAddL}) => //добавить под ним еще один
+<>
+    
+    <input value={name} onChange={(e) => onChange({'name': e.target.value, phone })} />
+   
+    <input value={phone} onChange={(e) =>(onChange({name, 'phone': e.target.value}))} />
+    <button onClick={onMoveUp}>^</button>
+    <button onClick={onMoveDown}>v</button>
+    <button onClick={onDelete}>x</button>
+    <button onClick={onAddL}>+</button>
+</>
+
+const defaultPeople = [{name: 'John', 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 keys  = useRef(people.map(() => Math.random()))
+    //должно меняться соответственно элементам списка - сдвигаться удаляться и тп
+    useEffect(() => {
+        setPpl(people);
+        setKeys(people.map(() => Math.random()));//тут и keys обновить
+    },[people])
+    //обеспечить для PhoneBookEntry:
+    //   onChange, onMoveUp, onMoveDown, onDelete
+    const onChange = (newData, i) => { //{name: 'НАМЕ', phone: 'НУМБЕР'}
+        const newPeople = [...ppl];//создаем новый массив ppl на базе старого, заменяем один элемент и делаем setPpl
+        newPeople[i] = newData; //ничего НЕ ДЕЛАЕМ с keys
+        setPpl(newPeople);
+    }
+    const onDelete = (i) => {  //фильтрует ppl и keys удаляя i-ый элемент
+      const newPeople = ppl.filter((_, index) => index!==i);
+      setPpl(newPeople);
+
+      const newKeys = keys.filter((_, index) => index!==i);
+      setKeys(newKeys);
+    }
+
+    const onMoveUp = (data, i) => {
+      const newPeople = [...ppl];
+      newPeople.splice(i, 1);
+      newPeople.splice((i-1), 0, data);
+      setPpl(newPeople);
+
+      const newKeys = [...keys];
+      newKeys.splice(i, 1);
+      newKeys.splice(i-1, 0, keys[i]);
+      setKeys(newKeys);
+
+    }
+
+    const onMoveDown = (data, i) => {
+      const newPeople = [...ppl];
+      newPeople.splice(i, 1);
+      newPeople.splice((i+1), 0, data);
+      setPpl(newPeople);
+
+      const newkeys = [...keys];
+      newkeys.splice(i, 1);
+      newkeys.splice(i+1, 0, keys[i]);
+    }
+
+    const onAddFirst = () => {
+      const newPeople = [...ppl];
+      newPeople.unshift({'name': '', 'phone': ''});
+      setPpl(newPeople);
+
+      const newKeys =[...keys];
+      newKeys.unshift(Math.random());
+      setKeys(newKeys);
+    }
+
+    const onAddL = () => {
+      const newPeople = [...ppl];
+      newPeople.push({'name': '', 'phone': ''});
+      setPpl(newPeople);
+
+      const newKeys =[...keys];
+      newKeys.push(Math.random());
+      setKeys(newKeys);
+    }
+
+    console.log(keys, ppl)
+    return (
+        <>
+            <button onClick={onAddFirst}>+</button> 
+            <div className='PhoneBook'>
+            
+                {ppl.map((data, i) =><div key={keys[i]} > <PhoneBookEntry data={data}   //не забудьте keys
+                                                 onChange={data => onChange(data, i)}
+                                                 onDelete={() => onDelete(i)}
+                                                 onMoveDown={() => onMoveDown(data, i)} 
+                                                 onMoveUp={() => onMoveUp(data, i)}
+                                                 onAddL={onAddL}
+
+                                                 />
+                                      </div>  )}
+            </div>
+            <button onClick={() => onSave(ppl)}>Save</button>
+        </>
+    )
+}
+
+
+
+
+
+function MyDropzone() {
+  const onDrop = useCallback(acceptedFiles => {
+    // Do something with the files
+  }, [])
+  const {getRootProps, getInputProps, isDragActive} = useDropzone({onDrop})
+
   return (
-    <div className="App">
-      <Gallery/>
+    <div {...getRootProps()}>
+      <input {...getInputProps()} onChange={(e) => getFile(e.target.value)}/>
+      {
+        isDragActive ?
+          <p>Drop the files here ...</p> :
+          <p>Drag 'n' drop some files here, or click to select files</p>
+      }
     </div>
+  )
+}
+
+
+const getFile =(file)=> file;
+
+let fd = new FormData;
+fd.append('photo', );
+
+photo.onchange = async () => {
+  fetch('/upload', {
+      method: "POST",
+      headers: localStorage.authToken ? {Authorization: 'Bearer ' + localStorage.authToken} : {},
+      body: new FormData(form)
+  })
+}
+
+function App() {
+  const [country, setCountry] = useState('AX')
+  return (
+    < >
+      {/* <div className="App">
+        {console.log(country)}
+        <MySelect value={country} onChange = {(w) => setCountry(w)} />
+        <Gallery/>
+      </div> */}
+      <div>
+      <PhoneBook/>
+      </div>
+      <div>
+      <MyDropzone getFile={getFile}/>
+      </div>
+     </>
+
   );
 }