소스 검색

Bug fixes, improved shopping cart, done a bit of work in Canvas

Bonyant 2 년 전
부모
커밋
d8d968fd26
8개의 변경된 파일510개의 추가작업 그리고 39개의 파일을 삭제
  1. 0 3
      07/.vscode/settings.json
  2. 0 3
      11/.vscode/settings.json
  3. 0 4
      13/.vscode/settings.json
  4. 0 3
      14/.vscode/settings.json
  5. 80 26
      15/index.js
  6. 28 0
      16/index.html
  7. 367 0
      16/index.js
  8. 35 0
      16/styles.css

+ 0 - 3
07/.vscode/settings.json

@@ -1,3 +0,0 @@
-{
-  "liveServer.settings.port": 5501
-}

+ 0 - 3
11/.vscode/settings.json

@@ -1,3 +0,0 @@
-{
-  "liveServer.settings.port": 5501
-}

+ 0 - 4
13/.vscode/settings.json

@@ -1,4 +0,0 @@
-{
-  "javascript.preferences.quoteStyle": "double",
-  "liveServer.settings.port": 5502
-}

+ 0 - 3
14/.vscode/settings.json

@@ -1,3 +0,0 @@
-{
-  "liveServer.settings.port": 5501
-}

+ 80 - 26
15/index.js

