├── .gitignore ├── .prettierignore ├── .prettierrc ├── README.md ├── gatsby-browser.js ├── gatsby-config.js ├── gatsby-node.js ├── gatsby-ssr.js ├── package-lock.json ├── package.json ├── src ├── api │ ├── exercises-list.js │ └── exercises.js ├── assets │ ├── KOMIKAX_-webfont.woff │ ├── Lemiesz-webfont.woff │ ├── Mitr-SemiBold-webfont.woff │ ├── alert.mp3 │ ├── alert.wav │ ├── fire.svg │ ├── product.png │ ├── success.svg │ └── yoga.svg ├── components │ ├── exercise.js │ └── navbar.js ├── images │ ├── 1487587.svg │ ├── audio.svg │ ├── audio1.svg │ ├── bicyclecrunches.gif │ ├── burpees.gif │ ├── buttkicks.gif │ ├── calfraises.gif │ ├── crunches.gif │ ├── flutterkicks.gif │ ├── gatsby-astronaut.png │ ├── gatsby-icon.png │ ├── glutebridges.gif │ ├── highknees.gif │ ├── jumping.gif │ ├── jumplunges.gif │ ├── jumpsquats.gif │ ├── lunges.gif │ ├── mountainclimbers.gif │ ├── mute.svg │ ├── planks.gif │ ├── pullups.gif │ ├── pushup.gif │ ├── search.svg │ ├── sidelunges.gif │ ├── situps.gif │ ├── spinalbalance.gif │ ├── squats.gif │ ├── stairstepping.gif │ ├── success.svg │ ├── supermanraises.gif │ └── tricepdips.gif ├── pages │ ├── 404.js │ ├── custom.js │ ├── exercise.js │ ├── home.js │ ├── index.css │ ├── index.js │ └── success.js └── styles │ └── style.css └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | package-lock.json 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | package-lock.json 40 | 41 | 42 | # Typescript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # gatsby files 61 | .cache/ 62 | public 63 | 64 | # Mac files 65 | .DS_Store 66 | 67 | # Yarn 68 | yarn-error.log 69 | .pnp/ 70 | .pnp.js 71 | # Yarn Integrity file 72 | .yarn-integrity 73 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "none", 8 | "bracketSpacing": true, 9 | "arrowParens": "avoid", 10 | "endOfLine": "lf" 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # brogrammers 2 | 💪🏼 Challenge your body while programming 3 | 4 | 5 | ![](https://i.imgur.com/vLJYD3a.png) 6 | 7 | ## Brogrammer 8 | 9 | Brogrammer is simple way to help people with sedentary office jobs maintain a fitter lifestyle. Brogrammer is for the busy bees. It lets you easily squeeze mini workouts in your busy schedule and keep your body moving, even if you don't have time to go to the gym. 10 | 11 | ## Screenshots 12 | ![](https://i.imgur.com/ItzWzpR.gif) 13 | ![](https://i.imgur.com/kuNDeqX.gif) 14 | ![](https://i.imgur.com/jCSKwSb.gif) 15 | 16 | ## Prerequisites 17 | 18 | Before running this locally you must have these installed. 19 | 20 | - Node 21 | 22 | ## Installing 23 | 24 | ``` 25 | $ npm install 26 | $ npm start 27 | ``` 28 | 29 | ## Development 30 | 31 | It's really easy, just follow these steps below 32 | 33 | ```sh 34 | $ git clone https://github.com/sarthology/brogrammers.git 35 | $ cd brogrammers 36 | $ npm install 37 | ``` 38 | 39 | Now to run Brogrammer, you can do `npm start`. 40 | 41 | That's it. 42 | 43 | ## Contributing 44 | 45 | Feel free to contribute to this project and treat it like your own. 😊 46 | 47 | ## License 48 | 49 | MIT License 50 | 51 | ## Author 52 | 53 | [Sarthak Sharma](https://twitter.com/sarthology) 54 | 55 | ## Acknowledgments 56 | 57 | Graphics used from [icons8](https://icons8.com). 58 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Browser APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/browser-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | pathPrefix: '/brogrammers', 3 | siteMetadata: { 4 | title: `Brogrammers`, 5 | description: `Challenge your body while programming`, 6 | author: `@sarthology` 7 | }, 8 | plugins: [ 9 | `gatsby-plugin-react-helmet`, 10 | { 11 | resolve: `gatsby-source-filesystem`, 12 | options: { 13 | name: `images`, 14 | path: `${__dirname}/src/images` 15 | } 16 | }, 17 | `gatsby-transformer-sharp`, 18 | `gatsby-plugin-sharp`, 19 | { 20 | resolve: `gatsby-plugin-manifest`, 21 | options: { 22 | name: `Brogrammers`, 23 | short_name: `Brogrammers`, 24 | start_url: `/`, 25 | background_color: `#663399`, 26 | theme_color: `#663399`, 27 | display: `minimal-ui`, 28 | icon: `src/images/gatsby-icon.png` // This path is relative to the root of the site. 29 | } 30 | }, 31 | { 32 | resolve: `gatsby-plugin-google-analytics`, 33 | options: { 34 | trackingId: 'G-0RGXLG2YCP' 35 | } 36 | } 37 | // this (optional) plugin enables Progressive Web App + Offline functionality 38 | // To learn more, visit: https://gatsby.dev/offline 39 | // `gatsby-plugin-offline`, 40 | ] 41 | }; -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Node APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/node-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-default", 3 | "private": true, 4 | "description": "A simple starter to get up and developing quickly with Gatsby", 5 | "version": "0.1.0", 6 | "author": "Kyle Mathews ", 7 | "dependencies": { 8 | "easytimer.js": "^4.0.1", 9 | "gatsby": "^2.13.73", 10 | "gatsby-image": "^2.2.10", 11 | "gatsby-plugin-google-analytics": "^3.1.0", 12 | "gatsby-plugin-manifest": "^2.2.6", 13 | "gatsby-plugin-offline": "^2.2.7", 14 | "gatsby-plugin-react-helmet": "^3.1.4", 15 | "gatsby-plugin-sharp": "^2.2.13", 16 | "gatsby-source-filesystem": "^2.1.11", 17 | "gatsby-transformer-sharp": "^2.2.7", 18 | "prop-types": "^15.7.2", 19 | "query-string": "^6.8.2", 20 | "react": "^16.9.0", 21 | "react-dom": "^16.9.0", 22 | "react-helmet": "^5.2.1", 23 | "react-input-range": "^1.3.0" 24 | }, 25 | "devDependencies": { 26 | "gh-pages": "^2.1.1", 27 | "prettier": "^1.18.2" 28 | }, 29 | "keywords": [ 30 | "gatsby" 31 | ], 32 | "license": "MIT", 33 | "scripts": { 34 | "build": "gatsby build", 35 | "develop": "gatsby develop", 36 | "format": "prettier --write \"**/*.{js,jsx,json,md}\"", 37 | "deploy": "gatsby build --prefix-paths && gh-pages -d public", 38 | "start": "npm run develop", 39 | "serve": "gatsby serve", 40 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing \"" 41 | }, 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/gatsbyjs/gatsby-starter-default" 45 | }, 46 | "bugs": { 47 | "url": "https://github.com/gatsbyjs/gatsby/issues" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/api/exercises-list.js: -------------------------------------------------------------------------------- 1 | const ExercisesList = [ 2 | 'Bicycle Crunches', 3 | 'Burpees', 4 | 'Butt Kicks', 5 | 'Calf Raises', 6 | 'Crunches', 7 | 'Flutter Kicks', 8 | 'Glute Bridges', 9 | 'High Knees', 10 | 'Jumping', 11 | 'Jump Lunges', 12 | 'Jump Squats', 13 | 'Lunges', 14 | 'Mountain Climber', 15 | 'Planks', 16 | 'Pullups', 17 | 'Pushups', 18 | 'Side Lunges', 19 | 'Situps', 20 | 'Spinal Balance', 21 | 'Squats', 22 | 'Stair Stepping', 23 | 'Superman Raises', 24 | 'Tricep Dips' 25 | ]; 26 | 27 | export default ExercisesList; 28 | -------------------------------------------------------------------------------- /src/api/exercises.js: -------------------------------------------------------------------------------- 1 | const Exercises = { 2 | 'Bicycle Crunches': { 3 | gif: 4 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/bicyclecrunches.gif', 5 | reps: { 6 | easy: 10, 7 | medium: 15, 8 | hard: 20 9 | }, 10 | duration: { 11 | easy: 0, 12 | medium: 0, 13 | hard: 0 14 | } 15 | }, 16 | 17 | Burpees: { 18 | gif: 19 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/burpees.gif', 20 | reps: { 21 | easy: 7, 22 | medium: 12, 23 | hard: 18 24 | }, 25 | duration: { 26 | easy: 0, 27 | medium: 0, 28 | hard: 0 29 | } 30 | }, 31 | 32 | 'Butt Kicks': { 33 | gif: 34 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/buttkicks.gif', 35 | duration: { 36 | easy: 30, 37 | medium: 60, 38 | hard: 90 39 | }, 40 | reps: { 41 | easy: 0, 42 | medium: 0, 43 | hard: 0 44 | } 45 | }, 46 | 47 | 'Calf Raises': { 48 | gif: 49 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/calfraises.gif', 50 | reps: { 51 | easy: 10, 52 | medium: 15, 53 | hard: 25 54 | }, 55 | duration: { 56 | easy: 0, 57 | medium: 0, 58 | hard: 0 59 | } 60 | }, 61 | 62 | Crunches: { 63 | gif: 64 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/crunches.gif', 65 | reps: { 66 | easy: 10, 67 | medium: 20, 68 | hard: 30 69 | }, 70 | duration: { 71 | easy: 0, 72 | medium: 0, 73 | hard: 0 74 | } 75 | }, 76 | 77 | 'Flutter Kicks': { 78 | gif: 79 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/flutterkicks.gif', 80 | duration: { 81 | easy: 20, 82 | medium: 30, 83 | hard: 45 84 | }, 85 | reps: { 86 | easy: 0, 87 | medium: 0, 88 | hard: 0 89 | } 90 | }, 91 | 92 | 'Glute Bridges': { 93 | gif: 94 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/glutebridges.gif', 95 | reps: { 96 | easy: 7, 97 | medium: 12, 98 | hard: 15 99 | }, 100 | duration: { 101 | easy: 0, 102 | medium: 0, 103 | hard: 0 104 | } 105 | }, 106 | 107 | 'High Knees': { 108 | gif: 109 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/highknees.gif', 110 | reps: { 111 | easy: 0, 112 | medium: 0, 113 | hard: 0 114 | }, 115 | duration: { 116 | easy: 100, 117 | medium: 200, 118 | hard: 300 119 | } 120 | }, 121 | 122 | Jumping: { 123 | gif: 124 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/jumping.gif', 125 | duration: { 126 | easy: 30, 127 | medium: 60, 128 | hard: 90 129 | }, 130 | reps: { 131 | easy: 0, 132 | medium: 0, 133 | hard: 0 134 | } 135 | }, 136 | 137 | 'Jump Lunges': { 138 | gif: 139 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/jumplunges.gif', 140 | duration: { 141 | easy: 20, 142 | medium: 30, 143 | hard: 60 144 | }, 145 | reps: { 146 | easy: 0, 147 | medium: 0, 148 | hard: 0 149 | } 150 | }, 151 | 152 | 'Jump Squats': { 153 | gif: 154 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/jumpsquats.gif', 155 | reps: { 156 | easy: 10, 157 | medium: 15, 158 | hard: 20 159 | }, 160 | duration: { 161 | easy: 0, 162 | medium: 0, 163 | hard: 0 164 | } 165 | }, 166 | 167 | Lunges: { 168 | gif: 169 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/lunges.gif', 170 | reps: { 171 | easy: 12, 172 | medium: 18, 173 | hard: 22 174 | }, 175 | duration: { 176 | easy: 0, 177 | medium: 0, 178 | hard: 0 179 | } 180 | }, 181 | 182 | 'Mountain Climber': { 183 | gif: 184 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/mountainclimbers.gif', 185 | duration: { 186 | easy: 20, 187 | medium: 30, 188 | hard: 60 189 | }, 190 | reps: { 191 | easy: 0, 192 | medium: 0, 193 | hard: 0 194 | } 195 | }, 196 | 197 | Planks: { 198 | gif: 199 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/planks.gif', 200 | duration: { 201 | easy: 30, 202 | medium: 60, 203 | hard: 90 204 | }, 205 | reps: { 206 | easy: 0, 207 | medium: 0, 208 | hard: 0 209 | } 210 | }, 211 | 212 | Pullups: { 213 | gif: 214 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/pullups.gif', 215 | reps: { 216 | easy: 5, 217 | medium: 10, 218 | hard: 15 219 | }, 220 | duration: { 221 | easy: 0, 222 | medium: 0, 223 | hard: 0 224 | } 225 | }, 226 | 227 | Pushups: { 228 | gif: 229 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/pushup.gif', 230 | reps: { 231 | easy: 10, 232 | medium: 20, 233 | hard: 30 234 | }, 235 | duration: { 236 | easy: 0, 237 | medium: 0, 238 | hard: 0 239 | } 240 | }, 241 | 242 | 'Side Lunges': { 243 | gif: 244 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/sidelunges.gif', 245 | reps: { 246 | easy: 10, 247 | medium: 15, 248 | hard: 20 249 | }, 250 | duration: { 251 | easy: 0, 252 | medium: 0, 253 | hard: 0 254 | } 255 | }, 256 | 257 | Situps: { 258 | gif: 259 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/situps.gif', 260 | reps: { 261 | easy: 10, 262 | medium: 15, 263 | hard: 20 264 | }, 265 | duration: { 266 | easy: 0, 267 | medium: 0, 268 | hard: 0 269 | } 270 | }, 271 | 272 | 'Spinal Balance': { 273 | gif: 274 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/spinalbalance.gif', 275 | reps: { 276 | easy: 10, 277 | medium: 20, 278 | hard: 30 279 | }, 280 | duration: { 281 | easy: 0, 282 | medium: 0, 283 | hard: 0 284 | } 285 | }, 286 | 287 | Squats: { 288 | gif: 289 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/squats.gif', 290 | reps: { 291 | easy: 7, 292 | medium: 15, 293 | hard: 22 294 | }, 295 | duration: { 296 | easy: 0, 297 | medium: 0, 298 | hard: 0 299 | } 300 | }, 301 | 302 | 'Stair Stepping': { 303 | gif: 304 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/stairstepping.gif', 305 | reps: { 306 | easy: 60, 307 | medium: 120, 308 | hard: 200 309 | }, 310 | duration: { 311 | easy: 0, 312 | medium: 0, 313 | hard: 0 314 | } 315 | }, 316 | 317 | 'Superman Raises': { 318 | gif: 319 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/supermanraises.gif', 320 | reps: { 321 | easy: 12, 322 | medium: 18, 323 | hard: 22 324 | }, 325 | duration: { 326 | easy: 0, 327 | medium: 0, 328 | hard: 0 329 | } 330 | }, 331 | 332 | 'Tricep Dips': { 333 | gif: 334 | 'https://raw.githubusercontent.com/sarthology/brogrammers/master/src/images/tricepdips.gif', 335 | reps: { 336 | easy: 10, 337 | medium: 15, 338 | hard: 20 339 | }, 340 | duration: { 341 | easy: 0, 342 | medium: 0, 343 | hard: 0 344 | } 345 | } 346 | }; 347 | 348 | export default Exercises; 349 | -------------------------------------------------------------------------------- /src/assets/KOMIKAX_-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/assets/KOMIKAX_-webfont.woff -------------------------------------------------------------------------------- /src/assets/Lemiesz-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/assets/Lemiesz-webfont.woff -------------------------------------------------------------------------------- /src/assets/Mitr-SemiBold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/assets/Mitr-SemiBold-webfont.woff -------------------------------------------------------------------------------- /src/assets/alert.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/assets/alert.mp3 -------------------------------------------------------------------------------- /src/assets/alert.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/assets/alert.wav -------------------------------------------------------------------------------- /src/assets/fire.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 12 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/assets/product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/assets/product.png -------------------------------------------------------------------------------- /src/assets/success.svg: -------------------------------------------------------------------------------- 1 | downloading -------------------------------------------------------------------------------- /src/components/exercise.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Exercise = props => ( 4 | <> 5 |
6 | 7 |
8 |
9 | {props.reps && ( 10 |
11 |

12 | Reps: 13 | {props.reps} 14 |

15 |
16 | )} 17 | {props.time && ( 18 |
19 |

20 | Duration: 21 | {props.time} 22 |

23 |
24 | )} 25 |
26 | 27 | ); 28 | 29 | export default Exercise; 30 | -------------------------------------------------------------------------------- /src/components/navbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'gatsby'; 3 | import yoga from '../assets/yoga.svg'; 4 | import audio from '../images/audio.svg'; 5 | import audio1 from '../images/audio1.svg'; 6 | 7 | const Navbar = props => ( 8 |
9 | 10 | 11 | 12 |

Brogrammer

13 | {props.isTabActive ? ( 14 | 15 | ) : ( 16 | 17 | )} 18 |
19 | ); 20 | 21 | export default Navbar; 22 | -------------------------------------------------------------------------------- /src/images/1487587.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/audio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/images/audio1.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 40 | 48 | 56 | 64 | -------------------------------------------------------------------------------- /src/images/bicyclecrunches.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/bicyclecrunches.gif -------------------------------------------------------------------------------- /src/images/burpees.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/burpees.gif -------------------------------------------------------------------------------- /src/images/buttkicks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/buttkicks.gif -------------------------------------------------------------------------------- /src/images/calfraises.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/calfraises.gif -------------------------------------------------------------------------------- /src/images/crunches.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/crunches.gif -------------------------------------------------------------------------------- /src/images/flutterkicks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/flutterkicks.gif -------------------------------------------------------------------------------- /src/images/gatsby-astronaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/gatsby-astronaut.png -------------------------------------------------------------------------------- /src/images/gatsby-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/gatsby-icon.png -------------------------------------------------------------------------------- /src/images/glutebridges.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/glutebridges.gif -------------------------------------------------------------------------------- /src/images/highknees.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/highknees.gif -------------------------------------------------------------------------------- /src/images/jumping.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/jumping.gif -------------------------------------------------------------------------------- /src/images/jumplunges.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/jumplunges.gif -------------------------------------------------------------------------------- /src/images/jumpsquats.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/jumpsquats.gif -------------------------------------------------------------------------------- /src/images/lunges.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/lunges.gif -------------------------------------------------------------------------------- /src/images/mountainclimbers.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/mountainclimbers.gif -------------------------------------------------------------------------------- /src/images/mute.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/images/planks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/planks.gif -------------------------------------------------------------------------------- /src/images/pullups.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/pullups.gif -------------------------------------------------------------------------------- /src/images/pushup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/pushup.gif -------------------------------------------------------------------------------- /src/images/search.svg: -------------------------------------------------------------------------------- 1 | Logged out_openSpace -------------------------------------------------------------------------------- /src/images/sidelunges.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/sidelunges.gif -------------------------------------------------------------------------------- /src/images/situps.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/situps.gif -------------------------------------------------------------------------------- /src/images/spinalbalance.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/spinalbalance.gif -------------------------------------------------------------------------------- /src/images/squats.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/squats.gif -------------------------------------------------------------------------------- /src/images/stairstepping.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/stairstepping.gif -------------------------------------------------------------------------------- /src/images/supermanraises.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/supermanraises.gif -------------------------------------------------------------------------------- /src/images/tricepdips.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarthology/brogrammers/eeba16feaf19980187fee4cfff97bc53059062ec/src/images/tricepdips.gif -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const NotFoundPage = () => ( 4 | <> 5 |

NOT FOUND

6 |

You just hit a route that doesn't exist... the sadness.

7 | 8 | ); 9 | 10 | export default NotFoundPage; 11 | -------------------------------------------------------------------------------- /src/pages/custom.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { navigate } from 'gatsby'; 3 | import NavBar from '../components/navbar'; 4 | import InputRange from 'react-input-range'; 5 | import exercises from '../api/exercises-list'; 6 | import 'react-input-range/lib/css/index.css'; 7 | import './index.css'; 8 | 9 | // if (typeof window !== 'undefined') { 10 | // const InputRange = require('react-input-range'); 11 | // } 12 | 13 | class CustomPage extends Component { 14 | constructor(props) { 15 | super(props); 16 | const customData = 17 | typeof window !== 'undefined' 18 | ? JSON.parse(localStorage.getItem('customData')) 19 | : {}; 20 | 21 | this.state = { 22 | frequency: customData && customData.frequency ? customData.frequency : 2, 23 | work: customData && customData.work ? customData.work : 3, 24 | level: customData && customData.level ? customData.level : '', 25 | selectedExercises: 26 | customData && customData.selectedExercises 27 | ? customData.selectedExercises 28 | : [] 29 | }; 30 | } 31 | componentDidMount() { 32 | this.state.selectedExercises.forEach((selectEx) => { 33 | const index = exercises.findIndex((exercise) => exercise === selectEx); 34 | document.getElementById(`${index}${selectEx}`).className = "choice selected-exercise"; 35 | }); 36 | if (typeof window !== 'undefined') { 37 | const customData = JSON.parse(localStorage.getItem('customData')); 38 | if (customData) { 39 | if (typeof window !== 'undefined') { 40 | document.getElementById(customData.level).checked = true; 41 | } 42 | } 43 | } 44 | } 45 | 46 | selectExercise = (exercise, index) => { 47 | // console.log( `${index}${exercise}`); 48 | if (this.state.selectedExercises.indexOf(exercise) === -1) { 49 | let exercises = this.state.selectedExercises; 50 | exercises.push(exercise); 51 | this.setState({ 52 | selectedExercises: exercises 53 | }); 54 | 55 | if (typeof window !== 'undefined') { 56 | document.getElementById(`${index}${exercise}`).className = 57 | 'choice selected-exercise'; 58 | } 59 | } else { 60 | let exercises = this.state.selectedExercises; 61 | // exercises.push(exercise); 62 | exercises.splice(this.state.selectedExercises.indexOf(exercise), 1); 63 | this.setState({ 64 | selectedExercises: exercises 65 | }); 66 | 67 | if (typeof window !== 'undefined') { 68 | document.getElementById(`${index}${exercise}`).className = 'choice'; 69 | } 70 | } 71 | }; 72 | 73 | selectLevel = level => { 74 | this.setState({ 75 | level: level 76 | }); 77 | 78 | if (typeof window !== 'undefined') { 79 | if (level === 'easy') { 80 | document.getElementById('medium').checked = false; 81 | document.getElementById('hard').checked = false; 82 | } else if (level === 'medium') { 83 | document.getElementById('easy').checked = false; 84 | document.getElementById('hard').checked = false; 85 | } else { 86 | document.getElementById('easy').checked = false; 87 | document.getElementById('medium').checked = false; 88 | } 89 | } 90 | }; 91 | 92 | saveCustomData = () => { 93 | if (typeof window !== 'undefined') { 94 | const { frequency, work, level } = this.state; 95 | if ( 96 | this.state.selectedExercises.length > 0 && 97 | frequency && 98 | work && 99 | level 100 | ) { 101 | localStorage.setItem( 102 | 'customData', 103 | JSON.stringify({ 104 | frequency, 105 | work, 106 | level, 107 | selectedExercises: this.state.selectedExercises, 108 | startExercise: 1 109 | }) 110 | ); 111 | navigate('/home?customData=true'); 112 | } 113 | } 114 | }; 115 | 116 | render() { 117 | return ( 118 | <> 119 | 120 |
121 |
122 | 123 |
    124 | {exercises.map((exercise, index) => { 125 | return ( 126 |
  • this.selectExercise(exercise, index)} 131 | > 132 | {exercise} 133 |
  • 134 | ); 135 | })} 136 |
