diff --git a/e2e/test_activities.py b/e2e/test_workouts.py similarity index 53% rename from e2e/test_activities.py rename to e2e/test_workouts.py index 8214188e..6c72e8d6 100644 --- a/e2e/test_activities.py +++ b/e2e/test_workouts.py @@ -4,35 +4,35 @@ from selenium.webdriver.support.ui import Select, WebDriverWait from .utils import TEST_URL, register_valid_user -class TestActivity: - def test_user_can_add_activity_without_gpx(self, selenium): +class TestWorkout: + def test_user_can_add_workout_without_gpx(self, selenium): register_valid_user(selenium) nav_items = selenium.find_elements_by_class_name('nav-item') nav_items[3].click() selenium.implicitly_wait(1) radio_buttons = selenium.find_elements_by_class_name( - 'add-activity-radio' + 'add-workout-radio' ) radio_buttons[1].click() - selenium.find_element_by_name('title').send_keys('Activity title') + selenium.find_element_by_name('title').send_keys('Workout title') select = Select(selenium.find_element_by_name('sport_id')) select.select_by_index(1) - selenium.find_element_by_name('activity_date').send_keys('2018-12-20') - selenium.find_element_by_name('activity_time').send_keys('14:05') + selenium.find_element_by_name('workout_date').send_keys('2018-12-20') + selenium.find_element_by_name('workout_time').send_keys('14:05') selenium.find_element_by_name('duration').send_keys('01:00:00') selenium.find_element_by_name('distance').send_keys('10') selenium.find_element_by_class_name('btn-primary').click() WebDriverWait(selenium, 10).until( - EC.url_changes(f"{TEST_URL}/activities/add") + EC.url_changes(f"{TEST_URL}/workouts/add") ) - activity_details = selenium.find_element_by_class_name( - 'activity-details' + workout_details = selenium.find_element_by_class_name( + 'workout-details' ).text - assert 'Duration: 1:00:00' in activity_details - assert 'Distance: 10 km' in activity_details - assert 'Average speed: 10 km/h' in activity_details - assert 'Max. speed: 10 km/h' in activity_details + assert 'Duration: 1:00:00' in workout_details + assert 'Distance: 10 km' in workout_details + assert 'Average speed: 10 km/h' in workout_details + assert 'Max. speed: 10 km/h' in workout_details diff --git a/fittrackee/dist/asset-manifest.json b/fittrackee/dist/asset-manifest.json index d0073ee0..b0bc2cd9 100644 --- a/fittrackee/dist/asset-manifest.json +++ b/fittrackee/dist/asset-manifest.json @@ -1,14 +1,14 @@ { "files": { - "main.css": "/static/css/main.34182cc5.chunk.css", - "main.js": "/static/js/main.385ae13c.chunk.js", - "main.js.map": "/static/js/main.385ae13c.chunk.js.map", + "main.css": "/static/css/main.06b7c846.chunk.css", + "main.js": "/static/js/main.c96409fd.chunk.js", + "main.js.map": "/static/js/main.c96409fd.chunk.js.map", "runtime-main.js": "/static/js/runtime-main.1240af94.js", "runtime-main.js.map": "/static/js/runtime-main.1240af94.js.map", "static/js/2.1b88ef3c.chunk.js": "/static/js/2.1b88ef3c.chunk.js", "static/js/2.1b88ef3c.chunk.js.map": "/static/js/2.1b88ef3c.chunk.js.map", "index.html": "/index.html", - "static/css/main.34182cc5.chunk.css.map": "/static/css/main.34182cc5.chunk.css.map", + "static/css/main.06b7c846.chunk.css.map": "/static/css/main.06b7c846.chunk.css.map", "static/js/2.1b88ef3c.chunk.js.LICENSE.txt": "/static/js/2.1b88ef3c.chunk.js.LICENSE.txt", "static/media/en.9e6dbfb0.svg": "/static/media/en.9e6dbfb0.svg", "static/media/fr.d0f9280c.svg": "/static/media/fr.d0f9280c.svg", @@ -18,7 +18,7 @@ "entrypoints": [ "static/js/runtime-main.1240af94.js", "static/js/2.1b88ef3c.chunk.js", - "static/css/main.34182cc5.chunk.css", - "static/js/main.385ae13c.chunk.js" + "static/css/main.06b7c846.chunk.css", + "static/js/main.c96409fd.chunk.js" ] } \ No newline at end of file diff --git a/fittrackee/dist/index.html b/fittrackee/dist/index.html index 0a15a654..e30b0558 100644 --- a/fittrackee/dist/index.html +++ b/fittrackee/dist/index.html @@ -1 +1 @@ -FitTrackee
\ No newline at end of file +FitTrackee
\ No newline at end of file diff --git a/fittrackee/dist/static/css/main.06b7c846.chunk.css b/fittrackee/dist/static/css/main.06b7c846.chunk.css new file mode 100644 index 00000000..04a4c84c --- /dev/null +++ b/fittrackee/dist/static/css/main.06b7c846.chunk.css @@ -0,0 +1,2 @@ +html{height:100vh}body{background-color:#eaeaea;margin:0;min-height:100vh;padding-bottom:50px;position:relative}.App{padding-bottom:20px;text-align:center}.App-logo{-webkit-animation:App-logo-spin 20s linear infinite;animation:App-logo-spin 20s linear infinite;height:80px}.App-header{background-color:#222;height:150px;padding:20px;color:#fff}.App-title{font-size:1.5em}.App-intro{font-size:large}.App-nav-profile-img{max-width:32px;max-height:32px;border-radius:50%}.App-profile-img-small{max-width:150px;max-height:150px;border-radius:50%}@-webkit-keyframes App-logo-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes App-logo-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a{color:#40578a}input[type=text],label,textarea{width:100%}.add-workout{margin-top:50px}.add-workout-radio{margin-right:10px}.admin-img{max-width:35px;max-height:35px}.admin-items{list-style-type:square}.admin-message{color:#7c7c7d;font-size:.9em;font-style:italic;margin-left:10px}.app-config-form label{font-weight:700}.btn{margin-right:10px}.card{text-align:left}.chart{font-size:.9em}.chart-workouts{margin-left:60px}.chart-arrows{margin-top:7px}.chart-filters{padding-bottom:10px}.chart-info{font-size:.8em;font-style:italic}.chart-radio{display:flex;font-size:.9em}.chart-radio input{margin-right:10px}.chart-stats{font-size:.8em}.chart-title{font-size:1.1em;margin-bottom:10px}.col-workout-logo{padding-right:0}.custom-modal{background-color:#fff;border-radius:5px;max-width:500px;margin:20% auto;z-index:1250}.custom-modal-backdrop{position:fixed;top:0;bottom:0;left:0;right:0;background-color:rgba(0,0,0,.3);padding:50px;z-index:1240}.custom-fa{margin-right:5px}.custom-fa-small{font-size:.8em;margin-left:-.8em}@media only screen and (max-width:992px){.custom-fa-small{font-size:.6em}}.custom-tooltip{background-color:#fff;border:1px solid #d3d3d3;padding:10px}.custom-tooltip p{margin:5px}.custom-tooltip-label{font-weight:700}.dashboard{height:100%}.dashboard,.history{margin-top:30px}.dropdown-wrapper{width:50px}.dropdown-list{background-color:#f8f9fa;padding:5px 0;position:absolute;text-align:left;z-index:10}.dropdown-item{cursor:default;font-size:.9em}.dropdown-item-selected{font-weight:700}.dropdown-item-selected:after{content:" ✔"}.error-message{margin-top:10px}.fa-as-link{cursor:pointer;color:#40578a}.fa-as-link:hover{color:#0056b3}.fa-question-circle{color:#6c757d;margin-left:3px}.fa-trophy{color:#daa520}.fa-color{color:#405976}.footer{background-color:#f8f9fa;bottom:0;color:#8b8c8c;font-size:.9em;height:50px;line-height:50px;position:absolute;width:100%}.form-disabled .form-group input::-webkit-inner-spin-button,.form-disabled .form-group input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.form-disabled .form-group input[type=number]{-moz-appearance:textfield}.form-disabled .form-group input{border:none;pointer-events:none}.gpx-file{height:inherit}.huge{font-size:25px}.i18n-flag svg{height:100%;opacity:.9;width:15px}.inactive-link{color:#d3d3d3}.leaflet-container{height:400px}.loader{-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;border:8px solid #f3f3f3;border-top-color:#3498db;border-radius:50%;height:60px;margin-left:41%;width:60px}@-webkit-keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.map-attribution{bottom:0;font-size:11px;position:absolute}.map-attribution-text{background-color:hsla(0,0%,100%,.5);padding-left:2px;padding-right:2px}.no-picture{color:#405976}.page-title{font-size:2em;margin:1em;text-align:center}.password-forget{margin:10px;font-size:.9em;font-style:italic}.radioLabel{text-align:center}.record-logo{margin-right:5px;max-width:25px;max-height:25px}.record-table table,.record-table td,.record-table th{font-size:.9em;padding:.1em}.sport-img{max-width:35px;max-height:35px}.sport-img-medium{max-width:45px;max-height:45px}.stats-disabled{opacity:.3;pointer-events:none}.svg-icon{fill:#405976;height:70px;margin-left:auto;margin-right:auto;width:70px}.time-frames{align-items:center;display:inline-flex}.time-frame label{float:left;padding:0 5px}.time-frame label input{display:none}.time-frame label span{border:1px solid #a9a9a9;border-radius:9%;color:#7b7b7b;display:block;font-size:.9em;padding:2px 6px;text-align:center}.time-frame input:checked+span{background-color:#a9a9a9;color:#fff}.timezone-custom{font-size:.9em!important;height:inherit!important}.timezone-custom input{border:0!important;padding:5px 1px!important}.timezone-custom ul{background:#fff}.timezone-picker{padding:0}.timezone-picker-textfield{font-size:15px}.unlink{color:#000}.user-filters{font-size:.9em;margin-bottom:10px}.user-label{font-weight:700}.weather-img{max-width:35px;max-height:35px}.weather-img-small{max-width:20px;max-height:20px}.weather-table{margin-bottom:0}.weather-table table,.weather-table td,.weather-table th{font-size:.9em;padding:.1em}.workouts-result{font-size:.85em}.workout-card{margin-bottom:15px}.workout-details{font-size:.95em}.workout-date{font-size:.75em}.workout-filter{font-size:.9em}.col-5,.workout-filter .col-2{padding:0}.workout-label{font-size:.8em;color:#666}.workout-logo{margin:0 5px;max-width:20px;max-height:20px}.workout-map{background-color:#eaeaea;height:225px;width:400px}.workout-no-map{background-color:#eaeaea;color:#666;font-style:italic;height:400px;line-height:400px}.actvitiy-segments,.workout-notes{font-size:.9em;font-style:italic;margin-top:10px;padding:5px}.workout-page{margin-top:20px}.workout-segments-list{list-style:square}.workout-sport{margin-right:1px;max-width:18px;max-height:18px}.workout-title .map-attribution-list,.workout-title img{display:none}.workout-title img{border:1px solid #d3d3d3;border-radius:4px;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.workout-title .map-attribution-list,.workout-title img{display:none;margin-left:20px;position:absolute;z-index:1000}.workout-title .map-attribution-list{font-size:11px}.workout-title:hover .map-attribution-list,.workout-title:hover img{display:block}.heading-span,.heading-span-absolute{background:#eee;color:#696969;display:none;font-size:10px;font-weight:700;padding:5px;text-transform:uppercase;top:0;left:0}.heading-span-absolute{position:absolute;display:none}@media(max-width:1024px){table thead{left:-9999px;position:absolute;visibility:hidden}table tr{border-bottom:0;display:flex;flex-direction:row;flex-wrap:wrap;margin-bottom:40px}table td{border:1px solid #d3d3d3;margin:0 -1px -1px 0;padding-top:30px!important;position:relative;text-align:center;width:50%}.record-tr{margin-bottom:0}.record-td{padding-top:0!important}.heading-span,.heading-span-absolute{display:block}}:root{--main-color:#1a8fff;--text-color:#777;--text-color-light:#ccc;--border-color:#eee;--bg-color:#f9f9f9;--neutral-color:#fff}.calendar .col-start{justify-content:flex-start;text-align:left}.calendar .col-center{justify-content:center;text-align:center}.calendar .col-end{justify-content:flex-end;text-align:right}.calendar{display:block;position:relative;width:100%;background:#fff;background:var(--neutral-color);border:1px solid #eee;border:1px solid var(--border-color)}.calendar .header{text-transform:uppercase;font-weight:700;padding:.5em 0;border-bottom:1px solid #eee;border-bottom:1px solid var(--border-color)}.calendar .header .icon{cursor:pointer;transition:.15s ease-out}.calendar .header .icon:hover{transform:scale(1.75);transition:.25s ease-out;color:#1a8fff;color:var(--main-color)}.calendar .header .icon:first-of-type{margin-left:1em}.calendar .header .icon:last-of-type{margin-right:1em}.calendar .days{text-transform:uppercase;font-weight:400;color:#ccc;color:var(--text-color-light);font-size:70%;padding:.75em 0;border-bottom:1px solid #eee;border-bottom:1px solid var(--border-color)}.calendar .body .cell{position:relative;height:3em;border-right:1px solid #eee;border-right:1px solid var(--border-color);background:#fff;background:var(--neutral-color)}.calendar .body .cell:hover{background:#f9f9f9;background:var(--bg-color)}.calendar .body .selected{border-left:10px solid transparent;border-image:linear-gradient(45deg,#1a8fff,#53cbf1 40%)}.calendar .body .row{border-bottom:1px solid #eee;border-bottom:1px solid var(--border-color);margin:0}.calendar .body .row:last-child{border-bottom:none}.calendar .body .cell:last-child{border-right:none}.calendar .body .cell .number{position:absolute;font-size:82.5%;line-height:1;top:.75em;right:.75em;font-weight:700}.calendar .body .disabled{color:#ccc;color:var(--text-color-light);pointer-events:none}.calendar .body .col{flex-grow:0;flex-basis:14.28571%;width:14.28571%}.calendar .body .img-disabled{opacity:.4}.calendar .body .weekend{background:#f5f5f5}.calendar .body .today{background:#eff1f3}.calendar-more,.calendar-workout{display:none}.calendar-more{color:#405976;font-size:.7em;margin-left:.3em}.calendar-display-more{background:#f5f5f5;border-radius:4px;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);margin-bottom:10px;padding:10px 15px;position:absolute;min-width:52px;z-index:1000}.calendar-workout-more{display:none}@media only screen and (max-width:992px){.calendar-workout-more:nth-child(n+3),.calendar-workout:nth-child(-n+2),.calendar-workout:nth-child(n+3)~.calendar-more{display:inline-block}}@media only screen and (min-width:992px) and (max-width:1200px){.calendar-workout-more:nth-child(n+5),.calendar-workout:nth-child(-n+4),.calendar-workout:nth-child(n+5)~.calendar-more{display:inline-block}}@media only screen and (min-width:1200px){.calendar-workout-more:nth-child(n+7),.calendar-workout:nth-child(-n+6),.calendar-workout:nth-child(n+7)~.calendar-more{display:inline-block}} +/*# sourceMappingURL=main.06b7c846.chunk.css.map */ \ No newline at end of file diff --git a/fittrackee/dist/static/css/main.06b7c846.chunk.css.map b/fittrackee/dist/static/css/main.06b7c846.chunk.css.map new file mode 100644 index 00000000..8e414904 --- /dev/null +++ b/fittrackee/dist/static/css/main.06b7c846.chunk.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://src/components/App.css"],"names":[],"mappings":"AAAA,KACE,YACF,CAEA,KACE,wBAAyB,CACzB,QAAS,CACT,gBAAiB,CACjB,mBAAoB,CACpB,iBACA,CAEF,KACE,mBAAoB,CACpB,iBACF,CAEA,UACE,mDAA4C,CAA5C,2CAA4C,CAC5C,WACF,CAEA,YACE,qBAAsB,CACtB,YAAa,CACb,YAAa,CACb,UACF,CAEA,WACE,eACF,CAEA,WACE,eACF,CAEA,qBACE,cAAe,CACf,eAAgB,CAChB,iBACF,CAEA,uBACE,eAAgB,CAChB,gBAAiB,CACjB,iBACF,CAEA,iCACE,GAAO,sBAAyB,CAChC,GAAK,uBAA2B,CAClC,CAHA,yBACE,GAAO,sBAAyB,CAChC,GAAK,uBAA2B,CAClC,CAEA,EACE,aACF,CAMA,gCACE,UACF,CAEA,aACE,eACF,CAEA,mBACE,iBACF,CAEA,WACE,cAAe,CACf,eACF,CAEA,aACE,sBACF,CAEA,eACE,aAAc,CACd,cAAgB,CAChB,iBAAkB,CAClB,gBACF,CAEA,uBACE,eACF,CAEA,KACE,iBACF,CAEA,MACE,eACF,CAEA,OACE,cACF,CAEA,gBACE,gBACF,CAEA,cACE,cACF,CAEA,eACE,mBACF,CAEA,YACE,cAAgB,CAChB,iBACF,CAEA,aACE,YAAa,CACb,cACF,CAMA,mBACE,iBACF,CAEA,aACE,cACF,CAEA,aACE,eAAgB,CAChB,kBACF,CAEA,kBACE,eACF,CAEA,cACE,qBAAsB,CACtB,iBAAkB,CAClB,eAAgB,CAChB,eAAgB,CAChB,YACF,CAEA,uBACE,cAAe,CACf,KAAM,CACN,QAAS,CACT,MAAO,CACP,OAAQ,CACR,+BAAiC,CACjC,YAAa,CACb,YACF,CAEA,WACE,gBACF,CAEA,iBACE,cAAgB,CAChB,iBACF,CAEA,yCACE,iBACE,cACF,CACF,CAEA,gBACE,qBAAsB,CACtB,wBAA2B,CAC3B,YACF,CAEA,kBACE,UACF,CAEA,sBACE,eACF,CAEA,WACE,WACF,CACA,oBACE,eACF,CAEA,kBACE,UACF,CAEA,eACE,wBAAyB,CACzB,aAAc,CACd,iBAAkB,CAClB,eAAgB,CAChB,UACF,CAEA,eACE,cAAe,CACf,cACF,CAEA,wBACE,eACF,CAEA,8BACE,YACF,CAEA,eACE,eACF,CAEA,YACE,cAAc,CACd,aACF,CAEA,kBACE,aACF,CAEA,oBACE,aAAc,CACd,eACF,CAEA,WACE,aACF,CAEA,UACE,aACF,CAEA,QACE,wBAAyB,CACzB,QAAS,CACT,aAAc,CACd,cAAgB,CAChB,WAAY,CACZ,gBAAiB,CACjB,iBAAkB,CAClB,UACF,CAGA,wHAEE,uBAAwB,CACxB,QACF,CAGA,8CACE,yBACF,CAEA,iCACE,WAAY,CACZ,mBACF,CAGA,UACE,cACF,CAEA,MACE,cACF,CAEA,eACE,WAAY,CACZ,UAAW,CACX,UACF,CAEA,eACE,aACF,CAEA,mBACE,YACF,CAEA,QACE,yCAAkC,CAAlC,iCAAkC,CAElC,wBAA6B,CAA7B,wBAA6B,CAC7B,iBAAkB,CAClB,WAAY,CACZ,eAAgB,CAChB,UACF,CAEA,wBACE,GAAK,sBAAyB,CAC9B,GAAO,uBAA2B,CACpC,CAHA,gBACE,GAAK,sBAAyB,CAC9B,GAAO,uBAA2B,CACpC,CAEA,iBACE,QAAS,CACT,cAAe,CACf,iBACF,CAEA,sBACE,mCAAyC,CACzC,gBAAiB,CACjB,iBACF,CAEA,YACE,aACF,CAEA,YACE,aAAc,CACd,UAAW,CACX,iBACF,CAEA,iBACE,WAAY,CACZ,cAAe,CACf,iBACF,CAEA,YACE,iBACF,CAEA,aACE,gBAAiB,CACjB,cAAe,CACf,eACF,CAEA,sDACE,cAAgB,CAChB,YACF,CAEA,WACE,cAAe,CACf,eACF,CAEA,kBACE,cAAe,CACf,eACF,CAEA,gBACE,UAAY,CACZ,mBACF,CAEA,UACE,YAAa,CACb,WAAY,CACZ,gBAAiB,CACjB,iBAAkB,CAClB,UACF,CAEA,aACE,kBAAmB,CACnB,mBACF,CAEA,kBACE,UAAW,CACX,aACF,CAEA,wBACE,YACF,CAEA,uBACE,wBAAyB,CACzB,gBAAiB,CACjB,aAAc,CACd,aAAc,CACd,cAAgB,CAChB,eAAgB,CAChB,iBACF,CAEA,+BACE,wBAAyB,CACzB,UACF,CAEA,iBACE,wBAA0B,CAC1B,wBACF,CAEA,uBACE,kBAAoB,CACpB,yBACF,CAEA,oBACE,eACF,CAEA,iBACE,SACF,CAEA,2BACE,cACF,CAEA,QACE,UACF,CAEA,cACE,cAAgB,CAChB,kBACF,CAEA,YACE,eACF,CAEA,aACE,cAAe,CACf,eACF,CAEA,mBACE,cAAe,CACf,eACF,CAEA,eACE,eACF,CAEA,yDACE,cAAgB,CAChB,YACF,CAEA,iBACE,eACF,CAEA,cACE,kBACF,CAEA,iBACE,eACF,CACA,cACE,eACF,CAEA,gBACE,cACF,CAEA,8BACE,SACF,CAEA,eACE,cAAgB,CAChB,UACF,CAEA,cACE,YAAa,CACb,cAAe,CACf,eACF,CAEA,aACE,wBAAyB,CACzB,YAAa,CACb,WACF,CAEA,gBACE,wBAAyB,CACzB,UAAc,CACd,iBAAkB,CAClB,YAAa,CACb,iBACF,CAEA,kCACE,cAAgB,CAChB,iBAAkB,CAClB,eAAgB,CAChB,WACF,CAEA,cACE,eACF,CAEA,uBACE,iBACF,CAEA,eACE,gBAAiB,CACjB,cAAe,CACf,eACF,CAEA,wDACE,YACF,CAEA,mBACE,wBAA2B,CAC3B,iBAAkB,CAClB,kEAKF,CAEA,wDANE,YAAa,CACb,gBAAiB,CACjB,iBAAkB,CAClB,YASF,CANA,qCAEE,cAIF,CAEA,oEACE,aACF,CAIA,qCAEE,eAAgB,CAChB,aAAc,CACd,YAAa,CACb,cAAe,CACf,eAAiB,CACjB,WAAY,CACZ,wBAAyB,CACzB,KAAM,CACN,MACF,CAEA,uBACE,iBAAkB,CAClB,YACF,CAEA,yBACE,YACE,YAAa,CACb,iBAAkB,CAClB,iBACF,CACA,SACE,eAAgB,CAChB,YAAa,CACb,kBAAmB,CACnB,cAAe,CACf,kBACF,CACA,SACE,wBAA2B,CAC3B,oBAAqB,CACrB,0BAA4B,CAC5B,iBAAkB,CAClB,iBAAkB,CAClB,SACF,CACA,WACE,eACF,CACA,WACE,uBACF,CACA,qCACE,aACF,CACF,CAGA,MACE,oBAAqB,CACrB,iBAAkB,CAClB,uBAAwB,CACxB,mBAAoB,CACpB,kBAAmB,CACnB,oBACF,CAEA,qBACE,0BAA2B,CAC3B,eACF,CAEA,sBACE,sBAAuB,CACvB,iBACF,CAEA,mBACE,wBAAyB,CACzB,gBACF,CAEA,UACE,aAAc,CACd,iBAAkB,CAClB,UAAW,CACX,eAAgC,CAAhC,+BAAgC,CAChC,qBAAqC,CAArC,oCACF,CAEA,kBACE,wBAAyB,CACzB,eAAgB,CAEhB,cAAgB,CAChB,4BAA4C,CAA5C,2CACF,CAEA,wBACE,cAAe,CACf,wBACF,CAEA,8BACE,qBAAsB,CACtB,wBAAyB,CACzB,aAAwB,CAAxB,uBACF,CAEA,sCACE,eACF,CAEA,qCACE,gBACF,CAEA,gBACE,wBAAyB,CACzB,eAAgB,CAChB,UAA8B,CAA9B,6BAA8B,CAC9B,aAAc,CACd,eAAgB,CAChB,4BAA4C,CAA5C,2CACF,CAEA,sBACE,iBAAkB,CAClB,UAAW,CACX,2BAA2C,CAA3C,0CAA2C,CAC3C,eAAgC,CAAhC,+BACF,CAEA,4BACE,kBAA2B,CAA3B,0BACF,CAEA,0BACE,kCAAmC,CACnC,uDACF,CAEA,qBACE,4BAA4C,CAA5C,2CAA4C,CAC5C,QACF,CAEA,gCACE,kBACF,CAEA,iCACE,iBACF,CAEA,8BACE,iBAAkB,CAClB,eAAgB,CAChB,aAAc,CACd,SAAU,CACV,WAAY,CACZ,eACF,CAEA,0BACE,UAA8B,CAA9B,6BAA8B,CAC9B,mBACF,CAEA,qBACE,WAAY,CACZ,oBAAwB,CACxB,eACF,CAEA,8BACE,UACF,CAEA,yBACE,kBACF,CAEA,uBACE,kBACF,CAEA,iCAEE,YACF,CAEA,eACE,aAAc,CACd,cAAe,CACf,gBACF,CAEA,uBACE,kBAAsB,CACtB,iBAAkB,CAClB,kEAA4E,CAC5E,kBAAmB,CACnB,iBAAkB,CAClB,iBAAkB,CAClB,cAAe,CACf,YACF,CAEA,uBACE,YACF,CAEA,yCAEE,wHAGE,oBACF,CAEF,CAEA,gEAEE,wHAGE,oBACF,CAEF,CAEA,0CAEE,wHAGE,oBACF,CAEF","file":"main.06b7c846.chunk.css","sourcesContent":["html {\n height: 100vh;\n}\n\nbody {\n background-color: #eaeaea;\n margin: 0;\n min-height: 100vh;\n padding-bottom: 50px;\n position: relative;\n }\n\n.App {\n padding-bottom: 20px;\n text-align: center;\n}\n\n.App-logo {\n animation: App-logo-spin infinite 20s linear;\n height: 80px;\n}\n\n.App-header {\n background-color: #222;\n height: 150px;\n padding: 20px;\n color: white;\n}\n\n.App-title {\n font-size: 1.5em;\n}\n\n.App-intro {\n font-size: large;\n}\n\n.App-nav-profile-img {\n max-width: 32px;\n max-height: 32px;\n border-radius: 50%;\n}\n\n.App-profile-img-small {\n max-width: 150px;\n max-height: 150px;\n border-radius: 50%;\n}\n\n@keyframes App-logo-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\na {\n color: #40578a;\n}\n\ninput[type=\"text\"], textarea {\n width: 100%;\n}\n\nlabel {\n width: 100%;\n}\n\n.add-workout {\n margin-top: 50px;\n}\n\n.add-workout-radio {\n margin-right: 10px;\n}\n\n.admin-img {\n max-width: 35px;\n max-height: 35px;\n}\n\n.admin-items {\n list-style-type: square;\n}\n\n.admin-message {\n color: #7c7c7d;\n font-size: 0.9em;\n font-style: italic;\n margin-left: 10px;\n}\n\n.app-config-form label {\n font-weight: bold;\n}\n\n.btn {\n margin-right: 10px;\n}\n\n.card {\n text-align: left;\n}\n\n.chart {\n font-size: 0.9em;\n}\n\n.chart-workouts {\n margin-left: 60px;\n}\n\n.chart-arrows {\n margin-top: 7px;\n}\n\n.chart-filters {\n padding-bottom: 10px;\n}\n\n.chart-info {\n font-size: 0.8em;\n font-style: italic;\n}\n\n.chart-radio {\n display: flex;\n font-size: 0.9em;\n}\n\n.chart-radio label {\n /* display: flex; */\n}\n\n.chart-radio input {\n margin-right: 10px;\n}\n\n.chart-stats {\n font-size: 0.8em;\n}\n\n.chart-title {\n font-size: 1.1em;\n margin-bottom: 10px;\n}\n\n.col-workout-logo{\n padding-right: 0;\n}\n\n.custom-modal {\n background-color: #fff;\n border-radius: 5px;\n max-width: 500px;\n margin: 20% auto;\n z-index: 1250;\n}\n\n.custom-modal-backdrop {\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n background-color: rgba(0,0,0,0.3);\n padding: 50px;\n z-index: 1240;\n}\n\n.custom-fa {\n margin-right: 5px;\n}\n\n.custom-fa-small {\n font-size: 0.8em;\n margin-left: -0.8em;\n}\n\n@media only screen and (max-width: 992px) {\n .custom-fa-small {\n font-size: 0.6em;\n }\n}\n\n.custom-tooltip {\n background-color: #fff;\n border: 1px solid lightgrey;\n padding: 10px;\n}\n\n.custom-tooltip p {\n margin: 5px;\n}\n\n.custom-tooltip-label {\n font-weight: bold;\n}\n\n.dashboard {\n height: 100%;\n}\n.dashboard, .history {\n margin-top: 30px;\n}\n\n.dropdown-wrapper {\n width: 50px;\n}\n\n.dropdown-list {\n background-color: #f8f9fa;\n padding: 5px 0;\n position: absolute;\n text-align: left;\n z-index: 10;\n}\n\n.dropdown-item {\n cursor: default;\n font-size: 0.9em;\n}\n\n.dropdown-item-selected {\n font-weight: bold;\n}\n\n.dropdown-item-selected::after {\n content: \" ✔\";\n}\n\n.error-message {\n margin-top: 10px;\n}\n\n.fa-as-link {\n cursor:pointer;\n color: #40578a;\n}\n\n.fa-as-link:hover {\n color: #0056b3;\n}\n\n.fa-question-circle {\n color: #6c757d;\n margin-left: 3px;\n}\n\n.fa-trophy {\n color: goldenrod;\n}\n\n.fa-color {\n color: #405976;\n}\n\n.footer {\n background-color: #f8f9fa;\n bottom: 0;\n color: #8b8c8c;\n font-size: 0.9em;\n height: 50px;\n line-height: 50px;\n position: absolute;\n width: 100%;\n}\n\n/* Chrome, Safari, Edge, Opera */\n.form-disabled .form-group input::-webkit-outer-spin-button,\n.form-disabled .form-group input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\n/* Firefox */\n.form-disabled .form-group input[type=number] {\n -moz-appearance: textfield;\n}\n\n.form-disabled .form-group input{\n border: none;\n pointer-events: none;\n}\n\n\n.gpx-file {\n height: inherit;\n}\n\n.huge {\n font-size: 25px;\n}\n\n.i18n-flag svg {\n height: 100%;\n opacity: .9;\n width: 15px;\n}\n\n.inactive-link {\n color: lightgrey;\n}\n\n.leaflet-container {\n height: 400px;\n}\n\n.loader {\n animation: spin 2s linear infinite;\n border: 8px solid #f3f3f3;\n border-top: 8px solid #3498db;\n border-radius: 50%;\n height: 60px;\n margin-left: 41%;\n width: 60px;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.map-attribution {\n bottom: 0;\n font-size: 11px;\n position: absolute;\n}\n\n.map-attribution-text {\n background-color: rgba(255, 255, 255, .5);\n padding-left: 2px;\n padding-right: 2px;\n}\n\n.no-picture {\n color: #405976;\n}\n\n.page-title {\n font-size: 2em;\n margin: 1em;\n text-align: center;\n}\n\n.password-forget {\n margin: 10px;\n font-size: .9em;\n font-style: italic;\n}\n\n.radioLabel {\n text-align: center;\n}\n\n.record-logo {\n margin-right: 5px;\n max-width: 25px;\n max-height: 25px;\n}\n\n.record-table table, .record-table th, .record-table td{\n font-size: 0.9em;\n padding: 0.1em;\n}\n\n.sport-img {\n max-width: 35px;\n max-height: 35px;\n}\n\n.sport-img-medium {\n max-width: 45px;\n max-height: 45px;\n}\n\n.stats-disabled {\n opacity: 0.3;\n pointer-events: none;\n}\n\n.svg-icon {\n fill: #405976;\n height: 70px;\n margin-left: auto;\n margin-right: auto;\n width: 70px;\n}\n\n.time-frames {\n align-items: center;\n display: inline-flex;\n}\n\n.time-frame label {\n float: left;\n padding: 0 5px;\n}\n\n.time-frame label input {\n display: none;\n}\n\n.time-frame label span {\n border: #a9a9a9 solid 1px;\n border-radius: 9%;\n color: #7b7b7b;\n display: block;\n font-size: 0.9em;\n padding: 2px 6px;\n text-align: center;\n}\n\n.time-frame input:checked + span {\n background-color: #a9a9a9;\n color: #ffffff;\n}\n\n.timezone-custom {\n font-size: .9em !important;\n height: inherit !important;\n}\n\n.timezone-custom input {\n border: 0 !important;\n padding: 5px 1px !important;\n}\n\n.timezone-custom ul {\n background: white;\n}\n\n.timezone-picker {\n padding: 0;\n}\n\n.timezone-picker-textfield {\n font-size: 15px;\n}\n\n.unlink {\n color: black;\n}\n\n.user-filters {\n font-size: 0.9em;\n margin-bottom: 10px;\n}\n\n.user-label {\n font-weight: bold;\n}\n\n.weather-img {\n max-width: 35px;\n max-height: 35px;\n}\n\n.weather-img-small {\n max-width: 20px;\n max-height: 20px;\n}\n\n.weather-table {\n margin-bottom: 0;\n}\n\n.weather-table table, .weather-table th, .weather-table td{\n font-size: 0.9em;\n padding: 0.1em;\n}\n\n.workouts-result {\n font-size: 0.85em;\n}\n\n.workout-card {\n margin-bottom: 15px;\n}\n\n.workout-details {\n font-size: 0.95em;\n}\n.workout-date {\n font-size: 0.75em;\n}\n\n.workout-filter {\n font-size: 0.9em;\n}\n\n.workout-filter .col-2, .col-5{\n padding: 0;\n}\n\n.workout-label {\n font-size: 0.8em;\n color: #666\n}\n\n.workout-logo {\n margin: 0 5px;\n max-width: 20px;\n max-height: 20px;\n}\n\n.workout-map {\n background-color: #eaeaea;\n height: 225px;\n width: 400px;\n}\n\n.workout-no-map {\n background-color: #eaeaea;\n color: #666666;\n font-style: italic;\n height: 400px;\n line-height: 400px;\n}\n\n.workout-notes, .actvitiy-segments {\n font-size: 0.9em;\n font-style: italic;\n margin-top: 10px;\n padding: 5px;\n}\n\n.workout-page {\n margin-top: 20px;\n}\n\n.workout-segments-list {\n list-style: square;\n}\n\n.workout-sport {\n margin-right: 1px;\n max-width: 18px;\n max-height: 18px;\n}\n\n.workout-title img, .workout-title .map-attribution-list {\n display: none;\n}\n\n.workout-title img {\n border: 1px solid lightgrey;\n border-radius: 4px;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n display: none;\n margin-left: 20px;\n position: absolute;\n z-index: 1000;\n}\n\n.workout-title .map-attribution-list {\n display: none;\n font-size: 11px;\n margin-left: 20px;\n position: absolute;\n z-index: 1000;\n}\n\n.workout-title:hover img, .workout-title:hover .map-attribution-list {\n display: block;\n}\n\n/* responsive table */\n/* adapted from https://uglyduck.ca/making-tables-responsive-with-minimal-css/ */\n.heading-span,\n.heading-span-absolute {\n background: #eee;\n color: dimgrey;\n display: none;\n font-size: 10px;\n font-weight: bold;\n padding: 5px;\n text-transform: uppercase;\n top: 0;\n left: 0;\n}\n\n.heading-span-absolute {\n position: absolute;\n display: none;\n}\n\n@media(max-width: 1024px) {\n table thead {\n left: -9999px;\n position: absolute;\n visibility: hidden;\n }\n table tr {\n border-bottom: 0;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n margin-bottom: 40px;\n }\n table td {\n border: 1px solid lightgrey;\n margin: 0 -1px -1px 0;\n padding-top: 30px !important;\n position: relative;\n text-align: center;\n width: 50%;\n }\n .record-tr {\n margin-bottom: 0;\n }\n .record-td {\n padding-top: 0 !important;\n }\n .heading-span, .heading-span-absolute {\n display: block;\n }\n}\n\n/* calendar */\n:root {\n --main-color: #1a8fff;\n --text-color: #777;\n --text-color-light: #ccc;\n --border-color: #eee;\n --bg-color: #f9f9f9;\n --neutral-color: #fff;\n}\n\n.calendar .col-start {\n justify-content: flex-start;\n text-align: left;\n}\n\n.calendar .col-center {\n justify-content: center;\n text-align: center;\n}\n\n.calendar .col-end {\n justify-content: flex-end;\n text-align: right;\n}\n\n.calendar {\n display: block;\n position: relative;\n width: 100%;\n background: var(--neutral-color);\n border: 1px solid var(--border-color);\n}\n\n.calendar .header {\n text-transform: uppercase;\n font-weight: 700;\n /*font-size: 115%;*/\n padding: 0.5em 0;\n border-bottom: 1px solid var(--border-color);\n}\n\n.calendar .header .icon {\n cursor: pointer;\n transition: .15s ease-out;\n}\n\n.calendar .header .icon:hover {\n transform: scale(1.75);\n transition: .25s ease-out;\n color: var(--main-color);\n}\n\n.calendar .header .icon:first-of-type {\n margin-left: 1em;\n}\n\n.calendar .header .icon:last-of-type {\n margin-right: 1em;\n}\n\n.calendar .days {\n text-transform: uppercase;\n font-weight: 400;\n color: var(--text-color-light);\n font-size: 70%;\n padding: .75em 0;\n border-bottom: 1px solid var(--border-color);\n}\n\n.calendar .body .cell {\n position: relative;\n height: 3em;\n border-right: 1px solid var(--border-color);\n background: var(--neutral-color);\n}\n\n.calendar .body .cell:hover {\n background: var(--bg-color);\n}\n\n.calendar .body .selected {\n border-left: 10px solid transparent;\n border-image: linear-gradient(45deg, #1a8fff 0%,#53cbf1 40%);\n}\n\n.calendar .body .row {\n border-bottom: 1px solid var(--border-color);\n margin: 0;\n}\n\n.calendar .body .row:last-child {\n border-bottom: none;\n}\n\n.calendar .body .cell:last-child {\n border-right: none;\n}\n\n.calendar .body .cell .number {\n position: absolute;\n font-size: 82.5%;\n line-height: 1;\n top: .75em;\n right: .75em;\n font-weight: 700;\n}\n\n.calendar .body .disabled {\n color: var(--text-color-light);\n pointer-events: none;\n}\n\n.calendar .body .col {\n flex-grow: 0;\n flex-basis: calc(100%/7);\n width: calc(100%/7);\n}\n\n.calendar .body .img-disabled {\n opacity: .4;\n}\n\n.calendar .body .weekend {\n background: #f5f5f5;\n}\n\n.calendar .body .today {\n background: #eff1f3;\n}\n\n.calendar-workout,\n.calendar-more {\n display: none;\n}\n\n.calendar-more {\n color: #405976;\n font-size: .7em;\n margin-left: 0.3em;\n}\n\n.calendar-display-more {\n background: whitesmoke;\n border-radius: 4px;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n margin-bottom: 10px;\n padding: 10px 15px;\n position: absolute;\n min-width: 52px;\n z-index: 1000;\n}\n\n.calendar-workout-more {\n display: none;\n}\n\n@media only screen and (max-width: 992px) {\n\n .calendar-workout:nth-child(-n+2),\n .calendar-workout:nth-child(n+3) ~ .calendar-more,\n .calendar-workout-more:nth-child(n+3) {\n display: inline-block;\n }\n\n}\n\n@media only screen and (min-width: 992px) and (max-width: 1200px) {\n\n .calendar-workout:nth-child(-n+4),\n .calendar-workout:nth-child(n+5) ~ .calendar-more,\n .calendar-workout-more:nth-child(n+5) {\n display: inline-block;\n }\n\n}\n\n@media only screen and (min-width: 1200px) {\n\n .calendar-workout:nth-child(-n+6),\n .calendar-workout:nth-child(n+7) ~ .calendar-more,\n .calendar-workout-more:nth-child(n+7) {\n display: inline-block;\n }\n\n}\n"]} \ No newline at end of file diff --git a/fittrackee/dist/static/css/main.34182cc5.chunk.css b/fittrackee/dist/static/css/main.34182cc5.chunk.css deleted file mode 100644 index 4811e998..00000000 --- a/fittrackee/dist/static/css/main.34182cc5.chunk.css +++ /dev/null @@ -1,2 +0,0 @@ -html{height:100vh}body{background-color:#eaeaea;margin:0;min-height:100vh;padding-bottom:50px;position:relative}.App{padding-bottom:20px;text-align:center}.App-logo{-webkit-animation:App-logo-spin 20s linear infinite;animation:App-logo-spin 20s linear infinite;height:80px}.App-header{background-color:#222;height:150px;padding:20px;color:#fff}.App-title{font-size:1.5em}.App-intro{font-size:large}.App-nav-profile-img{max-width:32px;max-height:32px;border-radius:50%}.App-profile-img-small{max-width:150px;max-height:150px;border-radius:50%}@-webkit-keyframes App-logo-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes App-logo-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a{color:#40578a}input[type=text],label,textarea{width:100%}.activities-result{font-size:.85em}.activity-card{margin-bottom:15px}.activity-details{font-size:.95em}.activity-date{font-size:.75em}.activity-filter{font-size:.9em}.activity-filter .col-2,.col-5{padding:0}.activity-label{font-size:.8em;color:#666}.activity-logo{margin:0 5px;max-width:20px;max-height:20px}.activity-map{background-color:#eaeaea;height:225px;width:400px}.activity-no-map{background-color:#eaeaea;color:#666;font-style:italic;height:400px;line-height:400px}.activity-notes,.actvitiy-segments{font-size:.9em;font-style:italic;margin-top:10px;padding:5px}.activity-page{margin-top:20px}.activity-segments-list{list-style:square}.activity-sport{margin-right:1px;max-width:18px;max-height:18px}.activity-title .map-attribution-list,.activity-title img{display:none}.activity-title img{border:1px solid #d3d3d3;border-radius:4px;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}.activity-title .map-attribution-list,.activity-title img{display:none;margin-left:20px;position:absolute;z-index:1000}.activity-title .map-attribution-list{font-size:11px}.activity-title:hover .map-attribution-list,.activity-title:hover img{display:block}.add-activity{margin-top:50px}.add-activity-radio{margin-right:10px}.admin-img{max-width:35px;max-height:35px}.admin-items{list-style-type:square}.admin-message{color:#7c7c7d;font-size:.9em;font-style:italic;margin-left:10px}.app-config-form label{font-weight:700}.btn{margin-right:10px}.card{text-align:left}.chart{font-size:.9em}.chart-activities{margin-left:60px}.chart-arrows{margin-top:7px}.chart-filters{padding-bottom:10px}.chart-info{font-size:.8em;font-style:italic}.chart-radio{display:flex;font-size:.9em}.chart-radio input{margin-right:10px}.chart-stats{font-size:.8em}.chart-title{font-size:1.1em;margin-bottom:10px}.col-activity-logo{padding-right:0}.custom-modal{background-color:#fff;border-radius:5px;max-width:500px;margin:20% auto;z-index:1250}.custom-modal-backdrop{position:fixed;top:0;bottom:0;left:0;right:0;background-color:rgba(0,0,0,.3);padding:50px;z-index:1240}.custom-fa{margin-right:5px}.custom-fa-small{font-size:.8em;margin-left:-.8em}@media only screen and (max-width:992px){.custom-fa-small{font-size:.6em}}.custom-tooltip{background-color:#fff;border:1px solid #d3d3d3;padding:10px}.custom-tooltip p{margin:5px}.custom-tooltip-label{font-weight:700}.dashboard{height:100%}.dashboard,.history{margin-top:30px}.dropdown-wrapper{width:50px}.dropdown-list{background-color:#f8f9fa;padding:5px 0;position:absolute;text-align:left;z-index:10}.dropdown-item{cursor:default;font-size:.9em}.dropdown-item-selected{font-weight:700}.dropdown-item-selected:after{content:" ✔"}.error-message{margin-top:10px}.fa-as-link{cursor:pointer;color:#40578a}.fa-as-link:hover{color:#0056b3}.fa-question-circle{color:#6c757d;margin-left:3px}.fa-trophy{color:#daa520}.fa-color{color:#405976}.footer{background-color:#f8f9fa;bottom:0;color:#8b8c8c;font-size:.9em;height:50px;line-height:50px;position:absolute;width:100%}.form-disabled .form-group input::-webkit-inner-spin-button,.form-disabled .form-group input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.form-disabled .form-group input[type=number]{-moz-appearance:textfield}.form-disabled .form-group input{border:none;pointer-events:none}.gpx-file{height:inherit}.huge{font-size:25px}.i18n-flag svg{height:100%;opacity:.9;width:15px}.inactive-link{color:#d3d3d3}.leaflet-container{height:400px}.loader{-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;border:8px solid #f3f3f3;border-top-color:#3498db;border-radius:50%;height:60px;margin-left:41%;width:60px}@-webkit-keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.map-attribution{bottom:0;font-size:11px;position:absolute}.map-attribution-text{background-color:hsla(0,0%,100%,.5);padding-left:2px;padding-right:2px}.no-picture{color:#405976}.page-title{font-size:2em;margin:1em;text-align:center}.password-forget{margin:10px;font-size:.9em;font-style:italic}.radioLabel{text-align:center}.record-logo{margin-right:5px;max-width:25px;max-height:25px}.record-table table,.record-table td,.record-table th{font-size:.9em;padding:.1em}.sport-img{max-width:35px;max-height:35px}.sport-img-medium{max-width:45px;max-height:45px}.stats-disabled{opacity:.3;pointer-events:none}.svg-icon{fill:#405976;height:70px;margin-left:auto;margin-right:auto;width:70px}.time-frames{align-items:center;display:inline-flex}.time-frame label{float:left;padding:0 5px}.time-frame label input{display:none}.time-frame label span{border:1px solid #a9a9a9;border-radius:9%;color:#7b7b7b;display:block;font-size:.9em;padding:2px 6px;text-align:center}.time-frame input:checked+span{background-color:#a9a9a9;color:#fff}.timezone-custom{font-size:.9em!important;height:inherit!important}.timezone-custom input{border:0!important;padding:5px 1px!important}.timezone-custom ul{background:#fff}.timezone-picker{padding:0}.timezone-picker-textfield{font-size:15px}.unlink{color:#000}.user-filters{font-size:.9em;margin-bottom:10px}.user-label{font-weight:700}.weather-img{max-width:35px;max-height:35px}.weather-img-small{max-width:20px;max-height:20px}.weather-table{margin-bottom:0}.weather-table table,.weather-table td,.weather-table th{font-size:.9em;padding:.1em}.heading-span,.heading-span-absolute{background:#eee;color:#696969;display:none;font-size:10px;font-weight:700;padding:5px;text-transform:uppercase;top:0;left:0}.heading-span-absolute{position:absolute;display:none}@media(max-width:1024px){table thead{left:-9999px;position:absolute;visibility:hidden}table tr{border-bottom:0;display:flex;flex-direction:row;flex-wrap:wrap;margin-bottom:40px}table td{border:1px solid #d3d3d3;margin:0 -1px -1px 0;padding-top:30px!important;position:relative;text-align:center;width:50%}.record-tr{margin-bottom:0}.record-td{padding-top:0!important}.heading-span,.heading-span-absolute{display:block}}:root{--main-color:#1a8fff;--text-color:#777;--text-color-light:#ccc;--border-color:#eee;--bg-color:#f9f9f9;--neutral-color:#fff}.calendar .col-start{justify-content:flex-start;text-align:left}.calendar .col-center{justify-content:center;text-align:center}.calendar .col-end{justify-content:flex-end;text-align:right}.calendar{display:block;position:relative;width:100%;background:#fff;background:var(--neutral-color);border:1px solid #eee;border:1px solid var(--border-color)}.calendar .header{text-transform:uppercase;font-weight:700;padding:.5em 0;border-bottom:1px solid #eee;border-bottom:1px solid var(--border-color)}.calendar .header .icon{cursor:pointer;transition:.15s ease-out}.calendar .header .icon:hover{transform:scale(1.75);transition:.25s ease-out;color:#1a8fff;color:var(--main-color)}.calendar .header .icon:first-of-type{margin-left:1em}.calendar .header .icon:last-of-type{margin-right:1em}.calendar .days{text-transform:uppercase;font-weight:400;color:#ccc;color:var(--text-color-light);font-size:70%;padding:.75em 0;border-bottom:1px solid #eee;border-bottom:1px solid var(--border-color)}.calendar .body .cell{position:relative;height:3em;border-right:1px solid #eee;border-right:1px solid var(--border-color);background:#fff;background:var(--neutral-color)}.calendar .body .cell:hover{background:#f9f9f9;background:var(--bg-color)}.calendar .body .selected{border-left:10px solid transparent;border-image:linear-gradient(45deg,#1a8fff,#53cbf1 40%)}.calendar .body .row{border-bottom:1px solid #eee;border-bottom:1px solid var(--border-color);margin:0}.calendar .body .row:last-child{border-bottom:none}.calendar .body .cell:last-child{border-right:none}.calendar .body .cell .number{position:absolute;font-size:82.5%;line-height:1;top:.75em;right:.75em;font-weight:700}.calendar .body .disabled{color:#ccc;color:var(--text-color-light);pointer-events:none}.calendar .body .col{flex-grow:0;flex-basis:14.28571%;width:14.28571%}.calendar .body .img-disabled{opacity:.4}.calendar .body .weekend{background:#f5f5f5}.calendar .body .today{background:#eff1f3}.calendar-activity,.calendar-more{display:none}.calendar-more{color:#405976;font-size:.7em;margin-left:.3em}.calendar-display-more{background:#f5f5f5;border-radius:4px;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19);margin-bottom:10px;padding:10px 15px;position:absolute;min-width:52px;z-index:1000}.calendar-activity-more{display:none}@media only screen and (max-width:992px){.calendar-activity-more:nth-child(n+3),.calendar-activity:nth-child(-n+2),.calendar-activity:nth-child(n+3)~.calendar-more{display:inline-block}}@media only screen and (min-width:992px) and (max-width:1200px){.calendar-activity-more:nth-child(n+5),.calendar-activity:nth-child(-n+4),.calendar-activity:nth-child(n+5)~.calendar-more{display:inline-block}}@media only screen and (min-width:1200px){.calendar-activity-more:nth-child(n+7),.calendar-activity:nth-child(-n+6),.calendar-activity:nth-child(n+7)~.calendar-more{display:inline-block}} -/*# sourceMappingURL=main.34182cc5.chunk.css.map */ \ No newline at end of file diff --git a/fittrackee/dist/static/css/main.34182cc5.chunk.css.map b/fittrackee/dist/static/css/main.34182cc5.chunk.css.map deleted file mode 100644 index a63c6121..00000000 --- a/fittrackee/dist/static/css/main.34182cc5.chunk.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack://src/components/App.css"],"names":[],"mappings":"AAAA,KACE,YACF,CAEA,KACE,wBAAyB,CACzB,QAAS,CACT,gBAAiB,CACjB,mBAAoB,CACpB,iBACA,CAEF,KACE,mBAAoB,CACpB,iBACF,CAEA,UACE,mDAA4C,CAA5C,2CAA4C,CAC5C,WACF,CAEA,YACE,qBAAsB,CACtB,YAAa,CACb,YAAa,CACb,UACF,CAEA,WACE,eACF,CAEA,WACE,eACF,CAEA,qBACE,cAAe,CACf,eAAgB,CAChB,iBACF,CAEA,uBACE,eAAgB,CAChB,gBAAiB,CACjB,iBACF,CAEA,iCACE,GAAO,sBAAyB,CAChC,GAAK,uBAA2B,CAClC,CAHA,yBACE,GAAO,sBAAyB,CAChC,GAAK,uBAA2B,CAClC,CAEA,EACE,aACF,CAMA,gCACE,UACF,CAEA,mBACE,eACF,CAEA,eACE,kBACF,CAEA,kBACE,eACF,CACA,eACE,eACF,CAEA,iBACE,cACF,CAEA,+BACE,SACF,CAEA,gBACE,cAAgB,CAChB,UACF,CAEA,eACE,YAAa,CACb,cAAe,CACf,eACF,CAEA,cACE,wBAAyB,CACzB,YAAa,CACb,WACF,CAEA,iBACE,wBAAyB,CACzB,UAAc,CACd,iBAAkB,CAClB,YAAa,CACb,iBACF,CAEA,mCACE,cAAgB,CAChB,iBAAkB,CAClB,eAAgB,CAChB,WACF,CAEA,eACE,eACF,CAEA,wBACE,iBACF,CAEA,gBACE,gBAAiB,CACjB,cAAe,CACf,eACF,CAEA,0DACE,YACF,CAEA,oBACE,wBAA2B,CAC3B,iBAAkB,CAClB,kEAKF,CAEA,0DANE,YAAa,CACb,gBAAiB,CACjB,iBAAkB,CAClB,YASF,CANA,sCAEE,cAIF,CAEA,sEACE,aACF,CAEA,cACE,eACF,CAEA,oBACE,iBACF,CAEA,WACE,cAAe,CACf,eACF,CAEA,aACE,sBACF,CAEA,eACE,aAAc,CACd,cAAgB,CAChB,iBAAkB,CAClB,gBACF,CAEA,uBACE,eACF,CAEA,KACE,iBACF,CAEA,MACE,eACF,CAEA,OACE,cACF,CAEA,kBACE,gBACF,CAEA,cACE,cACF,CAEA,eACE,mBACF,CAEA,YACE,cAAgB,CAChB,iBACF,CAEA,aACE,YAAa,CACb,cACF,CAMA,mBACE,iBACF,CAEA,aACE,cACF,CAEA,aACE,eAAgB,CAChB,kBACF,CAEA,mBACE,eACF,CAEA,cACE,qBAAsB,CACtB,iBAAkB,CAClB,eAAgB,CAChB,eAAgB,CAChB,YACF,CAEA,uBACE,cAAe,CACf,KAAM,CACN,QAAS,CACT,MAAO,CACP,OAAQ,CACR,+BAAiC,CACjC,YAAa,CACb,YACF,CAEA,WACE,gBACF,CAEA,iBACE,cAAgB,CAChB,iBACF,CAEA,yCACE,iBACE,cACF,CACF,CAEA,gBACE,qBAAsB,CACtB,wBAA2B,CAC3B,YACF,CAEA,kBACE,UACF,CAEA,sBACE,eACF,CAEA,WACE,WACF,CACA,oBACE,eACF,CAEA,kBACE,UACF,CAEA,eACE,wBAAyB,CACzB,aAAc,CACd,iBAAkB,CAClB,eAAgB,CAChB,UACF,CAEA,eACE,cAAe,CACf,cACF,CAEA,wBACE,eACF,CAEA,8BACE,YACF,CAEA,eACE,eACF,CAEA,YACE,cAAc,CACd,aACF,CAEA,kBACE,aACF,CAEA,oBACE,aAAc,CACd,eACF,CAEA,WACE,aACF,CAEA,UACE,aACF,CAEA,QACE,wBAAyB,CACzB,QAAS,CACT,aAAc,CACd,cAAgB,CAChB,WAAY,CACZ,gBAAiB,CACjB,iBAAkB,CAClB,UACF,CAGA,wHAEE,uBAAwB,CACxB,QACF,CAGA,8CACE,yBACF,CAEA,iCACE,WAAY,CACZ,mBACF,CAGA,UACE,cACF,CAEA,MACE,cACF,CAEA,eACE,WAAY,CACZ,UAAW,CACX,UACF,CAEA,eACE,aACF,CAEA,mBACE,YACF,CAEA,QACE,yCAAkC,CAAlC,iCAAkC,CAElC,wBAA6B,CAA7B,wBAA6B,CAC7B,iBAAkB,CAClB,WAAY,CACZ,eAAgB,CAChB,UACF,CAEA,wBACE,GAAK,sBAAyB,CAC9B,GAAO,uBAA2B,CACpC,CAHA,gBACE,GAAK,sBAAyB,CAC9B,GAAO,uBAA2B,CACpC,CAEA,iBACE,QAAS,CACT,cAAe,CACf,iBACF,CAEA,sBACE,mCAAyC,CACzC,gBAAiB,CACjB,iBACF,CAEA,YACE,aACF,CAEA,YACE,aAAc,CACd,UAAW,CACX,iBACF,CAEA,iBACE,WAAY,CACZ,cAAe,CACf,iBACF,CAEA,YACE,iBACF,CAEA,aACE,gBAAiB,CACjB,cAAe,CACf,eACF,CAEA,sDACE,cAAgB,CAChB,YACF,CAEA,WACE,cAAe,CACf,eACF,CAEA,kBACE,cAAe,CACf,eACF,CAEA,gBACE,UAAY,CACZ,mBACF,CAEA,UACE,YAAa,CACb,WAAY,CACZ,gBAAiB,CACjB,iBAAkB,CAClB,UACF,CAEA,aACE,kBAAmB,CACnB,mBACF,CAEA,kBACE,UAAW,CACX,aACF,CAEA,wBACE,YACF,CAEA,uBACE,wBAAyB,CACzB,gBAAiB,CACjB,aAAc,CACd,aAAc,CACd,cAAgB,CAChB,eAAgB,CAChB,iBACF,CAEA,+BACE,wBAAyB,CACzB,UACF,CAEA,iBACE,wBAA0B,CAC1B,wBACF,CAEA,uBACE,kBAAoB,CACpB,yBACF,CAEA,oBACE,eACF,CAEA,iBACE,SACF,CAEA,2BACE,cACF,CAEA,QACE,UACF,CAEA,cACE,cAAgB,CAChB,kBACF,CAEA,YACE,eACF,CAEA,aACE,cAAe,CACf,eACF,CAEA,mBACE,cAAe,CACf,eACF,CAEA,eACE,eACF,CAEA,yDACE,cAAgB,CAChB,YACF,CAIA,qCAEE,eAAgB,CAChB,aAAc,CACd,YAAa,CACb,cAAe,CACf,eAAiB,CACjB,WAAY,CACZ,wBAAyB,CACzB,KAAM,CACN,MACF,CAEA,uBACE,iBAAkB,CAClB,YACF,CAEA,yBACE,YACE,YAAa,CACb,iBAAkB,CAClB,iBACF,CACA,SACE,eAAgB,CAChB,YAAa,CACb,kBAAmB,CACnB,cAAe,CACf,kBACF,CACA,SACE,wBAA2B,CAC3B,oBAAqB,CACrB,0BAA4B,CAC5B,iBAAkB,CAClB,iBAAkB,CAClB,SACF,CACA,WACE,eACF,CACA,WACE,uBACF,CACA,qCACE,aACF,CACF,CAGA,MACE,oBAAqB,CACrB,iBAAkB,CAClB,uBAAwB,CACxB,mBAAoB,CACpB,kBAAmB,CACnB,oBACF,CAEA,qBACE,0BAA2B,CAC3B,eACF,CAEA,sBACE,sBAAuB,CACvB,iBACF,CAEA,mBACE,wBAAyB,CACzB,gBACF,CAEA,UACE,aAAc,CACd,iBAAkB,CAClB,UAAW,CACX,eAAgC,CAAhC,+BAAgC,CAChC,qBAAqC,CAArC,oCACF,CAEA,kBACE,wBAAyB,CACzB,eAAgB,CAEhB,cAAgB,CAChB,4BAA4C,CAA5C,2CACF,CAEA,wBACE,cAAe,CACf,wBACF,CAEA,8BACE,qBAAsB,CACtB,wBAAyB,CACzB,aAAwB,CAAxB,uBACF,CAEA,sCACE,eACF,CAEA,qCACE,gBACF,CAEA,gBACE,wBAAyB,CACzB,eAAgB,CAChB,UAA8B,CAA9B,6BAA8B,CAC9B,aAAc,CACd,eAAgB,CAChB,4BAA4C,CAA5C,2CACF,CAEA,sBACE,iBAAkB,CAClB,UAAW,CACX,2BAA2C,CAA3C,0CAA2C,CAC3C,eAAgC,CAAhC,+BACF,CAEA,4BACE,kBAA2B,CAA3B,0BACF,CAEA,0BACE,kCAAmC,CACnC,uDACF,CAEA,qBACE,4BAA4C,CAA5C,2CAA4C,CAC5C,QACF,CAEA,gCACE,kBACF,CAEA,iCACE,iBACF,CAEA,8BACE,iBAAkB,CAClB,eAAgB,CAChB,aAAc,CACd,SAAU,CACV,WAAY,CACZ,eACF,CAEA,0BACE,UAA8B,CAA9B,6BAA8B,CAC9B,mBACF,CAEA,qBACE,WAAY,CACZ,oBAAwB,CACxB,eACF,CAEA,8BACE,UACF,CAEA,yBACE,kBACF,CAEA,uBACE,kBACF,CAEA,kCAEE,YACF,CAEA,eACE,aAAc,CACd,cAAe,CACf,gBACF,CAEA,uBACE,kBAAsB,CACtB,iBAAkB,CAClB,kEAA4E,CAC5E,kBAAmB,CACnB,iBAAkB,CAClB,iBAAkB,CAClB,cAAe,CACf,YACF,CAEA,wBACE,YACF,CAEA,yCAEE,2HAGE,oBACF,CAEF,CAEA,gEAEE,2HAGE,oBACF,CAEF,CAEA,0CAEE,2HAGE,oBACF,CAEF","file":"main.34182cc5.chunk.css","sourcesContent":["html {\n height: 100vh;\n}\n\nbody {\n background-color: #eaeaea;\n margin: 0;\n min-height: 100vh;\n padding-bottom: 50px;\n position: relative;\n }\n\n.App {\n padding-bottom: 20px;\n text-align: center;\n}\n\n.App-logo {\n animation: App-logo-spin infinite 20s linear;\n height: 80px;\n}\n\n.App-header {\n background-color: #222;\n height: 150px;\n padding: 20px;\n color: white;\n}\n\n.App-title {\n font-size: 1.5em;\n}\n\n.App-intro {\n font-size: large;\n}\n\n.App-nav-profile-img {\n max-width: 32px;\n max-height: 32px;\n border-radius: 50%;\n}\n\n.App-profile-img-small {\n max-width: 150px;\n max-height: 150px;\n border-radius: 50%;\n}\n\n@keyframes App-logo-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\na {\n color: #40578a;\n}\n\ninput[type=\"text\"], textarea {\n width: 100%;\n}\n\nlabel {\n width: 100%;\n}\n\n.activities-result {\n font-size: 0.85em;\n}\n\n.activity-card {\n margin-bottom: 15px;\n}\n\n.activity-details {\n font-size: 0.95em;\n}\n.activity-date {\n font-size: 0.75em;\n}\n\n.activity-filter {\n font-size: 0.9em;\n}\n\n.activity-filter .col-2, .col-5{\n padding: 0;\n}\n\n.activity-label {\n font-size: 0.8em;\n color: #666\n}\n\n.activity-logo {\n margin: 0 5px;\n max-width: 20px;\n max-height: 20px;\n}\n\n.activity-map {\n background-color: #eaeaea;\n height: 225px;\n width: 400px;\n}\n\n.activity-no-map {\n background-color: #eaeaea;\n color: #666666;\n font-style: italic;\n height: 400px;\n line-height: 400px;\n}\n\n.activity-notes, .actvitiy-segments {\n font-size: 0.9em;\n font-style: italic;\n margin-top: 10px;\n padding: 5px;\n}\n\n.activity-page {\n margin-top: 20px;\n}\n\n.activity-segments-list {\n list-style: square;\n}\n\n.activity-sport {\n margin-right: 1px;\n max-width: 18px;\n max-height: 18px;\n}\n\n.activity-title img, .activity-title .map-attribution-list {\n display: none;\n}\n\n.activity-title img {\n border: 1px solid lightgrey;\n border-radius: 4px;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n display: none;\n margin-left: 20px;\n position: absolute;\n z-index: 1000;\n}\n\n.activity-title .map-attribution-list {\n display: none;\n font-size: 11px;\n margin-left: 20px;\n position: absolute;\n z-index: 1000;\n}\n\n.activity-title:hover img, .activity-title:hover .map-attribution-list {\n display: block;\n}\n\n.add-activity {\n margin-top: 50px;\n}\n\n.add-activity-radio {\n margin-right: 10px;\n}\n\n.admin-img {\n max-width: 35px;\n max-height: 35px;\n}\n\n.admin-items {\n list-style-type: square;\n}\n\n.admin-message {\n color: #7c7c7d;\n font-size: 0.9em;\n font-style: italic;\n margin-left: 10px;\n}\n\n.app-config-form label {\n font-weight: bold;\n}\n\n.btn {\n margin-right: 10px;\n}\n\n.card {\n text-align: left;\n}\n\n.chart {\n font-size: 0.9em;\n}\n\n.chart-activities {\n margin-left: 60px;\n}\n\n.chart-arrows {\n margin-top: 7px;\n}\n\n.chart-filters {\n padding-bottom: 10px;\n}\n\n.chart-info {\n font-size: 0.8em;\n font-style: italic;\n}\n\n.chart-radio {\n display: flex;\n font-size: 0.9em;\n}\n\n.chart-radio label {\n /* display: flex; */\n}\n\n.chart-radio input {\n margin-right: 10px;\n}\n\n.chart-stats {\n font-size: 0.8em;\n}\n\n.chart-title {\n font-size: 1.1em;\n margin-bottom: 10px;\n}\n\n.col-activity-logo{\n padding-right: 0;\n}\n\n.custom-modal {\n background-color: #fff;\n border-radius: 5px;\n max-width: 500px;\n margin: 20% auto;\n z-index: 1250;\n}\n\n.custom-modal-backdrop {\n position: fixed;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n background-color: rgba(0,0,0,0.3);\n padding: 50px;\n z-index: 1240;\n}\n\n.custom-fa {\n margin-right: 5px;\n}\n\n.custom-fa-small {\n font-size: 0.8em;\n margin-left: -0.8em;\n}\n\n@media only screen and (max-width: 992px) {\n .custom-fa-small {\n font-size: 0.6em;\n }\n}\n\n.custom-tooltip {\n background-color: #fff;\n border: 1px solid lightgrey;\n padding: 10px;\n}\n\n.custom-tooltip p {\n margin: 5px;\n}\n\n.custom-tooltip-label {\n font-weight: bold;\n}\n\n.dashboard {\n height: 100%;\n}\n.dashboard, .history {\n margin-top: 30px;\n}\n\n.dropdown-wrapper {\n width: 50px;\n}\n\n.dropdown-list {\n background-color: #f8f9fa;\n padding: 5px 0;\n position: absolute;\n text-align: left;\n z-index: 10;\n}\n\n.dropdown-item {\n cursor: default;\n font-size: 0.9em;\n}\n\n.dropdown-item-selected {\n font-weight: bold;\n}\n\n.dropdown-item-selected::after {\n content: \" ✔\";\n}\n\n.error-message {\n margin-top: 10px;\n}\n\n.fa-as-link {\n cursor:pointer;\n color: #40578a;\n}\n\n.fa-as-link:hover {\n color: #0056b3;\n}\n\n.fa-question-circle {\n color: #6c757d;\n margin-left: 3px;\n}\n\n.fa-trophy {\n color: goldenrod;\n}\n\n.fa-color {\n color: #405976;\n}\n\n.footer {\n background-color: #f8f9fa;\n bottom: 0;\n color: #8b8c8c;\n font-size: 0.9em;\n height: 50px;\n line-height: 50px;\n position: absolute;\n width: 100%;\n}\n\n/* Chrome, Safari, Edge, Opera */\n.form-disabled .form-group input::-webkit-outer-spin-button,\n.form-disabled .form-group input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n\n/* Firefox */\n.form-disabled .form-group input[type=number] {\n -moz-appearance: textfield;\n}\n\n.form-disabled .form-group input{\n border: none;\n pointer-events: none;\n}\n\n\n.gpx-file {\n height: inherit;\n}\n\n.huge {\n font-size: 25px;\n}\n\n.i18n-flag svg {\n height: 100%;\n opacity: .9;\n width: 15px;\n}\n\n.inactive-link {\n color: lightgrey;\n}\n\n.leaflet-container {\n height: 400px;\n}\n\n.loader {\n animation: spin 2s linear infinite;\n border: 8px solid #f3f3f3;\n border-top: 8px solid #3498db;\n border-radius: 50%;\n height: 60px;\n margin-left: 41%;\n width: 60px;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.map-attribution {\n bottom: 0;\n font-size: 11px;\n position: absolute;\n}\n\n.map-attribution-text {\n background-color: rgba(255, 255, 255, .5);\n padding-left: 2px;\n padding-right: 2px;\n}\n\n.no-picture {\n color: #405976;\n}\n\n.page-title {\n font-size: 2em;\n margin: 1em;\n text-align: center;\n}\n\n.password-forget {\n margin: 10px;\n font-size: .9em;\n font-style: italic;\n}\n\n.radioLabel {\n text-align: center;\n}\n\n.record-logo {\n margin-right: 5px;\n max-width: 25px;\n max-height: 25px;\n}\n\n.record-table table, .record-table th, .record-table td{\n font-size: 0.9em;\n padding: 0.1em;\n}\n\n.sport-img {\n max-width: 35px;\n max-height: 35px;\n}\n\n.sport-img-medium {\n max-width: 45px;\n max-height: 45px;\n}\n\n.stats-disabled {\n opacity: 0.3;\n pointer-events: none;\n}\n\n.svg-icon {\n fill: #405976;\n height: 70px;\n margin-left: auto;\n margin-right: auto;\n width: 70px;\n}\n\n.time-frames {\n align-items: center;\n display: inline-flex;\n}\n\n.time-frame label {\n float: left;\n padding: 0 5px;\n}\n\n.time-frame label input {\n display: none;\n}\n\n.time-frame label span {\n border: #a9a9a9 solid 1px;\n border-radius: 9%;\n color: #7b7b7b;\n display: block;\n font-size: 0.9em;\n padding: 2px 6px;\n text-align: center;\n}\n\n.time-frame input:checked + span {\n background-color: #a9a9a9;\n color: #ffffff;\n}\n\n.timezone-custom {\n font-size: .9em !important;\n height: inherit !important;\n}\n\n.timezone-custom input {\n border: 0 !important;\n padding: 5px 1px !important;\n}\n\n.timezone-custom ul {\n background: white;\n}\n\n.timezone-picker {\n padding: 0;\n}\n\n.timezone-picker-textfield {\n font-size: 15px;\n}\n\n.unlink {\n color: black;\n}\n\n.user-filters {\n font-size: 0.9em;\n margin-bottom: 10px;\n}\n\n.user-label {\n font-weight: bold;\n}\n\n.weather-img {\n max-width: 35px;\n max-height: 35px;\n}\n\n.weather-img-small {\n max-width: 20px;\n max-height: 20px;\n}\n\n.weather-table {\n margin-bottom: 0;\n}\n\n.weather-table table, .weather-table th, .weather-table td{\n font-size: 0.9em;\n padding: 0.1em;\n}\n\n/* responsive table */\n/* adapted from https://uglyduck.ca/making-tables-responsive-with-minimal-css/ */\n.heading-span,\n.heading-span-absolute {\n background: #eee;\n color: dimgrey;\n display: none;\n font-size: 10px;\n font-weight: bold;\n padding: 5px;\n text-transform: uppercase;\n top: 0;\n left: 0;\n}\n\n.heading-span-absolute {\n position: absolute;\n display: none;\n}\n\n@media(max-width: 1024px) {\n table thead {\n left: -9999px;\n position: absolute;\n visibility: hidden;\n }\n table tr {\n border-bottom: 0;\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n margin-bottom: 40px;\n }\n table td {\n border: 1px solid lightgrey;\n margin: 0 -1px -1px 0;\n padding-top: 30px !important;\n position: relative;\n text-align: center;\n width: 50%;\n }\n .record-tr {\n margin-bottom: 0;\n }\n .record-td {\n padding-top: 0 !important;\n }\n .heading-span, .heading-span-absolute {\n display: block;\n }\n}\n\n/* calendar */\n:root {\n --main-color: #1a8fff;\n --text-color: #777;\n --text-color-light: #ccc;\n --border-color: #eee;\n --bg-color: #f9f9f9;\n --neutral-color: #fff;\n}\n\n.calendar .col-start {\n justify-content: flex-start;\n text-align: left;\n}\n\n.calendar .col-center {\n justify-content: center;\n text-align: center;\n}\n\n.calendar .col-end {\n justify-content: flex-end;\n text-align: right;\n}\n\n.calendar {\n display: block;\n position: relative;\n width: 100%;\n background: var(--neutral-color);\n border: 1px solid var(--border-color);\n}\n\n.calendar .header {\n text-transform: uppercase;\n font-weight: 700;\n /*font-size: 115%;*/\n padding: 0.5em 0;\n border-bottom: 1px solid var(--border-color);\n}\n\n.calendar .header .icon {\n cursor: pointer;\n transition: .15s ease-out;\n}\n\n.calendar .header .icon:hover {\n transform: scale(1.75);\n transition: .25s ease-out;\n color: var(--main-color);\n}\n\n.calendar .header .icon:first-of-type {\n margin-left: 1em;\n}\n\n.calendar .header .icon:last-of-type {\n margin-right: 1em;\n}\n\n.calendar .days {\n text-transform: uppercase;\n font-weight: 400;\n color: var(--text-color-light);\n font-size: 70%;\n padding: .75em 0;\n border-bottom: 1px solid var(--border-color);\n}\n\n.calendar .body .cell {\n position: relative;\n height: 3em;\n border-right: 1px solid var(--border-color);\n background: var(--neutral-color);\n}\n\n.calendar .body .cell:hover {\n background: var(--bg-color);\n}\n\n.calendar .body .selected {\n border-left: 10px solid transparent;\n border-image: linear-gradient(45deg, #1a8fff 0%,#53cbf1 40%);\n}\n\n.calendar .body .row {\n border-bottom: 1px solid var(--border-color);\n margin: 0;\n}\n\n.calendar .body .row:last-child {\n border-bottom: none;\n}\n\n.calendar .body .cell:last-child {\n border-right: none;\n}\n\n.calendar .body .cell .number {\n position: absolute;\n font-size: 82.5%;\n line-height: 1;\n top: .75em;\n right: .75em;\n font-weight: 700;\n}\n\n.calendar .body .disabled {\n color: var(--text-color-light);\n pointer-events: none;\n}\n\n.calendar .body .col {\n flex-grow: 0;\n flex-basis: calc(100%/7);\n width: calc(100%/7);\n}\n\n.calendar .body .img-disabled {\n opacity: .4;\n}\n\n.calendar .body .weekend {\n background: #f5f5f5;\n}\n\n.calendar .body .today {\n background: #eff1f3;\n}\n\n.calendar-activity,\n.calendar-more {\n display: none;\n}\n\n.calendar-more {\n color: #405976;\n font-size: .7em;\n margin-left: 0.3em;\n}\n\n.calendar-display-more {\n background: whitesmoke;\n border-radius: 4px;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n margin-bottom: 10px;\n padding: 10px 15px;\n position: absolute;\n min-width: 52px;\n z-index: 1000;\n}\n\n.calendar-activity-more {\n display: none;\n}\n\n@media only screen and (max-width: 992px) {\n\n .calendar-activity:nth-child(-n+2),\n .calendar-activity:nth-child(n+3) ~ .calendar-more,\n .calendar-activity-more:nth-child(n+3) {\n display: inline-block;\n }\n\n}\n\n@media only screen and (min-width: 992px) and (max-width: 1200px) {\n\n .calendar-activity:nth-child(-n+4),\n .calendar-activity:nth-child(n+5) ~ .calendar-more,\n .calendar-activity-more:nth-child(n+5) {\n display: inline-block;\n }\n\n}\n\n@media only screen and (min-width: 1200px) {\n\n .calendar-activity:nth-child(-n+6),\n .calendar-activity:nth-child(n+7) ~ .calendar-more,\n .calendar-activity-more:nth-child(n+7) {\n display: inline-block;\n }\n\n}\n"]} \ No newline at end of file diff --git a/fittrackee/dist/static/js/main.385ae13c.chunk.js b/fittrackee/dist/static/js/main.385ae13c.chunk.js deleted file mode 100644 index 3a1e844d..00000000 --- a/fittrackee/dist/static/js/main.385ae13c.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[]).push([[0],{198:function(e){e.exports=JSON.parse('{"Activities":"Activities","Activity":"Activity","Activity Date":"Activity Date","Add a workout":"Add a workout","Are you sure you want to delete this activity?":"Are you sure you want to delete this activity?","Ave. speed":"Ave. speed","Ascent":"Ascent","Average speed":"Average speed","Chart":"Chart","data from gpx, without any cleaning":"data from gpx, without any cleaning","Date":"Date","Delete activity":"Delete activity","Descent":"Descent","Distance":"Distance","distance":"distance","Duration":"Duration","duration":"duration","Edit a workout":"Edit a workout","Edit activity":"Edit activity","elevation":"elevation","End":"End","Farest distance":"Farest distance","Filter":"Filter","From":"From","gpxFile":"gpx file","Longest duration":"Longest duration","Max. altitude":"Max. altitude","Max. speed":"Max. speed","Min. altitude":"Min. altitude","no folder inside":"no folder inside","files max":"files max","max size":"max size","No data to display":"No data to display","No Map":"No Map","No next activity":"No next activity","No next segment":"No next segment","No notes":"No notes","No previous activity":"No previous activity","No previous segment":"No previous segment","Notes":"Notes","pauses":"pauses","Personal records":"Personal records","See next activity":"See next activity","See next segment":"See next segment","See previous activity":"See previous activity","See previous segment":"See previous segment","segment":"segment","Segments":"Segments","speed":"speed","Start":"Start","Title":"Title","To":"To","total duration":"total duration","with gpx file":"with gpx file","without gpx file":"without gpx file","zipFile":"or zip file containing gpx files"}')},199:function(e){e.exports=JSON.parse('{"Actions":"Actions","Active":"Active","workouts exist":"workouts exist","Add admin rights":"Add admin rights","Add/remove admin rights, delete user account.":"Add/remove admin rights, delete user account.","Administration":"Administration","Application":"Application","Application configuration":"Application configuration","Back":"Back","Disable":"Disable","Enable":"Enable","Enable/disable sports.":"Enable/disable sports.","FitTrackee administration":"FitTrackee administration","id":"id","if 0, no limitation":"if 0, no limitation","Image":"Image","Label":"Label","Max. number of active users":"Max. number of active users","Max. files of zip archive":"Max. files of zip archive","Max. size of uploaded files":"Max. size of uploaded files","Max. size of uploaded files (in Mb)":"Max. size of uploaded files (in Mb)","Max. size of zip archive":"Max. size of zip archive","Max. size of zip archive (in Mb)":"Max. size of zip archive (in Mb)","Registration is currently disabled.":"Registration is currently disabled.","Registration is currently enabled.":"Registration is currently enabled.","Remove admin rights":"Remove admin rights","Sports":"Sports","Update application configuration (maximum number of registered users, maximum files size).":"Update application configuration (maximum number of registered users, maximum files size).","uploads":"uploads","user":"user","Users":"Users","users":"users"}')},200:function(e){e.exports=JSON.parse('{"workouts count":"workouts count","Add workout":"Add workout","admin rights":"admin rights","ascending":"ascending","Back":"Back","Back to home":"Back to home","Cancel":"Cancel","Confirmation":"Confirmation","Dashboard":"Dashboard","descending":"descending","Edit":"Edit","day":"day","days":"days","Next":"Next","No":"No","no":"no","No records.":"No records.","No workouts.":"No workouts.","Page not found":"Page not found","Previous":"Prev","registration date":"registration date","Sort":"Sort","Sort by":"Sort by","Sport":"Sport","sport":"sport","Sports":"Sports","sports":"sports","Statistics":"Statistics","Submit":"Submit","to":"to","user name":"user name","Workout":"Workout","Workouts":"Workouts","workout":"workout","workouts":"workouts","Yes":"Yes","yes":"yes"}')},201:function(e){e.exports=JSON.parse('{"Personal records":"Personal records","This month":"This month","Upload one !":"Upload one !"}')},202:function(e){e.exports=JSON.parse('{"3 to 12 characters required for username.":"3 to 12 characters required for username.","8 characters required for password.":"8 characters required for password.","An error occurred. Please contact the administrator.":"An error occurred. Please contact the administrator.","workouts":"workouts","Error during picture deletion.":"Error during picture deletion.","Error during picture update.":"Error during picture update.","Error during picture update, file size exceeds max size.":"Error during picture update, file size exceeds max size.","Error. Registration is disabled.":"Error. Registration is disabled.","Error. Please try again or contact the administrator.":"Error. Please try again or contact the administrator.","File extension not allowed.":"File extension not allowed.","File size is greater than the allowed size":"File size is greater than the allowed size","Incorrect id":"Incorrect id","Invalid credentials.":"Invalid credentials.","Invalid payload.":"Invalid payload.","Invalid token. Please log in again.":"Invalid token. Please log in again.","No file part.":"No file part.","No picture.":"No picture.","No selected file.":"No selected file.","no correct file.":"no correct file.","no gpx file for this activity":"no gpx file for this activity","Password and password confirmation don\'t match.":"Password and password confirmation don\'t match.","Provide a valid auth token":"Provide a valid auth token","records":"records","Signature expired. Please log in again.":"Signature expired. Please log in again.","Sorry. That user already exists.":"Sorry. That user already exists.","Sport can not be disabled, workouts exist.":"Sport can not be disabled, workouts exist.","Sport does not exist.":"Sport does not exist.","sports":"sports","statistics":"statistiques","User does not exist.":"User does not exist.","Valid email must be provided.\\n":"Valid email must be provided.","You can not delete your account, no other user has admin rights.":"You can not delete your account, no other user has admin rights.","You do not have permissions.":"You do not have permissions."}')},203:function(e){e.exports=JSON.parse('{"Cycling (Sport)":"Cycling (Sport)","Cycling (Transport)":"Cycling (Transport)","Hiking":"Hiking","Mountain Biking":"Mountain Biking","Running":"Running","Walking":"Walking"}')},204:function(e){e.exports=JSON.parse('{"workouts":"workouts","distance":"distance","duration":"duration","month":"month","Statistics":"Statistics","year":"year","week":"week"}')},205:function(e){e.exports=JSON.parse('{"Admin":"Admin","Are you sure you want to delete this account? All data will be deleted, this cannot be undone.":"Are you sure you want to delete this account? All data will be deleted, this cannot be undone.","Are you sure you want to delete your account? All data will be deleted, this cannot be undone.":"Are you sure you want to delete your account? All data will be deleted, this cannot be undone.","Bio":"Bio","Birth Date":"Birth Date","Check your email. If your address is in our database, you\'ll received an email with a link to reset your password.":"Check your email. If your address is in our database, you\'ll received an email with a link to reset your password.","Delete my account":"Delete my account","Delete picture":"Delete picture","Delete user account":"Delete user account","Edit Profile":"Edit Profile","Email":"Email","Enter a username":"Enter a username","Enter an email address":"Enter an email address","Enter a password":"Enter a password","Enter the password confirmation":"Enter the password confirmation","First day of week":"First day of week","First Name":"First Name","Forgot password?":"Forgot password?","Invalid token. Please request a new token.":"Invalid token. Please request a new token.","Language":"Language","Last Name":"Last Name","Location":"Location","loggedOut":"You are now logged out. Click <1>here to log back in.","Login":"Login","login":"login","Logout":"Logout","Monday":"Monday","Password":"Password","Password Confirmation":"Password Confirmation","Password reset":"Password reset","password reset":"password reset","Profile":"Profile","Profile Edition":"Profile Edition","Register":"Register","register":"register","Registration Date":"Registration Date","Reset your password":"Reset your password","reset your password":"reset your password","Send":"Send","Sunday":"Sunday","Timezone":"Timezone","updatedPasswordText":"Your password have been updated. Click <1>here to log in.","Username":"Username"}')},206:function(e){e.exports=JSON.parse('{"Activities":"Activit\xe9s","Activity":"Activit\xe9","Activity Date":"Date de l\'activit\xe9","Add a workout":"Ajouter une activit\xe9","Are you sure you want to delete this activity?":"Etes-vous s\xfbr de vouloir supprimer cette activit\xe9 ?","Ave. speed":"Vitesse moyenne","Ascent":"D\xe9nivel\xe9 positif","Average speed":"Vitesse moyenne","Chart":"Analyse","data from gpx, without any cleaning":"donn\xe9es issues du fichier gpx, sans correction","Date":"Date","Delete activity":"Supprimer l\'activit\xe9","Descent":"D\xe9nivel\xe9 n\xe9gatif","Distance":"Distance","distance":"distance","Duration":"Dur\xe9e","duration":"dur\xe9e","Edit a workout":"Editer une activit\xe9","Edit activity":"Editer une activity","elevation":"altitude","End":"Arriv\xe9e","Farest distance":"Distance la + longue","Filter":"Filtrer","From":"A partir de","gpxFile":"fichier gpx","Longest duration":"Dur\xe9e la + longue","Max. altitude":"Altitude max","Max. speed":"Vitesse max","Min. altitude":"Altitude min","no folder inside":"pas de r\xe9pertoire","files max":" fichiers max","max size":"taille max","No data to display":"Pas de donn\xe9es \xe0 afficher","No Map":"Pas de carte","No next activity":"Pas d\'activit\xe9 suivante","No next segment":"Pas de segment suivant","No notes":"Pas de notes","No previous activity":"Pas d\'activit\xe9 pr\xe9c\xe9dente","No previous segment":"Pas de segment pr\xe9c\xe9dent","Notes":"Notes","pauses":"pauses","Personal records":"Records personnels","See next activity":"Voir l\'activit\xe9 suivante","See next segment":"Voir le segment suivant","See previous activity":"Voir l\'activit\xe9 pr\xe9c\xe9dente","See previous segment":"Voir le segment pr\xe9c\xe9dent","segment":"segment","Segments":"Segments","Start":"D\xe9part","speed":"vitesse","Title":"Titre","To":"Jusqu\'au","total duration":"dur\xe9e totale","with gpx file":"avec un fichier gpx","without gpx file":"sans fichier gpx","zipFile":"ou un fichier zip contenant des fichiers gpx"}')},207:function(e){e.exports=JSON.parse('{"Actions":"Actions","Active":"Active","Add admin rights":"Ajouter des droits d\'admin","Add/remove admin rights, delete user account.":"Ajouter/retirer des droits d\'adminsitration, supprimer des comptes utilisateurs.","Administration":"Administration","workouts exist":"des activit\xe9s existent","Application":"Application","Application configuration":"Configuration de l\'application","Back":"Retour","Disable":"d\xe9sactiver","Enable":"activer","Enable/disable sports.":"Activer/d\xe9sactiver des sports.","FitTrackee administration":"Administration de FitTrackee","id":"id","if 0, no limitation":"si \xe9gal \xe0 0, pas limite d\'inscription","Image":"Image","Label":"Label","Max. number of active users":"Nombre maximum d\'utilisateurs actifs","Max. files of zip archive":"Nombre max. de fichiers dans une archive zip","Max. size of uploaded files":"Taille max. des fichiers","Max. size of uploaded files (in Mb)":"Taille max. des fichiers (en Mo)","Max. size of zip archive":"Taille max. des archives zip","Max. size of zip archive (in Mb)":"Taille max. des archives zip (en Mo)","Registration is currently disabled.":"Les inscriptions sont actuellement d\xe9sactiv\xe9es.","Registration is currently enabled.":"Les inscriptions sont actuellement activ\xe9es.","Remove admin rights":"Retirer des droits d\'admin","Sports":"Sports","Update application configuration (maximum number of registered users, maximum files size).":"Configurer l\'application (nombre maximum d\'utilisateurs inscrits, taille maximale des fichers).","uploads":"fichiers","user":"user","Users":"Utilisateurs","users":"utilisateurs"}')},208:function(e){e.exports=JSON.parse('{"workouts count":"nombre d\'activit\xe9s","Add workout":"Ajouter une activit\xe9","admin rights":"droits d\'admin","ascending":"ascendant","Back":"Revenir \xe0 la page pr\xe9c\xe9dente","Back to home":"Retour \xe0 l\'accueil","Cancel":"Annuler","Confirmation":"Confirmation","Dashboard":"Tableau de Bord","descending":"descendant","Edit":"Modifier","day":"jour","days":"jours","Next":"Page suivante","No":"Non","no":"non","No records.":"Pas de records.","No workouts.":"Pas d\'activit\xe9s.","Page not found":"Page introuvable","Previous":"Page pr\xe9c\xe9dente","registration date":"date d\'inscription","Sort":"Tri","Sort by":"Trier par","Sport":"Sport","sport":"sport","Sports":"Sports","sports":"sports","Statistics":"Statistiques","Submit":"Valider","to":"\xe0","user name":"utilisateur","Workout":"Activit\xe9","Workouts":"Activit\xe9s","workout":"activit\xe9","workouts":"activit\xe9s","Yes":"Oui","yes":"oui"}')},209:function(e){e.exports=JSON.parse('{"Personal records":"Mes records","This month":"Ce mois","Upload one !":"Ajoutez votre premi\xe8re activit\xe9 !"}')},210:function(e){e.exports=JSON.parse('{"3 to 12 characters required for username.":"3 \xe0 12 caract\xe8res requis pour le nom.","8 characters required for password.":"8 caract\xe8res minimum pour le mot de passe.","An error occurred. Please contact the administrator.":"Une erreur s\'est produite. Merci de contacter l\'administrateur.","workouts":"activit\xe9s","Error during picture deletion.":"Erreur lors de la suppression de l\'image.","Error during picture update.":"Erreur lors de la mise \xe0 jour de l\'image.","Error during picture update, file size exceeds max size.":"Erreur lors de la mise \xe0 jour de l\'image, la taille du ficher d\xe9passe la taille maximum autoris\xe9e","Error. Registration is disabled.":"Erreur. L\'inscription est d\xe9sactiv\xe9e.","Error. Please try again or contact the administrator.":"Erreur. Veuillez r\xe9essayer ou contacter l\'administrateur","File extension not allowed.":"Extension de fichier non autoris\xe9e.","File size is greater than the allowed size":"La taille du fichier est sup\xe9rieure \xe0 la limite autoris\xe9e","Incorrect id":"Id incorrect","Invalid credentials.":"Identifiants invalides.","Invalid payload.":"Donn\xe9es incorrectes.","Invalid token. Please log in again.":"Jeton invalide. Merci de vous reconnecter.","No file part.":"Pas de fichier fourni.","No picture.":"Pas d\'image.","No selected file.":"Pas de fichier s\xe9lectionn\xe9.","no correct file.":"fichier incorrect","no gpx file for this activity":"pas de fichier gpx pour cette activit\xe9","Password and password confirmation don\'t match.":"Les mots de passe saisis sont diff\xe9rents.","Provide a valid auth token":"Merci de fournir un jeton valide","records":"records","Signature expired. Please log in again.":"Signature expir\xe9e. Merci de vous reconnecter.","Sorry. That user already exists.":"D\xe9sol\xe9. Cet utilisateur existe d\xe9j\xe0.","Sport can not be disabled, workouts exist.":"Le sport ne peut \xeatre d\xe9sactiv\xe9, des activit\xe9es existent","Sport does not exist.":"Le sport n\'existe pas.","sports":"sports","statistics":"statistics","User does not exist.":"L\'utilisateur n\'existe pas.","Valid email must be provided.\\n":"L\'email fourni n\'est pas valide.","You can not delete your account, no other user has admin rights.":"Vous ne pouvez pas supprimer votre compte, aucun autre utilisateur n\'a des droits d\'administration.","You do not have permissions.":"Vous n\'avez pas les permissions n\xe9cessaires."}')},211:function(e){e.exports=JSON.parse('{"Cycling (Sport)":"V\xe9lo (Sport)","Cycling (Transport)":"V\xe9lo (Transport)","Hiking":"Randonn\xe9e","Mountain Biking":"VTT","Running":"Course","Walking":"Marche"}')},212:function(e){e.exports=JSON.parse('{"workouts":"activit\xe9s","distance":"distance","duration":"dur\xe9e","month":"mois","Statistics":"Statistiques","year":"ann\xe9e","week":"semaine"}')},213:function(e){e.exports=JSON.parse('{"Admin":"Admin","Are you sure you want to delete this account? All data will be deleted, this cannot be undone.":"Etes-vous s\xfbr de vouloir supprimer ce compte ? Toutes les donn\xe9es seront d\xe9finitivement effac\xe9s.","Are you sure you want to delete your account? All data will be deleted, this cannot be undone.":"Etes-vous s\xfbr de vouloir supprimer votre compte ? Toutes les donn\xe9es seront d\xe9finitivement effac\xe9s.","Bio":"Bio","Birth Date":"Date de naissance","Check your email. If your address is in our database, you\'ll received an email with a link to reset your password.":"V\xe9rifiez vore boite mail. Si vote adresse est dans notre base de donn\xe9es, vous recevrez un email avec un lien pour r\xe9initialiser votre mot de passe","Delete my account":"Supprimer mon compte","Delete picture":"Supprimer l\'image","Delete user account":"Supprimer le compte","Edit Profile":"Editer le profil","Email":"Email","Enter a username":"Saisir un nom","Enter an email address":"Saisir une adresse e-mail","Enter a password":"Saisir un mot de passe","Enter the password confirmation":"Confirmer le mot de passe","First day of week":"Premier jour de la semaine","First Name":"Pr\xe9nom","Forgot password?":"Mot de passe oubli\xe9 ?","Invalid token. Please request a new token.":"Token invalid. Veuillez demander un nouveau token.","Language":"Langue","Last Name":"Nom","Location":"Lieu","loggedOut":"Vous \xeates d\xe9connect\xe9. Cliquez <1>ici pour vous reconnecter.","Login":"Se connecter","login":"se connecter","Logout":"Se d\xe9connecter","Monday":"Lundi","Password":"Mot de passe","Password Confirmation":"Confirmation du mot de passe","Password reset":"R\xe9initialiser votre mot de passe","password reset":"r\xe9initialiser votre mot de passe","Profile":"Profil","Profile Edition":"Edition du profil","Register":"S\'inscrire","register":"s\'inscrire","Registration Date":"Date d\'inscription","Reset your password":"R\xe9initialiser votre mot de passe","reset your password":"r\xe9initialiser votre mot de passe","Send":"Envoyer","Sunday":"Dimanche","Timezone":"Fuseau horaire","updatedPasswordText":"Votre mot de passe a \xe9t\xe9 mis \xe0 jour. Cliquez <1>ici pour vous connecter.","Username":"Nom d\'utilisateur"}')},273:function(e,t,a){},281:function(e,t){},463:function(e,t,a){"use strict";a.r(t),a.d(t,"history",(function(){return Hi})),a.d(t,"rootNode",(function(){return Bi})),a.d(t,"store",(function(){return Vi}));var i=a(1),s=a(29),n=a(2),c=a.n(n),r=a(483),o=a(53),l=a.n(o),d=a(194),u=a(57),m=a(195),j=a(81),p=a(196),h=a(197),b={en:{activities:a(198),administration:a(199),common:a(200),dashboard:a(201),messages:a(202),sports:a(203),statistics:a(204),user:a(205)},fr:{activities:a(206),administration:a(207),common:a(208),dashboard:a(209),messages:a(210),sports:a(211),statistics:a(212),user:a(213)}};j.a.use(h.a).use(p.a).init({debug:!1,lng:"en",fallbackLng:"en",keySeparator:!1,interpolation:{escapeValue:!1},resources:b,ns:["common"],defaultNS:"common"});var v=j.a,f=a(6),O=a(7),x=a(10),g=a(9),y=a(8),N=a(19),w=(a(273),a(20)),k=a(466),_=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props,t=e.message,a=e.messages,s=e.t,n=""!==t&&t?t.split("|").length>1?"".concat(s("messages:".concat(t.split("|")[0])),": ").concat(s("messages:".concat(t.split("|")[1]))):s("messages:".concat(t)):"";return Object(i.jsxs)("div",{className:"error-message",children:[""!==n&&Object(i.jsx)("code",{children:n}),a&&a.length>0&&Object(i.jsx)("code",{children:Object(i.jsx)("ul",{children:a.map((function(e){return Object(i.jsx)("li",{children:s("messages:".concat(e.value))},e.id)}))})})]})}}]),a}(c.a.PureComponent),S=a(12),D=a(485),A=a(484),C=a(218),E=["bytes","KB","MB","GB","TB"],M=function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=Math.floor(Math.log(e)/Math.log(1024));if(!e)return t?"0 bytes":{size:0,suffix:"bytes"};var i=(e/Math.pow(1024,a)).toFixed(1),s=E[a];return t?"".concat(i).concat(s):{size:i,suffix:s}},T="/api/",P=[{key:"activities_count",label:"workouts count"},{key:"admin",label:"admin rights"},{key:"created_at",label:"registration date"},{key:"username",label:"user name"}],F=[{key:"asc",label:"ascending"},{key:"desc",label:"descending"}],z=function(){return!!window.localStorage.authToken},R=function(e){var t={};e.noAuthorization||(t.Authorization="Bearer ".concat(window.localStorage.getItem("authToken"))),e.type&&(t["Content-Type"]=e.type);var a={method:e.method,headers:t};"application/json"===e.type&&e.body?a.body=JSON.stringify(e.body):e.body&&(a.body=e.body);var i=new Request("".concat(T).concat(e.url),a);return fetch(i).then((function(t){return"DELETE"===e.method||413===t.status?t:t.json()})).catch((function(e){return console.error(e),new Error("An error occurred. Please contact the administrator.")}))},L=function(e,t){if(!e)return"";var a=C.DateTime.fromISO(Object(D.a)(new Date(e),"yyyy-MM-dd'T'HH:mm:ss.SSSxxx")).setZone(t);return Object(A.a)(a.toFormat("yyyy-MM-dd HH:mm:ss"),"yyyy-MM-dd HH:mm:ss",new Date)},I=function(e,t){var a=e.label.toLowerCase(),i=t.label.toLowerCase();return a>i?1:a2&&void 0!==arguments[2]?arguments[2]:"common";return t.map((function(t){return Object(S.a)(Object(S.a)({},t),{},{label:e("".concat(a,":").concat(t.label))})})).sort(I)},H=function(e,t){var a=e;return t.id||"users"===e&&t.username?a="".concat(a,"/").concat(t.username?t.username:t.id):Object.keys(t).length>0&&(a+="?",Object.keys(t).filter((function(e){return t[e]})).map((function(e,i){return a+="".concat(0===i?"":"&").concat(e,"=").concat(t[e])}))),a},q=function(){function e(){Object(f.a)(this,e)}return Object(O.a)(e,null,[{key:"getData",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=H(e,t),i={url:a,method:"GET",type:"application/json"};return R(i)}},{key:"addData",value:function(e,t){return R({url:e,method:"POST",body:t,type:"application/json"})}},{key:"addDataWithFile",value:function(e,t){return R({url:e,method:"POST",body:t})}},{key:"postData",value:function(e,t){var a={url:"".concat(e).concat(t.id?"/".concat(t.id):""),method:"POST",body:t,type:"application/json"};return R(a)}},{key:"updateData",value:function(e,t){var a={url:"".concat(e).concat(t.id?"/".concat(t.id):t.username?"/".concat(t.username):""),method:"PATCH",body:t,type:"application/json"};return R(a)}},{key:"deleteData",value:function(e,t){var a={url:"".concat(e,"/").concat(t),method:"DELETE",type:"application/json"};return R(a)}}]),e}(),B=function(e,t){return{type:"SET_DATA",data:t,target:e}},V=function(e,t,a){return{type:"SET_PAGINATED_DATA",data:t,pagination:a,target:e}},G=function(e){return{type:"SET_ERROR",message:e}},W=function(e){return{type:"SET_LOADING",loading:e}},J=function(e){return{type:"UPDATE_SPORT_DATA",data:e}},Y=function(e){return{type:"UPDATE_USER_DATA",data:e}},K=function(e,t,a){var i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];return function(s){return s(W(!0)),a&&a.id&&"activities"!==t&&isNaN(a.id)?(s(W(!1)),s(G("".concat(t,"|Incorrect id")))):(s(G("")),q[e](t,a).then((function(a){if("success"===a.status)if(i){if("users"===t&&"getData"===e)return s(V(t,a.data,a.pagination));s(B(t,a.data))}else"updateData"===e&&"sports"===t?s(J(a.data.sports[0])):"updateData"===e&&"users"===t&&s(Y(a.data.users[0]));else s(G("".concat(t,"|").concat(a.message||a.status)));s(W(!1))})).catch((function(e){s(W(!1)),s(G("".concat(t,"|").concat(e)))})))}},X=function(e){return function(t){j.a.changeLanguage(e).then(t(function(e){return{type:"SET_LANGUAGE",language:e}}(e)))}},$=function(e){return{type:"SET_APP_CONFIG",data:e}},Z=function(e){return function(t){return q.getData(e).then((function(a){"success"===a.status?"config"===e?t($(a.data)):"stats/all"===e&&t({type:"SET_APP_STATS",data:a.data}):t(G("application|".concat(a.message)))})).catch((function(e){return t(G("application|".concat(e)))}))}},Q=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={formData:{},isInEdition:!1},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.initForm()}},{key:"componentDidUpdate",value:function(e){this.props.appConfig!==e.appConfig&&this.initForm()}},{key:"initForm",value:function(){var e=this.props.appConfig,t={};Object.keys(e).map((function(a){return null===e[a]?t[a]="":["max_single_file_size","max_zip_file_size"].includes(a)?t[a]=+(e[a]/1048576).toFixed(2):t[a]=e[a]})),this.setState({formData:t})}},{key:"handleFormChange",value:function(e){var t=this.state.formData;t[e.target.name]=+e.target.value,this.setState(t)}},{key:"toggleInEdition",value:function(e){e.preventDefault();var t=this.state.isInEdition;this.setState({isInEdition:!t})}},{key:"render",value:function(){var e=this,t=this.props,a=t.message,s=t.onHandleConfigFormSubmit,n=t.t,c=this.state,r=c.formData,o=c.isInEdition;return Object(i.jsxs)("div",{children:[a&&Object(i.jsx)(_,{message:a,t:n}),Object.keys(r).length>0&&Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col-md-12",children:Object(i.jsxs)("div",{className:"card",children:[Object(i.jsx)("div",{className:"card-header",children:Object(i.jsx)("strong",{children:n("administration:Application configuration")})}),Object(i.jsx)("div",{className:"card-body",children:Object(i.jsxs)("form",{className:"app-config-form ".concat(o?"":"form-disabled"),onSubmit:function(t){e.toggleInEdition(t),s(r)},children:[Object(i.jsxs)("div",{className:"form-group row",children:[Object(i.jsxs)("label",{className:"col-sm-6 col-form-label",htmlFor:"max_users",children:[n("administration:Max. number of active users"),Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-question-circle","aria-hidden":"true",title:n("administration:if 0, no limitation")})}),":"]}),Object(i.jsx)("input",{className:"col-sm-5",id:"max_users",name:"max_users",type:"number",min:"0",value:r.max_users,onChange:function(t){return e.handleFormChange(t)}})]}),Object(i.jsxs)("div",{className:"form-group row",children:[Object(i.jsxs)("label",{className:"col-sm-6 col-form-label",htmlFor:"max_single_file_size",children:[n("administration:Max. size of uploaded files (in Mb)"),":"]}),Object(i.jsx)("input",{className:"col-sm-5",id:"max_single_file_size",name:"max_single_file_size",type:"number",step:"0.1",min:"0",value:r.max_single_file_size,onChange:function(t){return e.handleFormChange(t)}})]}),Object(i.jsxs)("div",{className:"form-group row",children:[Object(i.jsxs)("label",{className:"col-sm-6 col-form-label",htmlFor:"max_zip_file_size",children:[n("administration:Max. size of zip archive (in Mb)"),":"]}),Object(i.jsx)("input",{className:"col-sm-5",id:"max_zip_file_size",name:"max_zip_file_size",type:"number",step:"0.1",min:"0",value:r.max_zip_file_size,onChange:function(t){return e.handleFormChange(t)}})]}),Object(i.jsxs)("div",{className:"form-group row",children:[Object(i.jsx)("label",{className:"col-sm-6 col-form-label",htmlFor:"gpx_limit_import",children:n("administration:Max. files of zip archive")}),Object(i.jsx)("input",{className:"col-sm-5",id:"gpx_limit_import",name:"gpx_limit_import",type:"number",min:"0",value:r.gpx_limit_import,onChange:function(t){return e.handleFormChange(t)}})]}),o?Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("input",{type:"submit",className:"btn btn-primary",value:n("common:Submit")}),Object(i.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(t){return e.toggleInEdition(t)},value:n("common:Cancel")})]}):Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("input",{type:"submit",className:"btn btn-primary",onClick:function(t){e.toggleInEdition(t)},value:n("common:Edit")}),Object(i.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Hi.push("/admin")},value:n("common:Back")})]})]})})]})})})]})}}]),a}(c.a.Component),ee=Object(y.c)((function(e){return{message:e.message}}),(function(e){return{onHandleConfigFormSubmit:function(t){var a=Object.assign({},t);a.max_single_file_size*=1048576,a.max_zip_file_size*=1048576,e(function(e){return function(t){return q.updateData("config",e).then((function(e){"success"===e.status?t($(e.data)):t(G("application|".concat(e.message)))})).catch((function(e){return t(G("application|".concat(e)))}))}}(a))}}}))(Q),te=a(15),ae=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadAppStats()}},{key:"render",value:function(){var e=this.props,t=e.appStats,a=e.t,s=M(t.uploads_dir_size,!1);return Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-users fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:t.users?t.users:0}),Object(i.jsx)("div",{children:"".concat(1===t.users?a("administration:user"):a("administration:users"))})]})]})})}),Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-tags fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:t.sports?t.sports:0}),Object(i.jsx)("div",{children:"".concat(1===t.sports?a("common:sport"):a("common:sports"))})]})]})})}),Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-calendar fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:t.activities?t.activities:0}),Object(i.jsx)("div",{children:"".concat(1===t.activities?a("common:workout"):a("common:workouts"))})]})]})})}),Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-folder-open fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:s.size}),Object(i.jsxs)("div",{children:[s.suffix," (",a("administration:uploads"),")"]})]})]})})})]})}}]),a}(c.a.Component),ie=Object(k.a)()(Object(y.c)((function(e){return{appStats:e.application.statistics}}),(function(e){return{loadAppStats:function(){e(Z("stats/all"))}}}))(ae));function se(e){var t=e.appConfig,a=e.t;return Object(i.jsxs)("div",{className:"card activity-card",children:[Object(i.jsx)("div",{className:"card-header",children:Object(i.jsx)("strong",{children:a("administration:Administration")})}),Object(i.jsxs)("div",{className:"card-body",children:[Object(i.jsx)(ie,{}),Object(i.jsx)("br",{}),Object(i.jsxs)("dl",{className:"admin-items",children:[Object(i.jsx)("dt",{children:Object(i.jsx)(te.a,{to:{pathname:"/admin/application"},children:a("administration:Application")})}),Object(i.jsxs)("dd",{children:[a("administration:Update application configuration (maximum number of registered users, maximum files size)."),Object(i.jsx)("br",{}),Object(i.jsx)("strong",{children:a("administration:Registration is currently ".concat(t.is_registration_enabled?"enabled":"disabled","."))})]}),Object(i.jsx)("br",{}),Object(i.jsx)("dt",{children:Object(i.jsx)(te.a,{to:{pathname:"/admin/sports"},children:a("administration:Sports")})}),Object(i.jsx)("dd",{children:a("administration:Enable/disable sports.")}),Object(i.jsx)("br",{}),Object(i.jsx)("dt",{children:Object(i.jsx)(te.a,{to:{pathname:"/admin/users"},children:a("administration:Users")})}),Object(i.jsx)("dd",{children:a("administration:Add/remove admin rights, delete user account.")})]})]})]})}var ne=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadSports()}},{key:"render",value:function(){var e=this.props,t=e.message,a=e.sports,s=e.t,n=e.updateSport;return Object(i.jsxs)("div",{children:[t&&Object(i.jsx)(_,{message:t,t:s}),Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col",children:Object(i.jsxs)("div",{className:"card",children:[Object(i.jsx)("div",{className:"card-header",children:Object(i.jsx)("strong",{children:s("administration:Sports")})}),Object(i.jsxs)("div",{className:"card-body",children:[a.length>0&&Object(i.jsxs)("table",{className:"table",children:[Object(i.jsx)("thead",{children:Object(i.jsxs)("tr",{children:[Object(i.jsx)("th",{children:s("administration:id")}),Object(i.jsx)("th",{children:s("administration:Image")}),Object(i.jsx)("th",{children:s("administration:Label")}),Object(i.jsx)("th",{children:s("administration:Active")}),Object(i.jsx)("th",{children:s("administration:Actions")})]})}),Object(i.jsx)("tbody",{children:a.map((function(e){return Object(i.jsxs)("tr",{children:[Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:s("administration:id")}),e.id]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:s("administration:Image")}),Object(i.jsx)("img",{className:"admin-img",src:e.img?e.img:"/img/photo.png",alt:"sport logo"})]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:s("administration:Label")}),s("sports:".concat(e.label))]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:s("administration:Active")}),e.is_active?Object(i.jsx)("i",{className:"fa fa-check-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"}):Object(i.jsx)("i",{className:"fa fa-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"})]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:s("administration:Actions")}),Object(i.jsx)("input",{type:"submit",className:"btn btn-".concat(e.is_active?"dark":"primary"," btn-sm"),value:e.is_active?s("administration:Disable"):s("administration:Enable"),onClick:function(){return n(e.id,!e.is_active)}}),e.has_activities&&Object(i.jsxs)("span",{className:"admin-message",children:[Object(i.jsx)("i",{className:"fa fa-warning custom-fa","aria-hidden":"true"}),s("administration:workouts exist")]})]})]},e.id)}))})]}),Object(i.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Hi.push("/admin/")},value:s("common:Back")})]})]})})})]})}}]),a}(c.a.Component),ce=Object(y.c)((function(e){return{message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadSports:function(){e(K("getData","sports"))},updateSport:function(t,a){e(K("updateData","sports",{id:t,is_active:a},!1))}}}))(ne),re=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"getUrl",value:function(e){var t=this.props,a=t.query,i=t.pathname,s=Object.assign({},a),n=a.page?+a.page:1;switch(e){case"prev":n-=1;break;case"next":n+=1;break;default:n=+e}return s.page=n,H(i,s)}},{key:"render",value:function(){var e,t=this,a=this.props,s=a.pagination,n=a.t;return Object(i.jsx)(i.Fragment,{children:s&&Object.keys(s).length>0&&Object(i.jsx)("nav",{"aria-label":"Page navigation example",children:Object(i.jsxs)("ul",{className:"pagination justify-content-center",children:[Object(i.jsx)("li",{className:"page-item ".concat(s.has_prev?"":"disabled"),children:Object(i.jsx)(te.a,{className:"page-link",to:this.getUrl("prev"),"aria-disabled":!s.has_prev,children:n("common:Previous")})}),(e=s.pages,Array.from({length:e},(function(e,t){return t+1}))).map((function(e){return Object(i.jsx)("li",{className:"page-item ".concat(e===s.page?"active":""),children:Object(i.jsx)(te.a,{className:"page-link",to:t.getUrl(e),children:e})},e)})),Object(i.jsx)("li",{className:"page-item ".concat(s.has_next?"":"disabled"),children:Object(i.jsx)(te.a,{className:"page-link",to:this.getUrl("next"),"aria-disabled":!s.has_next,children:n("common:Next")})})]})})})}}]),a}(c.a.PureComponent),oe=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={page:null,per_page:null,order_by:"created_at",order:"asc"},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadUsers(this.initState())}},{key:"componentDidUpdate",value:function(e){e.location.query!==this.props.location.query&&this.props.loadUsers(this.props.location.query)}},{key:"initState",value:function(){var e=this.props.location.query,t={page:e.page,per_page:e.per_page,order_by:e.order_by?e.order_by:"created_at",order:e.order?e.order:"asc"};return this.setState(t),t}},{key:"updatePage",value:function(e,t){var a=Object.assign({},this.state);a[e]=t,this.setState(a);var i=H(this.props.location.pathname,a);Hi.push(i)}},{key:"render",value:function(){var e=this,t=this.props,a=t.authUser,s=t.location,n=t.message,c=t.t,r=t.pagination,o=t.updateUser,l=t.users,d=U(c,P),u=U(c,F);return Object(i.jsxs)("div",{children:[n&&Object(i.jsx)(_,{message:n,t:c}),Object(i.jsx)("div",{className:"container",children:Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col",children:Object(i.jsxs)("div",{className:"card",children:[Object(i.jsx)("div",{className:"card-header",children:Object(i.jsx)("strong",{children:c("administration:Users")})}),Object(i.jsxs)("div",{className:"card-body",children:[Object(i.jsxs)("div",{className:"row user-filters",children:[Object(i.jsx)("div",{className:"col-lg-4 col-md-6 col-sm-12",children:Object(i.jsxs)("label",{htmlFor:"order_by",children:[c("common:Sort by"),":"," ",Object(i.jsx)("select",{id:"order_by",name:"order_by",value:this.state.order_by,onChange:function(t){return e.updatePage("order_by",t.target.value)},children:d.map((function(e){return Object(i.jsx)("option",{value:e.key,children:e.label},e.key)}))})," "]})}),Object(i.jsx)("div",{className:"col-lg-4 col-md-6 col-sm-12",children:Object(i.jsxs)("label",{htmlFor:"sort",children:[c("common:Sort"),":"," ",Object(i.jsx)("select",{id:"sort",name:"sort",value:this.state.order,onChange:function(t){return e.updatePage("order",t.target.value)},children:u.map((function(e){return Object(i.jsx)("option",{value:e.key,children:e.label},e.key)}))})," "]})})]}),Object(i.jsxs)("table",{className:"table",children:[Object(i.jsx)("thead",{children:Object(i.jsxs)("tr",{children:[Object(i.jsx)("th",{children:"#"}),Object(i.jsx)("th",{children:c("user:Username")}),Object(i.jsx)("th",{children:c("user:Email")}),Object(i.jsx)("th",{children:c("user:Registration Date")}),Object(i.jsx)("th",{children:c("workouts:Activities")}),Object(i.jsx)("th",{children:c("user:Admin")}),Object(i.jsx)("th",{children:c("administration:Actions")})]})}),Object(i.jsx)("tbody",{children:l.map((function(e){return Object(i.jsxs)("tr",{children:[Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:"#"}),!0===e.picture?Object(i.jsx)("img",{alt:"Avatar",src:"".concat(T,"users/").concat(e.username,"/picture?").concat(Date.now()),className:"img-fluid App-nav-profile-img"}):Object(i.jsx)("i",{className:"fa fa-user-circle-o fa-2x no-picture","aria-hidden":"true"})]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:c("user:Username")}),Object(i.jsx)(te.a,{to:"/users/".concat(e.username),children:e.username})]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:c("user:Email")}),e.email]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:c("user:Registration Date")}),Object(D.a)(new Date(e.created_at),"dd/MM/yyyy HH:mm")]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:c("workouts:Activities")}),e.nb_activities]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:c("user:Admin")}),e.admin?Object(i.jsx)("i",{className:"fa fa-check-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"}):Object(i.jsx)("i",{className:"fa fa-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"})]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:c("administration:Actions")}),Object(i.jsx)("input",{type:"submit",className:"btn btn-".concat(e.admin?"dark":"primary"," btn-sm"),disabled:e.username===a.username,value:e.admin?c("administration:Remove admin rights"):c("administration:Add admin rights"),onClick:function(){return o(e.username,!e.admin)}})]})]},e.username)}))})]}),Object(i.jsx)(re,{pagination:r,pathname:s.pathname,query:this.state,t:c}),Object(i.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Hi.push("/admin/")},value:c("common:Back")})]})]})})})})]})}}]),a}(c.a.Component),le=Object(y.c)((function(e){return{authUser:e.user,location:e.router.location,message:e.message,pagination:e.users.pagination,users:e.users.data}}),(function(e){return{loadUsers:function(t){e(K("getData","users",t))},updateUser:function(t,a){e(K("updateData","users",{username:t,admin:a},!1))}}}))(oe),de=a(219);function ue(){var e=Object(de.a)().t;return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsx)("title",{children:"fittrackee - 404"})}),Object(i.jsx)("h1",{className:"page-title",children:e("Page not found")})]})}var me=Object(k.a)()(Object(y.c)((function(e){return{appConfig:e.application.config,user:e.user}}))((function(e){var t=e.appConfig,a=e.t,s=e.user;return Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",a("administration:Administration")]})}),Object(i.jsx)("div",{className:"container dashboard",children:s.admin?Object(i.jsxs)(N.d,{children:[Object(i.jsx)(N.b,{exact:!0,path:"/admin",render:function(){return Object(i.jsx)(se,{appConfig:t,t:a})}}),Object(i.jsx)(N.b,{exact:!0,path:"/admin/application",render:function(){return Object(i.jsx)(ee,{appConfig:t,t:a})}}),Object(i.jsx)(N.b,{exact:!0,path:"/admin/sports",render:function(){return Object(i.jsx)(ce,{t:a})}}),Object(i.jsx)(N.b,{exact:!0,path:"/admin/users",render:function(){return Object(i.jsx)(le,{t:a})}}),Object(i.jsx)(N.b,{component:ue})]}):Object(i.jsx)(ue,{})})]})}))),je=a(467),pe=a(24),he=a(487),be=a(222),ve=a.n(be),fe=["#55a8a3","#98C3A9","#D0838A","#ECC77E","#926692","#929292","#428bca"],Oe=[{record_type:"AS",label:"Ave. speed"},{record_type:"FD",label:"Farest distance"},{record_type:"LD",label:"Longest duration"},{record_type:"MS",label:"Max. speed"}],xe=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return t||(t="yyyy/MM/dd"),a||(a="HH:mm"),{activity_date:e?Object(D.a)(e,t):null,activity_time:e?Object(D.a)(e,a):null}},ge=function(e){var t=new Date(0);return(t=Object(he.a)(t.setSeconds(e),1)).getTime()},ye=function(e){for(var t=0;ti?1:a2&&void 0!==arguments[2]&&arguments[2];return e.filter((function(e){return!a||e.is_active})).map((function(e){return Object(S.a)(Object(S.a)({},e),{},{label:t("sports:".concat(e.label))})})).sort(Ne)},ke=function(){function e(){Object(f.a)(this,e)}return Object(O.a)(e,null,[{key:"loginOrRegisterOrPasswordReset",value:function(e,t){var a={url:"auth/".concat(e),method:"POST",noAuthorization:!0,body:t,type:"application/json"};return R(a)}},{key:"deletePicture",value:function(){return R({url:"auth/picture",method:"DELETE"})}}]),e}(),_e=function(e){return{type:"PICTURE_ERROR",message:e}},Se=function(e){return{type:"PROFILE_UPDATE_ERROR",message:e}},De=function(){return function(e){return window.localStorage.getItem("authToken")?e(Ae()):{type:"LOGOUT"}}},Ae=function(){return function(e){return q.getData("auth/profile").then((function(t){return"success"===t.status?(e(K("getData","sports")),t.data.isAuthenticated=!0,t.data.language&&e(X(t.data.language)),e({type:"PROFILE_SUCCESS",profil:t.data})):e({type:"PROFILE_ERROR",message:t.message})})).catch((function(e){throw e}))}},Ce=function(e,t){return function(a){if("register"===t||"password/update"===t){var i=function(e){var t=[];return!(arguments.length>1&&void 0!==arguments[1]&&arguments[1])&&(e.username.length<3||e.username.length>12)&&t.push("3 to 12 characters required for username."),e.password!==e.password_conf&&t.push("Password and password confirmation don't match."),e.password.length<8&&t.push("8 characters required for password."),t}(e,"password/update"===t);if(i.length>0)return a({type:"AUTH_ERRORS",messages:function(e){var t=0;return e.map((function(e){var a={id:t,value:e};return t++,a}))}(i)})}return a(function(e,t){return function(a){return ke.loginOrRegisterOrPasswordReset(e,t).then((function(t){if("success"===t.status){if("password/reset-request"===e)return Hi.push({pathname:"/password-reset/sent"});if("password/update"===e)return Hi.push({pathname:"/updated-password"});if("login"===e||"register"===e)return window.localStorage.setItem("authToken",t.auth_token),"register"===e&&a(Z("config")),a(Ae())}return a({type:"AUTH_ERROR",message:t.message})})).catch((function(e){throw e}))}}(t,e))}},Ee=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return function(a){return q.deleteData("users",e).then((function(e){204===e.status?(a(Z("config")),t?Hi.push("/admin/users"):(a({type:"LOGOUT"}),Hi.push("/"))):e.json().then((function(e){return a(G("".concat(e.message)))}))})).catch((function(e){return a(G("user|".concat(e)))}))}},Me=function(e){return{type:"SET_GPX",gpxContent:e}},Te=function(e){return{type:"SET_CHART_DATA",chartData:e}},Pe=function(e){return function(t){return q.updateData("activities",e).then((function(e){"success"===e.status?(t(De()),Hi.push("/workouts/".concat(e.data.activities[0].id))):t(G("workouts|".concat(e.message))),t(W(!1))})).catch((function(e){t(W(!1)),t(G("workouts|".concat(e)))}))}},Fe=function(e){return function(t){return q.getData("activities",e).then((function(e){"success"===e.status?e.data.activities.length>0&&t({type:"PUSH_ACTIVITIES",activities:e.data.activities}):t(G("workouts|".concat(e.message)))})).catch((function(e){return t(G("workouts|".concat(e)))}))}};var ze=Object(y.c)((function(e){return{appConfig:e.application.config,loading:e.loading}}),(function(e){return{onAddActivity:function(t){e(W(!0));var a=new FormData;a.append("file",t.target.form.gpxFile.files[0]),a.append("data",'{"sport_id": '.concat(t.target.form.sport.value,', "notes": "').concat(t.target.form.notes.value,'"}')),e(function(e){return function(t){return q.addDataWithFile("activities",e).then((function(e){"created"===e.status?0===e.data.activities.length?t(G("workouts|no correct file.")):1===e.data.activities.length?(t(De()),Hi.push("/workouts/".concat(e.data.activities[0].id))):(t(De()),Hi.push("/")):413===e.status?t(G("workouts|File size is greater than the allowed size")):t(G("workouts|".concat(e.message))),t(W(!1))})).catch((function(e){t(W(!1)),t(G("workouts|".concat(e)))}))}}(a))},onEditActivity:function(t,a){e(Pe({id:a.id,notes:t.target.form.notes.value,sport_id:+t.target.form.sport.value,title:t.target.form.title.value}))}}}))((function(e){var t=e.activity,a=e.appConfig,s=e.loading,n=e.onAddActivity,c=e.onEditActivity,r=e.sports,o=e.t,l=t?t.sport_id:"",d=we(r,o,!0),u="".concat(o("workouts:no folder inside"),", ").concat(a.gpx_limit_import," ").concat(o("workouts:files max"),", ").concat(o("workouts:max size"),": ").concat(M(a.max_zip_file_size)),m=M(a.max_single_file_size);return Object(i.jsxs)("form",{encType:"multipart/form-data",method:"post",onSubmit:function(e){return e.preventDefault()},children:[Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[o("common:Sport"),":",Object(i.jsxs)("select",{className:"form-control input-lg",defaultValue:l,disabled:s,name:"sport",required:!0,children:[Object(i.jsx)("option",{value:""}),d.map((function(e){return Object(i.jsx)("option",{value:e.id,children:e.label},e.id)}))]})]})}),t?Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[o("workouts:Title"),":",Object(i.jsx)("input",{name:"title",defaultValue:t?t.title:"",disabled:s,className:"form-control input-lg"})]})}):Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[Object(i.jsxs)(je.a,{i18nKey:"workouts:gpxFile",children:[Object(i.jsx)("strong",{children:"gpx"})," file"]}),Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-question-circle","aria-hidden":"true","data-toggle":"tooltip",title:"".concat(o("workouts:max size"),": ").concat(m)})})," ",Object(i.jsxs)(je.a,{i18nKey:"workouts:zipFile",children:["or ",Object(i.jsx)("strong",{children:" zip"})," file containing ",Object(i.jsx)("strong",{children:"gpx "}),"files"]}),Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-question-circle","aria-hidden":"true","data-toggle":"tooltip","data-placement":"top",title:u})})," ",":",Object(i.jsx)("input",{accept:".gpx, .zip",className:"form-control form-control-file gpx-file",disabled:s,name:"gpxFile",required:!0,type:"file"})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[o("workouts:Notes"),":",Object(i.jsx)("textarea",{name:"notes",defaultValue:t?t.notes:"",disabled:s,className:"form-control input-lg",maxLength:"500"})]})}),s?Object(i.jsx)("div",{className:"loader"}):Object(i.jsxs)("div",{children:[Object(i.jsx)("input",{type:"submit",className:"btn btn-primary",onClick:function(e){return t?c(e,t):n(e)},value:o("common:Submit")}),Object(i.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Hi.push("/")},value:o("common:Cancel")})]})]})}));var Re=Object(y.c)((function(e){return{user:e.user}}),(function(e){return{onAddOrEdit:function(t,a){var i,s=t.target.form.duration.value.split(":"),n=60*+s[0]*60+60*+s[1]+ +s[2],c={activity_date:"".concat(t.target.form.activity_date.value," ").concat(t.target.form.activity_time.value),distance:+t.target.form.distance.value,duration:n,notes:t.target.form.notes.value,sport_id:+t.target.form.sport_id.value,title:t.target.form.title.value};a?(c.id=a.id,e(Pe(c))):e((i=c,function(e){return q.addData("workouts/no_gpx",i).then((function(t){"created"===t.status?(e(De()),Hi.push("/workouts/".concat(t.data.activities[0].id))):e(G("workouts|".concat(t.message)))})).catch((function(t){return e(G("workouts|".concat(t)))}))}))}}}))((function(e){var t,a,s=e.activity,n=e.onAddOrEdit,c=e.sports,r=e.t,o=e.user,l=we(c,r,!0),d="";if(s){var u=xe(L(s.activity_date,o.timezone),"yyyy-MM-dd");t=u.activity_date,a=u.activity_time,d=s.sport_id}return Object(i.jsxs)("form",{onSubmit:function(e){return e.preventDefault()},children:[Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[r("workouts:Title"),":",Object(i.jsx)("input",{name:"title",defaultValue:s?s.title:"",className:"form-control input-lg"})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[r("common:Sport"),":",Object(i.jsxs)("select",{className:"form-control input-lg",defaultValue:d,name:"sport_id",required:!0,children:[Object(i.jsx)("option",{value:""}),l.map((function(e){return Object(i.jsx)("option",{value:e.id,children:e.label},e.id)}))]})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[r("workouts:Activity Date"),":",Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("input",{name:"activity_date",defaultValue:t,className:"form-control col-md",required:!0,type:"date"}),Object(i.jsx)("input",{name:"activity_time",defaultValue:a,className:"form-control col-md",required:!0,type:"time"})]})})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[r("workouts:Duration"),":",Object(i.jsx)("input",{name:"duration",defaultValue:s?s.duration:"",className:"form-control col-xs-4",pattern:"^([0-9]*[0-9]):([0-5][0-9]):([0-5][0-9])$",placeholder:"hh:mm:ss",required:!0,type:"text"})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[r("workouts:Distance")," (km):",Object(i.jsx)("input",{name:"distance",defaultValue:s?s.distance:"",className:"form-control input-lg",min:0,required:!0,step:"0.001",type:"number"})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[r("workouts:Notes"),":",Object(i.jsx)("textarea",{name:"notes",defaultValue:s?s.notes:"",className:"form-control input-lg",maxLength:"500"})]})}),Object(i.jsx)("input",{type:"submit",className:"btn btn-primary",onClick:function(e){return n(e,s)},value:r("common:Submit")}),Object(i.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Hi.push("/")},value:r("common:Cancel")})]})})),Le=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={withGpx:!0},s}return Object(O.a)(a,[{key:"handleRadioChange",value:function(e){this.setState({withGpx:"withGpx"===e.target.name?e.target.value:!e.target.value})}},{key:"render",value:function(){var e=this,t=this.props,a=t.activity,s=t.loading,n=t.message,c=t.sports,r=t.t,o=this.state.withGpx;return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee -"," ",r(a?"workouts:Edit a workout":"workouts:Add a workout")]})}),Object(i.jsx)("br",{}),Object(i.jsx)("br",{}),Object(i.jsx)(_,{message:n,t:r}),Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-md-2"}),Object(i.jsx)("div",{className:"col-md-8",children:Object(i.jsxs)("div",{className:"card add-activity",children:[Object(i.jsx)("h2",{className:"card-header text-center",children:r(a?"workouts:Edit a workout":"workouts:Add a workout")}),Object(i.jsx)("div",{className:"card-body",children:a?a.with_gpx?Object(i.jsx)(ze,{activity:a,sports:c,t:r}):Object(i.jsx)(Re,{activity:a,sports:c,t:r}):Object(i.jsxs)("div",{children:[Object(i.jsx)("form",{children:Object(i.jsxs)("div",{className:"form-group row",children:[Object(i.jsx)("div",{className:"col",children:Object(i.jsxs)("label",{className:"radioLabel",children:[Object(i.jsx)("input",{className:"add-activity-radio",type:"radio",name:"withGpx",disabled:s,checked:o,onChange:function(t){return e.handleRadioChange(t)}}),r("workouts:with gpx file")]})}),Object(i.jsx)("div",{className:"col",children:Object(i.jsxs)("label",{className:"radioLabel",children:[Object(i.jsx)("input",{className:"add-activity-radio",type:"radio",name:"withoutGpx",disabled:s,checked:!o,onChange:function(t){return e.handleRadioChange(t)}}),r("workouts:without gpx file")]})})]})}),o?Object(i.jsx)(ze,{sports:c,t:r}):Object(i.jsx)(Re,{sports:c,t:r})]})})]})}),Object(i.jsx)("div",{className:"col-md-2"})]})})]})}}]),a}(c.a.Component),Ie=Object(k.a)()(Object(y.c)((function(e){return{loading:e.loading}}))(Le));var Ue=Object(y.c)((function(e){return{message:e.message,sports:e.sports.data,user:e.user}}))((function(e){var t=e.message,a=e.sports;return Object(i.jsx)("div",{children:Object(i.jsx)(Ie,{activity:null,message:t,sports:a})})}));function He(e){var t=e.activity,a=e.dataType,s=e.displayModal,n=e.segmentId,c=e.sport,r=e.t,o=e.title,l=e.user,d=t?xe(L(t.activity_date,l.timezone)):null,u="segment"===a&&1!==n?"/workouts/".concat(t.id,"/segment/").concat(n-1):"activity"===a&&t.previous_activity?"/workouts/".concat(t.previous_activity):null,m="segment"===a&&n0?Object(i.jsxs)("div",{children:[Object(i.jsxs)("div",{className:"row chart-radio",children:[Object(i.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(i.jsx)("input",{type:"radio",name:"distance",checked:o,onChange:function(e){return a.handleRadioChange(e)}}),c("workouts:distance")]}),Object(i.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(i.jsx)("input",{type:"radio",name:"duration",checked:!o,onChange:function(e){return a.handleRadioChange(e)}}),c("workouts:duration")]})]}),Object(i.jsxs)("div",{className:"row chart-radio",children:[Object(i.jsx)("div",{className:"col-md-5"}),Object(i.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(i.jsx)("input",{type:"checkbox",name:"speed",checked:this.displayData("speed"),onChange:function(e){return a.handleLegendChange(e)}}),c("workouts:speed")]}),Object(i.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(i.jsx)("input",{type:"checkbox",name:"elevation",checked:this.displayData("elevation"),onChange:function(e){return a.handleLegendChange(e)}}),c("workouts:elevation")]}),Object(i.jsx)("div",{className:"col-md-5"})]}),Object(i.jsx)("div",{className:"row chart",children:Object(i.jsx)(qe.f,{height:300,children:Object(i.jsxs)(qe.d,{data:n,margin:{top:15,right:30,left:20,bottom:15},onMouseMove:function(e){return r(e.activePayload)},onMouseLeave:function(){return r(null)},children:[Object(i.jsx)(qe.h,{allowDecimals:!1,dataKey:e,label:{value:c("workouts:".concat(e)),offset:0,position:"bottom"},scale:t,interval:l,tickFormatter:function(e){return o?e:Object(D.a)(e,"HH:mm:ss")},type:"number"}),Object(i.jsx)(qe.i,{label:{value:"".concat(c("workouts:speed")," (km/h)"),angle:-90,position:"left"},yAxisId:"left"}),Object(i.jsx)(qe.i,{label:{value:"".concat(c("workouts:elevation")," (m)"),angle:-90,position:"right"},yAxisId:"right",orientation:"right"}),this.displayData("elevation")&&Object(i.jsx)(qe.a,{yAxisId:"right",type:"linear",dataKey:"elevation",name:c("workouts:elevation"),fill:"#e5e5e5",stroke:"#cccccc",dot:!1,unit:" m"}),this.displayData("speed")&&Object(i.jsx)(qe.e,{yAxisId:"left",type:"linear",dataKey:"speed",name:c("workouts:speed"),stroke:"#8884d8",strokeWidth:2,dot:!1,unit:" km/h"}),Object(i.jsx)(qe.g,{labelFormatter:function(e){return o?"".concat(c("workouts:distance"),": ").concat(e," km"):"".concat(c("workouts:duration"),": ").concat(Object(D.a)(e,"HH:mm:ss"))}})]})})}),Object(i.jsx)("div",{className:"chart-info",children:c("workouts:data from gpx, without any cleaning")})]}):c("workouts:No data to display")})}}]),a}(c.a.Component),Ve=Object(y.c)((function(e){return{chartData:e.chartData}}),(function(e){return{loadActivityData:function(t){e(function(e){return function(t){if(e)return q.getData("workouts/".concat(e,"/chart_data")).then((function(e){"success"===e.status?t(Te(ye(e.data.chart_data))):t(G("workouts|".concat(e.message)))})).catch((function(e){return t(G("workouts|".concat(e)))}));t(Te(null))}}(t))},loadSegmentData:function(t,a){e(function(e,t){return function(a){if(e)return q.getData("workouts/".concat(e,"/chart_data/segment/").concat(t)).then((function(e){"success"===e.status?a(Te(ye(e.data.chart_data))):a(G("workouts|".concat(e.message)))})).catch((function(e){return a(G("workouts|".concat(e)))}));a(Te(null))}}(t,a))}}}))(Be);function Ge(e){var t=e.activity,a=e.t;return Object(i.jsx)("div",{className:"container",children:t.weather_start&&t.weather_end&&Object(i.jsxs)("table",{className:"table table-borderless weather-table text-center",children:[Object(i.jsx)("thead",{children:Object(i.jsxs)("tr",{children:[Object(i.jsx)("th",{}),Object(i.jsxs)("th",{children:[a("workouts:Start"),Object(i.jsx)("br",{}),Object(i.jsx)("img",{className:"weather-img",src:"/img/weather/".concat(t.weather_start.icon,".png"),alt:"activity weather (".concat(t.weather_start.icon,")"),title:t.weather_start.summary})]}),Object(i.jsxs)("th",{children:[a("workouts:End"),Object(i.jsx)("br",{}),Object(i.jsx)("img",{className:"weather-img",src:"/img/weather/".concat(t.weather_end.icon,".png"),alt:"activity weather (".concat(t.weather_end.icon,")"),title:t.weather_end.summary})]})]})}),Object(i.jsxs)("tbody",{children:[Object(i.jsxs)("tr",{children:[Object(i.jsx)("td",{children:Object(i.jsx)("img",{className:"weather-img-small",src:"/img/weather/temperature.png",alt:"Temperatures"})}),Object(i.jsxs)("td",{children:[Number(t.weather_start.temperature).toFixed(1),"\xb0C"]}),Object(i.jsxs)("td",{children:[Number(t.weather_end.temperature).toFixed(1),"\xb0C"]})]}),Object(i.jsxs)("tr",{children:[Object(i.jsx)("td",{children:Object(i.jsx)("img",{className:"weather-img-small",src:"/img/weather/pour-rain.png",alt:"Temperatures"})}),Object(i.jsxs)("td",{children:[Number(100*t.weather_start.humidity).toFixed(1),"%"]}),Object(i.jsxs)("td",{children:[Number(100*t.weather_end.humidity).toFixed(1),"%"]})]}),Object(i.jsxs)("tr",{children:[Object(i.jsx)("td",{children:Object(i.jsx)("img",{className:"weather-img-small",src:"/img/weather/breeze.png",alt:"Temperatures"})}),Object(i.jsxs)("td",{children:[Number(t.weather_start.wind).toFixed(1),"m/s"]}),Object(i.jsxs)("td",{children:[Number(t.weather_end.wind).toFixed(1),"m/s"]})]})]})]})})}function We(e){var t=e.activity,a=e.t,s="0:00:00"!==t.pauses&&null!==t.pauses;return Object(i.jsxs)("div",{className:"activity-details",children:[Object(i.jsxs)("p",{children:[Object(i.jsx)("i",{className:"fa fa-clock-o custom-fa","aria-hidden":"true"}),a("workouts:Duration"),": ",t.moving,t.records&&t.records.find((function(e){return"LD"===e.record_type}))&&Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})}),s&&Object(i.jsxs)("span",{children:[Object(i.jsx)("br",{}),"(",a("workouts:pauses"),": ",t.pauses,","," ",a("workouts:total duration"),": ",t.duration,")"]})]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("i",{className:"fa fa-road custom-fa","aria-hidden":"true"}),a("workouts:Distance"),": ",t.distance," km",t.records&&t.records.find((function(e){return"FD"===e.record_type}))&&Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})})]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("i",{className:"fa fa-tachometer custom-fa","aria-hidden":"true"}),a("workouts:Average speed"),": ",t.ave_speed," km/h",t.records&&t.records.find((function(e){return"AS"===e.record_type}))&&Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})}),Object(i.jsx)("br",{}),a("workouts:Max. speed"),": ",t.max_speed," km/h",t.records&&t.records.find((function(e){return"MS"===e.record_type}))&&Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})})]}),t.min_alt&&t.max_alt&&Object(i.jsxs)("p",{children:[Object(i.jsx)("i",{className:"fi-mountains custom-fa"}),a("workouts:Min. altitude"),": ",t.min_alt,"m",Object(i.jsx)("br",{}),a("workouts:Max. altitude"),": ",t.max_alt,"m"]}),t.ascent&&t.descent&&Object(i.jsxs)("p",{children:[Object(i.jsx)("i",{className:"fa fa-location-arrow custom-fa"}),a("workouts:Ascent"),": ",t.ascent,"m",Object(i.jsx)("br",{}),a("workouts:Descent"),": ",t.descent,"m"]}),Object(i.jsx)(Ge,{activity:t,t:a})]})}var Je=a(471),Ye=a(468),Ke=a(489),Xe=a(469),$e=a(470),Ze=a(233),Qe=a.n(Ze);function et(e){var t=e.bounds,a=e.coordinates,s=e.jsonData,n=e.mapAttribution;return Object(Ye.a)().fitBounds(t),Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)(Ke.a,{attribution:n,url:"".concat(T,"workouts/map_tile/{s}/{z}/{x}/{y}.png")}),Object(i.jsx)(Xe.a,{data:s},Qe()(s)),a.latitude&&Object(i.jsx)($e.a,{position:[a.latitude,a.longitude]})]})}var tt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={zoom:13},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){"activity"===this.props.dataType?this.props.loadActivityGpx(this.props.activity.id):this.props.loadSegmentGpx(this.props.activity.id,this.props.segmentId)}},{key:"componentDidUpdate",value:function(e){("activity"===this.props.dataType&&e.activity.id!==this.props.activity.id||"activity"===this.props.dataType&&"segment"===e.dataType)&&this.props.loadActivityGpx(this.props.activity.id),"segment"===this.props.dataType&&e.segmentId!==this.props.segmentId&&this.props.loadSegmentGpx(this.props.activity.id,this.props.segmentId)}},{key:"componentWillUnmount",value:function(){this.props.loadActivityGpx(null)}},{key:"render",value:function(){var e=this.props,t=e.activity,a=e.coordinates,s=e.gpxContent,n=e.mapAttribution,c=function(e){var t;if(e){var a=(new DOMParser).parseFromString(e,"text/xml");t=ve.a.gpx(a)}return{jsonData:t}}(s).jsonData,r=[[t.bounds[0],t.bounds[1]],[t.bounds[2],t.bounds[3]]];return Object(i.jsx)("div",{children:c&&Object(i.jsx)(Je.a,{zoom:this.state.zoom,bounds:r,boundsOptions:{padding:[10,10]},children:Object(i.jsx)(et,{bounds:r,coordinates:a,jsonData:c,mapAttribution:n})})})}}]),a}(c.a.Component),at=Object(y.c)((function(e){return{gpxContent:e.gpx,mapAttribution:e.application.config.map_attribution}}),(function(e){return{loadActivityGpx:function(t){e(function(e){return function(t){if(e)return q.getData("workouts/".concat(e,"/gpx")).then((function(e){"success"===e.status?t(Me(e.data.gpx)):t(G("workouts|".concat(e.message)))})).catch((function(e){return t(G("workouts|".concat(e)))}));t(Me(null))}}(t))},loadSegmentGpx:function(t,a){e(function(e,t){return function(a){if(e)return q.getData("workouts/".concat(e,"/gpx/segment/").concat(t)).then((function(e){"success"===e.status?a(Me(e.data.gpx)):a(G("workouts|".concat(e.message)))})).catch((function(e){return a(G("workouts|".concat(e)))}));a(Me(null))}}(t,a))}}}))(tt);function it(e){var t=e.t;return Object(i.jsx)("div",{className:"activity-no-map text-center",children:t("workouts:No Map")})}function st(e){var t=e.notes,a=e.t;return Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body",children:["Notes",Object(i.jsx)("div",{className:"activity-notes",children:t||a("workouts:No notes")})]})})})})}function nt(e){var t=e.segments,a=e.t;return Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body",children:[a("workouts:Segments"),Object(i.jsx)("div",{className:"activity-segments",children:Object(i.jsx)("ul",{children:t.map((function(e,t){return Object(i.jsxs)("li",{className:"activity-segments-list",children:[Object(i.jsxs)(te.a,{to:"/workouts/".concat(e.activity_id,"/segment/").concat(t+1),children:[a("workouts:segment")," ",t+1]})," ","(",a("workouts:distance"),": ",e.distance," km,"," ",a("workouts:duration"),": ",e.duration,")"]},"segment-".concat(t))}))})})]})})})})}function ct(e){var t=Object(de.a)().t;return Object(i.jsx)("div",{className:"custom-modal-backdrop",children:Object(i.jsx)("div",{className:"custom-modal",children:Object(i.jsxs)("div",{className:"modal-content",children:[Object(i.jsxs)("div",{className:"modal-header",children:[Object(i.jsx)("h5",{className:"modal-title",children:e.title}),Object(i.jsx)("button",{type:"button",className:"close","aria-label":"Close",onClick:function(){return e.close()},children:Object(i.jsx)("span",{"aria-hidden":"true",children:"\xd7"})})]}),Object(i.jsx)("div",{className:"modal-body",children:Object(i.jsx)("p",{children:e.text})}),Object(i.jsxs)("div",{className:"modal-footer",children:[Object(i.jsx)("button",{type:"button",className:"btn btn-primary",onClick:function(){return e.confirm()},children:t("common:Yes")}),Object(i.jsx)("button",{type:"button",className:"btn btn-secondary",onClick:function(){return e.close()},children:t("common:No")})]})]})})})}var rt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={displayModal:!1,coordinates:{latitude:null,longitude:null}},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadActivity(this.props.match.params.activityId)}},{key:"componentDidUpdate",value:function(e){e.match.params.activityId!==this.props.match.params.activityId&&this.props.loadActivity(this.props.match.params.activityId)}},{key:"displayModal",value:function(e){this.setState((function(t){return Object(S.a)(Object(S.a)({},t),{},{displayModal:e})}))}},{key:"updateCoordinates",value:function(e){var t=e&&e.length>0?{latitude:e[0].payload.latitude,longitude:e[0].payload.longitude}:{latitude:null,longitude:null};this.setState((function(e){return Object(S.a)(Object(S.a)({},e),{},{coordinates:t})}))}},{key:"render",value:function(){var e=this,t=this.props,a=t.activities,s=t.message,n=t.onDeleteActivity,c=t.sports,r=t.t,o=t.user,l=this.state,d=l.coordinates,u=l.displayModal,m=Object(pe.a)(a,1)[0],j=m?m.title:r("workouts:Activity"),p=m?c.filter((function(e){return e.id===m.sport_id})):[],h=Object(pe.a)(p,1)[0],b=parseInt(this.props.match.params.segmentId),v=b>=0?"segment":"activity";return Object(i.jsxs)("div",{className:"activity-page",children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",j]})}),s?Object(i.jsx)(_,{message:s,t:r}):Object(i.jsxs)("div",{className:"container",children:[u&&Object(i.jsx)(ct,{title:r("common:Confirmation"),text:r("workouts:Are you sure you want to delete this activity?"),confirm:function(){n(m.id),e.displayModal(!1)},close:function(){return e.displayModal(!1)}}),m&&h&&1===a.length&&Object(i.jsxs)("div",{children:[Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col",children:Object(i.jsxs)("div",{className:"card activity-card",children:[Object(i.jsx)("div",{className:"card-header",children:Object(i.jsx)(He,{activity:m,dataType:v,segmentId:b,sport:h,t:r,title:j,user:o,displayModal:function(){return e.displayModal(!0)}})}),Object(i.jsx)("div",{className:"card-body",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-md-8",children:m.with_gpx?Object(i.jsx)(at,{activity:m,coordinates:d,dataType:v,segmentId:b}):Object(i.jsx)(it,{t:r})}),Object(i.jsx)("div",{className:"col",children:Object(i.jsx)(We,{activity:"activity"===v?m:m.segments[b-1],t:r})})]})})]})})}),m.with_gpx&&Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsx)("div",{className:"card-body",children:Object(i.jsx)("div",{className:"row",children:Object(i.jsxs)("div",{className:"col",children:[Object(i.jsx)("div",{className:"chart-title",children:r("workouts:Chart")}),Object(i.jsx)(Ve,{activity:m,dataType:v,segmentId:b,t:r,updateCoordinates:function(t){return e.updateCoordinates(t)}})]})})})})})}),"activity"===v&&Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)(st,{notes:m.notes,t:r}),m.segments.length>1&&Object(i.jsx)(nt,{segments:m.segments,t:r})]})]})]})]})}}]),a}(c.a.Component),ot=Object(k.a)()(Object(y.c)((function(e){return{activities:e.activities.data,message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadActivity:function(t){e(K("getData","activities",{id:t}))},onDeleteActivity:function(t){var a;e((a=t,function(e){return q.deleteData("activities",a).then((function(t){var i;204===t.status?Promise.resolve(e((i=a,{type:"REMOVE_ACTIVITY",activityId:i}))).then((function(){return e(De())})).then((function(){return Hi.push("/")})):e(G("workouts|".concat(t.status)))})).catch((function(t){return e(G("workouts|".concat(t)))}))}))}}}))(rt)),lt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadActivity(this.props.match.params.activityId)}},{key:"render",value:function(){var e=this.props,t=e.activities,a=e.message,s=e.sports,n=Object(pe.a)(t,1)[0];return Object(i.jsx)("div",{children:s.length>0&&Object(i.jsx)(Ie,{activity:n,message:a,sports:s})})}}]),a}(c.a.Component),dt=Object(y.c)((function(e){return{activities:e.activities.data,message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadActivity:function(t){e(K("getData","activities",{id:t}))}}}))(lt);var ut=Object(y.c)((function(e){return{user:e.user}}))((function(){return Object(i.jsx)("div",{children:z()?Object(i.jsxs)(N.d,{children:[Object(i.jsx)(N.b,{exact:!0,path:"/workouts/add",component:Ue}),Object(i.jsx)(N.b,{exact:!0,path:"/workouts/:activityId",component:ot}),Object(i.jsx)(N.b,{exact:!0,path:"/workouts/:activityId/edit",component:dt}),Object(i.jsx)(N.b,{path:"/workouts/:activityId/segment/:segmentId",component:ot}),Object(i.jsx)(N.b,{component:ue})]}):Object(i.jsx)(N.a,{to:"/login"})})})),mt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props,t=e.loadActivities,a=e.sports,s=e.t,n=e.updateParams,c=we(a,s);return Object(i.jsx)("div",{className:"card",children:Object(i.jsx)("div",{className:"card-body activity-filter",children:Object(i.jsxs)("form",{onSubmit:function(e){return e.preventDefault()},children:[Object(i.jsxs)("div",{className:"form-group",children:[Object(i.jsxs)("label",{children:[s("workouts:From"),":",Object(i.jsx)("input",{className:"form-control col-md",name:"from",onChange:function(e){return n(e)},type:"date"})]}),Object(i.jsxs)("label",{children:[s("workouts:To"),":",Object(i.jsx)("input",{className:"form-control col-md",name:"to",onChange:function(e){return n(e)},type:"date"})]})]}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[s("common:Sport"),":",Object(i.jsxs)("select",{className:"form-control input-lg",name:"sport_id",onChange:function(e){return n(e)},children:[Object(i.jsx)("option",{value:""}),c.map((function(e){return Object(i.jsx)("option",{value:e.id,children:e.label},e.id)}))]})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[s("workouts:Distance")," (km):",Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",min:0,name:"distance_from",onChange:function(e){return n(e)},step:"1",type:"number"})}),Object(i.jsx)("div",{className:"col-2 align-middle text-center",children:s("common:to")}),Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",min:0,name:"distance_to",onChange:function(e){return n(e)},step:"1",type:"number"})})]})})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[s("workouts:Duration"),":",Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",name:"duration_from",onChange:function(e){return n(e)},pattern:"^([0-9]*[0-9]):([0-5][0-9])$",placeholder:"hh:mm",type:"text"})}),Object(i.jsx)("div",{className:"col-2 align-middle text-center",children:s("common:to")}),Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",name:"duration_to",onChange:function(e){return n(e)},pattern:"^([0-9]*[0-9]):([0-5][0-9])$",placeholder:"hh:mm",type:"text"})})]})})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[s("workouts:Average speed")," (km/h):",Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",min:0,name:"ave_speed_from",onChange:function(e){return n(e)},step:"1",type:"number"})}),Object(i.jsx)("div",{className:"col-2 align-middle text-center",children:s("common:to")}),Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",min:0,name:"ave_speed_to",onChange:function(e){return n(e)},step:"1",type:"number"})})]})})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[s("workouts:Max. speed")," (km/h):",Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",min:0,name:"max_speed_from",onChange:function(e){return n(e)},step:"1",type:"number"})}),Object(i.jsx)("div",{className:"col-2 align-middle text-center",children:s("common:to")}),Object(i.jsx)("div",{className:"col-5",children:Object(i.jsx)("input",{className:"form-control",min:0,name:"max_speed_to",onChange:function(e){return n(e)},step:"1",type:"number"})})]})})]})}),Object(i.jsx)("input",{className:"btn btn-primary btn-lg btn-block",onClick:function(){return t()},type:"submit",value:s("workouts:Filter")})]})})})}}]),a}(c.a.PureComponent),jt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props,t=e.activity,a=e.display;return Object(i.jsxs)("div",{className:"activity-map".concat("list"===a?"-list":""),children:[Object(i.jsx)("img",{src:"".concat(T,"workouts/map/").concat(t.map,"?").concat(Date.now()),alt:"activity map"}),Object(i.jsxs)("div",{className:"map-attribution".concat("list"===a?"-list":""),children:[Object(i.jsx)("span",{className:"map-attribution-text",children:"\xa9"}),Object(i.jsx)("a",{className:"map-attribution-text",href:"http://www.openstreetmap.org/copyright",target:"_blank",rel:"noopener noreferrer",children:"OpenStreetMap"})]})]})}}]),a}(c.a.PureComponent),pt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props,t=e.activities,a=e.loading,s=e.sports,n=e.t,c=e.user;return Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body",children:[Object(i.jsxs)("table",{className:"table",children:[Object(i.jsx)("thead",{children:Object(i.jsxs)("tr",{children:[Object(i.jsx)("th",{scope:"col"}),Object(i.jsx)("th",{scope:"col",children:n("common:Workout")}),Object(i.jsx)("th",{scope:"col",children:n("workouts:Date")}),Object(i.jsx)("th",{scope:"col",children:n("workouts:Distance")}),Object(i.jsx)("th",{scope:"col",children:n("workouts:Duration")}),Object(i.jsx)("th",{scope:"col",children:n("workouts:Ave. speed")}),Object(i.jsx)("th",{scope:"col",children:n("workouts:Max. speed")})]})}),Object(i.jsx)("tbody",{children:!a&&s&&t.map((function(e,t){return Object(i.jsxs)("tr",{children:[Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("common:Sport")}),Object(i.jsx)("img",{className:"activity-sport",src:s.filter((function(t){return t.id===e.sport_id})).map((function(e){return e.img})),alt:"activity sport logo"})]}),Object(i.jsxs)("td",{className:"activity-title",children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("common:Workout")}),Object(i.jsx)(te.a,{to:"/workouts/".concat(e.id),children:e.title}),e.map&&Object(i.jsx)(jt,{activity:e,display:"list"})]}),Object(i.jsxs)("td",{children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("workouts:Date")}),Object(D.a)(L(e.activity_date,c.timezone),"dd/MM/yyyy HH:mm")]}),Object(i.jsxs)("td",{className:"text-right",children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("workouts:Distance")}),Number(e.distance).toFixed(2)," km"]}),Object(i.jsxs)("td",{className:"text-right",children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("workouts:Duration")}),e.moving]}),Object(i.jsxs)("td",{className:"text-right",children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("workouts:Ave. speed")}),e.ave_speed," km/h"]}),Object(i.jsxs)("td",{className:"text-right",children:[Object(i.jsx)("span",{className:"heading-span-absolute",children:n("workouts:Max. speed")}),e.max_speed," km/h"]})]},t)}))})]}),a&&Object(i.jsx)("div",{className:"loader"})]})})}}]),a}(c.a.PureComponent),ht=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props.t;return Object(i.jsx)("div",{className:"card text-center",children:Object(i.jsxs)("div",{className:"card-body",children:[e("common:No workouts.")," ",Object(i.jsx)(te.a,{to:{pathname:"/workouts/add"},children:e("dashboard:Upload one !")})]})})}}]),a}(c.a.PureComponent),bt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={params:{page:1,per_page:10}},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadActivities(this.state.params)}},{key:"setParams",value:function(e){var t=this.state.params;""===e.target.value?delete t[e.target.name]:t[e.target.name]=e.target.value,t.page=1,this.setState(t)}},{key:"render",value:function(){var e=this,t=this.props,a=t.activities,s=t.loading,n=t.loadActivities,c=t.loadMoreActivities,r=t.message,o=t.sports,l=t.t,d=t.user,u=this.state.params,m=!(a.length>0)||null===a[a.length-1].previous_activity;return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",l("common:Workouts")]})}),r?Object(i.jsx)(_,{message:r,t:l}):Object(i.jsx)("div",{className:"container history",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-md-3",children:Object(i.jsx)(mt,{sports:o,loadActivities:function(){return n(u)},t:l,updateParams:function(t){return e.setParams(t)}})}),Object(i.jsxs)("div",{className:"col-md-9 workouts-result",children:[Object(i.jsx)(pt,{activities:a,loading:s,sports:o,t:l,user:d}),!m&&Object(i.jsx)("input",{type:"submit",className:"btn btn-default btn-md btn-block",value:"Load more workouts",onClick:function(){u.page+=1,c(u),e.setState(u)}}),0===a.length&&Object(i.jsx)(ht,{t:l})]})]})})]})}}]),a}(c.a.Component),vt=Object(k.a)()(Object(y.c)((function(e){return{activities:e.activities.data,loading:e.loading,message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadActivities:function(t){e(K("getData","activities",t))},loadMoreActivities:function(t){e(Fe(t))}}}))(bt));var ft=Object(k.a)()(Object(y.c)((function(e){return{appConfig:e.application.config,pathname:e.router.location.pathname,message:e.message}}),(function(e){return{onDeletePicture:function(){e((function(e){return ke.deletePicture().then((function(t){return 204===t.status?e(Ae()):e(_e(t.message))})).catch((function(e){throw e}))}))},onUploadPicture:function(t){e(function(e){return function(t){e.preventDefault();var a=new FormData;return a.append("file",e.target.picture.files[0]),e.target.reset(),q.addDataWithFile("auth/picture",a).then((function(e){if("success"===e.status)return t(Ae());var a=e.message.match(/file size exceeds/g)?"Error during picture update, file size exceeds max size.":e.message;return t(_e(a))})).catch((function(e){throw e}))}}(t))}}}))((function(e){var t=e.appConfig,a=e.displayModal,s=e.editable,n=e.isDeletable,c=e.message,r=e.onDeletePicture,o=e.onUploadPicture,l=e.pathname,d=e.t,u=e.user,m=u.created_at?Object(D.a)(new Date(u.created_at),"dd/MM/yyyy HH:mm"):"",j=u.birth_date?Object(D.a)(new Date(u.birth_date),"dd/MM/yyyy"):"",p=M(t.max_single_file_size);return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",d("user:Profile")]})}),Object(i.jsx)(_,{message:c,t:d}),Object(i.jsxs)("div",{className:"container",children:[Object(i.jsx)("h1",{className:"page-title",children:d("user:Profile")}),Object(i.jsx)("div",{className:"row",children:Object(i.jsx)("div",{className:"col-md-12",children:Object(i.jsxs)("div",{className:"card",children:[Object(i.jsx)("div",{className:"card-header userName",children:Object(i.jsx)("strong",{children:u.username})}),Object(i.jsxs)("div",{className:"card-body",children:[Object(i.jsxs)("div",{className:"row",children:[Object(i.jsxs)("div",{className:"col-md-8",children:[Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Email")}),": ",u.email]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Registration Date")}),": ",m]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:First Name")}),": ",u.first_name]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Last Name")}),": ",u.last_name]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Birth Date")}),": ",j]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Location")}),": ",u.location]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Bio")}),":"," ",u.bio]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Language")}),": ",u.language]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:Timezone")}),": ",u.timezone]}),Object(i.jsxs)("p",{children:[Object(i.jsx)("span",{className:"user-label",children:d("user:First day of week")}),": ",u.weekm?d("user:Monday"):d("user:Sunday")]})]}),Object(i.jsxs)("div",{className:"col-md-4",children:[!0===u.picture&&Object(i.jsxs)("div",{children:[Object(i.jsx)("img",{alt:"Profile",src:"".concat(T,"users/").concat(u.username,"/picture")+"?".concat(Date.now()),className:"img-fluid App-profile-img-small"}),s&&Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("br",{}),Object(i.jsx)("button",{type:"submit",onClick:function(){return r()},children:d("user:Delete picture")}),Object(i.jsx)("br",{}),Object(i.jsx)("br",{})]})]}),s&&Object(i.jsxs)("form",{encType:"multipart/form-data",onSubmit:function(e){return o(e)},children:[Object(i.jsx)("input",{type:"file",name:"picture",accept:".png,.jpg,.gif"}),Object(i.jsx)("br",{}),Object(i.jsx)("button",{type:"submit",children:d("user:Send")})," (max. size: ".concat(p,")")]})," "]})]}),s&&Object(i.jsx)("button",{className:"btn btn-primary",onClick:function(){return Hi.push("/profile/edit")},children:d("common:Edit")}),n&&Object(i.jsx)("button",{className:"btn btn-danger",onClick:function(){return a(!0)},children:d("user:Delete user account")}),Object(i.jsx)("button",{className:"btn btn-secondary",onClick:function(){return"/profile"===l?Hi.push("/"):Hi.go(-1)},children:d("/profile"===l?"common:Back to home":"common:Back")})]})]})})})]})]})})));var Ot=Object(k.a)()(Object(y.c)((function(e){return{user:e.user}}))((function(e){var t=e.t,a=e.user;return Object(i.jsx)("div",{children:Object(i.jsx)(ft,{editable:!0,t:t,user:a})})})));function xt(e){var t=e.activity,a=e.sports,s=e.t,n=e.user;return Object(i.jsxs)("div",{className:"card activity-card text-center",children:[Object(i.jsx)("div",{className:"card-header",children:Object(i.jsxs)(te.a,{to:"/workouts/".concat(t.id),children:[a.filter((function(e){return e.id===t.sport_id})).map((function(e){return s("sports:".concat(e.label))}))," ","-"," ",Object(D.a)(L(t.activity_date,n.timezone),"dd/MM/yyyy HH:mm")]})}),Object(i.jsx)("div",{className:"card-body",children:Object(i.jsxs)("div",{className:"row",children:[t.map&&Object(i.jsx)("div",{className:"col",children:Object(i.jsx)(jt,{activity:t})}),Object(i.jsx)("div",{className:"col",children:Object(i.jsxs)("p",{children:[Object(i.jsx)("i",{className:"fa fa-clock-o","aria-hidden":"true"})," ",s("workouts:Duration"),": ",t.moving,t.map?Object(i.jsxs)("span",{children:[Object(i.jsx)("br",{}),Object(i.jsx)("br",{})]}):" - ",Object(i.jsx)("i",{className:"fa fa-road","aria-hidden":"true"})," ",s("workouts:Distance"),": ",t.distance," km"]})})]})})]})}var gt=a(472),yt=a(473),Nt=a(474),wt=a(475),kt=a(234),_t=a(238),St=a(476),Dt=a(477),At=a(110),Ct=a(478),Et=a(486),Mt=a(488);function Tt(e){var t=e.activity,a=e.isDisabled,s=e.isMore,n=e.sportImg;return Object(i.jsx)(te.a,{className:"calendar-activity".concat(s),to:"/workouts/".concat(t.id),children:Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("img",{alt:"activity sport logo",className:"activity-sport ".concat(a),src:n,title:t.title}),t.records.length>0&&Object(i.jsx)("sup",{children:Object(i.jsx)("i",{className:"fa fa-trophy custom-fa-small","aria-hidden":"true",title:t.records.map((function(e){return" ".concat(Oe.filter((function(t){return t.record_type===e.record_type}))[0].label)}))})})]})})}var Pt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={isHidden:!0},s}return Object(O.a)(a,[{key:"handleDisplayMore",value:function(){this.setState({isHidden:!this.state.isHidden})}},{key:"render",value:function(){var e=this,t=this.props,a=t.dayActivities,s=t.isDisabled,n=t.sports,c=this.state.isHidden;return Object(i.jsxs)("div",{children:[a.map((function(e){return Object(i.jsx)(Tt,{activity:e,isDisabled:s,isMore:"",sportImg:n.filter((function(t){return t.id===e.sport_id})).map((function(e){return e.img}))},e.id)})),a.length>2&&Object(i.jsx)("i",{className:"fa fa-".concat(c?"plus":"times"," calendar-more"),"aria-hidden":"true",onClick:function(){return e.handleDisplayMore()},title:"show more workouts"}),!c&&Object(i.jsx)("div",{className:"calendar-display-more",children:a.map((function(e){return Object(i.jsx)(Tt,{activity:e,isDisabled:s,isMore:"-more",sportImg:n.filter((function(t){return t.id===e.sport_id})).map((function(e){return e.img}))},e.id)}))})]})}}]),a}(c.a.Component),Ft=function(e,t){var a=Object(gt.a)(e),i=Object(yt.a)(e),s=t?1:0;return{start:Object(Nt.a)(a,{weekStartsOn:s}),end:Object(wt.a)(i)}},zt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;Object(f.a)(this,a),s=t.call(this,e,i);var n=new Date;return s.state={currentMonth:n,startDate:Ft(n,e.weekm).start,endDate:Ft(n,e.weekm).end,weekStartOnMonday:e.weekm},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadMonthActivities(this.state.startDate,this.state.endDate)}},{key:"renderHeader",value:function(e){var t=this;return Object(i.jsxs)("div",{className:"header row flex-middle",children:[Object(i.jsx)("div",{className:"col col-start",onClick:function(){return t.handlePrevMonth()},children:Object(i.jsx)("i",{className:"fa fa-chevron-left","aria-hidden":"true"})}),Object(i.jsx)("div",{className:"col col-center",children:Object(i.jsx)("span",{children:Object(D.a)(this.state.currentMonth,"MMM yyyy",e)})}),Object(i.jsx)("div",{className:"col col-end",onClick:function(){return t.handleNextMonth()},children:Object(i.jsx)("i",{className:"fa fa-chevron-right","aria-hidden":"true"})})]})}},{key:"renderDays",value:function(e){for(var t=[],a=this.state.startDate,s=0;s<7;s++)t.push(Object(i.jsx)("div",{className:"col col-center",children:Object(D.a)(Object(kt.a)(a,s),"EEE",e)},s));return Object(i.jsx)("div",{className:"days row",children:t})}},{key:"filterActivities",value:function(e){var t=this.props,a=t.activities,i=t.user;return a?a.filter((function(t){return Object(_t.a)(L(t.activity_date,i.timezone),e)})):[]}},{key:"renderCells",value:function(){for(var e=this.state,t=e.currentMonth,a=e.startDate,s=e.endDate,n=e.weekStartOnMonday,c=this.props.sports,r=[],o=[],l=a,d="";l<=s;){for(var u=0;u<7;u++){d=Object(D.a)(l,"d");var m=this.filterActivities(l),j=Object(St.a)(l,t)?"":"-disabled",p=n?[5,6].includes(u):[0,6].includes(u);o.push(Object(i.jsx)("div",{className:"col cell ".concat(p?" weekend":"").concat(Object(Dt.a)(l)?" today":""),children:Object(i.jsxs)("div",{className:"img".concat(j),children:[Object(i.jsx)("span",{className:"number",children:d}),Object(i.jsx)(Pt,{dayActivities:m,isDisabled:j,sports:c})]})},l)),l=Object(kt.a)(l,1)}r.push(Object(i.jsx)("div",{className:"row",children:o},l)),o=[]}return Object(i.jsx)("div",{className:"body",children:r})}},{key:"updateStateDate",value:function(e){var t=Ft(e,this.state.weekStartOnMonday),a=t.start,i=t.end;this.setState({currentMonth:e,startDate:a,endDate:i}),this.props.loadMonthActivities(a,i)}},{key:"handleNextMonth",value:function(){var e=Object(At.a)(this.state.currentMonth,1);this.updateStateDate(e)}},{key:"handlePrevMonth",value:function(){var e=Object(Ct.a)(this.state.currentMonth,1);this.updateStateDate(e)}},{key:"render",value:function(){var e={locale:"fr"===this.props.language?Et.a:Mt.a};return Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"calendar",children:[this.renderHeader(e),this.renderDays(e),this.renderCells()]})})}}]),a}(c.a.Component),Rt=Object(y.c)((function(e){return{activities:e.calendarActivities.data,language:e.language,sports:e.sports.data,user:e.user}}),(function(e){return{loadMonthActivities:function(t,a){var i,s,n="yyyy-MM-dd";e((i=Object(D.a)(t,n),s=Object(D.a)(a,n),function(e){return q.getData("activities",{from:i,to:s,order:"asc",per_page:100}).then((function(t){"success"===t.status?e({type:"UPDATE_CALENDAR",activities:t.data.activities}):e(G("workouts|".concat(t.message)))})).catch((function(t){return e(G("workouts|".concat(t)))}))}))}}}))(zt);function Lt(e){var t=e.records,a=e.sports,s=e.t,n=e.user,c=we(a,s),r=t.reduce((function(e,t){var a=c.find((function(e){return e.id===t.sport_id}));return void 0===e[a.label]&&(e[a.label]={img:a.img,records:[]}),e[a.label].records.push(function(e,t){var a;switch(e.record_type){case"AS":case"MS":a="".concat(e.value," km/h");break;case"FD":a="".concat(e.value," km");break;default:a=e.value}var i=Oe.filter((function(t){return t.record_type===e.record_type})),s=Object(pe.a)(i,1)[0];return{activity_date:xe(L(e.activity_date,t)).activity_date,activity_id:e.activity_id,id:e.id,record_type:s.label,value:a}}(t,n.timezone)),e}),{});return Object(i.jsxs)("div",{className:"card activity-card",children:[Object(i.jsx)("div",{className:"card-header",children:s("workouts:Personal records")}),Object(i.jsx)("div",{className:"card-body",children:0===Object.keys(r).length?s("common:No records."):Object.keys(r).sort().map((function(e){return Object(i.jsxs)("div",{children:[Object(i.jsxs)("span",{className:"heading-span",children:[Object(i.jsx)("img",{alt:"".concat(e," logo"),className:"record-logo",src:r[e].img}),e]}),Object(i.jsxs)("table",{className:"table table-borderless table-sm record-table",children:[Object(i.jsx)("thead",{children:Object(i.jsx)("tr",{children:Object(i.jsxs)("th",{colSpan:"3",children:[Object(i.jsx)("img",{alt:"".concat(e," logo"),className:"record-logo",src:r[e].img}),e]})})}),Object(i.jsx)("tbody",{children:r[e].records.map((function(e){return Object(i.jsxs)("tr",{className:"record-tr",children:[Object(i.jsx)("td",{className:"record-td",children:s("workouts:".concat(e.record_type))}),Object(i.jsx)("td",{className:"record-td text-right",children:e.value}),Object(i.jsx)("td",{className:"record-td text-right",children:Object(i.jsx)(te.a,{to:"/workouts/".concat(e.activity_id),children:e.activity_date})})]},e.id)}))})]})]},e)}))})]})}var It=a(235),Ut=a(479),Ht=[{duration:"week",dateFormat:"yyyy-MM-dd",xAxis:"dd/MM"},{duration:"month",dateFormat:"yyyy-MM",xAxis:"MM/yyyy"},{duration:"year",dateFormat:"yyyy",xAxis:"yyyy"}],qt=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a="0";t&&(a=String(Math.floor(e/86400)),e%=86400);var i=String(Math.floor(e/3600)).padStart(2,"0");e%=3600;var s=String(Math.floor(e/60)).padStart(2,"0"),n=String(e%60).padStart(2,"0");return t?"".concat("0"===a?"":"".concat(a,"d:")).concat("00"===i?"":"".concat(i,"h:")).concat(s,"m:").concat(n,"s"):"".concat("00"===i?"":"".concat(i,":")).concat(s,":").concat(n)},Bt=function(e,t){return 0===t?"":"distance"===e?"".concat(t.toFixed(2)," km"):"duration"===e?qt(t):t},Vt=function(e,t){switch(e){case"week":return Object(kt.a)(t,7);case"year":return Object(It.a)(t,1);case"month":default:return Object(At.a)(t,1)}},Gt=function(e,t,a,i,s){for(var n=[],c=[],r=[],o=function(s){var o=Ht.filter((function(e){return e.duration===a.duration})),l=Object(pe.a)(o,1)[0],d=Object(D.a)(s,l.dateFormat),u=Object(D.a)(s,l.xAxis),m={date:u},j={date:u},p={date:u};e[d]&&Object.keys(e[d]).filter((function(e){return!i||i.includes(+e)})).map((function(a){var i=t.filter((function(e){return e.id===+a}))[0].label;return m[i]=e[d][a].nb_activities,j[i]=e[d][a].total_distance,p[i]=e[d][a].total_duration,null})),n.push(m),c.push(j),r.push(p)},l=function(e,t,a){switch(e){case"week":return Object(Nt.a)(t,{weekStartsOn:a?1:0});case"year":return Object(Ut.a)(t);case"month":default:return Object(gt.a)(t)}}(a.duration,a.start,s);l<=a.end;l=Vt(a.duration,l))o(l);return{activities:n,distance:c,duration:r}},Wt=function(e,t){return"duration"===e?qt(t,!0):"distance"===e?t.toFixed(2):t};function Jt(e){if(e.active){var t=e.displayedData,a=e.payload,s=e.label,n=0;return a.map((function(e){return n+=e.value})),Object(i.jsxs)("div",{className:"custom-tooltip",children:[Object(i.jsx)("p",{className:"custom-tooltip-label",children:s}),a.map((function(e){return Object(i.jsxs)("p",{style:{color:e.fill},children:[e.name,": ",Wt(t,e.value)," ",e.unit]},e.name)})),a.length>0&&Object(i.jsxs)("p",{children:["Total: ",Wt(t,n)]})]})}return null}function Yt(e){var t=e.displayedData,a=e.x,s=e.y,n=e.width,c=e.value;if(!c)return null;var r=Bt(t,c);return Object(i.jsx)("g",{children:Object(i.jsx)("text",{x:a+n/2,y:s-10,fill:"#666",fontSize:"11",textAnchor:"middle",dominantBaseline:"middle",children:r})})}var Kt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={displayedData:"distance"},s}return Object(O.a)(a,[{key:"handleRadioChange",value:function(e){this.setState({displayedData:e.target.name})}},{key:"render",value:function(){var e=this,t=this.state.displayedData,a=this.props,s=a.sports,n=a.stats,c=a.t;return 0===Object.keys(n).length?c("common:No workouts."):Object(i.jsxs)("div",{className:"chart-stats",children:[Object(i.jsxs)("div",{className:"row chart-radio",children:[Object(i.jsxs)("label",{className:"radioLabel col",children:[Object(i.jsx)("input",{type:"radio",name:"distance",checked:"distance"===t,onChange:function(t){return e.handleRadioChange(t)}}),c("statistics:distance")]}),Object(i.jsxs)("label",{className:"radioLabel col",children:[Object(i.jsx)("input",{type:"radio",name:"duration",checked:"duration"===t,onChange:function(t){return e.handleRadioChange(t)}}),c("statistics:duration")]}),Object(i.jsxs)("label",{className:"radioLabel col",children:[Object(i.jsx)("input",{type:"radio",name:"activities",checked:"activities"===t,onChange:function(t){return e.handleRadioChange(t)}}),c("statistics:workouts")]})]}),Object(i.jsx)(qe.f,{height:300,children:Object(i.jsxs)(qe.c,{data:n[t],margin:{top:15,bottom:0},children:[Object(i.jsx)(qe.h,{dataKey:"date",interval:0}),Object(i.jsx)(qe.i,{tickFormatter:function(e){return Bt(t,e)}}),Object(i.jsx)(qe.g,{content:Object(i.jsx)(Jt,{displayedData:t})}),s.map((function(e,a){return Object(i.jsx)(qe.b,{isAnimationActive:!1,dataKey:e.label,stackId:"a",fill:fe[a],label:a===s.length-1?Object(i.jsx)(Yt,{displayedData:t}):"",name:c("sports:".concat(e.label))},e.id)}))]})})]})}}]),a}(c.a.PureComponent),Xt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.updateData()}},{key:"componentDidUpdate",value:function(e){(this.props.user.username&&this.props.user.username!==e.user.username||this.props.statsParams!==e.statsParams)&&this.updateData()}},{key:"updateData",value:function(){this.props.user.username&&this.props.loadActivities(this.props.user.username,this.props.user.weekm,this.props.statsParams)}},{key:"render",value:function(){var e=this.props,t=e.displayedSports,a=e.sports,s=e.statistics,n=e.statsParams,c=e.displayEmpty,r=e.t,o=e.user;if(!c&&0===Object.keys(s).length)return Object(i.jsx)("span",{children:r("common:No workouts.")});var l=Gt(s,a,n,t,o.weekm);return Object(i.jsx)(Kt,{sports:a,stats:l,t:r})}}]),a}(c.a.PureComponent),$t=Object(y.c)((function(e){return{sports:e.sports.data,statistics:e.statistics.data,user:e.user}}),(function(e){return{loadActivities:function(t,a,i){var s="yyyy-MM-dd",n="week"===i.duration?"".concat(i.duration).concat(a?"m":""):i.duration,c={from:Object(D.a)(i.start,s),to:Object(D.a)(i.end,s),time:n};e(function(e,t,a){return function(i){return q.getData("stats/".concat(e,"/").concat(t),a).then((function(e){"success"===e.status?i(B("statistics",e.data)):i(G("statistics|".concat(e.message)))})).catch((function(e){return i(G("statistics|".concat(e)))}))}}(t,i.type,c))}}}))(Xt),Zt=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;Object(f.a)(this,a),s=t.call(this,e,i);var n=new Date;return s.state={start:Object(gt.a)(n),end:Object(yt.a)(n),duration:"week",type:"by_time"},s}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props.t;return Object(i.jsxs)("div",{className:"card activity-card",children:[Object(i.jsx)("div",{className:"card-header",children:e("dashboard:This month")}),Object(i.jsx)("div",{className:"card-body",children:Object(i.jsx)($t,{displayEmpty:!1,statsParams:this.state,t:e})})]})}}]),a}(c.a.Component);function Qt(e){var t=e.t,a=e.user,s=a.total_duration.match(/day/g)?"".concat(a.total_duration.split(" ")[0]," ").concat(a.total_duration.match(/days/g)?t("common:days"):t("common:day")):"0 ".concat(t("common:days"),","),n=a.total_duration.match(/day/g)?a.total_duration.split(", ")[1]:a.total_duration;return n="".concat(n.split(":")[0],"h ").concat(n.split(":")[1],"min"),Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-calendar fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:a.nb_activities}),Object(i.jsx)("div",{children:"".concat(1===a.nb_activities?t("common:workout"):t("common:workouts"))})]})]})})}),Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-road fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:Number(a.total_distance).toFixed(2)}),Object(i.jsx)("div",{children:"km"})]})]})})}),Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-clock-o fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:s}),Object(i.jsx)("div",{children:n})]})]})})}),Object(i.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(i.jsx)("div",{className:"card activity-card",children:Object(i.jsxs)("div",{className:"card-body row",children:[Object(i.jsx)("div",{className:"col-3",children:Object(i.jsx)("i",{className:"fa fa-tags fa-3x fa-color"})}),Object(i.jsxs)("div",{className:"col-9 text-right",children:[Object(i.jsx)("div",{className:"huge",children:a.nb_sports}),Object(i.jsx)("div",{children:"".concat(1===a.nb_sports?t("common:sport"):t("common:sports"))})]})]})})})]})}var ea=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={page:1},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadActivities()}},{key:"render",value:function(){var e=this,t=this.props,a=t.activities,s=t.loadMoreActivities,n=t.message,c=t.records,r=t.sports,o=t.t,l=t.user,d=!(a.length>0)||null===a[a.length-1].previous_activity,u=this.state.page;return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",o("common:Dashboard")]})}),n?Object(i.jsx)(_,{message:n,t:o}):a&&l.total_duration&&r.length>0&&Object(i.jsxs)("div",{className:"container dashboard",children:[Object(i.jsx)(Qt,{user:l,t:o}),Object(i.jsxs)("div",{className:"row",children:[Object(i.jsxs)("div",{className:"col-md-4",children:[Object(i.jsx)(Zt,{t:o}),Object(i.jsx)(Lt,{t:o,records:c,sports:r,user:l})]}),Object(i.jsxs)("div",{className:"col-md-8",children:[Object(i.jsx)(Rt,{weekm:l.weekm}),a.length>0?a.map((function(e){return Object(i.jsx)(xt,{activity:e,sports:r,t:o,user:l},e.id)})):Object(i.jsx)(ht,{t:o}),!d&&Object(i.jsx)("input",{type:"submit",className:"btn btn-default btn-md btn-block",value:"Load more workouts",onClick:function(){s(u+1),e.setState({page:u+1})}})]})]})]})]})}}]),a}(c.a.Component),ta=Object(k.a)()(Object(y.c)((function(e){return{activities:e.activities.data,message:e.message,records:e.records.data,sports:e.sports.data,user:e.user}}),(function(e){return{loadActivities:function(){e(K("getData","activities",{page:1})),e(K("getData","records"))},loadMoreActivities:function(t){e(Fe({page:t}))}}}))(ea));function aa(){return Object(i.jsx)("footer",{className:"footer",children:Object(i.jsxs)("div",{className:"container",children:[Object(i.jsx)("strong",{children:"FitTrackee"})," v","0.4.2"," -"," ",Object(i.jsx)("a",{href:"https://github.com/SamR1/FitTrackee",target:"_blank",rel:"noopener noreferrer",children:"source code"})," ","under"," ",Object(i.jsx)("a",{href:"https://choosealicense.com/licenses/gpl-3.0/",target:"_blank",rel:"noopener noreferrer",children:"GPLv3"})," ","license -"," ",Object(i.jsx)("a",{href:"https://samr1.github.io/FitTrackee/",target:"_blank",rel:"noopener noreferrer",children:"documentation"})]})})}var ia=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.UserLogout()}},{key:"render",value:function(){return Object(i.jsx)("div",{className:"container dashboard",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-2"}),Object(i.jsx)("div",{className:"card col-8",children:Object(i.jsx)("div",{className:"card-body",children:Object(i.jsx)("div",{className:"text-center",children:Object(i.jsxs)(je.a,{i18nKey:"user:loggedOut",children:["You are now logged out. Click ",Object(i.jsx)(te.a,{to:"/login",children:"here"})," to log back in."]})})})}),Object(i.jsx)("div",{className:"col-2"})]})})}}]),a}(c.a.Component),sa=Object(y.c)((function(e){return{user:e.user}}),(function(e){return{UserLogout:function(){e({type:"LOGOUT"})}}}))(ia);function na(){return(na=Object.assign||function(e){for(var t=1;t=0||(s[a]=e[a]);return s}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(s[a]=e[a])}return s}var ra=n.createElement("path",{d:"m466.916 27.803h-421.832c-24.859 0-45.084 20.225-45.084 45.084v366.226c0 24.859 20.225 45.084 45.084 45.084h421.832c24.859 0 45.084-20.225 45.084-45.084v-366.226c0-24.859-20.225-45.084-45.084-45.084z",fill:"#f0f9ff"}),oa=n.createElement("path",{d:"m198.58 188.334-181.344-150.862c-7.75 6.107-13.456 14.691-15.905 24.554l164.142 136.551h33.102z",fill:"#f40055"}),la=n.createElement("path",{d:"m313.425 198.576h33.93l163.447-135.973c-2.325-9.923-7.93-18.592-15.613-24.796l-181.764 151.211z",fill:"#c20044"}),da=n.createElement("path",{d:"m165.472 313.425-164.141 136.549c2.449 9.863 8.155 18.447 15.905 24.553l181.344-150.861-.005-10.241z",fill:"#f40055"}),ua=n.createElement("path",{d:"m313.425 313.425v9.557l181.765 151.211c7.683-6.204 13.288-14.874 15.613-24.796l-163.446-135.971z",fill:"#c20044"}),ma=n.createElement("path",{d:"m53.273 27.803 145.302 120.879v-120.879z",fill:"#406bd4"}),ja=n.createElement("path",{d:"m313.425 150.571v-122.768h148.082z",fill:"#3257b0"}),pa=n.createElement("path",{d:"m394.732 198.575 117.268-97.556v97.556z",fill:"#3257b0"}),ha=n.createElement("g",{fill:"#406bd4"},n.createElement("path",{d:"m0 99.317v99.258h119.313z"}),n.createElement("path",{d:"m0 313.425v97.699l117.44-97.699z"}),n.createElement("path",{d:"m50.49 484.197 148.085-122.676v122.676z"})),ba=n.createElement("path",{d:"m313.425 484.197v-124.139l149.221 124.139z",fill:"#3257b0"}),va=n.createElement("path",{d:"m512 409.423-115.395-95.998h115.395z",fill:"#3257b0"}),fa=n.createElement("path",{d:"m512 222.142h-222.142v-194.339h-67.716v194.339h-222.142v67.716h222.142v194.339h67.716v-194.339h222.142z",fill:"#f40055"}),Oa=n.createElement("path",{d:"m289.858 222.142v-194.339h-33.858v456.394h33.858v-194.339h222.142v-67.716z",fill:"#c20044"});function xa(e,t){var a=e.title,i=e.titleId,s=ca(e,["title","titleId"]);return n.createElement("svg",na({id:"Capa_1",enableBackground:"new 0 0 512 512",height:512,viewBox:"0 0 512 512",width:512,xmlns:"http://www.w3.org/2000/svg",ref:t,"aria-labelledby":i},s),a?n.createElement("title",{id:i},a):null,ra,oa,la,da,ua,ma,ja,pa,ha,ba,va,fa,Oa)}var ga=n.forwardRef(xa);a.p;function ya(){return(ya=Object.assign||function(e){for(var t=1;t=0||(s[a]=e[a]);return s}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(s[a]=e[a])}return s}var wa=n.createElement("path",{d:"m173.899 31.804h-8.707l-4.397-4h-115.711c-24.859-.001-45.084 20.224-45.084 45.083v366.226c0 24.859 20.225 45.084 45.084 45.084h115.711l6.348-4h6.755v-448.393z",fill:"#406bd4"}),ka=n.createElement("path",{d:"m466.916 27.803h-115.711l-4.523 4h-5.141v448.393h4.141l5.523 4h115.711c24.859 0 45.084-20.225 45.084-45.084v-366.225c0-24.859-20.225-45.084-45.084-45.084z",fill:"#c20044"}),_a=n.createElement("path",{d:"m160.795 27.803h190.409v456.394h-190.409z",fill:"#f0f9ff"}),Sa=n.createElement("path",{d:"m256 27.803h95.205v456.394h-95.205z",fill:"#cee5f5"});function Da(e,t){var a=e.title,i=e.titleId,s=Na(e,["title","titleId"]);return n.createElement("svg",ya({id:"Capa_1",enableBackground:"new 0 0 512 512",height:512,viewBox:"0 0 512 512",width:512,xmlns:"http://www.w3.org/2000/svg",ref:t,"aria-labelledby":i},s),a?n.createElement("title",{id:i},a):null,wa,ka,_a,Sa)}var Aa=n.forwardRef(Da),Ca=(a.p,[{name:"en",selected:!0,flag:Object(i.jsx)(ga,{})},{name:"fr",selected:!1,flag:Object(i.jsx)(Aa,{})}]),Ea=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e){var i;return Object(f.a)(this,a),(i=t.call(this,e)).state={isOpen:!1},i}return Object(O.a)(a,[{key:"toggleDropdown",value:function(){this.setState((function(e){return{isOpen:!e.isOpen}}))}},{key:"render",value:function(){var e=this,t=this.state.isOpen,a=this.props,s=a.language,n=a.onUpdateLanguage;return Object(i.jsx)("div",{className:"dropdown-wrapper",onClick:function(){return e.toggleDropdown()},children:Object(i.jsx)("ul",{className:"dropdown-list i18n-flag",children:Ca.filter((function(e){return t?e:e.name===s})).map((function(e){return Object(i.jsxs)("li",{className:"dropdown-item".concat(e.name===s&&t?" dropdown-item-selected":""),onClick:function(){return n(e.name,s)},children:[e.flag," ",e.name]},e.name)}))})})}}]),a}(n.Component),Ma=Object(y.c)((function(e){return{language:e.language}}),(function(e){return{onUpdateLanguage:function(t,a){t!==a&&e(X(t))}}}))(Ea),Ta=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(O.a)(a,[{key:"render",value:function(){var e=this.props,t=e.admin,a=e.isAuthenticated,s=e.picture,n=e.t,c=e.username;return Object(i.jsx)("header",{children:Object(i.jsx)("nav",{className:"navbar navbar-expand-lg navbar-light bg-light",children:Object(i.jsxs)("div",{className:"container",children:[Object(i.jsx)("span",{className:"navbar-brand",children:"FitTrackee"}),Object(i.jsx)("button",{className:"navbar-toggler",type:"button","data-toggle":"collapse","data-target":"#navbarSupportedContent","aria-controls":"navbarSupportedContent","aria-expanded":"false","aria-label":"Toggle navigation",children:Object(i.jsx)("span",{className:"navbar-toggler-icon"})}),Object(i.jsxs)("div",{className:"collapse navbar-collapse",id:"navbarSupportedContent",children:[Object(i.jsxs)("ul",{className:"navbar-nav mr-auto",children:[Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/"},children:n("common:Dashboard")})}),a&&Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/workouts/history"},children:n("Workouts")})}),a&&Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/workouts/statistics"},children:n("common:Statistics")})}),t&&Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/admin"},children:"Admin"})}),a&&Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/workouts/add"},children:Object(i.jsx)("strong",{children:n("common:Add workout")})})})]}),Object(i.jsxs)("ul",{className:"navbar-nav flex-row ml-md-auto d-none d-md-flex",children:[!a&&Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/register"},children:n("user:Register")})}),!a&&Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/login"},children:n("user:Login")})}),a&&Object(i.jsxs)(i.Fragment,{children:[!0===s?Object(i.jsx)("img",{alt:"Avatar",src:"".concat(T,"users/").concat(c,"/picture?").concat(Date.now()),className:"img-fluid App-nav-profile-img"}):Object(i.jsx)("i",{className:"fa fa-user-circle-o fa-2x no-picture","aria-hidden":"true"}),Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/profile"},children:c})}),Object(i.jsx)("li",{className:"nav-item",children:Object(i.jsx)(te.a,{className:"nav-link",to:{pathname:"/logout"},children:n("user:Logout")})})]}),Object(i.jsx)("li",{children:Object(i.jsx)(Ma,{})})]})]})]})})})}}]),a}(c.a.PureComponent),Pa=Object(k.a)()(Object(y.c)((function(e){var t=e.user;return{admin:t.admin,isAuthenticated:t.isAuthenticated,picture:t.picture,username:t.username}}))(Ta));function Fa(){return(Fa=Object.assign||function(e){for(var t=1;t=0||(s[a]=e[a]);return s}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(s[a]=e[a])}return s}var Ra=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M468.683,287.265h-69.07c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h69.07 c4.147,0,7.508-3.361,7.508-7.508C476.191,290.626,472.83,287.265,468.683,287.265z"}))),La=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M105.012,268.377L85.781,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L58.034,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C109.507,275.266,108.499,270.62,105.012,268.377z"}))),Ia=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M194.441,268.377L175.21,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.47,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.776l-17.471-11.243 c-3.487-2.245-8.133-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L147.463,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.47,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C198.936,275.266,197.928,270.62,194.441,268.377z"}))),Ua=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M283.871,268.377L264.64,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.471-11.243 c-3.486-2.245-8.134-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L236.892,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.886-1.216,6.32-3.446C288.366,275.266,287.358,270.62,283.871,268.377z"}))),Ha=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M373.3,268.377L354.069,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L326.322,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C377.795,275.266,376.787,270.62,373.3,268.377z"}))),qa=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M271.792,330.359H15.016V181.642h93.1c4.147,0,7.508-3.361,7.508-7.508c0-4.147-3.361-7.508-7.508-7.508H12.513 C5.613,166.626,0,172.24,0,179.14v153.722c0,6.9,5.613,12.513,12.513,12.513h259.278c4.147,0,7.508-3.361,7.508-7.508 C279.299,333.72,275.939,330.359,271.792,330.359z"}))),Ba=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M499.487,166.626H162.174c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h334.811v148.716H323.848 c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h175.64c6.9,0,12.513-5.613,12.513-12.513V179.14 C512.001,172.24,506.387,166.626,499.487,166.626z"})));function Va(e,t){var a=e.title,i=e.titleId,s=za(e,["title","titleId"]);return n.createElement("svg",Fa({id:"Layer_1",xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 512.001 512.001",style:{enableBackground:"new 0 0 512.001 512.001"},xmlSpace:"preserve",ref:t,"aria-labelledby":i},s),a?n.createElement("title",{id:i},a):null,Ra,La,Ia,Ua,Ha,qa,Ba)}var Ga=n.forwardRef(Va);a.p;function Wa(){return(Wa=Object.assign||function(e){for(var t=1;t=0||(s[a]=e[a]);return s}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(s[a]=e[a])}return s}var Ya=n.createElement("g",null,n.createElement("path",{d:"M339.798,260.429c0.13-0.026,0.257-0.061,0.385-0.094c0.109-0.028,0.219-0.051,0.326-0.084 c0.125-0.038,0.247-0.085,0.369-0.129c0.108-0.039,0.217-0.074,0.324-0.119c0.115-0.048,0.226-0.104,0.338-0.157 c0.109-0.052,0.22-0.1,0.327-0.158c0.107-0.057,0.208-0.122,0.312-0.184c0.107-0.064,0.215-0.124,0.319-0.194 c0.111-0.074,0.214-0.156,0.321-0.236c0.09-0.067,0.182-0.13,0.27-0.202c0.162-0.133,0.316-0.275,0.466-0.421 c0.027-0.026,0.056-0.048,0.083-0.075c0.028-0.028,0.052-0.059,0.079-0.088c0.144-0.148,0.284-0.3,0.416-0.46 c0.077-0.094,0.144-0.192,0.216-0.289c0.074-0.1,0.152-0.197,0.221-0.301c0.074-0.111,0.139-0.226,0.207-0.34 c0.057-0.096,0.118-0.19,0.171-0.289c0.062-0.115,0.114-0.234,0.169-0.351c0.049-0.104,0.101-0.207,0.146-0.314 c0.048-0.115,0.086-0.232,0.128-0.349c0.041-0.114,0.085-0.227,0.12-0.343c0.036-0.118,0.062-0.238,0.092-0.358 c0.029-0.118,0.063-0.234,0.086-0.353c0.028-0.141,0.045-0.283,0.065-0.425c0.014-0.1,0.033-0.199,0.043-0.3 c0.025-0.249,0.038-0.498,0.038-0.748V92.76c0-4.143-3.357-7.5-7.5-7.5h-236.25c-0.066,0-0.13,0.008-0.196,0.01 c-0.143,0.004-0.285,0.01-0.427,0.022c-0.113,0.009-0.225,0.022-0.337,0.037c-0.128,0.016-0.255,0.035-0.382,0.058 c-0.119,0.021-0.237,0.046-0.354,0.073c-0.119,0.028-0.238,0.058-0.356,0.092c-0.117,0.033-0.232,0.069-0.346,0.107 c-0.117,0.04-0.234,0.082-0.349,0.128c-0.109,0.043-0.216,0.087-0.322,0.135c-0.118,0.053-0.235,0.11-0.351,0.169 c-0.099,0.051-0.196,0.103-0.292,0.158c-0.116,0.066-0.23,0.136-0.343,0.208c-0.093,0.06-0.184,0.122-0.274,0.185 c-0.106,0.075-0.211,0.153-0.314,0.235c-0.094,0.075-0.186,0.152-0.277,0.231c-0.09,0.079-0.179,0.158-0.266,0.242 c-0.099,0.095-0.194,0.194-0.288,0.294c-0.047,0.05-0.097,0.094-0.142,0.145c-0.027,0.03-0.048,0.063-0.074,0.093 c-0.094,0.109-0.182,0.223-0.27,0.338c-0.064,0.084-0.13,0.168-0.19,0.254c-0.078,0.112-0.15,0.227-0.222,0.343 c-0.059,0.095-0.12,0.189-0.174,0.286c-0.063,0.112-0.118,0.227-0.175,0.342c-0.052,0.105-0.106,0.21-0.153,0.317 c-0.049,0.113-0.092,0.23-0.135,0.345c-0.043,0.113-0.087,0.225-0.124,0.339c-0.037,0.115-0.067,0.232-0.099,0.349 c-0.032,0.12-0.066,0.239-0.093,0.36c-0.025,0.113-0.042,0.228-0.062,0.342c-0.022,0.13-0.044,0.26-0.06,0.39 c-0.013,0.108-0.019,0.218-0.027,0.328c-0.01,0.14-0.019,0.28-0.021,0.421c-0.001,0.041-0.006,0.081-0.006,0.122v46.252 c0,4.143,3.357,7.5,7.5,7.5s7.5-3.357,7.5-7.5v-29.595l66.681,59.037c-0.348,0.245-0.683,0.516-0.995,0.827l-65.687,65.687v-49.288 c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v9.164h-38.75c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h38.75v43.231 c0,4.143,3.357,7.5,7.5,7.5h236.25c0.247,0,0.494-0.013,0.74-0.037c0.115-0.011,0.226-0.033,0.339-0.049 C339.542,260.469,339.67,260.454,339.798,260.429z M330.834,234.967l-65.688-65.687c-0.042-0.042-0.087-0.077-0.13-0.117 l49.383-41.897c3.158-2.68,3.546-7.412,0.866-10.571c-2.678-3.157-7.41-3.547-10.571-0.866l-84.381,71.59l-98.444-87.158h208.965 V234.967z M185.878,179.888c0.535-0.535,0.969-1.131,1.308-1.765l28.051,24.835c1.418,1.255,3.194,1.885,4.972,1.885 c1.726,0,3.451-0.593,4.853-1.781l28.587-24.254c0.26,0.38,0.553,0.743,0.89,1.08l65.687,65.687H120.191L185.878,179.888z"}),n.createElement("path",{d:"M7.5,170.676h126.667c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H7.5c-4.143,0-7.5,3.357-7.5,7.5 S3.357,170.676,7.5,170.676z"}),n.createElement("path",{d:"M20.625,129.345H77.5c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H20.625c-4.143,0-7.5,3.357-7.5,7.5 S16.482,129.345,20.625,129.345z"}),n.createElement("path",{d:"M62.5,226.51h-55c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h55c4.143,0,7.5-3.357,7.5-7.5S66.643,226.51,62.5,226.51z"}));function Ka(e,t){var a=e.title,i=e.titleId,s=Ja(e,["title","titleId"]);return n.createElement("svg",Wa({id:"Capa_1",xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 345.834 345.834",style:{enableBackground:"new 0 0 345.834 345.834"},xmlSpace:"preserve",ref:t,"aria-labelledby":i},s),a?n.createElement("title",{id:i},a):null,Ya)}var Xa=n.forwardRef(Ka);a.p;function $a(e){var t=Object(de.a)().t,a=e.action;return Object(i.jsx)("div",{className:"container dashboard",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-2"}),Object(i.jsx)("div",{className:"card col-8",children:Object(i.jsx)("div",{className:"card-body",children:Object(i.jsxs)("div",{className:"text-center ",children:["sent"===a&&Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("div",{className:"svg-icon",children:Object(i.jsx)(Xa,{})}),t("user:Check your email. If your address is in our database, you'll received an email with a link to reset your password.")]}),"updated"===a&&Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("div",{className:"svg-icon",children:Object(i.jsx)(Ga,{})}),Object(i.jsxs)(je.a,{i18nKey:"user:updatedPasswordText",children:["Your password have been updated. Click",Object(i.jsx)(te.a,{to:"/login",children:"here"})," to log in."]})]})]})})}),Object(i.jsx)("div",{className:"col-2"})]})})}var Za=a(236),Qa=a.n(Za),ei=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={formData:{},displayModal:!1},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.initForm()}},{key:"componentDidUpdate",value:function(e){e.user!==this.props.user&&this.initForm()}},{key:"initForm",value:function(){var e=this.props.user,t={};Object.keys(e).map((function(a){return null===e[a]?t[a]="":t[a]="birth_date"===a?Object(D.a)(new Date(e[a]),"yyyy-MM-DD"):e[a]})),this.setState({formData:t})}},{key:"handleFormChange",value:function(e){var t=this.state.formData;"weekm"===e.target.name?t.weekm="Monday"===e.target.value:t[e.target.name]=e.target.value,this.setState(t)}},{key:"displayModal",value:function(e){this.setState((function(t){return Object(S.a)(Object(S.a)({},t),{},{displayModal:e})}))}},{key:"render",value:function(){var e=this,t=this.props,a=t.message,s=t.onDeleteUser,n=t.onHandleProfileFormSubmit,c=t.t,r=t.user,o=this.state,l=o.displayModal,d=o.formData;return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",c("user:Profile Edition")]})}),d.isAuthenticated&&Object(i.jsxs)("div",{className:"container",children:[l&&Object(i.jsx)(ct,{title:c("common:Confirmation"),text:c("user:Are you sure you want to delete your account? All data will be deleted, this cannot be undone."),confirm:function(){s(r.username),e.displayModal(!1)},close:function(){return e.displayModal(!1)}}),Object(i.jsx)("h1",{className:"page-title",children:c("user:Profile Edition")}),Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-md-2"}),Object(i.jsx)("div",{className:"col-md-8",children:Object(i.jsxs)("div",{className:"card",children:[Object(i.jsx)("div",{className:"card-header",children:r.username}),Object(i.jsx)("div",{className:"card-body",children:Object(i.jsx)("div",{className:"row",children:Object(i.jsxs)("div",{className:"col-md-12",children:[Object(i.jsxs)("form",{onSubmit:function(e){e.preventDefault(),n(d)},children:[Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Email"),":",Object(i.jsx)("input",{name:"email",className:"form-control input-lg",type:"text",value:d.email,readOnly:!0})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Registration Date"),":",Object(i.jsx)("input",{name:"createdAt",className:"form-control input-lg",type:"text",value:d.created_at,disabled:!0})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Password"),":",Object(i.jsx)("input",{name:"password",className:"form-control input-lg",type:"password",onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Password Confirmation"),":",Object(i.jsx)("input",{name:"password_conf",className:"form-control input-lg",type:"password",onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("hr",{}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:First Name"),":",Object(i.jsx)("input",{name:"first_name",className:"form-control input-lg",type:"text",value:d.first_name,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Last Name"),":",Object(i.jsx)("input",{name:"last_name",className:"form-control input-lg",type:"text",value:d.last_name,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Birth Date"),Object(i.jsx)("input",{name:"birth_date",className:"form-control input-lg",type:"date",value:d.birth_date,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Location"),":",Object(i.jsx)("input",{name:"location",className:"form-control input-lg",type:"text",value:d.location,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Bio"),":",Object(i.jsx)("textarea",{name:"bio",className:"form-control input-lg",maxLength:"200",value:d.bio,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Language"),":",Object(i.jsx)("select",{name:"language",className:"form-control input-lg",value:d.language,onChange:function(t){return e.handleFormChange(t)},children:Ca.map((function(e){return Object(i.jsx)("option",{value:e.name,children:e.name},e.name)}))})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:Timezone"),":",Object(i.jsx)(Qa.a,{className:"form-control timezone-custom",onChange:function(t){var a={target:{name:"timezone",value:t||"Europe/Paris"}};e.handleFormChange(a)},value:d.timezone})]})}),Object(i.jsx)("div",{className:"form-group",children:Object(i.jsxs)("label",{children:[c("user:First day of week"),":",Object(i.jsxs)("select",{name:"weekm",className:"form-control input-lg",value:d.weekm?"Monday":"Sunday",onChange:function(t){return e.handleFormChange(t)},children:[Object(i.jsx)("option",{value:"Sunday",children:c("user:Sunday")}),Object(i.jsx)("option",{value:"Monday",children:c("user:Monday")})]})]})}),Object(i.jsx)("button",{type:"submit",className:"btn btn-primary",children:c("common:Submit")}),Object(i.jsx)("button",{className:"btn btn-danger",onClick:function(t){t.preventDefault(),e.displayModal(!0)},children:c("user:Delete my account")}),Object(i.jsx)("button",{type:"submit",className:"btn btn-secondary",onClick:function(){return Hi.push("/profile")},children:c("common:Cancel")})]}),Object(i.jsx)(_,{message:a,t:c})]})})})]})}),Object(i.jsx)("div",{className:"col-md-2"})]})]})]})}}]),a}(c.a.Component),ti=Object(k.a)()(Object(y.c)((function(e){return{location:e.router.location,message:e.message,user:e.user}}),(function(e){return{onDeleteUser:function(t){e(Ee(t))},onHandleProfileFormSubmit:function(t){e(function(e){return function(t){return!e.password===e.password_conf?t(Se("Password and password confirmation don't match.")):(delete e.id,q.postData("auth/profile/edit",e).then((function(e){if("success"===e.status)return t(Ae()),Hi.push("/profile");t(Se(e.message))})).catch((function(e){throw e})))}}(t))}}}))(ei)),ai=a(480),ii=a(481),si=a(482),ni=a(237),ci=["week","month","year"],ri=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;Object(f.a)(this,a),s=t.call(this,e,i);var n=new Date;return s.state={displayedSports:e.sports.map((function(e){return e.id})),statsParams:{start:Object(gt.a)(Object(Ct.a)(n,11)),end:Object(yt.a)(n),duration:"month",type:"by_time"}},s}return Object(O.a)(a,[{key:"componentDidUpdate",value:function(e){this.props.sports!==e.sports&&this.updateDisplayedSports()}},{key:"updateDisplayedSports",value:function(){var e=this.props.sports;this.setState({displayedSports:e.map((function(e){return e.id}))})}},{key:"handleOnChangeDuration",value:function(e){var t=e.target.name,a=new Date,i="year"===t?Object(Ut.a)(Object(ai.a)(a,9)):"week"===t?Object(gt.a)(Object(Ct.a)(a,2)):Object(gt.a)(Object(Ct.a)(a,11)),s="year"===t?Object(ii.a)(a):"week"===t?Object(wt.a)(a):Object(yt.a)(a);this.setState({statsParams:{duration:t,end:s,start:i,type:"by_time"}})}},{key:"handleOnChangeSports",value:function(e){var t=this.state.displayedSports;t.includes(e)?this.setState({displayedSports:t.filter((function(t){return t!==e}))}):this.setState({displayedSports:t.concat([e])})}},{key:"handleOnClickArrows",value:function(e){var t,a,i=this.state.statsParams,s=i.start,n=i.end,c=i.duration;e?(t="year"===c?Object(Ut.a)(Object(ai.a)(s,1)):"week"===c?Object(Nt.a)(Object(si.a)(s,1)):Object(gt.a)(Object(Ct.a)(s,1)),a="year"===c?Object(ii.a)(Object(ai.a)(n,1)):"week"===c?Object(wt.a)(Object(si.a)(n,1)):Object(yt.a)(Object(Ct.a)(n,1))):(t="year"===c?Object(Ut.a)(Object(It.a)(s,1)):"week"===c?Object(Nt.a)(Object(ni.a)(s,1)):Object(gt.a)(Object(At.a)(s,1)),a="year"===c?Object(ii.a)(Object(It.a)(n,1)):"week"===c?Object(wt.a)(Object(ni.a)(n,1)):Object(yt.a)(Object(At.a)(n,1))),this.setState({statsParams:{duration:c,end:a,start:t,type:"by_time"}})}},{key:"render",value:function(){var e=this,t=this.state,a=t.displayedSports,s=t.statsParams,n=this.props,c=n.sports,r=n.t,o=n.user,l=we(c.filter((function(e){return o.sports_list.includes(e.id)})),r);return Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",r("statistics:Statistics")]})}),Object(i.jsxs)("div",{className:"container dashboard",children:[Object(i.jsxs)("div",{className:"card activity-card",children:[Object(i.jsx)("div",{className:"card-header",children:r("statistics:Statistics")}),Object(i.jsxs)("div",{className:"card-body".concat(0===o.nb_activities?" stats-disabled":""),children:[Object(i.jsxs)("div",{className:"chart-filters row",children:[Object(i.jsx)("div",{className:"col chart-arrows",children:Object(i.jsx)("p",{className:"text-center",children:Object(i.jsx)("i",{className:"fa fa-chevron-left","aria-hidden":"true",onClick:function(){return e.handleOnClickArrows(!0)}})})}),Object(i.jsx)("div",{className:"col-md-3 time-frames justify-content-around",children:ci.map((function(t){return Object(i.jsx)("div",{className:"time-frame",children:Object(i.jsxs)("label",{children:[Object(i.jsx)("input",{type:"radio",id:t,name:t,checked:t===s.duration,onChange:function(t){return e.handleOnChangeDuration(t)}}),Object(i.jsx)("span",{children:r("statistics:".concat(t))})]})},t)}))}),Object(i.jsx)("div",{className:"col chart-arrows",children:Object(i.jsx)("p",{className:"text-center",children:Object(i.jsx)("i",{className:"fa fa-chevron-right","aria-hidden":"true",onClick:function(){return e.handleOnClickArrows(!1)}})})})]}),Object(i.jsx)($t,{displayEmpty:!0,displayedSports:a,statsParams:s,t:r}),Object(i.jsx)("div",{className:"row chart-workouts",children:l.map((function(t){return Object(i.jsxs)("label",{className:"col activity-label",children:[Object(i.jsx)("input",{type:"checkbox",checked:a.includes(t.id),name:t.label,onChange:function(){return e.handleOnChangeSports(t.id)}}),Object(i.jsx)("span",{style:{color:fe[t.id-1]},children:" ".concat(t.label)})]},t.id)}))})]})]}),0===o.nb_activities&&Object(i.jsx)(ht,{t:r})]})]})}}]),a}(c.a.Component),oi=Object(k.a)()(Object(y.c)((function(e){return{sports:e.sports.data,user:e.user}}))(ri));function li(e){var t=Object(de.a)().t,a="user:".concat(e.formType.charAt(0).toUpperCase()).concat(e.formType.slice(1));return Object(i.jsxs)("div",{children:[Object(i.jsx)(w.a,{children:Object(i.jsxs)("title",{children:["FitTrackee - ",t("user:".concat(e.formType))]})}),Object(i.jsx)("h1",{className:"page-title",children:t(a)}),Object(i.jsx)("div",{className:"container",children:Object(i.jsxs)("div",{className:"row",children:[Object(i.jsx)("div",{className:"col-md-3"}),Object(i.jsxs)("div",{className:"col-md-6",children:[Object(i.jsx)("br",{}),"register"!==e.formType||e.isRegistrationAllowed?Object(i.jsxs)(i.Fragment,{children:[Object(i.jsxs)("form",{onSubmit:function(t){return e.handleUserFormSubmit(t,e.formType)},children:["register"===e.formType&&Object(i.jsx)("div",{className:"form-group",children:Object(i.jsx)("input",{className:"form-control input-lg",name:"username",placeholder:t("user:Enter a username"),required:!0,type:"text",value:e.userForm.username,onChange:e.onHandleFormChange})}),"password reset"!==e.formType&&Object(i.jsx)("div",{className:"form-group",children:Object(i.jsx)("input",{className:"form-control input-lg",name:"email",placeholder:t("user:Enter an email address"),required:!0,type:"email",value:e.userForm.email,onChange:e.onHandleFormChange})}),"reset your password"!==e.formType&&Object(i.jsxs)(i.Fragment,{children:[Object(i.jsx)("div",{className:"form-group",children:Object(i.jsx)("input",{className:"form-control input-lg",name:"password",placeholder:t("user:Enter a password"),required:!0,type:"password",value:e.userForm.password,onChange:e.onHandleFormChange})}),"login"!==e.formType&&Object(i.jsx)("div",{className:"form-group",children:Object(i.jsx)("input",{className:"form-control input-lg",name:"password_conf",placeholder:t("user:Enter the password confirmation"),required:!0,type:"password",value:e.userForm.password_conf,onChange:e.onHandleFormChange})})]}),Object(i.jsx)("input",{type:"submit",className:"btn btn-primary btn-lg btn-block",value:t("Submit")})]}),Object(i.jsx)("p",{className:"password-forget",children:"login"===e.formType&&Object(i.jsx)(te.a,{to:{pathname:"/password-reset/request"},children:t("user:Forgot password?")})})]}):Object(i.jsxs)("div",{className:"card",children:[Object(i.jsx)("div",{className:"card-body",children:"Registration is disabled."}),Object(i.jsx)("div",{className:"card-body",children:Object(i.jsx)("button",{type:"submit",className:"btn btn-secondary btn-lg btn-block",onClick:function(){return Hi.go(-1)},children:"Back"})})]})]}),Object(i.jsx)("div",{className:"col-md-3"})]})})]})}var di=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={formData:{username:"",email:"",password:"",password_conf:""}},s}return Object(O.a)(a,[{key:"componentDidUpdate",value:function(e){e.location.pathname!==this.props.location.pathname&&this.emptyForm()}},{key:"emptyForm",value:function(){var e=this.state.formData;Object.keys(e).map((function(t){return e[t]=""})),this.setState(e)}},{key:"onHandleFormChange",value:function(e){var t=this.state.formData;t[e.target.name]=e.target.value,this.setState(t)}},{key:"render",value:function(){var e=this,t=this.props,a=t.formType,s=t.isRegistrationAllowed,n=t.message,c=t.messages,r=t.onHandleUserFormSubmit,o=t.t,l=this.state.formData,d=this.props.location.query.token;return Object(i.jsx)("div",{children:z()||"password reset"===a&&!d?Object(i.jsx)(N.a,{to:"/"}):Object(i.jsxs)("div",{children:[Object(i.jsx)(_,{message:n,messages:c,t:o}),Object(i.jsx)(li,{isRegistrationAllowed:s,formType:a,userForm:l,onHandleFormChange:function(t){return e.onHandleFormChange(t)},handleUserFormSubmit:function(e){e.preventDefault(),"password reset"===a&&(l.token=d),r(l,a)}})]})})}}]),a}(c.a.Component),ui=Object(k.a)()(Object(y.c)((function(e){return{isRegistrationAllowed:e.application.config.is_registration_enabled,location:e.router.location,message:e.message,messages:e.messages}}),(function(e){return{onHandleUserFormSubmit:function(t,a){e(Ce(t,a="password reset"===a?"password/update":"reset your password"===a?"password/reset-request":a))}}}))(di)),mi=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e,i){var s;return Object(f.a)(this,a),(s=t.call(this,e,i)).state={displayModal:!1},s}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadUser(this.props.match.params.userName)}},{key:"componentDidUpdate",value:function(e){e.match.params.userName!==this.props.match.params.userName&&this.props.loadUser(this.props.match.params.userName)}},{key:"displayModal",value:function(e){this.setState((function(t){return Object(S.a)(Object(S.a)({},t),{},{displayModal:e})}))}},{key:"render",value:function(){var e=this,t=this.props,a=t.t,s=t.currentUser,n=t.onDeleteUser,c=t.users,r=this.state.displayModal,o=Object(pe.a)(c,1)[0],l=!!o&&s.username===o.username;return Object(i.jsxs)("div",{children:[r&&Object(i.jsx)(ct,{title:a("common:Confirmation"),text:a("user:Are you sure you want to delete this account? All data will be deleted, this cannot be undone."),confirm:function(){n(o.username),e.displayModal(!1)},close:function(){return e.displayModal(!1)}}),o&&Object(i.jsx)(ft,{editable:l,isDeletable:s.admin&&!l,onDeleteUser:n,displayModal:function(t){return e.displayModal(t)},t:a,user:o})]})}}]),a}(c.a.Component),ji=Object(k.a)()(Object(y.c)((function(e){return{currentUser:e.user,users:e.users.data}}),(function(e){return{onDeleteUser:function(t){e(Ee(t,!0))},loadUser:function(t){e(K("getData","users",{username:t}))}}}))(mi)),pi=function(e){Object(x.a)(a,e);var t=Object(g.a)(a);function a(e){var i;return Object(f.a)(this,a),(i=t.call(this,e)).props=e,i}return Object(O.a)(a,[{key:"componentDidMount",value:function(){this.props.loadAppConfig()}},{key:"render",value:function(){return Object(i.jsxs)("div",{className:"App",children:[Object(i.jsx)(Pa,{}),Object(i.jsxs)(N.d,{children:[Object(i.jsx)(N.b,{exact:!0,path:"/",component:ta}),Object(i.jsx)(N.b,{exact:!0,path:"/register",render:function(){return Object(i.jsx)(ui,{formType:"register"})}}),Object(i.jsx)(N.b,{exact:!0,path:"/login",render:function(){return Object(i.jsx)(ui,{formType:"login"})}}),Object(i.jsx)(N.b,{exact:!0,path:"/password-reset",render:function(){return Object(i.jsx)(ui,{formType:"password reset"})}}),Object(i.jsx)(N.b,{exact:!0,path:"/password-reset/request",render:function(){return Object(i.jsx)(ui,{formType:"reset your password"})}}),Object(i.jsx)(N.b,{exact:!0,path:"/password-reset/sent",render:function(){return Object(i.jsx)($a,{action:"sent"})}}),Object(i.jsx)(N.b,{exact:!0,path:"/updated-password",render:function(){return Object(i.jsx)($a,{action:"updated"})}}),Object(i.jsx)(N.b,{exact:!0,path:"/password-reset/sent",component:$a}),Object(i.jsx)(N.b,{exact:!0,path:"/logout",component:sa}),Object(i.jsx)(N.b,{exact:!0,path:"/profile/edit",component:ti}),Object(i.jsx)(N.b,{exact:!0,path:"/profile",component:Ot}),Object(i.jsx)(N.b,{exact:!0,path:"/workouts/history",component:vt}),Object(i.jsx)(N.b,{exact:!0,path:"/workouts/statistics",component:oi}),Object(i.jsx)(N.b,{exact:!0,path:"/users/:userName",component:ji}),Object(i.jsx)(N.b,{path:"/workouts",component:ut}),Object(i.jsx)(N.b,{path:"/admin",component:me}),Object(i.jsx)(N.b,{component:ue})]}),Object(i.jsx)(aa,{})]})}}]),a}(c.a.Component),hi=Object(y.c)((function(){return{}}),(function(e){return{loadAppConfig:function(){e(Z("config"))}}}))(pi),bi=a(78);function vi(e){var t=e.store,a=e.history,s=e.children;return Object(i.jsx)(y.a,{store:t,children:Object(i.jsx)(bi.a,{history:a,children:s})})}var fi=Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));function Oi(e){navigator.serviceWorker.register(e).then((function(e){e.onupdatefound=function(){var t=e.installing;t.onstatechange=function(){"installed"===t.state&&(navigator.serviceWorker.controller?console.log("New content is available; please refresh."):console.log("Content is cached for offline use."))}}})).catch((function(e){console.error("Error during service worker registration:",e)}))}var xi,gi={data:[]},yi={language:"en",message:"",messages:[],user:{isAuthenticated:!1},activities:Object(S.a)({},gi),application:{statistics:{},config:{gpx_limit_import:null,is_registration_enabled:null,max_single_file_size:null,max_users:null,max_zip_file_size:null,registration:null}},calendarActivities:Object(S.a)({},gi),chartData:[],gpx:null,loading:!1,records:Object(S.a)({},gi),sports:Object(S.a)({},gi),statistics:{data:{}},users:Object(S.a)({},gi)},Ni=function(e,t,a){return a.target!==t?e:"SET_DATA"===a.type?Object(S.a)(Object(S.a)({},e),{},{data:a.data[a.target]}):"SET_PAGINATED_DATA"===a.type?Object(S.a)(Object(S.a)({},e),{},{data:a.data[a.target],pagination:a.pagination}):e},wi=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.activities,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"LOGOUT":return yi.activities;case"PUSH_ACTIVITIES":return Object(S.a)(Object(S.a)({},e),{},{data:e.data.concat(t.activities)});case"REMOVE_ACTIVITY":return Object(S.a)(Object(S.a)({},e),{},{data:e.data.filter((function(e){return e.id!==t.activityId}))});default:return Ni(e,"activities",t)}},ki=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.application,t=arguments.length>1?arguments[1]:void 0;return"SET_APP_CONFIG"===t.type?Object(S.a)(Object(S.a)({},e),{},{config:t.data}):"SET_APP_STATS"===t.type?Object(S.a)(Object(S.a)({},e),{},{statistics:t.data}):e},_i=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.calendarActivities,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"LOGOUT":return yi.calendarActivities;case"UPDATE_CALENDAR":return Object(S.a)(Object(S.a)({},e),{},{data:t.activities});default:return Ni(e,"calendarActivities",t)}},Si=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.chartData,t=arguments.length>1?arguments[1]:void 0;return"SET_CHART_DATA"===t.type?t.chartData:e},Di=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.gpx,t=arguments.length>1?arguments[1]:void 0;return"SET_GPX"===t.type?t.gpxContent:e},Ai=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.language,t=arguments.length>1?arguments[1]:void 0;return"SET_LANGUAGE"===t.type?t.language:e},Ci=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.loading,t=arguments.length>1?arguments[1]:void 0;return"SET_LOADING"===t.type?t.loading:e},Ei=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.message,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"AUTH_ERROR":case"PROFILE_ERROR":case"PROFILE_UPDATE_ERROR":case"PICTURE_ERROR":case"SET_ERROR":return t.message;case"LOGOUT":case"PROFILE_SUCCESS":case"SET_RESULTS":case"@@router/LOCATION_CHANGE":return"";default:return e}},Mi=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.messages,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"AUTH_ERRORS":return t.messages;case"LOGOUT":case"PROFILE_SUCCESS":case"@@router/LOCATION_CHANGE":return[];default:return e}},Ti=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.records,t=arguments.length>1?arguments[1]:void 0;return"LOGOUT"===t.type?yi.records:Ni(e,"records",t)},Pi=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.sports,t=arguments.length>1?arguments[1]:void 0;return"UPDATE_SPORT_DATA"===t.type?Object(S.a)(Object(S.a)({},e),{},{data:e.data.map((function(e){return e.id===t.data.id&&(e.is_active=t.data.is_active),e}))}):Ni(e,"sports",t)},Fi=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.users,t=arguments.length>1?arguments[1]:void 0;return"UPDATE_USER_DATA"===t.type?Object(S.a)(Object(S.a)({},e),{},{data:e.data.map((function(e){return e.username===t.data.username&&(e.admin=t.data.admin),e}))}):Ni(e,"users",t)},zi=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.user,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"AUTH_ERROR":case"PROFILE_ERROR":case"LOGOUT":return window.localStorage.removeItem("authToken"),yi.user;case"PROFILE_SUCCESS":return t.profil;default:return e}},Ri=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:yi.statistics,t=arguments.length>1?arguments[1]:void 0;return"LOGOUT"===t.type?yi.statistics:Ni(e,"statistics",t)},Li=["/login","/register","/password-reset","/password-reset/request","/password-reset/sent","/updated-password"],Ii=function(e,t){return"string"===typeof e||e instanceof String?e=t:e.pathname=t,e},Ui=function(e){return window.localStorage.authToken||Li.includes(e.pathname)||(e=Ii(e,"/login")),window.localStorage.authToken&&Li.includes(e.pathname)&&(e=Ii(e,"/")),e},Hi=((xi=Object(s.a)()).location=Ui(xi.location),Object(S.a)(Object(S.a)({},xi),{},{push:function(e){for(var t=arguments.length,a=new Array(t>1?t-1:0),i=1;i1?t-1:0),i=1;i 1\n ? `${t(`messages:${message.split('|')[0]}`)}: ${t(\n `messages:${message.split('|')[1]}`\n )}`\n : t(`messages:${message}`)\n return (\n
\n {singleMessage !== '' && {singleMessage}}\n {messages && messages.length > 0 && (\n \n
    \n {messages.map(msg => (\n
  • {t(`messages:${msg.value}`)}
  • \n ))}\n
\n
\n )}\n
\n )\n }\n}\n","import { format, parse } from 'date-fns'\nimport { DateTime } from 'luxon'\n\nconst suffixes = ['bytes', 'KB', 'MB', 'GB', 'TB']\nexport const getFileSize = (fileSize, asText = true) => {\n const i = Math.floor(Math.log(fileSize) / Math.log(1024))\n if (!fileSize) {\n return asText ? '0 bytes' : { size: 0, suffix: 'bytes' }\n }\n const size = (fileSize / Math.pow(1024, i)).toFixed(1)\n const suffix = suffixes[i]\n return asText ? `${size}${suffix}` : { size, suffix }\n}\n\nexport const getFileSizeInMB = fileSize => {\n const value = fileSize / 1048576\n return (!fileSize && 0) || +value.toFixed(2)\n}\n\nexport const version = '0.4.2' // version stored in 'utils' for now\nexport const apiUrl =\n process.env.NODE_ENV === 'production'\n ? '/api/'\n : `${process.env.REACT_APP_API_URL}/api/`\n\nexport const userFilters = [\n { key: 'activities_count', label: 'activities count' },\n { key: 'admin', label: 'admin rights' },\n { key: 'created_at', label: 'registration date' },\n { key: 'username', label: 'user name' },\n]\n\nexport const sortOrders = [\n { key: 'asc', label: 'ascending' },\n { key: 'desc', label: 'descending' },\n]\n\nexport const isLoggedIn = () => !!window.localStorage.authToken\n\nexport const generateIds = arr => {\n let i = 0\n return arr.map(val => {\n const obj = { id: i, value: val }\n i++\n return obj\n })\n}\n\nexport const createApiRequest = params => {\n const headers = {}\n if (!params.noAuthorization) {\n headers.Authorization = `Bearer ${window.localStorage.getItem('authToken')}`\n }\n if (params.type) {\n headers['Content-Type'] = params.type\n }\n const requestParams = {\n method: params.method,\n headers: headers,\n }\n if (params.type === 'application/json' && params.body) {\n requestParams.body = JSON.stringify(params.body)\n } else if (params.body) {\n requestParams.body = params.body\n }\n const request = new Request(`${apiUrl}${params.url}`, requestParams)\n return fetch(request)\n .then(response =>\n params.method === 'DELETE' || response.status === 413\n ? response\n : response.json()\n )\n .catch(error => {\n console.error(error)\n return new Error('An error occurred. Please contact the administrator.')\n })\n}\n\nexport const getDateWithTZ = (date, tz) => {\n if (!date) {\n return ''\n }\n const dt = DateTime.fromISO(\n format(new Date(date), \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\")\n ).setZone(tz)\n return parse(\n dt.toFormat('yyyy-MM-dd HH:mm:ss'),\n 'yyyy-MM-dd HH:mm:ss',\n new Date()\n )\n}\n\nexport const capitalize = target =>\n target.charAt(0).toUpperCase() + target.slice(1)\n\nexport const rangePagination = pages =>\n Array.from({ length: pages }, (_, i) => i + 1)\n\nconst sortValues = (a, b) => {\n const valueALabel = a.label.toLowerCase()\n const valueBLabel = b.label.toLowerCase()\n return valueALabel > valueBLabel ? 1 : valueALabel < valueBLabel ? -1 : 0\n}\n\nexport const translateValues = (t, values, key = 'common') =>\n values\n .map(value => ({\n ...value,\n label: t(`${key}:${value.label}`),\n }))\n .sort(sortValues)\n\nexport const formatUrl = (pathname, query) => {\n let url = pathname\n if (query.id || (pathname === 'users' && query.username)) {\n url = `${url}/${query.username ? query.username : query.id}`\n } else if (Object.keys(query).length > 0) {\n url += '?'\n Object.keys(query)\n .filter(key => query[key])\n .map(\n (key, index) => (url += `${index === 0 ? '' : '&'}${key}=${query[key]}`)\n )\n }\n return url\n}\n","import { createApiRequest, formatUrl } from '../utils'\n\nexport default class FitTrackeeApi {\n static getData(target, data = {}) {\n const url = formatUrl(target, data)\n const params = {\n url: url,\n method: 'GET',\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static addData(target, data) {\n const params = {\n url: target,\n method: 'POST',\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static addDataWithFile(target, data) {\n const params = {\n url: target,\n method: 'POST',\n body: data,\n }\n return createApiRequest(params)\n }\n\n static postData(target, data) {\n const params = {\n url: `${target}${data.id ? `/${data.id}` : ''}`,\n method: 'POST',\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static updateData(target, data) {\n const params = {\n url: `${target}${\n data.id ? `/${data.id}` : data.username ? `/${data.username}` : ''\n }`,\n method: 'PATCH',\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static deleteData(target, id) {\n const params = {\n url: `${target}/${id}`,\n method: 'DELETE',\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n}\n","import i18next from 'i18next'\n\nimport FitTrackeeApi from '../fitTrackeeApi/index'\nimport { history } from '../index'\n\nexport const setData = (target, data) => ({\n type: 'SET_DATA',\n data,\n target,\n})\nexport const setPaginatedData = (target, data, pagination) => ({\n type: 'SET_PAGINATED_DATA',\n data,\n pagination,\n target,\n})\n\nexport const setError = message => ({\n type: 'SET_ERROR',\n message,\n})\n\nexport const setLanguage = language => ({\n type: 'SET_LANGUAGE',\n language,\n})\n\nexport const setLoading = loading => ({\n type: 'SET_LOADING',\n loading,\n})\n\nexport const updateSportsData = data => ({\n type: 'UPDATE_SPORT_DATA',\n data,\n})\n\nexport const updateUsersData = data => ({\n type: 'UPDATE_USER_DATA',\n data,\n})\n\nexport const getOrUpdateData = (\n action,\n target,\n data,\n canDispatch = true\n) => dispatch => {\n dispatch(setLoading(true))\n if (data && data.id && target !== 'activities' && isNaN(data.id)) {\n dispatch(setLoading(false))\n return dispatch(setError(`${target}|Incorrect id`))\n }\n dispatch(setError(''))\n return FitTrackeeApi[action](target, data)\n .then(ret => {\n if (ret.status === 'success') {\n if (canDispatch) {\n if (target === 'users' && action === 'getData') {\n return dispatch(setPaginatedData(target, ret.data, ret.pagination))\n }\n dispatch(setData(target, ret.data))\n } else if (action === 'updateData' && target === 'sports') {\n dispatch(updateSportsData(ret.data.sports[0]))\n } else if (action === 'updateData' && target === 'users') {\n dispatch(updateUsersData(ret.data.users[0]))\n }\n } else {\n dispatch(setError(`${target}|${ret.message || ret.status}`))\n }\n dispatch(setLoading(false))\n })\n .catch(error => {\n dispatch(setLoading(false))\n dispatch(setError(`${target}|${error}`))\n })\n}\n\nexport const addData = (target, data) => dispatch =>\n FitTrackeeApi.addData(target, data)\n .then(ret => {\n if (ret.status === 'created') {\n history.push(`/admin/${target}`)\n } else {\n dispatch(setError(`${target}|${ret.status}`))\n }\n })\n .catch(error => dispatch(setError(`${target}|${error}`)))\n\nexport const deleteData = (target, id) => dispatch => {\n if (isNaN(id)) {\n return dispatch(setError(target, `${target}|Incorrect id`))\n }\n return FitTrackeeApi.deleteData(target, id)\n .then(ret => {\n if (ret.status === 204) {\n history.push(`/admin/${target}`)\n } else {\n dispatch(setError(`${target}|${ret.message || ret.status}`))\n }\n })\n .catch(error => dispatch(setError(`${target}|${error}`)))\n}\n\nexport const updateLanguage = language => dispatch => {\n i18next.changeLanguage(language).then(dispatch(setLanguage(language)))\n}\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport { setError } from './index'\n\nexport const setAppConfig = data => ({\n type: 'SET_APP_CONFIG',\n data,\n})\n\nexport const setAppStats = data => ({\n type: 'SET_APP_STATS',\n data,\n})\n\nexport const getAppData = target => dispatch =>\n FitTrackeeGenericApi.getData(target)\n .then(ret => {\n if (ret.status === 'success') {\n if (target === 'config') {\n dispatch(setAppConfig(ret.data))\n } else if (target === 'stats/all') {\n dispatch(setAppStats(ret.data))\n }\n } else {\n dispatch(setError(`application|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`application|${error}`)))\n\nexport const updateAppConfig = formData => dispatch =>\n FitTrackeeGenericApi.updateData('config', formData)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setAppConfig(ret.data))\n } else {\n dispatch(setError(`application|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`application|${error}`)))\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport { updateAppConfig } from '../../actions/application'\nimport { history } from '../../index'\nimport { getFileSizeInMB } from '../../utils'\n\nclass AdminApplication extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n formData: {},\n isInEdition: false,\n }\n }\n\n componentDidMount() {\n this.initForm()\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.appConfig !== prevProps.appConfig) {\n this.initForm()\n }\n }\n\n initForm() {\n const { appConfig } = this.props\n const formData = {}\n Object.keys(appConfig).map(k =>\n appConfig[k] === null\n ? (formData[k] = '')\n : ['max_single_file_size', 'max_zip_file_size'].includes(k)\n ? (formData[k] = getFileSizeInMB(appConfig[k]))\n : (formData[k] = appConfig[k])\n )\n this.setState({ formData })\n }\n\n handleFormChange(e) {\n const { formData } = this.state\n formData[e.target.name] = +e.target.value\n this.setState(formData)\n }\n\n toggleInEdition(e) {\n e.preventDefault()\n const { isInEdition } = this.state\n this.setState({ isInEdition: !isInEdition })\n }\n\n render() {\n const { message, onHandleConfigFormSubmit, t } = this.props\n const { formData, isInEdition } = this.state\n return (\n
\n {message && }\n {Object.keys(formData).length > 0 && (\n
\n
\n
\n
\n \n {t('administration:Application configuration')}\n \n
\n
\n {\n this.toggleInEdition(e)\n onHandleConfigFormSubmit(formData)\n }}\n >\n
\n \n {t(\n // eslint-disable-next-line max-len\n 'administration:Max. number of active users'\n )}\n \n \n \n :\n \n this.handleFormChange(e)}\n />\n
\n
\n \n {t(\n 'administration:Max. size of uploaded files (in Mb)'\n )}\n :\n \n this.handleFormChange(e)}\n />\n
\n
\n \n {t('administration:Max. size of zip archive (in Mb)')}:\n \n this.handleFormChange(e)}\n />\n
\n
\n \n {t('administration:Max. files of zip archive')}\n \n this.handleFormChange(e)}\n />\n
\n {isInEdition ? (\n <>\n \n this.toggleInEdition(e)}\n value={t('common:Cancel')}\n />\n \n ) : (\n <>\n {\n this.toggleInEdition(e)\n }}\n value={t('common:Edit')}\n />\n history.push('/admin')}\n value={t('common:Back')}\n />\n \n )}\n \n
\n
\n
\n
\n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n message: state.message,\n }),\n dispatch => ({\n onHandleConfigFormSubmit: formData => {\n const data = Object.assign({}, formData)\n data.max_single_file_size *= 1048576\n data.max_zip_file_size *= 1048576\n dispatch(updateAppConfig(data))\n },\n })\n)(AdminApplication)\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport { getAppData } from '../../actions/application'\nimport { getFileSize } from '../../utils'\n\nclass AdminStats extends React.Component {\n componentDidMount() {\n this.props.loadAppStats()\n }\n\n render() {\n const { appStats, t } = this.props\n const uploadDirSize = getFileSize(appStats.uploads_dir_size, false)\n return (\n
\n
\n
\n
\n
\n \n
\n
\n
\n {appStats.users ? appStats.users : 0}\n
\n
{`${\n appStats.users === 1\n ? t('administration:user')\n : t('administration:users')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n {appStats.sports ? appStats.sports : 0}\n
\n
{`${\n appStats.sports === 1 ? t('common:sport') : t('common:sports')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n {appStats.activities ? appStats.activities : 0}\n
\n
{`${\n appStats.activities === 1\n ? t('common:workout')\n : t('common:workouts')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
{uploadDirSize.size}
\n
\n {uploadDirSize.suffix} ({t('administration:uploads')})\n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n appStats: state.application.statistics,\n }),\n dispatch => ({\n loadAppStats: () => {\n dispatch(getAppData('stats/all'))\n },\n })\n )(AdminStats)\n)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport AdminStats from './AdminStats'\n\nexport default function AdminDashboard(props) {\n const { appConfig, t } = props\n return (\n
\n
\n {t('administration:Administration')}\n
\n
\n \n
\n
\n
\n \n {t('administration:Application')}\n \n
\n
\n {t(\n 'administration:Update application configuration ' +\n '(maximum number of registered users, maximum files size).'\n )}\n
\n \n {t(\n `administration:Registration is currently ${\n appConfig.is_registration_enabled ? 'enabled' : 'disabled'\n }.`\n )}\n \n
\n
\n
\n \n {t('administration:Sports')}\n \n
\n
{t('administration:Enable/disable sports.')}
\n
\n
\n \n {t('administration:Users')}\n \n
\n
\n {t(\n 'administration:Add/remove admin rights, ' +\n 'delete user account.'\n )}\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport { getOrUpdateData } from '../../actions'\nimport { history } from '../../index'\n\nclass AdminSports extends React.Component {\n componentDidMount() {\n this.props.loadSports()\n }\n\n render() {\n const { message, sports, t, updateSport } = this.props\n return (\n
\n {message && }\n
\n
\n
\n
\n {t('administration:Sports')}\n
\n
\n {sports.length > 0 && (\n \n \n \n \n \n \n \n \n \n \n \n {sports.map(sport => (\n \n \n \n \n \n \n \n ))}\n \n
{t('administration:id')}{t('administration:Image')}{t('administration:Label')}{t('administration:Active')}{t('administration:Actions')}
\n \n {t('administration:id')}\n \n {sport.id}\n \n \n {t('administration:Image')}\n \n \n \n \n {t('administration:Label')}\n \n {t(`sports:${sport.label}`)}\n \n \n {t('administration:Active')}\n \n {sport.is_active ? (\n \n ) : (\n \n )}\n \n \n {t('administration:Actions')}\n \n \n updateSport(sport.id, !sport.is_active)\n }\n />\n {sport.has_activities && (\n \n \n {t('administration:activities exist')}\n \n )}\n
\n )}\n history.push('/admin/')}\n value={t('common:Back')}\n />\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadSports: () => {\n dispatch(getOrUpdateData('getData', 'sports'))\n },\n updateSport: (sportId, isActive) => {\n const data = { id: sportId, is_active: isActive }\n dispatch(getOrUpdateData('updateData', 'sports', data, false))\n },\n })\n)(AdminSports)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { formatUrl, rangePagination } from '../../utils'\n\nexport default class Pagination extends React.PureComponent {\n getUrl(value) {\n const { query, pathname } = this.props\n const newQuery = Object.assign({}, query)\n let page = query.page ? +query.page : 1\n switch (value) {\n case 'prev':\n page -= 1\n break\n case 'next':\n page += 1\n break\n default:\n page = +value\n }\n newQuery.page = page\n return formatUrl(pathname, newQuery)\n }\n\n render() {\n const { pagination, t } = this.props\n return (\n <>\n {pagination && Object.keys(pagination).length > 0 && (\n \n )}\n \n )\n }\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { connect } from 'react-redux'\nimport { Link } from 'react-router-dom'\n\nimport Message from '../Common/Message'\nimport Pagination from '../Common/Pagination'\nimport { history } from '../../index'\nimport { getOrUpdateData } from '../../actions'\nimport {\n apiUrl,\n formatUrl,\n sortOrders,\n translateValues,\n userFilters,\n} from '../../utils'\n\nclass AdminUsers extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n page: null,\n per_page: null,\n order_by: 'created_at',\n order: 'asc',\n }\n }\n\n componentDidMount() {\n this.props.loadUsers(this.initState())\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.location.query !== this.props.location.query) {\n this.props.loadUsers(this.props.location.query)\n }\n }\n\n initState() {\n const { query } = this.props.location\n const newQuery = {\n page: query.page,\n per_page: query.per_page,\n order_by: query.order_by ? query.order_by : 'created_at',\n order: query.order ? query.order : 'asc',\n }\n this.setState(newQuery)\n return newQuery\n }\n\n updatePage(key, value) {\n const query = Object.assign({}, this.state)\n query[key] = value\n this.setState(query)\n const url = formatUrl(this.props.location.pathname, query)\n history.push(url)\n }\n\n render() {\n const {\n authUser,\n location,\n message,\n t,\n pagination,\n updateUser,\n users,\n } = this.props\n const translatedFilters = translateValues(t, userFilters)\n const translatedSortOrders = translateValues(t, sortOrders)\n return (\n
\n {message && }\n
\n
\n
\n
\n
\n {t('administration:Users')}\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n {users.map(user => (\n \n \n \n \n \n \n \n \n \n ))}\n \n
#{t('user:Username')}{t('user:Email')}{t('user:Registration Date')}{t('activities:Activities')}{t('user:Admin')}{t('administration:Actions')}
\n #\n {user.picture === true ? (\n \n ) : (\n \n )}\n \n \n {t('user:Username')}\n \n \n {user.username}\n \n \n \n {t('user:Email')}\n \n {user.email}\n \n \n {t('user:Registration Date')}\n \n {format(\n new Date(user.created_at),\n 'dd/MM/yyyy HH:mm'\n )}\n \n \n {t('activities:Activities')}\n \n {user.nb_activities}\n \n \n {t('user:Admin')}\n \n {user.admin ? (\n \n ) : (\n \n )}\n \n \n {t('administration:Actions')}\n \n \n updateUser(user.username, !user.admin)\n }\n />\n
\n \n history.push('/admin/')}\n value={t('common:Back')}\n />\n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n authUser: state.user,\n location: state.router.location,\n message: state.message,\n pagination: state.users.pagination,\n users: state.users.data,\n }),\n dispatch => ({\n loadUsers: query => {\n dispatch(getOrUpdateData('getData', 'users', query))\n },\n updateUser: (userName, isAdmin) => {\n const data = { username: userName, admin: isAdmin }\n dispatch(getOrUpdateData('updateData', 'users', data, false))\n },\n })\n)(AdminUsers)\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { useTranslation } from 'react-i18next'\n\nexport default function NotFound() {\n const { t } = useTranslation()\n return (\n
\n \n fittrackee - 404\n \n

{t('Page not found')}

\n
\n )\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport { Route, Switch } from 'react-router-dom'\n\nimport AdminApplication from './AdminApplication'\nimport AdminDashboard from './AdminDashboard'\nimport AdminSports from './AdminSports'\nimport AdminUsers from './AdminUsers'\nimport NotFound from './../Others/NotFound'\n\nfunction Admin(props) {\n const { appConfig, t, user } = props\n return (\n <>\n \n FitTrackee - {t('administration:Administration')}\n \n
\n {user.admin ? (\n \n }\n />\n }\n />\n }\n />\n }\n />\n \n \n ) : (\n \n )}\n
\n \n )\n}\n\nexport default withTranslation()(\n connect(state => ({\n appConfig: state.application.config,\n user: state.user,\n }))(Admin)\n)\n","import { format, subHours } from 'date-fns'\nimport togeojson from '@mapbox/togeojson'\n\nimport { getDateWithTZ } from './index'\n\nexport const activityColors = [\n '#55a8a3',\n '#98C3A9',\n '#D0838A',\n '#ECC77E',\n '#926692',\n '#929292',\n '#428bca',\n]\n\nexport const recordsLabels = [\n { record_type: 'AS', label: 'Ave. speed' },\n { record_type: 'FD', label: 'Farest distance' },\n { record_type: 'LD', label: 'Longest duration' },\n { record_type: 'MS', label: 'Max. speed' },\n]\n\nexport const getGeoJson = gpxContent => {\n let jsonData\n if (gpxContent) {\n const gpx = new DOMParser().parseFromString(gpxContent, 'text/xml')\n jsonData = togeojson.gpx(gpx)\n }\n return { jsonData }\n}\n\nexport const formatActivityDate = (\n dateTime,\n dateFormat = null,\n timeFormat = null\n) => {\n if (!dateFormat) {\n dateFormat = 'yyyy/MM/dd'\n }\n if (!timeFormat) {\n timeFormat = 'HH:mm'\n }\n return {\n activity_date: dateTime ? format(dateTime, dateFormat) : null,\n activity_time: dateTime ? format(dateTime, timeFormat) : null,\n }\n}\n\nexport const formatActivityDuration = seconds => {\n let newDate = new Date(0)\n newDate = subHours(newDate.setSeconds(seconds), 1)\n return newDate.getTime()\n}\n\nexport const formatChartData = chartData => {\n for (let i = 0; i < chartData.length; i++) {\n chartData[i].time = new Date(chartData[i].time).getTime()\n chartData[i].duration = formatActivityDuration(chartData[i].duration)\n }\n return chartData\n}\n\nexport const formatRecord = (record, tz) => {\n let value\n switch (record.record_type) {\n case 'AS':\n case 'MS':\n value = `${record.value} km/h`\n break\n case 'FD':\n value = `${record.value} km`\n break\n default:\n // 'LD'\n value = record.value // eslint-disable-line prefer-destructuring\n }\n const [recordType] = recordsLabels.filter(\n r => r.record_type === record.record_type\n )\n return {\n activity_date: formatActivityDate(getDateWithTZ(record.activity_date, tz))\n .activity_date,\n activity_id: record.activity_id,\n id: record.id,\n record_type: recordType.label,\n value: value,\n }\n}\n\nconst sortSports = (a, b) => {\n const sportALabel = a.label.toLowerCase()\n const sportBLabel = b.label.toLowerCase()\n return sportALabel > sportBLabel ? 1 : sportALabel < sportBLabel ? -1 : 0\n}\n\nexport const translateSports = (sports, t, onlyActive = false) =>\n sports\n .filter(sport => (onlyActive ? sport.is_active : true))\n .map(sport => ({\n ...sport,\n label: t(`sports:${sport.label}`),\n }))\n .sort(sortSports)\n","import { createApiRequest } from '../utils'\n\nexport default class FitTrackeeApi {\n static loginOrRegisterOrPasswordReset(target, data) {\n const params = {\n url: `auth/${target}`,\n method: 'POST',\n noAuthorization: true,\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static deletePicture() {\n const params = {\n url: 'auth/picture',\n method: 'DELETE',\n }\n return createApiRequest(params)\n }\n}\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport FitTrackeeApi from '../fitTrackeeApi/auth'\nimport { history } from '../index'\nimport { generateIds } from '../utils'\nimport { getOrUpdateData, setError, updateLanguage } from './index'\nimport { getAppData } from './application'\n\nconst AuthError = message => ({ type: 'AUTH_ERROR', message })\n\nconst AuthErrors = messages => ({ type: 'AUTH_ERRORS', messages })\n\nconst PictureError = message => ({ type: 'PICTURE_ERROR', message })\n\nconst ProfileSuccess = profil => ({ type: 'PROFILE_SUCCESS', profil })\n\nconst ProfileError = message => ({ type: 'PROFILE_ERROR', message })\n\nconst ProfileUpdateError = message => ({\n type: 'PROFILE_UPDATE_ERROR',\n message,\n})\n\nexport const logout = () => ({ type: 'LOGOUT' })\n\nexport const loadProfile = () => dispatch => {\n if (window.localStorage.getItem('authToken')) {\n return dispatch(getProfile())\n }\n return { type: 'LOGOUT' }\n}\n\nexport const getProfile = () => dispatch =>\n FitTrackeeGenericApi.getData('auth/profile')\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(getOrUpdateData('getData', 'sports'))\n ret.data.isAuthenticated = true\n if (ret.data.language) {\n dispatch(updateLanguage(ret.data.language))\n }\n return dispatch(ProfileSuccess(ret.data))\n }\n return dispatch(ProfileError(ret.message))\n })\n .catch(error => {\n throw error\n })\n\nexport const loginOrRegisterOrPasswordReset = (target, formData) => dispatch =>\n FitTrackeeApi.loginOrRegisterOrPasswordReset(target, formData)\n .then(ret => {\n if (ret.status === 'success') {\n if (target === 'password/reset-request') {\n return history.push({\n pathname: '/password-reset/sent',\n })\n }\n if (target === 'password/update') {\n return history.push({\n pathname: '/updated-password',\n })\n }\n if (target === 'login' || target === 'register') {\n window.localStorage.setItem('authToken', ret.auth_token)\n if (target === 'register') {\n dispatch(getAppData('config'))\n }\n return dispatch(getProfile())\n }\n }\n return dispatch(AuthError(ret.message))\n })\n .catch(error => {\n throw error\n })\n\nconst RegisterFormControl = (formData, onlyPasswords = false) => {\n const errMsg = []\n if (\n !onlyPasswords &&\n (formData.username.length < 3 || formData.username.length > 12)\n ) {\n errMsg.push('3 to 12 characters required for username.')\n }\n if (formData.password !== formData.password_conf) {\n errMsg.push(\"Password and password confirmation don't match.\")\n }\n if (formData.password.length < 8) {\n errMsg.push('8 characters required for password.')\n }\n return errMsg\n}\n\nexport const handleUserFormSubmit = (formData, formType) => dispatch => {\n if (formType === 'register' || formType === 'password/update') {\n const ret = RegisterFormControl(formData, formType === 'password/update')\n if (ret.length > 0) {\n return dispatch(AuthErrors(generateIds(ret)))\n }\n }\n return dispatch(loginOrRegisterOrPasswordReset(formType, formData))\n}\n\nexport const handleProfileFormSubmit = formData => dispatch => {\n if (!formData.password === formData.password_conf) {\n return dispatch(\n ProfileUpdateError(\"Password and password confirmation don't match.\")\n )\n }\n delete formData.id\n return FitTrackeeGenericApi.postData('auth/profile/edit', formData)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(getProfile())\n return history.push('/profile')\n }\n dispatch(ProfileUpdateError(ret.message))\n })\n .catch(error => {\n throw error\n })\n}\n\nexport const uploadPicture = event => dispatch => {\n event.preventDefault()\n const form = new FormData()\n form.append('file', event.target.picture.files[0])\n event.target.reset()\n return FitTrackeeGenericApi.addDataWithFile('auth/picture', form)\n .then(ret => {\n if (ret.status === 'success') {\n return dispatch(getProfile())\n }\n const msg = ret.message.match(/file size exceeds/g)\n ? 'Error during picture update, file size exceeds max size.'\n : ret.message\n return dispatch(PictureError(msg))\n })\n .catch(error => {\n throw error\n })\n}\n\nexport const deletePicture = () => dispatch =>\n FitTrackeeApi.deletePicture()\n .then(ret => {\n if (ret.status === 204) {\n return dispatch(getProfile())\n }\n return dispatch(PictureError(ret.message))\n })\n .catch(error => {\n throw error\n })\n\nexport const deleteUser = (username, isAdmin = false) => dispatch =>\n FitTrackeeGenericApi.deleteData('users', username)\n .then(ret => {\n if (ret.status === 204) {\n dispatch(getAppData('config'))\n if (isAdmin) {\n history.push('/admin/users')\n } else {\n dispatch(logout())\n history.push('/')\n }\n } else {\n ret.json().then(r => dispatch(setError(`${r.message}`)))\n }\n })\n .catch(error => dispatch(setError(`user|${error}`)))\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport { history } from '../index'\nimport { formatChartData } from '../utils/activities'\nimport { setError, setLoading } from './index'\nimport { loadProfile } from './user'\n\nexport const pushActivities = activities => ({\n type: 'PUSH_ACTIVITIES',\n activities,\n})\n\nexport const removeActivity = activityId => ({\n type: 'REMOVE_ACTIVITY',\n activityId,\n})\n\nexport const updateCalendar = activities => ({\n type: 'UPDATE_CALENDAR',\n activities,\n})\n\nexport const setGpx = gpxContent => ({\n type: 'SET_GPX',\n gpxContent,\n})\n\nexport const setChartData = chartData => ({\n type: 'SET_CHART_DATA',\n chartData,\n})\n\nexport const addActivity = form => dispatch =>\n FitTrackeeGenericApi.addDataWithFile('activities', form)\n .then(ret => {\n if (ret.status === 'created') {\n if (ret.data.activities.length === 0) {\n dispatch(setError('activities|no correct file.'))\n } else if (ret.data.activities.length === 1) {\n dispatch(loadProfile())\n history.push(`/activities/${ret.data.activities[0].id}`)\n } else {\n // ret.data.activities.length > 1\n dispatch(loadProfile())\n history.push('/')\n }\n } else if (ret.status === 413) {\n dispatch(\n setError('activities|File size is greater than the allowed size')\n )\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n dispatch(setLoading(false))\n })\n .catch(error => {\n dispatch(setLoading(false))\n dispatch(setError(`activities|${error}`))\n })\n\nexport const addActivityWithoutGpx = form => dispatch =>\n FitTrackeeGenericApi.addData('activities/no_gpx', form)\n .then(ret => {\n if (ret.status === 'created') {\n dispatch(loadProfile())\n history.push(`/activities/${ret.data.activities[0].id}`)\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n\nexport const getActivityGpx = activityId => dispatch => {\n if (activityId) {\n return FitTrackeeGenericApi.getData(`activities/${activityId}/gpx`)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setGpx(ret.data.gpx))\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n }\n dispatch(setGpx(null))\n}\n\nexport const getSegmentGpx = (activityId, segmentId) => dispatch => {\n if (activityId) {\n return FitTrackeeGenericApi.getData(\n `activities/${activityId}/gpx/segment/${segmentId}`\n )\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setGpx(ret.data.gpx))\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n }\n dispatch(setGpx(null))\n}\n\nexport const getActivityChartData = activityId => dispatch => {\n if (activityId) {\n return FitTrackeeGenericApi.getData(`activities/${activityId}/chart_data`)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setChartData(formatChartData(ret.data.chart_data)))\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n }\n dispatch(setChartData(null))\n}\n\nexport const getSegmentChartData = (activityId, segmentId) => dispatch => {\n if (activityId) {\n return FitTrackeeGenericApi.getData(\n `activities/${activityId}/chart_data/segment/${segmentId}`\n )\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setChartData(formatChartData(ret.data.chart_data)))\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n }\n dispatch(setChartData(null))\n}\n\nexport const deleteActivity = id => dispatch =>\n FitTrackeeGenericApi.deleteData('activities', id)\n .then(ret => {\n if (ret.status === 204) {\n Promise.resolve(dispatch(removeActivity(id)))\n .then(() => dispatch(loadProfile()))\n .then(() => history.push('/'))\n } else {\n dispatch(setError(`activities|${ret.status}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n\nexport const editActivity = form => dispatch =>\n FitTrackeeGenericApi.updateData('activities', form)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(loadProfile())\n history.push(`/activities/${ret.data.activities[0].id}`)\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n dispatch(setLoading(false))\n })\n .catch(error => {\n dispatch(setLoading(false))\n dispatch(setError(`activities|${error}`))\n })\n\nexport const getMoreActivities = params => dispatch =>\n FitTrackeeGenericApi.getData('activities', params)\n .then(ret => {\n if (ret.status === 'success') {\n if (ret.data.activities.length > 0) {\n dispatch(pushActivities(ret.data.activities))\n }\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n\nexport const getMonthActivities = (from, to) => dispatch =>\n FitTrackeeGenericApi.getData('activities', {\n from,\n to,\n order: 'asc',\n per_page: 100,\n })\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(updateCalendar(ret.data.activities))\n } else {\n dispatch(setError(`activities|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`activities|${error}`)))\n","import React from 'react'\nimport { Trans } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport { setLoading } from '../../../actions/index'\nimport { addActivity, editActivity } from '../../../actions/activities'\nimport { history } from '../../../index'\nimport { getFileSize } from '../../../utils'\nimport { translateSports } from '../../../utils/activities'\n\nfunction FormWithGpx(props) {\n const {\n activity,\n appConfig,\n loading,\n onAddActivity,\n onEditActivity,\n sports,\n t,\n } = props\n const sportId = activity ? activity.sport_id : ''\n const translatedSports = translateSports(sports, t, true)\n const zipTooltip = `${t('activities:no folder inside')}, ${\n appConfig.gpx_limit_import\n } ${t('activities:files max')}, ${t('activities:max size')}: ${getFileSize(\n appConfig.max_zip_file_size\n )}`\n const fileSizeLimit = getFileSize(appConfig.max_single_file_size)\n return (\n event.preventDefault()}\n >\n
\n \n
\n {activity ? (\n
\n \n
\n ) : (\n
\n \n
\n )}\n
\n \n
\n {loading ? (\n
\n ) : (\n
\n \n activity ? onEditActivity(event, activity) : onAddActivity(event)\n }\n value={t('common:Submit')}\n />\n history.push('/')}\n value={t('common:Cancel')}\n />\n
\n )}\n \n )\n}\n\nexport default connect(\n state => ({\n appConfig: state.application.config,\n loading: state.loading,\n }),\n dispatch => ({\n onAddActivity: e => {\n dispatch(setLoading(true))\n const form = new FormData()\n form.append('file', e.target.form.gpxFile.files[0])\n /* prettier-ignore */\n form.append(\n 'data',\n `{\"sport_id\": ${e.target.form.sport.value\n }, \"notes\": \"${e.target.form.notes.value}\"}`\n )\n dispatch(addActivity(form))\n },\n onEditActivity: (e, activity) => {\n dispatch(\n editActivity({\n id: activity.id,\n notes: e.target.form.notes.value,\n sport_id: +e.target.form.sport.value,\n title: e.target.form.title.value,\n })\n )\n },\n })\n)(FormWithGpx)\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport {\n addActivityWithoutGpx,\n editActivity,\n} from '../../../actions/activities'\nimport { history } from '../../../index'\nimport { getDateWithTZ } from '../../../utils'\nimport { formatActivityDate, translateSports } from '../../../utils/activities'\n\nfunction FormWithoutGpx(props) {\n const { activity, onAddOrEdit, sports, t, user } = props\n const translatedSports = translateSports(sports, t, true)\n let activityDate,\n activityTime,\n sportId = ''\n if (activity) {\n const activityDateTime = formatActivityDate(\n getDateWithTZ(activity.activity_date, user.timezone),\n 'yyyy-MM-dd'\n )\n activityDate = activityDateTime.activity_date\n activityTime = activityDateTime.activity_time\n sportId = activity.sport_id\n }\n\n return (\n
event.preventDefault()}>\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n onAddOrEdit(event, activity)}\n value={t('common:Submit')}\n />\n history.push('/')}\n value={t('common:Cancel')}\n />\n \n )\n}\n\nexport default connect(\n state => ({\n user: state.user,\n }),\n dispatch => ({\n onAddOrEdit: (e, activity) => {\n const d = e.target.form.duration.value.split(':')\n const duration = +d[0] * 60 * 60 + +d[1] * 60 + +d[2]\n\n /* prettier-ignore */\n const activityDate = `${e.target.form.activity_date.value\n } ${ e.target.form.activity_time.value}`\n\n const data = {\n activity_date: activityDate,\n distance: +e.target.form.distance.value,\n duration,\n notes: e.target.form.notes.value,\n sport_id: +e.target.form.sport_id.value,\n title: e.target.form.title.value,\n }\n if (activity) {\n data.id = activity.id\n dispatch(editActivity(data))\n } else {\n dispatch(addActivityWithoutGpx(data))\n }\n },\n })\n)(FormWithoutGpx)\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport FormWithGpx from './ActivityForms/FormWithGpx'\nimport FormWithoutGpx from './ActivityForms/FormWithoutGpx'\nimport Message from '../Common/Message'\n\nclass ActivityAddEdit extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n withGpx: true,\n }\n }\n\n handleRadioChange(changeEvent) {\n this.setState({\n withGpx:\n changeEvent.target.name === 'withGpx'\n ? changeEvent.target.value\n : !changeEvent.target.value,\n })\n }\n\n render() {\n const { activity, loading, message, sports, t } = this.props\n const { withGpx } = this.state\n return (\n
\n \n \n FitTrackee -{' '}\n {activity\n ? t('activities:Edit a workout')\n : t('activities:Add a workout')}\n \n \n
\n
\n \n
\n
\n
\n
\n
\n

\n {activity\n ? t('activities:Edit a workout')\n : t('activities:Add a workout')}\n

\n
\n {activity ? (\n activity.with_gpx ? (\n \n ) : (\n \n )\n ) : (\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n {withGpx ? (\n \n ) : (\n \n )}\n
\n )}\n
\n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(state => ({\n loading: state.loading,\n }))(ActivityAddEdit)\n)\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport ActivityAddOrEdit from './ActivityAddOrEdit'\n\nfunction ActivityAdd(props) {\n const { message, sports } = props\n return (\n
\n \n
\n )\n}\n\nexport default connect(state => ({\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n}))(ActivityAdd)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { getDateWithTZ } from '../../../utils'\nimport { formatActivityDate } from '../../../utils/activities'\n\nexport default function ActivityCardHeader(props) {\n const {\n activity,\n dataType,\n displayModal,\n segmentId,\n sport,\n t,\n title,\n user,\n } = props\n const activityDate = activity\n ? formatActivityDate(getDateWithTZ(activity.activity_date, user.timezone))\n : null\n\n const previousUrl =\n dataType === 'segment' && segmentId !== 1\n ? `/activities/${activity.id}/segment/${segmentId - 1}`\n : dataType === 'activity' && activity.previous_activity\n ? `/activities/${activity.previous_activity}`\n : null\n const nextUrl =\n dataType === 'segment' && segmentId < activity.segments.length\n ? `/activities/${activity.id}/segment/${segmentId + 1}`\n : dataType === 'activity' && activity.next_activity\n ? `/activities/${activity.next_activity}`\n : null\n\n return (\n
\n
\n
\n {previousUrl ? (\n \n \n \n ) : (\n \n )}\n
\n
\n \"sport\n
\n
\n {dataType === 'activity' ? (\n <>\n {title}{' '}\n \n \n \n displayModal(true)}\n title={t('activities:Delete activity')}\n />\n \n ) : (\n <>\n {/* prettier-ignore */}\n \n {title}\n {' '}\n - {t('activities:segment')} {segmentId}\n \n )}\n
\n {activityDate && (\n \n {`${activityDate.activity_date} - ${activityDate.activity_time}`}\n \n )}\n
\n
\n {nextUrl ? (\n \n \n \n ) : (\n \n )}\n
\n
\n
\n )\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { connect } from 'react-redux'\nimport {\n Area,\n ComposedChart,\n Line,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts'\n\nimport {\n getActivityChartData,\n getSegmentChartData,\n} from '../../../actions/activities'\n\nclass ActivityCharts extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayDistance: true,\n dataToHide: [],\n }\n }\n\n componentDidMount() {\n if (this.props.dataType === 'activity') {\n this.props.loadActivityData(this.props.activity.id)\n } else {\n this.props.loadSegmentData(this.props.activity.id, this.props.segmentId)\n }\n }\n\n componentDidUpdate(prevProps) {\n if (\n (this.props.dataType === 'activity' &&\n prevProps.activity.id !== this.props.activity.id) ||\n (this.props.dataType === 'activity' && prevProps.dataType === 'segment')\n ) {\n this.props.loadActivityData(this.props.activity.id)\n }\n if (\n this.props.dataType === 'segment' &&\n prevProps.segmentId !== this.props.segmentId\n ) {\n this.props.loadSegmentData(this.props.activity.id, this.props.segmentId)\n }\n }\n\n componentWillUnmount() {\n this.props.loadActivityData(null)\n }\n\n handleRadioChange(changeEvent) {\n this.setState({\n displayDistance:\n changeEvent.target.name === 'distance'\n ? changeEvent.target.value\n : !changeEvent.target.value,\n })\n }\n\n handleLegendChange(e) {\n const { dataToHide } = this.state\n const name = e.target.name // eslint-disable-line prefer-destructuring\n if (dataToHide.find(d => d === name)) {\n dataToHide.splice(dataToHide.indexOf(name), 1)\n } else {\n dataToHide.push(name)\n }\n this.setState({ dataToHide })\n }\n\n displayData(name) {\n const { dataToHide } = this.state\n return !dataToHide.find(d => d === name)\n }\n\n render() {\n const { chartData, t, updateCoordinates } = this.props\n const { displayDistance } = this.state\n const xInterval = chartData ? parseInt(chartData.length / 10, 10) : 0\n let xDataKey, xScale\n if (displayDistance) {\n xDataKey = 'distance'\n xScale = 'linear'\n } else {\n xDataKey = 'duration'\n xScale = 'time'\n }\n return (\n
\n {chartData && chartData.length > 0 ? (\n
\n
\n \n \n
\n
\n
\n \n \n
\n
\n
\n \n updateCoordinates(e.activePayload)}\n onMouseLeave={() => updateCoordinates(null)}\n >\n \n displayDistance ? value : format(value, 'HH:mm:ss')\n }\n type=\"number\"\n />\n \n \n {this.displayData('elevation') && (\n \n )}\n {this.displayData('speed') && (\n \n )}\n \n displayDistance\n ? `${t('activities:distance')}: ${value} km`\n : `${t('activities:duration')}: ${format(\n value,\n 'HH:mm:ss'\n )}`\n }\n />\n \n \n
\n
\n {t('activities:data from gpx, without any cleaning')}\n
\n
\n ) : (\n t('activities:No data to display')\n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n chartData: state.chartData,\n }),\n dispatch => ({\n loadActivityData: activityId => {\n dispatch(getActivityChartData(activityId))\n },\n loadSegmentData: (activityId, segmentId) => {\n dispatch(getSegmentChartData(activityId, segmentId))\n },\n })\n)(ActivityCharts)\n","import React from 'react'\n\nexport default function ActivityWeather(props) {\n const { activity, t } = props\n return (\n
\n {activity.weather_start && activity.weather_end && (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {t('activities:Start')}\n
\n \n
\n {t('activities:End')}\n
\n \n
\n \n {Number(activity.weather_start.temperature).toFixed(1)}°C{Number(activity.weather_end.temperature).toFixed(1)}°C
\n \n \n {Number(activity.weather_start.humidity * 100).toFixed(1)}%\n {Number(activity.weather_end.humidity * 100).toFixed(1)}%
\n \n {Number(activity.weather_start.wind).toFixed(1)}m/s{Number(activity.weather_end.wind).toFixed(1)}m/s
\n )}\n
\n )\n}\n","import React from 'react'\n\nimport ActivityWeather from './ActivityWeather'\n\nexport default function ActivityDetails(props) {\n const { activity, t } = props\n const withPauses = activity.pauses !== '0:00:00' && activity.pauses !== null\n return (\n
\n

\n \n {t('activities:Duration')}: {activity.moving}\n {activity.records &&\n activity.records.find(r => r.record_type === 'LD') && (\n \n \n \n )}\n {withPauses && (\n \n
({t('activities:pauses')}: {activity.pauses},{' '}\n {t('activities:total duration')}: {activity.duration})\n
\n )}\n

\n

\n \n {t('activities:Distance')}: {activity.distance} km\n {activity.records &&\n activity.records.find(r => r.record_type === 'FD') && (\n \n \n \n )}\n

\n

\n \n {t('activities:Average speed')}: {activity.ave_speed} km/h\n {activity.records &&\n activity.records.find(r => r.record_type === 'AS') && (\n \n \n \n )}\n
\n {t('activities:Max. speed')}: {activity.max_speed} km/h\n {activity.records &&\n activity.records.find(r => r.record_type === 'MS') && (\n \n \n \n )}\n

\n {activity.min_alt && activity.max_alt && (\n

\n \n {t('activities:Min. altitude')}: {activity.min_alt}m\n
\n {t('activities:Max. altitude')}: {activity.max_alt}m\n

\n )}\n {activity.ascent && activity.descent && (\n

\n \n {t('activities:Ascent')}: {activity.ascent}m\n
\n {t('activities:Descent')}: {activity.descent}m\n

\n )}\n \n
\n )\n}\n","import React from 'react'\nimport { GeoJSON, Marker, TileLayer, useMap } from 'react-leaflet'\nimport hash from 'object-hash'\n\nimport { apiUrl } from '../../../utils'\n\nexport default function Map({ bounds, coordinates, jsonData, mapAttribution }) {\n const map = useMap()\n map.fitBounds(bounds)\n return (\n <>\n \n \n {coordinates.latitude && (\n \n )}\n \n )\n}\n","import React from 'react'\nimport { MapContainer } from 'react-leaflet'\nimport { connect } from 'react-redux'\n\nimport Map from './Map'\nimport { getActivityGpx, getSegmentGpx } from '../../../actions/activities'\nimport { getGeoJson } from '../../../utils/activities'\n\nclass ActivityMap extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n zoom: 13,\n }\n }\n\n componentDidMount() {\n if (this.props.dataType === 'activity') {\n this.props.loadActivityGpx(this.props.activity.id)\n } else {\n this.props.loadSegmentGpx(this.props.activity.id, this.props.segmentId)\n }\n }\n\n componentDidUpdate(prevProps) {\n if (\n (this.props.dataType === 'activity' &&\n prevProps.activity.id !== this.props.activity.id) ||\n (this.props.dataType === 'activity' && prevProps.dataType === 'segment')\n ) {\n this.props.loadActivityGpx(this.props.activity.id)\n }\n if (\n this.props.dataType === 'segment' &&\n prevProps.segmentId !== this.props.segmentId\n ) {\n this.props.loadSegmentGpx(this.props.activity.id, this.props.segmentId)\n }\n }\n\n componentWillUnmount() {\n this.props.loadActivityGpx(null)\n }\n\n render() {\n const { activity, coordinates, gpxContent, mapAttribution } = this.props\n const { jsonData } = getGeoJson(gpxContent)\n const bounds = [\n [activity.bounds[0], activity.bounds[1]],\n [activity.bounds[2], activity.bounds[3]],\n ]\n\n return (\n
\n {jsonData && (\n \n \n \n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n gpxContent: state.gpx,\n mapAttribution: state.application.config.map_attribution,\n }),\n dispatch => ({\n loadActivityGpx: activityId => {\n dispatch(getActivityGpx(activityId))\n },\n loadSegmentGpx: (activityId, segmentId) => {\n dispatch(getSegmentGpx(activityId, segmentId))\n },\n })\n)(ActivityMap)\n","import React from 'react'\n\nexport default function ActivityNoMap(props) {\n const { t } = props\n return (\n
{t('activities:No Map')}
\n )\n}\n","import React from 'react'\n\nexport default function ActivityNotes(props) {\n const { notes, t } = props\n return (\n
\n
\n
\n
\n Notes\n
\n {notes ? notes : t('activities:No notes')}\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nexport default function ActivitySegments(props) {\n const { segments, t } = props\n return (\n
\n
\n
\n
\n {t('activities:Segments')}\n
\n
    \n {segments.map((segment, index) => (\n \n \n {t('activities:segment')} {index + 1}\n {' '}\n ({t('activities:distance')}: {segment.distance} km,{' '}\n {t('activities:duration')}: {segment.duration})\n \n ))}\n
\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { useTranslation } from 'react-i18next'\n\nexport default function CustomModal(props) {\n const { t } = useTranslation()\n return (\n
\n
\n
\n
\n
{props.title}
\n props.close()}\n >\n ×\n \n
\n
\n

{props.text}

\n
\n
\n props.confirm()}\n >\n {t('common:Yes')}\n \n props.close()}\n >\n {t('common:No')}\n \n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport ActivityCardHeader from './ActivityCardHeader'\nimport ActivityCharts from './ActivityCharts'\nimport ActivityDetails from './ActivityDetails'\nimport ActivityMap from './ActivityMap'\nimport ActivityNoMap from './ActivityNoMap'\nimport ActivityNotes from './ActivityNotes'\nimport ActivitySegments from './ActivitySegments'\nimport CustomModal from '../../Common/CustomModal'\nimport Message from '../../Common/Message'\nimport { getOrUpdateData } from '../../../actions'\nimport { deleteActivity } from '../../../actions/activities'\n\nclass ActivityDisplay extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayModal: false,\n coordinates: {\n latitude: null,\n longitude: null,\n },\n }\n }\n\n componentDidMount() {\n this.props.loadActivity(this.props.match.params.activityId)\n }\n\n componentDidUpdate(prevProps) {\n if (\n prevProps.match.params.activityId !== this.props.match.params.activityId\n ) {\n this.props.loadActivity(this.props.match.params.activityId)\n }\n }\n\n displayModal(value) {\n this.setState(prevState => ({\n ...prevState,\n displayModal: value,\n }))\n }\n\n updateCoordinates(activePayload) {\n const coordinates =\n activePayload && activePayload.length > 0\n ? {\n latitude: activePayload[0].payload.latitude,\n longitude: activePayload[0].payload.longitude,\n }\n : {\n latitude: null,\n longitude: null,\n }\n this.setState(prevState => ({\n ...prevState,\n coordinates,\n }))\n }\n\n render() {\n const {\n activities,\n message,\n onDeleteActivity,\n sports,\n t,\n user,\n } = this.props\n const { coordinates, displayModal } = this.state\n const [activity] = activities\n const title = activity ? activity.title : t('activities:Activity')\n const [sport] = activity\n ? sports.filter(s => s.id === activity.sport_id)\n : []\n const segmentId = parseInt(this.props.match.params.segmentId)\n const dataType = segmentId >= 0 ? 'segment' : 'activity'\n return (\n
\n \n FitTrackee - {title}\n \n {message ? (\n \n ) : (\n
\n {displayModal && (\n {\n onDeleteActivity(activity.id)\n this.displayModal(false)\n }}\n close={() => this.displayModal(false)}\n />\n )}\n {activity && sport && activities.length === 1 && (\n
\n
\n
\n
\n
\n this.displayModal(true)}\n />\n
\n
\n
\n
\n {activity.with_gpx ? (\n \n ) : (\n \n )}\n
\n
\n \n
\n
\n
\n
\n
\n
\n {activity.with_gpx && (\n
\n
\n
\n
\n
\n
\n
\n {t('activities:Chart')}\n
\n \n this.updateCoordinates(e)\n }\n />\n
\n
\n
\n
\n
\n
\n )}\n {dataType === 'activity' && (\n <>\n \n {activity.segments.length > 1 && (\n \n )}\n \n )}\n
\n )}\n
\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n activities: state.activities.data,\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadActivity: activityId => {\n dispatch(getOrUpdateData('getData', 'activities', { id: activityId }))\n },\n onDeleteActivity: activityId => {\n dispatch(deleteActivity(activityId))\n },\n })\n )(ActivityDisplay)\n)\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport ActivityAddOrEdit from './ActivityAddOrEdit'\nimport { getOrUpdateData } from '../../actions'\n\nclass ActivityEdit extends React.Component {\n componentDidMount() {\n this.props.loadActivity(this.props.match.params.activityId)\n }\n\n render() {\n const { activities, message, sports } = this.props\n const [activity] = activities\n return (\n
\n {sports.length > 0 && (\n \n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n activities: state.activities.data,\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadActivity: activityId => {\n dispatch(getOrUpdateData('getData', 'activities', { id: activityId }))\n },\n })\n)(ActivityEdit)\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { Redirect, Route, Switch } from 'react-router-dom'\n\nimport ActivityAdd from './ActivityAdd'\nimport ActivityDisplay from './ActivityDisplay'\nimport ActivityEdit from './ActivityEdit'\nimport NotFound from './../Others/NotFound'\nimport { isLoggedIn } from '../../utils'\n\nfunction Activity() {\n return (\n
\n {isLoggedIn() ? (\n \n \n \n \n \n \n \n ) : (\n \n )}\n
\n )\n}\n\nexport default connect(state => ({\n user: state.user,\n}))(Activity)\n","import React from 'react'\n\nimport { translateSports } from '../../utils/activities'\n\nexport default class ActivitiesFilter extends React.PureComponent {\n render() {\n const { loadActivities, sports, t, updateParams } = this.props\n const translatedSports = translateSports(sports, t)\n return (\n
\n
\n
event.preventDefault()}>\n
\n \n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n loadActivities()}\n type=\"submit\"\n value={t('activities:Filter')}\n />\n \n
\n
\n )\n }\n}\n","import React from 'react'\n\nimport { apiUrl } from '../../utils'\n\nexport default class StaticMap extends React.PureComponent {\n render() {\n const { activity, display } = this.props\n\n return (\n
\n \n
\n ©\n \n OpenStreetMap\n \n
\n
\n )\n }\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport StaticMap from '../Common/StaticMap'\nimport { getDateWithTZ } from '../../utils'\n\nexport default class ActivitiesList extends React.PureComponent {\n render() {\n const { activities, loading, sports, t, user } = this.props\n return (\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n {!loading &&\n sports &&\n activities.map((activity, idx) => (\n // eslint-disable-next-line react/no-array-index-key\n \n \n \n \n \n \n \n \n \n ))}\n \n
\n {t('common:Workout')}{t('activities:Date')}{t('activities:Distance')}{t('activities:Duration')}{t('activities:Ave. speed')}{t('activities:Max. speed')}
\n \n {t('common:Sport')}\n \n s.id === activity.sport_id)\n .map(s => s.img)}\n alt=\"activity sport logo\"\n />\n \n \n {t('common:Workout')}\n \n \n {activity.title}\n \n {activity.map && (\n \n )}\n \n \n {t('activities:Date')}\n \n {format(\n getDateWithTZ(activity.activity_date, user.timezone),\n 'dd/MM/yyyy HH:mm'\n )}\n \n \n {t('activities:Distance')}\n \n {Number(activity.distance).toFixed(2)} km\n \n \n {t('activities:Duration')}\n \n {activity.moving}\n \n \n {t('activities:Ave. speed')}\n \n {activity.ave_speed} km/h\n \n \n {t('activities:Max. speed')}\n \n {activity.max_speed} km/h\n
\n {loading &&
}\n
\n
\n )\n }\n}\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nexport default class NoActivities extends React.PureComponent {\n render() {\n const { t } = this.props\n return (\n
\n
\n {t('common:No workouts.')}{' '}\n \n {t('dashboard:Upload one !')}\n \n
\n
\n )\n }\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport ActivitiesFilter from './ActivitiesFilter'\nimport ActivitiesList from './ActivitiesList'\nimport Message from '../Common/Message'\nimport NoActivities from '../Common/NoActivities'\nimport { getOrUpdateData } from '../../actions'\nimport { getMoreActivities } from '../../actions/activities'\n\nclass Activities extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n params: {\n page: 1,\n per_page: 10,\n },\n }\n }\n\n componentDidMount() {\n this.props.loadActivities(this.state.params)\n }\n\n setParams(e) {\n const { params } = this.state\n if (e.target.value === '') {\n delete params[e.target.name]\n } else {\n params[e.target.name] = e.target.value\n }\n params.page = 1\n this.setState(params)\n }\n render() {\n const {\n activities,\n loading,\n loadActivities,\n loadMoreActivities,\n message,\n sports,\n t,\n user,\n } = this.props\n const { params } = this.state\n const paginationEnd =\n activities.length > 0\n ? activities[activities.length - 1].previous_activity === null\n : true\n return (\n
\n \n FitTrackee - {t('common:Workouts')}\n \n {message ? (\n \n ) : (\n
\n
\n
\n loadActivities(params)}\n t={t}\n updateParams={e => this.setParams(e)}\n />\n
\n
\n \n {!paginationEnd && (\n {\n params.page += 1\n loadMoreActivities(params)\n this.setState(params)\n }}\n />\n )}\n {activities.length === 0 && }\n
\n
\n
\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n activities: state.activities.data,\n loading: state.loading,\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadActivities: params => {\n dispatch(getOrUpdateData('getData', 'activities', params))\n },\n loadMoreActivities: params => {\n dispatch(getMoreActivities(params))\n },\n })\n )(Activities)\n)\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport { deletePicture, uploadPicture } from '../../actions/user'\nimport { apiUrl, getFileSize } from '../../utils'\nimport { history } from '../../index'\n\nfunction ProfileDetail({\n appConfig,\n displayModal,\n editable,\n isDeletable,\n message,\n onDeletePicture,\n onUploadPicture,\n pathname,\n t,\n user,\n}) {\n const createdAt = user.created_at\n ? format(new Date(user.created_at), 'dd/MM/yyyy HH:mm')\n : ''\n const birthDate = user.birth_date\n ? format(new Date(user.birth_date), 'dd/MM/yyyy')\n : ''\n const fileSizeLimit = getFileSize(appConfig.max_single_file_size)\n return (\n
\n \n FitTrackee - {t('user:Profile')}\n \n \n
\n

{t('user:Profile')}

\n
\n
\n
\n
\n {user.username}\n
\n
\n
\n
\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Email')}\n : {user.email}\n

\n

\n \n {t('user:Registration Date')}\n \n : {createdAt}\n

\n

\n {t('user:First Name')}\n : {user.first_name}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Last Name')}\n : {user.last_name}\n

\n

\n {t('user:Birth Date')}\n : {birthDate}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Location')}\n : {user.location}\n

\n

\n {t('user:Bio')}:{' '}\n {user.bio}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Language')}\n : {user.language}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Timezone')}\n : {user.timezone}\n

\n

\n \n {t('user:First day of week')}\n \n : {user.weekm ? t('user:Monday') : t('user:Sunday')}\n

\n
\n
\n {user.picture === true && (\n
\n \n {editable && (\n <>\n
\n onDeletePicture()}\n >\n {t('user:Delete picture')}\n \n
\n
\n \n )}\n
\n )}\n {editable && (\n onUploadPicture(event)}\n >\n \n
\n \n {` (max. size: ${fileSizeLimit})`}\n \n )}{' '}\n
\n
\n {editable && (\n history.push('/profile/edit')}\n >\n {t('common:Edit')}\n \n )}\n {isDeletable && (\n displayModal(true)}\n >\n {t('user:Delete user account')}\n \n )}\n \n pathname === '/profile' ? history.push('/') : history.go(-1)\n }\n >\n {t(\n pathname === '/profile'\n ? 'common:Back to home'\n : 'common:Back'\n )}\n \n
\n
\n
\n
\n
\n
\n )\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n appConfig: state.application.config,\n pathname: state.router.location.pathname,\n message: state.message,\n }),\n dispatch => ({\n onDeletePicture: () => {\n dispatch(deletePicture())\n },\n onUploadPicture: event => {\n dispatch(uploadPicture(event))\n },\n })\n )(ProfileDetail)\n)\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport ProfileDetail from './ProfileDetail'\n\nfunction CurrentUserProfile({ t, user }) {\n return (\n
\n \n
\n )\n}\n\nexport default withTranslation()(\n connect(state => ({\n user: state.user,\n }))(CurrentUserProfile)\n)\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport StaticMap from '../Common/StaticMap'\nimport { getDateWithTZ } from '../../utils'\n\nexport default function ActivityCard(props) {\n const { activity, sports, t, user } = props\n\n return (\n
\n
\n \n {sports\n .filter(sport => sport.id === activity.sport_id)\n .map(sport => t(`sports:${sport.label}`))}{' '}\n -{' '}\n {format(\n getDateWithTZ(activity.activity_date, user.timezone),\n 'dd/MM/yyyy HH:mm'\n )}\n \n
\n
\n
\n {activity.map && (\n
\n \n
\n )}\n
\n

\n {' '}\n {t('activities:Duration')}: {activity.moving}\n {activity.map ? (\n \n
\n
\n
\n ) : (\n ' - '\n )}\n {' '}\n {t('activities:Distance')}: {activity.distance} km\n

\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { recordsLabels } from '../../utils/activities'\n\nexport default function CalendarActivity(props) {\n const { activity, isDisabled, isMore, sportImg } = props\n return (\n \n <>\n \n {activity.records.length > 0 && (\n \n \n ` ${\n recordsLabels.filter(\n r => r.record_type === rec.record_type\n )[0].label\n }`\n )}\n />\n \n )}\n \n \n )\n}\n","import React from 'react'\n\nimport CalendarActivity from './CalendarActivity'\n\nexport default class CalendarActivities extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n isHidden: true,\n }\n }\n\n handleDisplayMore() {\n this.setState({\n isHidden: !this.state.isHidden,\n })\n }\n\n render() {\n const { dayActivities, isDisabled, sports } = this.props\n const { isHidden } = this.state\n return (\n
\n {dayActivities.map(act => (\n s.id === act.sport_id).map(s => s.img)}\n />\n ))}\n {dayActivities.length > 2 && (\n this.handleDisplayMore()}\n title=\"show more activities\"\n />\n )}\n {!isHidden && (\n
\n {dayActivities.map(act => (\n s.id === act.sport_id)\n .map(s => s.img)}\n />\n ))}\n
\n )}\n
\n )\n }\n}\n","// eslint-disable-next-line max-len\n// source: https://blog.flowandform.agency/create-a-custom-calendar-in-react-3df1bfd0b728\nimport {\n addDays,\n addMonths,\n endOfMonth,\n endOfWeek,\n format,\n isSameDay,\n isSameMonth,\n isToday,\n startOfMonth,\n startOfWeek,\n subMonths,\n} from 'date-fns'\nimport { enGB, fr } from 'date-fns/locale'\nimport React from 'react'\nimport { connect } from 'react-redux'\n\nimport CalendarActivities from './CalendarActivities'\nimport { getMonthActivities } from '../../actions/activities'\nimport { getDateWithTZ } from '../../utils'\n\nconst getStartAndEndMonth = (date, weekStartOnMonday) => {\n const monthStart = startOfMonth(date)\n const monthEnd = endOfMonth(date)\n const weekStartsOn = weekStartOnMonday ? 1 : 0\n return {\n start: startOfWeek(monthStart, { weekStartsOn }),\n end: endOfWeek(monthEnd),\n }\n}\n\nclass Calendar extends React.Component {\n constructor(props, context) {\n super(props, context)\n const calendarDate = new Date()\n this.state = {\n currentMonth: calendarDate,\n startDate: getStartAndEndMonth(calendarDate, props.weekm).start,\n endDate: getStartAndEndMonth(calendarDate, props.weekm).end,\n weekStartOnMonday: props.weekm,\n }\n }\n\n componentDidMount() {\n this.props.loadMonthActivities(this.state.startDate, this.state.endDate)\n }\n\n renderHeader(localeOptions) {\n const dateFormat = 'MMM yyyy'\n return (\n
\n
this.handlePrevMonth()}>\n \n
\n
\n \n {format(this.state.currentMonth, dateFormat, localeOptions)}\n \n
\n
this.handleNextMonth()}>\n \n
\n
\n )\n }\n\n renderDays(localeOptions) {\n const dateFormat = 'EEE'\n const days = []\n const { startDate } = this.state\n\n for (let i = 0; i < 7; i++) {\n days.push(\n
\n {format(addDays(startDate, i), dateFormat, localeOptions)}\n
\n )\n }\n return
{days}
\n }\n\n filterActivities(day) {\n const { activities, user } = this.props\n if (activities) {\n return activities.filter(act =>\n isSameDay(getDateWithTZ(act.activity_date, user.timezone), day)\n )\n }\n return []\n }\n\n renderCells() {\n const { currentMonth, startDate, endDate, weekStartOnMonday } = this.state\n const { sports } = this.props\n\n const dateFormat = 'd'\n const rows = []\n\n let days = []\n let day = startDate\n let formattedDate = ''\n\n while (day <= endDate) {\n for (let i = 0; i < 7; i++) {\n formattedDate = format(day, dateFormat)\n const dayActivities = this.filterActivities(day)\n const isDisabled = isSameMonth(day, currentMonth) ? '' : '-disabled'\n const isWeekEnd = weekStartOnMonday\n ? [5, 6].includes(i)\n : [0, 6].includes(i)\n days.push(\n \n
\n {formattedDate}\n \n
\n
\n )\n day = addDays(day, 1)\n }\n rows.push(\n
\n {days}\n
\n )\n days = []\n }\n return
{rows}
\n }\n\n updateStateDate(calendarDate) {\n const { start, end } = getStartAndEndMonth(\n calendarDate,\n this.state.weekStartOnMonday\n )\n this.setState({\n currentMonth: calendarDate,\n startDate: start,\n endDate: end,\n })\n this.props.loadMonthActivities(start, end)\n }\n\n handleNextMonth() {\n const calendarDate = addMonths(this.state.currentMonth, 1)\n this.updateStateDate(calendarDate)\n }\n\n handlePrevMonth() {\n const calendarDate = subMonths(this.state.currentMonth, 1)\n this.updateStateDate(calendarDate)\n }\n\n render() {\n const localeOptions = {\n locale: this.props.language === 'fr' ? fr : enGB,\n }\n return (\n
\n
\n {this.renderHeader(localeOptions)}\n {this.renderDays(localeOptions)}\n {this.renderCells()}\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n activities: state.calendarActivities.data,\n language: state.language,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadMonthActivities: (start, end) => {\n const dateFormat = 'yyyy-MM-dd'\n dispatch(\n getMonthActivities(format(start, dateFormat), format(end, dateFormat))\n )\n },\n })\n)(Calendar)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { formatRecord, translateSports } from '../../utils/activities'\n\nexport default function RecordsCard(props) {\n const { records, sports, t, user } = props\n const translatedSports = translateSports(sports, t)\n const recordsBySport = records.reduce((sportList, record) => {\n const sport = translatedSports.find(s => s.id === record.sport_id)\n if (sportList[sport.label] === void 0) {\n sportList[sport.label] = {\n img: sport.img,\n records: [],\n }\n }\n sportList[sport.label].records.push(formatRecord(record, user.timezone))\n return sportList\n }, {})\n\n return (\n
\n
{t('activities:Personal records')}
\n
\n {Object.keys(recordsBySport).length === 0\n ? t('common:No records.')\n : Object.keys(recordsBySport)\n .sort()\n .map(sportLabel => (\n
\n \n \n {sportLabel}\n \n {/* eslint-disable-next-line max-len */}\n \n \n \n \n \n \n \n {recordsBySport[sportLabel].records.map(rec => (\n \n \n \n \n \n ))}\n \n
\n \n {sportLabel}\n
\n {t(`activities:${rec.record_type}`)}\n {rec.value}\n \n {rec.activity_date}\n \n
\n
\n ))}\n
\n
\n )\n}\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport { setData, setError } from './index'\n\nexport const getStats = (userName, type, data) => dispatch =>\n FitTrackeeGenericApi.getData(`stats/${userName}/${type}`, data)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setData('statistics', ret.data))\n } else {\n dispatch(setError(`statistics|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`statistics|${error}`)))\n","import {\n addDays,\n addMonths,\n addYears,\n format,\n startOfMonth,\n startOfWeek,\n startOfYear,\n} from 'date-fns'\n\nconst xAxisFormats = [\n { duration: 'week', dateFormat: 'yyyy-MM-dd', xAxis: 'dd/MM' },\n { duration: 'month', dateFormat: 'yyyy-MM', xAxis: 'MM/yyyy' },\n { duration: 'year', dateFormat: 'yyyy', xAxis: 'yyyy' },\n]\n\nexport const formatDuration = (totalSeconds, formatWithDay = false) => {\n let days = '0'\n if (formatWithDay) {\n days = String(Math.floor(totalSeconds / 86400))\n totalSeconds %= 86400\n }\n const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, '0')\n totalSeconds %= 3600\n const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0')\n const seconds = String(totalSeconds % 60).padStart(2, '0')\n if (formatWithDay) {\n return `${days === '0' ? '' : `${days}d:`}${\n hours === '00' ? '' : `${hours}h:`\n }${minutes}m:${seconds}s`\n }\n return `${hours === '00' ? '' : `${hours}:`}${minutes}:${seconds}`\n}\n\nexport const formatValue = (displayedData, value) =>\n value === 0\n ? ''\n : displayedData === 'distance'\n ? `${value.toFixed(2)} km`\n : displayedData === 'duration'\n ? formatDuration(value)\n : value\n\nconst dateIncrement = (duration, day) => {\n switch (duration) {\n case 'week':\n return addDays(day, 7)\n case 'year':\n return addYears(day, 1)\n case 'month':\n default:\n return addMonths(day, 1)\n }\n}\n\nconst startDate = (duration, day, weekm) => {\n switch (duration) {\n case 'week':\n return startOfWeek(day, { weekStartsOn: weekm ? 1 : 0 })\n case 'year':\n return startOfYear(day)\n case 'month':\n default:\n return startOfMonth(day)\n }\n}\n\nexport const formatStats = (stats, sports, params, displayedSports, weekm) => {\n const nbActivitiesStats = []\n const distanceStats = []\n const durationStats = []\n\n for (\n let day = startDate(params.duration, params.start, weekm);\n day <= params.end;\n day = dateIncrement(params.duration, day)\n ) {\n const [xAxisFormat] = xAxisFormats.filter(\n x => x.duration === params.duration\n )\n const date = format(day, xAxisFormat.dateFormat)\n const xAxis = format(day, xAxisFormat.xAxis)\n const dataNbActivities = { date: xAxis }\n const dataDistance = { date: xAxis }\n const dataDuration = { date: xAxis }\n\n if (stats[date]) {\n Object.keys(stats[date])\n .filter(sportId =>\n displayedSports ? displayedSports.includes(+sportId) : true\n )\n .map(sportId => {\n const sportLabel = sports.filter(s => s.id === +sportId)[0].label\n dataNbActivities[sportLabel] = stats[date][sportId].nb_activities\n dataDistance[sportLabel] = stats[date][sportId].total_distance\n dataDuration[sportLabel] = stats[date][sportId].total_duration\n return null\n })\n }\n nbActivitiesStats.push(dataNbActivities)\n distanceStats.push(dataDistance)\n durationStats.push(dataDuration)\n }\n\n return {\n activities: nbActivitiesStats,\n distance: distanceStats,\n duration: durationStats,\n }\n}\n","import React from 'react'\n\nimport { formatDuration } from '../../../utils/stats'\n\nconst formatValue = (displayedData, value) =>\n displayedData === 'duration'\n ? formatDuration(value, true)\n : displayedData === 'distance'\n ? value.toFixed(2)\n : value\n\n/**\n * @return {null}\n */\nexport default function CustomTooltip(props) {\n const { active } = props\n if (active) {\n const { displayedData, payload, label } = props\n let total = 0\n payload.map(p => (total += p.value))\n return (\n
\n

{label}

\n {payload.map(p => (\n

\n {p.name}: {formatValue(displayedData, p.value)} {p.unit}\n

\n ))}\n {payload.length > 0 && (\n

Total: {formatValue(displayedData, total)}

\n )}\n
\n )\n }\n return null\n}\n","import React from 'react'\n\nimport { formatValue } from '../../../utils/stats'\n\n/**\n * @return {null}\n */\nexport default function CustomLabel(props) {\n const { displayedData, x, y, width, value } = props\n if (!value) {\n return null\n }\n const radius = 10\n const formattedValue = formatValue(displayedData, value)\n\n return (\n \n \n {formattedValue}\n \n \n )\n}\n","import React from 'react'\nimport {\n Bar,\n BarChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts'\n\nimport { activityColors } from '../../../utils/activities'\nimport { formatValue } from '../../../utils/stats'\nimport CustomTooltip from './CustomTooltip'\nimport CustomLabel from './CustomLabel'\n\nexport default class StatsCharts extends React.PureComponent {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayedData: 'distance',\n }\n }\n handleRadioChange(changeEvent) {\n this.setState({\n displayedData: changeEvent.target.name,\n })\n }\n\n render() {\n const { displayedData } = this.state\n const { sports, stats, t } = this.props\n if (Object.keys(stats).length === 0) {\n return t('common:No workouts.')\n }\n return (\n
\n
\n \n \n \n
\n \n \n \n formatValue(displayedData, value)} />\n }\n />\n {sports.map((s, i) => (\n \n ) : (\n ''\n )\n }\n name={t(`sports:${s.label}`)}\n />\n ))}\n \n \n
\n )\n }\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { connect } from 'react-redux'\n\nimport { getStats } from '../../../actions/stats'\nimport { formatStats } from '../../../utils/stats'\nimport StatsChart from './StatsChart'\n\nclass Statistics extends React.PureComponent {\n componentDidMount() {\n this.updateData()\n }\n\n componentDidUpdate(prevProps) {\n if (\n (this.props.user.username &&\n this.props.user.username !== prevProps.user.username) ||\n this.props.statsParams !== prevProps.statsParams\n ) {\n this.updateData()\n }\n }\n\n updateData() {\n if (this.props.user.username) {\n this.props.loadActivities(\n this.props.user.username,\n this.props.user.weekm,\n this.props.statsParams\n )\n }\n }\n\n render() {\n const {\n displayedSports,\n sports,\n statistics,\n statsParams,\n displayEmpty,\n t,\n user,\n } = this.props\n if (!displayEmpty && Object.keys(statistics).length === 0) {\n return {t('common:No workouts.')}\n }\n const stats = formatStats(\n statistics,\n sports,\n statsParams,\n displayedSports,\n user.weekm\n )\n return \n }\n}\n\nexport default connect(\n state => ({\n sports: state.sports.data,\n statistics: state.statistics.data,\n user: state.user,\n }),\n dispatch => ({\n loadActivities: (userName, weekm, data) => {\n const dateFormat = 'yyyy-MM-dd'\n // depends on user config (first day of week)\n const time =\n data.duration === 'week'\n ? `${data.duration}${weekm ? 'm' : ''}`\n : data.duration\n const params = {\n from: format(data.start, dateFormat),\n to: format(data.end, dateFormat),\n time: time,\n }\n dispatch(getStats(userName, data.type, params))\n },\n })\n)(Statistics)\n","import { endOfMonth, startOfMonth } from 'date-fns'\nimport React from 'react'\n\nimport Stats from '../Common/Stats'\n\nexport default class Statistics extends React.Component {\n constructor(props, context) {\n super(props, context)\n const date = new Date()\n this.state = {\n start: startOfMonth(date),\n end: endOfMonth(date),\n duration: 'week',\n type: 'by_time',\n }\n }\n\n render() {\n const { t } = this.props\n return (\n
\n
{t('dashboard:This month')}
\n
\n \n
\n
\n )\n }\n}\n","import React from 'react'\n\nexport default function UserStatistics(props) {\n const { t, user } = props\n const days = user.total_duration.match(/day/g)\n ? `${user.total_duration.split(' ')[0]} ${\n user.total_duration.match(/days/g) ? t('common:days') : t('common:day')\n }`\n : `0 ${t('common:days')},`\n let duration = user.total_duration.match(/day/g)\n ? user.total_duration.split(', ')[1]\n : user.total_duration\n duration = `${duration.split(':')[0]}h ${duration.split(':')[1]}min`\n return (\n
\n
\n
\n
\n
\n \n
\n
\n
{user.nb_activities}
\n
{`${\n user.nb_activities === 1\n ? t('common:workout')\n : t('common:workouts')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n {Number(user.total_distance).toFixed(2)}\n
\n
km
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
{days}
\n
{duration}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
{user.nb_sports}
\n
{`${\n user.nb_sports === 1 ? t('common:sport') : t('common:sports')\n }`}
\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport ActivityCard from './ActivityCard'\nimport Calendar from './Calendar'\nimport Message from '../Common/Message'\nimport NoActivities from '../Common/NoActivities'\nimport Records from './Records'\nimport Statistics from './Statistics'\nimport UserStatistics from './UserStatistics'\nimport { getOrUpdateData } from '../../actions'\nimport { getMoreActivities } from '../../actions/activities'\n\nclass DashBoard extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n page: 1,\n }\n }\n\n componentDidMount() {\n this.props.loadActivities()\n }\n\n render() {\n const {\n activities,\n loadMoreActivities,\n message,\n records,\n sports,\n t,\n user,\n } = this.props\n const paginationEnd =\n activities.length > 0\n ? activities[activities.length - 1].previous_activity === null\n : true\n const { page } = this.state\n return (\n
\n \n FitTrackee - {t('common:Dashboard')}\n \n {message ? (\n \n ) : (\n activities &&\n user.total_duration &&\n sports.length > 0 && (\n
\n \n
\n
\n \n \n
\n
\n \n {activities.length > 0 ? (\n activities.map(activity => (\n \n ))\n ) : (\n \n )}\n {!paginationEnd && (\n {\n loadMoreActivities(page + 1)\n this.setState({ page: page + 1 })\n }}\n />\n )}\n
\n
\n
\n )\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n activities: state.activities.data,\n message: state.message,\n records: state.records.data,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadActivities: () => {\n dispatch(getOrUpdateData('getData', 'activities', { page: 1 }))\n dispatch(getOrUpdateData('getData', 'records'))\n },\n loadMoreActivities: page => {\n dispatch(getMoreActivities({ page }))\n },\n })\n )(DashBoard)\n)\n","import React from 'react'\n\nimport { version } from './../../utils'\n\nexport default function Footer() {\n return (\n
\n
\n FitTrackee v{version} -{' '}\n \n source code\n {' '}\n under{' '}\n \n GPLv3\n {' '}\n license -{' '}\n \n documentation\n \n
\n
\n )\n}\n","import React from 'react'\nimport { Trans } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport { Link } from 'react-router-dom'\n\nimport { logout } from '../../actions/user'\n\nclass Logout extends React.Component {\n componentDidMount() {\n this.props.UserLogout()\n }\n render() {\n return (\n
\n
\n
\n
\n
\n
\n \n You are now logged out. Click here to\n log back in.\n \n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n user: state.user,\n }),\n dispatch => ({\n UserLogout: () => {\n dispatch(logout())\n },\n })\n)(Logout)\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m466.916 27.803h-421.832c-24.859 0-45.084 20.225-45.084 45.084v366.226c0 24.859 20.225 45.084 45.084 45.084h421.832c24.859 0 45.084-20.225 45.084-45.084v-366.226c0-24.859-20.225-45.084-45.084-45.084z\",\n fill: \"#f0f9ff\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m198.58 188.334-181.344-150.862c-7.75 6.107-13.456 14.691-15.905 24.554l164.142 136.551h33.102z\",\n fill: \"#f40055\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 198.576h33.93l163.447-135.973c-2.325-9.923-7.93-18.592-15.613-24.796l-181.764 151.211z\",\n fill: \"#c20044\"\n});\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m165.472 313.425-164.141 136.549c2.449 9.863 8.155 18.447 15.905 24.553l181.344-150.861-.005-10.241z\",\n fill: \"#f40055\"\n});\n\nvar _ref6 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 313.425v9.557l181.765 151.211c7.683-6.204 13.288-14.874 15.613-24.796l-163.446-135.971z\",\n fill: \"#c20044\"\n});\n\nvar _ref7 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m53.273 27.803 145.302 120.879v-120.879z\",\n fill: \"#406bd4\"\n});\n\nvar _ref8 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 150.571v-122.768h148.082z\",\n fill: \"#3257b0\"\n});\n\nvar _ref9 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m394.732 198.575 117.268-97.556v97.556z\",\n fill: \"#3257b0\"\n});\n\nvar _ref10 = /*#__PURE__*/React.createElement(\"g\", {\n fill: \"#406bd4\"\n}, /*#__PURE__*/React.createElement(\"path\", {\n d: \"m0 99.317v99.258h119.313z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"m0 313.425v97.699l117.44-97.699z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"m50.49 484.197 148.085-122.676v122.676z\"\n}));\n\nvar _ref11 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 484.197v-124.139l149.221 124.139z\",\n fill: \"#3257b0\"\n});\n\nvar _ref12 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m512 409.423-115.395-95.998h115.395z\",\n fill: \"#3257b0\"\n});\n\nvar _ref13 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m512 222.142h-222.142v-194.339h-67.716v194.339h-222.142v67.716h222.142v194.339h67.716v-194.339h222.142z\",\n fill: \"#f40055\"\n});\n\nvar _ref14 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m289.858 222.142v-194.339h-33.858v456.394h33.858v-194.339h222.142v-67.716z\",\n fill: \"#c20044\"\n});\n\nfunction SvgEn(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Capa_1\",\n enableBackground: \"new 0 0 512 512\",\n height: 512,\n viewBox: \"0 0 512 512\",\n width: 512,\n xmlns: \"http://www.w3.org/2000/svg\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13, _ref14);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgEn);\nexport default __webpack_public_path__ + \"static/media/en.9e6dbfb0.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m173.899 31.804h-8.707l-4.397-4h-115.711c-24.859-.001-45.084 20.224-45.084 45.083v366.226c0 24.859 20.225 45.084 45.084 45.084h115.711l6.348-4h6.755v-448.393z\",\n fill: \"#406bd4\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m466.916 27.803h-115.711l-4.523 4h-5.141v448.393h4.141l5.523 4h115.711c24.859 0 45.084-20.225 45.084-45.084v-366.225c0-24.859-20.225-45.084-45.084-45.084z\",\n fill: \"#c20044\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m160.795 27.803h190.409v456.394h-190.409z\",\n fill: \"#f0f9ff\"\n});\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m256 27.803h95.205v456.394h-95.205z\",\n fill: \"#cee5f5\"\n});\n\nfunction SvgFr(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Capa_1\",\n enableBackground: \"new 0 0 512 512\",\n height: 512,\n viewBox: \"0 0 512 512\",\n width: 512,\n xmlns: \"http://www.w3.org/2000/svg\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3, _ref4, _ref5);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgFr);\nexport default __webpack_public_path__ + \"static/media/fr.d0f9280c.svg\";\nexport { ForwardRef as ReactComponent };","import React, { Component } from 'react'\nimport { connect } from 'react-redux'\n\nimport { ReactComponent as EnFlag } from '../../images/flags/en.svg'\nimport { ReactComponent as FrFlag } from '../../images/flags/fr.svg'\nimport { updateLanguage } from '../../actions/index'\n\nexport const languages = [\n {\n name: 'en',\n selected: true,\n flag: ,\n },\n {\n name: 'fr',\n selected: false,\n flag: ,\n },\n]\n\nclass Dropdown extends Component {\n constructor(props) {\n super(props)\n this.state = {\n isOpen: false,\n }\n }\n\n toggleDropdown() {\n this.setState(prevState => ({\n isOpen: !prevState.isOpen,\n }))\n }\n\n render() {\n const { isOpen } = this.state\n const { language: selected, onUpdateLanguage } = this.props\n return (\n
this.toggleDropdown()}>\n
    \n {languages\n .filter(language =>\n isOpen ? language : language.name === selected\n )\n .map(language => (\n onUpdateLanguage(language.name, selected)}\n >\n {language.flag} {language.name}\n \n ))}\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n language: state.language,\n }),\n dispatch => ({\n onUpdateLanguage: (lang, selected) => {\n if (lang !== selected) {\n dispatch(updateLanguage(lang))\n }\n },\n })\n)(Dropdown)\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { withTranslation } from 'react-i18next'\nimport { Link } from 'react-router-dom'\n\nimport LanguageDropdown from './LanguageDropdown'\nimport { apiUrl } from '../../utils'\n\nclass NavBar extends React.PureComponent {\n render() {\n const { admin, isAuthenticated, picture, t, username } = this.props\n return (\n
\n
\n \n \n )\n }\n}\n\nexport default withTranslation()(\n connect(({ user }) => ({\n admin: user.admin,\n isAuthenticated: user.isAuthenticated,\n picture: user.picture,\n username: user.username,\n }))(NavBar)\n)\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M468.683,287.265h-69.07c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h69.07 c4.147,0,7.508-3.361,7.508-7.508C476.191,290.626,472.83,287.265,468.683,287.265z\"\n})));\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M105.012,268.377L85.781,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L58.034,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C109.507,275.266,108.499,270.62,105.012,268.377z\"\n})));\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M194.441,268.377L175.21,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.47,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.776l-17.471-11.243 c-3.487-2.245-8.133-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L147.463,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.47,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C198.936,275.266,197.928,270.62,194.441,268.377z\"\n})));\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M283.871,268.377L264.64,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.471-11.243 c-3.486-2.245-8.134-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L236.892,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.886-1.216,6.32-3.446C288.366,275.266,287.358,270.62,283.871,268.377z\"\n})));\n\nvar _ref6 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M373.3,268.377L354.069,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L326.322,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C377.795,275.266,376.787,270.62,373.3,268.377z\"\n})));\n\nvar _ref7 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M271.792,330.359H15.016V181.642h93.1c4.147,0,7.508-3.361,7.508-7.508c0-4.147-3.361-7.508-7.508-7.508H12.513 C5.613,166.626,0,172.24,0,179.14v153.722c0,6.9,5.613,12.513,12.513,12.513h259.278c4.147,0,7.508-3.361,7.508-7.508 C279.299,333.72,275.939,330.359,271.792,330.359z\"\n})));\n\nvar _ref8 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M499.487,166.626H162.174c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h334.811v148.716H323.848 c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h175.64c6.9,0,12.513-5.613,12.513-12.513V179.14 C512.001,172.24,506.387,166.626,499.487,166.626z\"\n})));\n\nfunction SvgPassword(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Layer_1\",\n xmlns: \"http://www.w3.org/2000/svg\",\n xmlnsXlink: \"http://www.w3.org/1999/xlink\",\n x: \"0px\",\n y: \"0px\",\n viewBox: \"0 0 512.001 512.001\",\n style: {\n enableBackground: \"new 0 0 512.001 512.001\"\n },\n xmlSpace: \"preserve\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgPassword);\nexport default __webpack_public_path__ + \"static/media/password.afe6a2a5.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M339.798,260.429c0.13-0.026,0.257-0.061,0.385-0.094c0.109-0.028,0.219-0.051,0.326-0.084 c0.125-0.038,0.247-0.085,0.369-0.129c0.108-0.039,0.217-0.074,0.324-0.119c0.115-0.048,0.226-0.104,0.338-0.157 c0.109-0.052,0.22-0.1,0.327-0.158c0.107-0.057,0.208-0.122,0.312-0.184c0.107-0.064,0.215-0.124,0.319-0.194 c0.111-0.074,0.214-0.156,0.321-0.236c0.09-0.067,0.182-0.13,0.27-0.202c0.162-0.133,0.316-0.275,0.466-0.421 c0.027-0.026,0.056-0.048,0.083-0.075c0.028-0.028,0.052-0.059,0.079-0.088c0.144-0.148,0.284-0.3,0.416-0.46 c0.077-0.094,0.144-0.192,0.216-0.289c0.074-0.1,0.152-0.197,0.221-0.301c0.074-0.111,0.139-0.226,0.207-0.34 c0.057-0.096,0.118-0.19,0.171-0.289c0.062-0.115,0.114-0.234,0.169-0.351c0.049-0.104,0.101-0.207,0.146-0.314 c0.048-0.115,0.086-0.232,0.128-0.349c0.041-0.114,0.085-0.227,0.12-0.343c0.036-0.118,0.062-0.238,0.092-0.358 c0.029-0.118,0.063-0.234,0.086-0.353c0.028-0.141,0.045-0.283,0.065-0.425c0.014-0.1,0.033-0.199,0.043-0.3 c0.025-0.249,0.038-0.498,0.038-0.748V92.76c0-4.143-3.357-7.5-7.5-7.5h-236.25c-0.066,0-0.13,0.008-0.196,0.01 c-0.143,0.004-0.285,0.01-0.427,0.022c-0.113,0.009-0.225,0.022-0.337,0.037c-0.128,0.016-0.255,0.035-0.382,0.058 c-0.119,0.021-0.237,0.046-0.354,0.073c-0.119,0.028-0.238,0.058-0.356,0.092c-0.117,0.033-0.232,0.069-0.346,0.107 c-0.117,0.04-0.234,0.082-0.349,0.128c-0.109,0.043-0.216,0.087-0.322,0.135c-0.118,0.053-0.235,0.11-0.351,0.169 c-0.099,0.051-0.196,0.103-0.292,0.158c-0.116,0.066-0.23,0.136-0.343,0.208c-0.093,0.06-0.184,0.122-0.274,0.185 c-0.106,0.075-0.211,0.153-0.314,0.235c-0.094,0.075-0.186,0.152-0.277,0.231c-0.09,0.079-0.179,0.158-0.266,0.242 c-0.099,0.095-0.194,0.194-0.288,0.294c-0.047,0.05-0.097,0.094-0.142,0.145c-0.027,0.03-0.048,0.063-0.074,0.093 c-0.094,0.109-0.182,0.223-0.27,0.338c-0.064,0.084-0.13,0.168-0.19,0.254c-0.078,0.112-0.15,0.227-0.222,0.343 c-0.059,0.095-0.12,0.189-0.174,0.286c-0.063,0.112-0.118,0.227-0.175,0.342c-0.052,0.105-0.106,0.21-0.153,0.317 c-0.049,0.113-0.092,0.23-0.135,0.345c-0.043,0.113-0.087,0.225-0.124,0.339c-0.037,0.115-0.067,0.232-0.099,0.349 c-0.032,0.12-0.066,0.239-0.093,0.36c-0.025,0.113-0.042,0.228-0.062,0.342c-0.022,0.13-0.044,0.26-0.06,0.39 c-0.013,0.108-0.019,0.218-0.027,0.328c-0.01,0.14-0.019,0.28-0.021,0.421c-0.001,0.041-0.006,0.081-0.006,0.122v46.252 c0,4.143,3.357,7.5,7.5,7.5s7.5-3.357,7.5-7.5v-29.595l66.681,59.037c-0.348,0.245-0.683,0.516-0.995,0.827l-65.687,65.687v-49.288 c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v9.164h-38.75c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h38.75v43.231 c0,4.143,3.357,7.5,7.5,7.5h236.25c0.247,0,0.494-0.013,0.74-0.037c0.115-0.011,0.226-0.033,0.339-0.049 C339.542,260.469,339.67,260.454,339.798,260.429z M330.834,234.967l-65.688-65.687c-0.042-0.042-0.087-0.077-0.13-0.117 l49.383-41.897c3.158-2.68,3.546-7.412,0.866-10.571c-2.678-3.157-7.41-3.547-10.571-0.866l-84.381,71.59l-98.444-87.158h208.965 V234.967z M185.878,179.888c0.535-0.535,0.969-1.131,1.308-1.765l28.051,24.835c1.418,1.255,3.194,1.885,4.972,1.885 c1.726,0,3.451-0.593,4.853-1.781l28.587-24.254c0.26,0.38,0.553,0.743,0.89,1.08l65.687,65.687H120.191L185.878,179.888z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M7.5,170.676h126.667c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H7.5c-4.143,0-7.5,3.357-7.5,7.5 S3.357,170.676,7.5,170.676z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M20.625,129.345H77.5c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H20.625c-4.143,0-7.5,3.357-7.5,7.5 S16.482,129.345,20.625,129.345z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M62.5,226.51h-55c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h55c4.143,0,7.5-3.357,7.5-7.5S66.643,226.51,62.5,226.51z\"\n}));\n\nfunction SvgMailSend(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Capa_1\",\n xmlns: \"http://www.w3.org/2000/svg\",\n xmlnsXlink: \"http://www.w3.org/1999/xlink\",\n x: \"0px\",\n y: \"0px\",\n viewBox: \"0 0 345.834 345.834\",\n style: {\n enableBackground: \"new 0 0 345.834 345.834\"\n },\n xmlSpace: \"preserve\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgMailSend);\nexport default __webpack_public_path__ + \"static/media/mail-send.619079f0.svg\";\nexport { ForwardRef as ReactComponent };","import React from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { Link } from 'react-router-dom'\n\nimport { ReactComponent as Password } from '../../images/password.svg'\nimport { ReactComponent as MailSend } from '../../images/mail-send.svg'\n\nexport default function PasswordReset(props) {\n const { t } = useTranslation()\n const { action } = props\n return (\n
\n
\n
\n
\n
\n
\n {action === 'sent' && (\n <>\n
\n \n
\n {t(\n // eslint-disable-next-line max-len\n \"user:Check your email. If your address is in our database, you'll received an email with a link to reset your password.\"\n )}\n \n )}\n {action === 'updated' && (\n <>\n
\n \n
\n \n {/* prettier-ignore */}\n Your password have been updated. Click\n here to log in.\n \n \n )}\n
\n
\n
\n
\n
\n
\n )\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport TimezonePicker from 'react-timezone'\n\nimport Message from '../Common/Message'\nimport { deleteUser, handleProfileFormSubmit } from '../../actions/user'\nimport { history } from '../../index'\nimport { languages } from '../NavBar/LanguageDropdown'\nimport CustomModal from '../Common/CustomModal'\n\nclass ProfileEdit extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n formData: {},\n displayModal: false,\n }\n }\n\n componentDidMount() {\n this.initForm()\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.user !== this.props.user) {\n this.initForm()\n }\n }\n\n initForm() {\n const { user } = this.props\n const formData = {}\n Object.keys(user).map(k =>\n user[k] === null\n ? (formData[k] = '')\n : k === 'birth_date'\n ? (formData[k] = format(new Date(user[k]), 'yyyy-MM-DD'))\n : (formData[k] = user[k])\n )\n this.setState({ formData })\n }\n\n handleFormChange(e) {\n const { formData } = this.state\n if (e.target.name === 'weekm') {\n formData.weekm = e.target.value === 'Monday'\n } else {\n formData[e.target.name] = e.target.value\n }\n this.setState(formData)\n }\n\n displayModal(value) {\n this.setState(prevState => ({\n ...prevState,\n displayModal: value,\n }))\n }\n\n render() {\n const {\n message,\n onDeleteUser,\n onHandleProfileFormSubmit,\n t,\n user,\n } = this.props\n const { displayModal, formData } = this.state\n return (\n
\n \n FitTrackee - {t('user:Profile Edition')}\n \n {formData.isAuthenticated && (\n
\n {displayModal && (\n {\n onDeleteUser(user.username)\n this.displayModal(false)\n }}\n close={() => this.displayModal(false)}\n />\n )}\n

{t('user:Profile Edition')}

\n
\n
\n
\n
\n
{user.username}
\n
\n
\n
\n {\n event.preventDefault()\n onHandleProfileFormSubmit(formData)\n }}\n >\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n \n {\n event.preventDefault()\n this.displayModal(true)\n }}\n >\n {t('user:Delete my account')}\n \n history.push('/profile')}\n >\n {t('common:Cancel')}\n \n \n \n
\n
\n
\n
\n
\n
\n
\n
\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n location: state.router.location,\n message: state.message,\n user: state.user,\n }),\n dispatch => ({\n onDeleteUser: username => {\n dispatch(deleteUser(username))\n },\n onHandleProfileFormSubmit: formData => {\n dispatch(handleProfileFormSubmit(formData))\n },\n })\n )(ProfileEdit)\n)\n","import {\n endOfMonth,\n endOfWeek,\n endOfYear,\n startOfMonth,\n startOfYear,\n startOfWeek,\n addMonths,\n addWeeks,\n addYears,\n subMonths,\n subWeeks,\n subYears,\n} from 'date-fns'\nimport React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport NoActivities from '../Common/NoActivities'\nimport Stats from '../Common/Stats'\nimport { activityColors, translateSports } from '../../utils/activities'\n\nconst durations = ['week', 'month', 'year']\n\nclass Statistics extends React.Component {\n constructor(props, context) {\n super(props, context)\n const date = new Date()\n this.state = {\n displayedSports: props.sports.map(sport => sport.id),\n statsParams: {\n start: startOfMonth(subMonths(date, 11)),\n end: endOfMonth(date),\n duration: 'month',\n type: 'by_time',\n },\n }\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.sports !== prevProps.sports) {\n this.updateDisplayedSports()\n }\n }\n\n updateDisplayedSports() {\n const { sports } = this.props\n this.setState({ displayedSports: sports.map(sport => sport.id) })\n }\n\n handleOnChangeDuration(e) {\n const duration = e.target.name\n\n const date = new Date()\n const start =\n duration === 'year'\n ? startOfYear(subYears(date, 9))\n : duration === 'week'\n ? startOfMonth(subMonths(date, 2))\n : startOfMonth(subMonths(date, 11))\n const end =\n duration === 'year'\n ? endOfYear(date)\n : duration === 'week'\n ? endOfWeek(date)\n : endOfMonth(date)\n this.setState({ statsParams: { duration, end, start, type: 'by_time' } })\n }\n\n handleOnChangeSports(sportId) {\n const { displayedSports } = this.state\n if (displayedSports.includes(sportId)) {\n this.setState({\n displayedSports: displayedSports.filter(s => s !== sportId),\n })\n } else {\n this.setState({ displayedSports: displayedSports.concat([sportId]) })\n }\n }\n\n handleOnClickArrows(forward) {\n const { start, end, duration } = this.state.statsParams\n let newStart, newEnd\n if (forward) {\n newStart =\n duration === 'year'\n ? startOfYear(subYears(start, 1))\n : duration === 'week'\n ? startOfWeek(subWeeks(start, 1))\n : startOfMonth(subMonths(start, 1))\n newEnd =\n duration === 'year'\n ? endOfYear(subYears(end, 1))\n : duration === 'week'\n ? endOfWeek(subWeeks(end, 1))\n : endOfMonth(subMonths(end, 1))\n } else {\n newStart =\n duration === 'year'\n ? startOfYear(addYears(start, 1))\n : duration === 'week'\n ? startOfWeek(addWeeks(start, 1))\n : startOfMonth(addMonths(start, 1))\n newEnd =\n duration === 'year'\n ? endOfYear(addYears(end, 1))\n : duration === 'week'\n ? endOfWeek(addWeeks(end, 1))\n : endOfMonth(addMonths(end, 1))\n }\n this.setState({\n statsParams: { duration, end: newEnd, start: newStart, type: 'by_time' },\n })\n }\n\n render() {\n const { displayedSports, statsParams } = this.state\n const { sports, t, user } = this.props\n const translatedSports = translateSports(\n sports.filter(sport => user.sports_list.includes(sport.id)),\n t\n )\n return (\n <>\n \n FitTrackee - {t('statistics:Statistics')}\n \n
\n
\n
{t('statistics:Statistics')}
\n \n
\n
\n

\n this.handleOnClickArrows(true)}\n />\n

\n
\n
\n {durations.map(d => (\n
\n \n
\n ))}\n
\n
\n

\n this.handleOnClickArrows(false)}\n />\n

\n
\n
\n \n
\n {translatedSports.map(sport => (\n \n ))}\n
\n
\n
\n {user.nb_activities === 0 && }\n
\n \n )\n }\n}\n\nexport default withTranslation()(\n connect(state => ({\n sports: state.sports.data,\n user: state.user,\n }))(Statistics)\n)\n","import React from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { Helmet } from 'react-helmet'\nimport { Link } from 'react-router-dom'\n\nimport { history } from '../../index'\n\nexport default function Form(props) {\n const { t } = useTranslation()\n const pageTitle = `user:${props.formType\n .charAt(0)\n .toUpperCase()}${props.formType.slice(1)}`\n return (\n
\n \n FitTrackee - {t(`user:${props.formType}`)}\n \n

{t(pageTitle)}

\n
\n
\n
\n
\n
\n {props.formType === 'register' && !props.isRegistrationAllowed ? (\n
\n
Registration is disabled.
\n
\n history.go(-1)}\n >\n Back\n \n
\n
\n ) : (\n <>\n \n props.handleUserFormSubmit(event, props.formType)\n }\n >\n {props.formType === 'register' && (\n
\n \n
\n )}\n {props.formType !== 'password reset' && (\n
\n \n
\n )}\n {props.formType !== 'reset your password' && (\n <>\n
\n \n
\n {props.formType !== 'login' && (\n
\n \n
\n )}\n \n )}\n \n \n

\n {props.formType === 'login' && (\n \n {t('user:Forgot password?')}\n \n )}\n

\n \n )}\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport { Redirect } from 'react-router-dom'\n\nimport Form from './Form'\nimport Message from '../Common/Message'\nimport { handleUserFormSubmit } from '../../actions/user'\nimport { isLoggedIn } from '../../utils'\n\nclass UserForm extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n formData: {\n username: '',\n email: '',\n password: '',\n password_conf: '',\n },\n }\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.location.pathname !== this.props.location.pathname) {\n this.emptyForm()\n }\n }\n\n emptyForm() {\n const { formData } = this.state\n Object.keys(formData).map(k => (formData[k] = ''))\n this.setState(formData)\n }\n\n onHandleFormChange(e) {\n const { formData } = this.state\n formData[e.target.name] = e.target.value\n this.setState(formData)\n }\n\n render() {\n const {\n formType,\n isRegistrationAllowed,\n message,\n messages,\n onHandleUserFormSubmit,\n t,\n } = this.props\n const { formData } = this.state\n const { token } = this.props.location.query\n return (\n
\n {isLoggedIn() || (formType === 'password reset' && !token) ? (\n \n ) : (\n
\n \n this.onHandleFormChange(event)}\n handleUserFormSubmit={event => {\n event.preventDefault()\n if (formType === 'password reset') {\n formData.token = token\n }\n onHandleUserFormSubmit(formData, formType)\n }}\n />\n
\n )}\n
\n )\n }\n}\nexport default withTranslation()(\n connect(\n state => ({\n isRegistrationAllowed: state.application.config.is_registration_enabled,\n location: state.router.location,\n message: state.message,\n messages: state.messages,\n }),\n dispatch => ({\n onHandleUserFormSubmit: (formData, formType) => {\n formType =\n formType === 'password reset'\n ? 'password/update'\n : formType === 'reset your password'\n ? 'password/reset-request'\n : formType\n dispatch(handleUserFormSubmit(formData, formType))\n },\n })\n )(UserForm)\n)\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport CustomModal from '../Common/CustomModal'\nimport ProfileDetail from './ProfileDetail'\nimport { getOrUpdateData } from '../../actions'\nimport { deleteUser } from '../../actions/user'\n\nclass UserProfile extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayModal: false,\n }\n }\n\n componentDidMount() {\n this.props.loadUser(this.props.match.params.userName)\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.match.params.userName !== this.props.match.params.userName) {\n this.props.loadUser(this.props.match.params.userName)\n }\n }\n\n displayModal(value) {\n this.setState(prevState => ({\n ...prevState,\n displayModal: value,\n }))\n }\n\n render() {\n const { t, currentUser, onDeleteUser, users } = this.props\n const { displayModal } = this.state\n const [user] = users\n const editable = user ? currentUser.username === user.username : false\n return (\n
\n {displayModal && (\n {\n onDeleteUser(user.username)\n this.displayModal(false)\n }}\n close={() => this.displayModal(false)}\n />\n )}\n {user && (\n this.displayModal(e)}\n t={t}\n user={user}\n />\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n currentUser: state.user,\n users: state.users.data,\n }),\n dispatch => ({\n onDeleteUser: username => {\n dispatch(deleteUser(username, true))\n },\n loadUser: userName => {\n dispatch(getOrUpdateData('getData', 'users', { username: userName }))\n },\n })\n )(UserProfile)\n)\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { Route, Switch } from 'react-router-dom'\n\nimport './App.css'\nimport Admin from './Admin'\nimport Activity from './Activity'\nimport Activities from './Activities'\nimport CurrentUserProfile from './User/CurrentUserProfile'\nimport Dashboard from './Dashboard'\nimport Footer from './Footer'\nimport Logout from './User/Logout'\nimport NavBar from './NavBar'\nimport NotFound from './Others/NotFound'\nimport PasswordReset from './User/PasswordReset'\nimport ProfileEdit from './User/ProfileEdit'\nimport Statistics from './Statistics'\nimport UserForm from './User/UserForm'\nimport UserProfile from './User/UserProfile'\nimport { getAppData } from '../actions/application'\n\nclass App extends React.Component {\n constructor(props) {\n super(props)\n this.props = props\n }\n componentDidMount() {\n this.props.loadAppConfig()\n }\n\n render() {\n return (\n
\n \n \n \n }\n />\n }\n />\n }\n />\n }\n />\n }\n />\n }\n />\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n )\n }\n}\nexport default connect(\n () => ({}),\n dispatch => ({\n loadAppConfig: () => {\n dispatch(getAppData('config'))\n },\n })\n)(App)\n","import React from 'react'\nimport { Provider } from 'react-redux'\nimport { ConnectedRouter } from 'connected-react-router'\n\nexport default function Root({ store, history, children }) {\n return (\n \n {children}\n \n )\n}\n","// In production, we register a service worker to serve assets from local cache.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\n// cached resources are updated in the background.\n\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\n// This link also includes instructions on opting out of this behavior.\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n)\n\nexport default function register() {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location)\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets;\n // see https://github.com/facebookincubator/create-react-app/issues/2374\n return\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`\n\n if (isLocalhost) {\n // This is running on localhost.\n // Lets check if a service worker still exists or not.\n checkValidServiceWorker(swUrl)\n } else {\n // Is not local host. Just register service worker\n registerValidSW(swUrl)\n }\n })\n }\n}\n\nfunction registerValidSW(swUrl) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the old content will have been purged and\n // the fresh content will have been added to the cache.\n // It's the perfect time to display a \"New content is\n // available; please refresh.\" message in your web app.\n // eslint-disable-next-line no-console\n console.log('New content is available; please refresh.')\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n // eslint-disable-next-line no-console\n console.log('Content is cached for offline use.')\n }\n }\n }\n }\n })\n .catch(error => {\n console.error('Error during service worker registration:', error)\n })\n}\n\nfunction checkValidServiceWorker(swUrl) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n if (\n response.status === 404 ||\n response.headers.get('content-type').indexOf('javascript') === -1\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload()\n })\n })\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl)\n }\n })\n .catch(() => {\n // eslint-disable-next-line no-console\n console.log(\n 'No internet connection found. App is running in offline mode.'\n )\n })\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister()\n })\n }\n}\n","const emptyData = {\n data: [],\n}\n\nexport default {\n language: 'en',\n message: '',\n messages: [],\n user: {\n isAuthenticated: false,\n },\n activities: {\n ...emptyData,\n },\n application: {\n statistics: {},\n config: {\n gpx_limit_import: null,\n is_registration_enabled: null,\n max_single_file_size: null,\n max_users: null,\n max_zip_file_size: null,\n registration: null,\n },\n },\n calendarActivities: {\n ...emptyData,\n },\n chartData: [],\n // check if storing gpx content is OK\n gpx: null,\n loading: false,\n records: {\n ...emptyData,\n },\n sports: {\n ...emptyData,\n },\n statistics: {\n data: {},\n },\n users: {\n ...emptyData,\n },\n}\n","const routesWithoutAuthentication = [\n '/login',\n '/register',\n '/password-reset',\n '/password-reset/request',\n '/password-reset/sent',\n '/updated-password',\n]\n\nconst updatePath = (toPath, newPath) => {\n if (typeof toPath === 'string' || toPath instanceof String) {\n toPath = newPath\n } else {\n toPath.pathname = newPath\n }\n return toPath\n}\n\nconst pathInterceptor = toPath => {\n if (\n !window.localStorage.authToken &&\n !routesWithoutAuthentication.includes(toPath.pathname)\n ) {\n toPath = updatePath(toPath, '/login')\n }\n if (\n window.localStorage.authToken &&\n routesWithoutAuthentication.includes(toPath.pathname)\n ) {\n toPath = updatePath(toPath, '/')\n }\n return toPath\n}\n\nexport const historyEnhancer = originalHistory => {\n originalHistory.location = pathInterceptor(originalHistory.location)\n return {\n ...originalHistory,\n push: (path, ...args) =>\n originalHistory.push(pathInterceptor(path), ...args),\n replace: (path, ...args) =>\n originalHistory.replace(pathInterceptor(path), ...args),\n }\n}\n","import { connectRouter } from 'connected-react-router'\nimport { combineReducers } from 'redux'\n\nimport initial from './initial'\n\nconst handleDataAndError = (state, type, action) => {\n if (action.target !== type) {\n return state\n }\n if (action.type === 'SET_DATA') {\n return {\n ...state,\n data: action.data[action.target],\n }\n }\n if (action.type === 'SET_PAGINATED_DATA') {\n return {\n ...state,\n data: action.data[action.target],\n pagination: action.pagination,\n }\n }\n return state\n}\n\nconst activities = (state = initial.activities, action) => {\n switch (action.type) {\n case 'LOGOUT':\n return initial.activities\n case 'PUSH_ACTIVITIES':\n return {\n ...state,\n data: state.data.concat(action.activities),\n }\n case 'REMOVE_ACTIVITY':\n return {\n ...state,\n data: state.data.filter(activity => activity.id !== action.activityId),\n }\n default:\n return handleDataAndError(state, 'activities', action)\n }\n}\n\nconst application = (state = initial.application, action) => {\n if (action.type === 'SET_APP_CONFIG') {\n return {\n ...state,\n config: action.data,\n }\n }\n if (action.type === 'SET_APP_STATS') {\n return {\n ...state,\n statistics: action.data,\n }\n }\n return state\n}\n\nconst calendarActivities = (state = initial.calendarActivities, action) => {\n switch (action.type) {\n case 'LOGOUT':\n return initial.calendarActivities\n case 'UPDATE_CALENDAR':\n return {\n ...state,\n data: action.activities,\n }\n default:\n return handleDataAndError(state, 'calendarActivities', action)\n }\n}\n\nconst chartData = (state = initial.chartData, action) => {\n if (action.type === 'SET_CHART_DATA') {\n return action.chartData\n }\n return state\n}\n\nconst gpx = (state = initial.gpx, action) => {\n if (action.type === 'SET_GPX') {\n return action.gpxContent\n }\n return state\n}\n\nconst language = (state = initial.language, action) => {\n if (action.type === 'SET_LANGUAGE') {\n return action.language\n }\n return state\n}\n\nconst loading = (state = initial.loading, action) => {\n if (action.type === 'SET_LOADING') {\n return action.loading\n }\n return state\n}\n\nconst message = (state = initial.message, action) => {\n switch (action.type) {\n case 'AUTH_ERROR':\n case 'PROFILE_ERROR':\n case 'PROFILE_UPDATE_ERROR':\n case 'PICTURE_ERROR':\n case 'SET_ERROR':\n return action.message\n case 'LOGOUT':\n case 'PROFILE_SUCCESS':\n case 'SET_RESULTS':\n case '@@router/LOCATION_CHANGE':\n return ''\n default:\n return state\n }\n}\n\nconst messages = (state = initial.messages, action) => {\n switch (action.type) {\n case 'AUTH_ERRORS':\n return action.messages\n case 'LOGOUT':\n case 'PROFILE_SUCCESS':\n case '@@router/LOCATION_CHANGE':\n return []\n default:\n return state\n }\n}\n\nconst records = (state = initial.records, action) => {\n if (action.type === 'LOGOUT') {\n return initial.records\n }\n return handleDataAndError(state, 'records', action)\n}\n\nconst sports = (state = initial.sports, action) => {\n if (action.type === 'UPDATE_SPORT_DATA') {\n return {\n ...state,\n data: state.data.map(sport => {\n if (sport.id === action.data.id) {\n sport.is_active = action.data.is_active\n }\n return sport\n }),\n }\n }\n return handleDataAndError(state, 'sports', action)\n}\n\nconst users = (state = initial.users, action) => {\n if (action.type === 'UPDATE_USER_DATA') {\n return {\n ...state,\n data: state.data.map(user => {\n if (user.username === action.data.username) {\n user.admin = action.data.admin\n }\n return user\n }),\n }\n }\n return handleDataAndError(state, 'users', action)\n}\n\nconst user = (state = initial.user, action) => {\n switch (action.type) {\n case 'AUTH_ERROR':\n case 'PROFILE_ERROR':\n case 'LOGOUT':\n window.localStorage.removeItem('authToken')\n return initial.user\n case 'PROFILE_SUCCESS':\n return action.profil\n default:\n return state\n }\n}\n\nconst statistics = (state = initial.statistics, action) => {\n if (action.type === 'LOGOUT') {\n return initial.statistics\n }\n return handleDataAndError(state, 'statistics', action)\n}\n\nexport default history =>\n combineReducers({\n activities,\n application,\n calendarActivities,\n chartData,\n gpx,\n language,\n loading,\n message,\n messages,\n records,\n router: connectRouter(history),\n sports,\n statistics,\n user,\n users,\n })\n","/* eslint-disable react/jsx-filename-extension */\nimport { createBrowserHistory } from 'history'\nimport React from 'react'\nimport { I18nextProvider } from 'react-i18next'\nimport ReactDOM from 'react-dom'\nimport { routerMiddleware } from 'connected-react-router'\nimport { applyMiddleware, compose, createStore } from 'redux'\nimport thunk from 'redux-thunk'\n\nimport i18n from './i18n'\nimport App from './components/App'\nimport Root from './components/Root'\nimport registerServiceWorker from './registerServiceWorker'\nimport createRootReducer from './reducers'\nimport { loadProfile } from './actions/user'\nimport { historyEnhancer } from './utils/history'\n\nexport const history = historyEnhancer(createBrowserHistory())\n\nhistory.listen(() => {\n window.scrollTo(0, 0)\n})\n\nexport const rootNode = document.getElementById('root')\n\nexport const store = createStore(\n createRootReducer(history),\n window.__STATE__, // Server state\n (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose)(\n applyMiddleware(routerMiddleware(history), thunk)\n )\n)\n\nif (window.localStorage.authToken !== null) {\n store.dispatch(loadProfile())\n}\n\nReactDOM.render(\n \n \n \n \n ,\n rootNode\n)\nregisterServiceWorker()\n"],"sourceRoot":""} \ No newline at end of file diff --git a/fittrackee/dist/static/js/main.c96409fd.chunk.js b/fittrackee/dist/static/js/main.c96409fd.chunk.js new file mode 100644 index 00000000..a680aa36 --- /dev/null +++ b/fittrackee/dist/static/js/main.c96409fd.chunk.js @@ -0,0 +1,2 @@ +(this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[]).push([[0],{198:function(e){e.exports=JSON.parse('{"Workouts":"Workouts","Workout":"Workout","Workout Date":"Workout Date","Add a workout":"Add a workout","Are you sure you want to delete this workout?":"Are you sure you want to delete this workout?","Ave. speed":"Ave. speed","Ascent":"Ascent","Average speed":"Average speed","Chart":"Chart","data from gpx, without any cleaning":"data from gpx, without any cleaning","Date":"Date","Delete workout":"Delete workout","Descent":"Descent","Distance":"Distance","distance":"distance","Duration":"Duration","duration":"duration","Edit a workout":"Edit a workout","Edit workout":"Edit workout","elevation":"elevation","End":"End","Farest distance":"Farest distance","Filter":"Filter","From":"From","gpxFile":"gpx file","Longest duration":"Longest duration","Max. altitude":"Max. altitude","Max. speed":"Max. speed","Min. altitude":"Min. altitude","no folder inside":"no folder inside","files max":"files max","max size":"max size","No data to display":"No data to display","No Map":"No Map","No next workout":"No next workout","No next segment":"No next segment","No notes":"No notes","No previous workout":"No previous workout","No previous segment":"No previous segment","Notes":"Notes","pauses":"pauses","Personal records":"Personal records","See next workout":"See next workout","See next segment":"See next segment","See previous workout":"See previous workout","See previous segment":"See previous segment","segment":"segment","Segments":"Segments","speed":"speed","Start":"Start","Title":"Title","To":"To","total duration":"total duration","with gpx file":"with gpx file","without gpx file":"without gpx file","zipFile":"or zip file containing gpx files"}')},199:function(e){e.exports=JSON.parse('{"Actions":"Actions","Active":"Active","workouts exist":"workouts exist","Add admin rights":"Add admin rights","Add/remove admin rights, delete user account.":"Add/remove admin rights, delete user account.","Administration":"Administration","Application":"Application","Application configuration":"Application configuration","Back":"Back","Disable":"Disable","Enable":"Enable","Enable/disable sports.":"Enable/disable sports.","FitTrackee administration":"FitTrackee administration","id":"id","if 0, no limitation":"if 0, no limitation","Image":"Image","Label":"Label","Max. number of active users":"Max. number of active users","Max. files of zip archive":"Max. files of zip archive","Max. size of uploaded files":"Max. size of uploaded files","Max. size of uploaded files (in Mb)":"Max. size of uploaded files (in Mb)","Max. size of zip archive":"Max. size of zip archive","Max. size of zip archive (in Mb)":"Max. size of zip archive (in Mb)","Registration is currently disabled.":"Registration is currently disabled.","Registration is currently enabled.":"Registration is currently enabled.","Remove admin rights":"Remove admin rights","Sports":"Sports","Update application configuration (maximum number of registered users, maximum files size).":"Update application configuration (maximum number of registered users, maximum files size).","uploads":"uploads","user":"user","Users":"Users","users":"users"}')},200:function(e){e.exports=JSON.parse('{"workouts count":"workouts count","Add workout":"Add workout","admin rights":"admin rights","ascending":"ascending","Back":"Back","Back to home":"Back to home","Cancel":"Cancel","Confirmation":"Confirmation","Dashboard":"Dashboard","descending":"descending","Edit":"Edit","day":"day","days":"days","Next":"Next","No":"No","no":"no","No records.":"No records.","No workouts.":"No workouts.","Page not found":"Page not found","Previous":"Prev","registration date":"registration date","Sort":"Sort","Sort by":"Sort by","Sport":"Sport","sport":"sport","Sports":"Sports","sports":"sports","Statistics":"Statistics","Submit":"Submit","to":"to","user name":"user name","Workout":"Workout","Workouts":"Workouts","workout":"workout","workouts":"workouts","Yes":"Yes","yes":"yes"}')},201:function(e){e.exports=JSON.parse('{"Personal records":"Personal records","This month":"This month","Upload one !":"Upload one !"}')},202:function(e){e.exports=JSON.parse('{"3 to 12 characters required for username.":"3 to 12 characters required for username.","8 characters required for password.":"8 characters required for password.","An error occurred. Please contact the administrator.":"An error occurred. Please contact the administrator.","workouts":"workouts","Error during picture deletion.":"Error during picture deletion.","Error during picture update.":"Error during picture update.","Error during picture update, file size exceeds max size.":"Error during picture update, file size exceeds max size.","Error. Registration is disabled.":"Error. Registration is disabled.","Error. Please try again or contact the administrator.":"Error. Please try again or contact the administrator.","File extension not allowed.":"File extension not allowed.","File size is greater than the allowed size":"File size is greater than the allowed size","Incorrect id":"Incorrect id","Invalid credentials.":"Invalid credentials.","Invalid payload.":"Invalid payload.","Invalid token. Please log in again.":"Invalid token. Please log in again.","No file part.":"No file part.","No picture.":"No picture.","No selected file.":"No selected file.","no correct file.":"no correct file.","no gpx file for this workout":"no gpx file for this workout","Password and password confirmation don\'t match.":"Password and password confirmation don\'t match.","Provide a valid auth token":"Provide a valid auth token","records":"records","Signature expired. Please log in again.":"Signature expired. Please log in again.","Sorry. That user already exists.":"Sorry. That user already exists.","Sport can not be disabled, workouts exist.":"Sport can not be disabled, workouts exist.","Sport does not exist.":"Sport does not exist.","sports":"sports","statistics":"statistiques","User does not exist.":"User does not exist.","Valid email must be provided.\\n":"Valid email must be provided.","You can not delete your account, no other user has admin rights.":"You can not delete your account, no other user has admin rights.","You do not have permissions.":"You do not have permissions."}')},203:function(e){e.exports=JSON.parse('{"Cycling (Sport)":"Cycling (Sport)","Cycling (Transport)":"Cycling (Transport)","Hiking":"Hiking","Mountain Biking":"Mountain Biking","Running":"Running","Walking":"Walking"}')},204:function(e){e.exports=JSON.parse('{"workouts":"workouts","distance":"distance","duration":"duration","month":"month","Statistics":"Statistics","year":"year","week":"week"}')},205:function(e){e.exports=JSON.parse('{"Admin":"Admin","Are you sure you want to delete this account? All data will be deleted, this cannot be undone.":"Are you sure you want to delete this account? All data will be deleted, this cannot be undone.","Are you sure you want to delete your account? All data will be deleted, this cannot be undone.":"Are you sure you want to delete your account? All data will be deleted, this cannot be undone.","Bio":"Bio","Birth Date":"Birth Date","Check your email. If your address is in our database, you\'ll received an email with a link to reset your password.":"Check your email. If your address is in our database, you\'ll received an email with a link to reset your password.","Delete my account":"Delete my account","Delete picture":"Delete picture","Delete user account":"Delete user account","Edit Profile":"Edit Profile","Email":"Email","Enter a username":"Enter a username","Enter an email address":"Enter an email address","Enter a password":"Enter a password","Enter the password confirmation":"Enter the password confirmation","First day of week":"First day of week","First Name":"First Name","Forgot password?":"Forgot password?","Invalid token. Please request a new token.":"Invalid token. Please request a new token.","Language":"Language","Last Name":"Last Name","Location":"Location","loggedOut":"You are now logged out. Click <1>here to log back in.","Login":"Login","login":"login","Logout":"Logout","Monday":"Monday","Password":"Password","Password Confirmation":"Password Confirmation","Password reset":"Password reset","password reset":"password reset","Profile":"Profile","Profile Edition":"Profile Edition","Register":"Register","register":"register","Registration Date":"Registration Date","Reset your password":"Reset your password","reset your password":"reset your password","Send":"Send","Sunday":"Sunday","Timezone":"Timezone","updatedPasswordText":"Your password have been updated. Click <1>here to log in.","Username":"Username"}')},206:function(e){e.exports=JSON.parse('{"Workouts":"S\xe9ances","Workout":"S\xe9ance","Workout Date":"Date de l\'s\xe9ance","Add a workout":"Ajouter une s\xe9ance","Are you sure you want to delete this workout?":"Etes-vous s\xfbr de vouloir supprimer cette s\xe9ance ?","Ave. speed":"Vitesse moyenne","Ascent":"D\xe9nivel\xe9 positif","Average speed":"Vitesse moyenne","Chart":"Analyse","data from gpx, without any cleaning":"donn\xe9es issues du fichier gpx, sans correction","Date":"Date","Delete workout":"Supprimer l\'s\xe9ance","Descent":"D\xe9nivel\xe9 n\xe9gatif","Distance":"Distance","distance":"distance","Duration":"Dur\xe9e","duration":"dur\xe9e","Edit a workout":"Editer une s\xe9ance","Edit workout":"Editer une workout","elevation":"altitude","End":"Arriv\xe9e","Farest distance":"Distance la + longue","Filter":"Filtrer","From":"A partir de","gpxFile":"fichier gpx","Longest duration":"Dur\xe9e la + longue","Max. altitude":"Altitude max","Max. speed":"Vitesse max","Min. altitude":"Altitude min","no folder inside":"pas de r\xe9pertoire","files max":" fichiers max","max size":"taille max","No data to display":"Pas de donn\xe9es \xe0 afficher","No Map":"Pas de carte","No next workout":"Pas d\'s\xe9ance suivante","No next segment":"Pas de segment suivant","No notes":"Pas de notes","No previous workout":"Pas d\'s\xe9ance pr\xe9c\xe9dente","No previous segment":"Pas de segment pr\xe9c\xe9dent","Notes":"Notes","pauses":"pauses","Personal records":"Records personnels","See next workout":"Voir l\'s\xe9ance suivante","See next segment":"Voir le segment suivant","See previous workout":"Voir l\'s\xe9ance pr\xe9c\xe9dente","See previous segment":"Voir le segment pr\xe9c\xe9dent","segment":"segment","Segments":"Segments","Start":"D\xe9part","speed":"vitesse","Title":"Titre","To":"Jusqu\'au","total duration":"dur\xe9e totale","with gpx file":"avec un fichier gpx","without gpx file":"sans fichier gpx","zipFile":"ou un fichier zip contenant des fichiers gpx"}')},207:function(e){e.exports=JSON.parse('{"Actions":"Actions","Active":"Active","Add admin rights":"Ajouter des droits d\'admin","Add/remove admin rights, delete user account.":"Ajouter/retirer des droits d\'adminsitration, supprimer des comptes utilisateurs.","Administration":"Administration","workouts exist":"des s\xe9ances existent","Application":"Application","Application configuration":"Configuration de l\'application","Back":"Retour","Disable":"d\xe9sactiver","Enable":"activer","Enable/disable sports.":"Activer/d\xe9sactiver des sports.","FitTrackee administration":"Administration de FitTrackee","id":"id","if 0, no limitation":"si \xe9gal \xe0 0, pas limite d\'inscription","Image":"Image","Label":"Label","Max. number of active users":"Nombre maximum d\'utilisateurs actifs","Max. files of zip archive":"Nombre max. de fichiers dans une archive zip","Max. size of uploaded files":"Taille max. des fichiers","Max. size of uploaded files (in Mb)":"Taille max. des fichiers (en Mo)","Max. size of zip archive":"Taille max. des archives zip","Max. size of zip archive (in Mb)":"Taille max. des archives zip (en Mo)","Registration is currently disabled.":"Les inscriptions sont actuellement d\xe9sactiv\xe9es.","Registration is currently enabled.":"Les inscriptions sont actuellement activ\xe9es.","Remove admin rights":"Retirer des droits d\'admin","Sports":"Sports","Update application configuration (maximum number of registered users, maximum files size).":"Configurer l\'application (nombre maximum d\'utilisateurs inscrits, taille maximale des fichers).","uploads":"fichiers","user":"user","Users":"Utilisateurs","users":"utilisateurs"}')},208:function(e){e.exports=JSON.parse('{"workouts count":"nombre d\'s\xe9ances","Add workout":"Ajouter une s\xe9ance","admin rights":"droits d\'admin","ascending":"ascendant","Back":"Revenir \xe0 la page pr\xe9c\xe9dente","Back to home":"Retour \xe0 l\'accueil","Cancel":"Annuler","Confirmation":"Confirmation","Dashboard":"Tableau de Bord","descending":"descendant","Edit":"Modifier","day":"jour","days":"jours","Next":"Page suivante","No":"Non","no":"non","No records.":"Pas de records.","No workouts.":"Pas d\'s\xe9ances.","Page not found":"Page introuvable","Previous":"Page pr\xe9c\xe9dente","registration date":"date d\'inscription","Sort":"Tri","Sort by":"Trier par","Sport":"Sport","sport":"sport","Sports":"Sports","sports":"sports","Statistics":"Statistiques","Submit":"Valider","to":"\xe0","user name":"utilisateur","Workout":"S\xe9ance","Workouts":"S\xe9ances","workout":"s\xe9ance","workouts":"s\xe9ances","Yes":"Oui","yes":"oui"}')},209:function(e){e.exports=JSON.parse('{"Personal records":"Mes records","This month":"Ce mois","Upload one !":"Ajoutez votre premi\xe8re s\xe9ance !"}')},210:function(e){e.exports=JSON.parse('{"3 to 12 characters required for username.":"3 \xe0 12 caract\xe8res requis pour le nom.","8 characters required for password.":"8 caract\xe8res minimum pour le mot de passe.","An error occurred. Please contact the administrator.":"Une erreur s\'est produite. Merci de contacter l\'administrateur.","workouts":"s\xe9ances","Error during picture deletion.":"Erreur lors de la suppression de l\'image.","Error during picture update.":"Erreur lors de la mise \xe0 jour de l\'image.","Error during picture update, file size exceeds max size.":"Erreur lors de la mise \xe0 jour de l\'image, la taille du ficher d\xe9passe la taille maximum autoris\xe9e","Error. Registration is disabled.":"Erreur. L\'inscription est d\xe9sactiv\xe9e.","Error. Please try again or contact the administrator.":"Erreur. Veuillez r\xe9essayer ou contacter l\'administrateur","File extension not allowed.":"Extension de fichier non autoris\xe9e.","File size is greater than the allowed size":"La taille du fichier est sup\xe9rieure \xe0 la limite autoris\xe9e","Incorrect id":"Id incorrect","Invalid credentials.":"Identifiants invalides.","Invalid payload.":"Donn\xe9es incorrectes.","Invalid token. Please log in again.":"Jeton invalide. Merci de vous reconnecter.","No file part.":"Pas de fichier fourni.","No picture.":"Pas d\'image.","No selected file.":"Pas de fichier s\xe9lectionn\xe9.","no correct file.":"fichier incorrect","no gpx file for this workout":"pas de fichier gpx pour cette s\xe9ance","Password and password confirmation don\'t match.":"Les mots de passe saisis sont diff\xe9rents.","Provide a valid auth token":"Merci de fournir un jeton valide","records":"records","Signature expired. Please log in again.":"Signature expir\xe9e. Merci de vous reconnecter.","Sorry. That user already exists.":"D\xe9sol\xe9. Cet utilisateur existe d\xe9j\xe0.","Sport can not be disabled, workouts exist.":"Le sport ne peut \xeatre d\xe9sactiv\xe9, des s\xe9ancees existent","Sport does not exist.":"Le sport n\'existe pas.","sports":"sports","statistics":"statistics","User does not exist.":"L\'utilisateur n\'existe pas.","Valid email must be provided.\\n":"L\'email fourni n\'est pas valide.","You can not delete your account, no other user has admin rights.":"Vous ne pouvez pas supprimer votre compte, aucun autre utilisateur n\'a des droits d\'administration.","You do not have permissions.":"Vous n\'avez pas les permissions n\xe9cessaires."}')},211:function(e){e.exports=JSON.parse('{"Cycling (Sport)":"V\xe9lo (Sport)","Cycling (Transport)":"V\xe9lo (Transport)","Hiking":"Randonn\xe9e","Mountain Biking":"VTT","Running":"Course","Walking":"Marche"}')},212:function(e){e.exports=JSON.parse('{"workouts":"s\xe9ances","distance":"distance","duration":"dur\xe9e","month":"mois","Statistics":"Statistiques","year":"ann\xe9e","week":"semaine"}')},213:function(e){e.exports=JSON.parse('{"Admin":"Admin","Are you sure you want to delete this account? All data will be deleted, this cannot be undone.":"Etes-vous s\xfbr de vouloir supprimer ce compte ? Toutes les donn\xe9es seront d\xe9finitivement effac\xe9s.","Are you sure you want to delete your account? All data will be deleted, this cannot be undone.":"Etes-vous s\xfbr de vouloir supprimer votre compte ? Toutes les donn\xe9es seront d\xe9finitivement effac\xe9s.","Bio":"Bio","Birth Date":"Date de naissance","Check your email. If your address is in our database, you\'ll received an email with a link to reset your password.":"V\xe9rifiez vore boite mail. Si vote adresse est dans notre base de donn\xe9es, vous recevrez un email avec un lien pour r\xe9initialiser votre mot de passe","Delete my account":"Supprimer mon compte","Delete picture":"Supprimer l\'image","Delete user account":"Supprimer le compte","Edit Profile":"Editer le profil","Email":"Email","Enter a username":"Saisir un nom","Enter an email address":"Saisir une adresse e-mail","Enter a password":"Saisir un mot de passe","Enter the password confirmation":"Confirmer le mot de passe","First day of week":"Premier jour de la semaine","First Name":"Pr\xe9nom","Forgot password?":"Mot de passe oubli\xe9 ?","Invalid token. Please request a new token.":"Token invalid. Veuillez demander un nouveau token.","Language":"Langue","Last Name":"Nom","Location":"Lieu","loggedOut":"Vous \xeates d\xe9connect\xe9. Cliquez <1>ici pour vous reconnecter.","Login":"Se connecter","login":"se connecter","Logout":"Se d\xe9connecter","Monday":"Lundi","Password":"Mot de passe","Password Confirmation":"Confirmation du mot de passe","Password reset":"R\xe9initialiser votre mot de passe","password reset":"r\xe9initialiser votre mot de passe","Profile":"Profil","Profile Edition":"Edition du profil","Register":"S\'inscrire","register":"s\'inscrire","Registration Date":"Date d\'inscription","Reset your password":"R\xe9initialiser votre mot de passe","reset your password":"r\xe9initialiser votre mot de passe","Send":"Envoyer","Sunday":"Dimanche","Timezone":"Fuseau horaire","updatedPasswordText":"Votre mot de passe a \xe9t\xe9 mis \xe0 jour. Cliquez <1>ici pour vous connecter.","Username":"Nom d\'utilisateur"}')},273:function(e,t,a){},281:function(e,t){},463:function(e,t,a){"use strict";a.r(t),a.d(t,"history",(function(){return Ws})),a.d(t,"rootNode",(function(){return qs})),a.d(t,"store",(function(){return Bs}));var s=a(1),r=a(29),n=a(2),o=a.n(n),c=a(483),i=a(53),l=a.n(i),d=a(194),u=a(57),m=a(195),j=a(81),p=a(196),h=a(197),b={en:{workouts:a(198),administration:a(199),common:a(200),dashboard:a(201),messages:a(202),sports:a(203),statistics:a(204),user:a(205)},fr:{workouts:a(206),administration:a(207),common:a(208),dashboard:a(209),messages:a(210),sports:a(211),statistics:a(212),user:a(213)}};j.a.use(h.a).use(p.a).init({debug:!1,lng:"en",fallbackLng:"en",keySeparator:!1,interpolation:{escapeValue:!1},resources:b,ns:["common"],defaultNS:"common"});var O=j.a,f=a(6),x=a(7),g=a(10),v=a(9),k=a(8),w=a(19),y=(a(273),a(20)),N=a(466),_=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props,t=e.message,a=e.messages,r=e.t,n=""!==t&&t?t.split("|").length>1?"".concat(r("messages:".concat(t.split("|")[0])),": ").concat(r("messages:".concat(t.split("|")[1]))):r("messages:".concat(t)):"";return Object(s.jsxs)("div",{className:"error-message",children:[""!==n&&Object(s.jsx)("code",{children:n}),a&&a.length>0&&Object(s.jsx)("code",{children:Object(s.jsx)("ul",{children:a.map((function(e){return Object(s.jsx)("li",{children:r("messages:".concat(e.value))},e.id)}))})})]})}}]),a}(o.a.PureComponent),S=a(12),D=a(485),C=a(484),E=a(218),A=["bytes","KB","MB","GB","TB"],M=function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=Math.floor(Math.log(e)/Math.log(1024));if(!e)return t?"0 bytes":{size:0,suffix:"bytes"};var s=(e/Math.pow(1024,a)).toFixed(1),r=A[a];return t?"".concat(s).concat(r):{size:s,suffix:r}},T="/api/",P=[{key:"workouts_count",label:"workouts count"},{key:"admin",label:"admin rights"},{key:"created_at",label:"registration date"},{key:"username",label:"user name"}],F=[{key:"asc",label:"ascending"},{key:"desc",label:"descending"}],z=function(){return!!window.localStorage.authToken},R=function(e){var t={};e.noAuthorization||(t.Authorization="Bearer ".concat(window.localStorage.getItem("authToken"))),e.type&&(t["Content-Type"]=e.type);var a={method:e.method,headers:t};"application/json"===e.type&&e.body?a.body=JSON.stringify(e.body):e.body&&(a.body=e.body);var s=new Request("".concat(T).concat(e.url),a);return fetch(s).then((function(t){return"DELETE"===e.method||413===t.status?t:t.json()})).catch((function(e){return console.error(e),new Error("An error occurred. Please contact the administrator.")}))},L=function(e,t){if(!e)return"";var a=E.DateTime.fromISO(Object(D.a)(new Date(e),"yyyy-MM-dd'T'HH:mm:ss.SSSxxx")).setZone(t);return Object(C.a)(a.toFormat("yyyy-MM-dd HH:mm:ss"),"yyyy-MM-dd HH:mm:ss",new Date)},U=function(e,t){var a=e.label.toLowerCase(),s=t.label.toLowerCase();return a>s?1:a2&&void 0!==arguments[2]?arguments[2]:"common";return t.map((function(t){return Object(S.a)(Object(S.a)({},t),{},{label:e("".concat(a,":").concat(t.label))})})).sort(U)},W=function(e,t){var a=e;return t.id||"users"===e&&t.username?a="".concat(a,"/").concat(t.username?t.username:t.id):Object.keys(t).length>0&&(a+="?",Object.keys(t).filter((function(e){return t[e]})).map((function(e,s){return a+="".concat(0===s?"":"&").concat(e,"=").concat(t[e])}))),a},H=function(){function e(){Object(f.a)(this,e)}return Object(x.a)(e,null,[{key:"getData",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=W(e,t),s={url:a,method:"GET",type:"application/json"};return R(s)}},{key:"addData",value:function(e,t){return R({url:e,method:"POST",body:t,type:"application/json"})}},{key:"addDataWithFile",value:function(e,t){return R({url:e,method:"POST",body:t})}},{key:"postData",value:function(e,t){var a={url:"".concat(e).concat(t.id?"/".concat(t.id):""),method:"POST",body:t,type:"application/json"};return R(a)}},{key:"updateData",value:function(e,t){var a={url:"".concat(e).concat(t.id?"/".concat(t.id):t.username?"/".concat(t.username):""),method:"PATCH",body:t,type:"application/json"};return R(a)}},{key:"deleteData",value:function(e,t){var a={url:"".concat(e,"/").concat(t),method:"DELETE",type:"application/json"};return R(a)}}]),e}(),q=function(e,t){return{type:"SET_DATA",data:t,target:e}},B=function(e,t,a){return{type:"SET_PAGINATED_DATA",data:t,pagination:a,target:e}},V=function(e){return{type:"SET_ERROR",message:e}},G=function(e){return{type:"SET_LOADING",loading:e}},J=function(e){return{type:"UPDATE_SPORT_DATA",data:e}},K=function(e){return{type:"UPDATE_USER_DATA",data:e}},Y=function(e,t,a){var s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];return function(r){return r(G(!0)),a&&a.id&&"workouts"!==t&&isNaN(a.id)?(r(G(!1)),r(V("".concat(t,"|Incorrect id")))):(r(V("")),H[e](t,a).then((function(a){if("success"===a.status)if(s){if("users"===t&&"getData"===e)return r(B(t,a.data,a.pagination));r(q(t,a.data))}else"updateData"===e&&"sports"===t?r(J(a.data.sports[0])):"updateData"===e&&"users"===t&&r(K(a.data.users[0]));else r(V("".concat(t,"|").concat(a.message||a.status)));r(G(!1))})).catch((function(e){r(G(!1)),r(V("".concat(t,"|").concat(e)))})))}},X=function(e){return function(t){j.a.changeLanguage(e).then(t(function(e){return{type:"SET_LANGUAGE",language:e}}(e)))}},$=function(e){return{type:"SET_APP_CONFIG",data:e}},Z=function(e){return function(t){return H.getData(e).then((function(a){"success"===a.status?"config"===e?t($(a.data)):"stats/all"===e&&t({type:"SET_APP_STATS",data:a.data}):t(V("application|".concat(a.message)))})).catch((function(e){return t(V("application|".concat(e)))}))}},Q=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={formData:{},isInEdition:!1},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.initForm()}},{key:"componentDidUpdate",value:function(e){this.props.appConfig!==e.appConfig&&this.initForm()}},{key:"initForm",value:function(){var e=this.props.appConfig,t={};Object.keys(e).map((function(a){return null===e[a]?t[a]="":["max_single_file_size","max_zip_file_size"].includes(a)?t[a]=+(e[a]/1048576).toFixed(2):t[a]=e[a]})),this.setState({formData:t})}},{key:"handleFormChange",value:function(e){var t=this.state.formData;t[e.target.name]=+e.target.value,this.setState(t)}},{key:"toggleInEdition",value:function(e){e.preventDefault();var t=this.state.isInEdition;this.setState({isInEdition:!t})}},{key:"render",value:function(){var e=this,t=this.props,a=t.message,r=t.onHandleConfigFormSubmit,n=t.t,o=this.state,c=o.formData,i=o.isInEdition;return Object(s.jsxs)("div",{children:[a&&Object(s.jsx)(_,{message:a,t:n}),Object.keys(c).length>0&&Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col-md-12",children:Object(s.jsxs)("div",{className:"card",children:[Object(s.jsx)("div",{className:"card-header",children:Object(s.jsx)("strong",{children:n("administration:Application configuration")})}),Object(s.jsx)("div",{className:"card-body",children:Object(s.jsxs)("form",{className:"app-config-form ".concat(i?"":"form-disabled"),onSubmit:function(t){e.toggleInEdition(t),r(c)},children:[Object(s.jsxs)("div",{className:"form-group row",children:[Object(s.jsxs)("label",{className:"col-sm-6 col-form-label",htmlFor:"max_users",children:[n("administration:Max. number of active users"),Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-question-circle","aria-hidden":"true",title:n("administration:if 0, no limitation")})}),":"]}),Object(s.jsx)("input",{className:"col-sm-5",id:"max_users",name:"max_users",type:"number",min:"0",value:c.max_users,onChange:function(t){return e.handleFormChange(t)}})]}),Object(s.jsxs)("div",{className:"form-group row",children:[Object(s.jsxs)("label",{className:"col-sm-6 col-form-label",htmlFor:"max_single_file_size",children:[n("administration:Max. size of uploaded files (in Mb)"),":"]}),Object(s.jsx)("input",{className:"col-sm-5",id:"max_single_file_size",name:"max_single_file_size",type:"number",step:"0.1",min:"0",value:c.max_single_file_size,onChange:function(t){return e.handleFormChange(t)}})]}),Object(s.jsxs)("div",{className:"form-group row",children:[Object(s.jsxs)("label",{className:"col-sm-6 col-form-label",htmlFor:"max_zip_file_size",children:[n("administration:Max. size of zip archive (in Mb)"),":"]}),Object(s.jsx)("input",{className:"col-sm-5",id:"max_zip_file_size",name:"max_zip_file_size",type:"number",step:"0.1",min:"0",value:c.max_zip_file_size,onChange:function(t){return e.handleFormChange(t)}})]}),Object(s.jsxs)("div",{className:"form-group row",children:[Object(s.jsx)("label",{className:"col-sm-6 col-form-label",htmlFor:"gpx_limit_import",children:n("administration:Max. files of zip archive")}),Object(s.jsx)("input",{className:"col-sm-5",id:"gpx_limit_import",name:"gpx_limit_import",type:"number",min:"0",value:c.gpx_limit_import,onChange:function(t){return e.handleFormChange(t)}})]}),i?Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("input",{type:"submit",className:"btn btn-primary",value:n("common:Submit")}),Object(s.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(t){return e.toggleInEdition(t)},value:n("common:Cancel")})]}):Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("input",{type:"submit",className:"btn btn-primary",onClick:function(t){e.toggleInEdition(t)},value:n("common:Edit")}),Object(s.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Ws.push("/admin")},value:n("common:Back")})]})]})})]})})})]})}}]),a}(o.a.Component),ee=Object(k.c)((function(e){return{message:e.message}}),(function(e){return{onHandleConfigFormSubmit:function(t){var a=Object.assign({},t);a.max_single_file_size*=1048576,a.max_zip_file_size*=1048576,e(function(e){return function(t){return H.updateData("config",e).then((function(e){"success"===e.status?t($(e.data)):t(V("application|".concat(e.message)))})).catch((function(e){return t(V("application|".concat(e)))}))}}(a))}}}))(Q),te=a(15),ae=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadAppStats()}},{key:"render",value:function(){var e=this.props,t=e.appStats,a=e.t,r=M(t.uploads_dir_size,!1);return Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-users fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:t.users?t.users:0}),Object(s.jsx)("div",{children:"".concat(1===t.users?a("administration:user"):a("administration:users"))})]})]})})}),Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-tags fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:t.sports?t.sports:0}),Object(s.jsx)("div",{children:"".concat(1===t.sports?a("common:sport"):a("common:sports"))})]})]})})}),Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-calendar fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:t.workouts?t.workouts:0}),Object(s.jsx)("div",{children:"".concat(1===t.workouts?a("common:workout"):a("common:workouts"))})]})]})})}),Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-folder-open fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:r.size}),Object(s.jsxs)("div",{children:[r.suffix," (",a("administration:uploads"),")"]})]})]})})})]})}}]),a}(o.a.Component),se=Object(N.a)()(Object(k.c)((function(e){return{appStats:e.application.statistics}}),(function(e){return{loadAppStats:function(){e(Z("stats/all"))}}}))(ae));function re(e){var t=e.appConfig,a=e.t;return Object(s.jsxs)("div",{className:"card workout-card",children:[Object(s.jsx)("div",{className:"card-header",children:Object(s.jsx)("strong",{children:a("administration:Administration")})}),Object(s.jsxs)("div",{className:"card-body",children:[Object(s.jsx)(se,{}),Object(s.jsx)("br",{}),Object(s.jsxs)("dl",{className:"admin-items",children:[Object(s.jsx)("dt",{children:Object(s.jsx)(te.a,{to:{pathname:"/admin/application"},children:a("administration:Application")})}),Object(s.jsxs)("dd",{children:[a("administration:Update application configuration (maximum number of registered users, maximum files size)."),Object(s.jsx)("br",{}),Object(s.jsx)("strong",{children:a("administration:Registration is currently ".concat(t.is_registration_enabled?"enabled":"disabled","."))})]}),Object(s.jsx)("br",{}),Object(s.jsx)("dt",{children:Object(s.jsx)(te.a,{to:{pathname:"/admin/sports"},children:a("administration:Sports")})}),Object(s.jsx)("dd",{children:a("administration:Enable/disable sports.")}),Object(s.jsx)("br",{}),Object(s.jsx)("dt",{children:Object(s.jsx)(te.a,{to:{pathname:"/admin/users"},children:a("administration:Users")})}),Object(s.jsx)("dd",{children:a("administration:Add/remove admin rights, delete user account.")})]})]})]})}var ne=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadSports()}},{key:"render",value:function(){var e=this.props,t=e.message,a=e.sports,r=e.t,n=e.updateSport;return Object(s.jsxs)("div",{children:[t&&Object(s.jsx)(_,{message:t,t:r}),Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col",children:Object(s.jsxs)("div",{className:"card",children:[Object(s.jsx)("div",{className:"card-header",children:Object(s.jsx)("strong",{children:r("administration:Sports")})}),Object(s.jsxs)("div",{className:"card-body",children:[a.length>0&&Object(s.jsxs)("table",{className:"table",children:[Object(s.jsx)("thead",{children:Object(s.jsxs)("tr",{children:[Object(s.jsx)("th",{children:r("administration:id")}),Object(s.jsx)("th",{children:r("administration:Image")}),Object(s.jsx)("th",{children:r("administration:Label")}),Object(s.jsx)("th",{children:r("administration:Active")}),Object(s.jsx)("th",{children:r("administration:Actions")})]})}),Object(s.jsx)("tbody",{children:a.map((function(e){return Object(s.jsxs)("tr",{children:[Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("administration:id")}),e.id]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("administration:Image")}),Object(s.jsx)("img",{className:"admin-img",src:e.img?e.img:"/img/photo.png",alt:"sport logo"})]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("administration:Label")}),r("sports:".concat(e.label))]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("administration:Active")}),e.is_active?Object(s.jsx)("i",{className:"fa fa-check-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"}):Object(s.jsx)("i",{className:"fa fa-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"})]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("administration:Actions")}),Object(s.jsx)("input",{type:"submit",className:"btn btn-".concat(e.is_active?"dark":"primary"," btn-sm"),value:e.is_active?r("administration:Disable"):r("administration:Enable"),onClick:function(){return n(e.id,!e.is_active)}}),e.has_workouts&&Object(s.jsxs)("span",{className:"admin-message",children:[Object(s.jsx)("i",{className:"fa fa-warning custom-fa","aria-hidden":"true"}),r("administration:workouts exist")]})]})]},e.id)}))})]}),Object(s.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Ws.push("/admin/")},value:r("common:Back")})]})]})})})]})}}]),a}(o.a.Component),oe=Object(k.c)((function(e){return{message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadSports:function(){e(Y("getData","sports"))},updateSport:function(t,a){e(Y("updateData","sports",{id:t,is_active:a},!1))}}}))(ne),ce=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"getUrl",value:function(e){var t=this.props,a=t.query,s=t.pathname,r=Object.assign({},a),n=a.page?+a.page:1;switch(e){case"prev":n-=1;break;case"next":n+=1;break;default:n=+e}return r.page=n,W(s,r)}},{key:"render",value:function(){var e,t=this,a=this.props,r=a.pagination,n=a.t;return Object(s.jsx)(s.Fragment,{children:r&&Object.keys(r).length>0&&Object(s.jsx)("nav",{"aria-label":"Page navigation example",children:Object(s.jsxs)("ul",{className:"pagination justify-content-center",children:[Object(s.jsx)("li",{className:"page-item ".concat(r.has_prev?"":"disabled"),children:Object(s.jsx)(te.a,{className:"page-link",to:this.getUrl("prev"),"aria-disabled":!r.has_prev,children:n("common:Previous")})}),(e=r.pages,Array.from({length:e},(function(e,t){return t+1}))).map((function(e){return Object(s.jsx)("li",{className:"page-item ".concat(e===r.page?"active":""),children:Object(s.jsx)(te.a,{className:"page-link",to:t.getUrl(e),children:e})},e)})),Object(s.jsx)("li",{className:"page-item ".concat(r.has_next?"":"disabled"),children:Object(s.jsx)(te.a,{className:"page-link",to:this.getUrl("next"),"aria-disabled":!r.has_next,children:n("common:Next")})})]})})})}}]),a}(o.a.PureComponent),ie=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={page:null,per_page:null,order_by:"created_at",order:"asc"},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadUsers(this.initState())}},{key:"componentDidUpdate",value:function(e){e.location.query!==this.props.location.query&&this.props.loadUsers(this.props.location.query)}},{key:"initState",value:function(){var e=this.props.location.query,t={page:e.page,per_page:e.per_page,order_by:e.order_by?e.order_by:"created_at",order:e.order?e.order:"asc"};return this.setState(t),t}},{key:"updatePage",value:function(e,t){var a=Object.assign({},this.state);a[e]=t,this.setState(a);var s=W(this.props.location.pathname,a);Ws.push(s)}},{key:"render",value:function(){var e=this,t=this.props,a=t.authUser,r=t.location,n=t.message,o=t.t,c=t.pagination,i=t.updateUser,l=t.users,d=I(o,P),u=I(o,F);return Object(s.jsxs)("div",{children:[n&&Object(s.jsx)(_,{message:n,t:o}),Object(s.jsx)("div",{className:"container",children:Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col",children:Object(s.jsxs)("div",{className:"card",children:[Object(s.jsx)("div",{className:"card-header",children:Object(s.jsx)("strong",{children:o("administration:Users")})}),Object(s.jsxs)("div",{className:"card-body",children:[Object(s.jsxs)("div",{className:"row user-filters",children:[Object(s.jsx)("div",{className:"col-lg-4 col-md-6 col-sm-12",children:Object(s.jsxs)("label",{htmlFor:"order_by",children:[o("common:Sort by"),":"," ",Object(s.jsx)("select",{id:"order_by",name:"order_by",value:this.state.order_by,onChange:function(t){return e.updatePage("order_by",t.target.value)},children:d.map((function(e){return Object(s.jsx)("option",{value:e.key,children:e.label},e.key)}))})," "]})}),Object(s.jsx)("div",{className:"col-lg-4 col-md-6 col-sm-12",children:Object(s.jsxs)("label",{htmlFor:"sort",children:[o("common:Sort"),":"," ",Object(s.jsx)("select",{id:"sort",name:"sort",value:this.state.order,onChange:function(t){return e.updatePage("order",t.target.value)},children:u.map((function(e){return Object(s.jsx)("option",{value:e.key,children:e.label},e.key)}))})," "]})})]}),Object(s.jsxs)("table",{className:"table",children:[Object(s.jsx)("thead",{children:Object(s.jsxs)("tr",{children:[Object(s.jsx)("th",{children:"#"}),Object(s.jsx)("th",{children:o("user:Username")}),Object(s.jsx)("th",{children:o("user:Email")}),Object(s.jsx)("th",{children:o("user:Registration Date")}),Object(s.jsx)("th",{children:o("workouts:Workouts")}),Object(s.jsx)("th",{children:o("user:Admin")}),Object(s.jsx)("th",{children:o("administration:Actions")})]})}),Object(s.jsx)("tbody",{children:l.map((function(e){return Object(s.jsxs)("tr",{children:[Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:"#"}),!0===e.picture?Object(s.jsx)("img",{alt:"Avatar",src:"".concat(T,"users/").concat(e.username,"/picture?").concat(Date.now()),className:"img-fluid App-nav-profile-img"}):Object(s.jsx)("i",{className:"fa fa-user-circle-o fa-2x no-picture","aria-hidden":"true"})]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:o("user:Username")}),Object(s.jsx)(te.a,{to:"/users/".concat(e.username),children:e.username})]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:o("user:Email")}),e.email]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:o("user:Registration Date")}),Object(D.a)(new Date(e.created_at),"dd/MM/yyyy HH:mm")]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:o("workouts:Workouts")}),e.nb_workouts]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:o("user:Admin")}),e.admin?Object(s.jsx)("i",{className:"fa fa-check-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"}):Object(s.jsx)("i",{className:"fa fa-square-o custom-fa","aria-hidden":"true","data-toggle":"tooltip"})]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:o("administration:Actions")}),Object(s.jsx)("input",{type:"submit",className:"btn btn-".concat(e.admin?"dark":"primary"," btn-sm"),disabled:e.username===a.username,value:e.admin?o("administration:Remove admin rights"):o("administration:Add admin rights"),onClick:function(){return i(e.username,!e.admin)}})]})]},e.username)}))})]}),Object(s.jsx)(ce,{pagination:c,pathname:r.pathname,query:this.state,t:o}),Object(s.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Ws.push("/admin/")},value:o("common:Back")})]})]})})})})]})}}]),a}(o.a.Component),le=Object(k.c)((function(e){return{authUser:e.user,location:e.router.location,message:e.message,pagination:e.users.pagination,users:e.users.data}}),(function(e){return{loadUsers:function(t){e(Y("getData","users",t))},updateUser:function(t,a){e(Y("updateData","users",{username:t,admin:a},!1))}}}))(ie),de=a(219);function ue(){var e=Object(de.a)().t;return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsx)("title",{children:"fittrackee - 404"})}),Object(s.jsx)("h1",{className:"page-title",children:e("Page not found")})]})}var me=Object(N.a)()(Object(k.c)((function(e){return{appConfig:e.application.config,user:e.user}}))((function(e){var t=e.appConfig,a=e.t,r=e.user;return Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",a("administration:Administration")]})}),Object(s.jsx)("div",{className:"container dashboard",children:r.admin?Object(s.jsxs)(w.d,{children:[Object(s.jsx)(w.b,{exact:!0,path:"/admin",render:function(){return Object(s.jsx)(re,{appConfig:t,t:a})}}),Object(s.jsx)(w.b,{exact:!0,path:"/admin/application",render:function(){return Object(s.jsx)(ee,{appConfig:t,t:a})}}),Object(s.jsx)(w.b,{exact:!0,path:"/admin/sports",render:function(){return Object(s.jsx)(oe,{t:a})}}),Object(s.jsx)(w.b,{exact:!0,path:"/admin/users",render:function(){return Object(s.jsx)(le,{t:a})}}),Object(s.jsx)(w.b,{component:ue})]}):Object(s.jsx)(ue,{})})]})}))),je=a(467),pe=a(24),he=a(487),be=a(222),Oe=a.n(be),fe=["#55a8a3","#98C3A9","#D0838A","#ECC77E","#926692","#929292","#428bca"],xe=[{record_type:"AS",label:"Ave. speed"},{record_type:"FD",label:"Farest distance"},{record_type:"LD",label:"Longest duration"},{record_type:"MS",label:"Max. speed"}],ge=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return t||(t="yyyy/MM/dd"),a||(a="HH:mm"),{workout_date:e?Object(D.a)(e,t):null,workout_time:e?Object(D.a)(e,a):null}},ve=function(e){var t=new Date(0);return(t=Object(he.a)(t.setSeconds(e),1)).getTime()},ke=function(e){for(var t=0;ts?1:a2&&void 0!==arguments[2]&&arguments[2];return e.filter((function(e){return!a||e.is_active})).map((function(e){return Object(S.a)(Object(S.a)({},e),{},{label:t("sports:".concat(e.label))})})).sort(we)},Ne=function(){function e(){Object(f.a)(this,e)}return Object(x.a)(e,null,[{key:"loginOrRegisterOrPasswordReset",value:function(e,t){var a={url:"auth/".concat(e),method:"POST",noAuthorization:!0,body:t,type:"application/json"};return R(a)}},{key:"deletePicture",value:function(){return R({url:"auth/picture",method:"DELETE"})}}]),e}(),_e=function(e){return{type:"PICTURE_ERROR",message:e}},Se=function(e){return{type:"PROFILE_UPDATE_ERROR",message:e}},De=function(){return function(e){return window.localStorage.getItem("authToken")?e(Ce()):{type:"LOGOUT"}}},Ce=function(){return function(e){return H.getData("auth/profile").then((function(t){return"success"===t.status?(e(Y("getData","sports")),t.data.isAuthenticated=!0,t.data.language&&e(X(t.data.language)),e({type:"PROFILE_SUCCESS",profil:t.data})):e({type:"PROFILE_ERROR",message:t.message})})).catch((function(e){throw e}))}},Ee=function(e,t){return function(a){if("register"===t||"password/update"===t){var s=function(e){var t=[];return!(arguments.length>1&&void 0!==arguments[1]&&arguments[1])&&(e.username.length<3||e.username.length>12)&&t.push("3 to 12 characters required for username."),e.password!==e.password_conf&&t.push("Password and password confirmation don't match."),e.password.length<8&&t.push("8 characters required for password."),t}(e,"password/update"===t);if(s.length>0)return a({type:"AUTH_ERRORS",messages:function(e){var t=0;return e.map((function(e){var a={id:t,value:e};return t++,a}))}(s)})}return a(function(e,t){return function(a){return Ne.loginOrRegisterOrPasswordReset(e,t).then((function(t){if("success"===t.status){if("password/reset-request"===e)return Ws.push({pathname:"/password-reset/sent"});if("password/update"===e)return Ws.push({pathname:"/updated-password"});if("login"===e||"register"===e)return window.localStorage.setItem("authToken",t.auth_token),"register"===e&&a(Z("config")),a(Ce())}return a({type:"AUTH_ERROR",message:t.message})})).catch((function(e){throw e}))}}(t,e))}},Ae=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return function(a){return H.deleteData("users",e).then((function(e){204===e.status?(a(Z("config")),t?Ws.push("/admin/users"):(a({type:"LOGOUT"}),Ws.push("/"))):e.json().then((function(e){return a(V("".concat(e.message)))}))})).catch((function(e){return a(V("user|".concat(e)))}))}},Me=function(e){return{type:"SET_GPX",gpxContent:e}},Te=function(e){return{type:"SET_CHART_DATA",chartData:e}},Pe=function(e){return function(t){return H.updateData("workouts",e).then((function(e){"success"===e.status?(t(De()),Ws.push("/workouts/".concat(e.data.workouts[0].id))):t(V("workouts|".concat(e.message))),t(G(!1))})).catch((function(e){t(G(!1)),t(V("workouts|".concat(e)))}))}},Fe=function(e){return function(t){return H.getData("workouts",e).then((function(e){"success"===e.status?e.data.workouts.length>0&&t({type:"PUSH_WORKOUTS",workouts:e.data.workouts}):t(V("workouts|".concat(e.message)))})).catch((function(e){return t(V("workouts|".concat(e)))}))}};var ze=Object(k.c)((function(e){return{appConfig:e.application.config,loading:e.loading}}),(function(e){return{onAddWorkout:function(t){e(G(!0));var a=new FormData;a.append("file",t.target.form.gpxFile.files[0]),a.append("data",'{"sport_id": '.concat(t.target.form.sport.value,', "notes": "').concat(t.target.form.notes.value,'"}')),e(function(e){return function(t){return H.addDataWithFile("workouts",e).then((function(e){"created"===e.status?0===e.data.workouts.length?t(V("workouts|no correct file.")):1===e.data.workouts.length?(t(De()),Ws.push("/workouts/".concat(e.data.workouts[0].id))):(t(De()),Ws.push("/")):413===e.status?t(V("workouts|File size is greater than the allowed size")):t(V("workouts|".concat(e.message))),t(G(!1))})).catch((function(e){t(G(!1)),t(V("workouts|".concat(e)))}))}}(a))},onEditWorkout:function(t,a){e(Pe({id:a.id,notes:t.target.form.notes.value,sport_id:+t.target.form.sport.value,title:t.target.form.title.value}))}}}))((function(e){var t=e.appConfig,a=e.loading,r=e.onAddWorkout,n=e.onEditWorkout,o=e.sports,c=e.t,i=e.workout,l=i?i.sport_id:"",d=ye(o,c,!0),u="".concat(c("workouts:no folder inside"),", ").concat(t.gpx_limit_import," ").concat(c("workouts:files max"),", ").concat(c("workouts:max size"),": ").concat(M(t.max_zip_file_size)),m=M(t.max_single_file_size);return Object(s.jsxs)("form",{encType:"multipart/form-data",method:"post",onSubmit:function(e){return e.preventDefault()},children:[Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[c("common:Sport"),":",Object(s.jsxs)("select",{className:"form-control input-lg",defaultValue:l,disabled:a,name:"sport",required:!0,children:[Object(s.jsx)("option",{value:""}),d.map((function(e){return Object(s.jsx)("option",{value:e.id,children:e.label},e.id)}))]})]})}),i?Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[c("workouts:Title"),":",Object(s.jsx)("input",{name:"title",defaultValue:i?i.title:"",disabled:a,className:"form-control input-lg"})]})}):Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[Object(s.jsxs)(je.a,{i18nKey:"workouts:gpxFile",children:[Object(s.jsx)("strong",{children:"gpx"})," file"]}),Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-question-circle","aria-hidden":"true","data-toggle":"tooltip",title:"".concat(c("workouts:max size"),": ").concat(m)})})," ",Object(s.jsxs)(je.a,{i18nKey:"workouts:zipFile",children:["or ",Object(s.jsx)("strong",{children:" zip"})," file containing ",Object(s.jsx)("strong",{children:"gpx "}),"files"]}),Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-question-circle","aria-hidden":"true","data-toggle":"tooltip","data-placement":"top",title:u})})," ",":",Object(s.jsx)("input",{accept:".gpx, .zip",className:"form-control form-control-file gpx-file",disabled:a,name:"gpxFile",required:!0,type:"file"})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[c("workouts:Notes"),":",Object(s.jsx)("textarea",{name:"notes",defaultValue:i?i.notes:"",disabled:a,className:"form-control input-lg",maxLength:"500"})]})}),a?Object(s.jsx)("div",{className:"loader"}):Object(s.jsxs)("div",{children:[Object(s.jsx)("input",{type:"submit",className:"btn btn-primary",onClick:function(e){return i?n(e,i):r(e)},value:c("common:Submit")}),Object(s.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Ws.push("/")},value:c("common:Cancel")})]})]})}));var Re=Object(k.c)((function(e){return{user:e.user}}),(function(e){return{onAddOrEdit:function(t,a){var s,r=t.target.form.duration.value.split(":"),n=60*+r[0]*60+60*+r[1]+ +r[2],o={workout_date:"".concat(t.target.form.workout_date.value," ").concat(t.target.form.workout_time.value),distance:+t.target.form.distance.value,duration:n,notes:t.target.form.notes.value,sport_id:+t.target.form.sport_id.value,title:t.target.form.title.value};a?(o.id=a.id,e(Pe(o))):e((s=o,function(e){return H.addData("workouts/no_gpx",s).then((function(t){"created"===t.status?(e(De()),Ws.push("/workouts/".concat(t.data.workouts[0].id))):e(V("workouts|".concat(t.message)))})).catch((function(t){return e(V("workouts|".concat(t)))}))}))}}}))((function(e){var t,a,r=e.onAddOrEdit,n=e.sports,o=e.t,c=e.user,i=e.workout,l=ye(n,o,!0),d="";if(i){var u=ge(L(i.workout_date,c.timezone),"yyyy-MM-dd");t=u.workout_date,a=u.workout_time,d=i.sport_id}return Object(s.jsxs)("form",{onSubmit:function(e){return e.preventDefault()},children:[Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("workouts:Title"),":",Object(s.jsx)("input",{name:"title",defaultValue:i?i.title:"",className:"form-control input-lg"})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("common:Sport"),":",Object(s.jsxs)("select",{className:"form-control input-lg",defaultValue:d,name:"sport_id",required:!0,children:[Object(s.jsx)("option",{value:""}),l.map((function(e){return Object(s.jsx)("option",{value:e.id,children:e.label},e.id)}))]})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("workouts:Workout Date"),":",Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("input",{name:"workout_date",defaultValue:t,className:"form-control col-md",required:!0,type:"date"}),Object(s.jsx)("input",{name:"workout_time",defaultValue:a,className:"form-control col-md",required:!0,type:"time"})]})})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("workouts:Duration"),":",Object(s.jsx)("input",{name:"duration",defaultValue:i?i.duration:"",className:"form-control col-xs-4",pattern:"^([0-9]*[0-9]):([0-5][0-9]):([0-5][0-9])$",placeholder:"hh:mm:ss",required:!0,type:"text"})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("workouts:Distance")," (km):",Object(s.jsx)("input",{name:"distance",defaultValue:i?i.distance:"",className:"form-control input-lg",min:0,required:!0,step:"0.001",type:"number"})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("workouts:Notes"),":",Object(s.jsx)("textarea",{name:"notes",defaultValue:i?i.notes:"",className:"form-control input-lg",maxLength:"500"})]})}),Object(s.jsx)("input",{type:"submit",className:"btn btn-primary",onClick:function(e){return r(e,i)},value:o("common:Submit")}),Object(s.jsx)("input",{type:"submit",className:"btn btn-secondary",onClick:function(){return Ws.push("/")},value:o("common:Cancel")})]})})),Le=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={withGpx:!0},r}return Object(x.a)(a,[{key:"handleRadioChange",value:function(e){this.setState({withGpx:"withGpx"===e.target.name?e.target.value:!e.target.value})}},{key:"render",value:function(){var e=this,t=this.props,a=t.loading,r=t.message,n=t.sports,o=t.t,c=t.workout,i=this.state.withGpx;return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee -"," ",o(c?"workouts:Edit a workout":"workouts:Add a workout")]})}),Object(s.jsx)("br",{}),Object(s.jsx)("br",{}),Object(s.jsx)(_,{message:r,t:o}),Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-md-2"}),Object(s.jsx)("div",{className:"col-md-8",children:Object(s.jsxs)("div",{className:"card add-workout",children:[Object(s.jsx)("h2",{className:"card-header text-center",children:o(c?"workouts:Edit a workout":"workouts:Add a workout")}),Object(s.jsx)("div",{className:"card-body",children:c?c.with_gpx?Object(s.jsx)(ze,{workout:c,sports:n,t:o}):Object(s.jsx)(Re,{workout:c,sports:n,t:o}):Object(s.jsxs)("div",{children:[Object(s.jsx)("form",{children:Object(s.jsxs)("div",{className:"form-group row",children:[Object(s.jsx)("div",{className:"col",children:Object(s.jsxs)("label",{className:"radioLabel",children:[Object(s.jsx)("input",{className:"add-workout-radio",type:"radio",name:"withGpx",disabled:a,checked:i,onChange:function(t){return e.handleRadioChange(t)}}),o("workouts:with gpx file")]})}),Object(s.jsx)("div",{className:"col",children:Object(s.jsxs)("label",{className:"radioLabel",children:[Object(s.jsx)("input",{className:"add-workout-radio",type:"radio",name:"withoutGpx",disabled:a,checked:!i,onChange:function(t){return e.handleRadioChange(t)}}),o("workouts:without gpx file")]})})]})}),i?Object(s.jsx)(ze,{sports:n,t:o}):Object(s.jsx)(Re,{sports:n,t:o})]})})]})}),Object(s.jsx)("div",{className:"col-md-2"})]})})]})}}]),a}(o.a.Component),Ue=Object(N.a)()(Object(k.c)((function(e){return{loading:e.loading}}))(Le));var Ie=Object(k.c)((function(e){return{message:e.message,sports:e.sports.data,user:e.user}}))((function(e){var t=e.message,a=e.sports;return Object(s.jsx)("div",{children:Object(s.jsx)(Ue,{workout:null,message:t,sports:a})})}));function We(e){var t=Object(de.a)().t;return Object(s.jsx)("div",{className:"custom-modal-backdrop",children:Object(s.jsx)("div",{className:"custom-modal",children:Object(s.jsxs)("div",{className:"modal-content",children:[Object(s.jsxs)("div",{className:"modal-header",children:[Object(s.jsx)("h5",{className:"modal-title",children:e.title}),Object(s.jsx)("button",{type:"button",className:"close","aria-label":"Close",onClick:function(){return e.close()},children:Object(s.jsx)("span",{"aria-hidden":"true",children:"\xd7"})})]}),Object(s.jsx)("div",{className:"modal-body",children:Object(s.jsx)("p",{children:e.text})}),Object(s.jsxs)("div",{className:"modal-footer",children:[Object(s.jsx)("button",{type:"button",className:"btn btn-primary",onClick:function(){return e.confirm()},children:t("common:Yes")}),Object(s.jsx)("button",{type:"button",className:"btn btn-secondary",onClick:function(){return e.close()},children:t("common:No")})]})]})})})}function He(e){var t=e.dataType,a=e.displayModal,r=e.segmentId,n=e.sport,o=e.t,c=e.title,i=e.user,l=e.workout,d=l?ge(L(l.workout_date,i.timezone)):null,u="segment"===t&&1!==r?"/workouts/".concat(l.id,"/segment/").concat(r-1):"workout"===t&&l.previous_workout?"/workouts/".concat(l.previous_workout):null,m="segment"===t&&r0?Object(s.jsxs)("div",{children:[Object(s.jsxs)("div",{className:"row chart-radio",children:[Object(s.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(s.jsx)("input",{type:"radio",name:"distance",checked:i,onChange:function(e){return a.handleRadioChange(e)}}),o("workouts:distance")]}),Object(s.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(s.jsx)("input",{type:"radio",name:"duration",checked:!i,onChange:function(e){return a.handleRadioChange(e)}}),o("workouts:duration")]})]}),Object(s.jsxs)("div",{className:"row chart-radio",children:[Object(s.jsx)("div",{className:"col-md-5"}),Object(s.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(s.jsx)("input",{type:"checkbox",name:"speed",checked:this.displayData("speed"),onChange:function(e){return a.handleLegendChange(e)}}),o("workouts:speed")]}),Object(s.jsxs)("label",{className:"radioLabel col-md-1",children:[Object(s.jsx)("input",{type:"checkbox",name:"elevation",checked:this.displayData("elevation"),onChange:function(e){return a.handleLegendChange(e)}}),o("workouts:elevation")]}),Object(s.jsx)("div",{className:"col-md-5"})]}),Object(s.jsx)("div",{className:"row chart",children:Object(s.jsx)(qe.f,{height:300,children:Object(s.jsxs)(qe.d,{data:n,margin:{top:15,right:30,left:20,bottom:15},onMouseMove:function(e){return c(e.activePayload)},onMouseLeave:function(){return c(null)},children:[Object(s.jsx)(qe.h,{allowDecimals:!1,dataKey:e,label:{value:o("workouts:".concat(e)),offset:0,position:"bottom"},scale:t,interval:l,tickFormatter:function(e){return i?e:Object(D.a)(e,"HH:mm:ss")},type:"number"}),Object(s.jsx)(qe.i,{label:{value:"".concat(o("workouts:speed")," (km/h)"),angle:-90,position:"left"},yAxisId:"left"}),Object(s.jsx)(qe.i,{label:{value:"".concat(o("workouts:elevation")," (m)"),angle:-90,position:"right"},yAxisId:"right",orientation:"right"}),this.displayData("elevation")&&Object(s.jsx)(qe.a,{yAxisId:"right",type:"linear",dataKey:"elevation",name:o("workouts:elevation"),fill:"#e5e5e5",stroke:"#cccccc",dot:!1,unit:" m"}),this.displayData("speed")&&Object(s.jsx)(qe.e,{yAxisId:"left",type:"linear",dataKey:"speed",name:o("workouts:speed"),stroke:"#8884d8",strokeWidth:2,dot:!1,unit:" km/h"}),Object(s.jsx)(qe.g,{labelFormatter:function(e){return i?"".concat(o("workouts:distance"),": ").concat(e," km"):"".concat(o("workouts:duration"),": ").concat(Object(D.a)(e,"HH:mm:ss"))}})]})})}),Object(s.jsx)("div",{className:"chart-info",children:o("workouts:data from gpx, without any cleaning")})]}):o("workouts:No data to display")})}}]),a}(o.a.Component),Ve=Object(k.c)((function(e){return{chartData:e.chartData}}),(function(e){return{loadWorkoutData:function(t){e(function(e){return function(t){if(e)return H.getData("workouts/".concat(e,"/chart_data")).then((function(e){"success"===e.status?t(Te(ke(e.data.chart_data))):t(V("workouts|".concat(e.message)))})).catch((function(e){return t(V("workouts|".concat(e)))}));t(Te(null))}}(t))},loadSegmentData:function(t,a){e(function(e,t){return function(a){if(e)return H.getData("workouts/".concat(e,"/chart_data/segment/").concat(t)).then((function(e){"success"===e.status?a(Te(ke(e.data.chart_data))):a(V("workouts|".concat(e.message)))})).catch((function(e){return a(V("workouts|".concat(e)))}));a(Te(null))}}(t,a))}}}))(Be);function Ge(e){var t=e.t,a=e.workout;return Object(s.jsx)("div",{className:"container",children:a.weather_start&&a.weather_end&&Object(s.jsxs)("table",{className:"table table-borderless weather-table text-center",children:[Object(s.jsx)("thead",{children:Object(s.jsxs)("tr",{children:[Object(s.jsx)("th",{}),Object(s.jsxs)("th",{children:[t("workouts:Start"),Object(s.jsx)("br",{}),Object(s.jsx)("img",{className:"weather-img",src:"/img/weather/".concat(a.weather_start.icon,".png"),alt:"workout weather (".concat(a.weather_start.icon,")"),title:a.weather_start.summary})]}),Object(s.jsxs)("th",{children:[t("workouts:End"),Object(s.jsx)("br",{}),Object(s.jsx)("img",{className:"weather-img",src:"/img/weather/".concat(a.weather_end.icon,".png"),alt:"workout weather (".concat(a.weather_end.icon,")"),title:a.weather_end.summary})]})]})}),Object(s.jsxs)("tbody",{children:[Object(s.jsxs)("tr",{children:[Object(s.jsx)("td",{children:Object(s.jsx)("img",{className:"weather-img-small",src:"/img/weather/temperature.png",alt:"Temperatures"})}),Object(s.jsxs)("td",{children:[Number(a.weather_start.temperature).toFixed(1),"\xb0C"]}),Object(s.jsxs)("td",{children:[Number(a.weather_end.temperature).toFixed(1),"\xb0C"]})]}),Object(s.jsxs)("tr",{children:[Object(s.jsx)("td",{children:Object(s.jsx)("img",{className:"weather-img-small",src:"/img/weather/pour-rain.png",alt:"Temperatures"})}),Object(s.jsxs)("td",{children:[Number(100*a.weather_start.humidity).toFixed(1),"%"]}),Object(s.jsxs)("td",{children:[Number(100*a.weather_end.humidity).toFixed(1),"%"]})]}),Object(s.jsxs)("tr",{children:[Object(s.jsx)("td",{children:Object(s.jsx)("img",{className:"weather-img-small",src:"/img/weather/breeze.png",alt:"Temperatures"})}),Object(s.jsxs)("td",{children:[Number(a.weather_start.wind).toFixed(1),"m/s"]}),Object(s.jsxs)("td",{children:[Number(a.weather_end.wind).toFixed(1),"m/s"]})]})]})]})})}function Je(e){var t=e.t,a=e.workout,r="0:00:00"!==a.pauses&&null!==a.pauses;return Object(s.jsxs)("div",{className:"workout-details",children:[Object(s.jsxs)("p",{children:[Object(s.jsx)("i",{className:"fa fa-clock-o custom-fa","aria-hidden":"true"}),t("workouts:Duration"),": ",a.moving,a.records&&a.records.find((function(e){return"LD"===e.record_type}))&&Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})}),r&&Object(s.jsxs)("span",{children:[Object(s.jsx)("br",{}),"(",t("workouts:pauses"),": ",a.pauses,","," ",t("workouts:total duration"),": ",a.duration,")"]})]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("i",{className:"fa fa-road custom-fa","aria-hidden":"true"}),t("workouts:Distance"),": ",a.distance," km",a.records&&a.records.find((function(e){return"FD"===e.record_type}))&&Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})})]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("i",{className:"fa fa-tachometer custom-fa","aria-hidden":"true"}),t("workouts:Average speed"),": ",a.ave_speed," km/h",a.records&&a.records.find((function(e){return"AS"===e.record_type}))&&Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})}),Object(s.jsx)("br",{}),t("workouts:Max. speed"),": ",a.max_speed," km/h",a.records&&a.records.find((function(e){return"MS"===e.record_type}))&&Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-trophy custom-fa","aria-hidden":"true"})})]}),a.min_alt&&a.max_alt&&Object(s.jsxs)("p",{children:[Object(s.jsx)("i",{className:"fi-mountains custom-fa"}),t("workouts:Min. altitude"),": ",a.min_alt,"m",Object(s.jsx)("br",{}),t("workouts:Max. altitude"),": ",a.max_alt,"m"]}),a.ascent&&a.descent&&Object(s.jsxs)("p",{children:[Object(s.jsx)("i",{className:"fa fa-location-arrow custom-fa"}),t("workouts:Ascent"),": ",a.ascent,"m",Object(s.jsx)("br",{}),t("workouts:Descent"),": ",a.descent,"m"]}),Object(s.jsx)(Ge,{workout:a,t:t})]})}var Ke=a(471),Ye=a(468),Xe=a(489),$e=a(469),Ze=a(470),Qe=a(233),et=a.n(Qe);function tt(e){var t=e.bounds,a=e.coordinates,r=e.jsonData,n=e.mapAttribution;return Object(Ye.a)().fitBounds(t),Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)(Xe.a,{attribution:n,url:"".concat(T,"workouts/map_tile/{s}/{z}/{x}/{y}.png")}),Object(s.jsx)($e.a,{data:r},et()(r)),a.latitude&&Object(s.jsx)(Ze.a,{position:[a.latitude,a.longitude]})]})}var at=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={zoom:13},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){"workout"===this.props.dataType?this.props.loadWorkoutGpx(this.props.workout.id):this.props.loadSegmentGpx(this.props.workout.id,this.props.segmentId)}},{key:"componentDidUpdate",value:function(e){("workout"===this.props.dataType&&e.workout.id!==this.props.workout.id||"workout"===this.props.dataType&&"segment"===e.dataType)&&this.props.loadWorkoutGpx(this.props.workout.id),"segment"===this.props.dataType&&e.segmentId!==this.props.segmentId&&this.props.loadSegmentGpx(this.props.workout.id,this.props.segmentId)}},{key:"componentWillUnmount",value:function(){this.props.loadWorkoutGpx(null)}},{key:"render",value:function(){var e=this.props,t=e.coordinates,a=e.gpxContent,r=e.mapAttribution,n=e.workout,o=function(e){var t;if(e){var a=(new DOMParser).parseFromString(e,"text/xml");t=Oe.a.gpx(a)}return{jsonData:t}}(a).jsonData,c=[[n.bounds[0],n.bounds[1]],[n.bounds[2],n.bounds[3]]];return Object(s.jsx)("div",{children:o&&Object(s.jsx)(Ke.a,{zoom:this.state.zoom,bounds:c,boundsOptions:{padding:[10,10]},children:Object(s.jsx)(tt,{bounds:c,coordinates:t,jsonData:o,mapAttribution:r})})})}}]),a}(o.a.Component),st=Object(k.c)((function(e){return{gpxContent:e.gpx,mapAttribution:e.application.config.map_attribution}}),(function(e){return{loadWorkoutGpx:function(t){e(function(e){return function(t){if(e)return H.getData("workouts/".concat(e,"/gpx")).then((function(e){"success"===e.status?t(Me(e.data.gpx)):t(V("workouts|".concat(e.message)))})).catch((function(e){return t(V("workouts|".concat(e)))}));t(Me(null))}}(t))},loadSegmentGpx:function(t,a){e(function(e,t){return function(a){if(e)return H.getData("workouts/".concat(e,"/gpx/segment/").concat(t)).then((function(e){"success"===e.status?a(Me(e.data.gpx)):a(V("workouts|".concat(e.message)))})).catch((function(e){return a(V("workouts|".concat(e)))}));a(Me(null))}}(t,a))}}}))(at);function rt(e){var t=e.t;return Object(s.jsx)("div",{className:"workout-no-map text-center",children:t("workouts:No Map")})}function nt(e){var t=e.notes,a=e.t;return Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body",children:["Notes",Object(s.jsx)("div",{className:"workout-notes",children:t||a("workouts:No notes")})]})})})})}function ot(e){var t=e.segments,a=e.t;return Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body",children:[a("workouts:Segments"),Object(s.jsx)("div",{className:"workout-segments",children:Object(s.jsx)("ul",{children:t.map((function(e,t){return Object(s.jsxs)("li",{className:"workout-segments-list",children:[Object(s.jsxs)(te.a,{to:"/workouts/".concat(e.workout_id,"/segment/").concat(t+1),children:[a("workouts:segment")," ",t+1]})," ","(",a("workouts:distance"),": ",e.distance," km,"," ",a("workouts:duration"),": ",e.duration,")"]},"segment-".concat(t))}))})})]})})})})}var ct=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={displayModal:!1,coordinates:{latitude:null,longitude:null}},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadWorkout(this.props.match.params.workoutId)}},{key:"componentDidUpdate",value:function(e){e.match.params.workoutId!==this.props.match.params.workoutId&&this.props.loadWorkout(this.props.match.params.workoutId)}},{key:"displayModal",value:function(e){this.setState((function(t){return Object(S.a)(Object(S.a)({},t),{},{displayModal:e})}))}},{key:"updateCoordinates",value:function(e){var t=e&&e.length>0?{latitude:e[0].payload.latitude,longitude:e[0].payload.longitude}:{latitude:null,longitude:null};this.setState((function(e){return Object(S.a)(Object(S.a)({},e),{},{coordinates:t})}))}},{key:"render",value:function(){var e=this,t=this.props,a=t.message,r=t.onDeleteWorkout,n=t.sports,o=t.t,c=t.user,i=t.workouts,l=this.state,d=l.coordinates,u=l.displayModal,m=Object(pe.a)(i,1)[0],j=m?m.title:o("workouts:Workout"),p=m?n.filter((function(e){return e.id===m.sport_id})):[],h=Object(pe.a)(p,1)[0],b=parseInt(this.props.match.params.segmentId),O=b>=0?"segment":"workout";return Object(s.jsxs)("div",{className:"workout-page",children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",j]})}),a?Object(s.jsx)(_,{message:a,t:o}):Object(s.jsxs)("div",{className:"container",children:[u&&Object(s.jsx)(We,{title:o("common:Confirmation"),text:o("workouts:Are you sure you want to delete this workout?"),confirm:function(){r(m.id),e.displayModal(!1)},close:function(){return e.displayModal(!1)}}),m&&h&&1===i.length&&Object(s.jsxs)("div",{children:[Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col",children:Object(s.jsxs)("div",{className:"card workout-card",children:[Object(s.jsx)("div",{className:"card-header",children:Object(s.jsx)(He,{workout:m,dataType:O,segmentId:b,sport:h,t:o,title:j,user:c,displayModal:function(){return e.displayModal(!0)}})}),Object(s.jsx)("div",{className:"card-body",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-md-8",children:m.with_gpx?Object(s.jsx)(st,{workout:m,coordinates:d,dataType:O,segmentId:b}):Object(s.jsx)(rt,{t:o})}),Object(s.jsx)("div",{className:"col",children:Object(s.jsx)(Je,{workout:"workout"===O?m:m.segments[b-1],t:o})})]})})]})})}),m.with_gpx&&Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsx)("div",{className:"card-body",children:Object(s.jsx)("div",{className:"row",children:Object(s.jsxs)("div",{className:"col",children:[Object(s.jsx)("div",{className:"chart-title",children:o("workouts:Chart")}),Object(s.jsx)(Ve,{workout:m,dataType:O,segmentId:b,t:o,updateCoordinates:function(t){return e.updateCoordinates(t)}})]})})})})})}),"workout"===O&&Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)(nt,{notes:m.notes,t:o}),m.segments.length>1&&Object(s.jsx)(ot,{segments:m.segments,t:o})]})]})]})]})}}]),a}(o.a.Component),it=Object(N.a)()(Object(k.c)((function(e){return{workouts:e.workouts.data,message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadWorkout:function(t){e(Y("getData","workouts",{id:t}))},onDeleteWorkout:function(t){var a;e((a=t,function(e){return H.deleteData("workouts",a).then((function(t){var s;204===t.status?Promise.resolve(e((s=a,{type:"REMOVE_WORKOUT",workoutId:s}))).then((function(){return e(De())})).then((function(){return Ws.push("/")})):e(V("workouts|".concat(t.status)))})).catch((function(t){return e(V("workouts|".concat(t)))}))}))}}}))(ct)),lt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadWorkout(this.props.match.params.workoutId)}},{key:"render",value:function(){var e=this.props,t=e.message,a=e.sports,r=e.workouts,n=Object(pe.a)(r,1)[0];return Object(s.jsx)("div",{children:a.length>0&&Object(s.jsx)(Ue,{workout:n,message:t,sports:a})})}}]),a}(o.a.Component),dt=Object(k.c)((function(e){return{workouts:e.workouts.data,message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadWorkout:function(t){e(Y("getData","workouts",{id:t}))}}}))(lt);var ut=Object(k.c)((function(e){return{user:e.user}}))((function(){return Object(s.jsx)("div",{children:z()?Object(s.jsxs)(w.d,{children:[Object(s.jsx)(w.b,{exact:!0,path:"/workouts/add",component:Ie}),Object(s.jsx)(w.b,{exact:!0,path:"/workouts/:workoutId",component:it}),Object(s.jsx)(w.b,{exact:!0,path:"/workouts/:workoutId/edit",component:dt}),Object(s.jsx)(w.b,{path:"/workouts/:workoutId/segment/:segmentId",component:it}),Object(s.jsx)(w.b,{component:ue})]}):Object(s.jsx)(w.a,{to:"/login"})})})),mt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props.t;return Object(s.jsx)("div",{className:"card text-center",children:Object(s.jsxs)("div",{className:"card-body",children:[e("common:No workouts.")," ",Object(s.jsx)(te.a,{to:{pathname:"/workouts/add"},children:e("dashboard:Upload one !")})]})})}}]),a}(o.a.PureComponent),jt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props,t=e.loadWorkouts,a=e.sports,r=e.t,n=e.updateParams,o=ye(a,r);return Object(s.jsx)("div",{className:"card",children:Object(s.jsx)("div",{className:"card-body workout-filter",children:Object(s.jsxs)("form",{onSubmit:function(e){return e.preventDefault()},children:[Object(s.jsxs)("div",{className:"form-group",children:[Object(s.jsxs)("label",{children:[r("workouts:From"),":",Object(s.jsx)("input",{className:"form-control col-md",name:"from",onChange:function(e){return n(e)},type:"date"})]}),Object(s.jsxs)("label",{children:[r("workouts:To"),":",Object(s.jsx)("input",{className:"form-control col-md",name:"to",onChange:function(e){return n(e)},type:"date"})]})]}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[r("common:Sport"),":",Object(s.jsxs)("select",{className:"form-control input-lg",name:"sport_id",onChange:function(e){return n(e)},children:[Object(s.jsx)("option",{value:""}),o.map((function(e){return Object(s.jsx)("option",{value:e.id,children:e.label},e.id)}))]})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[r("workouts:Distance")," (km):",Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",min:0,name:"distance_from",onChange:function(e){return n(e)},step:"1",type:"number"})}),Object(s.jsx)("div",{className:"col-2 align-middle text-center",children:r("common:to")}),Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",min:0,name:"distance_to",onChange:function(e){return n(e)},step:"1",type:"number"})})]})})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[r("workouts:Duration"),":",Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",name:"duration_from",onChange:function(e){return n(e)},pattern:"^([0-9]*[0-9]):([0-5][0-9])$",placeholder:"hh:mm",type:"text"})}),Object(s.jsx)("div",{className:"col-2 align-middle text-center",children:r("common:to")}),Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",name:"duration_to",onChange:function(e){return n(e)},pattern:"^([0-9]*[0-9]):([0-5][0-9])$",placeholder:"hh:mm",type:"text"})})]})})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[r("workouts:Average speed")," (km/h):",Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",min:0,name:"ave_speed_from",onChange:function(e){return n(e)},step:"1",type:"number"})}),Object(s.jsx)("div",{className:"col-2 align-middle text-center",children:r("common:to")}),Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",min:0,name:"ave_speed_to",onChange:function(e){return n(e)},step:"1",type:"number"})})]})})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[r("workouts:Max. speed")," (km/h):",Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",min:0,name:"max_speed_from",onChange:function(e){return n(e)},step:"1",type:"number"})}),Object(s.jsx)("div",{className:"col-2 align-middle text-center",children:r("common:to")}),Object(s.jsx)("div",{className:"col-5",children:Object(s.jsx)("input",{className:"form-control",min:0,name:"max_speed_to",onChange:function(e){return n(e)},step:"1",type:"number"})})]})})]})}),Object(s.jsx)("input",{className:"btn btn-primary btn-lg btn-block",onClick:function(){return t()},type:"submit",value:r("workouts:Filter")})]})})})}}]),a}(o.a.PureComponent),pt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props,t=e.display,a=e.workout;return Object(s.jsxs)("div",{className:"workout-map".concat("list"===t?"-list":""),children:[Object(s.jsx)("img",{src:"".concat(T,"workouts/map/").concat(a.map,"?").concat(Date.now()),alt:"workout map"}),Object(s.jsxs)("div",{className:"map-attribution".concat("list"===t?"-list":""),children:[Object(s.jsx)("span",{className:"map-attribution-text",children:"\xa9"}),Object(s.jsx)("a",{className:"map-attribution-text",href:"http://www.openstreetmap.org/copyright",target:"_blank",rel:"noopener noreferrer",children:"OpenStreetMap"})]})]})}}]),a}(o.a.PureComponent),ht=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props,t=e.loading,a=e.sports,r=e.t,n=e.user,o=e.workouts;return Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body",children:[Object(s.jsxs)("table",{className:"table",children:[Object(s.jsx)("thead",{children:Object(s.jsxs)("tr",{children:[Object(s.jsx)("th",{scope:"col"}),Object(s.jsx)("th",{scope:"col",children:r("common:Workout")}),Object(s.jsx)("th",{scope:"col",children:r("workouts:Date")}),Object(s.jsx)("th",{scope:"col",children:r("workouts:Distance")}),Object(s.jsx)("th",{scope:"col",children:r("workouts:Duration")}),Object(s.jsx)("th",{scope:"col",children:r("workouts:Ave. speed")}),Object(s.jsx)("th",{scope:"col",children:r("workouts:Max. speed")})]})}),Object(s.jsx)("tbody",{children:!t&&a&&o.map((function(e,t){return Object(s.jsxs)("tr",{children:[Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("common:Sport")}),Object(s.jsx)("img",{className:"workout-sport",src:a.filter((function(t){return t.id===e.sport_id})).map((function(e){return e.img})),alt:"workout sport logo"})]}),Object(s.jsxs)("td",{className:"workout-title",children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("common:Workout")}),Object(s.jsx)(te.a,{to:"/workouts/".concat(e.id),children:e.title}),e.map&&Object(s.jsx)(pt,{workout:e,display:"list"})]}),Object(s.jsxs)("td",{children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("workouts:Date")}),Object(D.a)(L(e.workout_date,n.timezone),"dd/MM/yyyy HH:mm")]}),Object(s.jsxs)("td",{className:"text-right",children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("workouts:Distance")}),Number(e.distance).toFixed(2)," km"]}),Object(s.jsxs)("td",{className:"text-right",children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("workouts:Duration")}),e.moving]}),Object(s.jsxs)("td",{className:"text-right",children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("workouts:Ave. speed")}),e.ave_speed," km/h"]}),Object(s.jsxs)("td",{className:"text-right",children:[Object(s.jsx)("span",{className:"heading-span-absolute",children:r("workouts:Max. speed")}),e.max_speed," km/h"]})]},t)}))})]}),t&&Object(s.jsx)("div",{className:"loader"})]})})}}]),a}(o.a.PureComponent),bt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={params:{page:1,per_page:10}},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadWorkouts(this.state.params)}},{key:"setParams",value:function(e){var t=this.state.params;""===e.target.value?delete t[e.target.name]:t[e.target.name]=e.target.value,t.page=1,this.setState(t)}},{key:"render",value:function(){var e=this,t=this.props,a=t.loading,r=t.loadWorkouts,n=t.loadMoreWorkouts,o=t.message,c=t.sports,i=t.t,l=t.user,d=t.workouts,u=this.state.params,m=!(d.length>0)||null===d[d.length-1].previous_workout;return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",i("common:Workouts")]})}),o?Object(s.jsx)(_,{message:o,t:i}):Object(s.jsx)("div",{className:"container history",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-md-3",children:Object(s.jsx)(jt,{sports:c,loadWorkouts:function(){return r(u)},t:i,updateParams:function(t){return e.setParams(t)}})}),Object(s.jsxs)("div",{className:"col-md-9 workouts-result",children:[Object(s.jsx)(ht,{workouts:d,loading:a,sports:c,t:i,user:l}),!m&&Object(s.jsx)("input",{type:"submit",className:"btn btn-default btn-md btn-block",value:"Load more workouts",onClick:function(){u.page+=1,n(u),e.setState(u)}}),0===d.length&&Object(s.jsx)(mt,{t:i})]})]})})]})}}]),a}(o.a.Component),Ot=Object(N.a)()(Object(k.c)((function(e){return{workouts:e.workouts.data,loading:e.loading,message:e.message,sports:e.sports.data,user:e.user}}),(function(e){return{loadWorkouts:function(t){e(Y("getData","workouts",t))},loadMoreWorkouts:function(t){e(Fe(t))}}}))(bt));var ft=Object(N.a)()(Object(k.c)((function(e){return{appConfig:e.application.config,pathname:e.router.location.pathname,message:e.message}}),(function(e){return{onDeletePicture:function(){e((function(e){return Ne.deletePicture().then((function(t){return 204===t.status?e(Ce()):e(_e(t.message))})).catch((function(e){throw e}))}))},onUploadPicture:function(t){e(function(e){return function(t){e.preventDefault();var a=new FormData;return a.append("file",e.target.picture.files[0]),e.target.reset(),H.addDataWithFile("auth/picture",a).then((function(e){if("success"===e.status)return t(Ce());var a=e.message.match(/file size exceeds/g)?"Error during picture update, file size exceeds max size.":e.message;return t(_e(a))})).catch((function(e){throw e}))}}(t))}}}))((function(e){var t=e.appConfig,a=e.displayModal,r=e.editable,n=e.isDeletable,o=e.message,c=e.onDeletePicture,i=e.onUploadPicture,l=e.pathname,d=e.t,u=e.user,m=u.created_at?Object(D.a)(new Date(u.created_at),"dd/MM/yyyy HH:mm"):"",j=u.birth_date?Object(D.a)(new Date(u.birth_date),"dd/MM/yyyy"):"",p=M(t.max_single_file_size);return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",d("user:Profile")]})}),Object(s.jsx)(_,{message:o,t:d}),Object(s.jsxs)("div",{className:"container",children:[Object(s.jsx)("h1",{className:"page-title",children:d("user:Profile")}),Object(s.jsx)("div",{className:"row",children:Object(s.jsx)("div",{className:"col-md-12",children:Object(s.jsxs)("div",{className:"card",children:[Object(s.jsx)("div",{className:"card-header userName",children:Object(s.jsx)("strong",{children:u.username})}),Object(s.jsxs)("div",{className:"card-body",children:[Object(s.jsxs)("div",{className:"row",children:[Object(s.jsxs)("div",{className:"col-md-8",children:[Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Email")}),": ",u.email]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Registration Date")}),": ",m]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:First Name")}),": ",u.first_name]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Last Name")}),": ",u.last_name]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Birth Date")}),": ",j]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Location")}),": ",u.location]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Bio")}),":"," ",u.bio]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Language")}),": ",u.language]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:Timezone")}),": ",u.timezone]}),Object(s.jsxs)("p",{children:[Object(s.jsx)("span",{className:"user-label",children:d("user:First day of week")}),": ",u.weekm?d("user:Monday"):d("user:Sunday")]})]}),Object(s.jsxs)("div",{className:"col-md-4",children:[!0===u.picture&&Object(s.jsxs)("div",{children:[Object(s.jsx)("img",{alt:"Profile",src:"".concat(T,"users/").concat(u.username,"/picture")+"?".concat(Date.now()),className:"img-fluid App-profile-img-small"}),r&&Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("br",{}),Object(s.jsx)("button",{type:"submit",onClick:function(){return c()},children:d("user:Delete picture")}),Object(s.jsx)("br",{}),Object(s.jsx)("br",{})]})]}),r&&Object(s.jsxs)("form",{encType:"multipart/form-data",onSubmit:function(e){return i(e)},children:[Object(s.jsx)("input",{type:"file",name:"picture",accept:".png,.jpg,.gif"}),Object(s.jsx)("br",{}),Object(s.jsx)("button",{type:"submit",children:d("user:Send")})," (max. size: ".concat(p,")")]})," "]})]}),r&&Object(s.jsx)("button",{className:"btn btn-primary",onClick:function(){return Ws.push("/profile/edit")},children:d("common:Edit")}),n&&Object(s.jsx)("button",{className:"btn btn-danger",onClick:function(){return a(!0)},children:d("user:Delete user account")}),Object(s.jsx)("button",{className:"btn btn-secondary",onClick:function(){return"/profile"===l?Ws.push("/"):Ws.go(-1)},children:d("/profile"===l?"common:Back to home":"common:Back")})]})]})})})]})]})})));var xt=Object(N.a)()(Object(k.c)((function(e){return{user:e.user}}))((function(e){var t=e.t,a=e.user;return Object(s.jsx)("div",{children:Object(s.jsx)(ft,{editable:!0,t:t,user:a})})}))),gt=a(472),vt=a(473),kt=a(474),wt=a(475),yt=a(234),Nt=a(238),_t=a(476),St=a(477),Dt=a(110),Ct=a(478),Et=a(486),At=a(488);function Mt(e){var t=e.isDisabled,a=e.isMore,r=e.sportImg,n=e.workout;return Object(s.jsx)(te.a,{className:"calendar-workout".concat(a),to:"/workouts/".concat(n.id),children:Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("img",{alt:"workout sport logo",className:"workout-sport ".concat(t),src:r,title:n.title}),n.records.length>0&&Object(s.jsx)("sup",{children:Object(s.jsx)("i",{className:"fa fa-trophy custom-fa-small","aria-hidden":"true",title:n.records.map((function(e){return" ".concat(xe.filter((function(t){return t.record_type===e.record_type}))[0].label)}))})})]})})}var Tt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={isHidden:!0},r}return Object(x.a)(a,[{key:"handleDisplayMore",value:function(){this.setState({isHidden:!this.state.isHidden})}},{key:"render",value:function(){var e=this,t=this.props,a=t.dayWorkouts,r=t.isDisabled,n=t.sports,o=this.state.isHidden;return Object(s.jsxs)("div",{children:[a.map((function(e){return Object(s.jsx)(Mt,{workout:e,isDisabled:r,isMore:"",sportImg:n.filter((function(t){return t.id===e.sport_id})).map((function(e){return e.img}))},e.id)})),a.length>2&&Object(s.jsx)("i",{className:"fa fa-".concat(o?"plus":"times"," calendar-more"),"aria-hidden":"true",onClick:function(){return e.handleDisplayMore()},title:"show more workouts"}),!o&&Object(s.jsx)("div",{className:"calendar-display-more",children:a.map((function(e){return Object(s.jsx)(Mt,{workout:e,isDisabled:r,isMore:"-more",sportImg:n.filter((function(t){return t.id===e.sport_id})).map((function(e){return e.img}))},e.id)}))})]})}}]),a}(o.a.Component),Pt=function(e,t){var a=Object(gt.a)(e),s=Object(vt.a)(e),r=t?1:0;return{start:Object(kt.a)(a,{weekStartsOn:r}),end:Object(wt.a)(s)}},Ft=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;Object(f.a)(this,a),r=t.call(this,e,s);var n=new Date;return r.state={currentMonth:n,startDate:Pt(n,e.weekm).start,endDate:Pt(n,e.weekm).end,weekStartOnMonday:e.weekm},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadMonthWorkouts(this.state.startDate,this.state.endDate)}},{key:"renderHeader",value:function(e){var t=this;return Object(s.jsxs)("div",{className:"header row flex-middle",children:[Object(s.jsx)("div",{className:"col col-start",onClick:function(){return t.handlePrevMonth()},children:Object(s.jsx)("i",{className:"fa fa-chevron-left","aria-hidden":"true"})}),Object(s.jsx)("div",{className:"col col-center",children:Object(s.jsx)("span",{children:Object(D.a)(this.state.currentMonth,"MMM yyyy",e)})}),Object(s.jsx)("div",{className:"col col-end",onClick:function(){return t.handleNextMonth()},children:Object(s.jsx)("i",{className:"fa fa-chevron-right","aria-hidden":"true"})})]})}},{key:"renderDays",value:function(e){for(var t=[],a=this.state.startDate,r=0;r<7;r++)t.push(Object(s.jsx)("div",{className:"col col-center",children:Object(D.a)(Object(yt.a)(a,r),"EEE",e)},r));return Object(s.jsx)("div",{className:"days row",children:t})}},{key:"filterWorkouts",value:function(e){var t=this.props,a=t.workouts,s=t.user;return a?a.filter((function(t){return Object(Nt.a)(L(t.workout_date,s.timezone),e)})):[]}},{key:"renderCells",value:function(){for(var e=this.state,t=e.currentMonth,a=e.startDate,r=e.endDate,n=e.weekStartOnMonday,o=this.props.sports,c=[],i=[],l=a,d="";l<=r;){for(var u=0;u<7;u++){d=Object(D.a)(l,"d");var m=this.filterWorkouts(l),j=Object(_t.a)(l,t)?"":"-disabled",p=n?[5,6].includes(u):[0,6].includes(u);i.push(Object(s.jsx)("div",{className:"col cell ".concat(p?" weekend":"").concat(Object(St.a)(l)?" today":""),children:Object(s.jsxs)("div",{className:"img".concat(j),children:[Object(s.jsx)("span",{className:"number",children:d}),Object(s.jsx)(Tt,{dayWorkouts:m,isDisabled:j,sports:o})]})},l)),l=Object(yt.a)(l,1)}c.push(Object(s.jsx)("div",{className:"row",children:i},l)),i=[]}return Object(s.jsx)("div",{className:"body",children:c})}},{key:"updateStateDate",value:function(e){var t=Pt(e,this.state.weekStartOnMonday),a=t.start,s=t.end;this.setState({currentMonth:e,startDate:a,endDate:s}),this.props.loadMonthWorkouts(a,s)}},{key:"handleNextMonth",value:function(){var e=Object(Dt.a)(this.state.currentMonth,1);this.updateStateDate(e)}},{key:"handlePrevMonth",value:function(){var e=Object(Ct.a)(this.state.currentMonth,1);this.updateStateDate(e)}},{key:"render",value:function(){var e={locale:"fr"===this.props.language?Et.a:At.a};return Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"calendar",children:[this.renderHeader(e),this.renderDays(e),this.renderCells()]})})}}]),a}(o.a.Component),zt=Object(k.c)((function(e){return{workouts:e.calendarWorkouts.data,language:e.language,sports:e.sports.data,user:e.user}}),(function(e){return{loadMonthWorkouts:function(t,a){var s,r,n="yyyy-MM-dd";e((s=Object(D.a)(t,n),r=Object(D.a)(a,n),function(e){return H.getData("workouts",{from:s,to:r,order:"asc",per_page:100}).then((function(t){"success"===t.status?e({type:"UPDATE_CALENDAR",workouts:t.data.workouts}):e(V("workouts|".concat(t.message)))})).catch((function(t){return e(V("workouts|".concat(t)))}))}))}}}))(Ft);function Rt(e){var t=e.records,a=e.sports,r=e.t,n=e.user,o=ye(a,r),c=t.reduce((function(e,t){var a=o.find((function(e){return e.id===t.sport_id}));return void 0===e[a.label]&&(e[a.label]={img:a.img,records:[]}),e[a.label].records.push(function(e,t){var a;switch(e.record_type){case"AS":case"MS":a="".concat(e.value," km/h");break;case"FD":a="".concat(e.value," km");break;default:a=e.value}var s=xe.filter((function(t){return t.record_type===e.record_type})),r=Object(pe.a)(s,1)[0];return{workout_date:ge(L(e.workout_date,t)).workout_date,workout_id:e.workout_id,id:e.id,record_type:r.label,value:a}}(t,n.timezone)),e}),{});return Object(s.jsxs)("div",{className:"card workout-card",children:[Object(s.jsx)("div",{className:"card-header",children:r("workouts:Personal records")}),Object(s.jsx)("div",{className:"card-body",children:0===Object.keys(c).length?r("common:No records."):Object.keys(c).sort().map((function(e){return Object(s.jsxs)("div",{children:[Object(s.jsxs)("span",{className:"heading-span",children:[Object(s.jsx)("img",{alt:"".concat(e," logo"),className:"record-logo",src:c[e].img}),e]}),Object(s.jsxs)("table",{className:"table table-borderless table-sm record-table",children:[Object(s.jsx)("thead",{children:Object(s.jsx)("tr",{children:Object(s.jsxs)("th",{colSpan:"3",children:[Object(s.jsx)("img",{alt:"".concat(e," logo"),className:"record-logo",src:c[e].img}),e]})})}),Object(s.jsx)("tbody",{children:c[e].records.map((function(e){return Object(s.jsxs)("tr",{className:"record-tr",children:[Object(s.jsx)("td",{className:"record-td",children:r("workouts:".concat(e.record_type))}),Object(s.jsx)("td",{className:"record-td text-right",children:e.value}),Object(s.jsx)("td",{className:"record-td text-right",children:Object(s.jsx)(te.a,{to:"/workouts/".concat(e.workout_id),children:e.workout_date})})]},e.id)}))})]})]},e)}))})]})}var Lt=a(235),Ut=a(479),It=[{duration:"week",dateFormat:"yyyy-MM-dd",xAxis:"dd/MM"},{duration:"month",dateFormat:"yyyy-MM",xAxis:"MM/yyyy"},{duration:"year",dateFormat:"yyyy",xAxis:"yyyy"}],Wt=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a="0";t&&(a=String(Math.floor(e/86400)),e%=86400);var s=String(Math.floor(e/3600)).padStart(2,"0");e%=3600;var r=String(Math.floor(e/60)).padStart(2,"0"),n=String(e%60).padStart(2,"0");return t?"".concat("0"===a?"":"".concat(a,"d:")).concat("00"===s?"":"".concat(s,"h:")).concat(r,"m:").concat(n,"s"):"".concat("00"===s?"":"".concat(s,":")).concat(r,":").concat(n)},Ht=function(e,t){return 0===t?"":"distance"===e?"".concat(t.toFixed(2)," km"):"duration"===e?Wt(t):t},qt=function(e,t){switch(e){case"week":return Object(yt.a)(t,7);case"year":return Object(Lt.a)(t,1);case"month":default:return Object(Dt.a)(t,1)}},Bt=function(e,t,a,s,r){for(var n=[],o=[],c=[],i=function(r){var i=It.filter((function(e){return e.duration===a.duration})),l=Object(pe.a)(i,1)[0],d=Object(D.a)(r,l.dateFormat),u=Object(D.a)(r,l.xAxis),m={date:u},j={date:u},p={date:u};e[d]&&Object.keys(e[d]).filter((function(e){return!s||s.includes(+e)})).map((function(a){var s=t.filter((function(e){return e.id===+a}))[0].label;return m[s]=e[d][a].nb_workouts,j[s]=e[d][a].total_distance,p[s]=e[d][a].total_duration,null})),n.push(m),o.push(j),c.push(p)},l=function(e,t,a){switch(e){case"week":return Object(kt.a)(t,{weekStartsOn:a?1:0});case"year":return Object(Ut.a)(t);case"month":default:return Object(gt.a)(t)}}(a.duration,a.start,r);l<=a.end;l=qt(a.duration,l))i(l);return{workouts:n,distance:o,duration:c}},Vt=function(e,t){return"duration"===e?Wt(t,!0):"distance"===e?t.toFixed(2):t};function Gt(e){if(e.active){var t=e.displayedData,a=e.payload,r=e.label,n=0;return a.map((function(e){return n+=e.value})),Object(s.jsxs)("div",{className:"custom-tooltip",children:[Object(s.jsx)("p",{className:"custom-tooltip-label",children:r}),a.map((function(e){return Object(s.jsxs)("p",{style:{color:e.fill},children:[e.name,": ",Vt(t,e.value)," ",e.unit]},e.name)})),a.length>0&&Object(s.jsxs)("p",{children:["Total: ",Vt(t,n)]})]})}return null}function Jt(e){var t=e.displayedData,a=e.x,r=e.y,n=e.width,o=e.value;if(!o)return null;var c=Ht(t,o);return Object(s.jsx)("g",{children:Object(s.jsx)("text",{x:a+n/2,y:r-10,fill:"#666",fontSize:"11",textAnchor:"middle",dominantBaseline:"middle",children:c})})}var Kt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={displayedData:"distance"},r}return Object(x.a)(a,[{key:"handleRadioChange",value:function(e){this.setState({displayedData:e.target.name})}},{key:"render",value:function(){var e=this,t=this.state.displayedData,a=this.props,r=a.sports,n=a.stats,o=a.t;return 0===Object.keys(n).length?o("common:No workouts."):Object(s.jsxs)("div",{className:"chart-stats",children:[Object(s.jsxs)("div",{className:"row chart-radio",children:[Object(s.jsxs)("label",{className:"radioLabel col",children:[Object(s.jsx)("input",{type:"radio",name:"distance",checked:"distance"===t,onChange:function(t){return e.handleRadioChange(t)}}),o("statistics:distance")]}),Object(s.jsxs)("label",{className:"radioLabel col",children:[Object(s.jsx)("input",{type:"radio",name:"duration",checked:"duration"===t,onChange:function(t){return e.handleRadioChange(t)}}),o("statistics:duration")]}),Object(s.jsxs)("label",{className:"radioLabel col",children:[Object(s.jsx)("input",{type:"radio",name:"workouts",checked:"workouts"===t,onChange:function(t){return e.handleRadioChange(t)}}),o("statistics:workouts")]})]}),Object(s.jsx)(qe.f,{height:300,children:Object(s.jsxs)(qe.c,{data:n[t],margin:{top:15,bottom:0},children:[Object(s.jsx)(qe.h,{dataKey:"date",interval:0}),Object(s.jsx)(qe.i,{tickFormatter:function(e){return Ht(t,e)}}),Object(s.jsx)(qe.g,{content:Object(s.jsx)(Gt,{displayedData:t})}),r.map((function(e,a){return Object(s.jsx)(qe.b,{isAnimationActive:!1,dataKey:e.label,stackId:"a",fill:fe[a],label:a===r.length-1?Object(s.jsx)(Jt,{displayedData:t}):"",name:o("sports:".concat(e.label))},e.id)}))]})})]})}}]),a}(o.a.PureComponent),Yt=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.updateData()}},{key:"componentDidUpdate",value:function(e){(this.props.user.username&&this.props.user.username!==e.user.username||this.props.statsParams!==e.statsParams)&&this.updateData()}},{key:"updateData",value:function(){this.props.user.username&&this.props.loadWorkouts(this.props.user.username,this.props.user.weekm,this.props.statsParams)}},{key:"render",value:function(){var e=this.props,t=e.displayedSports,a=e.sports,r=e.statistics,n=e.statsParams,o=e.displayEmpty,c=e.t,i=e.user;if(!o&&0===Object.keys(r).length)return Object(s.jsx)("span",{children:c("common:No workouts.")});var l=Bt(r,a,n,t,i.weekm);return Object(s.jsx)(Kt,{sports:a,stats:l,t:c})}}]),a}(o.a.PureComponent),Xt=Object(k.c)((function(e){return{sports:e.sports.data,statistics:e.statistics.data,user:e.user}}),(function(e){return{loadWorkouts:function(t,a,s){var r="yyyy-MM-dd",n="week"===s.duration?"".concat(s.duration).concat(a?"m":""):s.duration,o={from:Object(D.a)(s.start,r),to:Object(D.a)(s.end,r),time:n};e(function(e,t,a){return function(s){return H.getData("stats/".concat(e,"/").concat(t),a).then((function(e){"success"===e.status?s(q("statistics",e.data)):s(V("statistics|".concat(e.message)))})).catch((function(e){return s(V("statistics|".concat(e)))}))}}(t,s.type,o))}}}))(Yt),$t=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;Object(f.a)(this,a),r=t.call(this,e,s);var n=new Date;return r.state={start:Object(gt.a)(n),end:Object(vt.a)(n),duration:"week",type:"by_time"},r}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props.t;return Object(s.jsxs)("div",{className:"card workout-card",children:[Object(s.jsx)("div",{className:"card-header",children:e("dashboard:This month")}),Object(s.jsx)("div",{className:"card-body",children:Object(s.jsx)(Xt,{displayEmpty:!1,statsParams:this.state,t:e})})]})}}]),a}(o.a.Component);function Zt(e){var t=e.t,a=e.user,r=a.total_duration.match(/day/g)?"".concat(a.total_duration.split(" ")[0]," ").concat(a.total_duration.match(/days/g)?t("common:days"):t("common:day")):"0 ".concat(t("common:days"),","),n=a.total_duration.match(/day/g)?a.total_duration.split(", ")[1]:a.total_duration;return n="".concat(n.split(":")[0],"h ").concat(n.split(":")[1],"min"),Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-calendar fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:a.nb_workouts}),Object(s.jsx)("div",{children:"".concat(1===a.nb_workouts?t("common:workout"):t("common:workouts"))})]})]})})}),Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-road fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:Number(a.total_distance).toFixed(2)}),Object(s.jsx)("div",{children:"km"})]})]})})}),Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-clock-o fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:r}),Object(s.jsx)("div",{children:n})]})]})})}),Object(s.jsx)("div",{className:"col-lg-3 col-md-6 col-sm-6",children:Object(s.jsx)("div",{className:"card workout-card",children:Object(s.jsxs)("div",{className:"card-body row",children:[Object(s.jsx)("div",{className:"col-3",children:Object(s.jsx)("i",{className:"fa fa-tags fa-3x fa-color"})}),Object(s.jsxs)("div",{className:"col-9 text-right",children:[Object(s.jsx)("div",{className:"huge",children:a.nb_sports}),Object(s.jsx)("div",{children:"".concat(1===a.nb_sports?t("common:sport"):t("common:sports"))})]})]})})})]})}function Qt(e){var t=e.sports,a=e.t,r=e.user,n=e.workout;return Object(s.jsxs)("div",{className:"card workout-card text-center",children:[Object(s.jsx)("div",{className:"card-header",children:Object(s.jsxs)(te.a,{to:"/workouts/".concat(n.id),children:[t.filter((function(e){return e.id===n.sport_id})).map((function(e){return a("sports:".concat(e.label))}))," ","-"," ",Object(D.a)(L(n.workout_date,r.timezone),"dd/MM/yyyy HH:mm")]})}),Object(s.jsx)("div",{className:"card-body",children:Object(s.jsxs)("div",{className:"row",children:[n.map&&Object(s.jsx)("div",{className:"col",children:Object(s.jsx)(pt,{workout:n})}),Object(s.jsx)("div",{className:"col",children:Object(s.jsxs)("p",{children:[Object(s.jsx)("i",{className:"fa fa-clock-o","aria-hidden":"true"})," ",a("workouts:Duration"),": ",n.moving,n.map?Object(s.jsxs)("span",{children:[Object(s.jsx)("br",{}),Object(s.jsx)("br",{})]}):" - ",Object(s.jsx)("i",{className:"fa fa-road","aria-hidden":"true"})," ",a("workouts:Distance"),": ",n.distance," km"]})})]})})]})}var ea=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={page:1},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadWorkouts()}},{key:"render",value:function(){var e=this,t=this.props,a=t.loadMoreWorkouts,r=t.message,n=t.records,o=t.sports,c=t.t,i=t.user,l=t.workouts,d=!(l.length>0)||null===l[l.length-1].previous_workout,u=this.state.page;return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",c("common:Dashboard")]})}),r?Object(s.jsx)(_,{message:r,t:c}):l&&i.total_duration&&o.length>0&&Object(s.jsxs)("div",{className:"container dashboard",children:[Object(s.jsx)(Zt,{user:i,t:c}),Object(s.jsxs)("div",{className:"row",children:[Object(s.jsxs)("div",{className:"col-md-4",children:[Object(s.jsx)($t,{t:c}),Object(s.jsx)(Rt,{t:c,records:n,sports:o,user:i})]}),Object(s.jsxs)("div",{className:"col-md-8",children:[Object(s.jsx)(zt,{weekm:i.weekm}),l.length>0?l.map((function(e){return Object(s.jsx)(Qt,{workout:e,sports:o,t:c,user:i},e.id)})):Object(s.jsx)(mt,{t:c}),!d&&Object(s.jsx)("input",{type:"submit",className:"btn btn-default btn-md btn-block",value:"Load more workouts",onClick:function(){a(u+1),e.setState({page:u+1})}})]})]})]})]})}}]),a}(o.a.Component),ta=Object(N.a)()(Object(k.c)((function(e){return{workouts:e.workouts.data,message:e.message,records:e.records.data,sports:e.sports.data,user:e.user}}),(function(e){return{loadWorkouts:function(){e(Y("getData","workouts",{page:1})),e(Y("getData","records"))},loadMoreWorkouts:function(t){e(Fe({page:t}))}}}))(ea));function aa(){return Object(s.jsx)("footer",{className:"footer",children:Object(s.jsxs)("div",{className:"container",children:[Object(s.jsx)("strong",{children:"FitTrackee"})," v","0.4.2"," -"," ",Object(s.jsx)("a",{href:"https://github.com/SamR1/FitTrackee",target:"_blank",rel:"noopener noreferrer",children:"source code"})," ","under"," ",Object(s.jsx)("a",{href:"https://choosealicense.com/licenses/gpl-3.0/",target:"_blank",rel:"noopener noreferrer",children:"GPLv3"})," ","license -"," ",Object(s.jsx)("a",{href:"https://samr1.github.io/FitTrackee/",target:"_blank",rel:"noopener noreferrer",children:"documentation"})]})})}var sa=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.UserLogout()}},{key:"render",value:function(){return Object(s.jsx)("div",{className:"container dashboard",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-2"}),Object(s.jsx)("div",{className:"card col-8",children:Object(s.jsx)("div",{className:"card-body",children:Object(s.jsx)("div",{className:"text-center",children:Object(s.jsxs)(je.a,{i18nKey:"user:loggedOut",children:["You are now logged out. Click ",Object(s.jsx)(te.a,{to:"/login",children:"here"})," to log back in."]})})})}),Object(s.jsx)("div",{className:"col-2"})]})})}}]),a}(o.a.Component),ra=Object(k.c)((function(e){return{user:e.user}}),(function(e){return{UserLogout:function(){e({type:"LOGOUT"})}}}))(sa);function na(){return(na=Object.assign||function(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var ca=n.createElement("path",{d:"m466.916 27.803h-421.832c-24.859 0-45.084 20.225-45.084 45.084v366.226c0 24.859 20.225 45.084 45.084 45.084h421.832c24.859 0 45.084-20.225 45.084-45.084v-366.226c0-24.859-20.225-45.084-45.084-45.084z",fill:"#f0f9ff"}),ia=n.createElement("path",{d:"m198.58 188.334-181.344-150.862c-7.75 6.107-13.456 14.691-15.905 24.554l164.142 136.551h33.102z",fill:"#f40055"}),la=n.createElement("path",{d:"m313.425 198.576h33.93l163.447-135.973c-2.325-9.923-7.93-18.592-15.613-24.796l-181.764 151.211z",fill:"#c20044"}),da=n.createElement("path",{d:"m165.472 313.425-164.141 136.549c2.449 9.863 8.155 18.447 15.905 24.553l181.344-150.861-.005-10.241z",fill:"#f40055"}),ua=n.createElement("path",{d:"m313.425 313.425v9.557l181.765 151.211c7.683-6.204 13.288-14.874 15.613-24.796l-163.446-135.971z",fill:"#c20044"}),ma=n.createElement("path",{d:"m53.273 27.803 145.302 120.879v-120.879z",fill:"#406bd4"}),ja=n.createElement("path",{d:"m313.425 150.571v-122.768h148.082z",fill:"#3257b0"}),pa=n.createElement("path",{d:"m394.732 198.575 117.268-97.556v97.556z",fill:"#3257b0"}),ha=n.createElement("g",{fill:"#406bd4"},n.createElement("path",{d:"m0 99.317v99.258h119.313z"}),n.createElement("path",{d:"m0 313.425v97.699l117.44-97.699z"}),n.createElement("path",{d:"m50.49 484.197 148.085-122.676v122.676z"})),ba=n.createElement("path",{d:"m313.425 484.197v-124.139l149.221 124.139z",fill:"#3257b0"}),Oa=n.createElement("path",{d:"m512 409.423-115.395-95.998h115.395z",fill:"#3257b0"}),fa=n.createElement("path",{d:"m512 222.142h-222.142v-194.339h-67.716v194.339h-222.142v67.716h222.142v194.339h67.716v-194.339h222.142z",fill:"#f40055"}),xa=n.createElement("path",{d:"m289.858 222.142v-194.339h-33.858v456.394h33.858v-194.339h222.142v-67.716z",fill:"#c20044"});function ga(e,t){var a=e.title,s=e.titleId,r=oa(e,["title","titleId"]);return n.createElement("svg",na({id:"Capa_1",enableBackground:"new 0 0 512 512",height:512,viewBox:"0 0 512 512",width:512,xmlns:"http://www.w3.org/2000/svg",ref:t,"aria-labelledby":s},r),a?n.createElement("title",{id:s},a):null,ca,ia,la,da,ua,ma,ja,pa,ha,ba,Oa,fa,xa)}var va=n.forwardRef(ga);a.p;function ka(){return(ka=Object.assign||function(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var ya=n.createElement("path",{d:"m173.899 31.804h-8.707l-4.397-4h-115.711c-24.859-.001-45.084 20.224-45.084 45.083v366.226c0 24.859 20.225 45.084 45.084 45.084h115.711l6.348-4h6.755v-448.393z",fill:"#406bd4"}),Na=n.createElement("path",{d:"m466.916 27.803h-115.711l-4.523 4h-5.141v448.393h4.141l5.523 4h115.711c24.859 0 45.084-20.225 45.084-45.084v-366.225c0-24.859-20.225-45.084-45.084-45.084z",fill:"#c20044"}),_a=n.createElement("path",{d:"m160.795 27.803h190.409v456.394h-190.409z",fill:"#f0f9ff"}),Sa=n.createElement("path",{d:"m256 27.803h95.205v456.394h-95.205z",fill:"#cee5f5"});function Da(e,t){var a=e.title,s=e.titleId,r=wa(e,["title","titleId"]);return n.createElement("svg",ka({id:"Capa_1",enableBackground:"new 0 0 512 512",height:512,viewBox:"0 0 512 512",width:512,xmlns:"http://www.w3.org/2000/svg",ref:t,"aria-labelledby":s},r),a?n.createElement("title",{id:s},a):null,ya,Na,_a,Sa)}var Ca=n.forwardRef(Da),Ea=(a.p,[{name:"en",selected:!0,flag:Object(s.jsx)(va,{})},{name:"fr",selected:!1,flag:Object(s.jsx)(Ca,{})}]),Aa=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e){var s;return Object(f.a)(this,a),(s=t.call(this,e)).state={isOpen:!1},s}return Object(x.a)(a,[{key:"toggleDropdown",value:function(){this.setState((function(e){return{isOpen:!e.isOpen}}))}},{key:"render",value:function(){var e=this,t=this.state.isOpen,a=this.props,r=a.language,n=a.onUpdateLanguage;return Object(s.jsx)("div",{className:"dropdown-wrapper",onClick:function(){return e.toggleDropdown()},children:Object(s.jsx)("ul",{className:"dropdown-list i18n-flag",children:Ea.filter((function(e){return t?e:e.name===r})).map((function(e){return Object(s.jsxs)("li",{className:"dropdown-item".concat(e.name===r&&t?" dropdown-item-selected":""),onClick:function(){return n(e.name,r)},children:[e.flag," ",e.name]},e.name)}))})})}}]),a}(n.Component),Ma=Object(k.c)((function(e){return{language:e.language}}),(function(e){return{onUpdateLanguage:function(t,a){t!==a&&e(X(t))}}}))(Aa),Ta=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(){return Object(f.a)(this,a),t.apply(this,arguments)}return Object(x.a)(a,[{key:"render",value:function(){var e=this.props,t=e.admin,a=e.isAuthenticated,r=e.picture,n=e.t,o=e.username;return Object(s.jsx)("header",{children:Object(s.jsx)("nav",{className:"navbar navbar-expand-lg navbar-light bg-light",children:Object(s.jsxs)("div",{className:"container",children:[Object(s.jsx)("span",{className:"navbar-brand",children:"FitTrackee"}),Object(s.jsx)("button",{className:"navbar-toggler",type:"button","data-toggle":"collapse","data-target":"#navbarSupportedContent","aria-controls":"navbarSupportedContent","aria-expanded":"false","aria-label":"Toggle navigation",children:Object(s.jsx)("span",{className:"navbar-toggler-icon"})}),Object(s.jsxs)("div",{className:"collapse navbar-collapse",id:"navbarSupportedContent",children:[Object(s.jsxs)("ul",{className:"navbar-nav mr-auto",children:[Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/"},children:n("common:Dashboard")})}),a&&Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/workouts/history"},children:n("Workouts")})}),a&&Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/workouts/statistics"},children:n("common:Statistics")})}),t&&Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/admin"},children:"Admin"})}),a&&Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/workouts/add"},children:Object(s.jsx)("strong",{children:n("common:Add workout")})})})]}),Object(s.jsxs)("ul",{className:"navbar-nav flex-row ml-md-auto d-none d-md-flex",children:[!a&&Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/register"},children:n("user:Register")})}),!a&&Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/login"},children:n("user:Login")})}),a&&Object(s.jsxs)(s.Fragment,{children:[!0===r?Object(s.jsx)("img",{alt:"Avatar",src:"".concat(T,"users/").concat(o,"/picture?").concat(Date.now()),className:"img-fluid App-nav-profile-img"}):Object(s.jsx)("i",{className:"fa fa-user-circle-o fa-2x no-picture","aria-hidden":"true"}),Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/profile"},children:o})}),Object(s.jsx)("li",{className:"nav-item",children:Object(s.jsx)(te.a,{className:"nav-link",to:{pathname:"/logout"},children:n("user:Logout")})})]}),Object(s.jsx)("li",{children:Object(s.jsx)(Ma,{})})]})]})]})})})}}]),a}(o.a.PureComponent),Pa=Object(N.a)()(Object(k.c)((function(e){var t=e.user;return{admin:t.admin,isAuthenticated:t.isAuthenticated,picture:t.picture,username:t.username}}))(Ta));function Fa(){return(Fa=Object.assign||function(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var Ra=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M468.683,287.265h-69.07c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h69.07 c4.147,0,7.508-3.361,7.508-7.508C476.191,290.626,472.83,287.265,468.683,287.265z"}))),La=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M105.012,268.377L85.781,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L58.034,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C109.507,275.266,108.499,270.62,105.012,268.377z"}))),Ua=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M194.441,268.377L175.21,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.47,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.776l-17.471-11.243 c-3.487-2.245-8.133-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L147.463,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.47,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C198.936,275.266,197.928,270.62,194.441,268.377z"}))),Ia=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M283.871,268.377L264.64,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.471-11.243 c-3.486-2.245-8.134-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L236.892,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.886-1.216,6.32-3.446C288.366,275.266,287.358,270.62,283.871,268.377z"}))),Wa=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M373.3,268.377L354.069,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L326.322,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C377.795,275.266,376.787,270.62,373.3,268.377z"}))),Ha=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M271.792,330.359H15.016V181.642h93.1c4.147,0,7.508-3.361,7.508-7.508c0-4.147-3.361-7.508-7.508-7.508H12.513 C5.613,166.626,0,172.24,0,179.14v153.722c0,6.9,5.613,12.513,12.513,12.513h259.278c4.147,0,7.508-3.361,7.508-7.508 C279.299,333.72,275.939,330.359,271.792,330.359z"}))),qa=n.createElement("g",null,n.createElement("g",null,n.createElement("path",{d:"M499.487,166.626H162.174c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h334.811v148.716H323.848 c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h175.64c6.9,0,12.513-5.613,12.513-12.513V179.14 C512.001,172.24,506.387,166.626,499.487,166.626z"})));function Ba(e,t){var a=e.title,s=e.titleId,r=za(e,["title","titleId"]);return n.createElement("svg",Fa({id:"Layer_1",xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 512.001 512.001",style:{enableBackground:"new 0 0 512.001 512.001"},xmlSpace:"preserve",ref:t,"aria-labelledby":s},r),a?n.createElement("title",{id:s},a):null,Ra,La,Ua,Ia,Wa,Ha,qa)}var Va=n.forwardRef(Ba);a.p;function Ga(){return(Ga=Object.assign||function(e){for(var t=1;t=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var Ka=n.createElement("g",null,n.createElement("path",{d:"M339.798,260.429c0.13-0.026,0.257-0.061,0.385-0.094c0.109-0.028,0.219-0.051,0.326-0.084 c0.125-0.038,0.247-0.085,0.369-0.129c0.108-0.039,0.217-0.074,0.324-0.119c0.115-0.048,0.226-0.104,0.338-0.157 c0.109-0.052,0.22-0.1,0.327-0.158c0.107-0.057,0.208-0.122,0.312-0.184c0.107-0.064,0.215-0.124,0.319-0.194 c0.111-0.074,0.214-0.156,0.321-0.236c0.09-0.067,0.182-0.13,0.27-0.202c0.162-0.133,0.316-0.275,0.466-0.421 c0.027-0.026,0.056-0.048,0.083-0.075c0.028-0.028,0.052-0.059,0.079-0.088c0.144-0.148,0.284-0.3,0.416-0.46 c0.077-0.094,0.144-0.192,0.216-0.289c0.074-0.1,0.152-0.197,0.221-0.301c0.074-0.111,0.139-0.226,0.207-0.34 c0.057-0.096,0.118-0.19,0.171-0.289c0.062-0.115,0.114-0.234,0.169-0.351c0.049-0.104,0.101-0.207,0.146-0.314 c0.048-0.115,0.086-0.232,0.128-0.349c0.041-0.114,0.085-0.227,0.12-0.343c0.036-0.118,0.062-0.238,0.092-0.358 c0.029-0.118,0.063-0.234,0.086-0.353c0.028-0.141,0.045-0.283,0.065-0.425c0.014-0.1,0.033-0.199,0.043-0.3 c0.025-0.249,0.038-0.498,0.038-0.748V92.76c0-4.143-3.357-7.5-7.5-7.5h-236.25c-0.066,0-0.13,0.008-0.196,0.01 c-0.143,0.004-0.285,0.01-0.427,0.022c-0.113,0.009-0.225,0.022-0.337,0.037c-0.128,0.016-0.255,0.035-0.382,0.058 c-0.119,0.021-0.237,0.046-0.354,0.073c-0.119,0.028-0.238,0.058-0.356,0.092c-0.117,0.033-0.232,0.069-0.346,0.107 c-0.117,0.04-0.234,0.082-0.349,0.128c-0.109,0.043-0.216,0.087-0.322,0.135c-0.118,0.053-0.235,0.11-0.351,0.169 c-0.099,0.051-0.196,0.103-0.292,0.158c-0.116,0.066-0.23,0.136-0.343,0.208c-0.093,0.06-0.184,0.122-0.274,0.185 c-0.106,0.075-0.211,0.153-0.314,0.235c-0.094,0.075-0.186,0.152-0.277,0.231c-0.09,0.079-0.179,0.158-0.266,0.242 c-0.099,0.095-0.194,0.194-0.288,0.294c-0.047,0.05-0.097,0.094-0.142,0.145c-0.027,0.03-0.048,0.063-0.074,0.093 c-0.094,0.109-0.182,0.223-0.27,0.338c-0.064,0.084-0.13,0.168-0.19,0.254c-0.078,0.112-0.15,0.227-0.222,0.343 c-0.059,0.095-0.12,0.189-0.174,0.286c-0.063,0.112-0.118,0.227-0.175,0.342c-0.052,0.105-0.106,0.21-0.153,0.317 c-0.049,0.113-0.092,0.23-0.135,0.345c-0.043,0.113-0.087,0.225-0.124,0.339c-0.037,0.115-0.067,0.232-0.099,0.349 c-0.032,0.12-0.066,0.239-0.093,0.36c-0.025,0.113-0.042,0.228-0.062,0.342c-0.022,0.13-0.044,0.26-0.06,0.39 c-0.013,0.108-0.019,0.218-0.027,0.328c-0.01,0.14-0.019,0.28-0.021,0.421c-0.001,0.041-0.006,0.081-0.006,0.122v46.252 c0,4.143,3.357,7.5,7.5,7.5s7.5-3.357,7.5-7.5v-29.595l66.681,59.037c-0.348,0.245-0.683,0.516-0.995,0.827l-65.687,65.687v-49.288 c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v9.164h-38.75c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h38.75v43.231 c0,4.143,3.357,7.5,7.5,7.5h236.25c0.247,0,0.494-0.013,0.74-0.037c0.115-0.011,0.226-0.033,0.339-0.049 C339.542,260.469,339.67,260.454,339.798,260.429z M330.834,234.967l-65.688-65.687c-0.042-0.042-0.087-0.077-0.13-0.117 l49.383-41.897c3.158-2.68,3.546-7.412,0.866-10.571c-2.678-3.157-7.41-3.547-10.571-0.866l-84.381,71.59l-98.444-87.158h208.965 V234.967z M185.878,179.888c0.535-0.535,0.969-1.131,1.308-1.765l28.051,24.835c1.418,1.255,3.194,1.885,4.972,1.885 c1.726,0,3.451-0.593,4.853-1.781l28.587-24.254c0.26,0.38,0.553,0.743,0.89,1.08l65.687,65.687H120.191L185.878,179.888z"}),n.createElement("path",{d:"M7.5,170.676h126.667c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H7.5c-4.143,0-7.5,3.357-7.5,7.5 S3.357,170.676,7.5,170.676z"}),n.createElement("path",{d:"M20.625,129.345H77.5c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H20.625c-4.143,0-7.5,3.357-7.5,7.5 S16.482,129.345,20.625,129.345z"}),n.createElement("path",{d:"M62.5,226.51h-55c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h55c4.143,0,7.5-3.357,7.5-7.5S66.643,226.51,62.5,226.51z"}));function Ya(e,t){var a=e.title,s=e.titleId,r=Ja(e,["title","titleId"]);return n.createElement("svg",Ga({id:"Capa_1",xmlns:"http://www.w3.org/2000/svg",xmlnsXlink:"http://www.w3.org/1999/xlink",x:"0px",y:"0px",viewBox:"0 0 345.834 345.834",style:{enableBackground:"new 0 0 345.834 345.834"},xmlSpace:"preserve",ref:t,"aria-labelledby":s},r),a?n.createElement("title",{id:s},a):null,Ka)}var Xa=n.forwardRef(Ya);a.p;function $a(e){var t=Object(de.a)().t,a=e.action;return Object(s.jsx)("div",{className:"container dashboard",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-2"}),Object(s.jsx)("div",{className:"card col-8",children:Object(s.jsx)("div",{className:"card-body",children:Object(s.jsxs)("div",{className:"text-center ",children:["sent"===a&&Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("div",{className:"svg-icon",children:Object(s.jsx)(Xa,{})}),t("user:Check your email. If your address is in our database, you'll received an email with a link to reset your password.")]}),"updated"===a&&Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("div",{className:"svg-icon",children:Object(s.jsx)(Va,{})}),Object(s.jsxs)(je.a,{i18nKey:"user:updatedPasswordText",children:["Your password have been updated. Click",Object(s.jsx)(te.a,{to:"/login",children:"here"})," to log in."]})]})]})})}),Object(s.jsx)("div",{className:"col-2"})]})})}var Za=a(236),Qa=a.n(Za),es=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={formData:{},displayModal:!1},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.initForm()}},{key:"componentDidUpdate",value:function(e){e.user!==this.props.user&&this.initForm()}},{key:"initForm",value:function(){var e=this.props.user,t={};Object.keys(e).map((function(a){return null===e[a]?t[a]="":t[a]="birth_date"===a?Object(D.a)(new Date(e[a]),"yyyy-MM-DD"):e[a]})),this.setState({formData:t})}},{key:"handleFormChange",value:function(e){var t=this.state.formData;"weekm"===e.target.name?t.weekm="Monday"===e.target.value:t[e.target.name]=e.target.value,this.setState(t)}},{key:"displayModal",value:function(e){this.setState((function(t){return Object(S.a)(Object(S.a)({},t),{},{displayModal:e})}))}},{key:"render",value:function(){var e=this,t=this.props,a=t.message,r=t.onDeleteUser,n=t.onHandleProfileFormSubmit,o=t.t,c=t.user,i=this.state,l=i.displayModal,d=i.formData;return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",o("user:Profile Edition")]})}),d.isAuthenticated&&Object(s.jsxs)("div",{className:"container",children:[l&&Object(s.jsx)(We,{title:o("common:Confirmation"),text:o("user:Are you sure you want to delete your account? All data will be deleted, this cannot be undone."),confirm:function(){r(c.username),e.displayModal(!1)},close:function(){return e.displayModal(!1)}}),Object(s.jsx)("h1",{className:"page-title",children:o("user:Profile Edition")}),Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-md-2"}),Object(s.jsx)("div",{className:"col-md-8",children:Object(s.jsxs)("div",{className:"card",children:[Object(s.jsx)("div",{className:"card-header",children:c.username}),Object(s.jsx)("div",{className:"card-body",children:Object(s.jsx)("div",{className:"row",children:Object(s.jsxs)("div",{className:"col-md-12",children:[Object(s.jsxs)("form",{onSubmit:function(e){e.preventDefault(),n(d)},children:[Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Email"),":",Object(s.jsx)("input",{name:"email",className:"form-control input-lg",type:"text",value:d.email,readOnly:!0})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Registration Date"),":",Object(s.jsx)("input",{name:"createdAt",className:"form-control input-lg",type:"text",value:d.created_at,disabled:!0})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Password"),":",Object(s.jsx)("input",{name:"password",className:"form-control input-lg",type:"password",onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Password Confirmation"),":",Object(s.jsx)("input",{name:"password_conf",className:"form-control input-lg",type:"password",onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("hr",{}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:First Name"),":",Object(s.jsx)("input",{name:"first_name",className:"form-control input-lg",type:"text",value:d.first_name,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Last Name"),":",Object(s.jsx)("input",{name:"last_name",className:"form-control input-lg",type:"text",value:d.last_name,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Birth Date"),Object(s.jsx)("input",{name:"birth_date",className:"form-control input-lg",type:"date",value:d.birth_date,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Location"),":",Object(s.jsx)("input",{name:"location",className:"form-control input-lg",type:"text",value:d.location,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Bio"),":",Object(s.jsx)("textarea",{name:"bio",className:"form-control input-lg",maxLength:"200",value:d.bio,onChange:function(t){return e.handleFormChange(t)}})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Language"),":",Object(s.jsx)("select",{name:"language",className:"form-control input-lg",value:d.language,onChange:function(t){return e.handleFormChange(t)},children:Ea.map((function(e){return Object(s.jsx)("option",{value:e.name,children:e.name},e.name)}))})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:Timezone"),":",Object(s.jsx)(Qa.a,{className:"form-control timezone-custom",onChange:function(t){var a={target:{name:"timezone",value:t||"Europe/Paris"}};e.handleFormChange(a)},value:d.timezone})]})}),Object(s.jsx)("div",{className:"form-group",children:Object(s.jsxs)("label",{children:[o("user:First day of week"),":",Object(s.jsxs)("select",{name:"weekm",className:"form-control input-lg",value:d.weekm?"Monday":"Sunday",onChange:function(t){return e.handleFormChange(t)},children:[Object(s.jsx)("option",{value:"Sunday",children:o("user:Sunday")}),Object(s.jsx)("option",{value:"Monday",children:o("user:Monday")})]})]})}),Object(s.jsx)("button",{type:"submit",className:"btn btn-primary",children:o("common:Submit")}),Object(s.jsx)("button",{className:"btn btn-danger",onClick:function(t){t.preventDefault(),e.displayModal(!0)},children:o("user:Delete my account")}),Object(s.jsx)("button",{type:"submit",className:"btn btn-secondary",onClick:function(){return Ws.push("/profile")},children:o("common:Cancel")})]}),Object(s.jsx)(_,{message:a,t:o})]})})})]})}),Object(s.jsx)("div",{className:"col-md-2"})]})]})]})}}]),a}(o.a.Component),ts=Object(N.a)()(Object(k.c)((function(e){return{location:e.router.location,message:e.message,user:e.user}}),(function(e){return{onDeleteUser:function(t){e(Ae(t))},onHandleProfileFormSubmit:function(t){e(function(e){return function(t){return!e.password===e.password_conf?t(Se("Password and password confirmation don't match.")):(delete e.id,H.postData("auth/profile/edit",e).then((function(e){if("success"===e.status)return t(Ce()),Ws.push("/profile");t(Se(e.message))})).catch((function(e){throw e})))}}(t))}}}))(es)),as=a(480),ss=a(481),rs=a(482),ns=a(237),os=["week","month","year"],cs=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;Object(f.a)(this,a),r=t.call(this,e,s);var n=new Date;return r.state={displayedSports:e.sports.map((function(e){return e.id})),statsParams:{start:Object(gt.a)(Object(Ct.a)(n,11)),end:Object(vt.a)(n),duration:"month",type:"by_time"}},r}return Object(x.a)(a,[{key:"componentDidUpdate",value:function(e){this.props.sports!==e.sports&&this.updateDisplayedSports()}},{key:"updateDisplayedSports",value:function(){var e=this.props.sports;this.setState({displayedSports:e.map((function(e){return e.id}))})}},{key:"handleOnChangeDuration",value:function(e){var t=e.target.name,a=new Date,s="year"===t?Object(Ut.a)(Object(as.a)(a,9)):"week"===t?Object(gt.a)(Object(Ct.a)(a,2)):Object(gt.a)(Object(Ct.a)(a,11)),r="year"===t?Object(ss.a)(a):"week"===t?Object(wt.a)(a):Object(vt.a)(a);this.setState({statsParams:{duration:t,end:r,start:s,type:"by_time"}})}},{key:"handleOnChangeSports",value:function(e){var t=this.state.displayedSports;t.includes(e)?this.setState({displayedSports:t.filter((function(t){return t!==e}))}):this.setState({displayedSports:t.concat([e])})}},{key:"handleOnClickArrows",value:function(e){var t,a,s=this.state.statsParams,r=s.start,n=s.end,o=s.duration;e?(t="year"===o?Object(Ut.a)(Object(as.a)(r,1)):"week"===o?Object(kt.a)(Object(rs.a)(r,1)):Object(gt.a)(Object(Ct.a)(r,1)),a="year"===o?Object(ss.a)(Object(as.a)(n,1)):"week"===o?Object(wt.a)(Object(rs.a)(n,1)):Object(vt.a)(Object(Ct.a)(n,1))):(t="year"===o?Object(Ut.a)(Object(Lt.a)(r,1)):"week"===o?Object(kt.a)(Object(ns.a)(r,1)):Object(gt.a)(Object(Dt.a)(r,1)),a="year"===o?Object(ss.a)(Object(Lt.a)(n,1)):"week"===o?Object(wt.a)(Object(ns.a)(n,1)):Object(vt.a)(Object(Dt.a)(n,1))),this.setState({statsParams:{duration:o,end:a,start:t,type:"by_time"}})}},{key:"render",value:function(){var e=this,t=this.state,a=t.displayedSports,r=t.statsParams,n=this.props,o=n.sports,c=n.t,i=n.user,l=ye(o.filter((function(e){return i.sports_list.includes(e.id)})),c);return Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",c("statistics:Statistics")]})}),Object(s.jsxs)("div",{className:"container dashboard",children:[Object(s.jsxs)("div",{className:"card workout-card",children:[Object(s.jsx)("div",{className:"card-header",children:c("statistics:Statistics")}),Object(s.jsxs)("div",{className:"card-body".concat(0===i.nb_workouts?" stats-disabled":""),children:[Object(s.jsxs)("div",{className:"chart-filters row",children:[Object(s.jsx)("div",{className:"col chart-arrows",children:Object(s.jsx)("p",{className:"text-center",children:Object(s.jsx)("i",{className:"fa fa-chevron-left","aria-hidden":"true",onClick:function(){return e.handleOnClickArrows(!0)}})})}),Object(s.jsx)("div",{className:"col-md-3 time-frames justify-content-around",children:os.map((function(t){return Object(s.jsx)("div",{className:"time-frame",children:Object(s.jsxs)("label",{children:[Object(s.jsx)("input",{type:"radio",id:t,name:t,checked:t===r.duration,onChange:function(t){return e.handleOnChangeDuration(t)}}),Object(s.jsx)("span",{children:c("statistics:".concat(t))})]})},t)}))}),Object(s.jsx)("div",{className:"col chart-arrows",children:Object(s.jsx)("p",{className:"text-center",children:Object(s.jsx)("i",{className:"fa fa-chevron-right","aria-hidden":"true",onClick:function(){return e.handleOnClickArrows(!1)}})})})]}),Object(s.jsx)(Xt,{displayEmpty:!0,displayedSports:a,statsParams:r,t:c}),Object(s.jsx)("div",{className:"row chart-workouts",children:l.map((function(t){return Object(s.jsxs)("label",{className:"col workout-label",children:[Object(s.jsx)("input",{type:"checkbox",checked:a.includes(t.id),name:t.label,onChange:function(){return e.handleOnChangeSports(t.id)}}),Object(s.jsx)("span",{style:{color:fe[t.id-1]},children:" ".concat(t.label)})]},t.id)}))})]})]}),0===i.nb_workouts&&Object(s.jsx)(mt,{t:c})]})]})}}]),a}(o.a.Component),is=Object(N.a)()(Object(k.c)((function(e){return{sports:e.sports.data,user:e.user}}))(cs));function ls(e){var t=Object(de.a)().t,a="user:".concat(e.formType.charAt(0).toUpperCase()).concat(e.formType.slice(1));return Object(s.jsxs)("div",{children:[Object(s.jsx)(y.a,{children:Object(s.jsxs)("title",{children:["FitTrackee - ",t("user:".concat(e.formType))]})}),Object(s.jsx)("h1",{className:"page-title",children:t(a)}),Object(s.jsx)("div",{className:"container",children:Object(s.jsxs)("div",{className:"row",children:[Object(s.jsx)("div",{className:"col-md-3"}),Object(s.jsxs)("div",{className:"col-md-6",children:[Object(s.jsx)("br",{}),"register"!==e.formType||e.isRegistrationAllowed?Object(s.jsxs)(s.Fragment,{children:[Object(s.jsxs)("form",{onSubmit:function(t){return e.handleUserFormSubmit(t,e.formType)},children:["register"===e.formType&&Object(s.jsx)("div",{className:"form-group",children:Object(s.jsx)("input",{className:"form-control input-lg",name:"username",placeholder:t("user:Enter a username"),required:!0,type:"text",value:e.userForm.username,onChange:e.onHandleFormChange})}),"password reset"!==e.formType&&Object(s.jsx)("div",{className:"form-group",children:Object(s.jsx)("input",{className:"form-control input-lg",name:"email",placeholder:t("user:Enter an email address"),required:!0,type:"email",value:e.userForm.email,onChange:e.onHandleFormChange})}),"reset your password"!==e.formType&&Object(s.jsxs)(s.Fragment,{children:[Object(s.jsx)("div",{className:"form-group",children:Object(s.jsx)("input",{className:"form-control input-lg",name:"password",placeholder:t("user:Enter a password"),required:!0,type:"password",value:e.userForm.password,onChange:e.onHandleFormChange})}),"login"!==e.formType&&Object(s.jsx)("div",{className:"form-group",children:Object(s.jsx)("input",{className:"form-control input-lg",name:"password_conf",placeholder:t("user:Enter the password confirmation"),required:!0,type:"password",value:e.userForm.password_conf,onChange:e.onHandleFormChange})})]}),Object(s.jsx)("input",{type:"submit",className:"btn btn-primary btn-lg btn-block",value:t("Submit")})]}),Object(s.jsx)("p",{className:"password-forget",children:"login"===e.formType&&Object(s.jsx)(te.a,{to:{pathname:"/password-reset/request"},children:t("user:Forgot password?")})})]}):Object(s.jsxs)("div",{className:"card",children:[Object(s.jsx)("div",{className:"card-body",children:"Registration is disabled."}),Object(s.jsx)("div",{className:"card-body",children:Object(s.jsx)("button",{type:"submit",className:"btn btn-secondary btn-lg btn-block",onClick:function(){return Ws.go(-1)},children:"Back"})})]})]}),Object(s.jsx)("div",{className:"col-md-3"})]})})]})}var ds=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={formData:{username:"",email:"",password:"",password_conf:""}},r}return Object(x.a)(a,[{key:"componentDidUpdate",value:function(e){e.location.pathname!==this.props.location.pathname&&this.emptyForm()}},{key:"emptyForm",value:function(){var e=this.state.formData;Object.keys(e).map((function(t){return e[t]=""})),this.setState(e)}},{key:"onHandleFormChange",value:function(e){var t=this.state.formData;t[e.target.name]=e.target.value,this.setState(t)}},{key:"render",value:function(){var e=this,t=this.props,a=t.formType,r=t.isRegistrationAllowed,n=t.message,o=t.messages,c=t.onHandleUserFormSubmit,i=t.t,l=this.state.formData,d=this.props.location.query.token;return Object(s.jsx)("div",{children:z()||"password reset"===a&&!d?Object(s.jsx)(w.a,{to:"/"}):Object(s.jsxs)("div",{children:[Object(s.jsx)(_,{message:n,messages:o,t:i}),Object(s.jsx)(ls,{isRegistrationAllowed:r,formType:a,userForm:l,onHandleFormChange:function(t){return e.onHandleFormChange(t)},handleUserFormSubmit:function(e){e.preventDefault(),"password reset"===a&&(l.token=d),c(l,a)}})]})})}}]),a}(o.a.Component),us=Object(N.a)()(Object(k.c)((function(e){return{isRegistrationAllowed:e.application.config.is_registration_enabled,location:e.router.location,message:e.message,messages:e.messages}}),(function(e){return{onHandleUserFormSubmit:function(t,a){e(Ee(t,a="password reset"===a?"password/update":"reset your password"===a?"password/reset-request":a))}}}))(ds)),ms=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e,s){var r;return Object(f.a)(this,a),(r=t.call(this,e,s)).state={displayModal:!1},r}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadUser(this.props.match.params.userName)}},{key:"componentDidUpdate",value:function(e){e.match.params.userName!==this.props.match.params.userName&&this.props.loadUser(this.props.match.params.userName)}},{key:"displayModal",value:function(e){this.setState((function(t){return Object(S.a)(Object(S.a)({},t),{},{displayModal:e})}))}},{key:"render",value:function(){var e=this,t=this.props,a=t.t,r=t.currentUser,n=t.onDeleteUser,o=t.users,c=this.state.displayModal,i=Object(pe.a)(o,1)[0],l=!!i&&r.username===i.username;return Object(s.jsxs)("div",{children:[c&&Object(s.jsx)(We,{title:a("common:Confirmation"),text:a("user:Are you sure you want to delete this account? All data will be deleted, this cannot be undone."),confirm:function(){n(i.username),e.displayModal(!1)},close:function(){return e.displayModal(!1)}}),i&&Object(s.jsx)(ft,{editable:l,isDeletable:r.admin&&!l,onDeleteUser:n,displayModal:function(t){return e.displayModal(t)},t:a,user:i})]})}}]),a}(o.a.Component),js=Object(N.a)()(Object(k.c)((function(e){return{currentUser:e.user,users:e.users.data}}),(function(e){return{onDeleteUser:function(t){e(Ae(t,!0))},loadUser:function(t){e(Y("getData","users",{username:t}))}}}))(ms)),ps=function(e){Object(g.a)(a,e);var t=Object(v.a)(a);function a(e){var s;return Object(f.a)(this,a),(s=t.call(this,e)).props=e,s}return Object(x.a)(a,[{key:"componentDidMount",value:function(){this.props.loadAppConfig()}},{key:"render",value:function(){return Object(s.jsxs)("div",{className:"App",children:[Object(s.jsx)(Pa,{}),Object(s.jsxs)(w.d,{children:[Object(s.jsx)(w.b,{exact:!0,path:"/",component:ta}),Object(s.jsx)(w.b,{exact:!0,path:"/register",render:function(){return Object(s.jsx)(us,{formType:"register"})}}),Object(s.jsx)(w.b,{exact:!0,path:"/login",render:function(){return Object(s.jsx)(us,{formType:"login"})}}),Object(s.jsx)(w.b,{exact:!0,path:"/password-reset",render:function(){return Object(s.jsx)(us,{formType:"password reset"})}}),Object(s.jsx)(w.b,{exact:!0,path:"/password-reset/request",render:function(){return Object(s.jsx)(us,{formType:"reset your password"})}}),Object(s.jsx)(w.b,{exact:!0,path:"/password-reset/sent",render:function(){return Object(s.jsx)($a,{action:"sent"})}}),Object(s.jsx)(w.b,{exact:!0,path:"/updated-password",render:function(){return Object(s.jsx)($a,{action:"updated"})}}),Object(s.jsx)(w.b,{exact:!0,path:"/password-reset/sent",component:$a}),Object(s.jsx)(w.b,{exact:!0,path:"/logout",component:ra}),Object(s.jsx)(w.b,{exact:!0,path:"/profile/edit",component:ts}),Object(s.jsx)(w.b,{exact:!0,path:"/profile",component:xt}),Object(s.jsx)(w.b,{exact:!0,path:"/workouts/history",component:Ot}),Object(s.jsx)(w.b,{exact:!0,path:"/workouts/statistics",component:is}),Object(s.jsx)(w.b,{exact:!0,path:"/users/:userName",component:js}),Object(s.jsx)(w.b,{path:"/workouts",component:ut}),Object(s.jsx)(w.b,{path:"/admin",component:me}),Object(s.jsx)(w.b,{component:ue})]}),Object(s.jsx)(aa,{})]})}}]),a}(o.a.Component),hs=Object(k.c)((function(){return{}}),(function(e){return{loadAppConfig:function(){e(Z("config"))}}}))(ps),bs=a(78);function Os(e){var t=e.store,a=e.history,r=e.children;return Object(s.jsx)(k.a,{store:t,children:Object(s.jsx)(bs.a,{history:a,children:r})})}var fs=Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));function xs(e){navigator.serviceWorker.register(e).then((function(e){e.onupdatefound=function(){var t=e.installing;t.onstatechange=function(){"installed"===t.state&&(navigator.serviceWorker.controller?console.log("New content is available; please refresh."):console.log("Content is cached for offline use."))}}})).catch((function(e){console.error("Error during service worker registration:",e)}))}var gs,vs={data:[]},ks={language:"en",message:"",messages:[],user:{isAuthenticated:!1},workouts:Object(S.a)({},vs),application:{statistics:{},config:{gpx_limit_import:null,is_registration_enabled:null,max_single_file_size:null,max_users:null,max_zip_file_size:null,registration:null}},calendarWorkouts:Object(S.a)({},vs),chartData:[],gpx:null,loading:!1,records:Object(S.a)({},vs),sports:Object(S.a)({},vs),statistics:{data:{}},users:Object(S.a)({},vs)},ws=function(e,t,a){return a.target!==t?e:"SET_DATA"===a.type?Object(S.a)(Object(S.a)({},e),{},{data:a.data[a.target]}):"SET_PAGINATED_DATA"===a.type?Object(S.a)(Object(S.a)({},e),{},{data:a.data[a.target],pagination:a.pagination}):e},ys=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.workouts,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"LOGOUT":return ks.workouts;case"PUSH_WORKOUTS":return Object(S.a)(Object(S.a)({},e),{},{data:e.data.concat(t.workouts)});case"REMOVE_WORKOUT":return Object(S.a)(Object(S.a)({},e),{},{data:e.data.filter((function(e){return e.id!==t.workoutId}))});default:return ws(e,"workouts",t)}},Ns=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.application,t=arguments.length>1?arguments[1]:void 0;return"SET_APP_CONFIG"===t.type?Object(S.a)(Object(S.a)({},e),{},{config:t.data}):"SET_APP_STATS"===t.type?Object(S.a)(Object(S.a)({},e),{},{statistics:t.data}):e},_s=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.calendarWorkouts,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"LOGOUT":return ks.calendarWorkouts;case"UPDATE_CALENDAR":return Object(S.a)(Object(S.a)({},e),{},{data:t.workouts});default:return ws(e,"calendarWorkouts",t)}},Ss=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.chartData,t=arguments.length>1?arguments[1]:void 0;return"SET_CHART_DATA"===t.type?t.chartData:e},Ds=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.gpx,t=arguments.length>1?arguments[1]:void 0;return"SET_GPX"===t.type?t.gpxContent:e},Cs=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.language,t=arguments.length>1?arguments[1]:void 0;return"SET_LANGUAGE"===t.type?t.language:e},Es=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.loading,t=arguments.length>1?arguments[1]:void 0;return"SET_LOADING"===t.type?t.loading:e},As=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.message,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"AUTH_ERROR":case"PROFILE_ERROR":case"PROFILE_UPDATE_ERROR":case"PICTURE_ERROR":case"SET_ERROR":return t.message;case"LOGOUT":case"PROFILE_SUCCESS":case"SET_RESULTS":case"@@router/LOCATION_CHANGE":return"";default:return e}},Ms=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.messages,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"AUTH_ERRORS":return t.messages;case"LOGOUT":case"PROFILE_SUCCESS":case"@@router/LOCATION_CHANGE":return[];default:return e}},Ts=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.records,t=arguments.length>1?arguments[1]:void 0;return"LOGOUT"===t.type?ks.records:ws(e,"records",t)},Ps=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.sports,t=arguments.length>1?arguments[1]:void 0;return"UPDATE_SPORT_DATA"===t.type?Object(S.a)(Object(S.a)({},e),{},{data:e.data.map((function(e){return e.id===t.data.id&&(e.is_active=t.data.is_active),e}))}):ws(e,"sports",t)},Fs=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.users,t=arguments.length>1?arguments[1]:void 0;return"UPDATE_USER_DATA"===t.type?Object(S.a)(Object(S.a)({},e),{},{data:e.data.map((function(e){return e.username===t.data.username&&(e.admin=t.data.admin),e}))}):ws(e,"users",t)},zs=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.user,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"AUTH_ERROR":case"PROFILE_ERROR":case"LOGOUT":return window.localStorage.removeItem("authToken"),ks.user;case"PROFILE_SUCCESS":return t.profil;default:return e}},Rs=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:ks.statistics,t=arguments.length>1?arguments[1]:void 0;return"LOGOUT"===t.type?ks.statistics:ws(e,"statistics",t)},Ls=["/login","/register","/password-reset","/password-reset/request","/password-reset/sent","/updated-password"],Us=function(e,t){return"string"===typeof e||e instanceof String?e=t:e.pathname=t,e},Is=function(e){return window.localStorage.authToken||Ls.includes(e.pathname)||(e=Us(e,"/login")),window.localStorage.authToken&&Ls.includes(e.pathname)&&(e=Us(e,"/")),e},Ws=((gs=Object(r.a)()).location=Is(gs.location),Object(S.a)(Object(S.a)({},gs),{},{push:function(e){for(var t=arguments.length,a=new Array(t>1?t-1:0),s=1;s1?t-1:0),s=1;s 1\n ? `${t(`messages:${message.split('|')[0]}`)}: ${t(\n `messages:${message.split('|')[1]}`\n )}`\n : t(`messages:${message}`)\n return (\n
\n {singleMessage !== '' && {singleMessage}}\n {messages && messages.length > 0 && (\n \n
    \n {messages.map(msg => (\n
  • {t(`messages:${msg.value}`)}
  • \n ))}\n
\n
\n )}\n
\n )\n }\n}\n","import { format, parse } from 'date-fns'\nimport { DateTime } from 'luxon'\n\nconst suffixes = ['bytes', 'KB', 'MB', 'GB', 'TB']\nexport const getFileSize = (fileSize, asText = true) => {\n const i = Math.floor(Math.log(fileSize) / Math.log(1024))\n if (!fileSize) {\n return asText ? '0 bytes' : { size: 0, suffix: 'bytes' }\n }\n const size = (fileSize / Math.pow(1024, i)).toFixed(1)\n const suffix = suffixes[i]\n return asText ? `${size}${suffix}` : { size, suffix }\n}\n\nexport const getFileSizeInMB = fileSize => {\n const value = fileSize / 1048576\n return (!fileSize && 0) || +value.toFixed(2)\n}\n\nexport const version = '0.4.2' // version stored in 'utils' for now\nexport const apiUrl =\n process.env.NODE_ENV === 'production'\n ? '/api/'\n : `${process.env.REACT_APP_API_URL}/api/`\n\nexport const userFilters = [\n { key: 'workouts_count', label: 'workouts count' },\n { key: 'admin', label: 'admin rights' },\n { key: 'created_at', label: 'registration date' },\n { key: 'username', label: 'user name' },\n]\n\nexport const sortOrders = [\n { key: 'asc', label: 'ascending' },\n { key: 'desc', label: 'descending' },\n]\n\nexport const isLoggedIn = () => !!window.localStorage.authToken\n\nexport const generateIds = arr => {\n let i = 0\n return arr.map(val => {\n const obj = { id: i, value: val }\n i++\n return obj\n })\n}\n\nexport const createApiRequest = params => {\n const headers = {}\n if (!params.noAuthorization) {\n headers.Authorization = `Bearer ${window.localStorage.getItem('authToken')}`\n }\n if (params.type) {\n headers['Content-Type'] = params.type\n }\n const requestParams = {\n method: params.method,\n headers: headers,\n }\n if (params.type === 'application/json' && params.body) {\n requestParams.body = JSON.stringify(params.body)\n } else if (params.body) {\n requestParams.body = params.body\n }\n const request = new Request(`${apiUrl}${params.url}`, requestParams)\n return fetch(request)\n .then(response =>\n params.method === 'DELETE' || response.status === 413\n ? response\n : response.json()\n )\n .catch(error => {\n console.error(error)\n return new Error('An error occurred. Please contact the administrator.')\n })\n}\n\nexport const getDateWithTZ = (date, tz) => {\n if (!date) {\n return ''\n }\n const dt = DateTime.fromISO(\n format(new Date(date), \"yyyy-MM-dd'T'HH:mm:ss.SSSxxx\")\n ).setZone(tz)\n return parse(\n dt.toFormat('yyyy-MM-dd HH:mm:ss'),\n 'yyyy-MM-dd HH:mm:ss',\n new Date()\n )\n}\n\nexport const capitalize = target =>\n target.charAt(0).toUpperCase() + target.slice(1)\n\nexport const rangePagination = pages =>\n Array.from({ length: pages }, (_, i) => i + 1)\n\nconst sortValues = (a, b) => {\n const valueALabel = a.label.toLowerCase()\n const valueBLabel = b.label.toLowerCase()\n return valueALabel > valueBLabel ? 1 : valueALabel < valueBLabel ? -1 : 0\n}\n\nexport const translateValues = (t, values, key = 'common') =>\n values\n .map(value => ({\n ...value,\n label: t(`${key}:${value.label}`),\n }))\n .sort(sortValues)\n\nexport const formatUrl = (pathname, query) => {\n let url = pathname\n if (query.id || (pathname === 'users' && query.username)) {\n url = `${url}/${query.username ? query.username : query.id}`\n } else if (Object.keys(query).length > 0) {\n url += '?'\n Object.keys(query)\n .filter(key => query[key])\n .map(\n (key, index) => (url += `${index === 0 ? '' : '&'}${key}=${query[key]}`)\n )\n }\n return url\n}\n","import { createApiRequest, formatUrl } from '../utils'\n\nexport default class FitTrackeeApi {\n static getData(target, data = {}) {\n const url = formatUrl(target, data)\n const params = {\n url: url,\n method: 'GET',\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static addData(target, data) {\n const params = {\n url: target,\n method: 'POST',\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static addDataWithFile(target, data) {\n const params = {\n url: target,\n method: 'POST',\n body: data,\n }\n return createApiRequest(params)\n }\n\n static postData(target, data) {\n const params = {\n url: `${target}${data.id ? `/${data.id}` : ''}`,\n method: 'POST',\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static updateData(target, data) {\n const params = {\n url: `${target}${\n data.id ? `/${data.id}` : data.username ? `/${data.username}` : ''\n }`,\n method: 'PATCH',\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static deleteData(target, id) {\n const params = {\n url: `${target}/${id}`,\n method: 'DELETE',\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n}\n","import i18next from 'i18next'\n\nimport FitTrackeeApi from '../fitTrackeeApi/index'\nimport { history } from '../index'\n\nexport const setData = (target, data) => ({\n type: 'SET_DATA',\n data,\n target,\n})\nexport const setPaginatedData = (target, data, pagination) => ({\n type: 'SET_PAGINATED_DATA',\n data,\n pagination,\n target,\n})\n\nexport const setError = message => ({\n type: 'SET_ERROR',\n message,\n})\n\nexport const setLanguage = language => ({\n type: 'SET_LANGUAGE',\n language,\n})\n\nexport const setLoading = loading => ({\n type: 'SET_LOADING',\n loading,\n})\n\nexport const updateSportsData = data => ({\n type: 'UPDATE_SPORT_DATA',\n data,\n})\n\nexport const updateUsersData = data => ({\n type: 'UPDATE_USER_DATA',\n data,\n})\n\nexport const getOrUpdateData = (\n action,\n target,\n data,\n canDispatch = true\n) => dispatch => {\n dispatch(setLoading(true))\n if (data && data.id && target !== 'workouts' && isNaN(data.id)) {\n dispatch(setLoading(false))\n return dispatch(setError(`${target}|Incorrect id`))\n }\n dispatch(setError(''))\n return FitTrackeeApi[action](target, data)\n .then(ret => {\n if (ret.status === 'success') {\n if (canDispatch) {\n if (target === 'users' && action === 'getData') {\n return dispatch(setPaginatedData(target, ret.data, ret.pagination))\n }\n dispatch(setData(target, ret.data))\n } else if (action === 'updateData' && target === 'sports') {\n dispatch(updateSportsData(ret.data.sports[0]))\n } else if (action === 'updateData' && target === 'users') {\n dispatch(updateUsersData(ret.data.users[0]))\n }\n } else {\n dispatch(setError(`${target}|${ret.message || ret.status}`))\n }\n dispatch(setLoading(false))\n })\n .catch(error => {\n dispatch(setLoading(false))\n dispatch(setError(`${target}|${error}`))\n })\n}\n\nexport const addData = (target, data) => dispatch =>\n FitTrackeeApi.addData(target, data)\n .then(ret => {\n if (ret.status === 'created') {\n history.push(`/admin/${target}`)\n } else {\n dispatch(setError(`${target}|${ret.status}`))\n }\n })\n .catch(error => dispatch(setError(`${target}|${error}`)))\n\nexport const deleteData = (target, id) => dispatch => {\n if (isNaN(id)) {\n return dispatch(setError(target, `${target}|Incorrect id`))\n }\n return FitTrackeeApi.deleteData(target, id)\n .then(ret => {\n if (ret.status === 204) {\n history.push(`/admin/${target}`)\n } else {\n dispatch(setError(`${target}|${ret.message || ret.status}`))\n }\n })\n .catch(error => dispatch(setError(`${target}|${error}`)))\n}\n\nexport const updateLanguage = language => dispatch => {\n i18next.changeLanguage(language).then(dispatch(setLanguage(language)))\n}\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport { setError } from './index'\n\nexport const setAppConfig = data => ({\n type: 'SET_APP_CONFIG',\n data,\n})\n\nexport const setAppStats = data => ({\n type: 'SET_APP_STATS',\n data,\n})\n\nexport const getAppData = target => dispatch =>\n FitTrackeeGenericApi.getData(target)\n .then(ret => {\n if (ret.status === 'success') {\n if (target === 'config') {\n dispatch(setAppConfig(ret.data))\n } else if (target === 'stats/all') {\n dispatch(setAppStats(ret.data))\n }\n } else {\n dispatch(setError(`application|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`application|${error}`)))\n\nexport const updateAppConfig = formData => dispatch =>\n FitTrackeeGenericApi.updateData('config', formData)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setAppConfig(ret.data))\n } else {\n dispatch(setError(`application|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`application|${error}`)))\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport { updateAppConfig } from '../../actions/application'\nimport { history } from '../../index'\nimport { getFileSizeInMB } from '../../utils'\n\nclass AdminApplication extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n formData: {},\n isInEdition: false,\n }\n }\n\n componentDidMount() {\n this.initForm()\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.appConfig !== prevProps.appConfig) {\n this.initForm()\n }\n }\n\n initForm() {\n const { appConfig } = this.props\n const formData = {}\n Object.keys(appConfig).map(k =>\n appConfig[k] === null\n ? (formData[k] = '')\n : ['max_single_file_size', 'max_zip_file_size'].includes(k)\n ? (formData[k] = getFileSizeInMB(appConfig[k]))\n : (formData[k] = appConfig[k])\n )\n this.setState({ formData })\n }\n\n handleFormChange(e) {\n const { formData } = this.state\n formData[e.target.name] = +e.target.value\n this.setState(formData)\n }\n\n toggleInEdition(e) {\n e.preventDefault()\n const { isInEdition } = this.state\n this.setState({ isInEdition: !isInEdition })\n }\n\n render() {\n const { message, onHandleConfigFormSubmit, t } = this.props\n const { formData, isInEdition } = this.state\n return (\n
\n {message && }\n {Object.keys(formData).length > 0 && (\n
\n
\n
\n
\n \n {t('administration:Application configuration')}\n \n
\n
\n {\n this.toggleInEdition(e)\n onHandleConfigFormSubmit(formData)\n }}\n >\n
\n \n {t(\n // eslint-disable-next-line max-len\n 'administration:Max. number of active users'\n )}\n \n \n \n :\n \n this.handleFormChange(e)}\n />\n
\n
\n \n {t(\n 'administration:Max. size of uploaded files (in Mb)'\n )}\n :\n \n this.handleFormChange(e)}\n />\n
\n
\n \n {t('administration:Max. size of zip archive (in Mb)')}:\n \n this.handleFormChange(e)}\n />\n
\n
\n \n {t('administration:Max. files of zip archive')}\n \n this.handleFormChange(e)}\n />\n
\n {isInEdition ? (\n <>\n \n this.toggleInEdition(e)}\n value={t('common:Cancel')}\n />\n \n ) : (\n <>\n {\n this.toggleInEdition(e)\n }}\n value={t('common:Edit')}\n />\n history.push('/admin')}\n value={t('common:Back')}\n />\n \n )}\n \n
\n
\n
\n
\n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n message: state.message,\n }),\n dispatch => ({\n onHandleConfigFormSubmit: formData => {\n const data = Object.assign({}, formData)\n data.max_single_file_size *= 1048576\n data.max_zip_file_size *= 1048576\n dispatch(updateAppConfig(data))\n },\n })\n)(AdminApplication)\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport { getAppData } from '../../actions/application'\nimport { getFileSize } from '../../utils'\n\nclass AdminStats extends React.Component {\n componentDidMount() {\n this.props.loadAppStats()\n }\n\n render() {\n const { appStats, t } = this.props\n const uploadDirSize = getFileSize(appStats.uploads_dir_size, false)\n return (\n
\n
\n
\n
\n
\n \n
\n
\n
\n {appStats.users ? appStats.users : 0}\n
\n
{`${\n appStats.users === 1\n ? t('administration:user')\n : t('administration:users')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n {appStats.sports ? appStats.sports : 0}\n
\n
{`${\n appStats.sports === 1 ? t('common:sport') : t('common:sports')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n {appStats.workouts ? appStats.workouts : 0}\n
\n
{`${\n appStats.workouts === 1\n ? t('common:workout')\n : t('common:workouts')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
{uploadDirSize.size}
\n
\n {uploadDirSize.suffix} ({t('administration:uploads')})\n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n appStats: state.application.statistics,\n }),\n dispatch => ({\n loadAppStats: () => {\n dispatch(getAppData('stats/all'))\n },\n })\n )(AdminStats)\n)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport AdminStats from './AdminStats'\n\nexport default function AdminDashboard(props) {\n const { appConfig, t } = props\n return (\n
\n
\n {t('administration:Administration')}\n
\n
\n \n
\n
\n
\n \n {t('administration:Application')}\n \n
\n
\n {t(\n 'administration:Update application configuration ' +\n '(maximum number of registered users, maximum files size).'\n )}\n
\n \n {t(\n `administration:Registration is currently ${\n appConfig.is_registration_enabled ? 'enabled' : 'disabled'\n }.`\n )}\n \n
\n
\n
\n \n {t('administration:Sports')}\n \n
\n
{t('administration:Enable/disable sports.')}
\n
\n
\n \n {t('administration:Users')}\n \n
\n
\n {t(\n 'administration:Add/remove admin rights, ' +\n 'delete user account.'\n )}\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport { getOrUpdateData } from '../../actions'\nimport { history } from '../../index'\n\nclass AdminSports extends React.Component {\n componentDidMount() {\n this.props.loadSports()\n }\n\n render() {\n const { message, sports, t, updateSport } = this.props\n return (\n
\n {message && }\n
\n
\n
\n
\n {t('administration:Sports')}\n
\n
\n {sports.length > 0 && (\n \n \n \n \n \n \n \n \n \n \n \n {sports.map(sport => (\n \n \n \n \n \n \n \n ))}\n \n
{t('administration:id')}{t('administration:Image')}{t('administration:Label')}{t('administration:Active')}{t('administration:Actions')}
\n \n {t('administration:id')}\n \n {sport.id}\n \n \n {t('administration:Image')}\n \n \n \n \n {t('administration:Label')}\n \n {t(`sports:${sport.label}`)}\n \n \n {t('administration:Active')}\n \n {sport.is_active ? (\n \n ) : (\n \n )}\n \n \n {t('administration:Actions')}\n \n \n updateSport(sport.id, !sport.is_active)\n }\n />\n {sport.has_workouts && (\n \n \n {t('administration:workouts exist')}\n \n )}\n
\n )}\n history.push('/admin/')}\n value={t('common:Back')}\n />\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadSports: () => {\n dispatch(getOrUpdateData('getData', 'sports'))\n },\n updateSport: (sportId, isActive) => {\n const data = { id: sportId, is_active: isActive }\n dispatch(getOrUpdateData('updateData', 'sports', data, false))\n },\n })\n)(AdminSports)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { formatUrl, rangePagination } from '../../utils'\n\nexport default class Pagination extends React.PureComponent {\n getUrl(value) {\n const { query, pathname } = this.props\n const newQuery = Object.assign({}, query)\n let page = query.page ? +query.page : 1\n switch (value) {\n case 'prev':\n page -= 1\n break\n case 'next':\n page += 1\n break\n default:\n page = +value\n }\n newQuery.page = page\n return formatUrl(pathname, newQuery)\n }\n\n render() {\n const { pagination, t } = this.props\n return (\n <>\n {pagination && Object.keys(pagination).length > 0 && (\n \n )}\n \n )\n }\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { connect } from 'react-redux'\nimport { Link } from 'react-router-dom'\n\nimport Message from '../Common/Message'\nimport Pagination from '../Common/Pagination'\nimport { history } from '../../index'\nimport { getOrUpdateData } from '../../actions'\nimport {\n apiUrl,\n formatUrl,\n sortOrders,\n translateValues,\n userFilters,\n} from '../../utils'\n\nclass AdminUsers extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n page: null,\n per_page: null,\n order_by: 'created_at',\n order: 'asc',\n }\n }\n\n componentDidMount() {\n this.props.loadUsers(this.initState())\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.location.query !== this.props.location.query) {\n this.props.loadUsers(this.props.location.query)\n }\n }\n\n initState() {\n const { query } = this.props.location\n const newQuery = {\n page: query.page,\n per_page: query.per_page,\n order_by: query.order_by ? query.order_by : 'created_at',\n order: query.order ? query.order : 'asc',\n }\n this.setState(newQuery)\n return newQuery\n }\n\n updatePage(key, value) {\n const query = Object.assign({}, this.state)\n query[key] = value\n this.setState(query)\n const url = formatUrl(this.props.location.pathname, query)\n history.push(url)\n }\n\n render() {\n const {\n authUser,\n location,\n message,\n t,\n pagination,\n updateUser,\n users,\n } = this.props\n const translatedFilters = translateValues(t, userFilters)\n const translatedSortOrders = translateValues(t, sortOrders)\n return (\n
\n {message && }\n
\n
\n
\n
\n
\n {t('administration:Users')}\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n {users.map(user => (\n \n \n \n \n \n \n \n \n \n ))}\n \n
#{t('user:Username')}{t('user:Email')}{t('user:Registration Date')}{t('workouts:Workouts')}{t('user:Admin')}{t('administration:Actions')}
\n #\n {user.picture === true ? (\n \n ) : (\n \n )}\n \n \n {t('user:Username')}\n \n \n {user.username}\n \n \n \n {t('user:Email')}\n \n {user.email}\n \n \n {t('user:Registration Date')}\n \n {format(\n new Date(user.created_at),\n 'dd/MM/yyyy HH:mm'\n )}\n \n \n {t('workouts:Workouts')}\n \n {user.nb_workouts}\n \n \n {t('user:Admin')}\n \n {user.admin ? (\n \n ) : (\n \n )}\n \n \n {t('administration:Actions')}\n \n \n updateUser(user.username, !user.admin)\n }\n />\n
\n \n history.push('/admin/')}\n value={t('common:Back')}\n />\n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n authUser: state.user,\n location: state.router.location,\n message: state.message,\n pagination: state.users.pagination,\n users: state.users.data,\n }),\n dispatch => ({\n loadUsers: query => {\n dispatch(getOrUpdateData('getData', 'users', query))\n },\n updateUser: (userName, isAdmin) => {\n const data = { username: userName, admin: isAdmin }\n dispatch(getOrUpdateData('updateData', 'users', data, false))\n },\n })\n)(AdminUsers)\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { useTranslation } from 'react-i18next'\n\nexport default function NotFound() {\n const { t } = useTranslation()\n return (\n
\n \n fittrackee - 404\n \n

{t('Page not found')}

\n
\n )\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport { Route, Switch } from 'react-router-dom'\n\nimport AdminApplication from './AdminApplication'\nimport AdminDashboard from './AdminDashboard'\nimport AdminSports from './AdminSports'\nimport AdminUsers from './AdminUsers'\nimport NotFound from './../Others/NotFound'\n\nfunction Admin(props) {\n const { appConfig, t, user } = props\n return (\n <>\n \n FitTrackee - {t('administration:Administration')}\n \n
\n {user.admin ? (\n \n }\n />\n }\n />\n }\n />\n }\n />\n \n \n ) : (\n \n )}\n
\n \n )\n}\n\nexport default withTranslation()(\n connect(state => ({\n appConfig: state.application.config,\n user: state.user,\n }))(Admin)\n)\n","import { format, subHours } from 'date-fns'\nimport togeojson from '@mapbox/togeojson'\n\nimport { getDateWithTZ } from './index'\n\nexport const workoutColors = [\n '#55a8a3',\n '#98C3A9',\n '#D0838A',\n '#ECC77E',\n '#926692',\n '#929292',\n '#428bca',\n]\n\nexport const recordsLabels = [\n { record_type: 'AS', label: 'Ave. speed' },\n { record_type: 'FD', label: 'Farest distance' },\n { record_type: 'LD', label: 'Longest duration' },\n { record_type: 'MS', label: 'Max. speed' },\n]\n\nexport const getGeoJson = gpxContent => {\n let jsonData\n if (gpxContent) {\n const gpx = new DOMParser().parseFromString(gpxContent, 'text/xml')\n jsonData = togeojson.gpx(gpx)\n }\n return { jsonData }\n}\n\nexport const formatWorkoutDate = (\n dateTime,\n dateFormat = null,\n timeFormat = null\n) => {\n if (!dateFormat) {\n dateFormat = 'yyyy/MM/dd'\n }\n if (!timeFormat) {\n timeFormat = 'HH:mm'\n }\n return {\n workout_date: dateTime ? format(dateTime, dateFormat) : null,\n workout_time: dateTime ? format(dateTime, timeFormat) : null,\n }\n}\n\nexport const formatWorkoutDuration = seconds => {\n let newDate = new Date(0)\n newDate = subHours(newDate.setSeconds(seconds), 1)\n return newDate.getTime()\n}\n\nexport const formatChartData = chartData => {\n for (let i = 0; i < chartData.length; i++) {\n chartData[i].time = new Date(chartData[i].time).getTime()\n chartData[i].duration = formatWorkoutDuration(chartData[i].duration)\n }\n return chartData\n}\n\nexport const formatRecord = (record, tz) => {\n let value\n switch (record.record_type) {\n case 'AS':\n case 'MS':\n value = `${record.value} km/h`\n break\n case 'FD':\n value = `${record.value} km`\n break\n default:\n // 'LD'\n value = record.value // eslint-disable-line prefer-destructuring\n }\n const [recordType] = recordsLabels.filter(\n r => r.record_type === record.record_type\n )\n return {\n workout_date: formatWorkoutDate(getDateWithTZ(record.workout_date, tz))\n .workout_date,\n workout_id: record.workout_id,\n id: record.id,\n record_type: recordType.label,\n value: value,\n }\n}\n\nconst sortSports = (a, b) => {\n const sportALabel = a.label.toLowerCase()\n const sportBLabel = b.label.toLowerCase()\n return sportALabel > sportBLabel ? 1 : sportALabel < sportBLabel ? -1 : 0\n}\n\nexport const translateSports = (sports, t, onlyActive = false) =>\n sports\n .filter(sport => (onlyActive ? sport.is_active : true))\n .map(sport => ({\n ...sport,\n label: t(`sports:${sport.label}`),\n }))\n .sort(sortSports)\n","import { createApiRequest } from '../utils'\n\nexport default class FitTrackeeApi {\n static loginOrRegisterOrPasswordReset(target, data) {\n const params = {\n url: `auth/${target}`,\n method: 'POST',\n noAuthorization: true,\n body: data,\n type: 'application/json',\n }\n return createApiRequest(params)\n }\n\n static deletePicture() {\n const params = {\n url: 'auth/picture',\n method: 'DELETE',\n }\n return createApiRequest(params)\n }\n}\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport FitTrackeeApi from '../fitTrackeeApi/auth'\nimport { history } from '../index'\nimport { generateIds } from '../utils'\nimport { getOrUpdateData, setError, updateLanguage } from './index'\nimport { getAppData } from './application'\n\nconst AuthError = message => ({ type: 'AUTH_ERROR', message })\n\nconst AuthErrors = messages => ({ type: 'AUTH_ERRORS', messages })\n\nconst PictureError = message => ({ type: 'PICTURE_ERROR', message })\n\nconst ProfileSuccess = profil => ({ type: 'PROFILE_SUCCESS', profil })\n\nconst ProfileError = message => ({ type: 'PROFILE_ERROR', message })\n\nconst ProfileUpdateError = message => ({\n type: 'PROFILE_UPDATE_ERROR',\n message,\n})\n\nexport const logout = () => ({ type: 'LOGOUT' })\n\nexport const loadProfile = () => dispatch => {\n if (window.localStorage.getItem('authToken')) {\n return dispatch(getProfile())\n }\n return { type: 'LOGOUT' }\n}\n\nexport const getProfile = () => dispatch =>\n FitTrackeeGenericApi.getData('auth/profile')\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(getOrUpdateData('getData', 'sports'))\n ret.data.isAuthenticated = true\n if (ret.data.language) {\n dispatch(updateLanguage(ret.data.language))\n }\n return dispatch(ProfileSuccess(ret.data))\n }\n return dispatch(ProfileError(ret.message))\n })\n .catch(error => {\n throw error\n })\n\nexport const loginOrRegisterOrPasswordReset = (target, formData) => dispatch =>\n FitTrackeeApi.loginOrRegisterOrPasswordReset(target, formData)\n .then(ret => {\n if (ret.status === 'success') {\n if (target === 'password/reset-request') {\n return history.push({\n pathname: '/password-reset/sent',\n })\n }\n if (target === 'password/update') {\n return history.push({\n pathname: '/updated-password',\n })\n }\n if (target === 'login' || target === 'register') {\n window.localStorage.setItem('authToken', ret.auth_token)\n if (target === 'register') {\n dispatch(getAppData('config'))\n }\n return dispatch(getProfile())\n }\n }\n return dispatch(AuthError(ret.message))\n })\n .catch(error => {\n throw error\n })\n\nconst RegisterFormControl = (formData, onlyPasswords = false) => {\n const errMsg = []\n if (\n !onlyPasswords &&\n (formData.username.length < 3 || formData.username.length > 12)\n ) {\n errMsg.push('3 to 12 characters required for username.')\n }\n if (formData.password !== formData.password_conf) {\n errMsg.push(\"Password and password confirmation don't match.\")\n }\n if (formData.password.length < 8) {\n errMsg.push('8 characters required for password.')\n }\n return errMsg\n}\n\nexport const handleUserFormSubmit = (formData, formType) => dispatch => {\n if (formType === 'register' || formType === 'password/update') {\n const ret = RegisterFormControl(formData, formType === 'password/update')\n if (ret.length > 0) {\n return dispatch(AuthErrors(generateIds(ret)))\n }\n }\n return dispatch(loginOrRegisterOrPasswordReset(formType, formData))\n}\n\nexport const handleProfileFormSubmit = formData => dispatch => {\n if (!formData.password === formData.password_conf) {\n return dispatch(\n ProfileUpdateError(\"Password and password confirmation don't match.\")\n )\n }\n delete formData.id\n return FitTrackeeGenericApi.postData('auth/profile/edit', formData)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(getProfile())\n return history.push('/profile')\n }\n dispatch(ProfileUpdateError(ret.message))\n })\n .catch(error => {\n throw error\n })\n}\n\nexport const uploadPicture = event => dispatch => {\n event.preventDefault()\n const form = new FormData()\n form.append('file', event.target.picture.files[0])\n event.target.reset()\n return FitTrackeeGenericApi.addDataWithFile('auth/picture', form)\n .then(ret => {\n if (ret.status === 'success') {\n return dispatch(getProfile())\n }\n const msg = ret.message.match(/file size exceeds/g)\n ? 'Error during picture update, file size exceeds max size.'\n : ret.message\n return dispatch(PictureError(msg))\n })\n .catch(error => {\n throw error\n })\n}\n\nexport const deletePicture = () => dispatch =>\n FitTrackeeApi.deletePicture()\n .then(ret => {\n if (ret.status === 204) {\n return dispatch(getProfile())\n }\n return dispatch(PictureError(ret.message))\n })\n .catch(error => {\n throw error\n })\n\nexport const deleteUser = (username, isAdmin = false) => dispatch =>\n FitTrackeeGenericApi.deleteData('users', username)\n .then(ret => {\n if (ret.status === 204) {\n dispatch(getAppData('config'))\n if (isAdmin) {\n history.push('/admin/users')\n } else {\n dispatch(logout())\n history.push('/')\n }\n } else {\n ret.json().then(r => dispatch(setError(`${r.message}`)))\n }\n })\n .catch(error => dispatch(setError(`user|${error}`)))\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport { history } from '../index'\nimport { formatChartData } from '../utils/workouts'\nimport { setError, setLoading } from './index'\nimport { loadProfile } from './user'\n\nexport const pushWorkouts = workouts => ({\n type: 'PUSH_WORKOUTS',\n workouts,\n})\n\nexport const removeWorkout = workoutId => ({\n type: 'REMOVE_WORKOUT',\n workoutId,\n})\n\nexport const updateCalendar = workouts => ({\n type: 'UPDATE_CALENDAR',\n workouts,\n})\n\nexport const setGpx = gpxContent => ({\n type: 'SET_GPX',\n gpxContent,\n})\n\nexport const setChartData = chartData => ({\n type: 'SET_CHART_DATA',\n chartData,\n})\n\nexport const addWorkout = form => dispatch =>\n FitTrackeeGenericApi.addDataWithFile('workouts', form)\n .then(ret => {\n if (ret.status === 'created') {\n if (ret.data.workouts.length === 0) {\n dispatch(setError('workouts|no correct file.'))\n } else if (ret.data.workouts.length === 1) {\n dispatch(loadProfile())\n history.push(`/workouts/${ret.data.workouts[0].id}`)\n } else {\n // ret.data.workouts.length > 1\n dispatch(loadProfile())\n history.push('/')\n }\n } else if (ret.status === 413) {\n dispatch(\n setError('workouts|File size is greater than the allowed size')\n )\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n dispatch(setLoading(false))\n })\n .catch(error => {\n dispatch(setLoading(false))\n dispatch(setError(`workouts|${error}`))\n })\n\nexport const addWorkoutWithoutGpx = form => dispatch =>\n FitTrackeeGenericApi.addData('workouts/no_gpx', form)\n .then(ret => {\n if (ret.status === 'created') {\n dispatch(loadProfile())\n history.push(`/workouts/${ret.data.workouts[0].id}`)\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n\nexport const getWorkoutGpx = workoutId => dispatch => {\n if (workoutId) {\n return FitTrackeeGenericApi.getData(`workouts/${workoutId}/gpx`)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setGpx(ret.data.gpx))\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n }\n dispatch(setGpx(null))\n}\n\nexport const getSegmentGpx = (workoutId, segmentId) => dispatch => {\n if (workoutId) {\n return FitTrackeeGenericApi.getData(\n `workouts/${workoutId}/gpx/segment/${segmentId}`\n )\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setGpx(ret.data.gpx))\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n }\n dispatch(setGpx(null))\n}\n\nexport const getWorkoutChartData = workoutId => dispatch => {\n if (workoutId) {\n return FitTrackeeGenericApi.getData(`workouts/${workoutId}/chart_data`)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setChartData(formatChartData(ret.data.chart_data)))\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n }\n dispatch(setChartData(null))\n}\n\nexport const getSegmentChartData = (workoutId, segmentId) => dispatch => {\n if (workoutId) {\n return FitTrackeeGenericApi.getData(\n `workouts/${workoutId}/chart_data/segment/${segmentId}`\n )\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setChartData(formatChartData(ret.data.chart_data)))\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n }\n dispatch(setChartData(null))\n}\n\nexport const deleteWorkout = id => dispatch =>\n FitTrackeeGenericApi.deleteData('workouts', id)\n .then(ret => {\n if (ret.status === 204) {\n Promise.resolve(dispatch(removeWorkout(id)))\n .then(() => dispatch(loadProfile()))\n .then(() => history.push('/'))\n } else {\n dispatch(setError(`workouts|${ret.status}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n\nexport const editWorkout = form => dispatch =>\n FitTrackeeGenericApi.updateData('workouts', form)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(loadProfile())\n history.push(`/workouts/${ret.data.workouts[0].id}`)\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n dispatch(setLoading(false))\n })\n .catch(error => {\n dispatch(setLoading(false))\n dispatch(setError(`workouts|${error}`))\n })\n\nexport const getMoreWorkouts = params => dispatch =>\n FitTrackeeGenericApi.getData('workouts', params)\n .then(ret => {\n if (ret.status === 'success') {\n if (ret.data.workouts.length > 0) {\n dispatch(pushWorkouts(ret.data.workouts))\n }\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n\nexport const getMonthWorkouts = (from, to) => dispatch =>\n FitTrackeeGenericApi.getData('workouts', {\n from,\n to,\n order: 'asc',\n per_page: 100,\n })\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(updateCalendar(ret.data.workouts))\n } else {\n dispatch(setError(`workouts|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`workouts|${error}`)))\n","import React from 'react'\nimport { Trans } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport { setLoading } from '../../../actions/index'\nimport { addWorkout, editWorkout } from '../../../actions/workouts'\nimport { history } from '../../../index'\nimport { getFileSize } from '../../../utils'\nimport { translateSports } from '../../../utils/workouts'\n\nfunction FormWithGpx(props) {\n const {\n appConfig,\n loading,\n onAddWorkout,\n onEditWorkout,\n sports,\n t,\n workout,\n } = props\n const sportId = workout ? workout.sport_id : ''\n const translatedSports = translateSports(sports, t, true)\n const zipTooltip = `${t('workouts:no folder inside')}, ${\n appConfig.gpx_limit_import\n } ${t('workouts:files max')}, ${t('workouts:max size')}: ${getFileSize(\n appConfig.max_zip_file_size\n )}`\n const fileSizeLimit = getFileSize(appConfig.max_single_file_size)\n return (\n event.preventDefault()}\n >\n
\n \n
\n {workout ? (\n
\n \n
\n ) : (\n
\n \n
\n )}\n
\n \n
\n {loading ? (\n
\n ) : (\n
\n \n workout ? onEditWorkout(event, workout) : onAddWorkout(event)\n }\n value={t('common:Submit')}\n />\n history.push('/')}\n value={t('common:Cancel')}\n />\n
\n )}\n \n )\n}\n\nexport default connect(\n state => ({\n appConfig: state.application.config,\n loading: state.loading,\n }),\n dispatch => ({\n onAddWorkout: e => {\n dispatch(setLoading(true))\n const form = new FormData()\n form.append('file', e.target.form.gpxFile.files[0])\n /* prettier-ignore */\n form.append(\n 'data',\n `{\"sport_id\": ${e.target.form.sport.value\n }, \"notes\": \"${e.target.form.notes.value}\"}`\n )\n dispatch(addWorkout(form))\n },\n onEditWorkout: (e, workout) => {\n dispatch(\n editWorkout({\n id: workout.id,\n notes: e.target.form.notes.value,\n sport_id: +e.target.form.sport.value,\n title: e.target.form.title.value,\n })\n )\n },\n })\n)(FormWithGpx)\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport { addWorkoutWithoutGpx, editWorkout } from '../../../actions/workouts'\nimport { history } from '../../../index'\nimport { getDateWithTZ } from '../../../utils'\nimport { formatWorkoutDate, translateSports } from '../../../utils/workouts'\n\nfunction FormWithoutGpx(props) {\n const { onAddOrEdit, sports, t, user, workout } = props\n const translatedSports = translateSports(sports, t, true)\n let workoutDate,\n workoutTime,\n sportId = ''\n if (workout) {\n const workoutDateTime = formatWorkoutDate(\n getDateWithTZ(workout.workout_date, user.timezone),\n 'yyyy-MM-dd'\n )\n workoutDate = workoutDateTime.workout_date\n workoutTime = workoutDateTime.workout_time\n sportId = workout.sport_id\n }\n\n return (\n
event.preventDefault()}>\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n onAddOrEdit(event, workout)}\n value={t('common:Submit')}\n />\n history.push('/')}\n value={t('common:Cancel')}\n />\n \n )\n}\n\nexport default connect(\n state => ({\n user: state.user,\n }),\n dispatch => ({\n onAddOrEdit: (e, workout) => {\n const d = e.target.form.duration.value.split(':')\n const duration = +d[0] * 60 * 60 + +d[1] * 60 + +d[2]\n\n /* prettier-ignore */\n const workoutDate = `${e.target.form.workout_date.value\n } ${ e.target.form.workout_time.value}`\n\n const data = {\n workout_date: workoutDate,\n distance: +e.target.form.distance.value,\n duration,\n notes: e.target.form.notes.value,\n sport_id: +e.target.form.sport_id.value,\n title: e.target.form.title.value,\n }\n if (workout) {\n data.id = workout.id\n dispatch(editWorkout(data))\n } else {\n dispatch(addWorkoutWithoutGpx(data))\n }\n },\n })\n)(FormWithoutGpx)\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport FormWithGpx from './WorkoutForms/FormWithGpx'\nimport FormWithoutGpx from './WorkoutForms/FormWithoutGpx'\nimport Message from '../Common/Message'\n\nclass WorkoutAddEdit extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n withGpx: true,\n }\n }\n\n handleRadioChange(changeEvent) {\n this.setState({\n withGpx:\n changeEvent.target.name === 'withGpx'\n ? changeEvent.target.value\n : !changeEvent.target.value,\n })\n }\n\n render() {\n const { loading, message, sports, t, workout } = this.props\n const { withGpx } = this.state\n return (\n
\n \n \n FitTrackee -{' '}\n {workout\n ? t('workouts:Edit a workout')\n : t('workouts:Add a workout')}\n \n \n
\n
\n \n
\n
\n
\n
\n
\n

\n {workout\n ? t('workouts:Edit a workout')\n : t('workouts:Add a workout')}\n

\n
\n {workout ? (\n workout.with_gpx ? (\n \n ) : (\n \n )\n ) : (\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n {withGpx ? (\n \n ) : (\n \n )}\n
\n )}\n
\n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(state => ({\n loading: state.loading,\n }))(WorkoutAddEdit)\n)\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport WorkoutAddOrEdit from './WorkoutAddOrEdit'\n\nfunction WorkoutAdd(props) {\n const { message, sports } = props\n return (\n
\n \n
\n )\n}\n\nexport default connect(state => ({\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n}))(WorkoutAdd)\n","import React from 'react'\nimport { useTranslation } from 'react-i18next'\n\nexport default function CustomModal(props) {\n const { t } = useTranslation()\n return (\n
\n
\n
\n
\n
{props.title}
\n props.close()}\n >\n ×\n \n
\n
\n

{props.text}

\n
\n
\n props.confirm()}\n >\n {t('common:Yes')}\n \n props.close()}\n >\n {t('common:No')}\n \n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { getDateWithTZ } from '../../../utils'\nimport { formatWorkoutDate } from '../../../utils/workouts'\n\nexport default function WorkoutCardHeader(props) {\n const {\n dataType,\n displayModal,\n segmentId,\n sport,\n t,\n title,\n user,\n workout,\n } = props\n const workoutDate = workout\n ? formatWorkoutDate(getDateWithTZ(workout.workout_date, user.timezone))\n : null\n\n const previousUrl =\n dataType === 'segment' && segmentId !== 1\n ? `/workouts/${workout.id}/segment/${segmentId - 1}`\n : dataType === 'workout' && workout.previous_workout\n ? `/workouts/${workout.previous_workout}`\n : null\n const nextUrl =\n dataType === 'segment' && segmentId < workout.segments.length\n ? `/workouts/${workout.id}/segment/${segmentId + 1}`\n : dataType === 'workout' && workout.next_workout\n ? `/workouts/${workout.next_workout}`\n : null\n\n return (\n
\n
\n
\n {previousUrl ? (\n \n \n \n ) : (\n \n )}\n
\n
\n \"sport\n
\n
\n {dataType === 'workout' ? (\n <>\n {title}{' '}\n \n \n \n displayModal(true)}\n title={t('workouts:Delete workout')}\n />\n \n ) : (\n <>\n {/* prettier-ignore */}\n \n {title}\n {' '}\n - {t('workouts:segment')} {segmentId}\n \n )}\n
\n {workoutDate && (\n \n {`${workoutDate.workout_date} - ${workoutDate.workout_time}`}\n \n )}\n
\n
\n {nextUrl ? (\n \n \n \n ) : (\n \n )}\n
\n
\n
\n )\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { connect } from 'react-redux'\nimport {\n Area,\n ComposedChart,\n Line,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts'\n\nimport {\n getSegmentChartData,\n getWorkoutChartData,\n} from '../../../actions/workouts'\n\nclass WorkoutCharts extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayDistance: true,\n dataToHide: [],\n }\n }\n\n componentDidMount() {\n if (this.props.dataType === 'workout') {\n this.props.loadWorkoutData(this.props.workout.id)\n } else {\n this.props.loadSegmentData(this.props.workout.id, this.props.segmentId)\n }\n }\n\n componentDidUpdate(prevProps) {\n if (\n (this.props.dataType === 'workout' &&\n prevProps.workout.id !== this.props.workout.id) ||\n (this.props.dataType === 'workout' && prevProps.dataType === 'segment')\n ) {\n this.props.loadWorkoutData(this.props.workout.id)\n }\n if (\n this.props.dataType === 'segment' &&\n prevProps.segmentId !== this.props.segmentId\n ) {\n this.props.loadSegmentData(this.props.workout.id, this.props.segmentId)\n }\n }\n\n componentWillUnmount() {\n this.props.loadWorkoutData(null)\n }\n\n handleRadioChange(changeEvent) {\n this.setState({\n displayDistance:\n changeEvent.target.name === 'distance'\n ? changeEvent.target.value\n : !changeEvent.target.value,\n })\n }\n\n handleLegendChange(e) {\n const { dataToHide } = this.state\n const name = e.target.name // eslint-disable-line prefer-destructuring\n if (dataToHide.find(d => d === name)) {\n dataToHide.splice(dataToHide.indexOf(name), 1)\n } else {\n dataToHide.push(name)\n }\n this.setState({ dataToHide })\n }\n\n displayData(name) {\n const { dataToHide } = this.state\n return !dataToHide.find(d => d === name)\n }\n\n render() {\n const { chartData, t, updateCoordinates } = this.props\n const { displayDistance } = this.state\n const xInterval = chartData ? parseInt(chartData.length / 10, 10) : 0\n let xDataKey, xScale\n if (displayDistance) {\n xDataKey = 'distance'\n xScale = 'linear'\n } else {\n xDataKey = 'duration'\n xScale = 'time'\n }\n return (\n
\n {chartData && chartData.length > 0 ? (\n
\n
\n \n \n
\n
\n
\n \n \n
\n
\n
\n \n updateCoordinates(e.activePayload)}\n onMouseLeave={() => updateCoordinates(null)}\n >\n \n displayDistance ? value : format(value, 'HH:mm:ss')\n }\n type=\"number\"\n />\n \n \n {this.displayData('elevation') && (\n \n )}\n {this.displayData('speed') && (\n \n )}\n \n displayDistance\n ? `${t('workouts:distance')}: ${value} km`\n : `${t('workouts:duration')}: ${format(\n value,\n 'HH:mm:ss'\n )}`\n }\n />\n \n \n
\n
\n {t('workouts:data from gpx, without any cleaning')}\n
\n
\n ) : (\n t('workouts:No data to display')\n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n chartData: state.chartData,\n }),\n dispatch => ({\n loadWorkoutData: workoutId => {\n dispatch(getWorkoutChartData(workoutId))\n },\n loadSegmentData: (workoutId, segmentId) => {\n dispatch(getSegmentChartData(workoutId, segmentId))\n },\n })\n)(WorkoutCharts)\n","import React from 'react'\n\nexport default function WorkoutWeather(props) {\n const { t, workout } = props\n return (\n
\n {workout.weather_start && workout.weather_end && (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {t('workouts:Start')}\n
\n \n
\n {t('workouts:End')}\n
\n \n
\n \n {Number(workout.weather_start.temperature).toFixed(1)}°C{Number(workout.weather_end.temperature).toFixed(1)}°C
\n \n \n {Number(workout.weather_start.humidity * 100).toFixed(1)}%\n {Number(workout.weather_end.humidity * 100).toFixed(1)}%
\n \n {Number(workout.weather_start.wind).toFixed(1)}m/s{Number(workout.weather_end.wind).toFixed(1)}m/s
\n )}\n
\n )\n}\n","import React from 'react'\n\nimport WorkoutWeather from './WorkoutWeather'\n\nexport default function WorkoutDetails(props) {\n const { t, workout } = props\n const withPauses = workout.pauses !== '0:00:00' && workout.pauses !== null\n return (\n
\n

\n \n {t('workouts:Duration')}: {workout.moving}\n {workout.records &&\n workout.records.find(record => record.record_type === 'LD') && (\n \n \n \n )}\n {withPauses && (\n \n
({t('workouts:pauses')}: {workout.pauses},{' '}\n {t('workouts:total duration')}: {workout.duration})\n
\n )}\n

\n

\n \n {t('workouts:Distance')}: {workout.distance} km\n {workout.records &&\n workout.records.find(record => record.record_type === 'FD') && (\n \n \n \n )}\n

\n

\n \n {t('workouts:Average speed')}: {workout.ave_speed} km/h\n {workout.records &&\n workout.records.find(record => record.record_type === 'AS') && (\n \n \n \n )}\n
\n {t('workouts:Max. speed')}: {workout.max_speed} km/h\n {workout.records &&\n workout.records.find(record => record.record_type === 'MS') && (\n \n \n \n )}\n

\n {workout.min_alt && workout.max_alt && (\n

\n \n {t('workouts:Min. altitude')}: {workout.min_alt}m\n
\n {t('workouts:Max. altitude')}: {workout.max_alt}m\n

\n )}\n {workout.ascent && workout.descent && (\n

\n \n {t('workouts:Ascent')}: {workout.ascent}m\n
\n {t('workouts:Descent')}: {workout.descent}m\n

\n )}\n \n
\n )\n}\n","import React from 'react'\nimport { GeoJSON, Marker, TileLayer, useMap } from 'react-leaflet'\nimport hash from 'object-hash'\n\nimport { apiUrl } from '../../../utils'\n\nexport default function Map({ bounds, coordinates, jsonData, mapAttribution }) {\n const map = useMap()\n map.fitBounds(bounds)\n return (\n <>\n \n \n {coordinates.latitude && (\n \n )}\n \n )\n}\n","import React from 'react'\nimport { MapContainer } from 'react-leaflet'\nimport { connect } from 'react-redux'\n\nimport Map from './Map'\nimport { getSegmentGpx, getWorkoutGpx } from '../../../actions/workouts'\nimport { getGeoJson } from '../../../utils/workouts'\n\nclass WorkoutMap extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n zoom: 13,\n }\n }\n\n componentDidMount() {\n if (this.props.dataType === 'workout') {\n this.props.loadWorkoutGpx(this.props.workout.id)\n } else {\n this.props.loadSegmentGpx(this.props.workout.id, this.props.segmentId)\n }\n }\n\n componentDidUpdate(prevProps) {\n if (\n (this.props.dataType === 'workout' &&\n prevProps.workout.id !== this.props.workout.id) ||\n (this.props.dataType === 'workout' && prevProps.dataType === 'segment')\n ) {\n this.props.loadWorkoutGpx(this.props.workout.id)\n }\n if (\n this.props.dataType === 'segment' &&\n prevProps.segmentId !== this.props.segmentId\n ) {\n this.props.loadSegmentGpx(this.props.workout.id, this.props.segmentId)\n }\n }\n\n componentWillUnmount() {\n this.props.loadWorkoutGpx(null)\n }\n\n render() {\n const { coordinates, gpxContent, mapAttribution, workout } = this.props\n const { jsonData } = getGeoJson(gpxContent)\n const bounds = [\n [workout.bounds[0], workout.bounds[1]],\n [workout.bounds[2], workout.bounds[3]],\n ]\n\n return (\n
\n {jsonData && (\n \n \n \n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n gpxContent: state.gpx,\n mapAttribution: state.application.config.map_attribution,\n }),\n dispatch => ({\n loadWorkoutGpx: workoutId => {\n dispatch(getWorkoutGpx(workoutId))\n },\n loadSegmentGpx: (workoutId, segmentId) => {\n dispatch(getSegmentGpx(workoutId, segmentId))\n },\n })\n)(WorkoutMap)\n","import React from 'react'\n\nexport default function WorkoutNoMap(props) {\n const { t } = props\n return (\n
{t('workouts:No Map')}
\n )\n}\n","import React from 'react'\n\nexport default function WorkoutNotes(props) {\n const { notes, t } = props\n return (\n
\n
\n
\n
\n Notes\n
\n {notes ? notes : t('workouts:No notes')}\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nexport default function WorkoutSegments(props) {\n const { segments, t } = props\n return (\n
\n
\n
\n
\n {t('workouts:Segments')}\n
\n
    \n {segments.map((segment, index) => (\n \n \n {t('workouts:segment')} {index + 1}\n {' '}\n ({t('workouts:distance')}: {segment.distance} km,{' '}\n {t('workouts:duration')}: {segment.duration})\n \n ))}\n
\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport CustomModal from '../../Common/CustomModal'\nimport Message from '../../Common/Message'\nimport WorkoutCardHeader from './WorkoutCardHeader'\nimport WorkoutCharts from './WorkoutCharts'\nimport WorkoutDetails from './WorkoutDetails'\nimport WorkoutMap from './WorkoutMap'\nimport WorkoutNoMap from './WorkoutNoMap'\nimport WorkoutNotes from './WorkoutNotes'\nimport WorkoutSegments from './WorkoutSegments'\nimport { getOrUpdateData } from '../../../actions'\nimport { deleteWorkout } from '../../../actions/workouts'\n\nclass WorkoutDisplay extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayModal: false,\n coordinates: {\n latitude: null,\n longitude: null,\n },\n }\n }\n\n componentDidMount() {\n this.props.loadWorkout(this.props.match.params.workoutId)\n }\n\n componentDidUpdate(prevProps) {\n if (\n prevProps.match.params.workoutId !== this.props.match.params.workoutId\n ) {\n this.props.loadWorkout(this.props.match.params.workoutId)\n }\n }\n\n displayModal(value) {\n this.setState(prevState => ({\n ...prevState,\n displayModal: value,\n }))\n }\n\n updateCoordinates(activePayload) {\n const coordinates =\n activePayload && activePayload.length > 0\n ? {\n latitude: activePayload[0].payload.latitude,\n longitude: activePayload[0].payload.longitude,\n }\n : {\n latitude: null,\n longitude: null,\n }\n this.setState(prevState => ({\n ...prevState,\n coordinates,\n }))\n }\n\n render() {\n const { message, onDeleteWorkout, sports, t, user, workouts } = this.props\n const { coordinates, displayModal } = this.state\n const [workout] = workouts\n const title = workout ? workout.title : t('workouts:Workout')\n const [sport] = workout ? sports.filter(s => s.id === workout.sport_id) : []\n const segmentId = parseInt(this.props.match.params.segmentId)\n const dataType = segmentId >= 0 ? 'segment' : 'workout'\n return (\n
\n \n FitTrackee - {title}\n \n {message ? (\n \n ) : (\n
\n {displayModal && (\n {\n onDeleteWorkout(workout.id)\n this.displayModal(false)\n }}\n close={() => this.displayModal(false)}\n />\n )}\n {workout && sport && workouts.length === 1 && (\n
\n
\n
\n
\n
\n this.displayModal(true)}\n />\n
\n
\n
\n
\n {workout.with_gpx ? (\n \n ) : (\n \n )}\n
\n
\n \n
\n
\n
\n
\n
\n
\n {workout.with_gpx && (\n
\n
\n
\n
\n
\n
\n
\n {t('workouts:Chart')}\n
\n \n this.updateCoordinates(e)\n }\n />\n
\n
\n
\n
\n
\n
\n )}\n {dataType === 'workout' && (\n <>\n \n {workout.segments.length > 1 && (\n \n )}\n \n )}\n
\n )}\n
\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n workouts: state.workouts.data,\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadWorkout: workoutId => {\n dispatch(getOrUpdateData('getData', 'workouts', { id: workoutId }))\n },\n onDeleteWorkout: workoutId => {\n dispatch(deleteWorkout(workoutId))\n },\n })\n )(WorkoutDisplay)\n)\n","import React from 'react'\nimport { connect } from 'react-redux'\n\nimport WorkoutAddOrEdit from './WorkoutAddOrEdit'\nimport { getOrUpdateData } from '../../actions'\n\nclass WorkoutEdit extends React.Component {\n componentDidMount() {\n this.props.loadWorkout(this.props.match.params.workoutId)\n }\n\n render() {\n const { message, sports, workouts } = this.props\n const [workout] = workouts\n return (\n
\n {sports.length > 0 && (\n \n )}\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n workouts: state.workouts.data,\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadWorkout: workoutId => {\n dispatch(getOrUpdateData('getData', 'workouts', { id: workoutId }))\n },\n })\n)(WorkoutEdit)\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { Redirect, Route, Switch } from 'react-router-dom'\n\nimport NotFound from './../Others/NotFound'\nimport WorkoutAdd from './WorkoutAdd'\nimport WorkoutDisplay from './WorkoutDisplay'\nimport WorkoutEdit from './WorkoutEdit'\nimport { isLoggedIn } from '../../utils'\n\nfunction Workout() {\n return (\n
\n {isLoggedIn() ? (\n \n \n \n \n \n \n \n ) : (\n \n )}\n
\n )\n}\n\nexport default connect(state => ({\n user: state.user,\n}))(Workout)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nexport default class NoWorkouts extends React.PureComponent {\n render() {\n const { t } = this.props\n return (\n
\n
\n {t('common:No workouts.')}{' '}\n \n {t('dashboard:Upload one !')}\n \n
\n
\n )\n }\n}\n","import React from 'react'\n\nimport { translateSports } from '../../utils/workouts'\n\nexport default class WorkoutsFilter extends React.PureComponent {\n render() {\n const { loadWorkouts, sports, t, updateParams } = this.props\n const translatedSports = translateSports(sports, t)\n return (\n
\n
\n
event.preventDefault()}>\n
\n \n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n loadWorkouts()}\n type=\"submit\"\n value={t('workouts:Filter')}\n />\n \n
\n
\n )\n }\n}\n","import React from 'react'\n\nimport { apiUrl } from '../../utils'\n\nexport default class StaticMap extends React.PureComponent {\n render() {\n const { display, workout } = this.props\n\n return (\n
\n \n
\n ©\n \n OpenStreetMap\n \n
\n
\n )\n }\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport StaticMap from '../Common/StaticMap'\nimport { getDateWithTZ } from '../../utils'\n\nexport default class WorkoutsList extends React.PureComponent {\n render() {\n const { loading, sports, t, user, workouts } = this.props\n return (\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n {!loading &&\n sports &&\n workouts.map((workout, idx) => (\n // eslint-disable-next-line react/no-array-index-key\n \n \n \n \n \n \n \n \n \n ))}\n \n
\n {t('common:Workout')}{t('workouts:Date')}{t('workouts:Distance')}{t('workouts:Duration')}{t('workouts:Ave. speed')}{t('workouts:Max. speed')}
\n \n {t('common:Sport')}\n \n s.id === workout.sport_id)\n .map(s => s.img)}\n alt=\"workout sport logo\"\n />\n \n \n {t('common:Workout')}\n \n \n {workout.title}\n \n {workout.map && (\n \n )}\n \n \n {t('workouts:Date')}\n \n {format(\n getDateWithTZ(workout.workout_date, user.timezone),\n 'dd/MM/yyyy HH:mm'\n )}\n \n \n {t('workouts:Distance')}\n \n {Number(workout.distance).toFixed(2)} km\n \n \n {t('workouts:Duration')}\n \n {workout.moving}\n \n \n {t('workouts:Ave. speed')}\n \n {workout.ave_speed} km/h\n \n \n {t('workouts:Max. speed')}\n \n {workout.max_speed} km/h\n
\n {loading &&
}\n
\n
\n )\n }\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport NoWorkouts from '../Common/NoWorkouts'\nimport WorkoutsFilter from './WorkoutsFilter'\nimport WorkoutsList from './WorkoutsList'\nimport { getOrUpdateData } from '../../actions'\nimport { getMoreWorkouts } from '../../actions/workouts'\n\nclass Workouts extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n params: {\n page: 1,\n per_page: 10,\n },\n }\n }\n\n componentDidMount() {\n this.props.loadWorkouts(this.state.params)\n }\n\n setParams(e) {\n const { params } = this.state\n if (e.target.value === '') {\n delete params[e.target.name]\n } else {\n params[e.target.name] = e.target.value\n }\n params.page = 1\n this.setState(params)\n }\n render() {\n const {\n loading,\n loadWorkouts,\n loadMoreWorkouts,\n message,\n sports,\n t,\n user,\n workouts,\n } = this.props\n const { params } = this.state\n const paginationEnd =\n workouts.length > 0\n ? workouts[workouts.length - 1].previous_workout === null\n : true\n return (\n
\n \n FitTrackee - {t('common:Workouts')}\n \n {message ? (\n \n ) : (\n
\n
\n
\n loadWorkouts(params)}\n t={t}\n updateParams={e => this.setParams(e)}\n />\n
\n
\n \n {!paginationEnd && (\n {\n params.page += 1\n loadMoreWorkouts(params)\n this.setState(params)\n }}\n />\n )}\n {workouts.length === 0 && }\n
\n
\n
\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n workouts: state.workouts.data,\n loading: state.loading,\n message: state.message,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadWorkouts: params => {\n dispatch(getOrUpdateData('getData', 'workouts', params))\n },\n loadMoreWorkouts: params => {\n dispatch(getMoreWorkouts(params))\n },\n })\n )(Workouts)\n)\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport Message from '../Common/Message'\nimport { deletePicture, uploadPicture } from '../../actions/user'\nimport { apiUrl, getFileSize } from '../../utils'\nimport { history } from '../../index'\n\nfunction ProfileDetail({\n appConfig,\n displayModal,\n editable,\n isDeletable,\n message,\n onDeletePicture,\n onUploadPicture,\n pathname,\n t,\n user,\n}) {\n const createdAt = user.created_at\n ? format(new Date(user.created_at), 'dd/MM/yyyy HH:mm')\n : ''\n const birthDate = user.birth_date\n ? format(new Date(user.birth_date), 'dd/MM/yyyy')\n : ''\n const fileSizeLimit = getFileSize(appConfig.max_single_file_size)\n return (\n
\n \n FitTrackee - {t('user:Profile')}\n \n \n
\n

{t('user:Profile')}

\n
\n
\n
\n
\n {user.username}\n
\n
\n
\n
\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Email')}\n : {user.email}\n

\n

\n \n {t('user:Registration Date')}\n \n : {createdAt}\n

\n

\n {t('user:First Name')}\n : {user.first_name}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Last Name')}\n : {user.last_name}\n

\n

\n {t('user:Birth Date')}\n : {birthDate}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Location')}\n : {user.location}\n

\n

\n {t('user:Bio')}:{' '}\n {user.bio}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Language')}\n : {user.language}\n

\n

\n {/* eslint-disable-next-line max-len */}\n \n {t('user:Timezone')}\n : {user.timezone}\n

\n

\n \n {t('user:First day of week')}\n \n : {user.weekm ? t('user:Monday') : t('user:Sunday')}\n

\n
\n
\n {user.picture === true && (\n
\n \n {editable && (\n <>\n
\n onDeletePicture()}\n >\n {t('user:Delete picture')}\n \n
\n
\n \n )}\n
\n )}\n {editable && (\n onUploadPicture(event)}\n >\n \n
\n \n {` (max. size: ${fileSizeLimit})`}\n \n )}{' '}\n
\n
\n {editable && (\n history.push('/profile/edit')}\n >\n {t('common:Edit')}\n \n )}\n {isDeletable && (\n displayModal(true)}\n >\n {t('user:Delete user account')}\n \n )}\n \n pathname === '/profile' ? history.push('/') : history.go(-1)\n }\n >\n {t(\n pathname === '/profile'\n ? 'common:Back to home'\n : 'common:Back'\n )}\n \n
\n
\n
\n
\n
\n
\n )\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n appConfig: state.application.config,\n pathname: state.router.location.pathname,\n message: state.message,\n }),\n dispatch => ({\n onDeletePicture: () => {\n dispatch(deletePicture())\n },\n onUploadPicture: event => {\n dispatch(uploadPicture(event))\n },\n })\n )(ProfileDetail)\n)\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport ProfileDetail from './ProfileDetail'\n\nfunction CurrentUserProfile({ t, user }) {\n return (\n
\n \n
\n )\n}\n\nexport default withTranslation()(\n connect(state => ({\n user: state.user,\n }))(CurrentUserProfile)\n)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { recordsLabels } from '../../utils/workouts'\n\nexport default function CalendarWorkout(props) {\n const { isDisabled, isMore, sportImg, workout } = props\n return (\n \n <>\n \n {workout.records.length > 0 && (\n \n \n ` ${\n recordsLabels.filter(\n r => r.record_type === rec.record_type\n )[0].label\n }`\n )}\n />\n \n )}\n \n \n )\n}\n","import React from 'react'\n\nimport CalendarWorkout from './CalendarWorkout'\n\nexport default class CalendarWorkouts extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n isHidden: true,\n }\n }\n\n handleDisplayMore() {\n this.setState({\n isHidden: !this.state.isHidden,\n })\n }\n\n render() {\n const { dayWorkouts, isDisabled, sports } = this.props\n const { isHidden } = this.state\n return (\n
\n {dayWorkouts.map(act => (\n s.id === act.sport_id).map(s => s.img)}\n />\n ))}\n {dayWorkouts.length > 2 && (\n this.handleDisplayMore()}\n title=\"show more workouts\"\n />\n )}\n {!isHidden && (\n
\n {dayWorkouts.map(act => (\n s.id === act.sport_id)\n .map(s => s.img)}\n />\n ))}\n
\n )}\n
\n )\n }\n}\n","// eslint-disable-next-line max-len\n// source: https://blog.flowandform.agency/create-a-custom-calendar-in-react-3df1bfd0b728\nimport {\n addDays,\n addMonths,\n endOfMonth,\n endOfWeek,\n format,\n isSameDay,\n isSameMonth,\n isToday,\n startOfMonth,\n startOfWeek,\n subMonths,\n} from 'date-fns'\nimport { enGB, fr } from 'date-fns/locale'\nimport React from 'react'\nimport { connect } from 'react-redux'\n\nimport CalendarWorkouts from './CalendarWorkouts'\nimport { getMonthWorkouts } from '../../actions/workouts'\nimport { getDateWithTZ } from '../../utils'\n\nconst getStartAndEndMonth = (date, weekStartOnMonday) => {\n const monthStart = startOfMonth(date)\n const monthEnd = endOfMonth(date)\n const weekStartsOn = weekStartOnMonday ? 1 : 0\n return {\n start: startOfWeek(monthStart, { weekStartsOn }),\n end: endOfWeek(monthEnd),\n }\n}\n\nclass Calendar extends React.Component {\n constructor(props, context) {\n super(props, context)\n const calendarDate = new Date()\n this.state = {\n currentMonth: calendarDate,\n startDate: getStartAndEndMonth(calendarDate, props.weekm).start,\n endDate: getStartAndEndMonth(calendarDate, props.weekm).end,\n weekStartOnMonday: props.weekm,\n }\n }\n\n componentDidMount() {\n this.props.loadMonthWorkouts(this.state.startDate, this.state.endDate)\n }\n\n renderHeader(localeOptions) {\n const dateFormat = 'MMM yyyy'\n return (\n
\n
this.handlePrevMonth()}>\n \n
\n
\n \n {format(this.state.currentMonth, dateFormat, localeOptions)}\n \n
\n
this.handleNextMonth()}>\n \n
\n
\n )\n }\n\n renderDays(localeOptions) {\n const dateFormat = 'EEE'\n const days = []\n const { startDate } = this.state\n\n for (let i = 0; i < 7; i++) {\n days.push(\n
\n {format(addDays(startDate, i), dateFormat, localeOptions)}\n
\n )\n }\n return
{days}
\n }\n\n filterWorkouts(day) {\n const { workouts, user } = this.props\n if (workouts) {\n return workouts.filter(act =>\n isSameDay(getDateWithTZ(act.workout_date, user.timezone), day)\n )\n }\n return []\n }\n\n renderCells() {\n const { currentMonth, startDate, endDate, weekStartOnMonday } = this.state\n const { sports } = this.props\n\n const dateFormat = 'd'\n const rows = []\n\n let days = []\n let day = startDate\n let formattedDate = ''\n\n while (day <= endDate) {\n for (let i = 0; i < 7; i++) {\n formattedDate = format(day, dateFormat)\n const dayWorkouts = this.filterWorkouts(day)\n const isDisabled = isSameMonth(day, currentMonth) ? '' : '-disabled'\n const isWeekEnd = weekStartOnMonday\n ? [5, 6].includes(i)\n : [0, 6].includes(i)\n days.push(\n \n
\n {formattedDate}\n \n
\n
\n )\n day = addDays(day, 1)\n }\n rows.push(\n
\n {days}\n
\n )\n days = []\n }\n return
{rows}
\n }\n\n updateStateDate(calendarDate) {\n const { start, end } = getStartAndEndMonth(\n calendarDate,\n this.state.weekStartOnMonday\n )\n this.setState({\n currentMonth: calendarDate,\n startDate: start,\n endDate: end,\n })\n this.props.loadMonthWorkouts(start, end)\n }\n\n handleNextMonth() {\n const calendarDate = addMonths(this.state.currentMonth, 1)\n this.updateStateDate(calendarDate)\n }\n\n handlePrevMonth() {\n const calendarDate = subMonths(this.state.currentMonth, 1)\n this.updateStateDate(calendarDate)\n }\n\n render() {\n const localeOptions = {\n locale: this.props.language === 'fr' ? fr : enGB,\n }\n return (\n
\n
\n {this.renderHeader(localeOptions)}\n {this.renderDays(localeOptions)}\n {this.renderCells()}\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n workouts: state.calendarWorkouts.data,\n language: state.language,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadMonthWorkouts: (start, end) => {\n const dateFormat = 'yyyy-MM-dd'\n dispatch(\n getMonthWorkouts(format(start, dateFormat), format(end, dateFormat))\n )\n },\n })\n)(Calendar)\n","import React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport { formatRecord, translateSports } from '../../utils/workouts'\n\nexport default function RecordsCard(props) {\n const { records, sports, t, user } = props\n const translatedSports = translateSports(sports, t)\n const recordsBySport = records.reduce((sportList, record) => {\n const sport = translatedSports.find(s => s.id === record.sport_id)\n if (sportList[sport.label] === void 0) {\n sportList[sport.label] = {\n img: sport.img,\n records: [],\n }\n }\n sportList[sport.label].records.push(formatRecord(record, user.timezone))\n return sportList\n }, {})\n\n return (\n
\n
{t('workouts:Personal records')}
\n
\n {Object.keys(recordsBySport).length === 0\n ? t('common:No records.')\n : Object.keys(recordsBySport)\n .sort()\n .map(sportLabel => (\n
\n \n \n {sportLabel}\n \n {/* eslint-disable-next-line max-len */}\n \n \n \n \n \n \n \n {recordsBySport[sportLabel].records.map(rec => (\n \n \n \n \n \n ))}\n \n
\n \n {sportLabel}\n
\n {t(`workouts:${rec.record_type}`)}\n {rec.value}\n \n {rec.workout_date}\n \n
\n
\n ))}\n
\n
\n )\n}\n","import FitTrackeeGenericApi from '../fitTrackeeApi'\nimport { setData, setError } from './index'\n\nexport const getStats = (userName, type, data) => dispatch =>\n FitTrackeeGenericApi.getData(`stats/${userName}/${type}`, data)\n .then(ret => {\n if (ret.status === 'success') {\n dispatch(setData('statistics', ret.data))\n } else {\n dispatch(setError(`statistics|${ret.message}`))\n }\n })\n .catch(error => dispatch(setError(`statistics|${error}`)))\n","import {\n addDays,\n addMonths,\n addYears,\n format,\n startOfMonth,\n startOfWeek,\n startOfYear,\n} from 'date-fns'\n\nconst xAxisFormats = [\n { duration: 'week', dateFormat: 'yyyy-MM-dd', xAxis: 'dd/MM' },\n { duration: 'month', dateFormat: 'yyyy-MM', xAxis: 'MM/yyyy' },\n { duration: 'year', dateFormat: 'yyyy', xAxis: 'yyyy' },\n]\n\nexport const formatDuration = (totalSeconds, formatWithDay = false) => {\n let days = '0'\n if (formatWithDay) {\n days = String(Math.floor(totalSeconds / 86400))\n totalSeconds %= 86400\n }\n const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, '0')\n totalSeconds %= 3600\n const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0')\n const seconds = String(totalSeconds % 60).padStart(2, '0')\n if (formatWithDay) {\n return `${days === '0' ? '' : `${days}d:`}${\n hours === '00' ? '' : `${hours}h:`\n }${minutes}m:${seconds}s`\n }\n return `${hours === '00' ? '' : `${hours}:`}${minutes}:${seconds}`\n}\n\nexport const formatValue = (displayedData, value) =>\n value === 0\n ? ''\n : displayedData === 'distance'\n ? `${value.toFixed(2)} km`\n : displayedData === 'duration'\n ? formatDuration(value)\n : value\n\nconst dateIncrement = (duration, day) => {\n switch (duration) {\n case 'week':\n return addDays(day, 7)\n case 'year':\n return addYears(day, 1)\n case 'month':\n default:\n return addMonths(day, 1)\n }\n}\n\nconst startDate = (duration, day, weekm) => {\n switch (duration) {\n case 'week':\n return startOfWeek(day, { weekStartsOn: weekm ? 1 : 0 })\n case 'year':\n return startOfYear(day)\n case 'month':\n default:\n return startOfMonth(day)\n }\n}\n\nexport const formatStats = (stats, sports, params, displayedSports, weekm) => {\n const nbWorkoutsStats = []\n const distanceStats = []\n const durationStats = []\n\n for (\n let day = startDate(params.duration, params.start, weekm);\n day <= params.end;\n day = dateIncrement(params.duration, day)\n ) {\n const [xAxisFormat] = xAxisFormats.filter(\n x => x.duration === params.duration\n )\n const date = format(day, xAxisFormat.dateFormat)\n const xAxis = format(day, xAxisFormat.xAxis)\n const dataNbWorkouts = { date: xAxis }\n const dataDistance = { date: xAxis }\n const dataDuration = { date: xAxis }\n\n if (stats[date]) {\n Object.keys(stats[date])\n .filter(sportId =>\n displayedSports ? displayedSports.includes(+sportId) : true\n )\n .map(sportId => {\n const sportLabel = sports.filter(s => s.id === +sportId)[0].label\n dataNbWorkouts[sportLabel] = stats[date][sportId].nb_workouts\n dataDistance[sportLabel] = stats[date][sportId].total_distance\n dataDuration[sportLabel] = stats[date][sportId].total_duration\n return null\n })\n }\n nbWorkoutsStats.push(dataNbWorkouts)\n distanceStats.push(dataDistance)\n durationStats.push(dataDuration)\n }\n\n return {\n workouts: nbWorkoutsStats,\n distance: distanceStats,\n duration: durationStats,\n }\n}\n","import React from 'react'\n\nimport { formatDuration } from '../../../utils/stats'\n\nconst formatValue = (displayedData, value) =>\n displayedData === 'duration'\n ? formatDuration(value, true)\n : displayedData === 'distance'\n ? value.toFixed(2)\n : value\n\n/**\n * @return {null}\n */\nexport default function CustomTooltip(props) {\n const { active } = props\n if (active) {\n const { displayedData, payload, label } = props\n let total = 0\n payload.map(p => (total += p.value))\n return (\n
\n

{label}

\n {payload.map(p => (\n

\n {p.name}: {formatValue(displayedData, p.value)} {p.unit}\n

\n ))}\n {payload.length > 0 && (\n

Total: {formatValue(displayedData, total)}

\n )}\n
\n )\n }\n return null\n}\n","import React from 'react'\n\nimport { formatValue } from '../../../utils/stats'\n\n/**\n * @return {null}\n */\nexport default function CustomLabel(props) {\n const { displayedData, x, y, width, value } = props\n if (!value) {\n return null\n }\n const radius = 10\n const formattedValue = formatValue(displayedData, value)\n\n return (\n \n \n {formattedValue}\n \n \n )\n}\n","import React from 'react'\nimport {\n Bar,\n BarChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts'\n\nimport { formatValue } from '../../../utils/stats'\nimport { workoutColors } from '../../../utils/workouts'\nimport CustomTooltip from './CustomTooltip'\nimport CustomLabel from './CustomLabel'\n\nexport default class StatsCharts extends React.PureComponent {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayedData: 'distance',\n }\n }\n handleRadioChange(changeEvent) {\n this.setState({\n displayedData: changeEvent.target.name,\n })\n }\n\n render() {\n const { displayedData } = this.state\n const { sports, stats, t } = this.props\n if (Object.keys(stats).length === 0) {\n return t('common:No workouts.')\n }\n return (\n
\n
\n \n \n \n
\n \n \n \n formatValue(displayedData, value)} />\n }\n />\n {sports.map((s, i) => (\n \n ) : (\n ''\n )\n }\n name={t(`sports:${s.label}`)}\n />\n ))}\n \n \n
\n )\n }\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { connect } from 'react-redux'\n\nimport { getStats } from '../../../actions/stats'\nimport { formatStats } from '../../../utils/stats'\nimport StatsChart from './StatsChart'\n\nclass Statistics extends React.PureComponent {\n componentDidMount() {\n this.updateData()\n }\n\n componentDidUpdate(prevProps) {\n if (\n (this.props.user.username &&\n this.props.user.username !== prevProps.user.username) ||\n this.props.statsParams !== prevProps.statsParams\n ) {\n this.updateData()\n }\n }\n\n updateData() {\n if (this.props.user.username) {\n this.props.loadWorkouts(\n this.props.user.username,\n this.props.user.weekm,\n this.props.statsParams\n )\n }\n }\n\n render() {\n const {\n displayedSports,\n sports,\n statistics,\n statsParams,\n displayEmpty,\n t,\n user,\n } = this.props\n if (!displayEmpty && Object.keys(statistics).length === 0) {\n return {t('common:No workouts.')}\n }\n const stats = formatStats(\n statistics,\n sports,\n statsParams,\n displayedSports,\n user.weekm\n )\n return \n }\n}\n\nexport default connect(\n state => ({\n sports: state.sports.data,\n statistics: state.statistics.data,\n user: state.user,\n }),\n dispatch => ({\n loadWorkouts: (userName, weekm, data) => {\n const dateFormat = 'yyyy-MM-dd'\n // depends on user config (first day of week)\n const time =\n data.duration === 'week'\n ? `${data.duration}${weekm ? 'm' : ''}`\n : data.duration\n const params = {\n from: format(data.start, dateFormat),\n to: format(data.end, dateFormat),\n time: time,\n }\n dispatch(getStats(userName, data.type, params))\n },\n })\n)(Statistics)\n","import { endOfMonth, startOfMonth } from 'date-fns'\nimport React from 'react'\n\nimport Stats from '../Common/Stats'\n\nexport default class Statistics extends React.Component {\n constructor(props, context) {\n super(props, context)\n const date = new Date()\n this.state = {\n start: startOfMonth(date),\n end: endOfMonth(date),\n duration: 'week',\n type: 'by_time',\n }\n }\n\n render() {\n const { t } = this.props\n return (\n
\n
{t('dashboard:This month')}
\n
\n \n
\n
\n )\n }\n}\n","import React from 'react'\n\nexport default function UserStatistics(props) {\n const { t, user } = props\n const days = user.total_duration.match(/day/g)\n ? `${user.total_duration.split(' ')[0]} ${\n user.total_duration.match(/days/g) ? t('common:days') : t('common:day')\n }`\n : `0 ${t('common:days')},`\n let duration = user.total_duration.match(/day/g)\n ? user.total_duration.split(', ')[1]\n : user.total_duration\n duration = `${duration.split(':')[0]}h ${duration.split(':')[1]}min`\n return (\n
\n
\n
\n
\n
\n \n
\n
\n
{user.nb_workouts}
\n
{`${\n user.nb_workouts === 1\n ? t('common:workout')\n : t('common:workouts')\n }`}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
\n {Number(user.total_distance).toFixed(2)}\n
\n
km
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
{days}
\n
{duration}
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n
{user.nb_sports}
\n
{`${\n user.nb_sports === 1 ? t('common:sport') : t('common:sports')\n }`}
\n
\n
\n
\n
\n
\n )\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Link } from 'react-router-dom'\n\nimport StaticMap from '../Common/StaticMap'\nimport { getDateWithTZ } from '../../utils'\n\nexport default function WorkoutCard(props) {\n const { sports, t, user, workout } = props\n\n return (\n
\n
\n \n {sports\n .filter(sport => sport.id === workout.sport_id)\n .map(sport => t(`sports:${sport.label}`))}{' '}\n -{' '}\n {format(\n getDateWithTZ(workout.workout_date, user.timezone),\n 'dd/MM/yyyy HH:mm'\n )}\n \n
\n
\n
\n {workout.map && (\n
\n \n
\n )}\n
\n

\n {' '}\n {t('workouts:Duration')}: {workout.moving}\n {workout.map ? (\n \n
\n
\n
\n ) : (\n ' - '\n )}\n {' '}\n {t('workouts:Distance')}: {workout.distance} km\n

\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport Calendar from './Calendar'\nimport Message from '../Common/Message'\nimport NoWorkouts from '../Common/NoWorkouts'\nimport Records from './Records'\nimport Statistics from './Statistics'\nimport UserStatistics from './UserStatistics'\nimport WorkoutCard from './WorkoutCard'\nimport { getOrUpdateData } from '../../actions'\nimport { getMoreWorkouts } from '../../actions/workouts'\n\nclass DashBoard extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n page: 1,\n }\n }\n\n componentDidMount() {\n this.props.loadWorkouts()\n }\n\n render() {\n const {\n loadMoreWorkouts,\n message,\n records,\n sports,\n t,\n user,\n workouts,\n } = this.props\n const paginationEnd =\n workouts.length > 0\n ? workouts[workouts.length - 1].previous_workout === null\n : true\n const { page } = this.state\n return (\n
\n \n FitTrackee - {t('common:Dashboard')}\n \n {message ? (\n \n ) : (\n workouts &&\n user.total_duration &&\n sports.length > 0 && (\n
\n \n
\n
\n \n \n
\n
\n \n {workouts.length > 0 ? (\n workouts.map(workout => (\n \n ))\n ) : (\n \n )}\n {!paginationEnd && (\n {\n loadMoreWorkouts(page + 1)\n this.setState({ page: page + 1 })\n }}\n />\n )}\n
\n
\n
\n )\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n workouts: state.workouts.data,\n message: state.message,\n records: state.records.data,\n sports: state.sports.data,\n user: state.user,\n }),\n dispatch => ({\n loadWorkouts: () => {\n dispatch(getOrUpdateData('getData', 'workouts', { page: 1 }))\n dispatch(getOrUpdateData('getData', 'records'))\n },\n loadMoreWorkouts: page => {\n dispatch(getMoreWorkouts({ page }))\n },\n })\n )(DashBoard)\n)\n","import React from 'react'\n\nimport { version } from './../../utils'\n\nexport default function Footer() {\n return (\n
\n
\n FitTrackee v{version} -{' '}\n \n source code\n {' '}\n under{' '}\n \n GPLv3\n {' '}\n license -{' '}\n \n documentation\n \n
\n
\n )\n}\n","import React from 'react'\nimport { Trans } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport { Link } from 'react-router-dom'\n\nimport { logout } from '../../actions/user'\n\nclass Logout extends React.Component {\n componentDidMount() {\n this.props.UserLogout()\n }\n render() {\n return (\n
\n
\n
\n
\n
\n
\n \n You are now logged out. Click here to\n log back in.\n \n
\n
\n
\n
\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n user: state.user,\n }),\n dispatch => ({\n UserLogout: () => {\n dispatch(logout())\n },\n })\n)(Logout)\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m466.916 27.803h-421.832c-24.859 0-45.084 20.225-45.084 45.084v366.226c0 24.859 20.225 45.084 45.084 45.084h421.832c24.859 0 45.084-20.225 45.084-45.084v-366.226c0-24.859-20.225-45.084-45.084-45.084z\",\n fill: \"#f0f9ff\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m198.58 188.334-181.344-150.862c-7.75 6.107-13.456 14.691-15.905 24.554l164.142 136.551h33.102z\",\n fill: \"#f40055\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 198.576h33.93l163.447-135.973c-2.325-9.923-7.93-18.592-15.613-24.796l-181.764 151.211z\",\n fill: \"#c20044\"\n});\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m165.472 313.425-164.141 136.549c2.449 9.863 8.155 18.447 15.905 24.553l181.344-150.861-.005-10.241z\",\n fill: \"#f40055\"\n});\n\nvar _ref6 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 313.425v9.557l181.765 151.211c7.683-6.204 13.288-14.874 15.613-24.796l-163.446-135.971z\",\n fill: \"#c20044\"\n});\n\nvar _ref7 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m53.273 27.803 145.302 120.879v-120.879z\",\n fill: \"#406bd4\"\n});\n\nvar _ref8 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 150.571v-122.768h148.082z\",\n fill: \"#3257b0\"\n});\n\nvar _ref9 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m394.732 198.575 117.268-97.556v97.556z\",\n fill: \"#3257b0\"\n});\n\nvar _ref10 = /*#__PURE__*/React.createElement(\"g\", {\n fill: \"#406bd4\"\n}, /*#__PURE__*/React.createElement(\"path\", {\n d: \"m0 99.317v99.258h119.313z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"m0 313.425v97.699l117.44-97.699z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"m50.49 484.197 148.085-122.676v122.676z\"\n}));\n\nvar _ref11 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m313.425 484.197v-124.139l149.221 124.139z\",\n fill: \"#3257b0\"\n});\n\nvar _ref12 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m512 409.423-115.395-95.998h115.395z\",\n fill: \"#3257b0\"\n});\n\nvar _ref13 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m512 222.142h-222.142v-194.339h-67.716v194.339h-222.142v67.716h222.142v194.339h67.716v-194.339h222.142z\",\n fill: \"#f40055\"\n});\n\nvar _ref14 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m289.858 222.142v-194.339h-33.858v456.394h33.858v-194.339h222.142v-67.716z\",\n fill: \"#c20044\"\n});\n\nfunction SvgEn(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Capa_1\",\n enableBackground: \"new 0 0 512 512\",\n height: 512,\n viewBox: \"0 0 512 512\",\n width: 512,\n xmlns: \"http://www.w3.org/2000/svg\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13, _ref14);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgEn);\nexport default __webpack_public_path__ + \"static/media/en.9e6dbfb0.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m173.899 31.804h-8.707l-4.397-4h-115.711c-24.859-.001-45.084 20.224-45.084 45.083v366.226c0 24.859 20.225 45.084 45.084 45.084h115.711l6.348-4h6.755v-448.393z\",\n fill: \"#406bd4\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m466.916 27.803h-115.711l-4.523 4h-5.141v448.393h4.141l5.523 4h115.711c24.859 0 45.084-20.225 45.084-45.084v-366.225c0-24.859-20.225-45.084-45.084-45.084z\",\n fill: \"#c20044\"\n});\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m160.795 27.803h190.409v456.394h-190.409z\",\n fill: \"#f0f9ff\"\n});\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"m256 27.803h95.205v456.394h-95.205z\",\n fill: \"#cee5f5\"\n});\n\nfunction SvgFr(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Capa_1\",\n enableBackground: \"new 0 0 512 512\",\n height: 512,\n viewBox: \"0 0 512 512\",\n width: 512,\n xmlns: \"http://www.w3.org/2000/svg\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3, _ref4, _ref5);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgFr);\nexport default __webpack_public_path__ + \"static/media/fr.d0f9280c.svg\";\nexport { ForwardRef as ReactComponent };","import React, { Component } from 'react'\nimport { connect } from 'react-redux'\n\nimport { ReactComponent as EnFlag } from '../../images/flags/en.svg'\nimport { ReactComponent as FrFlag } from '../../images/flags/fr.svg'\nimport { updateLanguage } from '../../actions/index'\n\nexport const languages = [\n {\n name: 'en',\n selected: true,\n flag: ,\n },\n {\n name: 'fr',\n selected: false,\n flag: ,\n },\n]\n\nclass Dropdown extends Component {\n constructor(props) {\n super(props)\n this.state = {\n isOpen: false,\n }\n }\n\n toggleDropdown() {\n this.setState(prevState => ({\n isOpen: !prevState.isOpen,\n }))\n }\n\n render() {\n const { isOpen } = this.state\n const { language: selected, onUpdateLanguage } = this.props\n return (\n
this.toggleDropdown()}>\n
    \n {languages\n .filter(language =>\n isOpen ? language : language.name === selected\n )\n .map(language => (\n onUpdateLanguage(language.name, selected)}\n >\n {language.flag} {language.name}\n \n ))}\n
\n
\n )\n }\n}\n\nexport default connect(\n state => ({\n language: state.language,\n }),\n dispatch => ({\n onUpdateLanguage: (lang, selected) => {\n if (lang !== selected) {\n dispatch(updateLanguage(lang))\n }\n },\n })\n)(Dropdown)\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { withTranslation } from 'react-i18next'\nimport { Link } from 'react-router-dom'\n\nimport LanguageDropdown from './LanguageDropdown'\nimport { apiUrl } from '../../utils'\n\nclass NavBar extends React.PureComponent {\n render() {\n const { admin, isAuthenticated, picture, t, username } = this.props\n return (\n
\n
\n \n \n )\n }\n}\n\nexport default withTranslation()(\n connect(({ user }) => ({\n admin: user.admin,\n isAuthenticated: user.isAuthenticated,\n picture: user.picture,\n username: user.username,\n }))(NavBar)\n)\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M468.683,287.265h-69.07c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h69.07 c4.147,0,7.508-3.361,7.508-7.508C476.191,290.626,472.83,287.265,468.683,287.265z\"\n})));\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M105.012,268.377L85.781,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L58.034,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C109.507,275.266,108.499,270.62,105.012,268.377z\"\n})));\n\nvar _ref4 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M194.441,268.377L175.21,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.47,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.776l-17.471-11.243 c-3.487-2.245-8.133-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L147.463,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.47,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C198.936,275.266,197.928,270.62,194.441,268.377z\"\n})));\n\nvar _ref5 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M283.871,268.377L264.64,256l19.231-12.376c3.487-2.243,4.495-6.888,2.251-10.376c-2.245-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.775c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.471-11.243 c-3.486-2.245-8.134-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L236.892,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.471-11.243v20.775 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.886-1.216,6.32-3.446C288.366,275.266,287.358,270.62,283.871,268.377z\"\n})));\n\nvar _ref6 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M373.3,268.377L354.069,256l19.231-12.376c3.487-2.244,4.495-6.889,2.25-10.376c-2.244-3.486-6.888-4.497-10.376-2.25 l-17.471,11.243v-20.776c0-4.147-3.361-7.508-7.508-7.508c-4.147,0-7.508,3.361-7.508,7.508v20.775l-17.47-11.243 c-3.486-2.245-8.132-1.238-10.376,2.25c-2.245,3.487-1.237,8.133,2.25,10.376L326.322,256l-19.231,12.376 c-3.487,2.244-4.495,6.889-2.25,10.376c1.435,2.23,3.852,3.446,6.32,3.446c1.391,0,2.799-0.386,4.056-1.196l17.47-11.243v20.776 c0,4.147,3.361,7.508,7.508,7.508c4.147,0,7.508-3.361,7.508-7.508V269.76l17.471,11.243c1.257,0.809,2.664,1.196,4.056,1.196 c2.467,0,4.885-1.216,6.32-3.446C377.795,275.266,376.787,270.62,373.3,268.377z\"\n})));\n\nvar _ref7 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M271.792,330.359H15.016V181.642h93.1c4.147,0,7.508-3.361,7.508-7.508c0-4.147-3.361-7.508-7.508-7.508H12.513 C5.613,166.626,0,172.24,0,179.14v153.722c0,6.9,5.613,12.513,12.513,12.513h259.278c4.147,0,7.508-3.361,7.508-7.508 C279.299,333.72,275.939,330.359,271.792,330.359z\"\n})));\n\nvar _ref8 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M499.487,166.626H162.174c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h334.811v148.716H323.848 c-4.147,0-7.508,3.361-7.508,7.508c0,4.147,3.361,7.508,7.508,7.508h175.64c6.9,0,12.513-5.613,12.513-12.513V179.14 C512.001,172.24,506.387,166.626,499.487,166.626z\"\n})));\n\nfunction SvgPassword(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Layer_1\",\n xmlns: \"http://www.w3.org/2000/svg\",\n xmlnsXlink: \"http://www.w3.org/1999/xlink\",\n x: \"0px\",\n y: \"0px\",\n viewBox: \"0 0 512.001 512.001\",\n style: {\n enableBackground: \"new 0 0 512.001 512.001\"\n },\n xmlSpace: \"preserve\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgPassword);\nexport default __webpack_public_path__ + \"static/media/password.afe6a2a5.svg\";\nexport { ForwardRef as ReactComponent };","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"g\", null, /*#__PURE__*/React.createElement(\"path\", {\n d: \"M339.798,260.429c0.13-0.026,0.257-0.061,0.385-0.094c0.109-0.028,0.219-0.051,0.326-0.084 c0.125-0.038,0.247-0.085,0.369-0.129c0.108-0.039,0.217-0.074,0.324-0.119c0.115-0.048,0.226-0.104,0.338-0.157 c0.109-0.052,0.22-0.1,0.327-0.158c0.107-0.057,0.208-0.122,0.312-0.184c0.107-0.064,0.215-0.124,0.319-0.194 c0.111-0.074,0.214-0.156,0.321-0.236c0.09-0.067,0.182-0.13,0.27-0.202c0.162-0.133,0.316-0.275,0.466-0.421 c0.027-0.026,0.056-0.048,0.083-0.075c0.028-0.028,0.052-0.059,0.079-0.088c0.144-0.148,0.284-0.3,0.416-0.46 c0.077-0.094,0.144-0.192,0.216-0.289c0.074-0.1,0.152-0.197,0.221-0.301c0.074-0.111,0.139-0.226,0.207-0.34 c0.057-0.096,0.118-0.19,0.171-0.289c0.062-0.115,0.114-0.234,0.169-0.351c0.049-0.104,0.101-0.207,0.146-0.314 c0.048-0.115,0.086-0.232,0.128-0.349c0.041-0.114,0.085-0.227,0.12-0.343c0.036-0.118,0.062-0.238,0.092-0.358 c0.029-0.118,0.063-0.234,0.086-0.353c0.028-0.141,0.045-0.283,0.065-0.425c0.014-0.1,0.033-0.199,0.043-0.3 c0.025-0.249,0.038-0.498,0.038-0.748V92.76c0-4.143-3.357-7.5-7.5-7.5h-236.25c-0.066,0-0.13,0.008-0.196,0.01 c-0.143,0.004-0.285,0.01-0.427,0.022c-0.113,0.009-0.225,0.022-0.337,0.037c-0.128,0.016-0.255,0.035-0.382,0.058 c-0.119,0.021-0.237,0.046-0.354,0.073c-0.119,0.028-0.238,0.058-0.356,0.092c-0.117,0.033-0.232,0.069-0.346,0.107 c-0.117,0.04-0.234,0.082-0.349,0.128c-0.109,0.043-0.216,0.087-0.322,0.135c-0.118,0.053-0.235,0.11-0.351,0.169 c-0.099,0.051-0.196,0.103-0.292,0.158c-0.116,0.066-0.23,0.136-0.343,0.208c-0.093,0.06-0.184,0.122-0.274,0.185 c-0.106,0.075-0.211,0.153-0.314,0.235c-0.094,0.075-0.186,0.152-0.277,0.231c-0.09,0.079-0.179,0.158-0.266,0.242 c-0.099,0.095-0.194,0.194-0.288,0.294c-0.047,0.05-0.097,0.094-0.142,0.145c-0.027,0.03-0.048,0.063-0.074,0.093 c-0.094,0.109-0.182,0.223-0.27,0.338c-0.064,0.084-0.13,0.168-0.19,0.254c-0.078,0.112-0.15,0.227-0.222,0.343 c-0.059,0.095-0.12,0.189-0.174,0.286c-0.063,0.112-0.118,0.227-0.175,0.342c-0.052,0.105-0.106,0.21-0.153,0.317 c-0.049,0.113-0.092,0.23-0.135,0.345c-0.043,0.113-0.087,0.225-0.124,0.339c-0.037,0.115-0.067,0.232-0.099,0.349 c-0.032,0.12-0.066,0.239-0.093,0.36c-0.025,0.113-0.042,0.228-0.062,0.342c-0.022,0.13-0.044,0.26-0.06,0.39 c-0.013,0.108-0.019,0.218-0.027,0.328c-0.01,0.14-0.019,0.28-0.021,0.421c-0.001,0.041-0.006,0.081-0.006,0.122v46.252 c0,4.143,3.357,7.5,7.5,7.5s7.5-3.357,7.5-7.5v-29.595l66.681,59.037c-0.348,0.245-0.683,0.516-0.995,0.827l-65.687,65.687v-49.288 c0-4.143-3.357-7.5-7.5-7.5s-7.5,3.357-7.5,7.5v9.164h-38.75c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h38.75v43.231 c0,4.143,3.357,7.5,7.5,7.5h236.25c0.247,0,0.494-0.013,0.74-0.037c0.115-0.011,0.226-0.033,0.339-0.049 C339.542,260.469,339.67,260.454,339.798,260.429z M330.834,234.967l-65.688-65.687c-0.042-0.042-0.087-0.077-0.13-0.117 l49.383-41.897c3.158-2.68,3.546-7.412,0.866-10.571c-2.678-3.157-7.41-3.547-10.571-0.866l-84.381,71.59l-98.444-87.158h208.965 V234.967z M185.878,179.888c0.535-0.535,0.969-1.131,1.308-1.765l28.051,24.835c1.418,1.255,3.194,1.885,4.972,1.885 c1.726,0,3.451-0.593,4.853-1.781l28.587-24.254c0.26,0.38,0.553,0.743,0.89,1.08l65.687,65.687H120.191L185.878,179.888z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M7.5,170.676h126.667c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H7.5c-4.143,0-7.5,3.357-7.5,7.5 S3.357,170.676,7.5,170.676z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M20.625,129.345H77.5c4.143,0,7.5-3.357,7.5-7.5s-3.357-7.5-7.5-7.5H20.625c-4.143,0-7.5,3.357-7.5,7.5 S16.482,129.345,20.625,129.345z\"\n}), /*#__PURE__*/React.createElement(\"path\", {\n d: \"M62.5,226.51h-55c-4.143,0-7.5,3.357-7.5,7.5s3.357,7.5,7.5,7.5h55c4.143,0,7.5-3.357,7.5-7.5S66.643,226.51,62.5,226.51z\"\n}));\n\nfunction SvgMailSend(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n id: \"Capa_1\",\n xmlns: \"http://www.w3.org/2000/svg\",\n xmlnsXlink: \"http://www.w3.org/1999/xlink\",\n x: \"0px\",\n y: \"0px\",\n viewBox: \"0 0 345.834 345.834\",\n style: {\n enableBackground: \"new 0 0 345.834 345.834\"\n },\n xmlSpace: \"preserve\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgMailSend);\nexport default __webpack_public_path__ + \"static/media/mail-send.619079f0.svg\";\nexport { ForwardRef as ReactComponent };","import React from 'react'\nimport { Trans, useTranslation } from 'react-i18next'\nimport { Link } from 'react-router-dom'\n\nimport { ReactComponent as Password } from '../../images/password.svg'\nimport { ReactComponent as MailSend } from '../../images/mail-send.svg'\n\nexport default function PasswordReset(props) {\n const { t } = useTranslation()\n const { action } = props\n return (\n
\n
\n
\n
\n
\n
\n {action === 'sent' && (\n <>\n
\n \n
\n {t(\n // eslint-disable-next-line max-len\n \"user:Check your email. If your address is in our database, you'll received an email with a link to reset your password.\"\n )}\n \n )}\n {action === 'updated' && (\n <>\n
\n \n
\n \n {/* prettier-ignore */}\n Your password have been updated. Click\n here to log in.\n \n \n )}\n
\n
\n
\n
\n
\n
\n )\n}\n","import { format } from 'date-fns'\nimport React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport TimezonePicker from 'react-timezone'\n\nimport Message from '../Common/Message'\nimport { deleteUser, handleProfileFormSubmit } from '../../actions/user'\nimport { history } from '../../index'\nimport { languages } from '../NavBar/LanguageDropdown'\nimport CustomModal from '../Common/CustomModal'\n\nclass ProfileEdit extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n formData: {},\n displayModal: false,\n }\n }\n\n componentDidMount() {\n this.initForm()\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.user !== this.props.user) {\n this.initForm()\n }\n }\n\n initForm() {\n const { user } = this.props\n const formData = {}\n Object.keys(user).map(k =>\n user[k] === null\n ? (formData[k] = '')\n : k === 'birth_date'\n ? (formData[k] = format(new Date(user[k]), 'yyyy-MM-DD'))\n : (formData[k] = user[k])\n )\n this.setState({ formData })\n }\n\n handleFormChange(e) {\n const { formData } = this.state\n if (e.target.name === 'weekm') {\n formData.weekm = e.target.value === 'Monday'\n } else {\n formData[e.target.name] = e.target.value\n }\n this.setState(formData)\n }\n\n displayModal(value) {\n this.setState(prevState => ({\n ...prevState,\n displayModal: value,\n }))\n }\n\n render() {\n const {\n message,\n onDeleteUser,\n onHandleProfileFormSubmit,\n t,\n user,\n } = this.props\n const { displayModal, formData } = this.state\n return (\n
\n \n FitTrackee - {t('user:Profile Edition')}\n \n {formData.isAuthenticated && (\n
\n {displayModal && (\n {\n onDeleteUser(user.username)\n this.displayModal(false)\n }}\n close={() => this.displayModal(false)}\n />\n )}\n

{t('user:Profile Edition')}

\n
\n
\n
\n
\n
{user.username}
\n
\n
\n
\n {\n event.preventDefault()\n onHandleProfileFormSubmit(formData)\n }}\n >\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n
\n \n
\n \n {\n event.preventDefault()\n this.displayModal(true)\n }}\n >\n {t('user:Delete my account')}\n \n history.push('/profile')}\n >\n {t('common:Cancel')}\n \n \n \n
\n
\n
\n
\n
\n
\n
\n
\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n location: state.router.location,\n message: state.message,\n user: state.user,\n }),\n dispatch => ({\n onDeleteUser: username => {\n dispatch(deleteUser(username))\n },\n onHandleProfileFormSubmit: formData => {\n dispatch(handleProfileFormSubmit(formData))\n },\n })\n )(ProfileEdit)\n)\n","import {\n endOfMonth,\n endOfWeek,\n endOfYear,\n startOfMonth,\n startOfYear,\n startOfWeek,\n addMonths,\n addWeeks,\n addYears,\n subMonths,\n subWeeks,\n subYears,\n} from 'date-fns'\nimport React from 'react'\nimport { Helmet } from 'react-helmet'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport NoWorkouts from '../Common/NoWorkouts'\nimport Stats from '../Common/Stats'\nimport { workoutColors, translateSports } from '../../utils/workouts'\n\nconst durations = ['week', 'month', 'year']\n\nclass Statistics extends React.Component {\n constructor(props, context) {\n super(props, context)\n const date = new Date()\n this.state = {\n displayedSports: props.sports.map(sport => sport.id),\n statsParams: {\n start: startOfMonth(subMonths(date, 11)),\n end: endOfMonth(date),\n duration: 'month',\n type: 'by_time',\n },\n }\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.sports !== prevProps.sports) {\n this.updateDisplayedSports()\n }\n }\n\n updateDisplayedSports() {\n const { sports } = this.props\n this.setState({ displayedSports: sports.map(sport => sport.id) })\n }\n\n handleOnChangeDuration(e) {\n const duration = e.target.name\n\n const date = new Date()\n const start =\n duration === 'year'\n ? startOfYear(subYears(date, 9))\n : duration === 'week'\n ? startOfMonth(subMonths(date, 2))\n : startOfMonth(subMonths(date, 11))\n const end =\n duration === 'year'\n ? endOfYear(date)\n : duration === 'week'\n ? endOfWeek(date)\n : endOfMonth(date)\n this.setState({ statsParams: { duration, end, start, type: 'by_time' } })\n }\n\n handleOnChangeSports(sportId) {\n const { displayedSports } = this.state\n if (displayedSports.includes(sportId)) {\n this.setState({\n displayedSports: displayedSports.filter(s => s !== sportId),\n })\n } else {\n this.setState({ displayedSports: displayedSports.concat([sportId]) })\n }\n }\n\n handleOnClickArrows(forward) {\n const { start, end, duration } = this.state.statsParams\n let newStart, newEnd\n if (forward) {\n newStart =\n duration === 'year'\n ? startOfYear(subYears(start, 1))\n : duration === 'week'\n ? startOfWeek(subWeeks(start, 1))\n : startOfMonth(subMonths(start, 1))\n newEnd =\n duration === 'year'\n ? endOfYear(subYears(end, 1))\n : duration === 'week'\n ? endOfWeek(subWeeks(end, 1))\n : endOfMonth(subMonths(end, 1))\n } else {\n newStart =\n duration === 'year'\n ? startOfYear(addYears(start, 1))\n : duration === 'week'\n ? startOfWeek(addWeeks(start, 1))\n : startOfMonth(addMonths(start, 1))\n newEnd =\n duration === 'year'\n ? endOfYear(addYears(end, 1))\n : duration === 'week'\n ? endOfWeek(addWeeks(end, 1))\n : endOfMonth(addMonths(end, 1))\n }\n this.setState({\n statsParams: { duration, end: newEnd, start: newStart, type: 'by_time' },\n })\n }\n\n render() {\n const { displayedSports, statsParams } = this.state\n const { sports, t, user } = this.props\n const translatedSports = translateSports(\n sports.filter(sport => user.sports_list.includes(sport.id)),\n t\n )\n return (\n <>\n \n FitTrackee - {t('statistics:Statistics')}\n \n
\n
\n
{t('statistics:Statistics')}
\n \n
\n
\n

\n this.handleOnClickArrows(true)}\n />\n

\n
\n
\n {durations.map(d => (\n
\n \n
\n ))}\n
\n
\n

\n this.handleOnClickArrows(false)}\n />\n

\n
\n
\n \n
\n {translatedSports.map(sport => (\n \n ))}\n
\n
\n
\n {user.nb_workouts === 0 && }\n
\n \n )\n }\n}\n\nexport default withTranslation()(\n connect(state => ({\n sports: state.sports.data,\n user: state.user,\n }))(Statistics)\n)\n","import React from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { Helmet } from 'react-helmet'\nimport { Link } from 'react-router-dom'\n\nimport { history } from '../../index'\n\nexport default function Form(props) {\n const { t } = useTranslation()\n const pageTitle = `user:${props.formType\n .charAt(0)\n .toUpperCase()}${props.formType.slice(1)}`\n return (\n
\n \n FitTrackee - {t(`user:${props.formType}`)}\n \n

{t(pageTitle)}

\n
\n
\n
\n
\n
\n {props.formType === 'register' && !props.isRegistrationAllowed ? (\n
\n
Registration is disabled.
\n
\n history.go(-1)}\n >\n Back\n \n
\n
\n ) : (\n <>\n \n props.handleUserFormSubmit(event, props.formType)\n }\n >\n {props.formType === 'register' && (\n
\n \n
\n )}\n {props.formType !== 'password reset' && (\n
\n \n
\n )}\n {props.formType !== 'reset your password' && (\n <>\n
\n \n
\n {props.formType !== 'login' && (\n
\n \n
\n )}\n \n )}\n \n \n

\n {props.formType === 'login' && (\n \n {t('user:Forgot password?')}\n \n )}\n

\n \n )}\n
\n
\n
\n
\n
\n )\n}\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\nimport { Redirect } from 'react-router-dom'\n\nimport Form from './Form'\nimport Message from '../Common/Message'\nimport { handleUserFormSubmit } from '../../actions/user'\nimport { isLoggedIn } from '../../utils'\n\nclass UserForm extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n formData: {\n username: '',\n email: '',\n password: '',\n password_conf: '',\n },\n }\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.location.pathname !== this.props.location.pathname) {\n this.emptyForm()\n }\n }\n\n emptyForm() {\n const { formData } = this.state\n Object.keys(formData).map(k => (formData[k] = ''))\n this.setState(formData)\n }\n\n onHandleFormChange(e) {\n const { formData } = this.state\n formData[e.target.name] = e.target.value\n this.setState(formData)\n }\n\n render() {\n const {\n formType,\n isRegistrationAllowed,\n message,\n messages,\n onHandleUserFormSubmit,\n t,\n } = this.props\n const { formData } = this.state\n const { token } = this.props.location.query\n return (\n
\n {isLoggedIn() || (formType === 'password reset' && !token) ? (\n \n ) : (\n
\n \n this.onHandleFormChange(event)}\n handleUserFormSubmit={event => {\n event.preventDefault()\n if (formType === 'password reset') {\n formData.token = token\n }\n onHandleUserFormSubmit(formData, formType)\n }}\n />\n
\n )}\n
\n )\n }\n}\nexport default withTranslation()(\n connect(\n state => ({\n isRegistrationAllowed: state.application.config.is_registration_enabled,\n location: state.router.location,\n message: state.message,\n messages: state.messages,\n }),\n dispatch => ({\n onHandleUserFormSubmit: (formData, formType) => {\n formType =\n formType === 'password reset'\n ? 'password/update'\n : formType === 'reset your password'\n ? 'password/reset-request'\n : formType\n dispatch(handleUserFormSubmit(formData, formType))\n },\n })\n )(UserForm)\n)\n","import React from 'react'\nimport { withTranslation } from 'react-i18next'\nimport { connect } from 'react-redux'\n\nimport CustomModal from '../Common/CustomModal'\nimport ProfileDetail from './ProfileDetail'\nimport { getOrUpdateData } from '../../actions'\nimport { deleteUser } from '../../actions/user'\n\nclass UserProfile extends React.Component {\n constructor(props, context) {\n super(props, context)\n this.state = {\n displayModal: false,\n }\n }\n\n componentDidMount() {\n this.props.loadUser(this.props.match.params.userName)\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.match.params.userName !== this.props.match.params.userName) {\n this.props.loadUser(this.props.match.params.userName)\n }\n }\n\n displayModal(value) {\n this.setState(prevState => ({\n ...prevState,\n displayModal: value,\n }))\n }\n\n render() {\n const { t, currentUser, onDeleteUser, users } = this.props\n const { displayModal } = this.state\n const [user] = users\n const editable = user ? currentUser.username === user.username : false\n return (\n
\n {displayModal && (\n {\n onDeleteUser(user.username)\n this.displayModal(false)\n }}\n close={() => this.displayModal(false)}\n />\n )}\n {user && (\n this.displayModal(e)}\n t={t}\n user={user}\n />\n )}\n
\n )\n }\n}\n\nexport default withTranslation()(\n connect(\n state => ({\n currentUser: state.user,\n users: state.users.data,\n }),\n dispatch => ({\n onDeleteUser: username => {\n dispatch(deleteUser(username, true))\n },\n loadUser: userName => {\n dispatch(getOrUpdateData('getData', 'users', { username: userName }))\n },\n })\n )(UserProfile)\n)\n","import React from 'react'\nimport { connect } from 'react-redux'\nimport { Route, Switch } from 'react-router-dom'\n\nimport './App.css'\nimport Admin from './Admin'\nimport Workout from './Workout'\nimport Workouts from './Workouts'\nimport CurrentUserProfile from './User/CurrentUserProfile'\nimport Dashboard from './Dashboard'\nimport Footer from './Footer'\nimport Logout from './User/Logout'\nimport NavBar from './NavBar'\nimport NotFound from './Others/NotFound'\nimport PasswordReset from './User/PasswordReset'\nimport ProfileEdit from './User/ProfileEdit'\nimport Statistics from './Statistics'\nimport UserForm from './User/UserForm'\nimport UserProfile from './User/UserProfile'\nimport { getAppData } from '../actions/application'\n\nclass App extends React.Component {\n constructor(props) {\n super(props)\n this.props = props\n }\n componentDidMount() {\n this.props.loadAppConfig()\n }\n\n render() {\n return (\n
\n \n \n \n }\n />\n }\n />\n }\n />\n }\n />\n }\n />\n }\n />\n \n \n \n \n \n \n \n \n \n \n \n
\n
\n )\n }\n}\nexport default connect(\n () => ({}),\n dispatch => ({\n loadAppConfig: () => {\n dispatch(getAppData('config'))\n },\n })\n)(App)\n","import React from 'react'\nimport { Provider } from 'react-redux'\nimport { ConnectedRouter } from 'connected-react-router'\n\nexport default function Root({ store, history, children }) {\n return (\n \n {children}\n \n )\n}\n","// In production, we register a service worker to serve assets from local cache.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on the \"N+1\" visit to a page, since previously\n// cached resources are updated in the background.\n\n// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.\n// This link also includes instructions on opting out of this behavior.\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n)\n\nexport default function register() {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location)\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets;\n // see https://github.com/facebookincubator/create-react-app/issues/2374\n return\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`\n\n if (isLocalhost) {\n // This is running on localhost.\n // Lets check if a service worker still exists or not.\n checkValidServiceWorker(swUrl)\n } else {\n // Is not local host. Just register service worker\n registerValidSW(swUrl)\n }\n })\n }\n}\n\nfunction registerValidSW(swUrl) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the old content will have been purged and\n // the fresh content will have been added to the cache.\n // It's the perfect time to display a \"New content is\n // available; please refresh.\" message in your web app.\n // eslint-disable-next-line no-console\n console.log('New content is available; please refresh.')\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n // eslint-disable-next-line no-console\n console.log('Content is cached for offline use.')\n }\n }\n }\n }\n })\n .catch(error => {\n console.error('Error during service worker registration:', error)\n })\n}\n\nfunction checkValidServiceWorker(swUrl) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n if (\n response.status === 404 ||\n response.headers.get('content-type').indexOf('javascript') === -1\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload()\n })\n })\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl)\n }\n })\n .catch(() => {\n // eslint-disable-next-line no-console\n console.log(\n 'No internet connection found. App is running in offline mode.'\n )\n })\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister()\n })\n }\n}\n","const emptyData = {\n data: [],\n}\n\nexport default {\n language: 'en',\n message: '',\n messages: [],\n user: {\n isAuthenticated: false,\n },\n workouts: {\n ...emptyData,\n },\n application: {\n statistics: {},\n config: {\n gpx_limit_import: null,\n is_registration_enabled: null,\n max_single_file_size: null,\n max_users: null,\n max_zip_file_size: null,\n registration: null,\n },\n },\n calendarWorkouts: {\n ...emptyData,\n },\n chartData: [],\n // check if storing gpx content is OK\n gpx: null,\n loading: false,\n records: {\n ...emptyData,\n },\n sports: {\n ...emptyData,\n },\n statistics: {\n data: {},\n },\n users: {\n ...emptyData,\n },\n}\n","const routesWithoutAuthentication = [\n '/login',\n '/register',\n '/password-reset',\n '/password-reset/request',\n '/password-reset/sent',\n '/updated-password',\n]\n\nconst updatePath = (toPath, newPath) => {\n if (typeof toPath === 'string' || toPath instanceof String) {\n toPath = newPath\n } else {\n toPath.pathname = newPath\n }\n return toPath\n}\n\nconst pathInterceptor = toPath => {\n if (\n !window.localStorage.authToken &&\n !routesWithoutAuthentication.includes(toPath.pathname)\n ) {\n toPath = updatePath(toPath, '/login')\n }\n if (\n window.localStorage.authToken &&\n routesWithoutAuthentication.includes(toPath.pathname)\n ) {\n toPath = updatePath(toPath, '/')\n }\n return toPath\n}\n\nexport const historyEnhancer = originalHistory => {\n originalHistory.location = pathInterceptor(originalHistory.location)\n return {\n ...originalHistory,\n push: (path, ...args) =>\n originalHistory.push(pathInterceptor(path), ...args),\n replace: (path, ...args) =>\n originalHistory.replace(pathInterceptor(path), ...args),\n }\n}\n","import { connectRouter } from 'connected-react-router'\nimport { combineReducers } from 'redux'\n\nimport initial from './initial'\n\nconst handleDataAndError = (state, type, action) => {\n if (action.target !== type) {\n return state\n }\n if (action.type === 'SET_DATA') {\n return {\n ...state,\n data: action.data[action.target],\n }\n }\n if (action.type === 'SET_PAGINATED_DATA') {\n return {\n ...state,\n data: action.data[action.target],\n pagination: action.pagination,\n }\n }\n return state\n}\n\nconst workouts = (state = initial.workouts, action) => {\n switch (action.type) {\n case 'LOGOUT':\n return initial.workouts\n case 'PUSH_WORKOUTS':\n return {\n ...state,\n data: state.data.concat(action.workouts),\n }\n case 'REMOVE_WORKOUT':\n return {\n ...state,\n data: state.data.filter(workout => workout.id !== action.workoutId),\n }\n default:\n return handleDataAndError(state, 'workouts', action)\n }\n}\n\nconst application = (state = initial.application, action) => {\n if (action.type === 'SET_APP_CONFIG') {\n return {\n ...state,\n config: action.data,\n }\n }\n if (action.type === 'SET_APP_STATS') {\n return {\n ...state,\n statistics: action.data,\n }\n }\n return state\n}\n\nconst calendarWorkouts = (state = initial.calendarWorkouts, action) => {\n switch (action.type) {\n case 'LOGOUT':\n return initial.calendarWorkouts\n case 'UPDATE_CALENDAR':\n return {\n ...state,\n data: action.workouts,\n }\n default:\n return handleDataAndError(state, 'calendarWorkouts', action)\n }\n}\n\nconst chartData = (state = initial.chartData, action) => {\n if (action.type === 'SET_CHART_DATA') {\n return action.chartData\n }\n return state\n}\n\nconst gpx = (state = initial.gpx, action) => {\n if (action.type === 'SET_GPX') {\n return action.gpxContent\n }\n return state\n}\n\nconst language = (state = initial.language, action) => {\n if (action.type === 'SET_LANGUAGE') {\n return action.language\n }\n return state\n}\n\nconst loading = (state = initial.loading, action) => {\n if (action.type === 'SET_LOADING') {\n return action.loading\n }\n return state\n}\n\nconst message = (state = initial.message, action) => {\n switch (action.type) {\n case 'AUTH_ERROR':\n case 'PROFILE_ERROR':\n case 'PROFILE_UPDATE_ERROR':\n case 'PICTURE_ERROR':\n case 'SET_ERROR':\n return action.message\n case 'LOGOUT':\n case 'PROFILE_SUCCESS':\n case 'SET_RESULTS':\n case '@@router/LOCATION_CHANGE':\n return ''\n default:\n return state\n }\n}\n\nconst messages = (state = initial.messages, action) => {\n switch (action.type) {\n case 'AUTH_ERRORS':\n return action.messages\n case 'LOGOUT':\n case 'PROFILE_SUCCESS':\n case '@@router/LOCATION_CHANGE':\n return []\n default:\n return state\n }\n}\n\nconst records = (state = initial.records, action) => {\n if (action.type === 'LOGOUT') {\n return initial.records\n }\n return handleDataAndError(state, 'records', action)\n}\n\nconst sports = (state = initial.sports, action) => {\n if (action.type === 'UPDATE_SPORT_DATA') {\n return {\n ...state,\n data: state.data.map(sport => {\n if (sport.id === action.data.id) {\n sport.is_active = action.data.is_active\n }\n return sport\n }),\n }\n }\n return handleDataAndError(state, 'sports', action)\n}\n\nconst users = (state = initial.users, action) => {\n if (action.type === 'UPDATE_USER_DATA') {\n return {\n ...state,\n data: state.data.map(user => {\n if (user.username === action.data.username) {\n user.admin = action.data.admin\n }\n return user\n }),\n }\n }\n return handleDataAndError(state, 'users', action)\n}\n\nconst user = (state = initial.user, action) => {\n switch (action.type) {\n case 'AUTH_ERROR':\n case 'PROFILE_ERROR':\n case 'LOGOUT':\n window.localStorage.removeItem('authToken')\n return initial.user\n case 'PROFILE_SUCCESS':\n return action.profil\n default:\n return state\n }\n}\n\nconst statistics = (state = initial.statistics, action) => {\n if (action.type === 'LOGOUT') {\n return initial.statistics\n }\n return handleDataAndError(state, 'statistics', action)\n}\n\nexport default history =>\n combineReducers({\n workouts,\n application,\n calendarWorkouts,\n chartData,\n gpx,\n language,\n loading,\n message,\n messages,\n records,\n router: connectRouter(history),\n sports,\n statistics,\n user,\n users,\n })\n","/* eslint-disable react/jsx-filename-extension */\nimport { createBrowserHistory } from 'history'\nimport React from 'react'\nimport { I18nextProvider } from 'react-i18next'\nimport ReactDOM from 'react-dom'\nimport { routerMiddleware } from 'connected-react-router'\nimport { applyMiddleware, compose, createStore } from 'redux'\nimport thunk from 'redux-thunk'\n\nimport i18n from './i18n'\nimport App from './components/App'\nimport Root from './components/Root'\nimport registerServiceWorker from './registerServiceWorker'\nimport createRootReducer from './reducers'\nimport { loadProfile } from './actions/user'\nimport { historyEnhancer } from './utils/history'\n\nexport const history = historyEnhancer(createBrowserHistory())\n\nhistory.listen(() => {\n window.scrollTo(0, 0)\n})\n\nexport const rootNode = document.getElementById('root')\n\nexport const store = createStore(\n createRootReducer(history),\n window.__STATE__, // Server state\n (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose)(\n applyMiddleware(routerMiddleware(history), thunk)\n )\n)\n\nif (window.localStorage.authToken !== null) {\n store.dispatch(loadProfile())\n}\n\nReactDOM.render(\n \n \n \n \n ,\n rootNode\n)\nregisterServiceWorker()\n"],"sourceRoot":""} \ No newline at end of file diff --git a/fittrackee_client/src/actions/activities.js b/fittrackee_client/src/actions/activities.js deleted file mode 100644 index 98ad2dac..00000000 --- a/fittrackee_client/src/actions/activities.js +++ /dev/null @@ -1,192 +0,0 @@ -import FitTrackeeGenericApi from '../fitTrackeeApi' -import { history } from '../index' -import { formatChartData } from '../utils/activities' -import { setError, setLoading } from './index' -import { loadProfile } from './user' - -export const pushActivities = activities => ({ - type: 'PUSH_ACTIVITIES', - activities, -}) - -export const removeActivity = activityId => ({ - type: 'REMOVE_ACTIVITY', - activityId, -}) - -export const updateCalendar = activities => ({ - type: 'UPDATE_CALENDAR', - activities, -}) - -export const setGpx = gpxContent => ({ - type: 'SET_GPX', - gpxContent, -}) - -export const setChartData = chartData => ({ - type: 'SET_CHART_DATA', - chartData, -}) - -export const addActivity = form => dispatch => - FitTrackeeGenericApi.addDataWithFile('activities', form) - .then(ret => { - if (ret.status === 'created') { - if (ret.data.activities.length === 0) { - dispatch(setError('activities|no correct file.')) - } else if (ret.data.activities.length === 1) { - dispatch(loadProfile()) - history.push(`/activities/${ret.data.activities[0].id}`) - } else { - // ret.data.activities.length > 1 - dispatch(loadProfile()) - history.push('/') - } - } else if (ret.status === 413) { - dispatch( - setError('activities|File size is greater than the allowed size') - ) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - dispatch(setLoading(false)) - }) - .catch(error => { - dispatch(setLoading(false)) - dispatch(setError(`activities|${error}`)) - }) - -export const addActivityWithoutGpx = form => dispatch => - FitTrackeeGenericApi.addData('activities/no_gpx', form) - .then(ret => { - if (ret.status === 'created') { - dispatch(loadProfile()) - history.push(`/activities/${ret.data.activities[0].id}`) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - -export const getActivityGpx = activityId => dispatch => { - if (activityId) { - return FitTrackeeGenericApi.getData(`activities/${activityId}/gpx`) - .then(ret => { - if (ret.status === 'success') { - dispatch(setGpx(ret.data.gpx)) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - } - dispatch(setGpx(null)) -} - -export const getSegmentGpx = (activityId, segmentId) => dispatch => { - if (activityId) { - return FitTrackeeGenericApi.getData( - `activities/${activityId}/gpx/segment/${segmentId}` - ) - .then(ret => { - if (ret.status === 'success') { - dispatch(setGpx(ret.data.gpx)) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - } - dispatch(setGpx(null)) -} - -export const getActivityChartData = activityId => dispatch => { - if (activityId) { - return FitTrackeeGenericApi.getData(`activities/${activityId}/chart_data`) - .then(ret => { - if (ret.status === 'success') { - dispatch(setChartData(formatChartData(ret.data.chart_data))) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - } - dispatch(setChartData(null)) -} - -export const getSegmentChartData = (activityId, segmentId) => dispatch => { - if (activityId) { - return FitTrackeeGenericApi.getData( - `activities/${activityId}/chart_data/segment/${segmentId}` - ) - .then(ret => { - if (ret.status === 'success') { - dispatch(setChartData(formatChartData(ret.data.chart_data))) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - } - dispatch(setChartData(null)) -} - -export const deleteActivity = id => dispatch => - FitTrackeeGenericApi.deleteData('activities', id) - .then(ret => { - if (ret.status === 204) { - Promise.resolve(dispatch(removeActivity(id))) - .then(() => dispatch(loadProfile())) - .then(() => history.push('/')) - } else { - dispatch(setError(`activities|${ret.status}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - -export const editActivity = form => dispatch => - FitTrackeeGenericApi.updateData('activities', form) - .then(ret => { - if (ret.status === 'success') { - dispatch(loadProfile()) - history.push(`/activities/${ret.data.activities[0].id}`) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - dispatch(setLoading(false)) - }) - .catch(error => { - dispatch(setLoading(false)) - dispatch(setError(`activities|${error}`)) - }) - -export const getMoreActivities = params => dispatch => - FitTrackeeGenericApi.getData('activities', params) - .then(ret => { - if (ret.status === 'success') { - if (ret.data.activities.length > 0) { - dispatch(pushActivities(ret.data.activities)) - } - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) - -export const getMonthActivities = (from, to) => dispatch => - FitTrackeeGenericApi.getData('activities', { - from, - to, - order: 'asc', - per_page: 100, - }) - .then(ret => { - if (ret.status === 'success') { - dispatch(updateCalendar(ret.data.activities)) - } else { - dispatch(setError(`activities|${ret.message}`)) - } - }) - .catch(error => dispatch(setError(`activities|${error}`))) diff --git a/fittrackee_client/src/actions/index.js b/fittrackee_client/src/actions/index.js index 1515176a..6536f79a 100644 --- a/fittrackee_client/src/actions/index.js +++ b/fittrackee_client/src/actions/index.js @@ -47,7 +47,7 @@ export const getOrUpdateData = ( canDispatch = true ) => dispatch => { dispatch(setLoading(true)) - if (data && data.id && target !== 'activities' && isNaN(data.id)) { + if (data && data.id && target !== 'workouts' && isNaN(data.id)) { dispatch(setLoading(false)) return dispatch(setError(`${target}|Incorrect id`)) } diff --git a/fittrackee_client/src/actions/workouts.js b/fittrackee_client/src/actions/workouts.js new file mode 100644 index 00000000..34865209 --- /dev/null +++ b/fittrackee_client/src/actions/workouts.js @@ -0,0 +1,192 @@ +import FitTrackeeGenericApi from '../fitTrackeeApi' +import { history } from '../index' +import { formatChartData } from '../utils/workouts' +import { setError, setLoading } from './index' +import { loadProfile } from './user' + +export const pushWorkouts = workouts => ({ + type: 'PUSH_WORKOUTS', + workouts, +}) + +export const removeWorkout = workoutId => ({ + type: 'REMOVE_WORKOUT', + workoutId, +}) + +export const updateCalendar = workouts => ({ + type: 'UPDATE_CALENDAR', + workouts, +}) + +export const setGpx = gpxContent => ({ + type: 'SET_GPX', + gpxContent, +}) + +export const setChartData = chartData => ({ + type: 'SET_CHART_DATA', + chartData, +}) + +export const addWorkout = form => dispatch => + FitTrackeeGenericApi.addDataWithFile('workouts', form) + .then(ret => { + if (ret.status === 'created') { + if (ret.data.workouts.length === 0) { + dispatch(setError('workouts|no correct file.')) + } else if (ret.data.workouts.length === 1) { + dispatch(loadProfile()) + history.push(`/workouts/${ret.data.workouts[0].id}`) + } else { + // ret.data.workouts.length > 1 + dispatch(loadProfile()) + history.push('/') + } + } else if (ret.status === 413) { + dispatch( + setError('workouts|File size is greater than the allowed size') + ) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + dispatch(setLoading(false)) + }) + .catch(error => { + dispatch(setLoading(false)) + dispatch(setError(`workouts|${error}`)) + }) + +export const addWorkoutWithoutGpx = form => dispatch => + FitTrackeeGenericApi.addData('workouts/no_gpx', form) + .then(ret => { + if (ret.status === 'created') { + dispatch(loadProfile()) + history.push(`/workouts/${ret.data.workouts[0].id}`) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + +export const getWorkoutGpx = workoutId => dispatch => { + if (workoutId) { + return FitTrackeeGenericApi.getData(`workouts/${workoutId}/gpx`) + .then(ret => { + if (ret.status === 'success') { + dispatch(setGpx(ret.data.gpx)) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + } + dispatch(setGpx(null)) +} + +export const getSegmentGpx = (workoutId, segmentId) => dispatch => { + if (workoutId) { + return FitTrackeeGenericApi.getData( + `workouts/${workoutId}/gpx/segment/${segmentId}` + ) + .then(ret => { + if (ret.status === 'success') { + dispatch(setGpx(ret.data.gpx)) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + } + dispatch(setGpx(null)) +} + +export const getWorkoutChartData = workoutId => dispatch => { + if (workoutId) { + return FitTrackeeGenericApi.getData(`workouts/${workoutId}/chart_data`) + .then(ret => { + if (ret.status === 'success') { + dispatch(setChartData(formatChartData(ret.data.chart_data))) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + } + dispatch(setChartData(null)) +} + +export const getSegmentChartData = (workoutId, segmentId) => dispatch => { + if (workoutId) { + return FitTrackeeGenericApi.getData( + `workouts/${workoutId}/chart_data/segment/${segmentId}` + ) + .then(ret => { + if (ret.status === 'success') { + dispatch(setChartData(formatChartData(ret.data.chart_data))) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + } + dispatch(setChartData(null)) +} + +export const deleteWorkout = id => dispatch => + FitTrackeeGenericApi.deleteData('workouts', id) + .then(ret => { + if (ret.status === 204) { + Promise.resolve(dispatch(removeWorkout(id))) + .then(() => dispatch(loadProfile())) + .then(() => history.push('/')) + } else { + dispatch(setError(`workouts|${ret.status}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + +export const editWorkout = form => dispatch => + FitTrackeeGenericApi.updateData('workouts', form) + .then(ret => { + if (ret.status === 'success') { + dispatch(loadProfile()) + history.push(`/workouts/${ret.data.workouts[0].id}`) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + dispatch(setLoading(false)) + }) + .catch(error => { + dispatch(setLoading(false)) + dispatch(setError(`workouts|${error}`)) + }) + +export const getMoreWorkouts = params => dispatch => + FitTrackeeGenericApi.getData('workouts', params) + .then(ret => { + if (ret.status === 'success') { + if (ret.data.workouts.length > 0) { + dispatch(pushWorkouts(ret.data.workouts)) + } + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) + +export const getMonthWorkouts = (from, to) => dispatch => + FitTrackeeGenericApi.getData('workouts', { + from, + to, + order: 'asc', + per_page: 100, + }) + .then(ret => { + if (ret.status === 'success') { + dispatch(updateCalendar(ret.data.workouts)) + } else { + dispatch(setError(`workouts|${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`workouts|${error}`))) diff --git a/fittrackee_client/src/components/Activity/ActivityDisplay/ActivityDetails.jsx b/fittrackee_client/src/components/Activity/ActivityDisplay/ActivityDetails.jsx deleted file mode 100644 index 1c0ceb3b..00000000 --- a/fittrackee_client/src/components/Activity/ActivityDisplay/ActivityDetails.jsx +++ /dev/null @@ -1,73 +0,0 @@ -import React from 'react' - -import ActivityWeather from './ActivityWeather' - -export default function ActivityDetails(props) { - const { activity, t } = props - const withPauses = activity.pauses !== '0:00:00' && activity.pauses !== null - return ( -
-

-