diff --git a/focus-block/gulpfile.js b/focus-block/gulpfile.js new file mode 100644 index 0000000..d1db4de --- /dev/null +++ b/focus-block/gulpfile.js @@ -0,0 +1,23 @@ +var gulp = require('gulp'); +var sass = require('gulp-sass'); +var autoprefixer = require('gulp-autoprefixer'); + +var scss_files = 'scss/**/*.scss'; +var css_folder = 'public'; + +var sassOptions = { + errLogToConsole: true, + outputStyle: 'expanded' +}; + +gulp.task('sass', function () { + return gulp + .src(scss_files) + .pipe(sass(sassOptions).on('error', sass.logError)) + .pipe(autoprefixer()) + .pipe(gulp.dest(css_folder)); +}); + +gulp.task('watch', function () { + gulp.watch(scss_files, gulp.series('sass')); +}); \ No newline at end of file diff --git a/focus-block/package-lock.json b/focus-block/package-lock.json index eced5a0..3124ce0 100644 --- a/focus-block/package-lock.json +++ b/focus-block/package-lock.json @@ -132,11 +132,27 @@ "string-width": "^2.0.0" } }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "requires": { + "ansi-wrap": "^0.1.0" + } + }, "ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", @@ -155,6 +171,11 @@ "color-convert": "^1.9.0" } }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", @@ -246,6 +267,11 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, "are-we-there-yet": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", @@ -287,6 +313,16 @@ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + }, "array-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", @@ -326,6 +362,11 @@ "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=" }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -1335,6 +1376,11 @@ "tweetnacl": "^0.14.3" } }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" + }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", @@ -1940,6 +1986,11 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1998,6 +2049,11 @@ "color-name": "^1.0.0" } }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "colormin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", @@ -2541,6 +2597,11 @@ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2582,6 +2643,14 @@ "strip-bom": "^2.0.0" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, "define-properties": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", @@ -2662,6 +2731,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=" + }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -2676,6 +2750,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -2832,6 +2911,37 @@ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "~1.1.9" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -2893,6 +3003,24 @@ "iconv-lite": "~0.4.13" } }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "requires": { + "once": "~1.3.0" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "requires": { + "wrappy": "1" + } + } + } + }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", @@ -3704,6 +3832,23 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + }, + "dependencies": { + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + } + } + }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", @@ -3844,6 +3989,11 @@ "pkg-dir": "^2.0.0" } }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=" + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -3852,6 +4002,54 @@ "locate-path": "^2.0.0" } }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=" + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -4554,6 +4752,145 @@ "is-glob": "^2.0.0" } }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "requires": { + "gaze": "^0.5.1" + }, + "dependencies": { + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "requires": { + "globule": "~0.1.0" + } + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=" + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=" + }, + "lodash": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "requires": { + "find-index": "^0.1.1" + } + }, "global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -4612,6 +4949,14 @@ "minimatch": "~3.0.2" } }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "requires": { + "sparkles": "^1.0.0" + } + }, "got": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", @@ -4640,6 +4985,234 @@ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, + "gulp": { + "version": "3.9.1", + "resolved": "http://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "semver": { + "version": "4.3.6", + "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + } + } + }, + "gulp-autoprefixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-6.0.0.tgz", + "integrity": "sha512-MyLymXKVGTVBx/okQSBqmdhwhyqi3igBmZBwgpZp0GRbY1LY8VctOTLzwkQ18bZKJkSDnOKR5u32TMY9wSYdqQ==", + "requires": { + "autoprefixer": "^9.1.3", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1", + "postcss": "^7.0.2", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "autoprefixer": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.3.0.tgz", + "integrity": "sha512-rpp+REfk0Ii3lCoiXhU4+CGYn8FbYckmvj6JJbJGSdzaxYCGJ7EvpHncDqgfAn/P6XhWig4u9BBNnsFAfAd5wg==", + "requires": { + "browserslist": "^4.3.2", + "caniuse-lite": "^1.0.30000898", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.5", + "postcss-value-parser": "^3.3.1" + } + }, + "browserslist": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.3.tgz", + "integrity": "sha512-6h84UD1mmHeuQ9IucX6yzBc+KBYcBBTLYt2CXtY7GYCra6iE5kOm7oM+zuGw/0tjGtbJxjm58OvxSBmogEMCRQ==", + "requires": { + "caniuse-lite": "^1.0.30000898", + "electron-to-chromium": "^1.3.81", + "node-releases": "^1.0.0-alpha.15" + } + }, + "caniuse-lite": { + "version": "1.0.30000898", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000898.tgz", + "integrity": "sha512-ytlTZqO4hYe4rNAJhMynUAIUI33jsP2Bb1two/9OVC39wZjPZ8exIO0eCLw5mqAtegOGiGF0kkTWTn3B02L+mw==" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "electron-to-chromium": { + "version": "1.3.81", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.81.tgz", + "integrity": "sha512-+rym2xtzwPWmoi8AYRrCdW65QOT0vfUHjZb5mjgh0VLyj31pGM3CpP3znKhQNBzQaWujR/KEl/mfC2lnKYgADA==" + }, + "postcss": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.5.tgz", + "integrity": "sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ==", + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.5.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "gulp-sass": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.0.2.tgz", + "integrity": "sha512-q8psj4+aDrblJMMtRxihNBdovfzGrXJp1l4JU0Sz4b/Mhsi2DPrKFYCGDwjIWRENs04ELVHxdOJQ7Vs98OFohg==", + "requires": { + "chalk": "^2.3.0", + "lodash.clonedeep": "^4.3.2", + "node-sass": "^4.8.3", + "plugin-error": "^1.0.1", + "replace-ext": "^1.0.0", + "strip-ansi": "^4.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "requires": { + "glogg": "^1.0.0" + } + }, "gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", @@ -4745,6 +5318,14 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "requires": { + "sparkles": "^1.0.0" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -5323,6 +5904,15 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, "is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", @@ -5610,6 +6200,14 @@ "has": "^1.0.1" } }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -5648,6 +6246,14 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -6559,6 +7165,21 @@ "type-check": "~0.3.2" } }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -6646,11 +7267,51 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" + }, "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", @@ -6676,6 +7337,34 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -6686,6 +7375,11 @@ "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==" }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + }, "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -6774,6 +7468,14 @@ } } }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + } + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -7011,6 +7713,14 @@ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "requires": { + "duplexer2": "0.0.2" + } + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -7040,6 +7750,11 @@ "to-regex": "^3.0.1" } }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7167,6 +7882,14 @@ "which": "^1.3.0" } }, + "node-releases": { + "version": "1.0.0-alpha.15", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.15.tgz", + "integrity": "sha512-hKG6hd/g6a9OV/ARt2qrxbRhe/4WEMFohTLOB9PNyTYvvI59gICZFzt9/mMgpYUTts06qXlN8H6UjfbIRdnW8A==", + "requires": { + "semver": "^5.3.0" + } + }, "node-sass": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.0.tgz", @@ -7589,6 +8312,46 @@ "isobject": "^3.0.0" } }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -7677,6 +8440,21 @@ "wordwrap": "~1.0.0" } }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=" + }, "original": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", @@ -7795,6 +8573,16 @@ "pbkdf2": "^3.0.3" } }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -7869,6 +8657,19 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + }, "path-to-regexp": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", @@ -7945,6 +8746,17 @@ "find-up": "^2.1.0" } }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", @@ -9155,6 +9967,11 @@ "ansi-styles": "^3.0.0" } }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -9184,11 +10001,10 @@ } }, "prop-types": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", - "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "version": "15.6.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", + "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", "requires": { - "fbjs": "^0.8.16", "loose-envify": "^1.3.1", "object-assign": "^4.1.1" } @@ -9587,6 +10403,14 @@ "set-immediate-shim": "^1.0.1" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, "recursive-readdir": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.1.tgz", @@ -9777,6 +10601,11 @@ "is-finite": "^1.0.0" } }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, "request": { "version": "2.85.0", "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", @@ -10093,6 +10922,11 @@ } } }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=" + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -10202,6 +11036,11 @@ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -10417,6 +11256,11 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" + }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", @@ -10557,6 +11401,11 @@ "duplexer": "~0.1.1" } }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" + }, "stream-http": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.2.tgz", @@ -10826,11 +11675,28 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, "thunky": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=" }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "requires": { + "os-homedir": "^1.0.0" + } + }, "time-stamp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", @@ -11066,6 +11932,11 @@ } } }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -11116,6 +11987,11 @@ "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=" + }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -11290,6 +12166,11 @@ "kind-of": "^6.0.2" } }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, "util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", @@ -11325,6 +12206,14 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "requires": { + "user-home": "^1.1.1" + } + }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", @@ -11359,6 +12248,109 @@ "extsprintf": "^1.2.0" } }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "requires": { + "natives": "^1.1.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", diff --git a/focus-block/package.json b/focus-block/package.json index d361e4e..342b7b4 100644 --- a/focus-block/package.json +++ b/focus-block/package.json @@ -4,8 +4,12 @@ "private": true, "dependencies": { "classnames": "^2.2.5", + "gulp": "^3.9.1", + "gulp-autoprefixer": "^6.0.0", + "gulp-sass": "^4.0.2", "node-sass-chokidar": "^1.3.0", "npm-run-all": "^4.1.3", + "prop-types": "^15.6.2", "react": "^16.3.2", "react-dom": "^16.3.2", "react-ga": "^2.5.3", diff --git a/focus-block/public/index.html b/focus-block/public/index.html index 8c98237..c0dab42 100644 --- a/focus-block/public/index.html +++ b/focus-block/public/index.html @@ -3,25 +3,13 @@ - + - - + + - - FocusBlock + FocusBlock — Don't Get Stuck! @@ -29,16 +17,6 @@ You need to enable JavaScript to run this app.
- \ No newline at end of file diff --git a/focus-block/public/manifest.json b/focus-block/public/manifest.json index ef19ec2..03a2238 100644 --- a/focus-block/public/manifest.json +++ b/focus-block/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "FocusBlock", + "name": "FocusBlock", "icons": [ { "src": "favicon.ico", diff --git a/focus-block/public/styles.css b/focus-block/public/styles.css new file mode 100644 index 0000000..cf3fea7 --- /dev/null +++ b/focus-block/public/styles.css @@ -0,0 +1,1443 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +.btn { + position: relative; + top: 0; + display: inline-block; + margin: 0; + padding: 15px 15px 13px; + border: none; + border-radius: 2px; + font: inherit; + font-size: 18px; + line-height: normal; + text-align: center; + cursor: pointer; + transition: color 0.15s linear, top 0.05s linear, box-shadow 0.05s linear, background-color 0.15s linear; +} + +.btn:active { + top: 2px; +} + +@media (min-width: 1800px) { + .btn--gets-larger { + padding: 20px 20px 17px; + font-size: 24px; + } +} + +.btn::-moz-focus-inner { + border: 0; + padding: 0; +} + +.btn--primary { + background-color: #C02647; + box-shadow: 0 6px 20px 0 rgba(51, 26, 34, 0.3); + color: white; + font-weight: 500; +} + +.btn--primary:hover { + background: #d52b4f; +} + +.btn--primary:active { + box-shadow: 0 4px 12px 0 rgba(51, 26, 34, 0.35); +} + +.btn--primary.btn--dark-bg { + position: relative; + background: white; + color: #C02647; + transition: box-shadow 0.2s linear, color 0.15s linear; +} + +.btn--primary.btn--dark-bg:hover { + color: #51B6D8; + box-shadow: 0 20px 40px 0 rgba(51, 26, 34, 0.25); +} + +.btn--primary-blue { + background-color: #51B6D8; +} + +.btn--primary-blue:hover { + background: #3cadd3; +} + +.btn--secondary { + font-weight: 400; + box-shadow: inset 0 0 0 1px #CCC6C7; + background-color: transparent; + color: #B3AAAB; +} + +.btn--secondary:hover { + box-shadow: inset 0 0 0 1px #51B6D8; + color: #51B6D8; +} + +.btn--secondary.btn--dark-bg { + background-color: #A21437; + box-shadow: none; + color: rgba(255, 255, 255, 0.9); +} + +.btn--secondary.btn--dark-bg:hover { + background: #8b112f; +} + +.btn-hint { + margin-top: 12px; + font-size: 12px; + line-height: 16px; + color: #B3AAAB; +} + +.link { + text-decoration: underline; + transition: color 0.1s linear; +} + +.link:hover { + color: #51B6D8; +} + +.link--white:hover { + color: #a8dbec; +} + +.input { + position: relative; + margin-bottom: 32px; +} + +@media (min-width: 1800px) { + .input { + margin-bottom: 48px; + } +} + +.input--has-error::before { + content: ""; + position: absolute; + left: -18px; + top: 37px; + width: 8px; + height: 8px; + border-radius: 9001px; + background-color: #EC4343; +} + +@media (min-width: 1800px) { + .input--has-error::before { + left: -24px; + top: 53px; + } +} + +.input--has-units { + display: flex; + flex-wrap: wrap; +} + +.input__label { + display: block; + width: 100%; + margin-bottom: 5px; + font-size: 12px; + font-weight: 400; + color: #311C22; +} + +@media (min-width: 1800px) { + .input__label { + font-size: 16px; + margin-bottom: 13px; + } +} + +.input__sublabel { + color: #B3AAAB; +} + +.input__field { + width: 100%; + padding: 13px 12px 12px; + border: 1px solid #CCC6C7; + border-radius: 2px; + outline: none; + font-size: 14px; + font-weight: 400; + color: #311C22; + background-color: white; + box-shadow: 0 2px 6px 0 rgba(51, 26, 34, 0); + transition: box-shadow 0.2s linear, border-color 0.1s linear; +} + +@media (min-width: 1800px) { + .input__field { + font-size: 18px; + padding: 15px 14px 13px; + } +} + +.input__field[type=number]::-webkit-inner-spin-button { + -webkit-appearance: none; +} + +.input__field::-webkit-input-placeholder { + color: #B3AAAB; +} + +.input__field:-ms-input-placeholder { + color: #B3AAAB; +} + +.input__field::-ms-input-placeholder { + color: #B3AAAB; +} + +.input__field::placeholder { + color: #B3AAAB; +} + +.input--has-error .input__field { + border-color: #EC4343; +} + +.input__field:focus { + border-color: #51B6D8; + box-shadow: 0 6px 12px 0 rgba(51, 26, 34, 0.15); +} + +.input__field--small { + flex-grow: 0; +} + +.input--has-units .input__field { + width: 96px; + flex-grow: 1; +} + +.input--has-units .input__field--small { + flex-grow: 0; +} + +.input__units { + margin-top: 19px; + margin-left: 12px; + font-size: 14px; + font-weight: 400; + color: #311C22; +} + +@media (min-width: 1800px) { + .input__units { + margin-top: 21px; + margin-left: 14px; + font-size: 18px; + } +} + +.input__hint { + width: 100%; + margin-top: 4px; + font-size: 12px; + font-weight: 400; + line-height: 16px; + color: #B3AAAB; +} + +.input--has-error .input__hint { + color: #EC4343; +} + +@media (min-width: 1800px) { + .input__hint { + margin-top: 11px; + font-size: 14px; + line-height: 18px; + } +} + +.input__suggestions { + display: flex; + width: 100%; +} + +.input__suggestion { + margin: 12px 8px 0 0; + padding: 6px 12px 5px; + border: 1px solid #51B6D8; + border-radius: 9001px; + background-color: transparent; + color: #51B6D8; + font: inherit; + font-size: 12px; + font-weight: 400; + line-height: normal; + cursor: pointer; + transition: color 0.1s ease-in, background-color 0.1s ease-in; +} + +.input__suggestion::-moz-focus-inner { + border: 0; + padding: 0; +} + +.input__suggestion:hover { + background-color: #51B6D8; + color: white; +} + +.first-screen { + background: linear-gradient(75deg, #d04041 0%, #cc2048 80%); + position: relative; + display: flex; + flex-direction: column; + height: 100vh; +} + +.first-screen::before { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(300deg, #b81650 0%, rgba(184, 22, 80, 0) 25%); +} + +.first-screen::after { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(210deg, #c10e4a 0%, rgba(193, 14, 74, 0) 40%); +} + +.first-screen__logo { + text-align: center; +} + +@media (max-width: 599px) and (max-height: 599px) { + .first-screen__logo { + margin-top: 48px; + } +} + +@media (max-width: 599px) and (min-height: 600px) { + .first-screen__logo { + margin-top: 84px; + } +} + +@media (min-width: 600px) { + .first-screen__logo { + margin-top: 152px; + } +} + +@media (min-width: 900px) { + .first-screen__logo { + text-align: left; + margin-top: 100px; + padding: 0 128px; + } +} + +@media (min-width: 1200px) { + .first-screen__logo { + margin-top: 128px; + padding: 0 128px; + } +} + +@media (min-width: 1800px) { + .first-screen__logo { + margin-top: 168px; + padding: 0 160px; + } +} + +.first-screen__logo img { + display: inline-block; +} + +@media (max-width: 599px) and (max-height: 599px) { + .first-screen__logo img { + height: 48px; + } +} + +@media (max-width: 599px) and (min-height: 600px) { + .first-screen__logo img { + height: 60px; + } +} + +@media (min-width: 600px) { + .first-screen__logo img { + height: 96px; + } +} + +@media (min-width: 900px) { + .first-screen__logo img { + height: 72px; + } +} + +@media (min-width: 1200px) { + .first-screen__logo img { + height: 72px; + } +} + +@media (min-width: 1800px) { + .first-screen__logo img { + height: 104px; + } +} + +.first-screen__text { + position: relative; + z-index: 8; + margin-top: 55px; + padding: 0 32px; + font-size: 16px; + line-height: 24px; + font-weight: 500; + color: rgba(255, 255, 255, 0.9); +} + +@media (max-width: 599px) and (max-height: 599px) { + .first-screen__text { + margin-top: 32px; + } +} + +@media (max-width: 599px) and (min-height: 600px) { + .first-screen__text { + margin-top: 55px; + } +} + +@media (min-width: 600px) { + .first-screen__text { + margin-top: 141px; + padding: 0 80px; + font-size: 32px; + line-height: 48px; + } +} + +@media (min-width: 900px) { + .first-screen__text { + margin-top: 80px; + padding: 0 128px; + } +} + +@media (min-width: 1200px) { + .first-screen__text { + max-width: 1000px; + margin-top: 128px; + padding: 0 128px; + font-size: 32px; + line-height: 48px; + } +} + +@media (min-width: 1800px) { + .first-screen__text { + max-width: 1200px; + margin-top: 160px; + padding: 0 160px; + font-size: 48px; + line-height: 64px; + } +} + +.first-screen__actions-container { + position: relative; + z-index: 8; + margin-top: auto; + -webkit-filter: drop-shadow(0 -12px 64px rgba(51, 26, 34, 0.4)); + filter: drop-shadow(0 -12px 64px rgba(51, 26, 34, 0.4)); +} + +@media (min-width: 1200px) { + .first-screen__actions-container { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + -webkit-filter: none; + filter: none; + } +} + +.first-screen__actions { + position: relative; + background: linear-gradient(60deg, rgba(221, 57, 64, 0.7) 0%, rgba(209, 38, 75, 0.7) 50%, rgba(201, 25, 82, 0.7) 100%); +} + +@media (max-width: 599px) and (max-height: 599px) { + .first-screen__actions { + padding: 80px 32px 16px; + -webkit-clip-path: polygon(0 60px, 100% 0, 100% 100%, 0% 100%); + clip-path: polygon(0 60px, 100% 0, 100% 100%, 0% 100%); + } +} + +@media (max-width: 599px) and (min-height: 600px) { + .first-screen__actions { + padding: 128px 32px 32px; + -webkit-clip-path: polygon(0 80px, 100% 0, 100% 100%, 0% 100%); + clip-path: polygon(0 80px, 100% 0, 100% 100%, 0% 100%); + } +} + +@media (min-width: 600px) { + .first-screen__actions { + display: flex; + justify-content: center; + padding: 220px 80px 120px; + -webkit-clip-path: polygon(0 140px, 100% 0, 100% 100%, 0% 100%); + clip-path: polygon(0 140px, 100% 0, 100% 100%, 0% 100%); + } +} + +@media (min-width: 900px) { + .first-screen__actions { + padding: 120px 128px 60px; + -webkit-clip-path: polygon(0 80px, 100% 0, 100% 100%, 0% 100%); + clip-path: polygon(0 80px, 100% 0, 100% 100%, 0% 100%); + } +} + +@media (min-width: 1200px) { + .first-screen__actions { + justify-content: start; + padding: 0 128px; + -webkit-clip-path: none; + clip-path: none; + background: none; + } +} + +@media (min-width: 1800px) { + .first-screen__actions { + padding: 0 160px; + } +} + +.first-screen__actions .btn { + width: 100%; +} + +@media (max-width: 599px) and (max-height: 599px) { + .first-screen__actions .btn { + margin-bottom: 20px; + } +} + +@media (max-width: 599px) and (min-height: 600px) { + .first-screen__actions .btn { + margin-bottom: 32px; + } +} + +@media (min-width: 600px) { + .first-screen__actions .btn { + display: inline-block; + flex-basis: 280px; + margin: 0 24px; + } +} + +@media (min-width: 1200px) { + .first-screen__actions .btn { + margin: 0 48px 0 0; + } +} + +@media (min-width: 1800px) { + .first-screen__actions .btn { + flex-basis: 320px; + margin: 0 64px 0 0; + } +} + +.first-screen__triangles { + display: none; + position: absolute; + z-index: 1; + top: 0; + right: 0; + bottom: 0; + width: 100%; + height: 100%; +} + +@media (min-width: 1200px) { + .first-screen__triangles { + display: block; + } +} + +.first-screen__triangle1 { + position: absolute; + top: 0; + right: 0; + width: 30%; + height: 100%; + -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%); + clip-path: polygon(0% 0%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.07; +} + +.first-screen__triangle2 { + position: absolute; + bottom: 0; + right: 0; + width: 50%; + height: 90%; + -webkit-clip-path: polygon(0% 100%, 100% 0%, 100% 100%); + clip-path: polygon(0% 100%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.07; +} + +.first-screen__triangle3 { + position: absolute; + bottom: 0; + right: 0; + width: 17%; + height: 70%; + -webkit-clip-path: polygon(0% 100%, 100% 0%, 100% 100%); + clip-path: polygon(0% 100%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.07; +} + +.info { + margin-top: 60px; +} + +@media (min-width: 600px) { + .info { + margin-top: 90px; + } +} + +.info__header { + padding: 0 32px; + font-size: 32px; + color: #311C22; + font-weight: 500; +} + +@media (min-width: 600px) { + .info__header { + text-align: center; + font-size: 48px; + } +} + +.info__box { + margin-top: 25px; +} + +@media (min-width: 600px) { + .info__box { + display: flex; + align-items: center; + height: 240px; + margin-top: 58px; + background-color: white; + box-shadow: 0 16px 32px 0 rgba(51, 26, 34, 0.1); + } +} + +.info__image { + position: relative; + width: 100%; + height: 0; + padding-top: calc(152 / 320 * 100%); + background: linear-gradient(75deg, #d04041 0%, #cc2048 80%); + overflow: hidden; +} + +.info__image::before { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(300deg, #b81650 0%, rgba(184, 22, 80, 0) 25%); +} + +.info__image::after { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(210deg, #c10e4a 0%, rgba(193, 14, 74, 0) 40%); +} + +@media (min-width: 600px) { + .info__image { + flex-shrink: 0; + width: 372px; + height: 100%; + padding-top: 0; + } + .info__image--right { + order: 1; + margin-left: auto; + } +} + +.info__image img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + -webkit-filter: drop-shadow(12px 0 48px rgba(0, 0, 0, 0.15)); + filter: drop-shadow(12px 0 48px rgba(0, 0, 0, 0.15)); + opacity: 0.95; +} + +.info__image-triangle1 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%); + clip-path: polygon(0% 0%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.5; +} + +.info__image--right .info__image-triangle1 { + left: 0; + right: auto; + -webkit-clip-path: polygon(0% 0%, 100% 0%, 50px 100%, 0 100%); + clip-path: polygon(0% 0%, 100% 0%, 50px 100%, 0 100%); +} + +@media (min-width: 600px) { + .info__image-triangle1 { + display: block; + } +} + +.info__image-triangle2 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + -webkit-clip-path: polygon(36px 0%, 100% 0%, 100% 100%, 0% 100%); + clip-path: polygon(36px 0%, 100% 0%, 100% 100%, 0% 100%); + background-color: white; + opacity: 0.5; +} + +.info__image--right .info__image-triangle2 { + left: 0; + right: auto; + -webkit-clip-path: polygon(0% 0%, 130px 0%, 66px 100%, 0% 100%); + clip-path: polygon(0% 0%, 130px 0%, 66px 100%, 0% 100%); +} + +@media (min-width: 600px) { + .info__image-triangle2 { + display: block; + } +} + +.info__image-triangle3 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + -webkit-clip-path: polygon(112px 0%, 100% 0%, 100% 100%, 48px 100%); + clip-path: polygon(112px 0%, 100% 0%, 100% 100%, 48px 100%); + background-color: white; + opacity: 0.5; +} + +.info__image--right .info__image-triangle3 { + left: 0; + right: auto; + -webkit-clip-path: polygon(0% 0%, 110px 0%, 140px 100%, 0% 100%); + clip-path: polygon(0% 0%, 110px 0%, 140px 100%, 0% 100%); +} + +@media (min-width: 600px) { + .info__image-triangle3 { + display: block; + } +} + +.info__image-triangle4 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + -webkit-clip-path: polygon(100% 0%, 100% 100%, 0% 100%); + clip-path: polygon(100% 0%, 100% 100%, 0% 100%); + background-color: white; + opacity: 1; +} + +.info__image--right .info__image-triangle4 { + left: 0; + right: auto; + -webkit-clip-path: polygon(0% 0%, 140px 100%, 0% 100%); + clip-path: polygon(0% 0%, 140px 100%, 0% 100%); +} + +@media (min-width: 600px) { + .info__image-triangle4 { + display: block; + } +} + +.info__text { + margin-top: 23px; + padding: 0 32px; + font-size: 16px; + line-height: 24px; + font-weight: 400; + color: #311C22; +} + +.info__text p { + margin-bottom: 12px; +} + +.info__text p:last-child { + margin-bottom: 0; +} + +@media (min-width: 600px) { + .info__text { + margin-top: 0; + } + .info__text--left { + margin-left: 32px; + } + .info__text p { + margin-bottom: 16px; + } +} + +@media (min-width: 1200px) { + .info__text { + font-size: 20px; + line-height: 32px; + } + .info__text--left { + margin-left: 80px; + } +} + +.landing-cta { + margin-top: 60px; + padding: 0 32px; +} + +.landing-cta .btn { + width: 100%; +} + +@media (min-width: 600px) { + .landing-cta { + margin-top: 92px; + padding: 0; + text-align: center; + } + .landing-cta .btn { + width: 280px; + } +} + +@media (min-width: 1800px) { + .landing-cta .btn { + width: 320px; + } +} + +.footer { + margin-top: 80px; + padding: 48px 24px; + background: linear-gradient(75deg, #d04041 0%, #cc2048 80%); +} + +.footer::before { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(300deg, #b81650 0%, rgba(184, 22, 80, 0) 25%); +} + +.footer::after { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(210deg, #c10e4a 0%, rgba(193, 14, 74, 0) 40%); +} + +@media (min-width: 600px) { + .footer { + margin-top: 96px; + padding: 60px 80px; + } +} + +@media (min-width: 900px) { + .footer { + display: flex; + justify-content: center; + padding: 80px; + } +} + +.footer-section { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + margin-bottom: 40px; +} + +.footer-section:last-child { + margin-bottom: 0; +} + +@media (min-width: 600px) { + .footer-section { + flex-direction: row; + align-items: flex-start; + } +} + +@media (min-width: 900px) { + .footer-section { + flex-basis: 320px; + margin: 0 40px; + } +} + +@media (min-width: 1200px) { + .footer-section { + flex-basis: 400px; + margin: 0 80px; + } +} + +.footer-section__icon { + margin-bottom: 15px; +} + +.footer-section__icon img { + height: 32px; + opacity: 0.9; +} + +@media (min-width: 600px) { + .footer-section__icon { + margin-right: 24px; + margin-top: 6px; + margin-bottom: 0; + } +} + +.footer-section__text { + color: white; + opacity: 0.9; + font-size: 16px; + line-height: 24px; + font-weight: 400; +} + +.footer-section__text p { + text-align: center; + margin-bottom: 8px; +} + +.footer-section__text p:last-child { + margin-bottom: 0; +} + +@media (min-width: 600px) { + .footer-section__text p { + text-align: left; + } +} + +@media (min-width: 1200px) { + .footer-section__text { + font-size: 20px; + } + .footer-section__text p { + margin-bottom: 10px; + } +} + +.app-wrapper { + width: 100%; + padding: 40px 32px 48px; +} + +@media (min-width: 600px) { + .app-wrapper { + padding: 64px 48px 80px; + } +} + +@media (min-width: 1800px) { + .app-wrapper { + padding: 112px; + } +} + +.app-wrapper--times-up::before { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + box-shadow: inset 0 0 0 6px #C02647; +} + +.app-wrapper--popup { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.app-wrapper--finished { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.app-header { + display: flex; + align-items: center; + margin-bottom: 36px; +} + +@media (min-width: 600px) { + .app-header { + margin-bottom: 48px; + } +} + +@media (min-width: 1800px) { + .app-header { + margin-bottom: 64px; + } +} + +.app-header__logo { + width: 40px; +} + +@media (min-width: 600px) { + .app-header__logo { + width: 64px; + } +} + +@media (min-width: 1800px) { + .app-header__logo { + width: 80px; + } +} + +.app-header__title { + margin-left: 30px; + margin-bottom: 3px; + font-size: 20px; + font-weight: 500; + color: #311C22; +} + +@media (min-width: 600px) { + .app-header__title { + margin-left: -64px; + margin-bottom: 2px; + flex-grow: 1; + text-align: center; + font-size: 24px; + } +} + +@media (min-width: 1800px) { + .app-header__title { + margin-left: -80px; + font-size: 32px; + margin-bottom: 1px; + } +} + +.app-wrapper--finished .app-form { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; +} + +.app-wrapper--popup .app-form { + margin-top: auto; +} + +@media (min-width: 900px) { + .app-wrapper--popup .app-form { + margin-top: 64px; + } +} + +@media (min-width: 600px) { + .app-form { + max-width: 480px; + margin-left: auto; + margin-right: auto; + padding-bottom: 100px; + } +} + +.app-form__header { + margin-bottom: 35px; + text-align: center; + font-size: 20px; + font-weight: 500; + color: #311C22; +} + +@media (min-width: 600px) { + .app-form__header { + margin-bottom: 64px; + font-size: 24px; + } +} + +@media (min-width: 1800px) { + .app-form__header { + margin-bottom: 80px; + font-size: 32px; + } +} + +.app-form__message { + margin-bottom: 48px; + text-align: center; + font-size: 16px; + line-height: 24px; + color: #311C22; +} + +@media (min-width: 600px) { + .app-form__message { + margin-bottom: 64px; + font-size: 18px; + line-height: 32px; + } +} + +@media (min-width: 1800px) { + .app-form__message { + margin-bottom: 80px; + } +} + +.app-form__actions .btn { + width: 100%; + margin-bottom: 24px; +} + +.app-form__actions .btn:last-child { + margin-bottom: 0; +} + +.app-wrapper--finished .app-form__actions .btn { + margin-top: 80px; +} + +@media (min-width: 600px) { + .app-wrapper--finished .app-form__actions .btn { + margin-top: 0; + } +} + +@media (min-width: 600px) { + .app-form__actions { + display: flex; + justify-content: center; + } + .app-form__actions .btn { + width: 220px; + margin-bottom: 0; + flex-grow: 1; + } + .app-form__actions .btn:first-child { + margin-left: 24px; + order: 1; + } + .app-form__actions .btn:last-child { + margin-right: 24px; + } + .app-form__actions .btn:only-child { + margin-left: 0; + margin-right: 0; + flex-grow: 0; + } +} + +.app-focusing { + margin-top: 52px; +} + +@media (min-width: 600px) { + .app-focusing { + max-width: 480px; + margin-left: auto; + margin-right: auto; + padding-bottom: 100px; + } +} + +.app-focusing-field { + margin-bottom: 26px; +} + +@media (min-width: 1800px) { + .app-focusing-field { + margin-bottom: 48px; + } +} + +.app-focusing-field--time { + text-align: center; + margin-bottom: 53px; +} + +@media (min-width: 1800px) { + .app-focusing-field--time { + margin-bottom: 64px; + } +} + +.app-focusing-field__label { + margin-bottom: 9px; + font-size: 12px; + color: #B3AAAB; +} + +@media (min-width: 1800px) { + .app-focusing-field__label { + margin-bottom: 11px; + font-size: 16px; + } +} + +.app-focusing-field__value { + font-size: 14px; + color: #311C22; +} + +@media (min-width: 1800px) { + .app-focusing-field__value { + font-size: 16px; + } +} + +.app-focusing-field--time .app-focusing-field__value { + font-size: 40px; + color: #C02647; +} + +@media (min-width: 1800px) { + .app-focusing-field--time .app-focusing-field__value { + font-size: 48px; + } +} + +.app-focusing-field--blue .app-focusing-field__value { + color: #51B6D8; +} + +.app-focusing-field__edit { + margin-top: 10px; + font-size: 12px; + color: #B3AAAB; + text-decoration: underline; + cursor: pointer; +} + +.app-focusing-field__edit:hover { + color: #51B6D8; +} + +.app-focusing__actions { + margin-top: 53px; +} + +.app-focusing__actions .btn { + display: block; + width: 100%; + margin-bottom: 24px; +} + +.app-focusing__actions .btn:last-child { + margin-bottom: 0; +} + +.app-focusing__actions .btn--with-hint { + margin-bottom: 0; +} + +.app-focusing__actions .btn-hint { + margin-bottom: 24px; +} + +@media (min-width: 600px) { + .app-focusing__actions { + margin-top: 80px; + display: flex; + flex-wrap: wrap; + justify-content: center; + } + .app-focusing__actions .btn { + width: 160px; + margin-bottom: 0; + flex-grow: 1; + } + .app-focusing__actions .btn:first-child { + margin-left: 24px; + order: 1; + } + .app-focusing__actions .btn:last-child { + margin-right: 24px; + } + .app-focusing__actions .btn-hint { + order: 2; + width: 50%; + margin-left: 50%; + padding-left: 24px; + } +} + +html { + height: 100%; + box-sizing: border-box; + font-family: "Archivo", sans-serif; + text-rendering: optimizeLegibility; +} + +body { + position: relative; + height: 100%; + min-height: 100%; + background-color: #FCFAFA; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +a { + color: inherit; + text-decoration: inherit; + cursor: pointer; +} diff --git a/focus-block/scss/base/_breakpoints.scss b/focus-block/scss/base/_breakpoints.scss new file mode 100644 index 0000000..e55ac30 --- /dev/null +++ b/focus-block/scss/base/_breakpoints.scss @@ -0,0 +1,23 @@ +@mixin for-short-phones-only { + @media (max-width: 599px) and (max-height: 599px) { @content; } +} + +@mixin for-tall-phones-up { + @media (max-width: 599px) and (min-height: 600px) { @content; } +} + +@mixin for-tablet-portrait-up { + @media (min-width: 600px) { @content; } +} + +@mixin for-tablet-landscape-up { + @media (min-width: 900px) { @content; } +} + +@mixin for-desktop-up { + @media (min-width: 1200px) { @content; } +} + +@mixin for-big-desktop-up { + @media (min-width: 1800px) { @content; } +} \ No newline at end of file diff --git a/focus-block/scss/base/_colors.scss b/focus-block/scss/base/_colors.scss new file mode 100644 index 0000000..b35da4f --- /dev/null +++ b/focus-block/scss/base/_colors.scss @@ -0,0 +1,44 @@ +$brand-red: #C02647; +$dark-red: #A21437; +$pink: #F02355; +$shadow-red: #331A22; +$gray: #CCC6C7; + +$blue: #51B6D8; +$error-red: #EC4343; + +$background-white: #FCFAFA; +$text-black: #311C22; +$text-gray: #B3AAAB; + +@mixin red-gradient() { + background: linear-gradient(120deg, #B9143B 0%, #C51C3B 50%, #B61748 100%) +} + +@mixin multicolor-gradient() { + background: linear-gradient(75deg, rgba(208,64,65, 1) 0%, rgba(204,32,72, 1) 80%); + + &::before { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(300deg, rgba(184,22,80, 1) 0%, rgba(184,22,80, 0) 25%); + } + + &::after { + content: ""; + display: block; + position: absolute; + z-index: -1; + width: 100%; + height: 100%; + top: 0; + right: 0; + background: linear-gradient(210deg, rgba(193,14,74, 1) 0%, rgba(193,14,74, 0) 40%); + } +} \ No newline at end of file diff --git a/focus-block/scss/base/_module.scss b/focus-block/scss/base/_module.scss new file mode 100644 index 0000000..f012aaf --- /dev/null +++ b/focus-block/scss/base/_module.scss @@ -0,0 +1,4 @@ +@import "reset"; +@import "breakpoints"; +@import "colors"; +@import "typography"; \ No newline at end of file diff --git a/focus-block/scss/base/_reset.scss b/focus-block/scss/base/_reset.scss new file mode 100644 index 0000000..754079d --- /dev/null +++ b/focus-block/scss/base/_reset.scss @@ -0,0 +1,49 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/focus-block/scss/base/_typography.scss b/focus-block/scss/base/_typography.scss new file mode 100644 index 0000000..9fa7dad --- /dev/null +++ b/focus-block/scss/base/_typography.scss @@ -0,0 +1,4 @@ +$regular-weight: 400; +$medium-weight: 500; + +$font-family: "Archivo", sans-serif; \ No newline at end of file diff --git a/focus-block/scss/components/_buttons.scss b/focus-block/scss/components/_buttons.scss new file mode 100644 index 0000000..69bc456 --- /dev/null +++ b/focus-block/scss/components/_buttons.scss @@ -0,0 +1,95 @@ +.btn { + position: relative; + top: 0; + display: inline-block; + margin: 0; + padding: 15px 15px 13px; + border: none; + border-radius: 2px; + font: inherit; + font-size: 18px; + line-height: normal; + text-align: center; + cursor: pointer; + transition: color 0.15s linear, top 0.05s linear, box-shadow 0.05s linear, background-color 0.15s linear; + + &:active { + top: 2px; + } + + &--gets-larger { + @include for-big-desktop-up { + padding: 20px 20px 17px; + font-size: 24px; + } + } + + &::-moz-focus-inner { + border: 0; + padding: 0; + } + + &--primary { + background-color: $brand-red; + box-shadow: 0 6px 20px 0 rgba($shadow-red, 0.3); + color: white; + font-weight: $medium-weight; + + &:hover { + background: lighten($brand-red, 5%); + } + + &:active { + box-shadow: 0 4px 12px 0 rgba($shadow-red, 0.35); + } + + &.btn--dark-bg { + position: relative; + background: white; + color: $brand-red; + transition: box-shadow 0.2s linear, color 0.15s linear; + + &:hover { + color: $blue; + box-shadow: 0 20px 40px 0 rgba($shadow-red, 0.25); + } + } + } + + &--primary-blue { + background-color: $blue; + + &:hover { + background: darken($blue, 5%); + } + } + + &--secondary { + font-weight: $regular-weight; + box-shadow: inset 0 0 0 1px $gray; + background-color: transparent; + color: $text-gray; + + &:hover { + box-shadow: inset 0 0 0 1px $blue; + color: $blue; + } + + &.btn--dark-bg { + background-color: $dark-red; + box-shadow: none; + color: rgba(white, 0.9); + + &:hover { + background: darken($dark-red, 5%); + } + } + } +} + +.btn-hint { + margin-top: 12px; + font-size: 12px; + line-height: 16px; + color: $text-gray; +} \ No newline at end of file diff --git a/focus-block/scss/components/_inputs.scss b/focus-block/scss/components/_inputs.scss new file mode 100644 index 0000000..3cf098f --- /dev/null +++ b/focus-block/scss/components/_inputs.scss @@ -0,0 +1,165 @@ +.input { + position: relative; + margin-bottom: 32px; + + @include for-big-desktop-up { + margin-bottom: 48px; + } + + &--has-error { + + &::before { + content: ""; + position: absolute; + left: -18px; + top: 37px; + width: 8px; + height: 8px; + border-radius: 9001px; + background-color: $error-red; + + @include for-big-desktop-up { + left: -24px; + top: 53px; + } + } + } + + &--has-units { + display: flex; + flex-wrap: wrap; + } + +} + +.input__label { + display: block; + width: 100%; + margin-bottom: 5px; + font-size: 12px; + font-weight: $regular-weight; + color: $text-black; + + @include for-big-desktop-up { + font-size: 16px; + margin-bottom: 13px; + } + +} + +.input__sublabel { + color: $text-gray; +} + +.input__field { + width: 100%; + padding: 13px 12px 12px; + border: 1px solid $gray; + border-radius: 2px; + outline: none; + font-size: 14px; + font-weight: $regular-weight; + color: $text-black; + background-color: white; + box-shadow: 0 2px 6px 0 rgba($shadow-red, 0); + transition: box-shadow 0.2s linear, border-color 0.1s linear; + + @include for-big-desktop-up { + font-size: 18px; + padding: 15px 14px 13px; + } + + &[type=number]::-webkit-inner-spin-button { + -webkit-appearance: none; + } + + &::placeholder { + color: $text-gray; + } + + .input--has-error & { + border-color: $error-red; + } + + &:focus { + border-color: $blue; + box-shadow: 0 6px 12px 0 rgba($shadow-red, 0.15); + } + + &--small { + flex-grow: 0; + } + + .input--has-units & { + width: 96px; + flex-grow: 1; + + &--small { + flex-grow: 0; + } + } + +} + +.input__units { + margin-top: 19px; + margin-left: 12px; + font-size: 14px; + font-weight: $regular-weight; + color: $text-black; + + @include for-big-desktop-up { + margin-top: 21px; + margin-left: 14px; + font-size: 18px; + } +} + +.input__hint { + width: 100%; + margin-top: 4px; + font-size: 12px; + font-weight: $regular-weight; + line-height: 16px; + color: $text-gray; + + .input--has-error & { + color: $error-red; + } + + @include for-big-desktop-up { + margin-top: 11px; + font-size: 14px; + line-height: 18px; + } +} + +.input__suggestions { + display: flex; + width: 100%; +} + +.input__suggestion { + margin: 12px 8px 0 0; + padding: 6px 12px 5px; + border: 1px solid $blue; + border-radius: 9001px; + background-color: transparent; + color: $blue; + font: inherit; + font-size: 12px; + font-weight: $regular-weight; + line-height: normal; + cursor: pointer; + transition: color 0.1s ease-in, background-color 0.1s ease-in; + + &::-moz-focus-inner { + border: 0; + padding: 0; + } + + &:hover { + background-color: $blue; + color: white; + } +} \ No newline at end of file diff --git a/focus-block/scss/components/_links.scss b/focus-block/scss/components/_links.scss new file mode 100644 index 0000000..7c10f35 --- /dev/null +++ b/focus-block/scss/components/_links.scss @@ -0,0 +1,14 @@ +.link { + text-decoration: underline; + transition: color 0.1s linear; + + &:hover { + color: $blue; + } + + &--white { + &:hover { + color: mix(white, $blue, 50%); + } + } +} \ No newline at end of file diff --git a/focus-block/scss/components/_module.scss b/focus-block/scss/components/_module.scss new file mode 100644 index 0000000..6a1eeff --- /dev/null +++ b/focus-block/scss/components/_module.scss @@ -0,0 +1,3 @@ +@import "buttons"; +@import "links"; +@import "inputs"; \ No newline at end of file diff --git a/focus-block/scss/layout/_app-base.scss b/focus-block/scss/layout/_app-base.scss new file mode 100644 index 0000000..82aa48a --- /dev/null +++ b/focus-block/scss/layout/_app-base.scss @@ -0,0 +1,87 @@ +.app-wrapper { + width: 100%; + padding: 40px 32px 48px; + + @include for-tablet-portrait-up { + padding: 64px 48px 80px; + } + + @include for-big-desktop-up { + padding: 112px; + } + + &--times-up { + + &::before { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + box-shadow: inset 0 0 0 6px $brand-red; + } + + } + + &--popup { + display: flex; + flex-direction: column; + min-height: 100vh; + } + + &--finished { + display: flex; + flex-direction: column; + min-height: 100vh; + } +} + +.app-header { + display: flex; + align-items: center; + margin-bottom: 36px; + + @include for-tablet-portrait-up { + margin-bottom: 48px; + } + + @include for-big-desktop-up { + margin-bottom: 64px; + } +} + +.app-header__logo { + width: 40px; + + @include for-tablet-portrait-up { + width: 64px; + } + + @include for-big-desktop-up { + width: 80px; + } +} + +.app-header__title { + margin-left: 30px; + margin-bottom: 3px; + font-size: 20px; + font-weight: $medium-weight; + color: $text-black; + + @include for-tablet-portrait-up { + margin-left: -64px; + margin-bottom: 2px; + flex-grow: 1; + text-align: center; + font-size: 24px; + } + + @include for-big-desktop-up { + margin-left: -80px; + font-size: 32px; + margin-bottom: 1px; + } +} \ No newline at end of file diff --git a/focus-block/scss/layout/_app-focusing.scss b/focus-block/scss/layout/_app-focusing.scss new file mode 100644 index 0000000..ce632bc --- /dev/null +++ b/focus-block/scss/layout/_app-focusing.scss @@ -0,0 +1,123 @@ +.app-focusing { + margin-top: 52px; + + @include for-tablet-portrait-up { + max-width: 480px; + margin-left: auto; + margin-right: auto; + padding-bottom: 100px; + } +} + +.app-focusing-field { + margin-bottom: 26px; + + @include for-big-desktop-up { + margin-bottom: 48px; + } + + &--time { + text-align: center; + margin-bottom: 53px; + + @include for-big-desktop-up { + margin-bottom: 64px; + } + } +} + +.app-focusing-field__label { + margin-bottom: 9px; + font-size: 12px; + color: $text-gray; + + @include for-big-desktop-up { + margin-bottom: 11px; + font-size: 16px; + } +} + +.app-focusing-field__value { + font-size: 14px; + color: $text-black; + + @include for-big-desktop-up { + font-size: 16px; + } + + .app-focusing-field--time & { + font-size: 40px; + color: $brand-red; + + @include for-big-desktop-up { + font-size: 48px; + } + } + + .app-focusing-field--blue & { + color: $blue; + } +} + +.app-focusing-field__edit { + margin-top: 10px; + font-size: 12px; + color: $text-gray; + text-decoration: underline; + cursor: pointer; + + &:hover { + color: $blue; + } +} + +.app-focusing__actions { + margin-top: 53px; + + .btn { + display: block; + width: 100%; + margin-bottom: 24px; + + &:last-child { + margin-bottom: 0; + } + + &--with-hint { + margin-bottom: 0; + } + } + + .btn-hint { + margin-bottom: 24px; + } + + @include for-tablet-portrait-up { + margin-top: 80px; + display: flex; + flex-wrap: wrap; + justify-content: center; + + .btn { + width: 160px; + margin-bottom: 0; + flex-grow: 1; + + &:first-child { + margin-left: 24px; + order: 1; + } + + &:last-child { + margin-right: 24px; + } + } + + .btn-hint { + order: 2; + width: 50%; + margin-left: 50%; + padding-left: 24px; + } + } +} diff --git a/focus-block/scss/layout/_app-form.scss b/focus-block/scss/layout/_app-form.scss new file mode 100644 index 0000000..2eaf419 --- /dev/null +++ b/focus-block/scss/layout/_app-form.scss @@ -0,0 +1,109 @@ +.app-form { + + .app-wrapper--finished & { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + } + + .app-wrapper--popup & { + margin-top: auto; + + @include for-tablet-landscape-up { + margin-top: 64px; + } + } + + @include for-tablet-portrait-up { + max-width: 480px; + margin-left: auto; + margin-right: auto; + padding-bottom: 100px; + } +} + +.app-form__header { + margin-bottom: 35px; + text-align: center; + font-size: 20px; + font-weight: $medium-weight; + color: $text-black; + + @include for-tablet-portrait-up { + margin-bottom: 64px; + font-size: 24px; + } + + @include for-big-desktop-up { + margin-bottom: 80px; + font-size: 32px; + } +} + +.app-form__message { + margin-bottom: 48px; + text-align: center; + font-size: 16px; + line-height: 24px; + color: $text-black; + + + @include for-tablet-portrait-up { + margin-bottom: 64px; + font-size: 18px; + line-height: 32px; + } + + @include for-big-desktop-up { + margin-bottom: 80px; + } +} + +.app-form__actions { + .btn { + width: 100%; + margin-bottom: 24px; + + &:last-child { + margin-bottom: 0; + } + } + + .app-wrapper--finished & { + .btn { + margin-top: 80px; + + @include for-tablet-portrait-up { + margin-top: 0; + } + } + } + + @include for-tablet-portrait-up { + display: flex; + justify-content: center; + + .btn { + width: 220px; + margin-bottom: 0; + flex-grow: 1; + + &:first-child { + margin-left: 24px; + order: 1; + } + + &:last-child { + margin-right: 24px; + } + + &:only-child { + margin-left: 0; + margin-right: 0; + flex-grow: 0; + } + } + } + +} \ No newline at end of file diff --git a/focus-block/scss/layout/_landing-cta.scss b/focus-block/scss/layout/_landing-cta.scss new file mode 100644 index 0000000..6c59575 --- /dev/null +++ b/focus-block/scss/layout/_landing-cta.scss @@ -0,0 +1,24 @@ +.landing-cta { + margin-top: 60px; + padding: 0 32px; + + .btn { + width: 100%; + } + + @include for-tablet-portrait-up { + margin-top: 92px; + padding: 0; + text-align: center; + + .btn { + width: 280px; + } + } + + @include for-big-desktop-up { + .btn { + width: 320px; + } + } +} \ No newline at end of file diff --git a/focus-block/scss/layout/_landing-first-screen.scss b/focus-block/scss/layout/_landing-first-screen.scss new file mode 100644 index 0000000..16cc006 --- /dev/null +++ b/focus-block/scss/layout/_landing-first-screen.scss @@ -0,0 +1,246 @@ +.first-screen { + @include multicolor-gradient(); + + position: relative; + display: flex; + flex-direction: column; + height: 100vh; +} + +.first-screen__logo { + text-align: center; + + @include for-short-phones-only { + margin-top: 48px; + } + + @include for-tall-phones-up { + margin-top: 84px; + } + + @include for-tablet-portrait-up { + margin-top: 152px; + } + + @include for-tablet-landscape-up { + text-align: left; + margin-top: 100px; + padding: 0 128px; + } + + @include for-desktop-up { + margin-top: 128px; + padding: 0 128px; + } + + @include for-big-desktop-up { + margin-top: 168px; + padding: 0 160px; + } + + img { + display: inline-block; + + @include for-short-phones-only { + height: 48px; + } + + @include for-tall-phones-up { + height: 60px; + } + + @include for-tablet-portrait-up { + height: 96px; + } + + @include for-tablet-landscape-up { + height: 72px; + } + + @include for-desktop-up { + height: 72px; + } + + @include for-big-desktop-up { + height: 104px; + } + } +} + +.first-screen__text { + position: relative; + z-index: 8; + margin-top: 55px; + padding: 0 32px; + font-size: 16px; + line-height: 24px; + font-weight: $medium-weight; + color: rgba(white, 0.9); + + @include for-short-phones-only { + margin-top: 32px; + } + + @include for-tall-phones-up { + margin-top: 55px; + } + + @include for-tablet-portrait-up { + margin-top: 141px; + padding: 0 80px; + font-size: 32px; + line-height: 48px; + } + + @include for-tablet-landscape-up { + margin-top: 80px; + padding: 0 128px; + } + + @include for-desktop-up { + max-width: 1000px; + margin-top: 128px; + padding: 0 128px; + font-size: 32px; + line-height: 48px; + } + + @include for-big-desktop-up { + max-width: 1200px; + margin-top: 160px; + padding: 0 160px; + font-size: 48px; + line-height: 64px; + } +} + +.first-screen__actions-container { + position: relative; + z-index: 8; + margin-top: auto; + filter: drop-shadow(0 -12px 64px rgba($shadow-red, 0.4)); + + @include for-desktop-up { + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: center; + filter: none; + } +} + +.first-screen__actions { + position: relative; + background: linear-gradient(60deg, rgba(#DD3940, 0.7) 0%, rgba(#D1264B, 0.7) 50%, rgba(#C91952, 0.7) 100%); + + @include for-short-phones-only { + padding: 80px 32px 16px; + clip-path: polygon(0 60px, 100% 0, 100% 100%, 0% 100%); + } + + @include for-tall-phones-up { + padding: 128px 32px 32px; + clip-path: polygon(0 80px, 100% 0, 100% 100%, 0% 100%); + } + + @include for-tablet-portrait-up { + display: flex; + justify-content: center; + padding: 220px 80px 120px; + clip-path: polygon(0 140px, 100% 0, 100% 100%, 0% 100%); + } + + @include for-tablet-landscape-up { + padding: 120px 128px 60px; + clip-path: polygon(0 80px, 100% 0, 100% 100%, 0% 100%); + } + + @include for-desktop-up { + justify-content: start; + padding: 0 128px; + clip-path: none; + background: none; + } + + @include for-big-desktop-up { + padding: 0 160px; + } + + .btn { + width: 100%; + + @include for-short-phones-only { + margin-bottom: 20px; + } + + @include for-tall-phones-up { + margin-bottom: 32px; + } + + @include for-tablet-portrait-up { + display: inline-block; + flex-basis: 280px; + margin: 0 24px; + } + + @include for-desktop-up { + margin: 0 48px 0 0; + } + + @include for-big-desktop-up { + flex-basis: 320px; + margin: 0 64px 0 0; + } + + } + +} + +.first-screen__triangles { + display: none; + + @include for-desktop-up { + display: block; + } + + position: absolute; + z-index: 1; + top: 0; + right: 0; + bottom: 0; + width: 100%; + height: 100%; +} + +.first-screen__triangle1 { + position: absolute; + top: 0; + right: 0; + width: 30%; + height: 100%; + clip-path: polygon(0% 0%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.07; +} + +.first-screen__triangle2 { + position: absolute; + bottom: 0; + right: 0; + width: 50%; + height: 90%; + clip-path: polygon(0% 100%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.07; +} + +.first-screen__triangle3 { + position: absolute; + bottom: 0; + right: 0; + width: 17%; + height: 70%; + clip-path: polygon(0% 100%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.07; +} \ No newline at end of file diff --git a/focus-block/scss/layout/_landing-footer.scss b/focus-block/scss/layout/_landing-footer.scss new file mode 100644 index 0000000..8dc99bf --- /dev/null +++ b/focus-block/scss/layout/_landing-footer.scss @@ -0,0 +1,91 @@ +.footer { + margin-top: 80px; + padding: 48px 24px; + @include multicolor-gradient(); + + @include for-tablet-portrait-up { + margin-top: 96px; + padding: 60px 80px; + } + + @include for-tablet-landscape-up { + display: flex; + justify-content: center; + padding: 80px; + } + +} + +.footer-section { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + margin-bottom: 40px; + + &:last-child { + margin-bottom: 0; + } + + @include for-tablet-portrait-up { + flex-direction: row; + align-items: flex-start; + } + + @include for-tablet-landscape-up { + flex-basis: 320px; + margin: 0 40px; + } + + @include for-desktop-up { + flex-basis: 400px; + margin: 0 80px; + } +} + +.footer-section__icon { + margin-bottom: 15px; + + img { + height: 32px; + opacity: 0.9; + } + + @include for-tablet-portrait-up { + margin-right: 24px; + margin-top: 6px; + margin-bottom: 0; + } +} + +.footer-section__text { + color: white; + opacity: 0.9; + font-size: 16px; + line-height: 24px; + font-weight: $regular-weight; + + + p { + text-align: center; + margin-bottom: 8px; + + &:last-child { + margin-bottom: 0; + } + } + + @include for-tablet-portrait-up { + p { + text-align: left; + } + } + + @include for-desktop-up { + font-size: 20px; + + p { + margin-bottom: 10px; + } + } +} \ No newline at end of file diff --git a/focus-block/scss/layout/_landing-info.scss b/focus-block/scss/layout/_landing-info.scss new file mode 100644 index 0000000..8a22ab6 --- /dev/null +++ b/focus-block/scss/layout/_landing-info.scss @@ -0,0 +1,190 @@ +.info { + margin-top: 60px; + + @include for-tablet-portrait-up { + margin-top: 90px; + } +} + +.info__header { + padding: 0 32px; + font-size: 32px; + color: $text-black; + font-weight: $medium-weight; + + @include for-tablet-portrait-up { + text-align: center; + font-size: 48px; + } +} + +.info__box { + margin-top: 25px; + + @include for-tablet-portrait-up { + display: flex; + align-items: center; + height: 240px; + margin-top: 58px; + background-color: white; + box-shadow: 0 16px 32px 0 rgba($shadow-red, 0.1); + } +} + +.info__image { + position: relative; + width: 100%; + height: 0; + padding-top: calc(152 / 320 * 100%); + @include multicolor-gradient(); + overflow: hidden; + + @include for-tablet-portrait-up { + flex-shrink: 0; + width: 372px; + height: 100%; + padding-top: 0; + + &--right { + order: 1; + margin-left: auto; + } + } +} + +.info__image img { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + filter: drop-shadow(12px 0 48px rgba(black, 0.15)); + opacity: 0.95; +} + +.info__image-triangle1 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + clip-path: polygon(0% 0%, 100% 0%, 100% 100%); + background-color: white; + opacity: 0.5; + + .info__image--right & { + left: 0; + right: auto; + clip-path: polygon(0% 0%, 100% 0%, 50px 100%, 0 100%); + } + + @include for-tablet-portrait-up { + display: block; + } +} + +.info__image-triangle2 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + clip-path: polygon(36px 0%, 100% 0%, 100% 100%, 0% 100%); + background-color: white; + opacity: 0.5; + + .info__image--right & { + left: 0; + right: auto; + clip-path: polygon(0% 0%, 130px 0%, 66px 100%, 0% 100%); + } + + @include for-tablet-portrait-up { + display: block; + } +} + +.info__image-triangle3 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + clip-path: polygon(112px 0%, 100% 0%, 100% 100%, 48px 100%); + background-color: white; + opacity: 0.5; + + .info__image--right & { + left: 0; + right: auto; + clip-path: polygon(0% 0%, 110px 0%, 140px 100%, 0% 100%); + } + + @include for-tablet-portrait-up { + display: block; + } +} + +.info__image-triangle4 { + display: none; + position: absolute; + top: 0; + right: 0; + width: 160px; + height: 100%; + clip-path: polygon(100% 0%, 100% 100%, 0% 100%); + background-color: white; + opacity: 1; + + .info__image--right & { + left: 0; + right: auto; + clip-path: polygon(0% 0%, 140px 100%, 0% 100%); + } + + @include for-tablet-portrait-up { + display: block; + } +} + +.info__text { + margin-top: 23px; + padding: 0 32px; + font-size: 16px; + line-height: 24px; + font-weight: $regular-weight; + color: $text-black; + + p { + margin-bottom: 12px; + + &:last-child { + margin-bottom: 0; + } + } + + @include for-tablet-portrait-up { + margin-top: 0; + + &--left { + margin-left: 32px; + } + + p { + margin-bottom: 16px; + } + } + + @include for-desktop-up { + font-size: 20px; + line-height: 32px; + + &--left { + margin-left: 80px; + } + } + +} \ No newline at end of file diff --git a/focus-block/scss/layout/_module.scss b/focus-block/scss/layout/_module.scss new file mode 100644 index 0000000..754d27e --- /dev/null +++ b/focus-block/scss/layout/_module.scss @@ -0,0 +1,7 @@ +@import "landing-first-screen"; +@import "landing-info"; +@import "landing-cta"; +@import "landing-footer"; +@import "app-base"; +@import "app-form"; +@import "app-focusing"; \ No newline at end of file diff --git a/focus-block/scss/styles.scss b/focus-block/scss/styles.scss new file mode 100644 index 0000000..c5125e8 --- /dev/null +++ b/focus-block/scss/styles.scss @@ -0,0 +1,27 @@ +@import "base/module"; +@import "components/module"; +@import "layout/module"; + +html { + height: 100%; + box-sizing: border-box; + font-family: $font-family; + text-rendering: optimizeLegibility; +} + +body { + position: relative; + height: 100%; + min-height: 100%; + background-color: $background-white; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +a { + color: inherit; + text-decoration: inherit; + cursor: pointer; +} \ No newline at end of file diff --git a/focus-block/src/App.css b/focus-block/src/App.css deleted file mode 100644 index cfc7f0f..0000000 --- a/focus-block/src/App.css +++ /dev/null @@ -1,53 +0,0 @@ -.nav { - width: 100%; - background-color: #fff; - display: inline-block; - border-bottom: 1px solid #979797; } - .nav .title { - display: inline-block; - font-size: 36px; - font-weight: 500; - margin: 21px 0 21px 20px; } - .nav .nav-options { - float: right; - font-size: 28px; } - .nav .nav-options ul a { - display: inline; - padding: 0 20px 0 20px; - text-decoration: none; - cursor: pointer; } - .nav .nav-options ul a:hover { - color: #5aca0e; } - -.content { - display: flex; - height: 100%; - text-align: center; - flex-direction: column; - position: relative; } - -@media (max-width: 414px) { - .nav .title { - text-align: center; - display: block; - margin: 21px 0 0 0; } - .nav .nav-options { - float: none; } } - -@media (max-width: 411px) { - .nav-options { - text-align: center; } - .nav-options ul { - padding: 0; } } - -@media (max-width: 375px) { - .nav .title { - text-align: center; - display: block; - margin: 21px 0 0 0; } - .nav .nav-options { - float: none; } } - -@media (max-width: 320px) { - .nav-options ul { - padding: 0; } } diff --git a/focus-block/src/App.js b/focus-block/src/App.js deleted file mode 100644 index 7575c1a..0000000 --- a/focus-block/src/App.js +++ /dev/null @@ -1,91 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import { Switch, Route, Link, withRouter } from 'react-router-dom'; -import Dashboard from './Components/Dashboard/Dashboard'; -import About from './Components/About/About'; -import './App.css'; - -/* - This is the main component where all other child components render in. -*/ - -class App extends Component { - constructor(props) { - super(props); - - this.state = { - dashboardPath: '' - }; - } - - // Need this to check to see if there is a current id in URL. We need to save the path to navigate - //-- MAD PROPS HiDeoo -- // - static getDerivedStateFromProps(props, state) { - let pathname = props.history.location.pathname.split('/'); - let joined = ''; - - if (pathname.length === 3 && state.dashboardPath === '') { - joined = pathname.join('/'); - return { dashboardPath: joined }; - } - - return null; - } - - //-- Helpers --// - - // Get current dashboard path to bring user back to their current FocusBlocks // - getPath = () => { - let pathname = this.props.history.location.pathname; - - switch (pathname) { - case '/about': - // Get About comp ref and grab dashPath url // - if (this.aboutRef.props.dashPath !== '') { - this.props.history.push(this.aboutRef.props.dashPath); - } else { - this.props.history.push('/dashboard'); - } - break; - case '/dashbaord': - if (this.state.dashboardPath !== '') { - this.props.history.push(this.state.dashboardPath); - } else { - this.props.history.push('/dashboard'); - } - break; - default: - this.props.history.push('/dashboard'); - } - }; - - render() { - return ( - -
-
FocusBlock
-
- -
-
-
- - - - - (this.aboutRef = ref)} - /> - -
-
- ); - } -} - -export default withRouter(App); diff --git a/focus-block/src/App.scss b/focus-block/src/App.scss deleted file mode 100644 index 3f2ea40..0000000 --- a/focus-block/src/App.scss +++ /dev/null @@ -1,84 +0,0 @@ -.nav { - width: 100%; - background-color: #fff; - display: inline-block; - border-bottom: 1px solid #979797; - - .title { - display: inline-block; - font-size: 36px; - font-weight: 500; - margin: 21px 0 21px 20px; - } - - .nav-options { - float: right; - font-size: 28px; - ul { - a { - display: inline; - padding: 0 20px 0 20px; - text-decoration: none; - cursor: pointer; - - &:hover { - color: #5aca0e; - } - } - } - } -} - -//-- MAD PROPS brutusharvenius (Flex box GOD)--// -.content { - display: flex; - height: 100%; - text-align: center; - flex-direction: column; - position: relative; -} - -@media (max-width: 414px) { - .nav { - .title { - text-align: center; - display: block; - margin: 21px 0 0 0; - } - - .nav-options { - float: none; - } - } -} - -@media (max-width: 411px) { - .nav-options { - text-align: center; - ul { - padding: 0; - } - } -} - -@media (max-width: 375px) { - .nav { - .title { - text-align: center; - display: block; - margin: 21px 0 0 0; - } - - .nav-options { - float: none; - } - } -} - -@media (max-width: 320px) { - .nav-options { - ul { - padding: 0; - } - } -} diff --git a/focus-block/src/App.test.js b/focus-block/src/App.test.js deleted file mode 100644 index a754b20..0000000 --- a/focus-block/src/App.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); - ReactDOM.unmountComponentAtNode(div); -}); diff --git a/focus-block/src/Assets/clock-mobile.svg b/focus-block/src/Assets/clock-mobile.svg new file mode 100644 index 0000000..36aab9b --- /dev/null +++ b/focus-block/src/Assets/clock-mobile.svg @@ -0,0 +1,16 @@ + + Clock + + + + + + + + + + + + + + \ No newline at end of file diff --git a/focus-block/src/Assets/clock-tablet.svg b/focus-block/src/Assets/clock-tablet.svg new file mode 100644 index 0000000..ef8042d --- /dev/null +++ b/focus-block/src/Assets/clock-tablet.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/focus-block/src/Assets/cmjio-button@2x.png b/focus-block/src/Assets/cmjio-button@2x.png deleted file mode 100644 index 5697403..0000000 Binary files a/focus-block/src/Assets/cmjio-button@2x.png and /dev/null differ diff --git a/focus-block/src/Assets/delete-trash@2x.png b/focus-block/src/Assets/delete-trash@2x.png deleted file mode 100644 index 30ef0e9..0000000 Binary files a/focus-block/src/Assets/delete-trash@2x.png and /dev/null differ diff --git a/focus-block/src/Assets/edit-pencil@2x.png b/focus-block/src/Assets/edit-pencil@2x.png deleted file mode 100644 index 9954e40..0000000 Binary files a/focus-block/src/Assets/edit-pencil@2x.png and /dev/null differ diff --git a/focus-block/src/Assets/focusblock-logo-blue.svg b/focus-block/src/Assets/focusblock-logo-blue.svg new file mode 100644 index 0000000..fd7166b --- /dev/null +++ b/focus-block/src/Assets/focusblock-logo-blue.svg @@ -0,0 +1 @@ +FocusBlock Logo diff --git a/focus-block/src/Assets/focusblock-logo-red.svg b/focus-block/src/Assets/focusblock-logo-red.svg new file mode 100644 index 0000000..5bf92f9 --- /dev/null +++ b/focus-block/src/Assets/focusblock-logo-red.svg @@ -0,0 +1 @@ +FocusBlock Logo diff --git a/focus-block/src/Assets/focusblock-logo-white.svg b/focus-block/src/Assets/focusblock-logo-white.svg new file mode 100644 index 0000000..7299d91 --- /dev/null +++ b/focus-block/src/Assets/focusblock-logo-white.svg @@ -0,0 +1 @@ +FocusBlock Logo diff --git a/focus-block/src/Assets/github.svg b/focus-block/src/Assets/github.svg new file mode 100644 index 0000000..e8659ee --- /dev/null +++ b/focus-block/src/Assets/github.svg @@ -0,0 +1,7 @@ + + + Github Icon + + + + \ No newline at end of file diff --git a/focus-block/src/Assets/github_logo.png b/focus-block/src/Assets/github_logo.png deleted file mode 100644 index d45d01c..0000000 Binary files a/focus-block/src/Assets/github_logo.png and /dev/null differ diff --git a/focus-block/src/Assets/keyboard-mobile.svg b/focus-block/src/Assets/keyboard-mobile.svg new file mode 100644 index 0000000..26617ab --- /dev/null +++ b/focus-block/src/Assets/keyboard-mobile.svg @@ -0,0 +1,15 @@ + + Keyboard + + + + + + + + + + + + + \ No newline at end of file diff --git a/focus-block/src/Assets/keyboard-tablet.svg b/focus-block/src/Assets/keyboard-tablet.svg new file mode 100644 index 0000000..e4c6496 --- /dev/null +++ b/focus-block/src/Assets/keyboard-tablet.svg @@ -0,0 +1,21 @@ + + Keyboard + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/focus-block/src/Assets/twitch.svg b/focus-block/src/Assets/twitch.svg new file mode 100644 index 0000000..1d2eb6c --- /dev/null +++ b/focus-block/src/Assets/twitch.svg @@ -0,0 +1,6 @@ + + Twitch icon + + + + \ No newline at end of file diff --git a/focus-block/src/Assets/twitch_logo.png b/focus-block/src/Assets/twitch_logo.png deleted file mode 100644 index 18de3e7..0000000 Binary files a/focus-block/src/Assets/twitch_logo.png and /dev/null differ diff --git a/focus-block/src/Components/About/About.js b/focus-block/src/Components/About/About.js deleted file mode 100644 index 8f2529f..0000000 --- a/focus-block/src/Components/About/About.js +++ /dev/null @@ -1,87 +0,0 @@ -import React, { Component } from 'react'; -import { Link } from 'react-router-dom'; -import ReactGA from 'react-ga'; -import './styles.css'; - -/* - This component is used to display basic information about FocusBlock - and link to Twitch & Github accounts -*/ -class About extends Component { - render() { - // Google Analytics // - ReactGA.initialize('UA-90746218-3'); - ReactGA.pageview(window.location.pathname); - - return ( -
-
-
-

FocusBlock

-
-
Be The Most Productive Version Of You
-
- -
-
-
-

Keep Yourself On Track

-

- Sometimes we lose track of time when working on a certain task. -

-

- Set the amount of time a task should take and let FocusBlock - remind you when time is up -

-
-
-
-
-

You Always Have Backup

-

- We don’t know everything and that's okay! Recruit someone’s help - through email. -

-

- Set someone's email address to connect them automatically if you - are having trouble -

-
-
-
-
-
- - Github Logo - -
-

Fully Open Source.

-

Contribute Today.

-
-
-
- - Twitch Logo - -
-

Developed Live On Twitch In 28 Days.

-

Check Out The Highlights.

-
-
-
-
- ); - } -} - -export default About; diff --git a/focus-block/src/Components/About/styles.css b/focus-block/src/Components/About/styles.css deleted file mode 100644 index 38cac44..0000000 --- a/focus-block/src/Components/About/styles.css +++ /dev/null @@ -1,61 +0,0 @@ -.container .header { - padding: 45px 0 45px 0; } - .container .header .title { - font-size: 36px; } - .container .header .title h3 { - margin: 0; } - .container .header .subtitle { - font-size: 28px; } - -.container .get-focused-btn { - height: 50px; - width: 265px; - font-size: 20px; - font-weight: 700; - border: 2px solid #5aca0e; - border-radius: 5px; - cursor: pointer; } - .container .get-focused-btn:hover { - background-color: #5aca0e; - color: #fff; - opacity: 0.7; } - .container .get-focused-btn a { - text-decoration: none; } - -.container .info-blocks { - display: flex; - justify-content: space-evenly; - flex-wrap: wrap; - padding-top: 90px; } - .container .info-blocks .info-block { - width: 690px; - height: 100%; - margin: 20px 20px; - background-color: #fff; - border: 3px solid #979797; - border-radius: 5px; } - .container .info-blocks .info-block .info-content { - padding: 20px; } - .container .info-blocks .info-block .info-content h3 { - font-size: 36px; } - .container .info-blocks .info-block .info-content p { - font-size: 28px; } - -.container .social-details { - display: flex; - justify-content: space-evenly; - flex-wrap: wrap; - padding: 40px 0 40px 0; } - .container .social-details .social-block { - width: 690px; - height: 150px; } - .container .social-details .social-block .github { - width: 225px; } - .container .social-details .social-block .twitch { - width: 200px; - padding-top: 20px; } - .container .social-details .social-block .social-text { - padding-top: 15px; } - .container .social-details .social-block .social-text p { - font-size: 24px; - margin: 0; } diff --git a/focus-block/src/Components/About/styles.scss b/focus-block/src/Components/About/styles.scss deleted file mode 100644 index eeac701..0000000 --- a/focus-block/src/Components/About/styles.scss +++ /dev/null @@ -1,92 +0,0 @@ -.container { - .header { - padding: 45px 0 45px 0; - .title { - font-size: 36px; - h3 { - margin: 0; - } - } - - .subtitle { - font-size: 28px; - } - } - - .get-focused-btn { - height: 50px; - width: 265px; - font-size: 20px; - font-weight: 700; - border: 2px solid #5aca0e; - border-radius: 5px; - cursor: pointer; - - &:hover { - background-color: #5aca0e; - color: #fff; - opacity: 0.7; - } - - a { - text-decoration: none; - } - } - - .info-blocks { - display: flex; - justify-content: space-evenly; - flex-wrap: wrap; - padding-top: 90px; - - .info-block { - width: 690px; - height: 100%; - margin: 20px 20px; - background-color: #fff; - border: 3px solid #979797; - border-radius: 5px; - - .info-content { - padding: 20px; - - h3 { - font-size: 36px; - } - - p { - font-size: 28px; - } - } - } - } - - .social-details { - display: flex; - justify-content: space-evenly; - flex-wrap: wrap; - padding: 40px 0 40px 0; - - .social-block { - width: 690px; - height: 150px; - - .github { - width: 225px; - } - - .twitch { - width: 200px; - padding-top: 20px; - } - - .social-text { - padding-top: 15px; - p { - font-size: 24px; - margin: 0; - } - } - } - } -} diff --git a/focus-block/src/Components/ActiveBlock/ActiveBlock.js b/focus-block/src/Components/ActiveBlock/ActiveBlock.js new file mode 100644 index 0000000..92c717e --- /dev/null +++ b/focus-block/src/Components/ActiveBlock/ActiveBlock.js @@ -0,0 +1,338 @@ +import React, { Component, Fragment } from 'react'; +import Email from '../../Containers/SmtpContainer'; +import Input from '../Input/Input'; + +class ActiveBlock extends Component { + constructor(props) { + super(props); + + this.state = { + name: props.block.name, + timeLimit: props.block.timeLimit, + helpEmail: props.block.helpEmail, + secondsLeft: props.block.timeLimit * 60, + taskTime: null, + timerIsActive: true, + timerStatus: 'Now Focusing', + isAltLogoColor: true, + isRedOutline: false, + timeLeft: null, + timerIntervalRef: null, + isEditEmailOpen: false, + isQuitConfirmationOpen: false, + isTaskCompletedOpen: false, + isEmailSentOpen: false, + helpEmailValue: props.block.helpEmail, + helpEmailIsValid: true, + helpEmailErrorShown: false, + helpEmailErrorMessage: 'This is not a valid email address' + }; + } + + componentDidMount() { + this.props.changedAppearance(this.state.timerStatus, this.state.isAltLogoColor, this.state.isRedOutline, false, false); + this.formatTimeLeft(); + this.setState({ + timerIntervalRef: this.createTimerInterval() + }); + } + + strPadLeft = (string, pad, length) => { + return (new Array(length+1).join(pad)+string).slice(-length); + } + + formatTimeLeft = () => { + let secondsLeft = this.state.secondsLeft; + let minutes = Math.floor(secondsLeft / 60); + let seconds = secondsLeft - minutes * 60; + let formattedMinutes; + if (minutes < 100) { + formattedMinutes = this.strPadLeft(minutes, '0', 2); + } else { + formattedMinutes = minutes; + } + let formattedTime = formattedMinutes + ':' + this.strPadLeft(seconds, '0', 2); + this.setState({ + timeLeft: formattedTime + }); + } + + timerTick = () => { + let secondsLeft = this.state.secondsLeft - 1; + let timerIsActive; + let timerStatus; + let isAltLogoColor; + let isRedOutline; + if (secondsLeft === 0) { + timerIsActive = false; + timerStatus = 'Time\'s Up!'; + isAltLogoColor = false; + isRedOutline = true; + clearInterval(this.state.timerIntervalRef); + } else { + timerIsActive = true; + timerStatus = 'Now Focusing'; + isAltLogoColor = true; + isRedOutline = false; + } + this.setState({ + secondsLeft: secondsLeft, + timerIsActive: timerIsActive, + timerStatus: timerStatus, + isAltLogoColor: isAltLogoColor, + isRedOutline: isRedOutline + }); + if (!this.state.isEditEmailOpen) { + this.props.changedAppearance(timerStatus, isAltLogoColor, isRedOutline, false, false); + this.formatTimeLeft(); + } + } + + createTimerInterval = () => { + this.timerTick(); + return setInterval(() => this.timerTick(), 1000); + } + + pauseTimer = () => { + clearInterval(this.state.timerIntervalRef); + let timerIsActive = false; + let timerStatus = 'On Pause'; + let isAltLogoColor = false; + this.setState({ + timerIsActive: timerIsActive, + timerStatus: timerStatus, + isAltLogoColor: isAltLogoColor + }); + this.props.changedAppearance(timerStatus, isAltLogoColor, this.state.isRedOutline, false, false); + } + + resumeTimer = () => { + this.setState({ + timerIntervalRef: this.createTimerInterval() + }); + } + + // This function is not used in this version + restartTimer = () => { + let secondsLeft = this.state.timeLimit * 60; + this.setState({ + secondsLeft: secondsLeft, + timerIntervalRef: this.createTimerInterval() + }); + } + + openEditEmail = () => { + this.setState({ + isEditEmailOpen: true + }); + this.props.changedAppearance('Edit Email', false, false, true, false); + } + + closeEditEmail = () => { + this.setState({ + isEditEmailOpen: false + }); + this.props.changedAppearance(this.state.timerStatus, this.state.isAltLogoColor, this.state.isRedOutline, false, false); + this.formatTimeLeft(); + } + + saveEditEmail = () => { + if (this.state.helpEmailIsValid) { + this.setState({ + helpEmail: this.state.helpEmailValue + }); + this.closeEditEmail(); + } else { + this.setState({ + helpEmailErrorShown: true + }); + } + } + + dontSaveEditEmail = () => { + this.setState({ + helpEmailValue: this.state.helpEmail, + helpEmailIsValid: true, + helpEmailErrorShown: false + }); + this.closeEditEmail(); + } + + helpEmailChangeHandler = (event) => { + let helpEmailValue = event.target.value; + let validContact = helpEmailValue.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i); + let helpEmailIsValid = helpEmailValue === '' || validContact; + this.setState({ + helpEmailValue: helpEmailValue, + helpEmailIsValid: helpEmailIsValid + }); + } + + helpEmailBlurHandler = () => { + this.setState({ + helpEmailErrorShown: !this.state.helpEmailIsValid + }); + } + + openQuitConfirmation = () => { + this.setState({ + isQuitConfirmationOpen: true + }); + this.props.changedAppearance('', false, false, true, false); + } + + closeQuitConfirmation = () => { + this.setState({ + isQuitConfirmationOpen: false + }); + this.props.changedAppearance(this.state.timerStatus, this.state.isAltLogoColor, this.state.isRedOutline, false, false); + } + + openTaskCompleted = () => { + this.pauseTimer(); + let timeLimitInSeconds = this.state.timeLimit * 60; + let secondsLeft = this.state.secondsLeft; + let taskTimeInSeconds = timeLimitInSeconds - secondsLeft; + let taskTime = Math.floor(taskTimeInSeconds / 60); + this.setState({ + taskTime: taskTime, + isTaskCompletedOpen: true + }); + this.props.changedAppearance('', false, false, false, true); + } + + openEmailSent = () => { + this.sendEmail(); + + this.setState({ + isEmailSentOpen: true + }); + this.props.changedAppearance('', false, false, false, true); + } + + sendEmail = () => { + let mailer = new Email(); + let sender = 'support@pixelogicapps.com'; + let subject = `Requesting Help: ${this.state.name}`; + let body = ` + Hi from Pixelogic Support! + + Looks like someone is requesting your help with task “${this.state.name}” + + Brought to you by FocusBlock + `; + let server = 'smtp.sendgrid.net'; + + mailer.send( + sender, + this.state.helpEmail, + subject, + body, + server, + process.env.REACT_APP_SMTP_USERNAME, + process.env.REACT_APP_SMTP_PW + ); + }; + + render() { + + return ( + (this.state.isEditEmailOpen ? ( +
+ +
+ + +
+
+ ) : this.state.isQuitConfirmationOpen ? ( +
+
Are you sure you want to end current task and start a new one?
+
+ + +
+
+ ) : this.state.isTaskCompletedOpen ? ( +
+
Good Job!
+
You've finished “{this.state.name}” in {this.state.taskTime} minutes.
+
+ +
+
+ ) : this.state.isEmailSentOpen ? ( +
+
Backup is on it's way
+
We've notified {this.state.helpEmail}.
+
+ +
+
+ ) : ( +
+
+
Time Left
+
{this.state.timeLeft}
+
+
+
Task
+
{this.state.name}
+
+
+
Backup person
+
+ {this.state.helpEmail === '' ? 'Nobody' : this.state.helpEmail} +
+
Edit backup email
+
+
+ {this.state.secondsLeft > 0 ? ( + this.state.timerIsActive ? ( + + + + + ) : ( + + + + + ) + ) : ( + + {this.state.helpEmail !== '' ? ( + + +
This will send an email with the task name to {this.state.helpEmail}
+
+ ) : ( + + )} + +
+ )} +
+
+ )) + ); + } +} + +export default ActiveBlock; \ No newline at end of file diff --git a/focus-block/src/Components/App/App.js b/focus-block/src/Components/App/App.js new file mode 100644 index 0000000..77dc961 --- /dev/null +++ b/focus-block/src/Components/App/App.js @@ -0,0 +1,72 @@ +import React, { Component } from 'react'; +import NewBlockForm from '../NewBlockForm/NewBlockForm' +import ActiveBlock from '../ActiveBlock/ActiveBlock'; + +class App extends Component { + constructor(props) { + super(props); + this.state = { + title: 'New Task', + isAltLogoColor: false, + wrapperClass: '', + currentBlock: null + }; + } + + formSubmitHandler = (block) => { + this.setState({currentBlock: block}); + } + + appearanceChangeHandler = (title, isAltLogoColor, isRedOutline, isPopup, isFinished) => { + let wrapperClass = ''; + if (isRedOutline) { + wrapperClass = 'app-wrapper--times-up'; + } else if (isPopup) { + wrapperClass = 'app-wrapper--popup' + } else if (isFinished) { + wrapperClass = 'app-wrapper--finished' + } + this.setState({ + title: title, + isAltLogoColor: isAltLogoColor, + wrapperClass: wrapperClass + }); + } + + blockEndHandler = () => { + this.setState({ + title: 'New Task', + isAltLogoColor: false, + wrapperClass: '', + currentBlock: null + }); + } + + render() { + return( +
+
+
+ +
+ {this.state.title &&
{this.state.title}
} +
+ {this.state.currentBlock ? ( + + ) : ( + + )} +
+ ); + } +} + +export default App; \ No newline at end of file diff --git a/focus-block/src/Components/BlockForm/BlockForm.js b/focus-block/src/Components/BlockForm/BlockForm.js deleted file mode 100644 index 3c8d336..0000000 --- a/focus-block/src/Components/BlockForm/BlockForm.js +++ /dev/null @@ -1,279 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import './styles.css'; - -/* - The BlockForm component is a form that is here to help you create a FocusBlock. -*/ - -class BlockForm extends Component { - constructor(props) { - super(props); - - // This component can be rendered on creation and on edit. Set state depending on scenario // - let currentState; - if (this.props.isEditing) { - currentState = { - title: props.focusBlock.state.title, - timer: props.focusBlock.state.timer, - customTimer: props.focusBlock.state.customTimer, - contact: props.focusBlock.state.contact, - formErrors: { title: 'valid', timer: 'valid', contact: 'valid' }, - formValid: true - }; - } else { - // Creates a new focusBlock // - currentState = { - title: '', - timer: 15, - customTimer: 15, - contact: '', - formErrors: { title: '', timer: 'valid', contact: 'valid' }, - formValid: false - }; - } - - this.state = currentState; - } - - //-- Helpers --// - // MAD PROPS: https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript#answer-2117523 // - uuid() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - ( - c ^ - (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) - ).toString(16) - ); - } - - // When a field is changed in the form, save to state // - handleChange = event => { - this.validateField(event); - this.setState({ - [event.target.name]: event.target.value - }); - }; - - // Convert the number value of the timer to a more valuable unit of time // - getFriendlyTime = () => { - let friendlyTimer = ''; - let timerVal; - - if (this.state.timer === 'custom') { - timerVal = this.state.customTimer; - } else { - timerVal = this.state.timer; - } - - if (timerVal < 60) { - friendlyTimer = `${timerVal}m`; - } else { - friendlyTimer = `${timerVal / 60}h`; - } - - return friendlyTimer; - }; - - // Use this to create the model of a FocusBlock on sumbit with the newly added form data // - initFocusBlock = () => { - return { - id: this.uuid(), - title: this.state.title, - timer: this.state.timer, - customTimer: this.state.customTimer, - friendlyTimer: this.getFriendlyTime(), - contact: this.state.contact, - contactVisible: false, - blockStarted: false, - timerRef: null, - currentProgress: 'start', - isEditing: false, - inputErrors: { contact: 'valid' }, - dashboardEvents: this.props.triggers - }; - }; - - // If editing update current FocusBlock passed in; else init new FocusBlock with form data // - blockEvent = event => { - if (this.props.isEditing) { - let focusBlock = this.props.focusBlock; - let updatedState = { - title: this.state.title, - timer: this.state.timer, - customTimer: this.state.customTimer, - friendlyTimer: this.getFriendlyTime(), - contact: this.state.contact, - isEditing: false - }; - - //-- MAD PROPS Empty_place --// - focusBlock.setState({ ...updatedState }, () => { - focusBlock.state.dashboardEvents.update(focusBlock.state); - }); - } else { - console.log('Creating block...'); - // Access dashboard component & send block // - this.props.triggers.create(this.initFocusBlock()); - } - - event.preventDefault(); - }; - - // Validate form field // - validateField = event => { - let titleValid = this.state.formErrors.title; - let timerValid = this.state.formErrors.timer; - let contactValid = this.state.formErrors.contact; - - switch (event.target.name) { - case 'title': - let titleLen = event.target.value.length; - titleValid = titleLen > 0 ? 'valid' : 'Title cannot be empty'; - break; - case 'timer': - if (event.target.value === 'custom') { - timerValid = 'valid'; - } else { - let timerLen = event.target.value.length; - timerValid = timerLen > 0 ? 'valid' : 'Please select a time'; - } - - break; - case 'contact': - let validContact = event.target.value.match( - /^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i - ); - - contactValid = - // Email address is not required to continue // - validContact || event.target.value === '' - ? 'valid' - : 'This is not an email, please try again.'; - break; - default: - break; - } - - this.formValid(titleValid, timerValid, contactValid); - }; - - // Check to see if entire form is valid before submitting // - formValid = (title, timer, contact) => { - let isFormValid = false; - if (title === 'valid' && timer === 'valid' && contact === 'valid') { - isFormValid = true; - } - - this.setState({ - formErrors: { - title: title, - timer: timer, - contact: contact - }, - formValid: isFormValid - }); - }; - - render() { - return ( - -
- {/* Form Start */} -
- {/* FocusBlock Title */} - - - {this.state.formErrors.title !== 'valid' ? ( -
{this.state.formErrors.title}
- ) : ( - '' - )} - {/* FocusBlock Timer */} - - - {this.state.timer === 'custom' ? ( - - ) : ( - '' - )} - {this.state.formErrors.timer !== 'valid' ? ( -
{this.state.formErrors.timer}
- ) : ( - '' - )} - {/* FocusBlock Email To Contact */} - - - {this.state.formErrors.contact !== 'valid' ? ( -
{this.state.formErrors.contact}
- ) : ( - '' - )} - {this.props.isEditing ? ( -
- - - -
- ) : ( - - )} -
- {/* Form End */} -
-
- ); - } -} - -export default BlockForm; diff --git a/focus-block/src/Components/BlockForm/styles.css b/focus-block/src/Components/BlockForm/styles.css deleted file mode 100644 index 485076a..0000000 --- a/focus-block/src/Components/BlockForm/styles.css +++ /dev/null @@ -1,84 +0,0 @@ -.form-content { - width: 40%; - max-width: 40%; - flex-basis: auto; - height: 445px; - border-radius: 5px; - margin: 2% 2%; - border: 3px solid #979797; - background-color: #fff; } - .form-content form { - display: flex; - flex-direction: column; - justify-content: center; - height: 100%; } - .form-content form label { - font-size: 18px; } - .form-content form .error-label { - color: red; - font-size: 14px; - text-align: left; - width: 75%; - margin: 10px auto; } - .form-content form input { - width: 75%; - height: 25px; - border: 0; - border-bottom: 2px #726d6d solid; - margin: 20px auto; - font-size: 16px; } - .form-content form input:focus { - outline: none; - border-bottom-color: #5aca0e; } - .form-content form select { - width: 75%; - height: 25px; - border: 0; - margin: 20px auto; - font-size: 16px; } - .form-content form select:focus { - outline: none; } - .form-content form .action-buttons button.action-delete { - width: 5%; - vertical-align: top; - border-color: #fb9595; } - .form-content form .action-buttons button.action-delete img { - width: 20px; - height: 25px; } - .form-content form .action-buttons button.action-delete:hover { - background-color: #fb9595; } - .form-content form .action-buttons button.action-delete, .form-content form .action-buttons button.action-cancel { - margin-right: 3%; } - .form-content form .action-buttons button.action-cancel { - border-color: #979797; } - .form-content form .action-buttons button.action-cancel:hover { - background-color: #979797; } - .form-content form .action-buttons button.action-cancel, .form-content form .action-buttons button:nth-child(3) { - width: 30%; } - .form-content form button { - margin: 0 auto; - width: 50%; - height: 50px; - border: 2px solid #5aca0e; - border-radius: 5px; - font-size: 16px; - cursor: pointer; } - .form-content form button:hover { - background-color: #5aca0e; - color: #fff; - opacity: 0.7; } - .form-content form button:disabled { - border: 2px #726d6d solid; - background-color: #726d6d; - color: #000; - opacity: 0.3; } - -@media (max-width: 1024px) { - .form-content form .action-buttons button.action-delete { - width: 10%; } } - -@media (max-width: 768px) { - .form-content { - width: 95%; - max-width: none; - margin: 2%; } } diff --git a/focus-block/src/Components/BlockForm/styles.scss b/focus-block/src/Components/BlockForm/styles.scss deleted file mode 100644 index 4c1120c..0000000 --- a/focus-block/src/Components/BlockForm/styles.scss +++ /dev/null @@ -1,132 +0,0 @@ -.form-content { - width: 40%; - max-width: 40%; - flex-basis: auto; - height: 445px; - border-radius: 5px; - margin: 2% 2%; - border: 3px solid #979797; - background-color: #fff; - - form { - display: flex; - flex-direction: column; - justify-content: center; - height: 100%; - - label { - font-size: 18px; - } - - .error-label { - color: red; - font-size: 14px; - text-align: left; - width: 75%; - margin: 10px auto; - } - - input { - width: 75%; - height: 25px; - border: 0; - border-bottom: 2px #726d6d solid; - margin: 20px auto; - font-size: 16px; - - &:focus { - outline: none; - border-bottom-color: #5aca0e; - } - } - - select { - width: 75%; - height: 25px; - border: 0; - margin: 20px auto; - font-size: 16px; - - &:focus { - outline: none; - } - } - - .action-buttons { - button { - &.action-delete { - width: 5%; - vertical-align: top; - border-color: #fb9595; - img { - width: 20px; - height: 25px; - } - &:hover { - background-color: #fb9595; - } - } - - &.action-delete, - &.action-cancel { - margin-right: 3%; - } - - &.action-cancel { - border-color: #979797; - &:hover { - background-color: #979797; - } - } - - &.action-cancel, - &:nth-child(3) { - width: 30%; - } - } - } - - button { - margin: 0 auto; - width: 50%; - height: 50px; - border: 2px solid #5aca0e; - border-radius: 5px; - font-size: 16px; - cursor: pointer; - - &:hover { - background-color: #5aca0e; - color: #fff; - opacity: 0.7; - } - - &:disabled { - border: 2px #726d6d solid; - background-color: #726d6d; - color: #000; - opacity: 0.3; - } - } - } -} - -@media (max-width: 1024px) { - .form-content { - form { - .action-buttons { - button.action-delete { - width: 10%; - } - } - } - } -} - -@media (max-width: 768px) { - .form-content { - width: 95%; - max-width: none; - margin: 2%; - } -} diff --git a/focus-block/src/Components/Dashboard/AddBlockButton/AddBlockButton.js b/focus-block/src/Components/Dashboard/AddBlockButton/AddBlockButton.js deleted file mode 100644 index f5d3678..0000000 --- a/focus-block/src/Components/Dashboard/AddBlockButton/AddBlockButton.js +++ /dev/null @@ -1,64 +0,0 @@ -import React, { Component } from 'react'; -import './styles.css'; - -/* - Simple Button Component to display BlockForm and add a new FocusBlock. -*/ - -class AddBlockButton extends Component { - constructor(props) { - super(props); - - this.state = { - didClick: false - }; - } - - //-- Helpers -- // - addBlock = () => { - if (this.props.blockCount !== 0) { - // Set didClick state // - this.setState({ - didClick: true - }); - - // Trigger addBlock event // - this.props.addBlockTrigger(); - - // Set State back after animation // - setTimeout(() => { - this.setState({ - didClick: false - }); - }, 100); - } - }; - - // Use this to set the state of the button. If just BlockForm is up, disable button; else enable // - addClasses = () => { - let classString = 'action-add'; - if (this.props.blockCount === 0) { - classString += ' disabled'; - } - - if (this.state.didClick && this.props.blockCount > 0) { - classString += ' scale'; - } - - return classString; - }; - - render() { - return ( - Add Focus Block Button - ); - } -} - -export default AddBlockButton; diff --git a/focus-block/src/Components/Dashboard/AddBlockButton/styles.css b/focus-block/src/Components/Dashboard/AddBlockButton/styles.css deleted file mode 100644 index 6089c09..0000000 --- a/focus-block/src/Components/Dashboard/AddBlockButton/styles.css +++ /dev/null @@ -1,14 +0,0 @@ -.action-add { - width: 60px; - height: 60px; - cursor: pointer; - position: fixed; - bottom: 0; - right: 0; - padding: 15px; } - -.disabled { - opacity: 0.3; } - -.scale { - transform: scale(0.8); } diff --git a/focus-block/src/Components/Dashboard/AddBlockButton/styles.scss b/focus-block/src/Components/Dashboard/AddBlockButton/styles.scss deleted file mode 100644 index 7c7abe2..0000000 --- a/focus-block/src/Components/Dashboard/AddBlockButton/styles.scss +++ /dev/null @@ -1,17 +0,0 @@ -.action-add { - width: 60px; - height: 60px; - cursor: pointer; - position: fixed; - bottom: 0; - right: 0; - padding: 15px; -} - -.disabled { - opacity: 0.3; -} - -.scale { - transform: scale(0.8); -} diff --git a/focus-block/src/Components/Dashboard/Dashboard.js b/focus-block/src/Components/Dashboard/Dashboard.js deleted file mode 100644 index c357e53..0000000 --- a/focus-block/src/Components/Dashboard/Dashboard.js +++ /dev/null @@ -1,257 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import FocusBlock from '../FocusBlock/FocusBlock'; -import BlockForm from '../BlockForm/BlockForm'; -import AddBlockButton from './AddBlockButton/AddBlockButton'; -import ServiceContainer from '../../Containers/ServiceContainer'; -import ReactGA from 'react-ga'; -import './styles.css'; - -/* - The Dashboard component is used to house all the FocusBlocks you have created. - NOTE: I did not want to keep any emails in the DB, so all emails are stripped before network call. -*/ - -class Dashboard extends Component { - constructor(props) { - super(props); - - // Init state // - this.state = { - user: { - _id: '', - url: '', - focusBlocks: [] - }, - isAdding: false, - service: new ServiceContainer() - }; - - // If new user, redirect to their unique url // - if (!props.match.params.id) { - let serviceContainer = new ServiceContainer(); - // Create user and redirect // - serviceContainer - .createUser() - .then(result => { - this.setState({ - user: result - }); - this.props.history.push(`/dashboard/${result._id}`); - }) - .catch(error => { - console.log(error); - }); - } - } - - componentDidMount() { - // If userID is part of path, get user from DB // - let userId = this.props.match.params.id; - if (userId) { - this.state.service - .getUser(userId) - .then(result => { - this.setState({ user: result }); - console.log('User dashboard set.'); - }) - .catch(error => { - console.log(error); - }); - } - } - - //-- Helpers --// - - // Event used to create a new FocusBlock & send to DB // - createBlock = focusBlock => { - // Get current blocks in state // - let currentBlocks = this.state.user.focusBlocks; - currentBlocks.push(focusBlock); - - this.setState({ - user: this.updateUserBlocks(currentBlocks), - isAdding: false - }); - - // Remove contact to not store in DB // - let clonedBlocks = this.blockCloner(currentBlocks); - - // Update DB // - this.state.service - .updateUser(this.state.user._id, clonedBlocks) - .then(result => { - console.log(result); - }) - .catch(error => { - console.log(error); - }); - }; - - // Event used to update a FocusBlock & send to DB // - updateBlock = focusBlock => { - // Search for FocusBlock by ID // - let index = this.findBlockIndex(focusBlock.id); - - if (index !== -1) { - // Replace Block with updated one // - let blocksCopy = this.state.user.focusBlocks; - blocksCopy[index] = focusBlock; - - // Set state // - this.setState({ - user: this.updateUserBlocks(blocksCopy) - }); - - // Clone block to remove email // - let clonedBlocks = this.blockCloner(blocksCopy); - - // Update db // - this.state.service - .updateUser(this.state.user._id, clonedBlocks) - .then(result => { - console.log(result); - }) - .catch(error => { - console.log(error); - }); - } else { - console.log('FocusBlock not found.'); - } - }; - - // Event used to delete a FocusBlock & send to DB // - deleteBlock = id => { - // Find index of block // - let index = this.findBlockIndex(id); - - if (index !== -1) { - // Pop alert to confirm delete // - let willDelete = window.confirm( - `This action will delete "${ - this.state.user.focusBlocks[index].title - }". Press 'Okay' to confirm.` - ); - - if (willDelete) { - // Trigger update // - let blocksCopy = this.state.user.focusBlocks; - blocksCopy.splice(index, 1); - - // Set state // - this.setState({ - user: this.updateUserBlocks(blocksCopy) - }); - - // Clone block to remove email // - let clonedBlocks = this.blockCloner(blocksCopy); - - // Update db // - this.state.service - .updateUser(this.state.user._id, clonedBlocks) - .then(result => { - console.log(result); - }) - .catch(error => { - console.log(error); - }); - } - } else { - console.log('FocusBlock not found.'); - } - }; - - // Get ID from path and parse // - getUserId = path => { - // Split path and check for id // - let idSplit = path.split('/'); - return idSplit[1] !== '' ? idSplit[1] : null; - }; - - // Find a FocusBlock in the state given an ID // - findBlockIndex = id => { - return this.state.user.focusBlocks - .map(block => { - return block.id; - }) - .indexOf(id); - }; - - // Logic to get current FocusBlocks and update array // - updateUserBlocks = newBlocks => { - // Get current user state // - let currentUser = { ...this.state.user }; - currentUser.focusBlocks = newBlocks; - return currentUser; - }; - - // Used to strip emails from each FocusBlock in array // - blockCloner = blocks => { - let cloneArray = []; - - blocks.forEach(block => { - let cloneBlock = { - ...block - }; - - // Remove contact // - cloneBlock.contact = ''; - cloneArray.push(cloneBlock); - }); - - return cloneArray; - }; - - // Used to show the BlockForm to create a new FocusBlock // - addNewBlockTrigger = () => { - this.setState({ - isAdding: true - }); - }; - - // If there are no FocusBlocks in state, just show the BlockForm // - showBlockForm = () => { - return this.state.user.focusBlocks.length === 0; - }; - - render() { - // Google Analytics // - ReactGA.initialize('UA-90746218-3'); - ReactGA.pageview(window.location.pathname); - - // This obj is used to trigger the events on this component from other components // - let triggerObj = { - create: this.createBlock, - update: this.updateBlock, - delete: this.deleteBlock - }; - - return ( - -
-
- Use this URL to come back to your saved FocusBlocks:{' '} - - {this.state.user.url} - -
- {this.showBlockForm() ? ( - - ) : ( -
- {this.state.user.focusBlocks.map((block, i) => ( - - ))} - {this.state.isAdding ? : ''} -
- )} -
- -
- ); - } -} - -export default Dashboard; diff --git a/focus-block/src/Components/Dashboard/styles.css b/focus-block/src/Components/Dashboard/styles.css deleted file mode 100644 index 4d3e786..0000000 --- a/focus-block/src/Components/Dashboard/styles.css +++ /dev/null @@ -1,22 +0,0 @@ -.container { - margin: 15px; } - .container .custom-url { - font-weight: 500; - font-size: 26px; - padding-bottom: 30px; } - .container .blocks { - display: flex; - flex-wrap: wrap; - justify-content: space-between; } - -@media (max-width: 414px) { - .container .custom-url { - font-size: 18px; } } - -@media (max-width: 375px) { - .container .custom-url { - font-size: 18px; } } - -@media (max-width: 320px) { - .container .custom-url { - font-size: 16px; } } diff --git a/focus-block/src/Components/Dashboard/styles.scss b/focus-block/src/Components/Dashboard/styles.scss deleted file mode 100644 index 8119ab3..0000000 --- a/focus-block/src/Components/Dashboard/styles.scss +++ /dev/null @@ -1,36 +0,0 @@ -.container { - .custom-url { - font-weight: 500; - font-size: 26px; - padding-bottom: 30px; - } - margin: 15px; - .blocks { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - } -} -@media (max-width: 414px) { - .container { - .custom-url { - font-size: 18px; - } - } -} - -@media (max-width: 375px) { - .container { - .custom-url { - font-size: 18px; - } - } -} - -@media (max-width: 320px) { - .container { - .custom-url { - font-size: 16px; - } - } -} diff --git a/focus-block/src/Components/FocusBlock/FocusBlock.js b/focus-block/src/Components/FocusBlock/FocusBlock.js deleted file mode 100644 index a83f3d9..0000000 --- a/focus-block/src/Components/FocusBlock/FocusBlock.js +++ /dev/null @@ -1,276 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import BlockForm from '../BlockForm/BlockForm'; -import Email from '../../Containers/SmtpContainer'; -import './styles.css'; -/* - This is the actual FocusBlock that describes everything a FocusBlock is and should do. -*/ -class FocusBlock extends Component { - constructor(props) { - super(props); - - // State is the same for either new or updating // - this.state = { - id: props.block.id === '' ? this.uuid() : props.block.id, - title: props.block.title, - timer: props.block.timer, - // MAD PROPS DigitalData (found the un-findable bug) // - customTimer: props.block.customTimer, // Value of the custom timer input - friendlyTimer: this.getFriendlyTime( - props.block.timer, - props.block.customTimer - ), - contact: props.block.contact, - contactVisible: false, - blockStarted: false, - timerRef: null, - currentProgress: 'start', - isEditing: false, - inputErrors: { contact: 'valid' }, - dashboardEvents: props.events - }; - } - - //-- Helpers --// - // MAD PROPS: https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript#answer-2117523 // - uuid() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - ( - c ^ - (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) - ).toString(16) - ); - } - - // Convert the number value of the timer to a more valuable unit of time // - getFriendlyTime = (timer, customTimer) => { - let friendlyTimer = ''; - let timerVal; - - if (timer === 'custom') { - timerVal = customTimer; - } else { - timerVal = timer; - } - - if (timerVal < 60) { - friendlyTimer = `${timerVal}m`; - } else { - friendlyTimer = `${timerVal / 60}h`; - } - - return friendlyTimer; - }; - - // Toggle the FocusBlock to start or stop // - toggleBlock = () => { - this.setState({ - blockStarted: !this.state.blockStarted, - currentProgress: 'start' - }); - - // Start timer // - this.toggleTimer(); - }; - - // Email composition that is sent to designated person if email is provided // - sendEmail = () => { - let mailer = new Email(); - let sender = 'support@pixelogicapps.com'; - let subject = `Requesting Help: ${this.state.title}`; - let body = ` - Hi from Pixelogic Support! - Looks like someone is requesting your help with task '${this.state.title}' - Brought to you by FocusBlock https://www.focusblock.stream - `; - let server = 'smtp.sendgrid.net'; - - mailer.send( - sender, - this.state.contact, - subject, - body, - server, - process.env.REACT_APP_SMTP_USERNAME, - process.env.REACT_APP_SMTP_PW - ); - }; - - // Setup the timer interval to start and stop countdown // - createTimerInterval = () => { - // Grab the current block minutes // - let timerVal; - - if (this.state.timer === 'custom') { - timerVal = this.state.customTimer; - } else { - timerVal = this.state.timer; - } - - let blockTime = timerVal * 60, - minutes, - seconds; - - return setInterval(() => { - // MAD PROPS https://stackoverflow.com/questions/20618355/the-simplest-possible-javascript-countdown-timer // - minutes = parseInt(blockTime / 60, 10); - seconds = parseInt(blockTime % 60, 10); - - let currentProgress = this.state.currentProgress; - if (parseInt(timerVal / 2, 10) === minutes) { - // Mid point // - currentProgress = 'mid'; - } - - if (minutes === 0) { - // End point // - currentProgress = 'end'; - } - - let friendlyTimer = ''; - minutes = minutes < 10 ? '0' + minutes : minutes; - seconds = seconds < 10 ? '0' + seconds : seconds; - friendlyTimer = minutes + ':' + seconds; - - this.setState({ - friendlyTimer: friendlyTimer, - currentProgress: currentProgress - }); - - if (--blockTime < 0) { - this.setState({ - blockStarted: false, - friendlyTimer: 'Times up!' - }); - - if (this.state.contact !== '') { - this.sendEmail(); - console.log('Email sent.'); - } - clearInterval(this.state.timerRef); - } - }, 1000); - }; - - // This will start or stop the timer logic as a whole // - toggleTimer = () => { - if (this.state.blockStarted) { - clearInterval(this.state.timerRef); - } else { - // Setup a timer on comp to count down // - this.setState({ - timerRef: this.createTimerInterval() - }); - } - }; - - // When adding a new email, validate and then set state // - contactBlurEvent = event => { - let targetVal = event.target.value; - let validContact = targetVal.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i); - - if (validContact || event.target.value === '') { - this.setState({ - contact: targetVal, - contactVisible: event.target.value === '' ? false : true, - inputErrors: { contact: 'valid' } - }); - } else { - this.setState({ - inputErrors: { contact: 'Please enter a valid email.' } - }); - } - }; - - // Hide or show contact on click // - toggleContact = event => { - this.setState({ - contactVisible: !this.state.contactVisible - }); - }; - - // Show BlockForm in edit mode on click // - toggleEdit = () => { - this.setState({ isEditing: !this.state.isEditing }); - }; - - // Delete FocusBlock event // - delete = () => { - // Trigger update on dashboard by passing comp ID // - this.state.dashboardEvents.delete(this.state.id); - }; - - render() { - // Setup dynamic class using classnames module // - let classNames = require('classnames'); - let classes = classNames('block', { - start: this.state.currentProgress === 'start' && this.state.blockStarted, - mid: this.state.currentProgress === 'mid' && this.state.blockStarted, - end: this.state.currentProgress === 'end' && this.state.blockStarted - }); - - return ( - - {this.state.isEditing ? ( - - ) : ( -
-
-
{this.state.title}
-
{this.state.friendlyTimer}
-
- {this.state.contactVisible ? ( - [ - this.state.contact === '' ? ( - // MAD PROPS Lumie1337 // - - ) : ( - - {this.state.contact} - - ) - ] - ) : ( - // If contact is empty, show input field to add contact // - - Click to show contact. - - )} -
- {this.state.inputErrors.contact !== 'valid' ? ( -
- {this.state.inputErrors.contact} -
- ) : ( - '' - )} -
- -
- Edit focus block pencil button -
-
- )} -
- ); - } -} - -export default FocusBlock; diff --git a/focus-block/src/Components/FocusBlock/styles.css b/focus-block/src/Components/FocusBlock/styles.css deleted file mode 100644 index c17ff18..0000000 --- a/focus-block/src/Components/FocusBlock/styles.css +++ /dev/null @@ -1,109 +0,0 @@ -.block { - width: 40%; - height: 445px; - margin: 2% 2%; - border: 3px solid #979797; - background-color: #fff; - border-radius: 5px; - position: relative; } - .block .block-content { - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; } - .block .block-content .block-title { - font-size: 60px; - font-weight: 300; - margin-bottom: 25px; } - .block .block-content .block-time { - font-size: 80px; } - .block .block-content .block-contact { - font-size: 38px; - font-weight: 300; - margin-bottom: 50px; - cursor: pointer; } - .block .block-content .block-contact .contact-input { - width: 75%; - height: 25px; - border: 0; - border-bottom: 2px #726d6d solid; - margin: 20px auto; - font-size: 16px; } - .block .block-content .block-contact .contact-input:focus { - outline: none; - border-bottom-color: #5aca0e; } - .block .block-content .error-label { - color: red; - font-size: 14px; - text-align: center; - width: 75%; - margin: 10px auto; } - .block .block-content .block-title, - .block .block-content .block-time, - .block .block-content .block-contact { - text-align: center; } - .block .block-content .focus-button { - text-align: center; } - .block .block-content .focus-button button { - height: 50px; - width: 265px; - font-size: 20px; - font-weight: 700; - border: 2px solid #5aca0e; - border-radius: 5px; - cursor: pointer; } - .block .block-content .focus-button button:hover { - background-color: #5aca0e; - color: #fff; - opacity: 0.7; } - .block .block-content .edit { - width: 35px; - height: 35px; - padding: 10px; - position: absolute; - cursor: pointer; - bottom: 0; - right: 0; } - -.transition { - transform: translateX(calc(50% - 280px)); - transition: all 2s; } - -.start { - animation: start-progress 25s infinite; } - -@keyframes start-progress { - 0% { - background-color: #fff; } - 50% { - background-color: #aaf69c; } - 100% { - background-color: #fff; } } - -.mid { - animation: mid-progress 20s infinite; } - -@keyframes mid-progress { - 0% { - background-color: #fff; } - 50% { - background-color: #fcfca8; } - 100% { - background-color: #fff; } } - -.end { - animation: end-progress 15s infinite; } - -@keyframes end-progress { - 0% { - background-color: #fff; } - 50% { - background-color: #fb9595; } - 100% { - background-color: #fff; } } - -@media (max-width: 768px) { - .block { - width: 100%; - max-width: 100%; - margin: 2%; } } diff --git a/focus-block/src/Components/FocusBlock/styles.scss b/focus-block/src/Components/FocusBlock/styles.scss deleted file mode 100644 index d9c8acf..0000000 --- a/focus-block/src/Components/FocusBlock/styles.scss +++ /dev/null @@ -1,142 +0,0 @@ -// Color // -$start-color: #aaf69c; -$mid-color: #fcfca8; -$end-color: #fb9595; - -// KeyFrame Mixin // -@mixin status-keyframe-animation($progress, $status-color, $interval) { - animation: $progress $interval infinite; - - //-- MAD PROPS brutusharvenius--// - @keyframes #{$progress} { - 0% { - background-color: #fff; - } - - 50% { - background-color: $status-color; - } - - 100% { - background-color: #fff; - } - } -} - -.block { - width: 40%; - height: 445px; - margin: 2% 2%; - border: 3px solid #979797; - background-color: #fff; - border-radius: 5px; - position: relative; - - .block-content { - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - - .block-title { - font-size: 60px; - font-weight: 300; - margin-bottom: 25px; - } - - .block-time { - font-size: 80px; - } - - .block-contact { - font-size: 38px; - font-weight: 300; - margin-bottom: 50px; - cursor: pointer; - - .contact-input { - width: 75%; - height: 25px; - border: 0; - border-bottom: 2px #726d6d solid; - margin: 20px auto; - font-size: 16px; - - &:focus { - outline: none; - border-bottom-color: #5aca0e; - } - } - } - - .error-label { - color: red; - font-size: 14px; - text-align: center; - width: 75%; - margin: 10px auto; - } - - .block-title, - .block-time, - .block-contact { - text-align: center; - } - - .focus-button { - text-align: center; - - button { - height: 50px; - width: 265px; - font-size: 20px; - font-weight: 700; - border: 2px solid #5aca0e; - border-radius: 5px; - cursor: pointer; - - &:hover { - background-color: #5aca0e; - color: #fff; - opacity: 0.7; - } - } - } - - .edit { - width: 35px; - height: 35px; - padding: 10px; - position: absolute; - cursor: pointer; - bottom: 0; - right: 0; - } - } -} - -.transition { - // left: 75%; - transform: translateX(calc(50% - 280px)); - transition: all 2s; -} - -.start { - @include status-keyframe-animation(start-progress, $start-color, 25s); -} - -.mid { - @include status-keyframe-animation(mid-progress, $mid-color, 20s); -} - -.end { - @include status-keyframe-animation(end-progress, $end-color, 15s); -} - -@media (max-width: 768px) { - .block { - width: 100%; - max-width: 100%; - margin: 2%; - } -} diff --git a/focus-block/src/Components/Input/Input.js b/focus-block/src/Components/Input/Input.js new file mode 100644 index 0000000..a924809 --- /dev/null +++ b/focus-block/src/Components/Input/Input.js @@ -0,0 +1,65 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const Input = (props) => { + let className = 'input'; + if (props.units) { + className += ' input--has-units'; + } + if (props.hasError) { + className += ' input--has-error'; + } + + return( +
+ + + {props.units &&
{props.units}
} + {(props.hasError || props.hint) && +
+ {(props.hasError && props.errorMessage) ? props.errorMessage : props.hint} +
+ } + {props.suggestions && +
+ {props.suggestions.map((s, key) => + + )} +
+ } +
+ ); +} + +Input.propTypes = { + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + sublabel: PropTypes.string, + placeholder: PropTypes.string, + units: PropTypes.string, + hint: PropTypes.string, + suggestions: PropTypes.array, + suggestionClicked: PropTypes.func, + value: PropTypes.any, + changed: PropTypes.func, + blurred: PropTypes.func, + hasError: PropTypes.bool, + errorMessage: PropTypes.string +}; + +export default Input; \ No newline at end of file diff --git a/focus-block/src/Components/Landing/Landing.js b/focus-block/src/Components/Landing/Landing.js new file mode 100644 index 0000000..cfb1996 --- /dev/null +++ b/focus-block/src/Components/Landing/Landing.js @@ -0,0 +1,107 @@ +import React, { Component, Fragment } from 'react'; +import { Link } from 'react-router-dom'; +import ReactGA from 'react-ga'; + +class Landing extends Component { + render() { + ReactGA.initialize('UA-90746218-3'); + ReactGA.pageview(window.location.pathname); + + return ( + +
+
+
+
+
+
+
+ +
+
+ FocusBlock helps you focus on tasks, and contacts a colleague if you're stuck. +
+
+
+ Launch FocusBlock + +
+
+
+ +
+
Time Yourself
+
+
+ + + + + + +
+
+
+
+
+
+

Set a timeframe for the task you're working on, and get straight to work.

+

FocusBlock will notify you when you're out of time.

+
+
+
+ + +
+
Get Backup
+
+
+ + + + + + +
+
+
+
+
+
+

We don’t know everything and that's okay! Recruit someone’s help through email.

+

Set someone's email address to connect them automatically if you are + having trouble.

+
+
+
+ +
+ Launch FocusBlock +
+ +
+
+
+ +
+
+

FocusBlock is fully open source.

+

Contribute today!

+
+
+
+
+ +
+
+

Developed live on Twitch in 28 days.

+

Check the highlights!

+
+
+
+
+ ); + } +} + +export default Landing; \ No newline at end of file diff --git a/focus-block/src/Components/NewBlockForm/NewBlockForm.js b/focus-block/src/Components/NewBlockForm/NewBlockForm.js new file mode 100644 index 0000000..ce43d77 --- /dev/null +++ b/focus-block/src/Components/NewBlockForm/NewBlockForm.js @@ -0,0 +1,158 @@ +import React, { Component, Fragment } from 'react'; +import Input from '../Input/Input'; + +class NewBlockForm extends Component { + constructor (props) { + super(props); + this.state = { + name: '', + timeLimit: '', + helpEmail: '', + nameIsValid: false, + nameErrorShown: false, + nameErrorMessage: 'Pick a name for this task', + timeLimitIsValid: false, + timeLimitErrorShown: false, + timeLimitErrorMessage: 'Set a time limit for the task', + helpEmailIsValid: true, + helpEmailErrorShown: false, + helpEmailErrorMessage: 'This is not a valid email address' + }; + } + + nameChangeHandler = (event) => { + let nameValue = event.target.value; + let nameIsValid = nameValue.length > 0; + this.setState({ + name: nameValue, + nameIsValid: nameIsValid + }); + } + + nameBlurHandler = (event) => { + this.setState({ + nameErrorShown: !this.state.nameIsValid + }); + } + + timeLimitChangeHandler = (event) => { + let timeLimitValue = event.target.value; + let timeLimitIsValid = event.target.value > 0; + this.setState({ + timeLimit: timeLimitValue, + timeLimitIsValid: timeLimitIsValid + }); + } + + timeLimitSuggestionClickedHandler = (event) => { + let timeLimitValue = event.target.value; + this.setState({ + timeLimit: timeLimitValue, + timeLimitIsValid: true, + timeLimitErrorShown: false + }); + } + + timeLimitBlurHandler = (event) => { + this.setState({ + timeLimitErrorShown: !this.state.timeLimitIsValid + }); + } + + helpEmailChangeHandler = (event) => { + let helpEmailValue = event.target.value; + let validContact = helpEmailValue.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i); + let helpEmailIsValid = helpEmailValue === '' || validContact; + this.setState({ + helpEmail: helpEmailValue, + helpEmailIsValid: helpEmailIsValid + }); + } + + helpEmailBlurHandler = (event) => { + this.setState({ + helpEmailErrorShown: !this.state.helpEmailIsValid + }); + } + + formSubmitHandler = (event) => { + if (this.state.nameIsValid && this.state.timeLimitIsValid && this.state.helpEmailIsValid) { + this.props.submitted({ + name: this.state.name, + timeLimit: this.state.timeLimit, + helpEmail: this.state.helpEmail + }); + } else { + this.setState({ + nameErrorShown: !this.state.nameIsValid, + timeLimitErrorShown: !this.state.timeLimitIsValid, + helpEmailErrorShown: !this.state.helpEmailIsValid + }); + } + } + + render() { + return ( + +
+ + + +
+ +
+
+
+ ); + } +} + +export default NewBlockForm; \ No newline at end of file diff --git a/focus-block/src/Containers/ServiceContainer.js b/focus-block/src/Containers/ServiceContainer.js deleted file mode 100644 index badff6b..0000000 --- a/focus-block/src/Containers/ServiceContainer.js +++ /dev/null @@ -1,69 +0,0 @@ -import { Component } from 'react'; - -/* - This component houses all the service calls needed to connect with the server. -*/ - -class ServiceContainer extends Component { - // POST create new user in DB // - createUser = () => { - return new Promise((resolve, reject) => { - let json = fetch(`${process.env.REACT_APP_API_BASE}/new`, { - credentials: 'omit', - headers: { - 'content-type': 'application/json' - }, - method: 'POST', - mode: 'cors' - }).then(response => { - return response.json(); - }); - - json.then(data => { - if (data) return resolve(data); - return reject('User could not be created.'); - }); - }); - }; - - // GET user based on ID // - getUser = id => { - return new Promise((resolve, reject) => { - //-- MAD PROPS for brutusharvenius -- // - let json = fetch(`${process.env.REACT_APP_API_BASE}/${id}`).then( - response => { - return response.json(); - } - ); - - json.then(data => { - if (data) return resolve(data); - return reject('User was not found'); - }); - }); - }; - - // POST update on user by ID // - updateUser = (id, focusBlocks) => { - return new Promise((resolve, reject) => { - let json = fetch(`${process.env.REACT_APP_API_BASE}/${id}`, { - body: JSON.stringify({ focusBlocks: focusBlocks }), - credentials: 'omit', - headers: { - 'content-type': 'application/json' - }, - method: 'POST', - mode: 'cors' - }).then(response => { - return response.json(); - }); - - json.then(data => { - if (data) return resolve(data); - return reject('User could not be created.'); - }); - }); - }; -} - -export default ServiceContainer; diff --git a/focus-block/src/Website.js b/focus-block/src/Website.js new file mode 100644 index 0000000..88e765d --- /dev/null +++ b/focus-block/src/Website.js @@ -0,0 +1,19 @@ +import React, { Component, Fragment } from 'react'; +import { Switch, Route, withRouter } from 'react-router-dom'; +import Landing from './Components/Landing/Landing'; +import App from './Components/App/App'; + +class Website extends Component { + render() { + return ( + + + + + + + ); + } +} + +export default withRouter(Website); \ No newline at end of file diff --git a/focus-block/src/index.css b/focus-block/src/index.css deleted file mode 100644 index e09d1d3..0000000 --- a/focus-block/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body, -button { - margin: 0; - padding: 0; - - /* MAD PROPS DigitalData & ScopeWebLLC */ - font-family: 'Quicksand', sans-serif; -} - -body { - background: linear-gradient(#f2f4ff, #d4dbf6); - background-attachment: fixed; -} diff --git a/focus-block/src/index.js b/focus-block/src/index.js index c24e83c..8c83efd 100644 --- a/focus-block/src/index.js +++ b/focus-block/src/index.js @@ -1,14 +1,14 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; -import './index.css'; -import App from './App'; +import Website from './Website'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render( - + , document.getElementById('root') ); -registerServiceWorker(); + +registerServiceWorker(); \ No newline at end of file