@@ -33,6 +34,7 @@
Alex Smith
Web Designer
+ Skills
diff --git a/docs/skills.html b/docs/skills.html
new file mode 100644
index 0000000..b489af9
--- /dev/null
+++ b/docs/skills.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
Portfolio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Web Designer
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/style.css b/docs/style.css
similarity index 85%
rename from dist/style.css
rename to docs/style.css
index cf482ab..5aed4df 100644
--- a/dist/style.css
+++ b/docs/style.css
@@ -91,7 +91,7 @@ body {
background-color: #c4c4c4;
}
.card__button {
- margin-top: 57px;
+ margin-top: 20px;
}
.btn {
display: inline-block;
@@ -136,6 +136,9 @@ body {
font-weight: normal;
margin-top: 8px;
}
+.card__info-button {
+ margin-top: 20px;
+}
button {
background-color: var(--bg-button);
padding: 10px 30px;
@@ -152,7 +155,7 @@ button {
right: 30px;
top: 10px;
}
-input {
+#switcher {
width: 0;
height: 0;
display: none;
@@ -180,11 +183,11 @@ label::after {
background-color: #2e2a44;
transition: 0.5s ease;
}
-input:checked + label::after {
+#switcher:checked + label::after {
left: calc(100% - 25px);
background-color: aliceblue;
}
-input + label {
+#switcher + label {
background-color: var(--input-bg-color);
border: 2px solid var(--input-border-color);
}
@@ -494,3 +497,89 @@ template {
[hidden] {
display: none;
}
+
+.skills {
+ position: relative;
+ height: 90%;
+ width: 90%;
+ display: flex;
+ flex-direction: column;
+}
+.skills__title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+.skills__button svg {
+ fill: #222222;
+ width: 40px;
+ height: 40px;
+}
+.skills__add-dialog {
+ width: 400px;
+ height: 200px;
+ position: absolute;
+ background-color: #444;
+ border-radius: 1em;
+ right: 50px;
+ top: 0;
+ z-index: 1;
+ display: flex;
+ padding: 20px;
+ flex-direction: column;
+ justify-content: space-around;
+}
+.skills__input {
+ outline: none;
+ height: 50px;
+ border-radius: 10px;
+ font-size: 20px;
+ padding: 0 10px;
+ background: transparent;
+ border: 3px solid #999;
+ color: #999;
+}
+.skills__content {
+ margin-top: 10px;
+}
+.skills__item {
+ margin: 35px 0;
+ display: flex;
+ align-items: center;
+}
+.skills__item-inner {
+ flex-grow: 1;
+ margin-right: 10px;
+}
+.skills__item-subtitle {
+ display: flex;
+ justify-content: space-between;
+}
+.skills__button {
+ width: 40px;
+ height: 40px;
+ background-color: #fff;
+ border-radius: 50%;
+}
+.progress-bar {
+ margin-top: 10px;
+ height: 15px;
+ position: relative;
+ border: 1px solid #6da8c4;
+ border-radius: 25px;
+ padding: 3px;
+}
+.progress-bar > span {
+ display: block;
+ height: 100%;
+ border-radius: 20px 8px 8px 20px;
+ background-color: #52b2da;
+ position: relative;
+ overflow: hidden;
+}
+.blue {
+ color: #52b2da;
+}
+.hidden {
+ display: none;
+}
diff --git a/gulpfile.js b/gulpfile.js
index 698d238..20b18f3 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -4,15 +4,16 @@ const less = require('gulp-less');
const inject = require('gulp-inject');
const rollup = require('rollup');
const image = require('gulp-image');
+const typescript = require('@rollup/plugin-typescript');
const assetsPath = 'src/assets/*.{jpg,jpeg,png,webp}';
const stylesPath = './src/styles/**/*.scss';
-const jsPath = 'src/**/*.js';
-const htmlPath = './src/index.html';
-const distPath = './dist/';
+const jsPath = './src/**/*.ts';
+const htmlPath = './src/skills.html';
+const distPath = './docs/';
const rollupConfig = {
- input: 'src/app.js',
- plugins: []
+ input: './src/app.ts',
+ plugins: [typescript()]
}
const imageOptimizingSettings = {
@@ -33,7 +34,7 @@ gulp.task('rollup', async (done) => {
bundle.write({
format: 'esm',
- file: 'dist/app.js'
+ file: 'docs/app.js'
});
done();
@@ -73,11 +74,11 @@ gulp.task('assets', function () {
*/
gulp.task('html', function () {
const target = gulp.src(htmlPath);
- const sources = gulp.src(['./dist/**/*.js', './dist/**/*.css'], { read: false });
+ const sources = gulp.src(['./docs/**/*.js', './docs/**/*.css'], { read: false });
- return target.pipe(inject(sources, { ignorePath: '../dist', relative: true, addPrefix: '.' }))
+ return target.pipe(inject(sources, { ignorePath: '../docs', relative: true, addPrefix: '.' }))
.pipe(gulp.dest(distPath));
});
-gulp.task('default', gulp.series('rollup', 'css', 'assets', 'html', 'watch'));
+gulp.task('default', gulp.series('rollup', 'css', 'html', 'assets', 'watch'));
gulp.task('build', gulp.series('rollup', 'css', 'assets', 'html'));
diff --git a/package-lock.json b/package-lock.json
index ef5034d..d638400 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,13 +9,51 @@
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
+ "@rollup/plugin-typescript": "^8.3.0",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-image": "^6.2.1",
"gulp-inject": "^5.0.5",
"gulp-less": "^5.0.0",
+ "gulp-typescript": "^6.0.0-alpha.1",
"rollup": "^2.58.0",
- "sass": "^1.43.2"
+ "sass": "^1.43.2",
+ "typescript": "^4.5.2"
+ }
+ },
+ "node_modules/@rollup/plugin-typescript": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz",
+ "integrity": "sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==",
+ "dev": true,
+ "dependencies": {
+ "@rollup/pluginutils": "^3.1.0",
+ "resolve": "^1.17.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.14.0",
+ "tslib": "*",
+ "typescript": ">=3.7.0"
+ }
+ },
+ "node_modules/@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0"
}
},
"node_modules/@sindresorhus/is": {
@@ -27,6 +65,12 @@
"node": ">=4"
}
},
+ "node_modules/@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
"node_modules/@types/q": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
@@ -1945,6 +1989,12 @@
"node": ">=4"
}
},
+ "node_modules/estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
"node_modules/exec-buffer": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz",
@@ -2461,6 +2511,20 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -2876,6 +2940,25 @@
"node": ">=0.10.0"
}
},
+ "node_modules/glob-watcher/node_modules/fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ },
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
"node_modules/glob-watcher/node_modules/glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -3263,6 +3346,54 @@
"readable-stream": "3"
}
},
+ "node_modules/gulp-typescript": {
+ "version": "6.0.0-alpha.1",
+ "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz",
+ "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "plugin-error": "^1.0.1",
+ "source-map": "^0.7.3",
+ "through2": "^3.0.1",
+ "vinyl": "^2.2.0",
+ "vinyl-fs": "^3.0.3"
+ },
+ "engines": {
+ "node": ">= 8"
+ },
+ "peerDependencies": {
+ "typescript": "~2.7.1 || >=2.8.0-dev || >=2.9.0-dev || ~3.0.0 || >=3.0.0-dev || >=3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev "
+ }
+ },
+ "node_modules/gulp-typescript/node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/gulp-typescript/node_modules/source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/gulp-typescript/node_modules/through2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
+ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "readable-stream": "2 || 3"
+ }
+ },
"node_modules/gulp/node_modules/gulp-cli": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz",
@@ -7027,6 +7158,19 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
+ "node_modules/typescript": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz",
+ "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
"node_modules/unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@@ -7498,12 +7642,39 @@
}
},
"dependencies": {
+ "@rollup/plugin-typescript": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz",
+ "integrity": "sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.1.0",
+ "resolve": "^1.17.0"
+ }
+ },
+ "@rollup/pluginutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
+ "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "0.0.39",
+ "estree-walker": "^1.0.1",
+ "picomatch": "^2.2.2"
+ }
+ },
"@sindresorhus/is": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
"integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
"dev": true
},
+ "@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
"@types/q": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
@@ -9052,6 +9223,12 @@
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
+ "estree-walker": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
+ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
+ "dev": true
+ },
"exec-buffer": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz",
@@ -9469,6 +9646,13 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true
+ },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -9784,6 +9968,17 @@
"to-regex-range": "^2.1.0"
}
},
+ "fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ }
+ },
"glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -10133,6 +10328,44 @@
}
}
},
+ "gulp-typescript": {
+ "version": "6.0.0-alpha.1",
+ "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz",
+ "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1",
+ "plugin-error": "^1.0.1",
+ "source-map": "^0.7.3",
+ "through2": "^3.0.1",
+ "vinyl": "^2.2.0",
+ "vinyl-fs": "^3.0.3"
+ },
+ "dependencies": {
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "through2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
+ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.4",
+ "readable-stream": "2 || 3"
+ }
+ }
+ }
+ },
"gulplog": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
@@ -13011,6 +13244,12 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
+ "typescript": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz",
+ "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==",
+ "dev": true
+ },
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
diff --git a/package.json b/package.json
index b022f81..6e3fbf0 100644
--- a/package.json
+++ b/package.json
@@ -11,12 +11,14 @@
"author": "",
"license": "ISC",
"devDependencies": {
+ "@rollup/plugin-typescript": "^8.3.0",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-image": "^6.2.1",
"gulp-inject": "^5.0.5",
"gulp-less": "^5.0.0",
"rollup": "^2.58.0",
- "sass": "^1.43.2"
+ "sass": "^1.43.2",
+ "typescript": "^4.5.2"
}
}
diff --git a/src/app.js b/src/app.js
deleted file mode 100644
index a2ede2d..0000000
--- a/src/app.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const switcher = document.getElementById('switcher');
-
-document.addEventListener("DOMContentLoaded", function() {
- switcher.addEventListener('change', switchTheme);
-})
-
-function switchTheme (event) {
- if (event.target.checked) {
- document.body.classList.add('dark-theme');
- document.body.classList.remove('light-theme');
- } else {
- document.body.classList.remove('dark-theme');
- document.body.classList.add('light-theme');
- }
-}
diff --git a/src/app.ts b/src/app.ts
new file mode 100644
index 0000000..9c4280d
--- /dev/null
+++ b/src/app.ts
@@ -0,0 +1,7 @@
+import SkillController from "./scripts/SkillController";
+import './scripts/Switcher';
+
+const addSkillBtn: HTMLElement = document.getElementById('add-skill');
+const addBlock: HTMLElement = document.querySelector('.skills__add-dialog');
+
+const skillController: SkillController = new SkillController(addSkillBtn, addBlock);
diff --git a/src/index.html b/src/index.html
index 3acc23f..0b9d704 100644
--- a/src/index.html
+++ b/src/index.html
@@ -20,6 +20,7 @@
Web Designer
+
Skills
@@ -32,6 +33,7 @@
Alex Smith
Web Designer
+ Skills
diff --git a/src/scripts/Skill.ts b/src/scripts/Skill.ts
new file mode 100644
index 0000000..6d01308
--- /dev/null
+++ b/src/scripts/Skill.ts
@@ -0,0 +1,6 @@
+class Skill {
+ constructor(readonly name: string, readonly ratio: number) {
+ }
+}
+
+export default Skill;
diff --git a/src/scripts/SkillController.ts b/src/scripts/SkillController.ts
new file mode 100644
index 0000000..1a90d44
--- /dev/null
+++ b/src/scripts/SkillController.ts
@@ -0,0 +1,58 @@
+import SkillView from "./SkillView";
+import Skill from "./Skill";
+
+class SkillController {
+ readonly startSkills: Skill[] = [
+ new Skill('JavaScript', 85),
+ new Skill('HTML', 100),
+ new Skill('PHP', 75)
+ ];
+ readonly skills: Skill[] = [];
+ readonly skillView: SkillView;
+ readonly addBlock: HTMLElement;
+ readonly addForm: HTMLFormElement;
+ readonly inputs: NodeListOf
;
+
+ constructor(addSkillButton: HTMLElement, addBlock: HTMLElement) {
+ this.skillView = new SkillView(document.querySelector('.skills__content'));
+
+ this.addBlock = addBlock;
+ this.addForm = document.forms[0];
+ this.inputs = this.addForm.querySelectorAll('.skills__input');
+
+ for (let i = 0; i < this.startSkills.length; i++) {
+ this.addSkill(this.startSkills[i]);
+ }
+
+ addSkillButton.addEventListener('click', () => this.showSkillForm());
+ this.addBlock.addEventListener('submit', (event) => this.addSkillEvent(event));
+ }
+
+ addSkill(skill: Skill) {
+ if (skill.ratio <= 100 && skill.ratio >= 0 && this.skills.length < 5 && skill.name.length < 20) {
+ this.skills.push(skill);
+ const skillsButton = this.skillView.renderNewSkill(this.skills.length - 1, skill);
+ skillsButton.addEventListener('click', () => {
+ this.removeSkill(skillsButton);
+ });
+ }
+ }
+
+ removeSkill(skillNode: HTMLElement) {
+ this.skills.splice(Number(skillNode.id), 1);
+ this.skillView.removeSkill(skillNode);
+ }
+
+ addSkillEvent(event) {
+ event.preventDefault();
+ this.addSkill(new Skill(this.inputs[0].value, Number(this.inputs[1].value)));
+ this.addForm.reset();
+ this.addBlock.classList.add('hidden');
+ }
+
+ showSkillForm() {
+ this.addBlock.classList.toggle('hidden');
+ }
+}
+
+export default SkillController;
diff --git a/src/scripts/SkillView.ts b/src/scripts/SkillView.ts
new file mode 100644
index 0000000..1f7696a
--- /dev/null
+++ b/src/scripts/SkillView.ts
@@ -0,0 +1,51 @@
+class SkillView {
+ constructor(readonly skillsContainer) {
+ }
+
+ removeSkill(skillNode) {
+ skillNode.parentNode.remove();
+ }
+
+ renderNewSkill(id, skill): HTMLElement {
+ const skillItem: HTMLElement = document.createElement('div');
+ const skillItemInner: HTMLElement = document.createElement('div');
+ const skillSubtitle: HTMLElement = document.createElement('div');
+ const skillName: HTMLElement = document.createElement('span');
+ const skillRatio: HTMLElement = document.createElement('span');
+ const progressbar: HTMLElement = document.createElement('div');
+ const progressbarInner: HTMLElement = document.createElement('span');
+ const skillsButton: HTMLElement = document.createElement('div');
+ const svg: SVGElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
+ const use: SVGElement = document.createElementNS('http://www.w3.org/2000/svg', 'use');
+
+ skillItem.classList.add('skills__item');
+ skillItemInner.classList.add('skills__item-inner');
+ skillSubtitle.classList.add('skills__item-subtitle');
+ progressbar.classList.add('progress-bar');
+ skillsButton.classList.add('skills__button');
+ skillsButton.classList.add('delete-button');
+
+ skillsButton.id = id;
+
+ skillName.innerText = skill.name;
+ skillRatio.innerText = skill.ratio + '%';
+
+ progressbarInner.style.width = skillRatio.innerText;
+ use.setAttribute('href', '#minus');
+
+ skillItem.appendChild(skillItemInner);
+ skillItem.appendChild(skillsButton);
+ skillItemInner.appendChild(skillSubtitle);
+ skillSubtitle.appendChild(skillName);
+ skillSubtitle.appendChild(skillRatio);
+ skillItemInner.appendChild(progressbar);
+ progressbar.appendChild(progressbarInner);
+ skillsButton.appendChild(svg);
+ svg.appendChild(use);
+
+ this.skillsContainer.appendChild(skillItem);
+ return skillsButton;
+ }
+}
+
+export default SkillView;
diff --git a/dist/app.js b/src/scripts/Switcher.ts
similarity index 55%
rename from dist/app.js
rename to src/scripts/Switcher.ts
index a2ede2d..bec343a 100644
--- a/dist/app.js
+++ b/src/scripts/Switcher.ts
@@ -1,10 +1,7 @@
-const switcher = document.getElementById('switcher');
+const switcher: HTMLElement = document.getElementById('switcher');
+switcher.addEventListener('change', switchTheme);
-document.addEventListener("DOMContentLoaded", function() {
- switcher.addEventListener('change', switchTheme);
-})
-
-function switchTheme (event) {
+function switchTheme(event) {
if (event.target.checked) {
document.body.classList.add('dark-theme');
document.body.classList.remove('light-theme');
diff --git a/src/skills.html b/src/skills.html
new file mode 100644
index 0000000..6a669a1
--- /dev/null
+++ b/src/skills.html
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+ Portfolio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Web Designer
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/styles/app.scss b/src/styles/app.scss
index e5284e0..1be66b4 100644
--- a/src/styles/app.scss
+++ b/src/styles/app.scss
@@ -96,7 +96,7 @@ body {
}
.card__button {
- margin-top: 57px;
+ margin-top: 20px;
}
.btn {
@@ -148,6 +148,10 @@ body {
margin-top: 8px;
}
+.card__info-button {
+ margin-top: 20px;
+}
+
button {
background-color: var(--bg-button);
padding: 10px 30px;
@@ -159,17 +163,20 @@ button {
margin-top: 20px;
cursor: pointer;
}
+
.theme-switcher {
position: absolute;
right: 30px;
top: 10px;
}
-input {
+
+#switcher {
width: 0;
height: 0;
display: none;
visibility: hidden;
}
+
label {
cursor: pointer;
display: block;
@@ -180,6 +187,7 @@ label {
background-color: rgb(255, 255, 255);
transition: 0.5s ease background-color;
}
+
label::after {
position: absolute;
content: "";
@@ -192,11 +200,13 @@ label::after {
background-color: rgb(46, 42, 68);
transition: 0.5s ease;
}
-input:checked + label::after {
+
+#switcher:checked + label::after {
left: calc(100% - 25px);
background-color: aliceblue;
}
-input + label {
+
+#switcher + label {
background-color: var(--input-bg-color);
border: 2px solid var(--input-border-color);
}
diff --git a/src/styles/skills.scss b/src/styles/skills.scss
new file mode 100644
index 0000000..c790eef
--- /dev/null
+++ b/src/styles/skills.scss
@@ -0,0 +1,98 @@
+.skills {
+ position: relative;
+ height: 90%;
+ width: 90%;
+ display: flex;
+ flex-direction: column;
+}
+
+.skills__title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.skills__button svg {
+ fill: #222222;
+ width: 40px;
+ height: 40px;
+}
+
+.skills__add-dialog {
+ width: 400px;
+ height: 200px;
+ position: absolute;
+ background-color: #444;
+ border-radius: 1em;
+ right: 50px;
+ top: 0;
+ z-index: 1;
+ display: flex;
+ padding: 20px;
+ flex-direction: column;
+ justify-content: space-around;
+}
+
+.skills__input {
+ outline: none;
+ height: 50px;
+ border-radius: 10px;
+ font-size: 20px;
+ padding: 0 10px;
+ background: transparent;
+ border: 3px solid #999;
+ color: #999;
+}
+
+.skills__content {
+ margin-top: 10px;
+}
+
+.skills__item {
+ margin: 35px 0;
+ display: flex;
+ align-items: center;
+}
+
+.skills__item-inner {
+ flex-grow: 1;
+ margin-right: 10px;
+}
+
+.skills__item-subtitle {
+ display: flex;
+ justify-content: space-between;
+}
+
+.skills__button {
+ width: 40px;
+ height: 40px;
+ background-color: #fff;
+ border-radius: 50%;
+}
+
+.progress-bar {
+ margin-top: 10px;
+ height: 15px;
+ position: relative;
+ border: 1px solid #6da8c4;
+ border-radius: 25px;
+ padding: 3px;
+}
+
+.progress-bar > span {
+ display: block;
+ height: 100%;
+ border-radius: 20px 8px 8px 20px;
+ background-color: #52b2da;
+ position: relative;
+ overflow: hidden;
+}
+
+.blue {
+ color: #52b2da;
+}
+
+.hidden {
+ display: none;
+}