Browse Source

PhoneBook homework and some changes in the React Store

Bonyant 2 years ago
parent
commit
8c09efdec7
3 changed files with 268 additions and 54 deletions
  1. 22 11
      1/src/App.js
  2. 11 25
      1/src/App.scss
  3. 235 18
      2/src/App.js

+ 22 - 11
1/src/App.js

@@ -74,7 +74,7 @@ const actionCatById = (_id) =>
             }
           },
           subCategories{
-            name, subCategories{
+            _id, name, subCategories{
               name
             }
           }
@@ -340,14 +340,20 @@ const Footer = ({ logo = logoDefault }) => (
 
 const Content = ({ children }) => <div className="Content">{children}</div>;
 
-const SubCategories = ({ cats } = {}) => {
-  console.log(...cats);
-  return (
-    <div className="SubCategories">
-      <h3>Подкатегории</h3>
-    </div>
-  );
-};
+const SubCategories = ({ cats }) => (
+  <div>
+    {console.log(cats)}
+    {cats.map((subcat, i) => (
+      <Link
+        className="d-block m-3 text-decoration-none text-reset blockquote"
+        to={`/category/${subcat._id}`}
+        key={i}
+      >
+        {subcat.name}
+      </Link>
+    ))}
+  </div>
+);
 
 const GoodCard = ({ good: { _id, name, price, images } = {}, onCartAdd }) => (
   <div className="GoodCard">
@@ -372,10 +378,12 @@ const CGoodCard = connect(null, { onCartAdd: actionCartAdd })(GoodCard);
 const Category = ({ cat: { _id, name, goods, subCategories } }) => (
   <div className="Category">
     <h1>{name}</h1>
+    {subCategories ? <h4>Подкатегории раздела "{name}":</h4> : null}
     {subCategories && <SubCategories cats={subCategories} />}
     {(goods || []).map((good, i) => (
       <CGoodCard good={good} key={i} />
     ))}
+    {subCategories || goods ? null : <h3>В этой категории нет товаров.</h3>}
   </div>
 );
 
@@ -433,7 +441,7 @@ const CartPage = ({ cart, clearCart }) => (
     ))}
 
     {Object.keys(cart).length === 0 ? (
-      <h2>Your cart is empty!</h2>
+      <h2>Ваша корзина пуста!</h2>
     ) : (
       <Button variant="danger" id="ClearBtn" onClick={() => clearCart()}>
         Clear Cart
@@ -572,12 +580,15 @@ const Authorizations = ({ auth, actionLogOut }) => {
         <Button variant="danger" onClick={() => actionLogOut()}>
           Выйти
         </Button>
+        {auth.token && history.location.pathname === "/authorizations"
+          ? history.push("/")
+          : null}
       </div>
     );
   } else {
     return (
       <Link className="nav-link" to={`/authorizations`}>
-        Авторизоваться
+        Авторизовация/Регистрация
       </Link>
     );
   }

+ 11 - 25
1/src/App.scss

@@ -2,6 +2,14 @@
 @import url("https://fonts.googleapis.com/css?family=Montserrat:400,600,700");
 @import url("https://fonts.googleapis.com/css?family=Catamaran:400,800");
 
+body {
+  margin: 0;
+  color: #fff;
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+}
+
 .GoodCard {
   border: 1px solid cyan;
   border-radius: 15px;
@@ -10,34 +18,12 @@
   }
 }
 
-App {
-  header {
-    .Logo {
-      img {
-        max-height: 100px;
-      }
-    }
-  }
+.App {
   main {
-    .Content {
-    }
+    flex-direction: row;
   }
-
   footer {
-    background-color: #303030;
-    .Logo {
-      img {
-        max-height: 200px;
-      }
-    }
-  }
-  main {
-    display: flex;
-    flex-direction: row;
-    aside {
-      width: 30%;
-      background-color: cyan;
-    }
+    flex-shrink: 0;
   }
 }
 

+ 235 - 18
2/src/App.js

@@ -50,15 +50,15 @@ const RGBInput = () => {
 };
 
 // Spoiler
-const Spoiler = ({ header = <h4>+</h4>, open, children }) => {
+const Spoiler = ({ header = <h2>+</h2>, open, children }) => {
   const [visible, setVisible] = useState(open);
   return (
     <div className="Spoiler">
       <div className="header" onClick={(e) => setVisible(!visible)}>
-        <h3>
+        <div>
           {header}
           {visible ? "hide" : "show"}
-        </h3>
+        </div>
         {visible && children}
       </div>
     </div>
@@ -158,14 +158,20 @@ const Timer = ({
         Hours: {hours.toFixed(3)} | Minutes: {minutes.toFixed(3)} | Seconds:{" "}
         {seconds.toFixed(3)}
       </h3>
-      {onDelete && <button onClick={onDelete}>x</button>}
-      <button
+      {onDelete && (
+        <Button variant="danger" className="m-1" onClick={onDelete}>
+          x
+        </Button>
+      )}
+      <Button
+        variant="primary"
+        className="m-1"
         onClick={() => {
           setPause(!pause);
         }}
       >
         {pause ? "Continue" : "Pause"}
-      </button>
+      </Button>
     </>
   );
 };
@@ -175,10 +181,28 @@ const Timers = () => {
   const [ms, setMS] = useState(1000);
   return (
     <>
-      <button onClick={() => setMS(ms + 100)}>+</button>
+      <Button
+        variant="secondary"
+        className="m-1"
+        onClick={() => setMS(ms + 100)}
+      >
+        +
+      </Button>
       {ms}
-      <button onClick={() => setMS(ms - 100)}>-</button>
-      <button onClick={() => setTimers([Math.random(), ...timers])}>ADD</button>
+      <Button
+        variant="secondary"
+        className="m-1"
+        onClick={() => setMS(ms - 100)}
+      >
+        -
+      </Button>
+      <Button
+        variant="success"
+        className="m-1"
+        onClick={() => setTimers([Math.random(), ...timers])}
+      >
+        ADD
+      </Button>
       {timers.map((i) => (
         <Timer
           key={i}
@@ -225,9 +249,13 @@ const TimerControl = () => {
           setSeconds(+e.currentTarget.value ? +e.currentTarget.value : 0)
         }
       />{" "}
-      <button onClick={() => setStart(!start)}>
+      <Button
+        variant="primary"
+        className="m-1"
+        onClick={() => setStart(!start)}
+      >
         {start ? "Hide" : "Start"}
-      </button>
+      </Button>
       {start && <Timer h={hours} m={minutes} s={seconds} />}
     </div>
   );
@@ -333,7 +361,7 @@ const TimerControlContainer = ({ refresh, render: Render }) => {
 
   return (
     <div className="TimerControl">
-      <label for="Seconds">{seconds} seconds</label>
+      <label htmlFor="Seconds">{seconds} seconds</label>
       <input
         id="Seconds"
         min="0"
@@ -342,9 +370,13 @@ const TimerControlContainer = ({ refresh, render: Render }) => {
           setSeconds(+e.currentTarget.value ? +e.currentTarget.value : 0)
         }
       />{" "}
-      <button onClick={() => setStart(!start)}>
+      <Button
+        variant="primary"
+        className="m-1"
+        onClick={() => setStart(!start)}
+      >
         {start ? "Hide" : "Start"}
-      </button>
+      </Button>
       {start && <Render seconds={time.toFixed(1)} />}
     </div>
   );
@@ -602,8 +634,10 @@ const countries = {
 
 const MySelect = ({ options = countries, value = "YE", onChange }) => (
   <select value={value} onChange={(value) => onChange(value.target.value)}>
-    {Object.entries(options).map((option) => (
-      <option value={option[0]}>{option[1]}</option>
+    {Object.entries(options).map((option, i) => (
+      <option value={option[0]} key={i}>
+        {option[1]}
+      </option>
     ))}
   </select>
 );
@@ -621,6 +655,7 @@ const Dots = ({ active, count, onClick }) => {
             : { border: "2px solid black" }
         }
         onClick={() => onClick(i)}
+        key={i}
       >
         {i + 1}
       </div>
@@ -666,15 +701,183 @@ const Gallery = ({
   );
 };
 
+const PhoneBookEntry = ({
+  data = { name: "", phone: "" },
+  onChange,
+  onMoveUp,
+  onMoveDown,
+  onDelete,
+  onAdd,
+}) => (
+  <>
+    <input
+      className="m-1"
+      value={data.name}
+      type="text"
+      placeholder="Name"
+      onChange={(value) =>
+        onChange({ name: value.target.value, phone: data.phone })
+      }
+    />
+    <input
+      className="m-1"
+      value={data.phone}
+      type="number"
+      placeholder="Phone"
+      onChange={(value) =>
+        onChange({ name: data.name, phone: value.target.value })
+      }
+    />
+    <Button className="m-1" variant="primary" onClick={onMoveUp}>
+      ^
+    </Button>
+    <Button className="m-1" variant="primary" onClick={onMoveDown}>
+      v
+    </Button>
+    <Button className="m-1" variant="danger" onClick={onDelete}>
+      x
+    </Button>
+    <Button className="m-1" variant="warning" onClick={onAdd}>
+      +
+    </Button>
+    <br />
+  </>
+);
+
+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()));
+  useEffect(() => {
+    setPpl(people);
+  }, [people]);
+
+  const onChange = (newData, i) => {
+    const people = [...ppl];
+    people[i] = newData;
+    return setPpl(people);
+  };
+
+  const onDelete = (i) => {
+    setKeys(keys.filter((k, index) => index !== i));
+    setPpl(ppl.filter((p, index) => index !== i));
+  };
+
+  const onAdd = (data, i) => {
+    const people = [...ppl];
+    people.splice(i + 1, 0, data);
+    setPpl(people);
+    const k = [...keys];
+    k.splice(i + 1, 0, Math.random());
+    setKeys(k);
+  };
+
+  const onMoveUp = (i) => {
+    const people = [...ppl];
+    const k = [...keys];
+    let currentP = people[i];
+    let currentK = k[i];
+    let prevP;
+    let prevK;
+    if (people[i - 1]) {
+      prevP = people[i - 1];
+      people[i - 1] = currentP;
+      people[i] = prevP;
+      setPpl(people);
+      prevK = k[i - 1];
+      k[i - 1] = currentK;
+      k[i] = prevK;
+      setKeys(k);
+    } else {
+      people.push(people.shift());
+      setPpl(people);
+      k.push(k.shift());
+      setKeys(k);
+    }
+  };
+
+  const onMoveDown = (i) => {
+    const people = [...ppl];
+    const k = [...keys];
+    let currentP = people[i];
+    let currentK = k[i];
+    let afterP;
+    let afterK;
+    if (people[i + 1]) {
+      afterP = people[i + 1];
+      people[i + 1] = currentP;
+      people[i] = afterP;
+      setPpl(people);
+      afterK = k[i + 1];
+      k[i + 1] = currentK;
+      k[i] = afterK;
+      setKeys(k);
+    } else {
+      people.unshift(people.pop());
+      setPpl(people);
+      k.unshift(k.pop());
+      setKeys(k);
+    }
+  };
+
+  return (
+    <>
+      <Button
+        className="m-1"
+        variant="success"
+        onClick={() => {
+          setPpl([{ name: "", phone: "" }, ...ppl]);
+          setKeys([Math.random(), ...keys]);
+        }}
+      >
+        Add to start
+      </Button>
+
+      <div className="PhoneBook">
+        {ppl.map((data, i) => (
+          <PhoneBookEntry
+            data={data}
+            onChange={(data) => onChange(data, i)}
+            onDelete={() => onDelete(i)}
+            onAdd={() => onAdd(data, i)}
+            onMoveUp={() => onMoveUp(i)}
+            onMoveDown={() => onMoveDown(i)}
+            key={keys[i]}
+          />
+        ))}
+      </div>
+      <Button
+        className="m-1"
+        variant="dark"
+        onClick={() => {
+          onSave(ppl);
+          onSave(keys);
+        }}
+      >
+        Save
+      </Button>
+    </>
+  );
+};
+
 function App() {
   const [country, setCountry] = useState("UA");
+  let secondsNow =
+    new Date().getHours() * 3600 +
+    new Date().getMinutes() * 60 +
+    new Date().getSeconds() +
+    new Date().getMilliseconds() / 1000;
   return (
     <div className="App">
       <h3>RGB Input:</h3>
       <RGBInput />
 
       <h3>Spoilers:</h3>
-      <Spoiler header={<h1>Заголовок</h1>} open>
+      <Spoiler header={<h2>Заголовок</h2>} open>
         <h2>Контент 1</h2>
         <p>
           Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium
@@ -719,7 +922,13 @@ function App() {
       <TimerControlContainer refresh={100} render={TimerLCD} />
 
       <h3>Watch:</h3>
-      <TimerContainer seconds={10} refresh={100} render={Watch} mode="plus" />
+
+      <TimerContainer
+        seconds={secondsNow}
+        refresh={100}
+        render={Watch}
+        mode="plus"
+      />
 
       <h3>MySelect:</h3>
       <MySelect
@@ -729,6 +938,14 @@ function App() {
 
       <h3>Gallery:</h3>
       <Gallery />
+
+      <h3>Phones Book:</h3>
+      <PhoneBook
+        onSave={(phones, keys) => {
+          console.log(phones);
+          console.log(keys);
+        }}
+      />
     </div>
   );
 }