@@ -89,6 +89,10 @@ function cartReducer(state = {}, { type, good = {}, count }) {
     CART_CLEAR() {
       return {};
     },
+    CART_SHOW() {
+      state = JSON.parse(localStorage.cart);
+      return state;
+    },
   };
   if (type in types) {
     return types[type]();
@@ -169,29 +173,32 @@ const actionCartChange = (good, count) => ({
 });
 const actionCartRemove = (good) => ({ type: "CART_REMOVE", good });
 const actionCartClear = () => ({ type: "CART_CLEAR" });
+const actionCartShow = () => ({ type: "CART_SHOW" });
 
 const actionOrder = () => async (dispatch, getState) => {
   let { cart } = getState();
-  let count = 0;
-  const orderGoods = Object.entries(cart).map(([_id, {}]) => ({
+  const orderGoods = Object.entries(cart).map(([_id, { count }]) => ({
     good: { _id },
-    count: count++,
+    count,
   }));
-
-  await dispatch(
+  let result = await dispatch(
     actionPromise(
       "order",
       gql(
         `
-                  mutation newOrder($order:OrderInput){
-                    OrderUpsert(order:$order)
-                      { _id total 	}
-                  }
-          `,
+                    mutation newOrder($order:OrderInput){
+                      OrderUpsert(order:$order)
+                        { _id total }
+                    }
+            `,
         { order: { orderGoods } }
       )
     )
   );
+
+  if (result?._id) {
+    dispatch(actionCleanCart());
+  }
 };
 
 const getGQL =
@@ -273,7 +280,9 @@ const actionLogin = (login, password) =>
   );
 
 const actionFullLogin = (login, password) => async (dispatch) => {
+  console.log(login, password);
   let token = await dispatch(actionLogin(login, password));
+  console.log(token);
   if (token) {
     dispatch(actionAuthLogin(token));
   }
@@ -281,11 +290,11 @@ const actionFullLogin = (login, password) => async (dispatch) => {
 
 const actionRegister = (login, password) =>
   actionPromise(
-    "register",
+    "registration",
     gql(
-      `mutation reg($user:UserInput) {
+      `mutation reg2($user:UserInput) {
       UserUpsert(user:$user) {
-      _id 
+      _id login
       }
   }
   `,
@@ -294,7 +303,9 @@ const actionRegister = (login, password) =>
   );
 
 const actionFullRegister = (login, password) => async (dispatch) => {
+  console.log(login, password);
   let check = await dispatch(actionRegister(login, password));
+  console.log(check);
   if (check) {
     dispatch(actionFullLogin(login, password));
   }
@@ -342,18 +353,22 @@ const openCart = () => {
       cardMain.id = "cardMain";
       let goodImgBlock = document.createElement("div");
       goodImgBlock.innerHTML = `
-      <div>
           <img src="${backURL}/${url}" width="400" height="200"/>
-      </div>
       `;
+      cardMain.appendChild(goodImgBlock);
       let goodInfoBlock = document.createElement("div");
-      goodInfoBlock.innerHTML = `
-      <div>
-        <h2>${name}</h2>
-        <p><strong>${price}$</strong></p>
-        <p><span>${count}</span></p>
-      </div>
-      `;
+      let goodName = document.createElement("h2");
+      goodName.innerText = `${name}`;
+      let goodPrice = document.createElement("p");
+      goodPrice.innerText = `${price * count}$`;
+      let goodCount = document.createElement("p");
+      goodCount.innerText = `${count} шт.`;
+      goodInfoBlock.appendChild(goodName);
+      goodInfoBlock.appendChild(goodPrice);
+      goodInfoBlock.appendChild(goodCount);
+      cardMain.appendChild(goodInfoBlock);
+
+      let br = document.createElement("br");
       let goodEditBlock = document.createElement("div");
       goodEditBlock.className = "form-outline";
       let deleteBtn = document.createElement("button");
@@ -362,8 +377,11 @@ const openCart = () => {
       deleteBtn.type = "button";
       deleteBtn.className = "btn btn-danger";
       goodEditBlock.appendChild(deleteBtn);
+      goodEditBlock.appendChild(br);
       deleteBtn.onclick = () => {
         store.dispatch(actionCartRemove(cart[good].good));
+        cardMain.remove();
+        console.log(store.getState());
       };
 
       let countLabel = document.createElement("label");
@@ -372,13 +390,17 @@ const openCart = () => {
       countLabel.innerText = "Change count";
       let countField = document.createElement("input");
       countField.type = "number";
+      countField.value = cart[good].count;
+      countField.min = "1";
       countField.id = "countField";
       countField.className = "form-control";
       goodEditBlock.appendChild(countLabel);
       goodEditBlock.appendChild(countField);
-
-      cardMain.appendChild(goodImgBlock);
-      cardMain.appendChild(goodInfoBlock);
+      countField.oninput = () => {
+        goodPrice.innerText = `${price * +countField.value}$`;
+        goodCount.innerText = `${countField.value} шт.`;
+        store.dispatch(actionCartChange(cart[good].good, countField.value));
+      };
       cardMain.appendChild(goodEditBlock);
       main.appendChild(cardMain);
     }
@@ -398,11 +420,14 @@ const openCart = () => {
       main.appendChild(makeOrder);
       main.appendChild(clearBtn);
     } else {
-      main.innerHTML = `<h2>Your cart is empty!</h2>`;
+      main.innerHTML = "<h2>Your cart is empty!</h2>";
     }
 
     makeOrder.onclick = () => {
       store.dispatch(actionOrder());
+      alert("Thanks for your order!");
+      store.dispatch(actionCartClear());
+      document.location.reload();
     };
 
     clearBtn.onclick = () => {
@@ -467,6 +492,35 @@ window.onhashchange = () => {
 
 window.onhashchange();
 
+store.subscribe(() => {
+  const [, route] = location.hash.split("/");
+  const { cart } = store.getState();
+  if (Object.keys(cart).length === 0 && route === "cart") {
+    let makeOrderBtn = document.getElementById("makeOrder");
+    let clearCartBtn = document.getElementById("clearBtn");
+    if (makeOrderBtn) {
+      makeOrderBtn.remove();
+    }
+    if (clearCartBtn) {
+      clearCartBtn.remove();
+    }
+    localStorage.cart = "";
+    main.innerHTML = "<h2>Your cart is empty!</h2>";
+  } else if (Object.keys(cart).length !== 0) {
+    let cartStr = JSON.stringify(cart);
+    localStorage.cart = cartStr;
+  }
+});
+
+window.onunload = () => {
+  if (localStorage.cart !== "") {
+    store.dispatch(actionCartShow());
+    openCart();
+  }
+};
+
+window.onunload();
+
 store.subscribe(() => {
   const { promise } = store.getState();
   const [, route, _id] = location.hash.split("/");

+ 28 - 0
16/index.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width" />
+    <title>JavaScript Canvas</title>
+    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.3/papaparse.min.js"></script>
+    <script src="http://gitlab.a-level.com.ua/gitgod/nanobind/raw/master/static/nb.js"></script>
+    <link rel="stylesheet" href="styles.css" />
+  </head>
+  <body>
+    <canvas id="canvas" width="400" height="400"></canvas>
+    <button id="undo">UNDO</button>
+    <input type="color" id="color" />
+    <select id="tool">
+      <option value="graffity">Graffity</option>
+      <option value="circle">Circle</option>
+      <option value="line">Line</option>
+      <option value="rectangle">Rectangle</option>
+      <option value="ellipse">Ellipse</option>
+      <option value="select">Select</option>
+    </select>
+    <input type="number" id="size" value="10" />
+    <button id="delete">Delete...</button>
+    <script src="index.js"></script>
+  </body>
+</html>

+ 367 - 0
16/index.js

@@ -0,0 +1,367 @@
+const canvas = document.getElementById("canvas");
+const ctx = canvas.getContext("2d");
+
+const width = canvas.width;
+const height = canvas.height;
+
+let current;
+let selection = [];
+
+const tools = {
+  graffity: {
+    mousemove(e) {
+      e.buttons & 1 &&
+        new Circle(e.clientX, e.clientY, +size.value, color.value);
+    },
+  },
+  circle: {
+    mousedown(e) {
+      current = new Circle(e.clientX, e.clientY, 1, color.value);
+    },
+    mousemove(e) {
+      if (!current) return;
+
+      current.radius = current.distanceTo(e.clientX, e.clientY);
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+  line: {
+    mousedown(e) {
+      current = new Line(e.clientX, e.clientY, 0, 0, color.value, +size.value);
+    },
+    mousemove(e) {
+      if (!current) return;
+
+      current.width = e.clientX - current.x;
+      current.height = e.clientY - current.y;
+
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+  rectangle: {
+    mousedown(e) {
+      current = new Rectangle(e.clientX, e.clientY, 0, 0, color.value);
+    },
+    mousemove(e) {
+      if (!current) return;
+
+      current.width = e.clientX - current.x;
+      current.height = e.clientY - current.y;
+
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+  ellipse: {
+    mousedown(e) {
+      current = new Ellipse(e.clientX, e.clientY, 0, 0, color.value);
+    },
+    mousemove(e) {
+      if (!current) return;
+
+      current.width = e.clientX - current.x;
+      current.height = e.clientY - current.y;
+
+      Drawable.drawAll();
+    },
+
+    mouseup(e) {
+      current = null;
+    },
+  },
+  select: {
+    click(e) {
+      console.log(e);
+      let found = Drawable.instances.filter(
+        (c) => c.in && c.in(e.clientX, e.clientY)
+      );
+      if (found.length) {
+        if (e.ctrlKey) {
+          selection.push(found.pop());
+        } else {
+          selection = [found.pop()];
+        }
+      } else {
+        if (!e.ctrlKey) selection = [];
+      }
+
+      Drawable.drawAll(selection);
+    },
+    mousedown(e) {
+      //
+    },
+    mousemove(e) {},
+
+    mouseup(e) {
+      //x,y, w, h прямоугольника
+      //selection - только те элеменеты Drawable.instances которые в границах прямоугольника.
+    },
+  },
+};
+
+function superHandler(evt) {
+  let t = tools[tool.value];
+  if (typeof t[evt.type] === "function") t[evt.type].call(this, evt);
+}
+
+canvas.onmousemove = superHandler;
+canvas.onmouseup = superHandler;
+canvas.onmousedown = superHandler;
+canvas.onclick = superHandler;
+
+function Drawable() {
+  Drawable.addInstance(this);
+}
+
+const distance = (x1, y1, x2, y2) => ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5;
+
+Drawable.prototype.draw = function () {};
+Drawable.prototype.distanceTo = function (x, y) {
+  if (typeof this.x !== "number" || typeof this.y !== "number") {
+    return NaN;
+  }
+  return distance(this.x, this.y, x, y);
+};
+Drawable.instances = [];
+Drawable.addInstance = function (item) {
+  Drawable.instances.push(item);
+};
+
+Drawable.drawAll = function (selection = []) {
+  ctx.clearRect(0, 0, width, height);
+  Drawable.forAll((item) => item.draw());
+  selection.forEach((item) => item.draw(true));
+};
+
+Drawable.forAll = function (callback) {
+  for (var i = 0; i < Drawable.instances.length; i++) {
+    callback(Drawable.instances[i]);
+  }
+};
+
+class Circle extends Drawable {
+  constructor(x, y, radius, color) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radius = radius;
+    this.color = color;
+
+    this.draw();
+  }
+
+  draw(selected) {
+    ctx.beginPath();
+    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
+    ctx.closePath();
+    ctx.fillStyle = this.color;
+    if (selected) {
+      ctx.lineWidth = 2;
+      ctx.strokeStyle = "red";
+      ctx.stroke();
+    }
+    ctx.fill();
+  }
+
+  in(x, y) {
+    return this.distanceTo(x, y) < this.radius;
+  }
+
+  inBounds(x, y, w, h) {
+    return this.x >= x && this.x <= x + w && this.y >= y && this.y <= y + h;
+  }
+}
+
+class Line extends Drawable {
+  constructor(x, y, width, height, color, lineWidth) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.color = color;
+    this.lineWidth = lineWidth;
+
+    this.draw();
+  }
+
+  draw(selected) {
+    ctx.beginPath();
+    ctx.moveTo(this.x, this.y);
+    ctx.lineTo(this.x + this.width, this.y + this.height);
+    ctx.closePath();
+    ctx.strokeStyle = this.color;
+    ctx.lineWidth = this.lineWidth;
+    if (selected) {
+    }
+    ctx.stroke();
+  }
+
+  in(x, y) {
+    // console.log("this.x " + this.x, "this.y " + this.y);
+    // console.log("x " + x, "y " + y);
+    // new Line(this.x, this.y, this.width, 0, "red");
+  }
+}
+
+class Rectangle extends Drawable {
+  constructor(x, y, width, height, color) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.color = color;
+
+    this.draw();
+  }
+
+  draw(selected) {
+    ctx.fillStyle = this.color;
+    ctx.fillRect(this.x, this.y, this.width, this.height);
+    if (selected) {
+      ctx.beginPath();
+      ctx.strokeStyle = "green";
+      ctx.rect(this.x, this.y, this.width, this.height);
+      ctx.stroke();
+      ctx.closePath();
+    }
+  }
+
+  in(x, y) {
+    return (
+      this.x <= x &&
+      this.x + this.width >= x &&
+      this.y <= y &&
+      this.y + this.height >= y
+    );
+  }
+}
+
+class Ellipse extends Drawable {
+  constructor(x, y, width, height, color) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.color = color;
+
+    this.draw();
+  }
+
+  #width = 0;
+  #height = 0;
+
+  set height(newHeight) {
+    if (newHeight < 0) {
+      this.#height = -newHeight;
+      this.y += newHeight;
+    } else {
+      this.#height = newHeight;
+    }
+  }
+
+  set width(newWidth) {
+    if (newWidth < 0) {
+      this.#width = -newWidth;
+      this.x += newWidth;
+    } else {
+      this.#width = newWidth;
+    }
+  }
+
+  get width() {
+    return this.#width;
+  }
+
+  get height() {
+    return this.#height;
+  }
+
+  get rx() {
+    return this.#width / 2;
+  }
+
+  get ry() {
+    return this.#height / 2;
+  }
+
+  draw(selected) {
+    ctx.beginPath();
+    ctx.moveTo(this.x, this.y);
+    ctx.fillStyle = this.color;
+    ctx.ellipse(
+      this.x + this.width / 2,
+      this.y + this.height / 2,
+      this.width / 2,
+      this.height / 2,
+      0,
+      0,
+      2 * Math.PI
+    );
+    ctx.fill();
+    ctx.closePath();
+    if (selected) {
+      ctx.beginPath();
+      ctx.strokeStyle = "green";
+      ctx.ellipse(
+        this.x + this.width / 2,
+        this.y + this.height / 2,
+        this.width / 2,
+        this.height / 2,
+        0,
+        0,
+        2 * Math.PI
+      );
+      ctx.stroke();
+      ctx.closePath();
+    }
+  }
+
+  in(x, y) {
+    let cx = (this.x * 2 + this.width) / 2;
+    let cy = (this.y * 2 + this.height) / 2;
+    return (
+      (x - cx) ** 2 / (this.width / 2) ** 2 +
+        (y - cy) ** 2 / (this.height / 2) ** 2 <=
+      1
+    );
+  }
+}
+
+color.onchange = () => {
+  selection.forEach((c) => (c.color = color.value));
+  Drawable.drawAll(selection);
+};
+
+document.getElementById("delete").onclick = () => {
+  Drawable.instances = Drawable.instances.filter(
+    (item) => !selection.includes(item)
+  );
+  selection = [];
+  Drawable.drawAll();
+};
+// new Rectangle(10, 10, 100, 100, "black");
+//new Line(0,0,100,100, "red")
+////new Circle(30,30,10, "red")
+
+////canvas.onmousemove = function(e){
+////}
+
+//undo.onclick = function(){
+//Drawable.instances.pop()
+////Drawable.instances = []
+//Drawable.drawAll()
+//}

+ 35 - 0
16/styles.css

@@ -0,0 +1,35 @@
+* {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  margin: 0;
+  padding: 0;
+}
+
+button {
+  width: 100%;
+  font-size: 2em;
+}
+input,
+button,
+select {
+  width: 100%;
+  font-size: 2em;
+}
+
+table {
+  border: 1px;
+  border-collapse: collapse;
+}
+
+td,
+th {
+  border: 1px solid black;
+}
+
+/*div#content {*/
+/*display: none;*/
+/*}*/