diff --git a/hw7node/main.js b/hw7node/main.js
new file mode 100644
index 0000000..e60a7ff
--- /dev/null
+++ b/hw7node/main.js
@@ -0,0 +1,22 @@
+let products = [{"product_name": "Мышка", "price": 100}]
+
+const http = require ('http');
+
+const server = http.createServer((req, res) => {
+ if(req.url === '/') {
+ res.write('Hello');
+ res.end();
+ }
+
+ if(req.url === '/products') {
+ res.write(JSON.stringify(products));
+ res.end();
+ }
+})
+
+server.listen(3000);
+server.on('connection', (socket) => {
+ console.log('New connection')
+});
+
+console.log('server listen at port 3000...');
\ No newline at end of file
diff --git a/hw7node/package-lock.json b/hw7node/package-lock.json
new file mode 100644
index 0000000..04b7f04
--- /dev/null
+++ b/hw7node/package-lock.json
@@ -0,0 +1,13 @@
+{
+ "name": "hw7node",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "moment": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+ }
+ }
+}
diff --git a/hw7node/package.json b/hw7node/package.json
new file mode 100644
index 0000000..75330f4
--- /dev/null
+++ b/hw7node/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "hw7node",
+ "version": "1.0.0",
+ "description": "",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "moment": "^2.24.0"
+ }
+}
diff --git a/hw7node/project/package-lock.json b/hw7node/project/package-lock.json
new file mode 100644
index 0000000..8b396c4
--- /dev/null
+++ b/hw7node/project/package-lock.json
@@ -0,0 +1,363 @@
+{
+ "name": "project",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
+ },
+ "body-parser": {
+ "version": "1.18.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+ "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+ "requires": {
+ "bytes": "3.0.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "~1.6.3",
+ "iconv-lite": "0.4.23",
+ "on-finished": "~2.3.0",
+ "qs": "6.5.2",
+ "raw-body": "2.3.3",
+ "type-is": "~1.6.16"
+ }
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
+ },
+ "express": {
+ "version": "4.16.4",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+ "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+ "requires": {
+ "accepts": "~1.3.5",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.18.3",
+ "content-disposition": "0.5.2",
+ "content-type": "~1.0.4",
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.1.1",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.4",
+ "qs": "6.5.2",
+ "range-parser": "~1.2.0",
+ "safe-buffer": "5.1.2",
+ "send": "0.16.2",
+ "serve-static": "1.13.2",
+ "setprototypeof": "1.1.0",
+ "statuses": "~1.4.0",
+ "type-is": "~1.6.16",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+ "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "statuses": "~1.4.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "moment": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
+ },
+ "proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ }
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
+ },
+ "raw-body": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+ "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+ "requires": {
+ "bytes": "3.0.0",
+ "http-errors": "1.6.3",
+ "iconv-lite": "0.4.23",
+ "unpipe": "1.0.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "send": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
+ "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.0",
+ "statuses": "~1.4.0"
+ }
+ },
+ "serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.2",
+ "send": "0.16.2"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+ },
+ "statuses": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+ }
+ }
+}
diff --git a/hw7node/project/package.json b/hw7node/project/package.json
new file mode 100644
index 0000000..91669fe
--- /dev/null
+++ b/hw7node/project/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "express": "^4.16.4",
+ "moment": "^2.24.0"
+ }
+}
diff --git a/hw7node/project/public/index.html b/hw7node/project/public/index.html
new file mode 100644
index 0000000..d78f060
--- /dev/null
+++ b/hw7node/project/public/index.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ e-Shop
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hw7node/project/public/js/basketComponent.js b/hw7node/project/public/js/basketComponent.js
new file mode 100644
index 0000000..e7d7468
--- /dev/null
+++ b/hw7node/project/public/js/basketComponent.js
@@ -0,0 +1,84 @@
+Vue.component('cart', {
+ data() {
+ return {
+ cartItems: [],
+ imgCart: 'https://placehold.it/50x100',
+ cartUrl: '/getBasket.json',
+ showCart: false,
+ }
+ },
+ methods: {
+ addProduct(product) {
+ let find = this.cartItems.find(el => el.id_product === product.id_product);
+ if (find) {
+ this.$parent.putJson(`/api/cart/${find.id_product}`, { quantity: 1 })
+ .then(data => {
+ if (data.result) {
+ find.quantity++;
+ }
+ })
+ } else {
+ let prod = Object.assign({ quantity: 1 }, product);
+ this.$parent.postJson('/api/cart/', prod)
+ .then(data => {
+ if (data.result) {
+ this.cartItems.push(prod);
+ }
+ })
+ }
+ },
+ remove(product) {
+ let find = this.cartItems.find(el => el.id_product === product.id_product);
+ if (find && find.quantity > 1) {
+ this.$parent.putJson(`/api/cart/${find.id_product}`, { quantity: -1 })
+ .then(data => {
+ if (data.result) {
+ if (product.quantity > 1) {
+ product.quantity--;
+ }
+ }
+ })
+ } else {
+ this.$parent.deleteJson(`/api/cart/${find.id_product}`)
+ this.cartItems.splice(this.cartItems.indexOf(product), 1);
+ }
+ },
+ },
+ mounted() {
+ this.$parent.getJson(`/api/cart`)
+ .then(data => {
+ for (let el of data.contents) {
+ this.cartItems.push(el);
+ }
+ });
+ },
+ template: ``
+});
+Vue.component('cart-item', {
+ props: ['cartItem', 'img'],
+ template: `
+
+
![Some image]()
+
+
{{cartItem.product_name}}
+
Quantity: {{cartItem.quantity}}
+
$ {{cartItem.price}} each
+
+
+
+
{{cartItem.quantity*cartItem.price}}
+
+
+
`
+})
diff --git a/hw7node/project/public/js/errorComponent.js b/hw7node/project/public/js/errorComponent.js
new file mode 100644
index 0000000..34808e0
--- /dev/null
+++ b/hw7node/project/public/js/errorComponent.js
@@ -0,0 +1,19 @@
+Vue.component('error', {
+ data(){
+ return {
+ text: ''
+ }
+ },
+ methods: {
+ setError(error){
+ this.text = error
+ }
+ },
+ template: ``
+});
diff --git a/hw7node/project/public/js/productComponent.js b/hw7node/project/public/js/productComponent.js
new file mode 100644
index 0000000..bb11156
--- /dev/null
+++ b/hw7node/project/public/js/productComponent.js
@@ -0,0 +1,51 @@
+Vue.component('products', {
+ data(){
+ return {
+ filtered: [],
+ products: [],
+ imgCatalog: 'https://placehold.it/200x150',
+ catalogUrl: '/catalogData.json'
+ }
+ },
+ mounted(){
+ this.$parent.getJson(`/api/products`)
+ .then(data => {
+ for(let el of data){
+ this.products.push(el);
+ this.filtered.push(el);
+ }
+ });
+ // this.$parent.getJson(`getProducts.json`)
+ // .then(data => {
+ // for(let el of data){
+ // this.products.push(el);
+ // this.filtered.push(el);
+ // }
+ // });
+ },
+ methods: {
+ filter(value){
+ let regexp = new RegExp(value, 'i');
+ this.filtered = this.products.filter(el => regexp.test(el.product_name));
+ }
+ },
+ template: ``
+});
+
+Vue.component('product', {
+ props: ['product', 'img'],
+ template: `
+
![Some img]()
+
+
{{ product.product_name }}
+
{{ product.price }} $
+
+
+
`
+})
diff --git a/hw7node/project/public/js/script.js b/hw7node/project/public/js/script.js
new file mode 100644
index 0000000..6065db1
--- /dev/null
+++ b/hw7node/project/public/js/script.js
@@ -0,0 +1,63 @@
+const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses';
+
+let app = new Vue({
+ el: '#app',
+ methods: {
+ getJson(url){
+ return fetch(url)
+ .then(result => result.json())
+ .catch(error => {
+ this.$refs.error.setError(error);
+ console.log(error)
+ })
+ },
+ postJson(url, data){
+ return fetch(url, {
+ method: 'POST',
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(data)
+ })
+ .then(result => result.json())
+ .catch(error => {
+ this.$refs.error.setError(error);
+ console.log(error)
+ })
+ },
+ putJson(url, data){
+ return fetch(url, {
+ method: 'PUT',
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(data)
+ })
+ .then(result => result.json())
+ .catch(error => {
+ this.$refs.error.setError(error);
+ console.log(error)
+ })
+ },
+ deleteJson(url, data){
+ return fetch(url, {
+ method: 'DELETE',
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(data)
+ })
+ .then(result => result.json())
+ .catch(error => {
+ this.$refs.error.setError(error);
+ console.log(error)
+ })
+ },
+
+ },
+ mounted(){
+
+
+
+ }
+})
diff --git a/hw7node/project/public/js/searchComponent.js b/hw7node/project/public/js/searchComponent.js
new file mode 100644
index 0000000..8640bc9
--- /dev/null
+++ b/hw7node/project/public/js/searchComponent.js
@@ -0,0 +1,14 @@
+Vue.component('filter-el', {
+ data(){
+ return {
+ userSearch: '',
+ }
+ },
+ template: ``
+ });
+
\ No newline at end of file
diff --git a/hw7node/project/public/styles/normalize.css b/hw7node/project/public/styles/normalize.css
new file mode 100644
index 0000000..8c331ec
--- /dev/null
+++ b/hw7node/project/public/styles/normalize.css
@@ -0,0 +1,350 @@
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+ ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+ html {
+ line-height: 1.15; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+ }
+
+ /* Sections
+ ========================================================================== */
+
+ /**
+ * Remove the margin in all browsers.
+ */
+
+ body {
+ margin: 0;
+ }
+
+ /**
+ * Render the `main` element consistently in IE.
+ */
+
+ main {
+ display: block;
+ }
+
+ /**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+ h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+ }
+
+ /* Grouping content
+ ========================================================================== */
+
+ /**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+ hr {
+ box-sizing: content-box; /* 1 */
+ height: 0; /* 1 */
+ overflow: visible; /* 2 */
+ }
+
+ /**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+ pre {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+ }
+
+ /* Text-level semantics
+ ========================================================================== */
+
+ /**
+ * Remove the gray background on active links in IE 10.
+ */
+
+ a {
+ background-color: transparent;
+ }
+
+ /**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+ abbr[title] {
+ border-bottom: none; /* 1 */
+ text-decoration: underline; /* 2 */
+ text-decoration: underline dotted; /* 2 */
+ }
+
+ /**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+ b,
+ strong {
+ font-weight: bolder;
+ }
+
+ /**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+ code,
+ kbd,
+ samp {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+ }
+
+ /**
+ * Add the correct font size in all browsers.
+ */
+
+ small {
+ font-size: 80%;
+ }
+
+ /**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+ sub,
+ sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+ }
+
+ sub {
+ bottom: -0.25em;
+ }
+
+ sup {
+ top: -0.5em;
+ }
+
+ /* Embedded content
+ ========================================================================== */
+
+ /**
+ * Remove the border on images inside links in IE 10.
+ */
+
+ img {
+ border-style: none;
+ }
+
+ /* Forms
+ ========================================================================== */
+
+ /**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+ button,
+ input,
+ optgroup,
+ select,
+ textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+ }
+
+ /**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+ button,
+ input { /* 1 */
+ overflow: visible;
+ }
+
+ /**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+ button,
+ select { /* 1 */
+ text-transform: none;
+ }
+
+ /**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+ button,
+ [type="button"],
+ [type="reset"],
+ [type="submit"] {
+ -webkit-appearance: button;
+ }
+
+ /**
+ * Remove the inner border and padding in Firefox.
+ */
+
+ button::-moz-focus-inner,
+ [type="button"]::-moz-focus-inner,
+ [type="reset"]::-moz-focus-inner,
+ [type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+ }
+
+ /**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+ button:-moz-focusring,
+ [type="button"]:-moz-focusring,
+ [type="reset"]:-moz-focusring,
+ [type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+ }
+
+ /**
+ * Correct the padding in Firefox.
+ */
+
+ fieldset {
+ padding: 0.35em 0.75em 0.625em;
+ }
+
+ /**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+ legend {
+ box-sizing: border-box; /* 1 */
+ color: inherit; /* 2 */
+ display: table; /* 1 */
+ max-width: 100%; /* 1 */
+ padding: 0; /* 3 */
+ white-space: normal; /* 1 */
+ }
+
+ /**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+ progress {
+ vertical-align: baseline;
+ }
+
+ /**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+ textarea {
+ overflow: auto;
+ }
+
+ /**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+ [type="checkbox"],
+ [type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+ }
+
+ /**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+ [type="number"]::-webkit-inner-spin-button,
+ [type="number"]::-webkit-outer-spin-button {
+ height: auto;
+ }
+
+ /**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+ [type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ outline-offset: -2px; /* 2 */
+ }
+
+ /**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+ [type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+ }
+
+ /**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+ ::-webkit-file-upload-button {
+ -webkit-appearance: button; /* 1 */
+ font: inherit; /* 2 */
+ }
+
+ /* Interactive
+ ========================================================================== */
+
+ /*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+ details {
+ display: block;
+ }
+
+ /*
+ * Add the correct display in all browsers.
+ */
+
+ summary {
+ display: list-item;
+ }
+
+ /* Misc
+ ========================================================================== */
+
+ /**
+ * Add the correct display in IE 10+.
+ */
+
+ template {
+ display: none;
+ }
+
+ /**
+ * Add the correct display in IE 10.
+ */
+
+ [hidden] {
+ display: none;
+ }
+
\ No newline at end of file
diff --git a/hw7node/project/public/styles/style.css b/hw7node/project/public/styles/style.css
new file mode 100644
index 0000000..008f02f
--- /dev/null
+++ b/hw7node/project/public/styles/style.css
@@ -0,0 +1,198 @@
+body{
+ font-family: 'SF Pro Display', sans-serif;
+}
+header{
+ display: flex;
+ background-color: #2f2a2d;
+ justify-content: space-between;
+ color: #fafafa;
+ padding: 30px 80px;
+}
+button:focus{
+ outline: none;
+}
+.logo{
+
+ text-transform: uppercase;
+ font-weight: bold;
+}
+.btn-cart{
+ background-color: #fafafa;
+ padding: 10px 20px;
+ border: 1px solid transparent;
+ color: #2f2a2d;
+ border-radius: 5px;
+ transition: all ease-in-out .4s;
+ cursor: pointer;
+}
+.btn-cart:hover{
+ background-color: transparent;
+ border-color: #fafafa;
+ color: #fafafa;
+}
+.btn-cart, .logo{
+ align-self: center;
+}
+/*.products {*/
+/*display: flex;*/
+/*justify-content: space-between;*/
+/*flex-wrap: wrap;*/
+/*padding: 40px 80px;*/
+/*}*/
+.products{
+ column-gap: 30px;
+ display: grid;
+ grid-template-columns: repeat(auto-fit, 200px);
+ grid-template-rows: 1fr;
+ padding: 40px 80px;
+ justify-content: space-between;
+}
+p {
+ margin: 0 0 5px 0;
+}
+.product-item{
+ display: flex;
+ flex-direction: column;
+ width: 200px;
+ border-radius: 5px;
+ overflow: hidden;
+ margin: 20px 0;
+}
+img {
+ max-width: 100%;
+ height: auto
+}
+.desc {
+ border: 1px solid #c0c0c040;
+ padding: 15px
+}
+.cart{
+ display: flex;
+ position: relative;
+}
+.cart-block{
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.62);
+ border-radius: 5px;
+ box-sizing: border-box;
+ right: 0;
+ top: 130%;
+ position: absolute;
+ background-color: white;
+ padding: 20px;
+ color: black;
+ width: 300px;
+}
+
+.invisible{
+ display: none;
+}
+.cart-block:before{
+ content: '';
+ width: 0;
+ height: 0;
+ position: absolute;
+ top: -10px;
+ right: 35px;
+ border-left: 10px solid transparent;
+ border-right: 10px solid transparent;
+ border-bottom: 10px solid white;
+}
+
+.buy-btn, .del-btn{
+ margin-top: 5px;
+ background-color: #2f2a2d;
+ padding: 5px 15px;
+ border: 1px solid transparent;
+ color: #fafafa;
+ border-radius: 5px;
+ transition: all ease-in-out .4s;
+ cursor: pointer;
+}
+.buy-btn:hover, .del-btn:hover{
+ background-color: #fafafa;
+ color: #2f2a2d;
+ border: 1px solid #2f2a2d;
+}
+.cart-item {
+ display: flex;
+ justify-content: space-between;
+}
+.cart-item:not(:last-child){
+ margin-bottom: 20px;
+}
+.product-bio{
+ display: flex;
+}
+.cart-item img{
+ align-self: flex-start;
+ margin-right: 15px;
+}
+.product-single-price{
+ color: #474747;
+ font-size: 0.5em;
+}
+.product-price{
+ margin-left: 30px;
+}
+.product-desc{
+ max-width: 150px;
+}
+.product-quantity {
+ margin-top: 15px;
+ font-size: 0.75em;
+}
+.right-block{
+ text-align: right;
+}
+.btn-search {
+ background-color: transparent;
+ border: none;
+ color: #fafafa;
+ font-size: 1.2em;
+ position: absolute;
+ bottom: 5px;
+ right: 0;
+}
+.search-form{
+ position: relative;
+ margin-right: 50px;
+ display: inline-block;
+}
+.search-field:focus{
+ outline: none;
+}
+.search-field {
+ box-sizing: border-box;
+ width: 200px;
+ color: #fafafa;
+ padding: 10px;
+ background-color: transparent;
+ border: none;
+ border-bottom: 2px solid #fafafa;
+}
+.error-msg {
+ padding: 30px 20px;
+ background-color: red;
+ color: white;
+ position: relative;
+}
+.error-block {
+ background-color: rgba(0,0,0, .5);
+ justify-content: center;
+ display: flex;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ align-items: center;
+}
+.close-btn {
+ font-size: 1.5em;
+ top: -40px;
+ position: absolute;
+ right: 0;
+ background: none;
+ border: none;
+ color: white;
+ font-weight: bold;
+}
diff --git a/hw7node/project/server/cart.js b/hw7node/project/server/cart.js
new file mode 100644
index 0000000..4fc81d5
--- /dev/null
+++ b/hw7node/project/server/cart.js
@@ -0,0 +1,20 @@
+let add = (cart, req) => {
+ cart.contents.push (req.body);
+ return JSON.stringify(cart, null, 4);
+}
+
+let change = (cart, req) => {
+ let find = cart.contents.find(el => el.id_product === +req.params.id);
+ find.quantity += req.body.quantity;
+ return JSON.stringify(cart, null, 4);
+}
+
+let remove = (cart, req) => {
+ let find = cart.contents.find(el => el.id_product === +req.params.id);
+ cart.contents.splice(cart.contents.indexOf(find), 1);
+ return JSON.stringify(cart, null, 4);
+}
+
+module.exports = {
+ add, change, remove
+}
\ No newline at end of file
diff --git a/hw7node/project/server/db/products.json b/hw7node/project/server/db/products.json
new file mode 100644
index 0000000..8d546ba
--- /dev/null
+++ b/hw7node/project/server/db/products.json
@@ -0,0 +1,42 @@
+[
+ {
+ "id_product": 124,
+ "product_name": "Keyboard",
+ "price": 1600
+ },
+ {
+ "id_product": 457,
+ "product_name": "Gamepad",
+ "price": 3000
+ },
+ {
+ "id_product": 129,
+ "product_name": "Notebook",
+ "price": 160000
+ },
+ {
+ "id_product": 458,
+ "product_name": "Display",
+ "price": 12000
+ },
+ {
+ "id_product": 224,
+ "product_name": "USB-Camera",
+ "price": 2400
+ },
+ {
+ "id_product": 228,
+ "product_name": "Scaner",
+ "price": 6000
+ },
+ {
+ "id_product": 123,
+ "product_name": "Ноутбук",
+ "price": 45600
+ },
+ {
+ "id_product": 456,
+ "product_name": "Мышка",
+ "price": 1000
+ }
+]
\ No newline at end of file
diff --git a/hw7node/project/server/db/userCart.json b/hw7node/project/server/db/userCart.json
new file mode 100644
index 0000000..01531c9
--- /dev/null
+++ b/hw7node/project/server/db/userCart.json
@@ -0,0 +1,5 @@
+{
+ "amount": 46600,
+ "countGoods": 2,
+ "contents": []
+}
\ No newline at end of file
diff --git a/hw7node/project/server/handler.js b/hw7node/project/server/handler.js
new file mode 100644
index 0000000..17a5985
--- /dev/null
+++ b/hw7node/project/server/handler.js
@@ -0,0 +1,27 @@
+const cart = require('./cart');
+const fs = require('fs');
+
+const actions = {
+ add: cart.add,
+ change: cart.change,
+ remove: cart.remove
+};
+
+let handler = (req, res, action, file) => {
+ fs.readFile(file, 'utf8', (err, data) => {
+ if (err) {
+ res.sendStatus(404, JSON.stringify({ result: 0, text: err }));
+ } else {
+ let newCart = actions[action](JSON.parse(data), req);
+ fs.writeFile(file, newCart, (err) => {
+ if (err) {
+ res.sendStatus(404, JSON.stringify({ result: 0, text: err }));
+ } else {
+ res.send({ result: 1, text: 'success' });
+ }
+ })
+ }
+ })
+}
+
+module.exports = handler;
\ No newline at end of file
diff --git a/hw7node/project/server/server.js b/hw7node/project/server/server.js
new file mode 100644
index 0000000..ae30f56
--- /dev/null
+++ b/hw7node/project/server/server.js
@@ -0,0 +1,53 @@
+//в экспрессе мы получаем особые методы отлова запросов
+//
+// app.get();
+// app.post();
+// app.put();
+// app.delete();
+
+
+const express = require('express');
+const fs = require('fs');
+const app = express();
+app.use(express.json ());//определение json запроса
+app.use('/', express.static('public'));
+
+app.get('/api/products', (req, res) => {
+ fs.readFile('server/db/products.json', 'utf8', (err, data) => {
+ if (err) {
+ res.sendStatus(404, JSON.stringify({result: 0, text: err}));
+ } else {
+ res.send(data);
+ }
+ });
+});
+
+app.get('/api/cart', (req, res) => {
+ fs.readFile('server/db/userCart.json', 'utf8', (err, data) => {
+ if (err) {
+ res.sendStatus(404, JSON.stringify({result: 0, text: err}));
+ } else {
+ res.send(data);
+ }
+ });
+});
+
+const handler = require('./handler');
+
+app.post ('/api/cart/', (req, res) => {
+ handler(req, res, 'add', 'server/db/userCart.json');
+});
+
+app.put ('/api/cart/:id', (req, res) => {
+ handler(req, res, 'change', 'server/db/userCart.json');
+});
+
+app.delete ('/api/cart/:id', (req, res) => {
+ handler(req, res, 'remove', 'server/db/userCart.json');
+});
+
+
+app.listen(3000, () => ('listening at port 3000...'));
+
+
+