137 |
138 | {typeof window !== 'undefined' && ( 139 |
140 |
141 | 142 | this.setState({ frequency: value })} 147 | /> 148 |
149 |
150 | 151 | this.setState({ work: value })} 156 | /> 157 |
158 |
159 | )} 160 |
161 | 162 |
163 |
164 | this.selectLevel('easy')} 169 | /> 170 | 171 |
172 |
173 | this.selectLevel('medium')} 178 | /> 179 | 180 |
181 |
182 | this.selectLevel('hard')} 187 | /> 188 | 191 |
192 |
193 |
194 |
195 |
199 | Start Custom Session 200 |
201 |
202 |
203 | 204 | ); 205 | } 206 | } 207 | 208 | export default CustomPage; 209 | -------------------------------------------------------------------------------- /src/pages/exercise.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useLayoutEffect } from 'react'; 2 | import { navigate } from 'gatsby'; 3 | import queryString from 'query-string'; 4 | import { Timer } from 'easytimer.js'; 5 | import NavBar from '../components/navbar'; 6 | import Exercise from '../components/exercise'; 7 | import ExercisesData from '../api/exercises'; 8 | import ExercisesList from '../api/exercises-list'; 9 | import './index.css'; 10 | 11 | import alertAudioFile from '../assets/alert.wav'; 12 | 13 | const ExercisePage = () => { 14 | const query = 15 | typeof window !== 'undefined' 16 | ? queryString.parse(document.location.search) 17 | : ''; 18 | 19 | const audioFile = 20 | typeof window !== 'undefined' ? new Audio(alertAudioFile) : null; 21 | 22 | const [time, setTime] = useState(null); 23 | const [start, setStart] = useState(false); 24 | const [randomNumber, setRandomNumber] = useState(null); 25 | const [randomExercise, setRandomExercise] = useState(null); 26 | const [exerciseName, setExerciseName] = useState(null); 27 | const [isActive, setIsActive] = useState(false); 28 | const [difficulty, setDifficulty] = useState(null); 29 | 30 | const [timer] = useState(new Timer()); 31 | const [alarm] = useState(audioFile); 32 | 33 | const handleStartExercise = e => { 34 | e.preventDefault(); 35 | 36 | if (typeof window !== 'undefined') { 37 | alarm.pause(); 38 | setIsActive(true); 39 | } 40 | 41 | if (start) { 42 | timer.pause(); 43 | } 44 | 45 | setStart(!start); 46 | 47 | if (randomExercise && randomExercise.reps && start) { 48 | setTime(null); 49 | localStorage.removeItem('random'); 50 | if (query && query.customData) { 51 | navigate('/success?customData=true'); 52 | } else navigate('/success'); 53 | } 54 | }; 55 | 56 | const handlePauseAlarm = e => { 57 | e.preventDefault(); 58 | 59 | if (typeof window !== 'undefined') { 60 | alarm.pause(); 61 | setIsActive(true); 62 | } 63 | }; 64 | 65 | useLayoutEffect(() => { 66 | let t; 67 | const visibility = 68 | typeof window !== 'undefined' 69 | ? document.visibilityState === 'hidden' 70 | : false; 71 | 72 | if (visibility && !isActive && alarm !== null) { 73 | t = setInterval(() => { 74 | alarm.play(); 75 | }, 3000); 76 | } 77 | 78 | return () => clearInterval(t); 79 | }, [alarm, isActive]); 80 | 81 | useEffect(() => { 82 | const getLocalData = item => { 83 | const localData = localStorage.getItem('customData'); 84 | const data = 85 | localData && JSON.parse(localData)[item] 86 | ? JSON.parse(localData)[item] 87 | : null; 88 | 89 | return data; 90 | }; 91 | 92 | const getRandom = arrayLength => { 93 | const random = localStorage.getItem('random') 94 | ? localStorage.getItem('random') 95 | : localStorage.setItem( 96 | 'random', 97 | Math.floor(Math.random() * arrayLength) 98 | ); 99 | 100 | return random; 101 | }; 102 | 103 | const selectedExercises = getLocalData('selectedExercises'); 104 | 105 | if (query && query.customData && selectedExercises.length) { 106 | if (selectedExercises.length < randomNumber) { 107 | localStorage.removeItem('random'); 108 | } 109 | 110 | setRandomNumber(getRandom(selectedExercises.length)); 111 | setRandomExercise(ExercisesData[selectedExercises[randomNumber]]); 112 | setExerciseName(selectedExercises[randomNumber]); 113 | setDifficulty(getLocalData('level')); 114 | } else { 115 | setRandomNumber(getRandom(ExercisesList.length)); 116 | setRandomExercise(ExercisesData[ExercisesList[randomNumber]]); 117 | setExerciseName(ExercisesList[randomNumber]); 118 | setDifficulty('easy'); 119 | } 120 | 121 | // setRandomExercise(exercises[0]); 122 | }, [randomNumber, randomExercise, exerciseName]); 123 | 124 | useEffect(() => { 125 | if ( 126 | randomExercise && 127 | randomExercise.duration && 128 | randomExercise.duration['easy'] !== 0 && 129 | start 130 | ) { 131 | timer.start({ 132 | countdown: true, 133 | startValues: { seconds: randomExercise.duration[difficulty] } 134 | }); 135 | 136 | timer.addEventListener('secondsUpdated', function(e) { 137 | setTime(timer.getTimeValues().toString()); 138 | }); 139 | 140 | timer.addEventListener('targetAchieved', function(e) { 141 | alarm.play(); 142 | setTimeout(() => { 143 | setTime(null); 144 | localStorage.removeItem('random'); 145 | if (query && query.customData) { 146 | navigate('/success?customData=true'); 147 | } else navigate('/success'); 148 | }, 3000); 149 | }); 150 | } else if (randomExercise && randomExercise.reps && start) { 151 | timer.start(); 152 | 153 | timer.addEventListener('secondsUpdated', function(e) { 154 | setTime(timer.getTimeValues().toString()); 155 | }); 156 | } 157 | }, [randomExercise, start, timer, difficulty, alarm]); 158 | 159 | return ( 160 | <> 161 | 162 |
163 |
164 |

Go kill it, you beast

165 | {exerciseName &&

{exerciseName}

} 166 |
167 | {randomExercise && ( 168 | 183 | )} 184 |
185 |
186 | {start ? 'Stop Exercise Now!!' : 'Start Exercise Now!!'} 187 |
188 |
189 |
190 | 191 | ); 192 | }; 193 | 194 | export default ExercisePage; 195 | -------------------------------------------------------------------------------- /src/pages/home.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { navigate } from 'gatsby'; 3 | import { Timer } from 'easytimer.js'; 4 | import NavBar from '../components/navbar'; 5 | import search from '../images/search.svg'; 6 | import './index.css'; 7 | import queryString from 'query-string'; 8 | 9 | const HomePage = () => { 10 | const [time, setTime] = useState(null); 11 | 12 | const handleSkipTimer = e => { 13 | e.preventDefault(); 14 | 15 | let query = queryString.parse(document.location.search); 16 | if (query && query.customData) { 17 | navigate('/exercise?customData=true'); 18 | } else navigate('/exercise'); 19 | }; 20 | 21 | useEffect(() => { 22 | let query = queryString.parse(document.location.search); 23 | let customSeconds; 24 | if (query && query.customData) { 25 | let customData = JSON.parse(localStorage.getItem('customData')); 26 | if (customData.startExercise * customData.frequency <= customData.work) { 27 | customSeconds = 3600 * customData['frequency']; 28 | } else { 29 | navigate('/'); 30 | } 31 | } 32 | if (query && query.createRandom) { 33 | const randomMinutes = Math.floor(Math.random() * 21) + 40; 34 | customSeconds = 60 * randomMinutes; 35 | } 36 | 37 | const timer = new Timer(); 38 | 39 | timer.start({ 40 | countdown: true, 41 | startValues: { seconds: customSeconds ? customSeconds : 10 } 42 | }); 43 | 44 | timer.addEventListener('secondsUpdated', function(e) { 45 | setTime(timer.getTimeValues().toString()); 46 | }); 47 | 48 | timer.addEventListener('targetAchieved', function(e) { 49 | setTime(null); 50 | if (query && query.customData) { 51 | navigate('/exercise?customData=true'); 52 | } else navigate('/exercise'); 53 | }); 54 | }, []); 55 | 56 | return ( 57 | <> 58 | 59 | 75 | 76 | ); 77 | }; 78 | 79 | export default HomePage; 80 | -------------------------------------------------------------------------------- /src/pages/index.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'komikax'; 3 | src: url('../assets/KOMIKAX_-webfont.woff') format('woff'); 4 | font-weight: normal; 5 | font-style: normal; 6 | } 7 | 8 | .head { 9 | display: grid; 10 | /* grid-template-columns: 1fr 2fr; */ 11 | width: 40%; 12 | margin: 0 auto; 13 | font-family: sans-serif; 14 | text-align: center; 15 | } 16 | 17 | body { 18 | font-family: sans-serif; 19 | } 20 | 21 | .head img { 22 | width: 100px; 23 | margin: 0 auto; 24 | } 25 | 26 | .nav h1 { 27 | color: #173947; 28 | font-family: komikax; 29 | font-weight: bolder; 30 | letter-spacing: 2px; 31 | font-size: 40px; 32 | text-align: center; 33 | } 34 | 35 | .head h1 { 36 | display: grid; 37 | align-content: center; 38 | } 39 | 40 | .content-center { 41 | width: 70%; 42 | margin: 0 auto; 43 | } 44 | 45 | .start { 46 | margin-top: 50px; 47 | } 48 | 49 | .button-start { 50 | width: 40%; 51 | margin: 15px auto; 52 | text-align: center; 53 | padding: 10px; 54 | color: white; 55 | background: #2c67ee; 56 | font-weight: 100; 57 | cursor: pointer; 58 | } 59 | 60 | .exercise h2 { 61 | text-align: center; 62 | font-weight: 100; 63 | } 64 | 65 | .exercise img { 66 | max-height: 300px; 67 | margin: 0 auto; 68 | } 69 | 70 | .exercise { 71 | display: grid; 72 | } 73 | 74 | audio { 75 | display: none; 76 | } 77 | 78 | .logo img { 79 | width: 350px; 80 | } 81 | .success img { 82 | width: 250px; 83 | } 84 | .logo, 85 | .action, 86 | .success { 87 | margin: 0 auto; 88 | justify-content: center; 89 | display: grid; 90 | } 91 | 92 | .custom, 93 | .create, 94 | .start-exercise, 95 | .success-button { 96 | text-align: center; 97 | border: 2px solid #173947; 98 | margin-left: 10px; 99 | padding: 20px; 100 | font-family: komikax; 101 | font-weight: lighter; 102 | color: #173947; 103 | cursor: pointer; 104 | } 105 | 106 | .create, 107 | .custom-session { 108 | background: #e56166; 109 | border-color: #e56166; 110 | color: white; 111 | } 112 | 113 | .custom a { 114 | color: inherit; 115 | text-decoration: none; 116 | } 117 | 118 | .create a { 119 | color: inherit; 120 | text-decoration: none; 121 | } 122 | 123 | .start-button { 124 | display: grid; 125 | grid-template-columns: 1fr 1fr; 126 | margin: 0 auto; 127 | width: 50%; 128 | margin-top: 40px; 129 | } 130 | 131 | .navbar { 132 | display: grid; 133 | grid-template-columns: 1fr 1fr 1fr; 134 | } 135 | 136 | .icon { 137 | width: 80px; 138 | } 139 | 140 | .selected-exercise { 141 | background: #389cae; 142 | color: white !important; 143 | } 144 | 145 | .navbar h1 { 146 | margin: 10px; 147 | font-family: komikax; 148 | align-self: center; 149 | color: #173947; 150 | text-align: center; 151 | } 152 | 153 | .f-audio { 154 | width: 30px; 155 | align-self: center; 156 | justify-self: end; 157 | margin: 0 20px; 158 | cursor: pointer; 159 | } 160 | 161 | .search-image { 162 | display: grid; 163 | justify-content: center; 164 | } 165 | 166 | .search-image img { 167 | width: 350px; 168 | } 169 | 170 | .search-area { 171 | margin-top: 100px; 172 | } 173 | 174 | .search-message, 175 | .timer, 176 | .exercise-message, 177 | .success-message { 178 | margin-top: 30px; 179 | text-align: center; 180 | color: #173947; 181 | font-family: komikax; 182 | font-weight: 100; 183 | } 184 | .exercise-gif { 185 | display: grid; 186 | justify-content: center; 187 | margin-top: 20px; 188 | } 189 | .exercise-gif img { 190 | width: 480px; 191 | height: 250px; 192 | } 193 | 194 | .exercise-message, 195 | .success-message { 196 | color: #e56166; 197 | } 198 | 199 | .exercise-info { 200 | display: grid; 201 | width: 40%; 202 | margin: 20px auto; 203 | text-align: center; 204 | font-family: komikax; 205 | } 206 | 207 | .exercise-info h3 { 208 | margin: 0; 209 | color: #f0bc08; 210 | letter-spacing: 1px; 211 | font-weight: 100; 212 | } 213 | 214 | .exercise-info span { 215 | color: #389cae; 216 | } 217 | .exercise-name { 218 | font-size: 1.4em; 219 | text-align: center; 220 | color: #173947; 221 | font-weight: 400; 222 | font-family: komikax; 223 | } 224 | .big-form { 225 | display: grid; 226 | margin: 10px auto; 227 | width: 80%; 228 | } 229 | 230 | .f-section { 231 | display: grid; 232 | margin: 5px 0; 233 | } 234 | 235 | .f-section label { 236 | font-size: 22px; 237 | margin: 20px 0; 238 | font-family: komikax; 239 | font-weight: lighter; 240 | color: #173947; 241 | } 242 | 243 | .choices { 244 | margin: 10px 0px; 245 | overflow-x: auto; 246 | white-space: nowrap; 247 | padding-left: 0px; 248 | scrollbar-width: none; 249 | -ms-overflow-style: none; 250 | } 251 | .choices::-webkit-scrollbar { 252 | width: 0; 253 | height: 0; 254 | } 255 | 256 | .level { 257 | color: #389cae; 258 | font-size: 18px; 259 | display: flex; 260 | } 261 | 262 | .choice { 263 | border: 2px solid #389cae; 264 | margin: 10px 10px 10px 0px; 265 | padding: 15px; 266 | color: #389cae; 267 | cursor: pointer; 268 | text-transform: uppercase; 269 | display: inline-block; 270 | transition: 1s background, 1s color; 271 | } 272 | 273 | .choice:hover { 274 | background: #389cae; 275 | color: white; 276 | } 277 | 278 | @keyframes floating { 279 | from { 280 | transform: translate(0, -0px); 281 | } 282 | 65% { 283 | transform: translate(0, -25px); 284 | } 285 | to { 286 | transform: translate(0, 0px); 287 | } 288 | } 289 | 290 | @-webkit-keyframes tada { 291 | from { 292 | -webkit-transform: scale3d(1, 1, 1); 293 | transform: scale3d(1, 1, 1); 294 | } 295 | 10%, 296 | 20% { 297 | -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 298 | transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 299 | } 300 | 30%, 301 | 50%, 302 | 70%, 303 | 90% { 304 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 305 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 306 | } 307 | 40%, 308 | 60%, 309 | 80% { 310 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 311 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 312 | } 313 | to { 314 | -webkit-transform: scale3d(1, 1, 1); 315 | transform: scale3d(1, 1, 1); 316 | } 317 | } 318 | 319 | @keyframes tada { 320 | from { 321 | -webkit-transform: scale3d(1, 1, 1); 322 | transform: scale3d(1, 1, 1); 323 | } 324 | 10%, 325 | 20% { 326 | -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 327 | transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 328 | } 329 | 30%, 330 | 50%, 331 | 70%, 332 | 90% { 333 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 334 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 335 | } 336 | 40%, 337 | 60%, 338 | 80% { 339 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 340 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 341 | } 342 | to { 343 | -webkit-transform: scale3d(1, 1, 1); 344 | transform: scale3d(1, 1, 1); 345 | } 346 | } 347 | 348 | .tada { 349 | animation-name: tada; 350 | animation-duration: 1.5s; 351 | animation-iteration-count: infinite; 352 | animation-fill-mode: forwards; 353 | } 354 | 355 | .icon:hover { 356 | animation-name: tada; 357 | animation-duration: 1.5s; 358 | animation-iteration-count: infinite; 359 | animation-fill-mode: forwards; 360 | } 361 | 362 | .floating { 363 | animation-name: floating; 364 | animation-duration: 2s; 365 | animation-iteration-count: infinite; 366 | animation-timing-function: ease-in-out; 367 | } 368 | 369 | .save-custom { 370 | justify-content: left; 371 | display: grid; 372 | } 373 | 374 | .custom-session { 375 | padding: 15px; 376 | margin-top: 30px; 377 | margin-left: 0; 378 | } 379 | .input-range__track { 380 | height: 0.7rem; 381 | } 382 | 383 | .input-range__track--active { 384 | background: #389cae; 385 | } 386 | .input-range__slider { 387 | background: #389cae; 388 | border-color: #389cae; 389 | margin-top: -0.97rem; 390 | height: 1.1rem; 391 | width: 1.1rem; 392 | } 393 | .input-range__label { 394 | color: #173947; 395 | } 396 | 397 | .checkbox { 398 | width: 100%; 399 | margin: 0px auto; 400 | position: relative; 401 | display: block; 402 | } 403 | 404 | .checkbox input[type='checkbox'] { 405 | width: auto; 406 | opacity: 0.00000001; 407 | position: absolute; 408 | left: 0; 409 | margin-left: -20px; 410 | } 411 | 412 | .checkbox label { 413 | position: relative; 414 | } 415 | 416 | .checkbox label:before { 417 | content: ''; 418 | position: absolute; 419 | left: 0; 420 | top: 0; 421 | margin: 4px; 422 | width: 22px; 423 | height: 22px; 424 | transition: transform 0.28s ease; 425 | border-radius: 3px; 426 | border: 2px solid #389cae; 427 | } 428 | 429 | .checkbox label:after { 430 | content: ''; 431 | display: block; 432 | width: 10px; 433 | height: 5px; 434 | border-bottom: 2px solid #389cae; 435 | border-left: 2px solid #389cae; 436 | -webkit-transform: rotate(-45deg) scale(0); 437 | -moz-transform: rotate(-45deg) scale(0); 438 | -ms-transform: rotate(-45deg) scale(0); 439 | transform: rotate(-45deg) scale(0); 440 | position: absolute; 441 | top: 12px; 442 | left: 10px; 443 | } 444 | 445 | .checkbox input[type='checkbox']:checked ~ label::before { 446 | color: #389cae; 447 | } 448 | 449 | .checkbox input[type='checkbox']:checked ~ label::after { 450 | -webkit-transform: rotate(-45deg) scale(1); 451 | -moz-transform: rotate(-45deg) scale(1); 452 | -ms-transform: rotate(-45deg) scale(1); 453 | transform: rotate(-45deg) scale(1); 454 | } 455 | 456 | .checkbox label { 457 | min-height: 34px; 458 | display: block; 459 | padding-left: 40px; 460 | margin-bottom: 0; 461 | cursor: pointer; 462 | } 463 | 464 | .checkbox label span { 465 | position: absolute; 466 | top: 50%; 467 | -webkit-transform: translateY(-50%); 468 | transform: translateY(-50%); 469 | } 470 | 471 | .checkbox input[type='checkbox']:focus + label::before { 472 | outline: 0; 473 | } 474 | 475 | .checkbox-2 { 476 | display: flex; 477 | justify-content: center; 478 | } 479 | .hard-label { 480 | float: right; 481 | } 482 | .producthunt { 483 | position: fixed; 484 | width: 210px; 485 | height: 180px; 486 | background: white; 487 | bottom: 10px; 488 | right: 10px; 489 | z-index: 9000; 490 | border: 1px solid #e3e3e3; 491 | padding: 10px; 492 | box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15); 493 | animation: linear finite alternate; 494 | animation-name: run; 495 | animation-duration: 2s; 496 | -webkit-animation: linear finite alternate; 497 | -webkit-animation-name: run; 498 | -webkit-animation-duration: 2s; 499 | } 500 | 501 | .producthunt img { 502 | width: 90px; 503 | margin: 0px auto; 504 | display: block; 505 | } 506 | 507 | .close-it { 508 | font-size: 10px; 509 | font-family: 'komikax'; 510 | color: #173947; 511 | text-align: right; 512 | cursor: pointer; 513 | } 514 | 515 | .product-link { 516 | color: #e56166; 517 | font-family: 'komikax'; 518 | font-size: 10px; 519 | text-align: center; 520 | margin: 10px auto; 521 | border: 1px solid #e56166; 522 | cursor: pointer; 523 | width: 40%; 524 | padding: 4px 0px; 525 | } 526 | 527 | .product-link a { 528 | color: #e56166; 529 | font-family: 'komikax'; 530 | font-size: 10px; 531 | text-align: center; 532 | margin: 10px auto; 533 | cursor: pointer; 534 | width: 40%; 535 | padding: 4px 0px; 536 | text-decoration: none; 537 | } 538 | 539 | .button-pro p { 540 | font-size: 10px; 541 | color: #173947; 542 | text-align: center; 543 | font-family: 'komikax'; 544 | } 545 | 546 | .copyright-link { 547 | font-size: 17px; 548 | margin-top: 30px; 549 | display: flex; 550 | justify-content: center; 551 | } 552 | 553 | .copyright-link p { 554 | margin: 0; 555 | text-align: center; 556 | color: #173947; 557 | } 558 | 559 | @keyframes run { 560 | 0% { 561 | right: -500px; 562 | } 563 | 100% { 564 | right: 0px; 565 | } 566 | } 567 | 568 | @-webkit-keyframes run { 569 | 0% { 570 | right: -500px; 571 | } 572 | 100% { 573 | right: 0px; 574 | } 575 | } 576 | 577 | .copyright-link span { 578 | color: red; 579 | } 580 | 581 | .copyright-link a { 582 | text-decoration: none; 583 | } 584 | 585 | .copyright-link .team-xenox-link { 586 | color: #173947; 587 | } 588 | 589 | .copyright-link img { 590 | width: 20px; 591 | height: 20px; 592 | margin-bottom: -2px; 593 | } 594 | 595 | .copyright-link .join-us { 596 | margin-left: 10px; 597 | color: #e56166; 598 | font-size: 18px; 599 | display: grid; 600 | align-content: center; 601 | } 602 | .success-button { 603 | padding: 20px 100px; 604 | background: #ffffff; 605 | } 606 | @-webkit-keyframes pulse { 607 | from { 608 | -webkit-transform: scale3d(1, 1, 1); 609 | transform: scale3d(1, 1, 1); 610 | } 611 | 612 | 50% { 613 | -webkit-transform: scale3d(1.05, 1.05, 1.05); 614 | transform: scale3d(1.05, 1.05, 1.05); 615 | } 616 | 617 | to { 618 | -webkit-transform: scale3d(1, 1, 1); 619 | transform: scale3d(1, 1, 1); 620 | } 621 | } 622 | 623 | @keyframes pulse { 624 | from { 625 | -webkit-transform: scale3d(1, 1, 1); 626 | transform: scale3d(1, 1, 1); 627 | } 628 | 629 | 50% { 630 | -webkit-transform: scale3d(1.05, 1.05, 1.05); 631 | transform: scale3d(1.05, 1.05, 1.05); 632 | } 633 | 634 | to { 635 | -webkit-transform: scale3d(1, 1, 1); 636 | transform: scale3d(1, 1, 1); 637 | } 638 | } 639 | 640 | .pulse { 641 | -webkit-animation-name: pulse; 642 | animation-name: pulse; 643 | animation-iteration-count: infinite; 644 | -webkit-animation-duration: 1s; 645 | animation-duration: 1s; 646 | -webkit-animation-fill-mode: both; 647 | animation-fill-mode: both; 648 | } 649 | .skip-timer { 650 | display: grid; 651 | grid-template-columns: 1fr 1fr; 652 | width: 40%; 653 | margin-left: auto; 654 | margin-right: auto; 655 | } 656 | .skip-button h1 { 657 | text-align: center; 658 | color: #173947; 659 | font-family: komikax; 660 | font-weight: 100; 661 | cursor: pointer; 662 | } 663 | .timer { 664 | margin-top: 0; 665 | } 666 | .skip-button h1:hover { 667 | text-decoration: underline; 668 | } 669 | @media (max-width: 1237px) { 670 | .start-button { 671 | width: 55%; 672 | } 673 | } 674 | @media (max-width: 970px) { 675 | .start-button { 676 | width: 70%; 677 | } 678 | } 679 | @media (max-width: 888px) { 680 | .start-button { 681 | width: 80%; 682 | } 683 | } 684 | @media (max-width: 779px) { 685 | .start-button { 686 | width: 90%; 687 | } 688 | } 689 | @media (max-width: 694px) { 690 | .start-button { 691 | grid-template-columns: 1fr; 692 | } 693 | .skip-timer { 694 | display: grid; 695 | grid-template-columns: 1fr; 696 | } 697 | .custom { 698 | margin-bottom: 40px; 699 | } 700 | } 701 | @media (max-width: 600px) { 702 | .level { 703 | display: block; 704 | } 705 | .checkbox-2 { 706 | display: block; 707 | } 708 | .hard-label { 709 | float: none; 710 | } 711 | } 712 | @media (max-width: 597px) { 713 | .exercise-info { 714 | width: 100%; 715 | } 716 | .exercise-gif img { 717 | width: 100%; 718 | height: auto; 719 | } 720 | } 721 | @media (max-width: 400px) { 722 | .logo img { 723 | width: 300px; 724 | } 725 | .navbar h1 { 726 | font-size: 1.5em; 727 | text-align: center; 728 | } 729 | } 730 | @media (max-width: 355px) { 731 | .start-button { 732 | width: 100%; 733 | } 734 | .icon { 735 | width: 60px; 736 | } 737 | } 738 | @media (max-width: 330px) { 739 | .logo img { 740 | width: 260px; 741 | } 742 | .copyright-link { 743 | display: block; 744 | } 745 | .copyright-link .join-us { 746 | text-align: center; 747 | margin-top: 10px; 748 | } 749 | .navbar h1 { 750 | font-size: 1.2em; 751 | } 752 | } 753 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { navigate } from 'gatsby'; 3 | import './index.css'; 4 | import yoga from '../assets/yoga.svg'; 5 | import product from '../assets/product.png'; 6 | import fire from '../assets/fire.svg'; 7 | 8 | const IndexPage = () => { 9 | const [popup, setPopup] = useState(true); 10 | 11 | return ( 12 | <> 13 |
14 |

15 | Brogrammer! 16 |

17 |
18 |
19 | 20 |
21 |
22 |
{ 25 | e.preventDefault(); 26 | navigate('/home'); 27 | }} 28 | > 29 | Take Random Challenge 30 |
31 |
{ 34 | e.preventDefault(); 35 | navigate('/custom'); 36 | }} 37 | > 38 | Create Your Own Challenge 39 |
40 |
41 |
42 |

43 | Made with by{' '} 44 | 45 | Xenox 46 | 47 | 48 |

49 | 53 | Join us 54 | 55 |
56 | 57 | ); 58 | }; 59 | 60 | export default IndexPage; 61 | -------------------------------------------------------------------------------- /src/pages/success.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { navigate } from 'gatsby'; 3 | import success from '../assets/success.svg'; 4 | import queryString from 'query-string'; 5 | import './index.css'; 6 | 7 | const SuccessPage = () => { 8 | const query = 9 | typeof window !== 'undefined' 10 | ? queryString.parse(document.location.search) 11 | : ''; 12 | 13 | const onDone = e => { 14 | e.preventDefault(); 15 | if (query && query.customData) { 16 | let customData = JSON.parse(localStorage.getItem('customData')); 17 | customData.startExercise += 1; 18 | localStorage.setItem('customData', JSON.stringify(customData)); 19 | navigate('/home?customData=true'); 20 | } else navigate('/home?createRandom=true'); 21 | }; 22 | 23 | return ( 24 | <> 25 |
26 |

27 | Good Job! 28 |

29 |
30 |
31 | 32 |
33 |
34 |

Now go and hydrate!

35 |
36 | 37 |
38 | 41 |
42 | 43 | ); 44 | }; 45 | 46 | export default SuccessPage; 47 | -------------------------------------------------------------------------------- /src/styles/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "komikax"; 3 | src: url("../assets/KOMIKAX_-webfont.woff") format("woff"); 4 | font-weight: normal; 5 | font-style: normal; 6 | } 7 | .head { 8 | display: grid; 9 | /* grid-template-columns: 1fr 2fr; */ 10 | width: 40%; 11 | margin: 0 auto; 12 | font-family: sans-serif; 13 | text-align: center; 14 | } 15 | body { 16 | font-family: sans-serif; 17 | } 18 | .head img { 19 | width: 100px; 20 | margin: 0 auto; 21 | } 22 | 23 | .nav h1 { 24 | color: #173947; 25 | font-family: komikax; 26 | font-weight: bolder; 27 | letter-spacing: 2px; 28 | font-size: 40px; 29 | text-align: center; 30 | } 31 | .head h1 { 32 | display: grid; 33 | align-content: center; 34 | } 35 | 36 | .content-center { 37 | width: 70%; 38 | margin: 0 auto; 39 | } 40 | 41 | .start { 42 | margin-top: 50px; 43 | } 44 | .button-start { 45 | width: 40%; 46 | margin: 15px auto; 47 | text-align: center; 48 | padding: 10px; 49 | color: white; 50 | background: #2c67ee; 51 | font-weight: 100; 52 | cursor: pointer; 53 | } 54 | .exercise h2 { 55 | text-align: center; 56 | font-weight: 100; 57 | } 58 | .exercise img { 59 | max-height: 300px; 60 | margin: 0 auto; 61 | } 62 | .exercise { 63 | display: grid; 64 | } 65 | 66 | audio { 67 | display: none; 68 | } 69 | .logo img { 70 | width: 400px; 71 | } 72 | 73 | .logo, 74 | .action { 75 | margin: 0 auto; 76 | justify-content: center; 77 | display: grid; 78 | } 79 | 80 | .custom, 81 | .create, 82 | .start-exercise { 83 | text-align: center; 84 | border: 2px solid #173947; 85 | margin-left: 10px; 86 | padding: 20px; 87 | font-family: komikax; 88 | font-weight: lighter; 89 | color: #173947; 90 | cursor: pointer; 91 | } 92 | .create, 93 | .custom-session { 94 | background: #e56166; 95 | border-color: #e56166; 96 | color: white; 97 | } 98 | .start-button { 99 | display: grid; 100 | grid-template-columns: 1fr 1fr; 101 | margin: 0 auto; 102 | width: 40%; 103 | margin-top: 40px; 104 | } 105 | .navbar { 106 | display: grid; 107 | grid-template-columns: 1fr 1fr 1fr; 108 | } 109 | .navbar > .icon { 110 | width: 80px; 111 | } 112 | .navbar h1 { 113 | margin: 10px; 114 | font-family: komikax; 115 | align-self: center; 116 | color: #173947; 117 | text-align: center; 118 | } 119 | .f-audio { 120 | width: 30px; 121 | align-self: center; 122 | justify-self: end; 123 | margin: 0 20px; 124 | cursor: pointer; 125 | } 126 | .search-image { 127 | display: grid; 128 | justify-content: center; 129 | } 130 | .search-image img { 131 | width: 400px; 132 | } 133 | .search-area { 134 | margin-top: 100px; 135 | } 136 | .search-message, 137 | .timer, 138 | .exercise-message { 139 | margin-top: 30px; 140 | text-align: center; 141 | color: #173947; 142 | font-family: komikax; 143 | font-weight: 100; 144 | } 145 | 146 | .exercise-gif { 147 | display: grid; 148 | justify-content: center; 149 | margin-top: 20px; 150 | } 151 | 152 | .exercise-message { 153 | color: #e56166; 154 | } 155 | 156 | .exercise-info { 157 | display: grid; 158 | width: 40%; 159 | margin: 20px auto; 160 | text-align: center; 161 | font-family: komikax; 162 | } 163 | .exercise-info h3 { 164 | margin: 0; 165 | color: #f0bc08; 166 | letter-spacing: 1px; 167 | font-weight: 100; 168 | } 169 | 170 | .exercise-info span { 171 | color: #389cae; 172 | } 173 | .big-form { 174 | display: grid; 175 | margin: 10px auto; 176 | width: 80%; 177 | } 178 | .f-section { 179 | display: grid; 180 | margin: 5px 0; 181 | } 182 | .f-section label { 183 | font-size: 22px; 184 | margin: 20px 0; 185 | font-family: komikax; 186 | font-weight: lighter; 187 | color: #173947; 188 | } 189 | .choices { 190 | display: flex; 191 | margin: 10px; 192 | } 193 | .level { 194 | color: #389cae; 195 | font-size: 18px; 196 | } 197 | .choice { 198 | border: 2px solid #389cae; 199 | margin: 10px; 200 | padding: 15px; 201 | color: #389cae; 202 | cursor: pointer; 203 | text-transform: uppercase; 204 | transition: 1s background, 1s color; 205 | } 206 | .choice:hover { 207 | background: #389cae; 208 | color: white; 209 | } 210 | @keyframes floating { 211 | from { 212 | transform: translate(0, -0px); 213 | } 214 | 65% { 215 | transform: translate(0, -25px); 216 | } 217 | to { 218 | transform: translate(0, 0px); 219 | } 220 | } 221 | @-webkit-keyframes tada { 222 | from { 223 | -webkit-transform: scale3d(1, 1, 1); 224 | transform: scale3d(1, 1, 1); 225 | } 226 | 227 | 10%, 228 | 20% { 229 | -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 230 | transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 231 | } 232 | 233 | 30%, 234 | 50%, 235 | 70%, 236 | 90% { 237 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 238 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 239 | } 240 | 241 | 40%, 242 | 60%, 243 | 80% { 244 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 245 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 246 | } 247 | 248 | to { 249 | -webkit-transform: scale3d(1, 1, 1); 250 | transform: scale3d(1, 1, 1); 251 | } 252 | } 253 | 254 | @keyframes tada { 255 | from { 256 | -webkit-transform: scale3d(1, 1, 1); 257 | transform: scale3d(1, 1, 1); 258 | } 259 | 260 | 10%, 261 | 20% { 262 | -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 263 | transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); 264 | } 265 | 266 | 30%, 267 | 50%, 268 | 70%, 269 | 90% { 270 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 271 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); 272 | } 273 | 274 | 40%, 275 | 60%, 276 | 80% { 277 | -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 278 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); 279 | } 280 | 281 | to { 282 | -webkit-transform: scale3d(1, 1, 1); 283 | transform: scale3d(1, 1, 1); 284 | } 285 | } 286 | 287 | .tada { 288 | animation-name: tada; 289 | animation-duration: 1.5s; 290 | animation-iteration-count: infinite; 291 | animation-fill-mode: forwards; 292 | } 293 | 294 | .navbar > .icon:hover { 295 | animation-name: tada; 296 | animation-duration: 1.5s; 297 | animation-iteration-count: infinite; 298 | animation-fill-mode: forwards; 299 | } 300 | .floating { 301 | animation-name: floating; 302 | animation-duration: 2s; 303 | animation-iteration-count: infinite; 304 | animation-timing-function: ease-in-out; 305 | } 306 | 307 | .save-custom { 308 | justify-content: left; 309 | display: grid; 310 | } 311 | .custom-session { 312 | padding: 15px; 313 | margin-top: 30px; 314 | margin-left: 0; 315 | } 316 | 317 | .slider { 318 | -webkit-appearance: none; 319 | width: 100%; 320 | height: 20px; 321 | background: #389cae; 322 | outline: none; 323 | opacity: 0.7; 324 | border-radius: 20px; 325 | -webkit-transition: 0.2s; 326 | transition: opacity 0.2s; 327 | } 328 | .slider::-webkit-slider-thumb { 329 | -webkit-appearance: none; 330 | appearance: none; 331 | width: 20px; 332 | height: 20px; 333 | background: #389cae; 334 | border: 4px solid #173947; 335 | cursor: pointer; 336 | border-radius: 50%; 337 | } 338 | 339 | .slider::-moz-range-thumb { 340 | width: 20px; 341 | height: 20px; 342 | background: #389cae; 343 | cursor: pointer; 344 | border: 4px solid #173947; 345 | border-radius: 50%; 346 | } 347 | .level { 348 | display: flex; 349 | } 350 | .checkbox { 351 | width: 100%; 352 | margin: 0px auto; 353 | position: relative; 354 | display: block; 355 | } 356 | 357 | .checkbox input[type="checkbox"] { 358 | width: auto; 359 | opacity: 0.00000001; 360 | position: absolute; 361 | left: 0; 362 | margin-left: -20px; 363 | } 364 | .checkbox label { 365 | position: relative; 366 | } 367 | .checkbox label:before { 368 | content: ""; 369 | position: absolute; 370 | left: 0; 371 | top: 0; 372 | margin: 4px; 373 | width: 22px; 374 | height: 22px; 375 | transition: transform 0.28s ease; 376 | border-radius: 3px; 377 | border: 2px solid #389cae; 378 | } 379 | .checkbox label:after { 380 | content: ""; 381 | display: block; 382 | width: 10px; 383 | height: 5px; 384 | border-bottom: 2px solid #389cae; 385 | border-left: 2px solid #389cae; 386 | -webkit-transform: rotate(-45deg) scale(0); 387 | -moz-transform: rotate(-45deg) scale(0); 388 | -ms-transform: rotate(-45deg) scale(0); 389 | transform: rotate(-45deg) scale(0); 390 | position: absolute; 391 | top: 12px; 392 | left: 10px; 393 | } 394 | .checkbox input[type="checkbox"]:checked ~ label::before { 395 | color: #389cae; 396 | } 397 | 398 | .checkbox input[type="checkbox"]:checked ~ label::after { 399 | -webkit-transform: rotate(-45deg) scale(1); 400 | -moz-transform: rotate(-45deg) scale(1); 401 | -ms-transform: rotate(-45deg) scale(1); 402 | transform: rotate(-45deg) scale(1); 403 | } 404 | 405 | .checkbox label { 406 | min-height: 34px; 407 | display: block; 408 | padding-left: 40px; 409 | margin-bottom: 0; 410 | cursor: pointer; 411 | } 412 | .checkbox label span { 413 | position: absolute; 414 | top: 50%; 415 | -webkit-transform: translateY(-50%); 416 | transform: translateY(-50%); 417 | } 418 | .checkbox input[type="checkbox"]:focus + label::before { 419 | outline: 0; 420 | } 421 | --------------------------------------------------------------------------------