1 line
224 KiB
Plaintext
1 line
224 KiB
Plaintext
{"version":3,"sources":["webpack:///./src/components/User/UserAuthForm.vue","webpack:///./src/components/User/UserAuthForm.vue?719c","webpack:///./src/components/User/UserAuthForm.vue?a581","webpack:///./node_modules/core-js/internals/string-pad.js","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue?312e","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkouts.vue?a956","webpack:///./src/components/Dashboard/UserMonthStats.vue?4cf2","webpack:///./src/components/Dashboard/UserCalendar/CalendarCells.vue?de83","webpack:///./src/components/Dashboard/UserRecords/RecordsCard.vue?adca","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkout.vue?4cd6","webpack:///./src/components/Workout/WorkoutCard.vue?b0d4","webpack:///./node_modules/core-js/modules/es.string.pad-start.js","webpack:///./node_modules/core-js/modules/es.object.entries.js","webpack:///./src/components/Dashboard/UserCalendar/index.vue?7c8e","webpack:///./src/components/Dashboard/UserCalendar/CalendarDays.vue?301b","webpack:///./src/components/BikePic.vue?bad3","webpack:///./node_modules/core-js/internals/object-to-array.js","webpack:///./node_modules/date-fns/esm/subYears/index.js","webpack:///./node_modules/date-fns/esm/endOfYear/index.js","webpack:///./node_modules/date-fns/esm/addWeeks/index.js","webpack:///./node_modules/date-fns/esm/subWeeks/index.js","webpack:///./src/utils/statistics.ts","webpack:///./src/components/Statistics/index.vue?27b1","webpack:///./src/views/DashBoard.vue","webpack:///./node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js","webpack:///./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js","webpack:///./node_modules/@babel/runtime/helpers/esm/iterableToArray.js","webpack:///./node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js","webpack:///./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js","webpack:///./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js","webpack:///./src/components/Dashboard/Timeline.vue","webpack:///./src/components/Workout/WorkoutCard.vue","webpack:///./node_modules/date-fns/esm/compareAsc/index.js","webpack:///./node_modules/date-fns/esm/differenceInCalendarMonths/index.js","webpack:///./node_modules/date-fns/esm/endOfDay/index.js","webpack:///./node_modules/date-fns/esm/isLastDayOfMonth/index.js","webpack:///./node_modules/date-fns/esm/differenceInMonths/index.js","webpack:///./node_modules/date-fns/esm/differenceInMilliseconds/index.js","webpack:///./node_modules/date-fns/esm/differenceInSeconds/index.js","webpack:///./node_modules/date-fns/esm/_lib/assign/index.js","webpack:///./node_modules/date-fns/esm/_lib/cloneObject/index.js","webpack:///./node_modules/date-fns/esm/formatDistance/index.js","webpack:///./src/components/Workout/WorkoutCard.vue?b099","webpack:///./src/components/Workout/WorkoutCard.vue?313a","webpack:///./src/components/Dashboard/Timeline.vue?427a","webpack:///./src/components/Dashboard/Timeline.vue?4efd","webpack:///./src/components/Dashboard/UserCalendar/index.vue","webpack:///./src/components/Dashboard/UserCalendar/CalendarCells.vue","webpack:///./node_modules/date-fns/esm/startOfDay/index.js","webpack:///./node_modules/date-fns/esm/isSameDay/index.js","webpack:///./node_modules/date-fns/esm/isSameMonth/index.js","webpack:///./node_modules/date-fns/esm/isToday/index.js","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkouts.vue","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkout.vue","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkout.vue?dbdf","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkout.vue?d46b","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue","webpack:///./src/components/Dashboard/UserCalendar/DonutChart.vue","webpack:///./src/components/Dashboard/UserCalendar/DonutChart.vue?4d49","webpack:///./src/components/Dashboard/UserCalendar/DonutChart.vue?7394","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue?4c41","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue?2788","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkouts.vue?cd5f","webpack:///./src/components/Dashboard/UserCalendar/CalendarWorkouts.vue?fbae","webpack:///./src/components/Dashboard/UserCalendar/CalendarCells.vue?6eda","webpack:///./src/components/Dashboard/UserCalendar/CalendarCells.vue?88a4","webpack:///./src/components/Dashboard/UserCalendar/CalendarDays.vue","webpack:///./src/components/Dashboard/UserCalendar/CalendarDays.vue?a950","webpack:///./src/components/Dashboard/UserCalendar/CalendarDays.vue?50af","webpack:///./src/components/Dashboard/UserCalendar/CalendarHeader.vue","webpack:///./src/components/Dashboard/UserCalendar/CalendarHeader.vue?dc81","webpack:///./src/components/Dashboard/UserCalendar/CalendarHeader.vue?1bf2","webpack:///./src/components/Dashboard/UserCalendar/index.vue?3519","webpack:///./src/components/Dashboard/UserCalendar/index.vue?b135","webpack:///./src/components/Dashboard/UserMonthStats.vue","webpack:///./src/components/Dashboard/UserMonthStats.vue?deb8","webpack:///./src/components/Dashboard/UserMonthStats.vue?2111","webpack:///./src/components/Dashboard/UserRecords/index.vue","webpack:///./src/components/Dashboard/UserRecords/RecordsCard.vue","webpack:///./src/components/Dashboard/UserRecords/RecordsCard.vue?67f3","webpack:///./src/components/Dashboard/UserRecords/RecordsCard.vue?ca60","webpack:///./src/utils/records.ts","webpack:///./src/components/Dashboard/UserRecords/index.vue?995a","webpack:///./src/components/Dashboard/UserRecords/index.vue?5ce7","webpack:///./src/components/Dashboard/UserStatsCards/index.vue","webpack:///./src/components/Dashboard/UserStatsCards/index.vue?5f4d","webpack:///./src/components/Dashboard/UserStatsCards/index.vue?24f5","webpack:///./src/views/DashBoard.vue?aa23","webpack:///./src/views/DashBoard.vue?a17b","webpack:///./src/views/DashBoard.vue?8171","webpack:///./src/components/Dashboard/Timeline.vue?c735","webpack:///./src/components/Common/StatsChart/index.vue?f8fc","webpack:///./src/components/Statistics/StatsSportsMenu.vue?4263","webpack:///./node_modules/core-js/internals/string-pad-webkit-bug.js","webpack:///./node_modules/date-fns/esm/subMonths/index.js","webpack:///./src/views/LoginOrRegister.vue?618a","webpack:///./src/components/Statistics/StatsMenu.vue?a690","webpack:///./src/components/Dashboard/UserRecords/index.vue?5fd1","webpack:///./src/components/User/UserAuthForm.vue?07a9","webpack:///./src/views/LoginOrRegister.vue","webpack:///./src/components/BikePic.vue","webpack:///./src/components/BikePic.vue?f93b","webpack:///./src/views/LoginOrRegister.vue?dd66","webpack:///./src/views/LoginOrRegister.vue?2a8a","webpack:///./src/views/StatisticsView.vue","webpack:///./src/components/Statistics/index.vue","webpack:///./src/components/Statistics/StatsMenu.vue","webpack:///./src/components/Statistics/StatsMenu.vue?3e92","webpack:///./src/components/Statistics/StatsMenu.vue?e2ad","webpack:///./src/components/Statistics/StatsSportsMenu.vue","webpack:///./src/components/Statistics/StatsSportsMenu.vue?793d","webpack:///./src/components/Statistics/StatsSportsMenu.vue?bb1a","webpack:///./src/components/Statistics/index.vue?3134","webpack:///./src/components/Statistics/index.vue?fcc1","webpack:///./src/views/StatisticsView.vue?db9f","webpack:///./src/views/StatisticsView.vue?7475","webpack:///./src/components/Dashboard/UserStatsCards/index.vue?a172","webpack:///./node_modules/core-js/modules/es.symbol.iterator.js","webpack:///./src/views/StatisticsView.vue?dde7","webpack:///./node_modules/core-js/modules/es.symbol.description.js","webpack:///./src/views/NotFoundView.vue","webpack:///./src/views/NotFoundView.vue?efa2","webpack:///./src/views/NotFoundView.vue?d15d","webpack:///./src/components/Dashboard/UserCalendar/CalendarHeader.vue?7fc5","webpack:///./src/components/Common/StatsChart/index.vue","webpack:///./src/components/Common/StatsChart/Chart.vue","webpack:///./src/utils/duration.ts","webpack:///./src/utils/tooltip.ts","webpack:///./src/components/Common/StatsChart/Chart.vue?bf85","webpack:///./src/components/Common/StatsChart/Chart.vue?979a","webpack:///./src/components/Common/StatsChart/index.vue?d5f7","webpack:///./src/components/Common/StatsChart/index.vue?e269","webpack:///./node_modules/core-js/modules/es.array.slice.js"],"names":["id","class","registration_disabled","message","onSubmit","action","disabled","required","formData","username","placeholder","$t","type","email","password","includes","password_conf","buttonText","to","errorMessages","name","props","String","token","default","setup","route","store","useStore","getButtonText","getters","GETTERS","ERROR_MESSAGES","appConfig","APP_CONFIG","value","is_registration_enabled","toUpperCase","actionType","dispatch","ACTIONS","RESET_USER_PASSWORD","commit","MUTATIONS","SET_ERROR_MESSAGES","SEND_PASSWORD_RESET_REQUEST","LOGIN_OR_REGISTER","resetFormData","path","EMPTY_ERROR_MESSAGES","render","__scopeId","toLength","repeat","requireObjectCoercible","ceil","Math","createMethod","IS_END","$this","maxLength","fillString","fillLen","stringFiller","S","stringLength","length","fillStr","undefined","intMaxLength","call","slice","module","exports","start","end","$","$padStart","WEBKIT_BUG","target","proto","forced","padStart","this","arguments","$entries","entries","stat","O","DESCRIPTORS","objectKeys","toIndexedObject","propertyIsEnumerable","f","TO_ENTRIES","it","key","keys","i","result","push","values","subYears","dirtyDate","dirtyAmount","requiredArgs","amount","toInteger","addYears","endOfYear","date","toDate","year","getFullYear","setFullYear","setHours","addWeeks","days","addDays","subWeeks","dateFormats","week","api","chart","month","datasetKeys","params","weekStartingMonday","day","duration","getStatisticsChartDataset","sportLabel","color","label","backgroundColor","data","displayedSports","datasets","nb_workouts","total_distance","total_duration","map","sport","sports","displayedSportsId","apiStats","dayKeys","dateFormat","filter","labels","sportsId","displayedSport","format","datasetKey","dataset","timeFrame","weekStartsOn","startOfYear","startOfWeek","subMonths","startOfMonth","endOfWeek","endOfMonth","chartParams","backward","addMonths","aria-hidden","authUser","isSelected","updateDisplayColumn","user","_arrayLikeToArray","arr","len","arr2","Array","_arrayWithoutHoles","isArray","arrayLikeToArray","_iterableToArray","iter","Symbol","iterator","from","_unsupportedIterableToArray","o","minLen","n","Object","prototype","toString","constructor","test","_nonIterableSpread","TypeError","_toConsumableArray","arrayWithoutHoles","iterableToArray","unsupportedIterableToArray","nonIterableSpread","workouts","initWorkoutsCount","index","workout","moreWorkoutsExist","loadMoreWorkouts","userPictureUrl","alt","src","title","formatDistance","Date","workout_date","with_gpx","sport-label","moving","distance","compareAsc","dirtyDateLeft","dirtyDateRight","dateLeft","dateRight","diff","getTime","differenceInCalendarMonths","yearDiff","monthDiff","getMonth","endOfDay","isLastDayOfMonth","differenceInMonths","sign","difference","abs","getDate","setDate","setMonth","isLastMonthNotFull","Number","differenceInMilliseconds","differenceInSeconds","floor","dirtyObject","property","hasOwnProperty","cloneObject","MINUTES_IN_DAY","MINUTES_IN_ALMOST_TWO_DAYS","MINUTES_IN_MONTH","MINUTES_IN_TWO_MONTHS","dirtyBaseDate","options","locale","RangeError","comparison","isNaN","localizeOptions","addSuffix","Boolean","months","seconds","offsetInSeconds","getTimezoneOffsetInMilliseconds","minutes","round","includeSeconds","hours","nearestMonth","monthsSinceStartOfYear","years","components","StaticMap","picture","now","LOCALE","getDateWithTZ","NoWorkouts","WorkoutCard","page","per_page","loadWorkouts","USER_WORKOUTS","previous_workout","GET_USER_WORKOUTS","GET_MORE_USER_WORKOUTS","locale-options","displayNextMonth","displayPreviousMonth","start-date","calendarDates","currentDay","end-date","timezone","calendarWorkouts","weekm","rows","row","filterWorkouts","startOfDay","isSameDay","dateLeftStartOfDay","dateRightStartOfDay","isSameMonth","isToday","displayedWorkoutCount","getSportLabel","chartDatasets","colors","records","t","togglePane","isHidden","height","width","viewBox","cx","cy","r","radius","fill","stroke","stroke-dashoffset","stroke-dasharray","circumference","stroke-width","stroke-opacity","transform","returnCircleTransformValue","percentage","angleOffset","PI","calculateStrokeDashOffset","rotation","CalendarWorkout","DonutChart","event","stopPropagation","CalendarWorkoutsChart","CalendarWorkouts","endDate","startDate","getDays","isWeekEnd","reverse","localeOptions","emit","emits","CalendarCells","CalendarDays","CalendarHeader","getCalendarWorkouts","CALENDAR_WORKOUTS","apiParams","order","GET_CALENDAR_WORKOUTS","content","chart-params","displayed-sport-ids","selectedSportIds","hide-chart-if-no-data","StatChart","recordsBySport","sort","sportTranslatedLabel","record","record_type","tz","Error","workout_id","getRecordsBySports","translatedSports","reduce","sportList","find","s","sport_id","translatedLabel","RecordsCard","icon","text","toFixed","nb_sports","StatCard","get_duration","match","split","Timeline","UserCalendar","UserMonthStats","UserRecords","UserStatsCards","AUTH_USER_PROFILE","SPORTS","EMPTY_WORKOUTS","userAgent","BikePic","LoginOrRegisterForm","updateTimeFrame","handleOnClickArrows","fullStats","selected-sport-ids","user-sports","updateSelectedSportIds","timeFrames","frame","checked","selectedTimeFrame","onUpdateTimeFrame","style","sportColors","userSports","sportId","SportsMenu","StatsMenu","getChartParams","getSports","newSports","Statistics","sports_list","defineWellKnownSymbol","global","has","isObject","defineProperty","copyConstructorProperties","NativeSymbol","description","EmptyStringDescriptionStore","SymbolWrapper","symbolPrototype","symbolToString","native","regexp","configurable","get","symbol","valueOf","string","desc","replace","NotFound","hideChartIfNoData","emptyStats","displayedData","updateDisplayData","displayedSportIds","formatDuration","totalSeconds","formatWithUnits","BarChart","getNumber","getSum","total","chartData","JSON","parse","stringify","responsive","maintainAspectRatio","animation","layout","padding","top","scales","x","stacked","grid","drawOnChartArea","y","ticks","maxTicksLimit","callback","afterFit","scale","plugins","datalabels","anchor","align","context","chartArea","display","formatter","d","dataIndex","datasetIndex","legend","tooltip","interaction","intersect","mode","tooltipItem","formattedValue","callbacks","parsed","footer","tooltipItems","sum","barChartProps","Chart","statistics","USER_STATS","formattedStats","getStatistics","GET_USER_STATS","filterType","getApiParams","time","newParams","toAbsoluteIndex","createProperty","wellKnownSymbol","arrayMethodHasSpeciesSupport","HAS_SPECIES_SUPPORT","SPECIES","nativeSlice","max","Constructor","k","fin"],"mappings":"mOACOA,GAAG,kB,GACDA,GAAG,a,GAYGC,MAAM,c,sPAbnB,yBA0EM,MA1EN,EA0EM,CAzEJ,yBAwEM,MAxEN,EAwEM,CAvEJ,yBAsEM,OArEJA,MAAK,CAAC,WAAU,C,SACc,2B,CAMtB,EAAAC,uB,yBAFR,yBAGE,G,MAFAC,QAAQ,4B,uCAGV,yBAqDO,QArDA,SAAM,2DAAU,EAAAC,SAAS,EAAAC,UAAM,e,CACpC,yBAgDM,MAhDN,EAgDM,CA9CU,aAAN,EAAAA,O,sDADR,yBAOE,S,MALAL,GAAG,WACFM,SAAU,EAAAJ,sBACXK,SAAA,G,qDACS,EAAAC,SAASC,SAAQ,IACzBC,YAAa,EAAAC,GAAE,kB,sDADP,EAAAH,SAASC,Y,uCAIN,UAAN,EAAAJ,O,sDADR,yBAYE,S,MAVAL,GAAG,QACFM,SAAU,EAAAJ,sBACXK,SAAA,GACAK,KAAK,Q,qDACI,EAAAJ,SAASK,MAAK,IACtBH,YAAoC,kBAAN,SAA+C,KAAE,oBAAyC,KAAE,e,sDADlH,EAAAF,SAASK,S,uCAQN,kBAAN,EAAAR,O,sDADR,yBAYE,S,MAVAL,GAAG,WACFM,SAAU,EAAAJ,sBACXK,SAAA,GACAK,KAAK,W,qDACI,EAAAJ,SAASM,SAAQ,IACzBJ,YAAoC,UAAN,SAAuC,KAAE,uBAA4C,KAAE,kB,sDAD7G,EAAAF,SAASM,Y,4DAQUC,SAAS,EAAAV,Q,sDADvC,yBAYE,S,MAVAL,GAAG,mBACFM,SAAU,EAAAJ,sBACXU,KAAK,WACLL,SAAA,G,qDACS,EAAAC,SAASQ,cAAa,IAC9BN,YAAoC,UAAN,SAAuC,KAAE,oCAAyD,KAAE,0B,sDAD1H,EAAAF,SAASQ,iB,yCAQtB,yBAES,UAFDJ,KAAK,SAAUN,SAAU,EAAAJ,uB,6BAC5B,EAAAS,GAAG,EAAAM,aAAU,iB,IAGH,UAAN,EAAAZ,Q,yBAAX,yBAIM,SAHJ,yBAEc,GAFDJ,MAAM,qBAAqBiB,GAAG,2B,YACzC,iBAAmC,C,0DAAhC,EAAAP,GAAE,mC,gDAGoC,EAAAQ,e,yBAA7C,yBAA8D,G,MAA/ChB,QAAS,EAAAgB,e,mIC/Df,+BAAgB,CAC7BC,KAAM,eACNC,MAAO,CACLhB,OAAQ,CACNO,KAAMU,OACNf,UAAU,GAEZgB,MAAO,CACLX,KAAMU,OACNE,QAAS,KAGbC,MAZ6B,SAYvBJ,GACJ,IAAMb,EAAmC,sBAAS,CAChDC,SAAU,GACVI,MAAO,GACPC,SAAU,GACVE,cAAe,KAEXU,EAAQ,iBACRC,EAAQ,OAAAC,EAAA,QAERX,EAAkC,uBAAS,kBAC/CY,EAAcR,EAAMhB,WAEhBc,EAAuD,uBAC3D,kBAAMQ,EAAMG,QAAQ,OAAWC,QAAQC,mBAEnCC,EAAqC,uBACzC,kBAAMN,EAAMG,QAAQ,OAAWC,QAAQG,eAEnChC,EAA8C,uBAClD,iBACmB,aAAjBmB,EAAMhB,SACL4B,EAAUE,MAAMC,2BAGrB,SAASP,EAAcxB,GACrB,OAAQA,GACN,IAAK,gBACL,IAAK,QACH,MAAO,iBACT,QACE,wBAAkBgB,EAAMhB,OAAOgC,gBAGrC,SAASjC,EAASkC,GAChB,OAAQA,GACN,IAAK,QACH,OAAKjB,EAAME,MAMJI,EAAMY,SAAS,OAAWC,QAAQC,oBAAqB,CAC5D3B,SAAUN,EAASM,SACnBE,cAAeR,EAASQ,cACxBO,MAAOF,EAAME,QARNI,EAAMe,OACX,OAAWC,UAAUC,mBACrB,sBAQN,IAAK,gBACH,OAAOjB,EAAMY,SACX,OAAWC,QAAQK,4BACnB,CACEhC,MAAOL,EAASK,QAGtB,QACEc,EAAMY,SAAS,OAAWC,QAAQM,kBAAmB,CACnDR,aACA9B,cAIR,SAASuC,IACPvC,EAASC,SAAW,GACpBD,EAASK,MAAQ,GACjBL,EAASM,SAAW,GACpBN,EAASQ,cAAgB,GAS3B,OAPA,oBACE,kBAAMU,EAAMsB,OADT,wCAEH,8FACErB,EAAMe,OAAO,OAAWC,UAAUM,sBAClCF,IAFF,4CAKK,CACLd,YACAhB,aACAE,gBACAX,WACAN,wBACAE,e,UCjGR,EAAO8C,OAASA,EAChB,EAAOC,UAAY,kBAEJ,U,gDCPf,IAAIC,EAAW,EAAQ,QACnBC,EAAS,EAAQ,QACjBC,EAAyB,EAAQ,QAEjCC,EAAOC,KAAKD,KAGZE,EAAe,SAAUC,GAC3B,OAAO,SAAUC,EAAOC,EAAWC,GACjC,IAIIC,EAASC,EAJTC,EAAI1C,OAAOgC,EAAuBK,IAClCM,EAAeD,EAAEE,OACjBC,OAAyBC,IAAfP,EAA2B,IAAMvC,OAAOuC,GAClDQ,EAAejB,EAASQ,GAE5B,OAAIS,GAAgBJ,GAA2B,IAAXE,EAAsBH,GAC1DF,EAAUO,EAAeJ,EACzBF,EAAeV,EAAOiB,KAAKH,EAASZ,EAAKO,EAAUK,EAAQD,SACvDH,EAAaG,OAASJ,IAASC,EAAeA,EAAaQ,MAAM,EAAGT,IACjEJ,EAASM,EAAID,EAAeA,EAAeC,KAItDQ,EAAOC,QAAU,CAGfC,MAAOjB,GAAa,GAGpBkB,IAAKlB,GAAa,K,oCC7BpB,W,oCCAA,W,oCCAA,W,oCCAA,W,oCCAA,W,oCCAA,W,+GCAA,W,oCCCA,IAAImB,EAAI,EAAQ,QACZC,EAAY,EAAQ,QAA2BH,MAC/CI,EAAa,EAAQ,QAIzBF,EAAE,CAAEG,OAAQ,SAAUC,OAAO,EAAMC,OAAQH,GAAc,CACvDI,SAAU,SAAkBtB,GAC1B,OAAOiB,EAAUM,KAAMvB,EAAWwB,UAAUlB,OAAS,EAAIkB,UAAU,QAAKhB,O,uBCT5E,IAAIQ,EAAI,EAAQ,QACZS,EAAW,EAAQ,QAAgCC,QAIvDV,EAAE,CAAEG,OAAQ,SAAUQ,MAAM,GAAQ,CAClCD,QAAS,SAAiBE,GACxB,OAAOH,EAASG,O,2DCPpB,W,oCCAA,W,sFCAA,W,uBCAA,IAAIC,EAAc,EAAQ,QACtBC,EAAa,EAAQ,QACrBC,EAAkB,EAAQ,QAC1BC,EAAuB,EAAQ,QAA8CC,EAG7EpC,EAAe,SAAUqC,GAC3B,OAAO,SAAUC,GACf,IAKIC,EALAR,EAAIG,EAAgBI,GACpBE,EAAOP,EAAWF,GAClBtB,EAAS+B,EAAK/B,OACdgC,EAAI,EACJC,EAAS,GAEb,MAAOjC,EAASgC,EACdF,EAAMC,EAAKC,KACNT,IAAeG,EAAqBtB,KAAKkB,EAAGQ,IAC/CG,EAAOC,KAAKN,EAAa,CAACE,EAAKR,EAAEQ,IAAQR,EAAEQ,IAG/C,OAAOG,IAIX3B,EAAOC,QAAU,CAGfa,QAAS7B,GAAa,GAGtB4C,OAAQ5C,GAAa,K,gPCJR,SAAS6C,EAASC,EAAWC,GAC1C,OAAAC,EAAA,MAAa,EAAGrB,WAChB,IAAIsB,EAAS,OAAAC,EAAA,MAAUH,GACvB,OAAO,OAAAI,EAAA,MAASL,GAAYG,G,oDCJf,SAASG,EAAUN,GAChC,OAAAE,EAAA,MAAa,EAAGrB,WAChB,IAAI0B,EAAO,OAAAC,EAAA,MAAOR,GACdS,EAAOF,EAAKG,cAGhB,OAFAH,EAAKI,YAAYF,EAAO,EAAG,EAAG,GAC9BF,EAAKK,SAAS,GAAI,GAAI,GAAI,KACnBL,E,wCCLM,SAASM,EAASb,EAAWC,GAC1C,OAAAC,EAAA,MAAa,EAAGrB,WAChB,IAAIsB,EAAS,OAAAC,EAAA,MAAUH,GACnBa,EAAgB,EAATX,EACX,OAAO,OAAAY,EAAA,MAAQf,EAAWc,GCJb,SAASE,EAAShB,EAAWC,GAC1C,OAAAC,EAAA,MAAa,EAAGrB,WAChB,IAAIsB,EAAS,OAAAC,EAAA,MAAUH,GACvB,OAAOY,EAASb,GAAYG,G,wCCDxBc,EAAsD,CAC1DC,KAAM,CACJC,IAAK,aACLC,MAAO,cAETC,MAAO,CACLF,IAAK,UACLC,MAAO,WAETX,KAAM,CACJU,IAAK,OACLC,MAAO,SAIEE,EAAwC,CACnD,cACA,iBACA,kBAGW,EAAc,SACzBC,EACAC,GAGA,IADA,IAAMV,EAAO,GAEPW,EAAM,eAAaF,EAAOG,SAAUH,EAAOpD,MAAOqD,GACtDC,GAAOF,EAAOnD,IACdqD,EAAM,eAAcF,EAAOG,SAAUD,GAErCX,EAAKjB,KAAK4B,GAEZ,OAAOX,GAGHa,EAA4B,SAChCC,EACAC,GAEA,MAAO,CACLC,MAAOF,EACPG,gBAAiB,CAACF,GAClBG,KAAM,KAIG,EAAc,SAACC,GAC1B,IAAMC,EAAgC,CACpCC,YAAa,GACbC,eAAgB,GAChBC,eAAgB,IAQlB,OANAJ,EAAgBK,KAAI,SAACC,GACnB,IAAMV,EAAQ,OAAYU,EAAMT,OAChCI,EAASC,YAAYtC,KAAK8B,EAA0BY,EAAMT,MAAOD,IACjEK,EAASE,eAAevC,KAAK8B,EAA0BY,EAAMT,MAAOD,IACpEK,EAASG,eAAexC,KAAK8B,EAA0BY,EAAMT,MAAOD,OAE/DK,GAGI,EAAc,SACzBX,EACAC,EACAgB,EACAC,EACAC,GAEA,IAAMC,EAAU,EAAYpB,EAAQC,GAC9BoB,EAAa3B,EAAYM,EAAOG,UAChCO,EAAkBO,EAAOK,QAAO,SAACN,GAAD,OACpCE,EAAkBjI,SAAS+H,EAAM9I,OAE7BqJ,EAAmB,GACnBZ,EAAW,EAAYD,GACvBc,EAAmC,GAqBzC,OApBAd,EAAgBK,KACd,SAACU,GAAD,OAAqBD,EAASC,EAAelB,OAASkB,EAAevJ,MAGvEkJ,EAAQL,KAAI,SAAC7C,GACX,IAAMc,EAAe,OAAA0C,EAAA,MAAOxD,EAAKmD,EAAWzB,KACtCW,EAAgB,OAAAmB,EAAA,MAAOxD,EAAKmD,EAAWxB,OAC7C0B,EAAOjD,KAAKiC,GACZR,EAAYgB,KAAI,SAACY,GACfhB,EAASgB,GAAYZ,KAAI,SAACa,GACxBA,EAAQnB,KAAKnC,KACX6C,IAAa,IACXnC,KAAQmC,GACRK,EAASI,EAAQrB,SAAUY,EAASnC,GAClCmC,EAASnC,GAAMwC,EAASI,EAAQrB,QAAQoB,GACxC,YAKL,CACLJ,SACAZ,aAIS,EAAqB,SAChC3B,EACA6C,EACA5B,GAEA,IAAM6B,EAAe7B,EAAqB,EAAI,EACxCrD,EACU,SAAdiF,EACI,OAAAE,EAAA,MAAYvD,EAASQ,EAAM,IACb,SAAd6C,EACA,OAAAG,EAAA,MAAY,OAAAC,EAAA,MAAUjD,EAAM,GAAI,CAAE8C,iBAClC,OAAAI,EAAA,MAAa,OAAAD,EAAA,MAAUjD,EAAM,KAC7BnC,EACU,SAAdgF,EACI9C,EAAUC,GACI,SAAd6C,EACA,OAAAM,EAAA,MAAUnD,EAAM,CAAE8C,iBAClB,OAAAM,EAAA,MAAWpD,GACjB,MAAO,CACLmB,SAAU0B,EACVhF,MACAD,UAIS,EAAoB,SAC/ByF,EACAC,EACArC,GAEA,IAAQE,EAAyBkC,EAAzBlC,SAAUvD,EAAeyF,EAAfzF,MAAOC,EAAQwF,EAARxF,IACnBiF,EAAe7B,EAAqB,EAAI,EAC9C,MAAO,CACLE,WACAtD,IACe,SAAbsD,EACIpB,EAAUuD,EAAW9D,EAAS3B,EAAK,GAAK,OAAAiC,EAAA,MAASjC,EAAK,IACzC,SAAbsD,EACA,OAAAgC,EAAA,MAAUG,EAAW7C,EAAS5C,EAAK,GAAKyC,EAASzC,EAAK,GAAI,CACxDiF,iBAEF,OAAAM,EAAA,MAAWE,EAAW,OAAAL,EAAA,MAAUpF,EAAK,GAAK,OAAA0F,EAAA,MAAU1F,EAAK,IAC/DD,MACe,SAAbuD,EACI,OAAA4B,EAAA,MAAYO,EAAW9D,EAAS5B,EAAO,GAAK,OAAAkC,EAAA,MAASlC,EAAO,IAC/C,SAAbuD,EACA,OAAA6B,EAAA,MAAYM,EAAW7C,EAAS7C,EAAO,GAAK0C,EAAS1C,EAAO,GAAI,CAC9DkF,iBAEF,OAAAI,EAAA,MAAaI,EAAW,OAAAL,EAAA,MAAUrF,EAAO,GAAK,OAAA2F,EAAA,MAAU3F,EAAO,O,oCCpLzE,W,kKCCO1E,GAAG,a,GACDC,MAAM,yB,GACJA,MAAM,O,EAMP,yBAAgD,KAA7CA,MAAM,kBAAkBqK,cAAY,Q,WAOvC,yBAA+C,KAA5CrK,MAAM,iBAAiBqK,cAAY,Q,WAOtC,yBAA4C,KAAzCrK,MAAM,cAAcqK,cAAY,Q,WAOnC,yBAA6C,KAA1CrK,MAAM,eAAeqK,cAAY,Q,YAIrCrK,MAAM,a,GAGNA,MAAM,iC,GACJA,MAAM,0C,GAYNA,MAAM,2C,EAab,yBAAmB,OAAdD,GAAG,UAAQ,S,SAENC,MAAM,e,6VAhEQ,EAAAsK,SAAS9J,UAAY,EAAAsI,OAAO7E,OAAM,G,yBAA5D,yBA+DM,MA/DN,EA+DM,CA9DJ,yBA+BM,MA/BN,EA+BM,CA9BJ,yBA6BM,MA7BN,EA6BM,CA5BJ,yBAMM,OALJjE,MAAK,CAAC,mBAAkB,eACW,UAAV,EAAAuK,aACxB,QAAK,+BAAE,EAAAC,oBAAmB,Y,CAE3B,G,GAEF,yBAMM,OALJxK,MAAK,CAAC,mBAAkB,eACW,aAAV,EAAAuK,aACxB,QAAK,+BAAE,EAAAC,oBAAmB,e,CAE3B,G,GAEF,yBAMM,OALJxK,MAAK,CAAC,mBAAkB,eACW,aAAV,EAAAuK,aACxB,QAAK,+BAAE,EAAAC,oBAAmB,e,CAE3B,G,GAEF,yBAMM,OALJxK,MAAK,CAAC,mBAAkB,eACW,YAAV,EAAAuK,aACxB,QAAK,+BAAE,EAAAC,oBAAmB,c,CAE3B,G,OAIN,yBAEM,MAFN,EAEM,CADJ,yBAAmC,GAAlBC,KAAM,EAAAH,UAAQ,mBAEjC,yBAyBM,MAzBN,EAyBM,CAxBJ,yBAWM,MAXN,EAWM,CAVJ,yBAIE,GAHCxB,OAAQ,EAAAA,OACR2B,KAAM,EAAAH,SACNtK,MAAK,eAA6B,UAAV,EAAAuK,c,kCAE3B,yBAIE,GAHCzB,OAAQ,EAAAA,OACR2B,KAAM,EAAAH,SACNtK,MAAK,eAA6B,YAAV,EAAAuK,c,oCAG7B,yBAWM,MAXN,EAWM,CAVJ,yBAIE,GAHCzB,OAAQ,EAAAA,OACR2B,KAAM,EAAAH,SACNtK,MAAK,eAA6B,aAAV,EAAAuK,c,kCAE3B,yBAIE,GAHCzB,OAAQ,EAAAA,OACR2B,KAAM,EAAAH,SACNtK,MAAK,eAA6B,aAAV,EAAAuK,c,sCAI/B,M,yBAEF,yBAEM,MAFN,EAEM,CADJ,yBAAU,SClEC,SAASG,EAAkBC,EAAKC,IAClC,MAAPA,GAAeA,EAAMD,EAAI1G,UAAQ2G,EAAMD,EAAI1G,QAE/C,IAAK,IAAIgC,EAAI,EAAG4E,EAAO,IAAIC,MAAMF,GAAM3E,EAAI2E,EAAK3E,IAC9C4E,EAAK5E,GAAK0E,EAAI1E,GAGhB,OAAO4E,ECNM,SAASE,EAAmBJ,GACzC,GAAIG,MAAME,QAAQL,GAAM,OAAOM,EAAiBN,G,sECFnC,SAASO,EAAiBC,GACvC,GAAsB,qBAAXC,QAAmD,MAAzBD,EAAKC,OAAOC,WAA2C,MAAtBF,EAAK,cAAuB,OAAOL,MAAMQ,KAAKH,G,oBCAvG,SAASI,EAA4BC,EAAGC,GACrD,GAAKD,EAAL,CACA,GAAiB,kBAANA,EAAgB,OAAOP,EAAiBO,EAAGC,GACtD,IAAIC,EAAIC,OAAOC,UAAUC,SAASxH,KAAKmH,GAAGlH,MAAM,GAAI,GAEpD,MADU,WAANoH,GAAkBF,EAAEM,cAAaJ,EAAIF,EAAEM,YAAY3K,MAC7C,QAANuK,GAAqB,QAANA,EAAoBZ,MAAMQ,KAAKE,GACxC,cAANE,GAAqB,2CAA2CK,KAAKL,GAAWT,EAAiBO,EAAGC,QAAxG,GCPa,SAASO,IACtB,MAAM,IAAIC,UAAU,wICGP,SAASC,EAAmBvB,GACzC,OAAOwB,EAAkBxB,IAAQyB,EAAgBzB,IAAQ0B,EAA2B1B,IAAQ2B,I,+GCJvFvM,GAAG,Y,GACDC,MAAM,iB,6BAqBqBA,MAAM,iB,0LAtBxC,yBA4BM,MA5BN,EA4BM,CA3BJ,yBAAqE,MAArE,EAAqE,6BAAvC,EAAAU,GAAE,gCACrB,EAAA+J,KAAKhC,YAAW,GAAuB,IAAf,EAAA8D,SAAStI,Q,yBAA5C,yBAMM,U,2BALJ,yBAIE,6CAHoB6G,MAAM,EAAA0B,mBAAmBxG,SAAI,SAA1CyG,G,gCADT,yBAIE,GAFChC,KAAM,EAAAA,KACN1E,IAAK0G,G,uDAGV,yBAkBM,U,2BAjBJ,yBAUE,2CATkB,EAAAF,UAAQ,SAAnBG,G,gCADT,yBAUE,GARCA,QAASA,EACT7D,MAAkB,WAAS,OAAM,EAAmB,SAAO,QAAM,SAAE,GAAF,OAAQ,EAAE,KAAO,EAAQ,YAAQ,G,KAKlG4B,KAAM,EAAAA,KACN1E,IAAK2G,EAAQ3M,I,4CAEiB,IAAf,EAAAwM,SAAStI,Q,yBAA3B,yBAA2C,Y,uCAChC,EAAA0I,mB,yBAAX,yBAIM,MAJN,EAIM,CAHJ,yBAES,UAFA,QAAK,8BAAE,EAAAC,kBAAA,EAAAA,iBAAA,sB,6BACX,EAAAlM,GAAE,qC,gJCxBRV,MAAM,oB,GACJA,MAAM,O,GACJA,MAAM,qB,GACJA,MAAM,gB,SAOGA,MAAM,c,EAChB,yBAAoD,KAAjDA,MAAM,sBAAsBqK,cAAY,Q,kBAElBrK,MAAM,qB,mBAoCrBA,MAAM,U,EAelB,yBAA8C,KAA3CA,MAAM,gBAAgBqK,cAAY,Q,qBAIrC,yBAA2C,KAAxCrK,MAAM,aAAaqK,cAAY,Q,2MApE1C,yBAyEM,MAzEN,EAyEM,CAxEJ,yBAuEM,MAvEN,EAuEM,CAtEJ,yBAgCM,MAhCN,EAgCM,CA/BJ,yBAaM,MAbN,EAaM,CAVkB,KAAd,EAAAwC,gB,yBAFR,yBAKE,O,MAJA7M,MAAM,cAEL8M,IAAK,EAAApM,GAAE,qBACPqM,IAAK,EAAAF,gB,iDAER,yBAEM,MAFN,EAEM,CADJ,KAEU,EAAApC,KAAKjK,U,yBAAjB,yBAEO,OAFP,EAEO,6BADF,EAAAiK,KAAKjK,UAAQ,I,yCAKZ,EAAAkM,SAAW,EAAAjC,M,yBAFnB,yBAgBM,O,MAfJzK,MAAM,eAELgN,MAAoB,SAAsB,gBAAc,UAAQ,aAAc,OAAK,U,kDAQlF,EAAAC,eAAc,IAAKC,KAAK,EAAAR,QAAQS,cAAY,IAAOD,KAAI,C,oBAAmD,Y,uDAOhH,yBAkBM,OAjBJlN,MAAK,CAAC,cAAa,cACK,EAAA0M,UACvB,QAAK,+BAAa,UAAsB,UAAQ,KAAI,C,iCAAyE,UAAQ,M,SAS3H,EAAAA,S,yBAAX,yBAKM,SAJa,EAAAA,QAAQU,U,yBAAzB,yBAAwD,G,MAApBV,QAAS,EAAAA,S,+CAC7C,yBAEM,MAFN,EAEM,6BADD,EAAAhM,GAAE,2B,2CAIX,yBAiBM,OAhBJV,MAAM,eACL,QAAK,+BAAa,UAAQ,KAAI,kCAAyC,UAAQ,S,CAIhF,yBAEM,YADc,EAAA6I,O,yBAAlB,yBAAsD,G,MAA5BwE,cAAa,EAAAxE,MAAMT,O,kEAE/C,yBAGM,YAFJ,EACY,EAAAsE,S,yBAAZ,yBAAgD,sCAAxB,EAAAA,QAAQY,QAAM,I,yCAExC,yBAGM,YAFJ,EACY,EAAAZ,S,yBAAZ,yBAAqD,sCAA7B,EAAAA,QAAQa,UAAW,MAAG,I,kGC/BzC,SAASC,EAAWC,EAAeC,GAChD,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAAIwI,EAAW,OAAA7G,EAAA,MAAO2G,GAClBG,EAAY,OAAA9G,EAAA,MAAO4G,GACnBG,EAAOF,EAASG,UAAYF,EAAUE,UAE1C,OAAID,EAAO,GACD,EACCA,EAAO,EACT,EAEAA,ECtBI,SAASE,EAA2BN,EAAeC,GAChE,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAAIwI,EAAW,OAAA7G,EAAA,MAAO2G,GAClBG,EAAY,OAAA9G,EAAA,MAAO4G,GACnBM,EAAWL,EAAS3G,cAAgB4G,EAAU5G,cAC9CiH,EAAYN,EAASO,WAAaN,EAAUM,WAChD,OAAkB,GAAXF,EAAgBC,ECTV,SAASE,EAAS7H,GAC/B,OAAAE,EAAA,MAAa,EAAGrB,WAChB,IAAI0B,EAAO,OAAAC,EAAA,MAAOR,GAElB,OADAO,EAAKK,SAAS,GAAI,GAAI,GAAI,KACnBL,E,gBCHM,SAASuH,GAAiB9H,GACvC,OAAAE,EAAA,MAAa,EAAGrB,WAChB,IAAI0B,EAAO,OAAAC,EAAA,MAAOR,GAClB,OAAO6H,EAAStH,GAAMiH,YAAc,OAAA7D,EAAA,MAAWpD,GAAMiH,UCDxC,SAASO,GAAmBZ,EAAeC,GACxD,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAIIe,EAJAyH,EAAW,OAAA7G,EAAA,MAAO2G,GAClBG,EAAY,OAAA9G,EAAA,MAAO4G,GACnBY,EAAOd,EAAWG,EAAUC,GAC5BW,EAAahL,KAAKiL,IAAIT,EAA2BJ,EAAUC,IAG/D,GAAIW,EAAa,EACfrI,EAAS,MACJ,CACuB,IAAxByH,EAASO,YAAoBP,EAASc,UAAY,IAGpDd,EAASe,QAAQ,IAGnBf,EAASgB,SAAShB,EAASO,WAAaI,EAAOC,GAG/C,IAAIK,EAAqBpB,EAAWG,EAAUC,MAAgBU,EAE1DF,GAAiB,OAAAtH,EAAA,MAAO2G,KAAkC,IAAfc,GAA6D,IAAzCf,EAAWC,EAAeG,KAC3FgB,GAAqB,GAGvB1I,EAASoI,GAAQC,EAAaM,OAAOD,IAIvC,OAAkB,IAAX1I,EAAe,EAAIA,EC7Bb,SAAS4I,GAAyBrB,EAAeC,GAC9D,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAAIwI,EAAW,OAAA7G,EAAA,MAAO2G,GAClBG,EAAY,OAAA9G,EAAA,MAAO4G,GACvB,OAAOC,EAASG,UAAYF,EAAUE,UCJzB,SAASiB,GAAoBtB,EAAeC,GACzD,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAAI0I,EAAOiB,GAAyBrB,EAAeC,GAAkB,IACrE,OAAOG,EAAO,EAAItK,KAAKyL,MAAMnB,GAAQtK,KAAKD,KAAKuK,G,iBChClC,SAAS,GAAO/I,EAAQmK,GACrC,GAAc,MAAVnK,EACF,MAAM,IAAImH,UAAU,iEAKtB,IAAK,IAAIiD,KAFTD,EAAcA,GAAe,GAERA,EACftD,OAAOC,UAAUuD,eAAe9K,KAAK4K,EAAaC,KACpDpK,EAAOoK,GAAYD,EAAYC,IAInC,OAAOpK,ECZM,SAASsK,GAAYH,GAClC,OAAO,GAAO,GAAIA,G,iBCMhBI,GAAiB,KACjBC,GAA6B,KAC7BC,GAAmB,MACnBC,GAAwB,MA8Gb,SAASvC,GAAe3G,EAAWmJ,GAChD,IAAIC,EAAUvK,UAAUlB,OAAS,QAAsBE,IAAjBgB,UAAU,GAAmBA,UAAU,GAAK,GAClF,OAAAqB,EAAA,MAAa,EAAGrB,WAChB,IAAIwK,EAASD,EAAQC,QAAU,QAE/B,IAAKA,EAAO1C,eACV,MAAM,IAAI2C,WAAW,+CAGvB,IAAIC,EAAarC,EAAWlH,EAAWmJ,GAEvC,GAAIK,MAAMD,GACR,MAAM,IAAID,WAAW,sBAGvB,IAGIjC,EACAC,EAJAmC,EAAkBX,GAAYM,GAClCK,EAAgBC,UAAYC,QAAQP,EAAQM,WAC5CD,EAAgBF,WAAaA,EAIzBA,EAAa,GACflC,EAAW,OAAA7G,EAAA,MAAO2I,GAClB7B,EAAY,OAAA9G,EAAA,MAAOR,KAEnBqH,EAAW,OAAA7G,EAAA,MAAOR,GAClBsH,EAAY,OAAA9G,EAAA,MAAO2I,IAGrB,IAGIS,EAHAC,EAAUpB,GAAoBnB,EAAWD,GACzCyC,GAAmB,OAAAC,GAAA,MAAgCzC,GAAa,OAAAyC,GAAA,MAAgC1C,IAAa,IAC7G2C,EAAU/M,KAAKgN,OAAOJ,EAAUC,GAAmB,IAGvD,GAAIE,EAAU,EACZ,OAAIZ,EAAQc,eACNL,EAAU,EACLR,EAAO1C,eAAe,mBAAoB,EAAG8C,GAC3CI,EAAU,GACZR,EAAO1C,eAAe,mBAAoB,GAAI8C,GAC5CI,EAAU,GACZR,EAAO1C,eAAe,mBAAoB,GAAI8C,GAC5CI,EAAU,GACZR,EAAO1C,eAAe,cAAe,KAAM8C,GACzCI,EAAU,GACZR,EAAO1C,eAAe,mBAAoB,EAAG8C,GAE7CJ,EAAO1C,eAAe,WAAY,EAAG8C,GAG9B,IAAZO,EACKX,EAAO1C,eAAe,mBAAoB,EAAG8C,GAE7CJ,EAAO1C,eAAe,WAAYqD,EAASP,GAIjD,GAAIO,EAAU,GACnB,OAAOX,EAAO1C,eAAe,WAAYqD,EAASP,GAC7C,GAAIO,EAAU,GACnB,OAAOX,EAAO1C,eAAe,cAAe,EAAG8C,GAC1C,GAAIO,EAAUjB,GAAgB,CACnC,IAAIoB,EAAQlN,KAAKgN,MAAMD,EAAU,IACjC,OAAOX,EAAO1C,eAAe,cAAewD,EAAOV,GAC9C,GAAIO,EAAUhB,GACnB,OAAOK,EAAO1C,eAAe,QAAS,EAAG8C,GACpC,GAAIO,EAAUf,GAAkB,CACrC,IAAInI,EAAO7D,KAAKgN,MAAMD,EAAUjB,IAChC,OAAOM,EAAO1C,eAAe,QAAS7F,EAAM2I,GACvC,GAAIO,EAAUd,GAEnB,OADAU,EAAS3M,KAAKgN,MAAMD,EAAUf,IACvBI,EAAO1C,eAAe,eAAgBiD,EAAQH,GAKvD,GAFAG,EAAS7B,GAAmBT,EAAWD,GAEnCuC,EAAS,GAAI,CACf,IAAIQ,EAAenN,KAAKgN,MAAMD,EAAUf,IACxC,OAAOI,EAAO1C,eAAe,UAAWyD,EAAcX,GAEtD,IAAIY,EAAyBT,EAAS,GAClCU,EAAQrN,KAAKyL,MAAMkB,EAAS,IAEhC,OAAIS,EAAyB,EACpBhB,EAAO1C,eAAe,cAAe2D,EAAOb,GAC1CY,EAAyB,EAC3BhB,EAAO1C,eAAe,aAAc2D,EAAOb,GAE3CJ,EAAO1C,eAAe,eAAgB2D,EAAQ,EAAGb,G,qECpM7C,gCAAgB,CAC7B5O,KAAM,cACN0P,WAAY,CACVC,aAAA,MAEF1P,MAAO,CACLsL,QAAS,CACP/L,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,GAEZuI,MAAO,CACLlI,KAAMgL,OACNrL,UAAU,IAGdkB,MAnB6B,SAmBvBJ,GACJ,IAAMM,EAAQ,OAAAC,GAAA,QAERkL,EAAsC,uBAAS,kBACnDzL,EAAMqJ,KAAKsG,QAAX,UACO,kBADP,kBAC4B3P,EAAMqJ,KAAKjK,SADvC,oBAC2D0M,KAAK8D,OAC5D,MAEArB,EAA8B,uBAClC,kBAAMjO,EAAMG,QAAQ,QAAWC,QAAQmP,WAGzC,MAAO,CACL1H,SAAA,KACA0D,kBACAiE,cAAA,QACAvB,SACA9C,qB,UC5CR,GAAO5J,OAAS,EAChB,GAAOC,UAAY,kBAEJ,U,aCUE,gCAAgB,CAC7B/B,KAAM,WACN0P,WAAY,CACVM,cAAA,KACAC,gBAEFhQ,MAAO,CACL0H,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,IAGdkB,MAhB6B,SAgBvBJ,GACJ,IAAMM,EAAQ,OAAAC,GAAA,QAEV0P,EAAO,iBAAI,GACTC,EAAW,EACX9E,EACJpL,EAAMqJ,KAAKhC,aAAe6I,EAAWA,EAAWlQ,EAAMqJ,KAAKhC,YAC7D,4BAAc,kBAAM8I,OAEpB,IAAMhF,EAAoC,uBACxC,kBAAM7K,EAAMG,QAAQ,QAAeC,QAAQ0P,kBAEvC7E,EAA0C,uBAAS,kBACvDJ,EAASrK,MAAM+B,OAAS,GAC2C,OAA/DsI,EAASrK,MAAMqK,EAASrK,MAAM+B,OAAS,GAAGwN,oBAIhD,SAASF,IACP7P,EAAMY,SAAS,QAAeC,QAAQmP,kBAAmB,CACvDL,KAAMA,EAAKnP,MACXoP,aAGJ,SAAS1E,IACPyE,EAAKnP,OAAS,EACdR,EAAMY,SAAS,QAAeC,QAAQoP,uBAAwB,CAC5DN,KAAMA,EAAKnP,MACXoP,aAIJ,MAAO,CACL9E,oBACAG,oBACA2E,WACA/E,WACAK,uB,UClER,GAAO3J,OAAS,EAChB,GAAOC,UAAY,kBAEJ,U,ICPRnD,GAAG,iB,IACDC,MAAM,qB,gNADb,yBAmBM,MAnBN,GAmBM,CAlBJ,yBAiBM,MAjBN,GAiBM,CAhBJ,yBAKE,GAJC+H,IAAK,EAAAA,IACN6J,iBAAe,OACd,mBAAkB,EAAAC,iBAClB,uBAAsB,EAAAC,sB,8DAEzB,yBAAwE,GAAzDC,aAAY,EAAAC,cAAcvN,MAAOmN,iBAAe,Q,uBAC/D,yBAQE,GAPCK,WAAY,EAAAlK,IACZmK,WAAU,EAAAF,cAActN,IACxBoE,OAAQ,EAAAA,OACRiJ,aAAY,EAAAC,cAAcvN,MAC1B0N,SAAU,EAAA1H,KAAK0H,SACf5F,SAAU,EAAA6F,iBACVtK,mBAAoB,EAAA2C,KAAK4H,O,yIChB3BrS,MAAM,kB,IAgBAA,MAAM,qB,iHAhBjB,yBAqBM,MArBN,GAqBM,E,2BApBJ,yBAmBM,2CAnB2C,EAAAsS,MAAI,SAAnBC,EAAK9F,G,gCAAvC,yBAmBM,OAnBDzM,MAAM,eAA6C+F,IAAK0G,G,6BAC3D,yBAiBM,2CAVe8F,GAAG,SAAdxK,EAAK9B,G,gCAPf,yBAiBM,OAhBJjG,MAAK,CAAC,gBAAe,C,iBACiB,cAAY,EAAK,c,WAAmC,YAAU,G,MAAqB,UAAQ,KAMhI+F,IAAKE,G,CAEN,yBAGE,GAFCsG,SAAU,EAAAiG,eAAezK,EAAK,EAAAwE,UAC9BzD,OAAQ,EAAAA,Q,8BAEX,yBAEM,MAFN,GAEM,6BADD,EAAAS,OAAOxB,EAAG,U,oDCOR,SAAS0K,GAAWnM,GACjC,OAAAE,EAAA,MAAa,EAAGrB,WAChB,IAAI0B,EAAO,OAAAC,EAAA,MAAOR,GAElB,OADAO,EAAKK,SAAS,EAAG,EAAG,EAAG,GAChBL,ECJM,SAAS6L,GAAUjF,EAAeC,GAC/C,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAAIwN,EAAqBF,GAAWhF,GAChCmF,EAAsBH,GAAW/E,GACrC,OAAOiF,EAAmB7E,YAAc8E,EAAoB9E,UCJ/C,SAAS+E,GAAYpF,EAAeC,GACjD,OAAAlH,EAAA,MAAa,EAAGrB,WAChB,IAAIwI,EAAW,OAAA7G,EAAA,MAAO2G,GAClBG,EAAY,OAAA9G,EAAA,MAAO4G,GACvB,OAAOC,EAAS3G,gBAAkB4G,EAAU5G,eAAiB2G,EAASO,aAAeN,EAAUM,WCDlF,SAAS4E,GAAQxM,GAE9B,OADA,OAAAE,EAAA,MAAa,EAAGrB,WACTuN,GAAUpM,EAAW4G,KAAK8D,O,QC7B5BhR,MAAM,qB,IACJA,MAAM,mB,UAEPA,MAAM,oB,UAUIA,MAAM,iB,IASfA,MAAM,kB,UACJA,MAAM,iB,yKAvBf,yBAgCM,MAhCN,GAgCM,CA/BJ,yBAoBM,MApBN,GAoBM,CAjBI,EAAAuM,SAAStI,QAAU,EAAA8O,uB,yBAF3B,yBAUM,MAVN,GAUM,E,2BANJ,yBAKE,2CAJ2B,EAAAxG,SAASjI,MAAK,EAAI,EAAAyO,wBAAqB,SAA1DrG,EAASD,G,gCADnB,yBAKE,GAHC1G,IAAK0G,EACLC,QAASA,EACTxE,WAAY,EAAA8K,cAActG,EAAS,EAAA5D,S,uEAGxC,yBAOM,MAPN,GAOM,CANJ,yBAKE,GAJCyD,SAAU,EAAAA,SACVzD,OAAQ,EAAAA,OACRN,SAAU,EAAAyK,cACVC,OAAQ,EAAAA,Q,uDAIf,yBASM,MATN,GASM,CAR6B,EAAA3G,SAAStI,OAAM,G,yBAAhD,yBAOM,MAPN,GAOM,CANJ,yBAKE,GAJCsI,SAAU,EAAAA,SACVzD,OAAQ,EAAAA,OACRN,SAAU,EAAAyK,cACVC,OAAQ,EAAAA,Q,qNC5BjB,yBAmBM,OAlBJlT,MAAM,mBACL,QAAK,+BAAS,UAAQ,KAAI,kCAAyC,UAAQ,S,CAI5E,yBAA+D,GAAlDqN,cAAa,EAAAnF,WAAa8E,MAAO,EAAAN,QAAQM,O,gCACtD,yBAWM,YATI,EAAAN,QAAQyG,QAAQlP,OAAM,G,yBAD9B,yBASE,K,MAPAjE,MAAM,+BACNqK,cAAY,OACX2C,MAAkB,UAAQ,QAAQ,K,SAAkB,G,iBAAe,8BAAqB,EAAO,mB,+ECPvF,gCAAgB,CAC7B7L,KAAM,kBACNC,MAAO,CACLsL,QAAS,CACP/L,KAAMgL,OACNrL,UAAU,GAEZ4H,WAAY,CACVvH,KAAMU,OACNf,UAAU,IAGdkB,MAZ6B,WAa3B,MAAc,kBAAN4R,EAAR,EAAQA,EACR,MAAO,CAAEA,Q,UCff,GAAOnQ,OAAS,GAED,U,mGCNRjD,MAAM,2B,IAEFA,MAAM,kB,UAGRA,MAAM,iB,IACJA,MAAM,iB,iPANf,yBAoBM,MApBN,GAoBM,CAnBJ,yBAGM,OAHDA,MAAM,iBAAkB,QAAK,8BAAE,EAAAqT,YAAA,EAAAA,WAAA,sB,CAClC,yBAAuD,MAAvD,GAAuD,6BAAxB,EAAA9G,SAAStI,QAAM,GAC9C,yBAAoD,GAAvCuE,SAAU,EAAAA,SAAW0K,OAAQ,EAAAA,Q,gCAEV,EAAAI,S,iEAAlC,yBAcM,MAdN,GAcM,C,4BAbJ,yBAYM,MAZN,GAYM,CAXJ,yBAIE,KAHAtT,MAAM,4BACNqK,cAAY,OACX,QAAK,8BAAE,EAAAgJ,YAAA,EAAAA,WAAA,wB,2BAEV,yBAKE,2CAJ2B,EAAA9G,UAAQ,SAA3BG,EAASD,G,gCADnB,yBAKE,GAHC1G,IAAK0G,EACLC,QAASA,EACTxE,WAAY,EAAA8K,cAActG,EAAS,EAAA5D,S,oDAVI,EAAAuK,sB,eCL3CrT,MAAM,gB,IACJuT,OAAO,KAAKC,MAAM,KAAKC,QAAQ,a,yDADtC,yBAmBM,MAnBN,GAmBM,E,yBAlBJ,yBAiBM,MAjBN,GAiBM,E,2BAhBJ,yBAeI,2CAfuB9H,OAAOtG,QAAQ,EAAAmD,WAAQ,SAAvCF,EAAMmE,G,gCAAjB,yBAeI,KAfkD1G,IAAK0G,GAAK,CAC9D,yBAaE,UAZCiH,GAAI,EAAAA,GACJC,GAAI,EAAAA,GACJC,EAAG,EAAAC,OACJC,KAAK,cACJC,OAAQ,EAAAb,QAAQ5K,EAAK,IACrB0L,oBAAgC,4BAA0B,EAAI,GAAI,WAAY,iBAG9EC,mBAAkB,EAAAC,cACnBC,eAAa,IACbC,iBAAe,MACdC,UAAW,EAAAC,2BAA2B7H,EAAOnE,EAAK,GAAGiM,a,oGCd/C,oCAAgB,CAC7BpT,KAAM,aACNC,MAAO,CACL8R,OAAQ,CACNvS,KAAMgL,OACNrL,UAAU,GAEZkI,SAAU,CACR7H,KAAMgL,OACNrL,UAAU,IAGdkB,MAZ6B,WAa3B,IAAIgT,GAAe,GACbd,EAAK,GACLC,EAAK,GACLE,EAAS,GACTK,EAAgB,EAAI3Q,KAAKkR,GAAKZ,EAEpC,SAASa,EACPH,EACAL,GAEA,OAAOA,EAAgBK,EAAaL,EAEtC,SAASI,EACP7H,EACA8H,GAEA,IAAMI,EAAW,UAAH,OAAaH,EAAb,aAA6Bd,EAA7B,aAAoCC,EAApC,KAEd,OADAa,EAA2B,IAAbD,EAAmBC,EAC1BG,EAGT,MAAO,CACLH,cACAN,gBACAR,KACAC,KACAE,SACAa,4BACAJ,iCCzCR,GAAOrR,OAAS,GAED,U,aCIE,gCAAgB,CAC7B9B,KAAM,wBACN0P,WAAY,CACV+D,mBACAC,eAEFzT,MAAO,CACL8R,OAAQ,CACNvS,KAAMgL,OACNrL,UAAU,GAEZkI,SAAU,CACR7H,KAAMgL,OACNrL,UAAU,GAEZwI,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZiM,SAAU,CACR5L,KAAMgL,OACNrL,UAAU,IAGdkB,MAxB6B,WAyB3B,IAAM8R,EAAW,kBAAI,GACrB,SAASD,EAAWyB,GAClBA,EAAMC,kBACNzB,EAASpR,OAASoR,EAASpR,MAE7B,MAAO,CAAEoR,WAAUN,cAAA,QAAeK,iB,UClCxC,GAAOpQ,OAAS,GAChB,GAAOC,UAAY,kBAEJ,U,aCEE,gCAAgB,CAC7B/B,KAAM,mBACN0P,WAAY,CACV+D,mBACAI,0BAEF5T,MAAO,CACLmL,SAAU,CACR5L,KAAMgL,OACNrL,UAAU,GAEZwI,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,IAGdkB,MAhB6B,SAgBvBJ,GACJ,MAAO,CACL6R,cAAe,uBAAS,kBAAM,gBAAiB7R,EAAMmL,aACrD2G,OAAQ,uBAAS,kBAAM,gBAAc9R,EAAM0H,WAC3CiK,sBAAuB,EACvBC,cAAA,Y,UC1BR,GAAO/P,OAAS,GAED,UCUE,gCAAgB,CAC7B9B,KAAM,gBACN0P,WAAY,CACVoE,qBAEF7T,MAAO,CACL6Q,WAAY,CACVtR,KAAMuM,KACN5M,UAAU,GAEZ4U,QAAS,CACPvU,KAAMuM,KACN5M,UAAU,GAEZwI,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZ6U,UAAW,CACTxU,KAAMuM,KACN5M,UAAU,GAEZ6R,SAAU,CACRxR,KAAMU,OACNf,UAAU,GAEZwH,mBAAoB,CAClBnH,KAAMsP,QACN3P,UAAU,GAEZiM,SAAU,CACR5L,KAAMgL,OACNrL,UAAU,IAGdkB,MAnC6B,SAmCvBJ,GACJ,IAAMkR,EAAsB,iBAAI,IAChC,EAAiD,oBAAOlR,GAAlD+T,EAAN,EAAMA,UAAWD,EAAjB,EAAiBA,QAASpN,EAA1B,EAA0BA,mBAI1B,SAASsN,IACP9C,EAAKpQ,MAAQ,GACb,IAAI6F,EAAMoN,EAAUjT,MACpB,MAAO6F,GAAOmN,EAAQhT,MAAO,CAE3B,IADA,IAAMkF,EAAe,GACZnB,EAAI,EAAGA,EAAI,EAAGA,IACrBmB,EAAKjB,KAAK4B,GACVA,EAAM,OAAAV,GAAA,MAAQU,EAAK,GAErBuK,EAAKpQ,MAAMiE,KAAKiB,IAIpB,SAASiO,EAAUtN,GACjB,OAAOD,EAAmB5F,MACtB,CAAC,EAAG,GAAGpB,SAASiH,GAChB,CAAC,EAAG,GAAGjH,SAASiH,GAGtB,SAASyK,EAAezK,EAAWwE,GACjC,OAAIA,EACKA,EACJpD,QAAO,SAACuD,GAAD,OACNgG,GACE,gBAAchG,EAAQS,aAAc/L,EAAM+Q,UAC1CpK,MAGHuN,UAEE,GAQT,OAxCA,wBAAU,kBAAMF,OAmChB,oBACE,kBAAMhU,EAAM6Q,cACZ,kBAAMmD,OAGD,CAAE9C,OAAM/I,SAAA,KAAQsJ,eAAaC,WAASuC,YAAW7C,qB,UC3F9D,GAAOvP,OAAS,GAED,U,ICNRjD,MAAM,iB,yDAAX,yBAIM,MAJN,GAIM,E,2BAHJ,yBAEM,2CAF2C,EAAAoH,MAAI,SAAnBW,EAAK0E,G,gCAAvC,yBAEM,OAFDzM,MAAM,eAA6C+F,IAAK0G,G,6BACxD,EAAAlD,OAAOxB,EAAG,MAAS,EAAAwN,gBAAa,M,QCCxB,oCAAgB,CAC7BpU,KAAM,eACNC,MAAO,CACL+T,UAAW,CACTxU,KAAMuM,KACN5M,UAAU,GAEZiV,cAAe,CACb5U,KAAMU,OACNf,UAAU,IAGdkB,MAZ6B,SAYvBJ,GAEJ,IADA,IAAMgG,EAAO,GACJnB,EAAI,EAAGA,EAAI,EAAGA,IACrBmB,EAAKjB,KAAK,OAAAkB,GAAA,MAAQjG,EAAM+T,UAAWlP,IAErC,MAAO,CAAEmB,OAAMC,WAAA,KAASkC,SAAA,S,UChB9B,GAAOtG,OAAS,GAED,U,ICNRjD,MAAM,mB,GAKP,yBAAmD,KAAhDA,MAAM,qBAAqBqK,cAAY,Q,aAEvCrK,MAAM,kB,GAST,yBAAoD,KAAjDA,MAAM,sBAAsBqK,cAAY,Q,kEAhB/C,yBAkBM,MAlBN,GAkBM,CAjBJ,yBAKM,OAJJrK,MAAM,qCACL,QAAK,+BAAE,EAAAwV,KAAI,2B,CAEZ,KAEF,yBAIM,MAJN,GAIM,CAHJ,yBAEO,yCADF,EAAAjM,OAAO,EAAAxB,IAAG,WAAc,EAAAwN,gBAAa,KAG5C,yBAKM,OAJJvV,MAAM,sCACL,QAAK,+BAAE,EAAAwV,KAAI,uB,CAEZ,OCbW,oCAAgB,CAC7BrU,KAAM,iBACNC,MAAO,CACL2G,IAAK,CACHpH,KAAMuM,KACN5M,UAAU,GAEZiV,cAAe,CACb5U,KAAMU,OACNf,UAAU,IAGdmV,MAAO,CAAC,mBAAoB,wBAC5BjU,MAb6B,SAavBJ,EAbuB,GAaR,IAANoU,EAAM,EAANA,KACb,MAAO,CAAEA,OAAMjM,SAAA,S,UCbrB,GAAOtG,OAAS,GAED,UCcE,gCAAgB,CAC7B9B,KAAM,eACN0P,WAAY,CACV6E,iBACAC,gBACAC,mBAEFxU,MAAO,CACL0H,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,IAGdkB,MAjB6B,SAiBvBJ,GACJ,IAAMM,EAAQ,OAAAC,GAAA,QAEd,4BAAc,kBAAMkU,OAEpB,IAAM3M,EAAa,aACfnB,EAAM,iBAAI,IAAImF,MACd8E,EAAgB,iBAClB,gBAAuBjK,EAAI7F,MAAOd,EAAMqJ,KAAK4H,QAEzCD,EAA4C,uBAChD,kBAAM1Q,EAAMG,QAAQ,QAAeC,QAAQgU,sBAG7C,SAASD,IACP7D,EAAc9P,MAAQ,gBACpB6F,EAAI7F,MACJd,EAAMqJ,KAAK4H,OAEb,IAAM0D,EAA8B,CAClCzK,KAAM,OAAA/B,EAAA,MAAOyI,EAAc9P,MAAMuC,MAAOyE,GACxCjI,GAAI,OAAAsI,EAAA,MAAOyI,EAAc9P,MAAMwC,IAAKwE,GACpC8M,MAAO,OACP1E,SAAU,KAEZ5P,EAAMY,SAAS,QAAeC,QAAQ0T,sBAAuBF,GAG/D,SAASlE,IACP9J,EAAI7F,MAAQ,OAAAkI,GAAA,MAAUrC,EAAI7F,MAAO,GACjC2T,IAEF,SAAS/D,IACP/J,EAAI7F,MAAQ,OAAA4H,GAAA,MAAU/B,EAAI7F,MAAO,GACjC2T,IAGF,MAAO,CACL9N,MACAiK,gBACAI,mBACAP,mBACAC,2B,UC3ER,GAAO7O,OAAS,GAED,U,mGCNRjD,MAAM,oB,oLAAX,yBAaM,MAbN,GAaM,CAZJ,yBAWO,QAVMgN,MAAK,IAAC,iBAAgC,C,0DAA7B,EAAAtM,GAAE,gCACXwV,QAAO,IAChB,iBAME,CANF,yBAME,GALCpN,OAAQ,EAAAA,OACR2B,KAAM,EAAAA,KACN0L,eAAc,EAAAjM,YACdkM,sBAAqB,EAAAC,iBACrBC,yBAAuB,G,wGCFjB,gCAAgB,CAC7BnV,KAAM,iBACN0P,WAAY,CACV0F,UAAA,SAEFnV,MAAO,CACL0H,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,IAGdkB,MAf6B,SAevBJ,GACJ,IAAMyF,EAAO,IAAIqG,KACjB,MAAO,CACLhD,YAAa,CACXlC,SAAU,OACVvD,MAAO,OAAAsF,GAAA,MAAalD,GACpBnC,IAAK,OAAAuF,EAAA,MAAWpD,IAElBwP,iBAAkBjV,EAAM0H,OAAOF,KAAI,SAACC,GAAD,OAAWA,EAAM9I,U,UC1B5D,GAAOkD,OAAS,GAChB,GAAOC,UAAY,kBAEJ,U,yHCPRlD,MAAM,wB,IACJA,MAAM,iB,GACT,yBAA6D,KAA1DA,MAAM,+BAA+BqK,cAAY,Q,aAGjDrK,MAAM,gB,UAC4CA,MAAM,c,8IAN/D,yBAgBM,MAhBN,GAgBM,CAfJ,yBAGM,MAHN,GAGM,CAFJ,G,6BAA6D,IAC7D,6BAAG,EAAAU,GAAE,2BAEP,yBAUM,MAVN,GAUM,CATyC,IAAlCiL,OAAO3F,KAAK,EAAAwQ,gBAAgBvS,Q,yBAAvC,yBAEM,MAFN,GAEM,6BADD,EAAAvD,GAAE,4B,mEAEP,yBAKE,2CAJ+BiL,OAAO3F,KAAK,EAAAwQ,gBAAgBC,QAAI,SAAxDC,G,gCADT,yBAKE,GAHCA,qBAAsBA,EACtBvD,QAAS,EAAAqD,eAAeE,GACxB3Q,IAAK2Q,G,8JCbP1W,MAAM,gB,IAQGA,MAAM,e,IAGNA,MAAM,gB,IACNA,MAAM,e,oOAZpB,yBAwBM,MAxBN,GAwBM,CAvBJ,yBAsBO,QArBMgN,MAAK,IACd,iBAA2C,CAA3C,yBAA2C,GAA9BK,cAAa,EAAA8F,QAAQ/K,O,qDAAS,IAC3C,6BAAG,EAAAsO,sBAAoB,OAEdR,QAAO,IACI,iBAAiC,E,2BAArD,yBAcM,2CAd+B,EAAA/C,QAAQA,SAAO,SAAzBwD,G,gCAA3B,yBAcM,OAdD3W,MAAM,SAA4C+F,IAAK4Q,EAAO5W,I,CACjE,yBAES,OAFT,GAES,6BADP,EAAAqT,EAAA,0BAAqBuD,EAAOC,eAAW,GAEzC,yBAAoD,OAApD,GAAoD,6BAAtBD,EAAOzU,OAAK,GAC1C,yBAQO,OARP,GAQO,CAPL,yBAMC,GALEjB,GAAE,C,iCAA0E,EAAO,c,aAInF,iBAAyB,C,0DAAtB0V,EAAOxJ,cAAY,O,8CCbpB,gCAAgB,CAC7BhM,KAAM,cACNC,MAAO,CACL+R,QAAS,CACPxS,KAAMgL,OACNrL,UAAU,GAEZoW,qBAAsB,CACpB/V,KAAMU,OACNf,UAAU,IAGdkB,MAZ6B,WAa3B,MAAc,kBAAN4R,EAAR,EAAQA,EACR,MAAO,CAAEA,Q,UCff,GAAOnQ,OAAS,GAChB,GAAOC,UAAY,kBAEJ,UCJF,I,UAAe,SAC1ByT,EACAE,GAEA,IAAI3U,EACJ,OAAQyU,EAAOC,aACb,IAAK,KACL,IAAK,KACH1U,EAAQ,GAAH,OAAMyU,EAAOzU,MAAb,SACL,MACF,IAAK,KACHA,EAAQ,GAAH,OAAMyU,EAAOzU,MAAb,OACL,MACF,IAAK,KACHA,EAAQyU,EAAOzU,MACf,MACF,QACE,MAAM,IAAI4U,MAAJ,uEAC4DH,EAAOC,YADnE,MAIV,MAAO,CACLzJ,aAAc,gBAAkB,gBAAcwJ,EAAOxJ,aAAc0J,IAChE1J,aACH4J,WAAYJ,EAAOI,WACnBhX,GAAI4W,EAAO5W,GACX6W,YAAaD,EAAOC,YACpB1U,MAAOA,KAIE8U,GAAqB,SAChC7D,EACA8D,EACAJ,GAHgC,OAKhC1D,EAAQ+D,QAAO,SAACC,EAA6BR,GAC3C,IAAM9N,EAAQoO,EAAiBG,MAAK,SAACC,GAAD,OAAOA,EAAEtX,KAAO4W,EAAOW,YAU3D,OATIzO,GAASA,EAAMT,aACwB,IAArC+O,EAAUtO,EAAM0O,mBAClBJ,EAAUtO,EAAM0O,iBAAmB,CACjCnP,MAAOS,EAAMT,MACb+K,QAAS,KAGbgE,EAAUtO,EAAM0O,iBAAiBpE,QAAQhN,KAAK,GAAawQ,EAAQE,KAE9DM,IACN,KC1CY,gCAAgB,CAC7BhW,KAAM,cACN0P,WAAY,CACV2G,gBAEFpW,MAAO,CACL0H,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,IAGdkB,MAf6B,SAevBJ,GACJ,MAAc,kBAANgS,EAAR,EAAQA,EACFoD,EAAiB,uBAAS,kBAC9BQ,GACE5V,EAAMqJ,KAAK0I,QACX,gBAAgB/R,EAAM0H,OAAQsK,GAC9BhS,EAAMqJ,KAAK0H,aAGf,MAAO,CAAEqE,qB,UC7Bf,GAAOvT,OAAS,GAChB,GAAOC,UAAY,kBAEJ,U,yBCPRnD,GAAG,e,yGAAR,yBAqBM,MArBN,GAqBM,CApBJ,yBAIE,GAHA0X,KAAK,WACJvV,MAAO,EAAAuI,KAAKhC,YACZiP,KAAM,EAAAhX,GAAE,mBAAqB,EAAA+J,KAAKhC,c,yBAErC,yBAIE,GAHAgP,KAAK,OACJvV,MAAO2M,OAAO,EAAApE,KAAK/B,gBAAgBiP,QAAO,GAC1CD,KAAM,EAAAhX,GAAE,gB,yBAEX,yBAIE,GAHA+W,KAAK,UACJvV,MAAO,EAAAyG,eAAevB,KACtBsQ,KAAM,EAAA/O,eAAeX,U,yBAExB,yBAIE,GAHAyP,KAAK,OACJvV,MAAO,EAAAuI,KAAKmN,UACZF,KAAM,EAAAhX,GAAE,iBAAmB,EAAA+J,KAAKmN,Y,0ECbtB,gCAAgB,CAC7BzW,KAAM,iBACN0P,WAAY,CACVgH,YAAA,MAEFzW,MAAO,CACLqJ,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,IAGdkB,MAX6B,SAWvBJ,GACJ,MAAc,kBAANgS,EAAR,EAAQA,EACFzK,EAAsC,uBAC1C,kBAAMvH,EAAMqJ,KAAK9B,kBAGnB,SAASmP,EAAanP,GACpB,IAAMX,EAAWW,EAAezG,MAAM6V,MAAM,QACxCpP,EAAezG,MAAM8V,MAAM,MAAM,GACjCrP,EAAezG,MACnB,MAAO,CACLkF,KAAMuB,EAAezG,MAAM6V,MAAM,QAA3B,UACCpP,EAAezG,MAAM8V,MAAM,KAAK,GADjC,YAEArP,EAAezG,MAAM6V,MAAM,SACvB3E,EAAE,aAAc,GAChBA,EAAE,aAAc,IAJpB,YAMGA,EAAE,aAAc,GANnB,KAONpL,SAAU,GAAF,OAAKA,EAASgQ,MAAM,KAAK,GAAzB,aAAgChQ,EAASgQ,MAAM,KAAK,GAApD,QAIZ,MAAO,CAAErP,eAAgB,uBAAS,kBAAMmP,EAAanP,U,UCnC3D,GAAO1F,OAAS,GAED,UCaE,gCAAgB,CAC7B9B,KAAM,YACN0P,WAAY,CACVoH,YACAC,gBACAC,kBACAC,eACAC,mBAEF7W,MAT6B,WAU3B,IAAME,EAAQ,OAAAC,GAAA,QACR2I,EAAsC,uBAC1C,kBAAM5I,EAAMG,QAAQ,QAAWC,QAAQwW,sBAEnCxP,EAAgC,uBACpC,kBAAMpH,EAAMG,QAAQ,QAAaC,QAAQyW,WAErChO,EAA0B,iBAAI,SAKpC,SAASC,EAAoB1F,GAC3ByF,EAAWrI,MAAQ4C,EAGrB,OARA,0BAAY,WACVpD,EAAMe,OAAO,QAAeC,UAAU8V,mBAOjC,CAAElO,WAAUxB,SAAQyB,aAAYC,0B,UCzC7C,GAAOvH,OAASA,EAChB,GAAOC,UAAY,kBAEJ,iB,oCCRf,W,oFCAA,W,6DCAA,W,2DCAA,W,gDCCA,IAAIuV,EAAY,EAAQ,QAGxBlU,EAAOC,QAAU,mEAAmEuH,KAAK0M,I,yDCJzF,0EA0Be,SAAS3O,EAAUxD,EAAWC,GAC3C,eAAa,EAAGpB,WAChB,IAAIsB,EAAS,eAAUF,GACvB,OAAO,eAAUD,GAAYG,K,yDC7B/B,W,yDCAA,W,yDCAA,W,yDCAA,W,4DCCO1G,GAAG,mB,GACDC,MAAM,a,GACJA,MAAM,iB,GAGNA,MAAM,iB,8JALf,yBASM,MATN,EASM,CARJ,yBAOM,MAPN,EAOM,CANJ,yBAEM,MAFN,EAEM,CADJ,yBAAW,KAEb,yBAEM,MAFN,EAEM,CADJ,yBAAwC,GAAlBI,OAAQ,EAAAA,QAAM,yB,qGCNrCL,GAAG,S,yFAAR,yBAEM,MAFN,EAEM,CADJ,yBAAmE,OAA9DC,MAAM,WAAY+M,IAAK,gBAAiBD,IAAI,iB,qBAKpC,GACb3L,KAAM,S,UCHV,EAAO8B,OAAS,EAChB,EAAOC,UAAY,kBAEJ,Q,YCFE,+BAAgB,CAC7B/B,KAAM,SACN0P,WAAY,CACV6H,UACAC,oBAAA,QAEFvX,MAAO,CACLhB,OAAQ,CACNO,KAAMU,OACNf,UAAU,M,UCVlB,EAAO2C,OAASA,EAED,gB,0JCNRlD,GAAG,c,SACDC,MAAM,a,iOADb,yBAcM,MAdN,EAcM,CAbyB,EAAAsK,SAAS9J,U,yBAAtC,yBAYM,MAZN,EAYM,CAXJ,yBASO,QARMwM,MAAK,GAAC,iBAAiC,C,0DAA9B,EAAAtM,GAAE,iCACXwV,QAAO,GAChB,iBAIE,CAJF,yBAIE,GAHClW,MAAK,kBAA0C,IAApB,EAAAsK,SAAS7B,aACpCgC,KAAM,EAAAH,SACNxB,OAAQ,EAAAA,Q,4CAIuB,IAApB,EAAAwB,SAAS7B,a,yBAA3B,yBAA2D,Y,6NCZ1D1I,GAAG,mB,4MAAwB,EAAAkX,kB,yBAAhC,yBAiBM,MAjBN,EAiBM,CAhBJ,yBAGE,GAFC,kBAAiB,EAAA2B,gBACjB,aAAY,EAAAC,qB,6CAEf,yBAME,GALC/P,OAAQ,EAAAA,OACR2B,KAAM,EAAAA,KACNP,YAAa,EAAAA,YACbkM,sBAAqB,EAAAC,iBACrByC,WAAW,G,8DAEd,yBAIE,GAHCC,qBAAoB,EAAA1C,iBACpB2C,cAAa,EAAAlQ,OACb,yBAAwB,EAAAmQ,wB,0PCfxBjZ,MAAM,c,GACJA,MAAM,e,GAONA,MAAM,uC,GACJA,MAAM,4C,GAmBRA,MAAM,e,yFA5Bb,yBAmCM,MAnCN,EAmCM,CAlCJ,yBAMM,MANN,EAMM,CALJ,yBAIE,KAHAA,MAAM,qBACNqK,cAAY,OACX,QAAK,+BAAE,EAAAmL,KAAI,uBAGhB,yBAmBM,MAnBN,EAmBM,CAlBJ,yBAiBM,MAjBN,EAiBM,E,2BAhBJ,yBAeM,2CAdY,EAAA0D,YAAU,SAAnBC,G,gCADT,yBAeM,OAbJnZ,MAAM,6BACL+F,IAAKoT,G,CAEN,yBASQ,cARN,yBAME,SALAxY,KAAK,QACJZ,GAAIoZ,EACJhY,KAAMgY,EACNC,QAAS,EAAAC,oBAAsBF,EAC/B,QAAK,mBAAE,EAAAG,kBAAkBH,K,2CAE5B,yBAAwD,yCAA/C,EAAAzY,GAAA,iCAA6ByY,KAAK,U,UAKnD,yBAMM,MANN,EAMM,CALJ,yBAIE,KAHAnZ,MAAM,sBACNqK,cAAY,OACX,QAAK,+BAAE,EAAAmL,KAAI,4BC9BH,+BAAgB,CAC7BrU,KAAM,YACNsU,MAAO,CAAC,aAAc,mBACtBjU,MAH6B,SAGvBJ,EAHuB,GAGR,IAANoU,EAAM,EAANA,KACT6D,EAAoB,iBAAI,SACtBH,EAAa,CAAC,OAAQ,QAAS,QAErC,SAASI,EAAkB5P,GACzB2P,EAAkBnX,MAAQwH,EAC1B8L,EAAK,kBAAmB9L,GAG1B,MAAO,CACL2P,oBACAH,aACAI,oBACA9D,W,UCdR,EAAOvS,OAAS,EAChB,EAAOC,UAAY,kBAEJ,Q,GCPRlD,MAAM,e,GAeDA,MAAM,e,0GAfhB,yBAiBM,MAjBN,EAiBM,E,2BAhBJ,yBAeQ,2CAdU,EAAAiX,kBAAgB,SAAzBpO,G,gCADT,yBAeQ,SAbNlI,KAAK,WACJoF,IAAK8C,EAAM9I,GACXwZ,MAAK,OAAW,EAAAC,YAAY3Q,EAAMT,S,CAEnC,yBAME,SALAzH,KAAK,WACJZ,GAAI8I,EAAM9I,GACVoB,KAAM0H,EAAMT,MACZgR,QAAS,EAAA/C,iBAAiBvV,SAAS+H,EAAM9I,IACzC,QAAK,mBAAE,EAAAkZ,uBAAuBpQ,EAAM9I,M,2CAEvC,yBAAyC,GAA5BsN,cAAaxE,EAAMT,O,wBAChC,yBAA4D,OAA5D,EAA4D,6BAA/BS,EAAM0O,iBAAe,I,8BCTvC,+BAAgB,CAC7BpW,KAAM,aACNC,MAAO,CACLiV,iBAAkB,CAChB1V,KAAMmK,MACNvJ,QAAS,iBAAM,KAEjBkY,WAAY,CACV9Y,KAAMgL,OACNrL,UAAU,IAGdmV,MAAO,CAAC,0BACRjU,MAb6B,SAavBJ,EAbuB,GAaR,IAANoU,EAAM,EAANA,KACb,EAAc,iBAANpC,EAAR,EAAQA,EACF6D,EAAoD,uBAAS,kBACjE,eAAgB7V,EAAMqY,WAAYrG,MAGpC,SAAS6F,EAAuBS,GAC9BlE,EAAK,yBAA0BkE,GAGjC,MAAO,CACLF,YAAa,oBAAO,eACpBvC,mBACAgC,6B,UC5BR,EAAOhW,OAAS,EAED,Q,YCcE,+BAAgB,CAC7B9B,KAAM,aACN0P,WAAY,CACV8I,WAAA,EACApD,UAAA,OACAqD,aAEFxY,MAAO,CACL0H,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,IAGdkB,MAjB6B,SAiBvBJ,GACJ,MAAc,iBAANgS,EAAR,EAAQA,EACJiG,EAAoB,iBAAI,SACtBH,EAAa,CAAC,OAAQ,QAAS,QAC/BhP,EAA0C,iBAC9C2P,EAAeR,EAAkBnX,QAE7B+U,EAAoD,uBAAS,kBACjE,eAAgB7V,EAAM0H,OAAQsK,MAE1BiD,EAAkC,iBAAIyD,EAAU1Y,EAAM0H,SAE5D,SAAS8P,EAAgBlP,GACvB2P,EAAkBnX,MAAQwH,EAC1BQ,EAAYhI,MAAQ2X,EAAeR,EAAkBnX,OAEvD,SAAS2X,EAAenQ,GACtB,OAAO,eAAmB,IAAIwD,KAAQxD,EAAWtI,EAAMqJ,KAAK4H,OAE9D,SAASwG,EAAoB1O,GAC3BD,EAAYhI,MAAQ,eAClBgI,EAAYhI,MACZiI,EACA/I,EAAMqJ,KAAK4H,OAGf,SAASyH,EAAUhR,GACjB,OAAOA,EAAOF,KAAI,SAACC,GAAD,OAAWA,EAAM9I,MAErC,SAASkZ,EAAuBS,GAC1BrD,EAAiBnU,MAAMpB,SAAS4Y,GAClCrD,EAAiBnU,MAAQmU,EAAiBnU,MAAMiH,QAC9C,SAACpJ,GAAD,OAAQA,IAAO2Z,KAGjBrD,EAAiBnU,MAAMiE,KAAKuT,GAWhC,OAPA,oBACE,kBAAMtY,EAAM0H,UACZ,SAACiR,GACC1D,EAAiBnU,MAAQ4X,EAAUC,MAIhC,CACL7P,cACAmP,oBACAH,aACAjC,mBACAZ,mBACAwC,sBACAI,yBACAL,sB,UCvFR,EAAO3V,OAAS,EAChB,EAAOC,UAAY,kBAEJ,Q,oCCEE,+BAAgB,CAC7B/B,KAAM,iBACN0P,WAAY,CACVM,aAAA,KACA6I,cAEFxY,MAN6B,WAO3B,IAAME,EAAQ,OAAAC,EAAA,QACR2I,EAAsC,uBAC1C,kBAAM5I,EAAMG,QAAQ,OAAWC,QAAQwW,sBAEnCxP,EAAgC,uBAAS,kBAC7CpH,EAAMG,QAAQ,OAAaC,QAAQyW,QAAQpP,QAAO,SAACN,GAAD,OAChDyB,EAASpI,MAAM+X,YAAYnZ,SAAS+H,EAAM9I,UAG9C,MAAO,CAAEuK,WAAUxB,a,UCrBzB,EAAO7F,OAASA,EAChB,EAAOC,UAAY,kBAEJ,gB,kCCRf,W,qBCAA,IAAIgX,EAAwB,EAAQ,QAIpCA,EAAsB,a,kCCJtB,W,gFCGA,IAAIvV,EAAI,EAAQ,QACZa,EAAc,EAAQ,QACtB2U,EAAS,EAAQ,QACjBC,EAAM,EAAQ,QACdC,EAAW,EAAQ,QACnBC,EAAiB,EAAQ,QAAuC1U,EAChE2U,EAA4B,EAAQ,QAEpCC,EAAeL,EAAO/O,OAE1B,GAAI5F,GAAsC,mBAAhBgV,MAAiC,gBAAiBA,EAAa5O,iBAExDzH,IAA/BqW,IAAeC,aACd,CACD,IAAIC,EAA8B,GAE9BC,EAAgB,WAClB,IAAIF,EAActV,UAAUlB,OAAS,QAAsBE,IAAjBgB,UAAU,QAAmBhB,EAAY9C,OAAO8D,UAAU,IAChGe,EAAShB,gBAAgByV,EACzB,IAAIH,EAAaC,QAEDtW,IAAhBsW,EAA4BD,IAAiBA,EAAaC,GAE9D,MADoB,KAAhBA,IAAoBC,EAA4BxU,IAAU,GACvDA,GAETqU,EAA0BI,EAAeH,GACzC,IAAII,EAAkBD,EAAc/O,UAAY4O,EAAa5O,UAC7DgP,EAAgB9O,YAAc6O,EAE9B,IAAIE,EAAiBD,EAAgB/O,SACjCiP,EAAyC,gBAAhCzZ,OAAOmZ,EAAa,SAC7BO,EAAS,wBACbT,EAAeM,EAAiB,cAAe,CAC7CI,cAAc,EACdC,IAAK,WACH,IAAIC,EAASb,EAASnV,MAAQA,KAAKiW,UAAYjW,KAC3CkW,EAASP,EAAexW,KAAK6W,GACjC,GAAId,EAAIM,EAA6BQ,GAAS,MAAO,GACrD,IAAIG,EAAOP,EAASM,EAAO9W,MAAM,GAAI,GAAK8W,EAAOE,QAAQP,EAAQ,MACjE,MAAgB,KAATM,OAAclX,EAAYkX,KAIrC1W,EAAE,CAAEwV,QAAQ,EAAMnV,QAAQ,GAAQ,CAChCoG,OAAQuP,M,4DC9CL3a,MAAM,a,wGAAX,yBAEM,MAFN,EAEM,CADJ,yBAAY,K,gBCGC,+BAAgB,CAC7BmB,KAAM,eACN0P,WAAY,CACV0K,WAAA,QCLN,EAAOtY,OAASA,EAED,gB,kCCLf,W,mJCCOjD,MAAM,e,uBAKFA,MAAM,e,sIALf,yBA2CM,MA3CN,EA2CM,CA1CO,EAAAwb,mBAAqB,EAAAC,Y,yBAAhC,yBAEM,qCADD,EAAA/a,GAAE,8B,yBAEP,yBAsCM,SArCJ,yBA4BM,MA5BN,EA4BM,CA3BJ,yBAQQ,cAPN,yBAKE,SAJAC,KAAK,QACLQ,KAAK,iBACJiY,QAAsB,mBAAb,EAAAsC,cACT,QAAK,8BAAE,EAAAC,mBAAA,EAAAA,kBAAA,sB,iDACR,IACF,6BAAG,EAAAjb,GAAE,2BAEP,yBAQQ,cAPN,yBAKE,SAJAC,KAAK,QACLQ,KAAK,iBACJiY,QAAsB,mBAAb,EAAAsC,cACT,QAAK,8BAAE,EAAAC,mBAAA,EAAAA,kBAAA,sB,iDACR,IACF,6BAAG,EAAAjb,GAAE,2BAEP,yBAQQ,cAPN,yBAKE,SAJAC,KAAK,QACLQ,KAAK,cACJiY,QAAsB,gBAAb,EAAAsC,cACT,QAAK,8BAAE,EAAAC,mBAAA,EAAAA,kBAAA,sB,iDACR,IACF,6BAAG,EAAAjb,GAAE,8BAID,EAAA0I,OAAOnF,OAAM,G,yBADrB,yBAOE,G,MALCuE,SAAU,EAAAA,SACVY,OAAQ,EAAAA,OACRsS,cAAe,EAAAA,cACfE,kBAAmB,EAAAA,kBACnB9C,UAAW,EAAAA,W,yLCxCb9Y,MAAM,S,wGAAX,yBAEM,MAFN,EAEM,CADJ,yBAAqD,EAArD,wBAAqD,EAAtB,eAAEA,MAAM,cAAW,W,sCCFzC6b,G,kDAAiB,SAC5BC,GAEU,IADVC,EACU,wDACN3U,EAAO,IACP2U,IACF3U,EAAO/F,OAAOkC,KAAKyL,MAAM8M,EAAe,QACxCA,GAAgB,OAElB,IAAMrL,EAAQpP,OAAOkC,KAAKyL,MAAM8M,EAAe,OAAO7W,SAAS,EAAG,KAClE6W,GAAgB,KAChB,IAAMxL,EAAUjP,OAAOkC,KAAKyL,MAAM8M,EAAe,KAAK7W,SAAS,EAAG,KAC5DkL,EAAU9O,OAAOya,EAAe,IAAI7W,SAAS,EAAG,KACtD,OAAI8W,EACF,UAAmB,MAAT3U,EAAe,GAAf,UAAuBA,EAAvB,OAAV,OACY,OAAVqJ,EAAiB,GAAjB,UAAyBA,EAAzB,OADF,OAEGH,EAFH,aAEeH,EAFf,KAIF,UAAoB,OAAVM,EAAiB,GAAjB,UAAyBA,EAAzB,MAAV,OAA8CH,EAA9C,YAAyDH,KCf9C,EAAqB,SAChCuL,EACAxZ,GAEU,IADV6Z,IACU,yDACV,MAAyB,mBAAlBL,EACHG,EAAe3Z,EAAO6Z,GACJ,mBAAlBL,EACAxZ,EAAMyV,QAAQ,GAAK,MACnBzV,EAAM2J,YCFK,+BAAgB,CAC7B1K,KAAM,QACN0P,WAAY,CACVmL,SAAA,eAEF5a,MAAO,CACLoH,SAAU,CACR7H,KAAMgL,OACNrL,UAAU,GAEZ8I,OAAQ,CACNzI,KAAMgL,OACNrL,UAAU,GAEZob,cAAe,CACb/a,KAAMU,OACNf,UAAU,GAEZsb,kBAAmB,CACjBjb,KAAMmK,MACNxK,UAAU,GAEZwY,UAAW,CACTnY,KAAMsP,QACN3P,UAAU,IAGdkB,MA3B6B,SA2BvBJ,GACJ,MAAc,iBAANgS,EAAR,EAAQA,EAER,SAAS6I,EAAU/Z,GACjB,OAAO4N,MAAM5N,GAAS,GAAKA,EAG7B,SAASga,EAAOC,EAAYja,GAC1B,OAAO+Z,EAAUE,GAASF,EAAU/Z,GAEtC,IAAIka,EAA2C,uBAAS,iBAAO,CAC7DhT,OAAQhI,EAAMgI,OAEdZ,SAAU6T,KAAKC,MAAMD,KAAKE,UAAUnb,EAAMoH,eAEtCkH,EAAU,uBAA8B,iBAAO,CACnD8M,YAAY,EACZC,qBAAqB,EACrBC,WAAW,EACXC,OAAQ,CACNC,QAAS,CACPC,IAAKzb,EAAM0X,UAAY,GAAK,KAGhCgE,OAAQ,CACNC,EAAG,CACDC,SAAS,EACTC,KAAM,CACJC,iBAAiB,IAGrBC,EAAG,CACDH,SAAS,EACTC,KAAM,CACJC,iBAAiB,GAEnBE,MAAO,CACLC,cAAe,EACfC,SAAU,SAAUpb,GAClB,OAAO,EAAmBd,EAAMsa,eAAgBxZ,GAAO,KAG3Dqb,SAAU,SAAUC,GAClBA,EAAMhK,MAAQpS,EAAM0X,UAAY,GAAK,MAI3C2E,QAAS,CACPC,WAAY,CACVC,OAAQ,MACRC,MAAO,MACPjJ,SAAU,SAAUkJ,GAClB,OAAOzc,EAAM0X,WAAa+E,EAAQnW,MAAMoW,UAAUtK,MAAQ,IACtD,IACA,GAENuK,QAAS,SAAUF,GACjB,QAASzc,EAAM0X,WAAa+E,EAAQnW,MAAMoW,UAAUtK,MAAQ,MAE9DwK,UAAW,SAAU9b,EAAO2b,GAG1B,IAAM1B,EAAgB0B,EAAQnW,MAAMY,KAAKE,SACtCI,KAAI,SAACqV,GAAD,OAAOA,EAAE3V,KAAKuV,EAAQK,cAC1BhH,QAAO,SAACiF,EAAOja,GAAR,OAAkBga,EAAOC,EAAOja,KAAQ,GAClD,OAAO2b,EAAQM,eACb/c,EAAMwa,kBAAkB3X,OAAS,GAAKkY,EAAQ,EAC5C,EAAmB/a,EAAMsa,cAAeS,GAAO,GAC/C,OAGRiC,OAAQ,CACNL,SAAS,GAEXM,QAAS,CACPC,YAAa,CACXC,WAAW,EACXC,KAAM,SAERrV,OAAQ,SAAUsV,GAChB,MAAsC,MAA/BA,EAAYC,gBAErBC,UAAW,CACTvW,MAAO,SAAUyV,GACf,IAAIzV,EAAQgL,EAAE,UAAD,OAAWyK,EAAQpU,QAAQrB,MAA3B,YAA6C,GAU1D,OATIA,IACFA,GAAS,MAEc,OAArByV,EAAQe,OAAOzB,IACjB/U,GAAS,EACPhH,EAAMsa,cACNmC,EAAQe,OAAOzB,IAGZ/U,GAETyW,OAAQ,SAAUC,GAChB,IAAIC,EAAM,EAIV,OAHAD,EAAalW,KAAI,SAAC6V,GAChBM,GAAON,EAAYG,OAAOzB,KAG1B,UAAG/J,EAAE,oBAAL,MACA,EAAmBhS,EAAMsa,cAAeqD,WAOpD,EAA0B,yBAAY,CACpC3C,YACA1M,YAFMsP,EAAR,EAAQA,cAIR,MAAO,CAAEA,oBCpJf,EAAO/b,OAAS,EAED,Q,oCCsBE,+BAAgB,CAC7B9B,KAAM,iBACN0P,WAAY,CACVoO,SAEF7d,MAAO,CACL0H,OAAQ,CACNnI,KAAMgL,OACNrL,UAAU,GAEZmK,KAAM,CACJ9J,KAAMgL,OACNrL,UAAU,GAEZ4J,YAAa,CACXvJ,KAAMgL,OACNrL,UAAU,GAEZsb,kBAAmB,CACjBjb,KAAMmK,MACNvJ,QAAS,iBAAM,KAEjBuX,UAAW,CACTnY,KAAMsP,QACN1O,SAAS,GAEXia,kBAAmB,CACjB7a,KAAMsP,QACN1O,SAAS,IAGbC,MA/B6B,SA+BvBJ,GACJ,IAAMM,EAAQ,OAAAC,EAAA,QAEV+Z,EAA6C,iBAAI,kBAC/CwD,EAA8C,uBAClD,kBAAMxd,EAAMG,QAAQ,OAAYC,QAAQqd,eAEpCC,EAAoD,uBAAS,kBACjE,eACEhe,EAAM8I,YACN9I,EAAMqJ,KAAK4H,MACXjR,EAAM0H,OACN1H,EAAMwa,kBACNsD,EAAWhd,UAQf,SAASmd,EAActJ,GACrBrU,EAAMY,SAAS,OAAYC,QAAQ+c,eAAgB,CACjD9e,SAAUY,EAAMqJ,KAAKjK,SACrB+e,WAAY,UACZ1X,OAAQkO,IAGZ,SAAS4F,EACP7G,GAIA4G,EAAcxZ,MAAQ4S,EAAMhQ,OAAO3D,KAErC,SAASqe,EACPtV,EACAO,GAEA,MAAO,CACLa,KAAM,OAAA/B,EAAA,MAAOW,EAAYzF,MAAO,cAChCxD,GAAI,OAAAsI,EAAA,MAAOW,EAAYxF,IAAK,cAC5B+a,KAC2B,SAAzBvV,EAAYlC,SAAZ,cACWyC,EAAK4H,MAAQ,IAAM,IAC1BnI,EAAYlC,UAWtB,OAvCA,4BAAc,kBACZqX,EAAcG,EAAape,EAAM8I,YAAa9I,EAAMqJ,UA+BtD,oBACE,kBAAMrJ,EAAM8I,cADT,yDAEH,WAAOwV,GAAP,iFACEL,EAAcG,EAAaE,EAAWte,EAAMqJ,OAD9C,2CAFG,uDAOE,CACLjC,SAAU,uBACR,kBAAM4W,EAAeld,MAAMsG,SAASkT,EAAcxZ,UAEpDkH,OAAQ,uBAAS,kBAAMgW,EAAeld,MAAMkH,UAC5CqS,WAAY,uBAAS,kBAA+C,IAAzC9P,OAAO3F,KAAKkZ,EAAWhd,OAAO+B,UACzDyX,gBACAC,wB,UCpHR,EAAO1Y,OAASA,EAChB,EAAOC,UAAY,kBAEJ,U,gFCPf,IAAIyB,EAAI,EAAQ,QACZ0V,EAAW,EAAQ,QACnBrP,EAAU,EAAQ,QAClB2U,EAAkB,EAAQ,QAC1Bxc,EAAW,EAAQ,QACnBuC,EAAkB,EAAQ,QAC1Bka,EAAiB,EAAQ,QACzBC,EAAkB,EAAQ,QAC1BC,EAA+B,EAAQ,QAEvCC,EAAsBD,EAA6B,SAEnDE,EAAUH,EAAgB,WAC1BI,EAAc,GAAG3b,MACjB4b,EAAM3c,KAAK2c,IAKfvb,EAAE,CAAEG,OAAQ,QAASC,OAAO,EAAMC,QAAS+a,GAAuB,CAChEzb,MAAO,SAAeG,EAAOC,GAC3B,IAKIyb,EAAaja,EAAQwF,EALrBnG,EAAIG,EAAgBR,MACpBjB,EAASd,EAASoC,EAAEtB,QACpBmc,EAAIT,EAAgBlb,EAAOR,GAC3Boc,EAAMV,OAAwBxb,IAARO,EAAoBT,EAASS,EAAKT,GAG5D,GAAI+G,EAAQzF,KACV4a,EAAc5a,EAAEuG,YAEU,mBAAfqU,GAA8BA,IAAgBrV,QAASE,EAAQmV,EAAYvU,WAE3EyO,EAAS8F,KAClBA,EAAcA,EAAYH,GACN,OAAhBG,IAAsBA,OAAchc,IAHxCgc,OAAchc,EAKZgc,IAAgBrV,YAAyB3G,IAAhBgc,GAC3B,OAAOF,EAAY5b,KAAKkB,EAAG6a,EAAGC,GAIlC,IADAna,EAAS,SAAqB/B,IAAhBgc,EAA4BrV,MAAQqV,GAAaD,EAAIG,EAAMD,EAAG,IACvE1U,EAAI,EAAG0U,EAAIC,EAAKD,IAAK1U,IAAS0U,KAAK7a,GAAGqa,EAAe1Z,EAAQwF,EAAGnG,EAAE6a,IAEvE,OADAla,EAAOjC,OAASyH,EACTxF,M","file":"static/js/main.597d0b47.js","sourcesContent":["<template>\n <div id=\"user-auth-form\">\n <div id=\"user-form\">\n <div\n class=\"form-box\"\n :class=\"{\n disabled: registration_disabled,\n }\"\n >\n <AlertMessage\n message=\"user.REGISTER_DISABLED\"\n v-if=\"registration_disabled\"\n />\n <form @submit.prevent=\"onSubmit(action)\">\n <div class=\"form-items\">\n <input\n v-if=\"action === 'register'\"\n id=\"username\"\n :disabled=\"registration_disabled\"\n required\n v-model=\"formData.username\"\n :placeholder=\"$t('user.USERNAME')\"\n />\n <input\n v-if=\"action !== 'reset'\"\n id=\"email\"\n :disabled=\"registration_disabled\"\n required\n type=\"email\"\n v-model=\"formData.email\"\n :placeholder=\"\n action === 'reset-request'\n ? $t('user.ENTER_EMAIL')\n : $t('user.EMAIL')\n \"\n />\n <input\n v-if=\"action !== 'reset-request'\"\n id=\"password\"\n :disabled=\"registration_disabled\"\n required\n type=\"password\"\n v-model=\"formData.password\"\n :placeholder=\"\n action === 'reset'\n ? $t('user.ENTER_PASSWORD')\n : $t('user.PASSWORD')\n \"\n />\n <input\n v-if=\"['register', 'reset'].includes(action)\"\n id=\"confirm-password\"\n :disabled=\"registration_disabled\"\n type=\"password\"\n required\n v-model=\"formData.password_conf\"\n :placeholder=\"\n action === 'reset'\n ? $t('user.ENTER_PASSWORD_CONFIRMATION')\n : $t('user.PASSWORD_CONFIRM')\n \"\n />\n </div>\n <button type=\"submit\" :disabled=\"registration_disabled\">\n {{ $t(buttonText) }}\n </button>\n </form>\n <div v-if=\"action === 'login'\">\n <router-link class=\"password-forgotten\" to=\"/password-reset/request\">\n {{ $t('user.PASSWORD_FORGOTTEN') }}\n </router-link>\n </div>\n <ErrorMessage :message=\"errorMessages\" v-if=\"errorMessages\" />\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { ComputedRef, computed, defineComponent, reactive, watch } from 'vue'\n import { useRoute } from 'vue-router'\n\n import { ROOT_STORE, USER_STORE } from '@/store/constants'\n import { TAppConfig } from '@/types/application'\n import { ILoginRegisterFormData } from '@/types/user'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'UserAuthForm',\n props: {\n action: {\n type: String,\n required: true,\n },\n token: {\n type: String,\n default: '',\n },\n },\n setup(props) {\n const formData: ILoginRegisterFormData = reactive({\n username: '',\n email: '',\n password: '',\n password_conf: '',\n })\n const route = useRoute()\n const store = useStore()\n\n const buttonText: ComputedRef<string> = computed(() =>\n getButtonText(props.action)\n )\n const errorMessages: ComputedRef<string | string[] | null> = computed(\n () => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]\n )\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const registration_disabled: ComputedRef<boolean> = computed(\n () =>\n props.action === 'register' &&\n !appConfig.value.is_registration_enabled\n )\n\n function getButtonText(action: string): string {\n switch (action) {\n case 'reset-request':\n case 'reset':\n return 'buttons.SUBMIT'\n default:\n return `buttons.${props.action.toUpperCase()}`\n }\n }\n function onSubmit(actionType: string) {\n switch (actionType) {\n case 'reset':\n if (!props.token) {\n return store.commit(\n ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES,\n 'user.INVALID_TOKEN'\n )\n }\n return store.dispatch(USER_STORE.ACTIONS.RESET_USER_PASSWORD, {\n password: formData.password,\n password_conf: formData.password_conf,\n token: props.token,\n })\n case 'reset-request':\n return store.dispatch(\n USER_STORE.ACTIONS.SEND_PASSWORD_RESET_REQUEST,\n {\n email: formData.email,\n }\n )\n default:\n store.dispatch(USER_STORE.ACTIONS.LOGIN_OR_REGISTER, {\n actionType,\n formData,\n })\n }\n }\n function resetFormData() {\n formData.username = ''\n formData.email = ''\n formData.password = ''\n formData.password_conf = ''\n }\n watch(\n () => route.path,\n async () => {\n store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)\n resetFormData()\n }\n )\n return {\n appConfig,\n buttonText,\n errorMessages,\n formData,\n registration_disabled,\n onSubmit,\n }\n },\n })\n</script>\n\n<style scoped lang=\"scss\">\n @import '~@/scss/base';\n\n #user-auth-form {\n display: flex;\n align-items: center;\n\n margin: $default-margin 0;\n height: 100%;\n\n #user-form {\n width: 60%;\n\n .password-forgotten {\n font-size: 0.9em;\n font-style: italic;\n padding-left: $default-padding;\n }\n\n button {\n margin: $default-margin;\n border: solid 1px var(--app-color);\n\n &:disabled {\n border-color: var(--disabled-color);\n }\n }\n }\n\n @media screen and (max-width: $medium-limit) {\n height: auto;\n margin-bottom: 50px;\n\n #user-form {\n margin-top: $default-margin;\n width: 100%;\n }\n }\n }\n</style>\n","\n import { ComputedRef, computed, defineComponent, reactive, watch } from 'vue'\n import { useRoute } from 'vue-router'\n\n import { ROOT_STORE, USER_STORE } from '@/store/constants'\n import { TAppConfig } from '@/types/application'\n import { ILoginRegisterFormData } from '@/types/user'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'UserAuthForm',\n props: {\n action: {\n type: String,\n required: true,\n },\n token: {\n type: String,\n default: '',\n },\n },\n setup(props) {\n const formData: ILoginRegisterFormData = reactive({\n username: '',\n email: '',\n password: '',\n password_conf: '',\n })\n const route = useRoute()\n const store = useStore()\n\n const buttonText: ComputedRef<string> = computed(() =>\n getButtonText(props.action)\n )\n const errorMessages: ComputedRef<string | string[] | null> = computed(\n () => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]\n )\n const appConfig: ComputedRef<TAppConfig> = computed(\n () => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]\n )\n const registration_disabled: ComputedRef<boolean> = computed(\n () =>\n props.action === 'register' &&\n !appConfig.value.is_registration_enabled\n )\n\n function getButtonText(action: string): string {\n switch (action) {\n case 'reset-request':\n case 'reset':\n return 'buttons.SUBMIT'\n default:\n return `buttons.${props.action.toUpperCase()}`\n }\n }\n function onSubmit(actionType: string) {\n switch (actionType) {\n case 'reset':\n if (!props.token) {\n return store.commit(\n ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES,\n 'user.INVALID_TOKEN'\n )\n }\n return store.dispatch(USER_STORE.ACTIONS.RESET_USER_PASSWORD, {\n password: formData.password,\n password_conf: formData.password_conf,\n token: props.token,\n })\n case 'reset-request':\n return store.dispatch(\n USER_STORE.ACTIONS.SEND_PASSWORD_RESET_REQUEST,\n {\n email: formData.email,\n }\n )\n default:\n store.dispatch(USER_STORE.ACTIONS.LOGIN_OR_REGISTER, {\n actionType,\n formData,\n })\n }\n }\n function resetFormData() {\n formData.username = ''\n formData.email = ''\n formData.password = ''\n formData.password_conf = ''\n }\n watch(\n () => route.path,\n async () => {\n store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)\n resetFormData()\n }\n )\n return {\n appConfig,\n buttonText,\n errorMessages,\n formData,\n registration_disabled,\n onSubmit,\n }\n },\n })\n","import { render } from \"./UserAuthForm.vue?vue&type=template&id=7717f19a&scoped=true\"\nimport script from \"./UserAuthForm.vue?vue&type=script&lang=ts\"\nexport * from \"./UserAuthForm.vue?vue&type=script&lang=ts\"\n\nimport \"./UserAuthForm.vue?vue&type=style&index=0&id=7717f19a&scoped=true&lang=scss\"\nscript.render = render\nscript.__scopeId = \"data-v-7717f19a\"\n\nexport default script","// https://github.com/tc39/proposal-string-pad-start-end\nvar toLength = require('../internals/to-length');\nvar repeat = require('../internals/string-repeat');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\n\nvar ceil = Math.ceil;\n\n// `String.prototype.{ padStart, padEnd }` methods implementation\nvar createMethod = function (IS_END) {\n return function ($this, maxLength, fillString) {\n var S = String(requireObjectCoercible($this));\n var stringLength = S.length;\n var fillStr = fillString === undefined ? ' ' : String(fillString);\n var intMaxLength = toLength(maxLength);\n var fillLen, stringFiller;\n if (intMaxLength <= stringLength || fillStr == '') return S;\n fillLen = intMaxLength - stringLength;\n stringFiller = repeat.call(fillStr, ceil(fillLen / fillStr.length));\n if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);\n return IS_END ? S + stringFiller : stringFiller + S;\n };\n};\n\nmodule.exports = {\n // `String.prototype.padStart` method\n // https://tc39.es/ecma262/#sec-string.prototype.padstart\n start: createMethod(false),\n // `String.prototype.padEnd` method\n // https://tc39.es/ecma262/#sec-string.prototype.padend\n end: createMethod(true)\n};\n","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CalendarWorkoutsChart.vue?vue&type=style&index=0&id=b30dea28&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CalendarWorkouts.vue?vue&type=style&index=0&id=3822f77d&lang=scss\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./UserMonthStats.vue?vue&type=style&index=0&id=7958b39f&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CalendarCells.vue?vue&type=style&index=0&id=17e3f666&lang=scss\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./RecordsCard.vue?vue&type=style&index=0&id=db29ce96&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CalendarWorkout.vue?vue&type=style&index=0&id=cf219d62&lang=scss\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./WorkoutCard.vue?vue&type=style&index=0&id=7846af32&lang=scss&scoped=true\"","'use strict';\nvar $ = require('../internals/export');\nvar $padStart = require('../internals/string-pad').start;\nvar WEBKIT_BUG = require('../internals/string-pad-webkit-bug');\n\n// `String.prototype.padStart` method\n// https://tc39.es/ecma262/#sec-string.prototype.padstart\n$({ target: 'String', proto: true, forced: WEBKIT_BUG }, {\n padStart: function padStart(maxLength /* , fillString = ' ' */) {\n return $padStart(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);\n }\n});\n","var $ = require('../internals/export');\nvar $entries = require('../internals/object-to-array').entries;\n\n// `Object.entries` method\n// https://tc39.es/ecma262/#sec-object.entries\n$({ target: 'Object', stat: true }, {\n entries: function entries(O) {\n return $entries(O);\n }\n});\n","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=0f5eddb2&lang=scss\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CalendarDays.vue?vue&type=style&index=0&id=8c842a34&lang=scss\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./BikePic.vue?vue&type=style&index=0&id=645e8c6f&scoped=true&lang=scss\"","var DESCRIPTORS = require('../internals/descriptors');\nvar objectKeys = require('../internals/object-keys');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar propertyIsEnumerable = require('../internals/object-property-is-enumerable').f;\n\n// `Object.{ entries, values }` methods implementation\nvar createMethod = function (TO_ENTRIES) {\n return function (it) {\n var O = toIndexedObject(it);\n var keys = objectKeys(O);\n var length = keys.length;\n var i = 0;\n var result = [];\n var key;\n while (length > i) {\n key = keys[i++];\n if (!DESCRIPTORS || propertyIsEnumerable.call(O, key)) {\n result.push(TO_ENTRIES ? [key, O[key]] : O[key]);\n }\n }\n return result;\n };\n};\n\nmodule.exports = {\n // `Object.entries` method\n // https://tc39.es/ecma262/#sec-object.entries\n entries: createMethod(true),\n // `Object.values` method\n // https://tc39.es/ecma262/#sec-object.values\n values: createMethod(false)\n};\n","import toInteger from \"../_lib/toInteger/index.js\";\nimport addYears from \"../addYears/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name subYears\n * @category Year Helpers\n * @summary Subtract the specified number of years from the given date.\n *\n * @description\n * Subtract the specified number of years from the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of years to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the years subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 5 years from 1 September 2014:\n * const result = subYears(new Date(2014, 8, 1), 5)\n * //=> Tue Sep 01 2009 00:00:00\n */\n\nexport default function subYears(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n return addYears(dirtyDate, -amount);\n}","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name endOfYear\n * @category Year Helpers\n * @summary Return the end of a year for the given date.\n *\n * @description\n * Return the end of a year for the given date.\n * The result will be in the local timezone.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the end of a year\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The end of a year for 2 September 2014 11:55:00:\n * var result = endOfYear(new Date(2014, 8, 2, 11, 55, 00))\n * //=> Wed Dec 31 2014 23:59:59.999\n */\n\nexport default function endOfYear(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n var year = date.getFullYear();\n date.setFullYear(year + 1, 0, 0);\n date.setHours(23, 59, 59, 999);\n return date;\n}","import toInteger from \"../_lib/toInteger/index.js\";\nimport addDays from \"../addDays/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name addWeeks\n * @category Week Helpers\n * @summary Add the specified number of weeks to the given date.\n *\n * @description\n * Add the specified number of week to the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of weeks to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the weeks added\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Add 4 weeks to 1 September 2014:\n * const result = addWeeks(new Date(2014, 8, 1), 4)\n * //=> Mon Sep 29 2014 00:00:00\n */\n\nexport default function addWeeks(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n var days = amount * 7;\n return addDays(dirtyDate, days);\n}","import toInteger from \"../_lib/toInteger/index.js\";\nimport addWeeks from \"../addWeeks/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name subWeeks\n * @category Week Helpers\n * @summary Subtract the specified number of weeks from the given date.\n *\n * @description\n * Subtract the specified number of weeks from the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of weeks to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the weeks subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 4 weeks from 1 September 2014:\n * const result = subWeeks(new Date(2014, 8, 1), 4)\n * //=> Mon Aug 04 2014 00:00:00\n */\n\nexport default function subWeeks(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n return addWeeks(dirtyDate, -amount);\n}","import {\n addMonths,\n addWeeks,\n addYears,\n endOfMonth,\n endOfWeek,\n endOfYear,\n format,\n startOfMonth,\n startOfWeek,\n startOfYear,\n subMonths,\n subWeeks,\n subYears,\n} from 'date-fns'\n\nimport { IChartDataset } from '@/types/chart'\nimport { ISport } from '@/types/sports'\nimport {\n IStatisticsChartData,\n IStatisticsDateParams,\n TStatisticsDatasetKeys,\n TStatisticsDatasets,\n TStatisticsFromApi,\n} from '@/types/statistics'\nimport { incrementDate, getStartDate } from '@/utils/dates'\nimport { sportColors } from '@/utils/sports'\n\nconst dateFormats: Record<string, Record<string, string>> = {\n week: {\n api: 'yyyy-MM-dd',\n chart: 'dd/MM/yyyy',\n },\n month: {\n api: 'yyyy-MM',\n chart: 'MM/yyyy',\n },\n year: {\n api: 'yyyy',\n chart: 'yyyy',\n },\n}\n\nexport const datasetKeys: TStatisticsDatasetKeys[] = [\n 'nb_workouts',\n 'total_duration',\n 'total_distance',\n]\n\nexport const getDateKeys = (\n params: IStatisticsDateParams,\n weekStartingMonday: boolean\n): Date[] => {\n const days = []\n for (\n let day = getStartDate(params.duration, params.start, weekStartingMonday);\n day <= params.end;\n day = incrementDate(params.duration, day)\n ) {\n days.push(day)\n }\n return days\n}\n\nconst getStatisticsChartDataset = (\n sportLabel: string,\n color: string\n): IChartDataset => {\n return {\n label: sportLabel,\n backgroundColor: [color],\n data: [],\n }\n}\n\nexport const getDatasets = (displayedSports: ISport[]): TStatisticsDatasets => {\n const datasets: TStatisticsDatasets = {\n nb_workouts: [],\n total_distance: [],\n total_duration: [],\n }\n displayedSports.map((sport) => {\n const color = sportColors[sport.label]\n datasets.nb_workouts.push(getStatisticsChartDataset(sport.label, color))\n datasets.total_distance.push(getStatisticsChartDataset(sport.label, color))\n datasets.total_duration.push(getStatisticsChartDataset(sport.label, color))\n })\n return datasets\n}\n\nexport const formatStats = (\n params: IStatisticsDateParams,\n weekStartingMonday: boolean,\n sports: ISport[],\n displayedSportsId: number[],\n apiStats: TStatisticsFromApi\n): IStatisticsChartData => {\n const dayKeys = getDateKeys(params, weekStartingMonday)\n const dateFormat = dateFormats[params.duration]\n const displayedSports = sports.filter((sport) =>\n displayedSportsId.includes(sport.id)\n )\n const labels: string[] = []\n const datasets = getDatasets(displayedSports)\n const sportsId: Record<string, number> = {}\n displayedSports.map(\n (displayedSport) => (sportsId[displayedSport.label] = displayedSport.id)\n )\n\n dayKeys.map((key) => {\n const date: string = format(key, dateFormat.api)\n const label: string = format(key, dateFormat.chart)\n labels.push(label)\n datasetKeys.map((datasetKey) => {\n datasets[datasetKey].map((dataset) => {\n dataset.data.push(\n apiStats !== {} &&\n date in apiStats &&\n sportsId[dataset.label] in apiStats[date]\n ? apiStats[date][sportsId[dataset.label]][datasetKey]\n : 0\n )\n })\n })\n })\n return {\n labels,\n datasets,\n }\n}\n\nexport const getStatsDateParams = (\n date: Date,\n timeFrame: string,\n weekStartingMonday: boolean\n): IStatisticsDateParams => {\n const weekStartsOn = weekStartingMonday ? 1 : 0\n const start =\n timeFrame === 'year'\n ? startOfYear(subYears(date, 9))\n : timeFrame === 'week'\n ? startOfWeek(subMonths(date, 2), { weekStartsOn })\n : startOfMonth(subMonths(date, 11)) // month\n const end =\n timeFrame === 'year'\n ? endOfYear(date)\n : timeFrame === 'week'\n ? endOfWeek(date, { weekStartsOn })\n : endOfMonth(date) // month\n return {\n duration: timeFrame,\n end,\n start,\n }\n}\n\nexport const updateChartParams = (\n chartParams: IStatisticsDateParams,\n backward: boolean,\n weekStartingMonday: boolean\n): IStatisticsDateParams => {\n const { duration, start, end } = chartParams\n const weekStartsOn = weekStartingMonday ? 1 : 0\n return {\n duration,\n end:\n duration === 'year'\n ? endOfYear(backward ? subYears(end, 1) : addYears(end, 1))\n : duration === 'week'\n ? endOfWeek(backward ? subWeeks(end, 1) : addWeeks(end, 1), {\n weekStartsOn,\n })\n : endOfMonth(backward ? subMonths(end, 1) : addMonths(end, 1)),\n start:\n duration === 'year'\n ? startOfYear(backward ? subYears(start, 1) : addYears(start, 1))\n : duration === 'week'\n ? startOfWeek(backward ? subWeeks(start, 1) : addWeeks(start, 1), {\n weekStartsOn,\n })\n : startOfMonth(backward ? subMonths(start, 1) : addMonths(start, 1)),\n }\n}\n","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=dad311d4&lang=scss&scoped=true\"","<template>\n <div id=\"dashboard\" v-if=\"authUser.username && sports.length > 0\">\n <div class=\"container mobile-menu\">\n <div class=\"box\">\n <div\n class=\"mobile-menu-item\"\n :class=\"{ 'is-selected': isSelected === 'chart' }\"\n @click=\"updateDisplayColumn('chart')\"\n >\n <i class=\"fa fa-bar-chart\" aria-hidden=\"true\" />\n </div>\n <div\n class=\"mobile-menu-item\"\n :class=\"{ 'is-selected': isSelected === 'calendar' }\"\n @click=\"updateDisplayColumn('calendar')\"\n >\n <i class=\"fa fa-calendar\" aria-hidden=\"true\" />\n </div>\n <div\n class=\"mobile-menu-item\"\n :class=\"{ 'is-selected': isSelected === 'timeline' }\"\n @click=\"updateDisplayColumn('timeline')\"\n >\n <i class=\"fa fa-map-o\" aria-hidden=\"true\" />\n </div>\n <div\n class=\"mobile-menu-item\"\n :class=\"{ 'is-selected': isSelected === 'records' }\"\n @click=\"updateDisplayColumn('records')\"\n >\n <i class=\"fa fa-trophy\" aria-hidden=\"true\" />\n </div>\n </div>\n </div>\n <div class=\"container\">\n <UserStatsCards :user=\"authUser\" />\n </div>\n <div class=\"container dashboard-container\">\n <div class=\"left-container dashboard-sub-container\">\n <UserMonthStats\n :sports=\"sports\"\n :user=\"authUser\"\n :class=\"{ 'is-hidden': !(isSelected === 'chart') }\"\n />\n <UserRecords\n :sports=\"sports\"\n :user=\"authUser\"\n :class=\"{ 'is-hidden': !(isSelected === 'records') }\"\n />\n </div>\n <div class=\"right-container dashboard-sub-container\">\n <UserCalendar\n :sports=\"sports\"\n :user=\"authUser\"\n :class=\"{ 'is-hidden': !(isSelected === 'calendar') }\"\n />\n <Timeline\n :sports=\"sports\"\n :user=\"authUser\"\n :class=\"{ 'is-hidden': !(isSelected === 'timeline') }\"\n />\n </div>\n </div>\n <div id=\"bottom\" />\n </div>\n <div v-else class=\"app-loading\">\n <Loader />\n </div>\n</template>\n\n<script lang=\"ts\">\n import {\n ComputedRef,\n Ref,\n computed,\n defineComponent,\n ref,\n onUnmounted,\n } from 'vue'\n\n import Timeline from '@/components/Dashboard/Timeline.vue'\n import UserCalendar from '@/components/Dashboard/UserCalendar/index.vue'\n import UserMonthStats from '@/components/Dashboard/UserMonthStats.vue'\n import UserRecords from '@/components/Dashboard/UserRecords/index.vue'\n import UserStatsCards from '@/components/Dashboard/UserStatsCards/index.vue'\n import { SPORTS_STORE, USER_STORE, WORKOUTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'Dashboard',\n components: {\n Timeline,\n UserCalendar,\n UserMonthStats,\n UserRecords,\n UserStatsCards,\n },\n setup() {\n const store = useStore()\n const authUser: ComputedRef<IUserProfile> = computed(\n () => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]\n )\n const sports: ComputedRef<ISport[]> = computed(\n () => store.getters[SPORTS_STORE.GETTERS.SPORTS]\n )\n const isSelected: Ref<string> = ref('chart')\n onUnmounted(() => {\n store.commit(WORKOUTS_STORE.MUTATIONS.EMPTY_WORKOUTS)\n })\n\n function updateDisplayColumn(target: string) {\n isSelected.value = target\n }\n\n return { authUser, sports, isSelected, updateDisplayColumn }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n #dashboard {\n padding-bottom: 30px;\n .dashboard-container {\n display: flex;\n flex-direction: row;\n\n .dashboard-sub-container {\n display: flex;\n flex-direction: column;\n }\n\n .left-container {\n width: 32%;\n }\n\n .right-container {\n width: 68%;\n }\n }\n .mobile-menu {\n display: none;\n }\n\n @media screen and (max-width: $medium-limit) {\n padding-bottom: 60px;\n .dashboard-container {\n display: flex;\n flex-direction: column;\n\n .left-container {\n width: 100%;\n }\n\n .right-container {\n width: 100%;\n }\n }\n .mobile-menu {\n display: flex;\n .box {\n display: flex;\n justify-content: space-between;\n padding: 0;\n width: 100%;\n\n .mobile-menu-item {\n display: flex;\n justify-content: space-around;\n border: none;\n border-radius: $border-radius;\n box-shadow: none;\n font-size: 0.95em;\n padding: $default-padding;\n width: 25%;\n\n .fa-trophy {\n color: var(--app-color);\n }\n &.is-selected {\n .fa-trophy {\n color: var(--mobile-menu-selected-color);\n }\n color: var(--mobile-menu-selected-color);\n background-color: var(--mobile-menu-selected-bgcolor);\n }\n }\n }\n }\n .is-hidden {\n display: none;\n }\n }\n }\n</style>\n","export default function _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n\n for (var i = 0, arr2 = new Array(len); i < len; i++) {\n arr2[i] = arr[i];\n }\n\n return arr2;\n}","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nexport default function _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) return arrayLikeToArray(arr);\n}","export default function _iterableToArray(iter) {\n if (typeof Symbol !== \"undefined\" && iter[Symbol.iterator] != null || iter[\"@@iterator\"] != null) return Array.from(iter);\n}","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nexport default function _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(o);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen);\n}","export default function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}","import arrayWithoutHoles from \"./arrayWithoutHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableSpread from \"./nonIterableSpread.js\";\nexport default function _toConsumableArray(arr) {\n return arrayWithoutHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableSpread();\n}","<template>\n <div id=\"timeline\">\n <div class=\"section-title\">{{ $t('workouts.LATEST_WORKOUTS') }}</div>\n <div v-if=\"user.nb_workouts > 0 && workouts.length === 0\">\n <WorkoutCard\n v-for=\"index in [...Array(initWorkoutsCount).keys()]\"\n :user=\"user\"\n :key=\"index\"\n />\n </div>\n <div v-else>\n <WorkoutCard\n v-for=\"workout in workouts\"\n :workout=\"workout\"\n :sport=\"\n workouts.length > 0\n ? sports.filter((s) => s.id === workout.sport_id)[0]\n : null\n \"\n :user=\"user\"\n :key=\"workout.id\"\n />\n <NoWorkouts v-if=\"workouts.length === 0\" />\n <div v-if=\"moreWorkoutsExist\" class=\"more-workouts\">\n <button @click=\"loadMoreWorkouts\">\n {{ $t('workouts.LOAD_MORE_WORKOUT') }}\n </button>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import {\n ComputedRef,\n PropType,\n computed,\n defineComponent,\n ref,\n onBeforeMount,\n } from 'vue'\n\n import WorkoutCard from '@/components/Workout/WorkoutCard.vue'\n import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'\n import { WORKOUTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { IWorkout } from '@/types/workouts'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'Timeline',\n components: {\n NoWorkouts,\n WorkoutCard,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n\n let page = ref(1)\n const per_page = 5\n const initWorkoutsCount =\n props.user.nb_workouts >= per_page ? per_page : props.user.nb_workouts\n onBeforeMount(() => loadWorkouts())\n\n const workouts: ComputedRef<IWorkout[]> = computed(\n () => store.getters[WORKOUTS_STORE.GETTERS.USER_WORKOUTS]\n )\n const moreWorkoutsExist: ComputedRef<boolean> = computed(() =>\n workouts.value.length > 0\n ? workouts.value[workouts.value.length - 1].previous_workout !== null\n : false\n )\n\n function loadWorkouts() {\n store.dispatch(WORKOUTS_STORE.ACTIONS.GET_USER_WORKOUTS, {\n page: page.value,\n per_page,\n })\n }\n function loadMoreWorkouts() {\n page.value += 1\n store.dispatch(WORKOUTS_STORE.ACTIONS.GET_MORE_USER_WORKOUTS, {\n page: page.value,\n per_page,\n })\n }\n\n return {\n initWorkoutsCount,\n moreWorkoutsExist,\n per_page,\n workouts,\n loadMoreWorkouts,\n }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n #timeline {\n margin-bottom: 20px;\n\n .more-workouts {\n display: flex;\n justify-content: center;\n }\n }\n</style>\n","<template>\n <div class=\"timeline-workout\">\n <div class=\"box\">\n <div class=\"workout-user-date\">\n <div class=\"workout-user\">\n <img\n class=\"profile-img\"\n v-if=\"userPictureUrl !== ''\"\n :alt=\"$t('user.USER_PICTURE')\"\n :src=\"userPictureUrl\"\n />\n <div v-else class=\"no-picture\">\n <i class=\"fa fa-user-circle-o\" aria-hidden=\"true\" />\n </div>\n <span v-if=\"user.username\" class=\"workout-user-name\">\n {{ user.username }}\n </span>\n </div>\n <div\n class=\"workout-date\"\n v-if=\"workout && user\"\n :title=\"\n format(\n getDateWithTZ(workout.workout_date, user.timezone),\n 'dd/MM/yyyy HH:mm'\n )\n \"\n >\n {{\n formatDistance(new Date(workout.workout_date), new Date(), {\n addSuffix: true,\n locale,\n })\n }}\n </div>\n </div>\n <div\n class=\"workout-map\"\n :class=\"{ 'no-cursor': !workout }\"\n @click=\"\n workout\n ? $router.push({\n name: 'Workout',\n params: { workoutId: workout.id },\n })\n : null\n \"\n >\n <div v-if=\"workout\">\n <StaticMap v-if=\"workout.with_gpx\" :workout=\"workout\" />\n <div v-else class=\"no-map\">\n {{ $t('workouts.NO_MAP') }}\n </div>\n </div>\n </div>\n <div\n class=\"workout-data\"\n @click=\"\n $router.push({ name: 'Workout', params: { workoutId: workout.id } })\n \"\n >\n <div>\n <SportImage v-if=\"sport\" :sport-label=\"sport.label\" />\n </div>\n <div>\n <i class=\"fa fa-clock-o\" aria-hidden=\"true\" />\n <span v-if=\"workout\">{{ workout.moving }}</span>\n </div>\n <div>\n <i class=\"fa fa-road\" aria-hidden=\"true\" />\n <span v-if=\"workout\">{{ workout.distance }} km</span>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { Locale, format, formatDistance } from 'date-fns'\n import { PropType, defineComponent, ComputedRef, computed } from 'vue'\n\n import StaticMap from '@/components/Common/StaticMap.vue'\n import { ROOT_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { IWorkout } from '@/types/workouts'\n import { useStore } from '@/use/useStore'\n import { getApiUrl } from '@/utils'\n import { getDateWithTZ } from '@/utils/dates'\n\n export default defineComponent({\n name: 'WorkoutCard',\n components: {\n StaticMap,\n },\n props: {\n workout: {\n type: Object as PropType<IWorkout>,\n required: false,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n sport: {\n type: Object as PropType<ISport>,\n required: false,\n },\n },\n setup(props) {\n const store = useStore()\n\n const userPictureUrl: ComputedRef<string> = computed(() =>\n props.user.picture\n ? `${getApiUrl()}/users/${props.user.username}/picture?${Date.now()}`\n : ''\n )\n const locale: ComputedRef<Locale> = computed(\n () => store.getters[ROOT_STORE.GETTERS.LOCALE]\n )\n\n return {\n format,\n formatDistance,\n getDateWithTZ,\n locale,\n userPictureUrl,\n }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n .timeline-workout {\n margin-bottom: $default-margin * 2;\n\n .box {\n flex-direction: column;\n padding: 0;\n .workout-user-date {\n display: flex;\n justify-content: space-between;\n padding: $default-padding * 0.5 $default-padding;\n .workout-user {\n display: flex;\n .profile-img {\n border-radius: 50%;\n height: 25px;\n width: 25px;\n }\n .fa-user-circle-o {\n font-size: 1.5em;\n }\n .workout-user-name {\n padding-left: 5px;\n }\n }\n .workout-date {\n font-size: 0.85em;\n font-style: italic;\n }\n }\n\n .workout-map {\n background-color: var(--workout-no-map-bg-color);\n height: 150px;\n .no-map {\n line-height: 150px;\n }\n ::v-deep(.bg-map-image) {\n height: 150px;\n }\n }\n\n .workout-data {\n display: flex;\n padding: $default-padding * 0.5;\n font-size: 0.9em;\n .sport-img {\n height: 25px;\n width: 25px;\n }\n div {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 33%;\n }\n }\n\n .workout-map,\n .workout-data {\n cursor: pointer;\n }\n .no-cursor {\n cursor: default;\n }\n .fa {\n padding-right: $default-padding;\n }\n }\n }\n</style>\n","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name compareAsc\n * @category Common Helpers\n * @summary Compare the two dates and return -1, 0 or 1.\n *\n * @description\n * Compare the two dates and return 1 if the first date is after the second,\n * -1 if the first date is before the second or 0 if dates are equal.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the first date to compare\n * @param {Date|Number} dateRight - the second date to compare\n * @returns {Number} the result of the comparison\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Compare 11 February 1987 and 10 July 1989:\n * const result = compareAsc(new Date(1987, 1, 11), new Date(1989, 6, 10))\n * //=> -1\n *\n * @example\n * // Sort the array of dates:\n * const result = [\n * new Date(1995, 6, 2),\n * new Date(1987, 1, 11),\n * new Date(1989, 6, 10)\n * ].sort(compareAsc)\n * //=> [\n * // Wed Feb 11 1987 00:00:00,\n * // Mon Jul 10 1989 00:00:00,\n * // Sun Jul 02 1995 00:00:00\n * // ]\n */\n\nexport default function compareAsc(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var diff = dateLeft.getTime() - dateRight.getTime();\n\n if (diff < 0) {\n return -1;\n } else if (diff > 0) {\n return 1; // Return 0 if diff is 0; return NaN if diff is NaN\n } else {\n return diff;\n }\n}","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInCalendarMonths\n * @category Month Helpers\n * @summary Get the number of calendar months between the given dates.\n *\n * @description\n * Get the number of calendar months between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of calendar months\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many calendar months are between 31 January 2014 and 1 September 2014?\n * var result = differenceInCalendarMonths(\n * new Date(2014, 8, 1),\n * new Date(2014, 0, 31)\n * )\n * //=> 8\n */\n\nexport default function differenceInCalendarMonths(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var yearDiff = dateLeft.getFullYear() - dateRight.getFullYear();\n var monthDiff = dateLeft.getMonth() - dateRight.getMonth();\n return yearDiff * 12 + monthDiff;\n}","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name endOfDay\n * @category Day Helpers\n * @summary Return the end of a day for the given date.\n *\n * @description\n * Return the end of a day for the given date.\n * The result will be in the local timezone.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the end of a day\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The end of a day for 2 September 2014 11:55:00:\n * const result = endOfDay(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 02 2014 23:59:59.999\n */\n\nexport default function endOfDay(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n date.setHours(23, 59, 59, 999);\n return date;\n}","import toDate from \"../toDate/index.js\";\nimport endOfDay from \"../endOfDay/index.js\";\nimport endOfMonth from \"../endOfMonth/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isLastDayOfMonth\n * @category Month Helpers\n * @summary Is the given date the last day of a month?\n *\n * @description\n * Is the given date the last day of a month?\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to check\n * @returns {Boolean} the date is the last day of a month\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // Is 28 February 2014 the last day of a month?\n * var result = isLastDayOfMonth(new Date(2014, 1, 28))\n * //=> true\n */\n\nexport default function isLastDayOfMonth(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n return endOfDay(date).getTime() === endOfMonth(date).getTime();\n}","import toDate from \"../toDate/index.js\";\nimport differenceInCalendarMonths from \"../differenceInCalendarMonths/index.js\";\nimport compareAsc from \"../compareAsc/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nimport isLastDayOfMonth from \"../isLastDayOfMonth/index.js\";\n/**\n * @name differenceInMonths\n * @category Month Helpers\n * @summary Get the number of full months between the given dates.\n *\n * @description\n * Get the number of full months between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of full months\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many full months are between 31 January 2014 and 1 September 2014?\n * var result = differenceInMonths(new Date(2014, 8, 1), new Date(2014, 0, 31))\n * //=> 7\n */\n\nexport default function differenceInMonths(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n var sign = compareAsc(dateLeft, dateRight);\n var difference = Math.abs(differenceInCalendarMonths(dateLeft, dateRight));\n var result; // Check for the difference of less than month\n\n if (difference < 1) {\n result = 0;\n } else {\n if (dateLeft.getMonth() === 1 && dateLeft.getDate() > 27) {\n // This will check if the date is end of Feb and assign a higher end of month date\n // to compare it with Jan\n dateLeft.setDate(30);\n }\n\n dateLeft.setMonth(dateLeft.getMonth() - sign * difference); // Math.abs(diff in full months - diff in calendar months) === 1 if last calendar month is not full\n // If so, result must be decreased by 1 in absolute value\n\n var isLastMonthNotFull = compareAsc(dateLeft, dateRight) === -sign; // Check for cases of one full calendar month\n\n if (isLastDayOfMonth(toDate(dirtyDateLeft)) && difference === 1 && compareAsc(dirtyDateLeft, dateRight) === 1) {\n isLastMonthNotFull = false;\n }\n\n result = sign * (difference - Number(isLastMonthNotFull));\n } // Prevent negative zero\n\n\n return result === 0 ? 0 : result;\n}","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInMilliseconds\n * @category Millisecond Helpers\n * @summary Get the number of milliseconds between the given dates.\n *\n * @description\n * Get the number of milliseconds between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of milliseconds\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many milliseconds are between\n * // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?\n * const result = differenceInMilliseconds(\n * new Date(2014, 6, 2, 12, 30, 21, 700),\n * new Date(2014, 6, 2, 12, 30, 20, 600)\n * )\n * //=> 1100\n */\n\nexport default function differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n return dateLeft.getTime() - dateRight.getTime();\n}","import differenceInMilliseconds from \"../differenceInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name differenceInSeconds\n * @category Second Helpers\n * @summary Get the number of seconds between the given dates.\n *\n * @description\n * Get the number of seconds between the given dates.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the later date\n * @param {Date|Number} dateRight - the earlier date\n * @returns {Number} the number of seconds\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // How many seconds are between\n * // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?\n * const result = differenceInSeconds(\n * new Date(2014, 6, 2, 12, 30, 20, 0),\n * new Date(2014, 6, 2, 12, 30, 7, 999)\n * )\n * //=> 12\n */\n\nexport default function differenceInSeconds(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / 1000;\n return diff > 0 ? Math.floor(diff) : Math.ceil(diff);\n}","export default function assign(target, dirtyObject) {\n if (target == null) {\n throw new TypeError('assign requires that input parameter not be null or undefined');\n }\n\n dirtyObject = dirtyObject || {};\n\n for (var property in dirtyObject) {\n if (Object.prototype.hasOwnProperty.call(dirtyObject, property)) {\n target[property] = dirtyObject[property];\n }\n }\n\n return target;\n}","import assign from \"../assign/index.js\";\nexport default function cloneObject(dirtyObject) {\n return assign({}, dirtyObject);\n}","import compareAsc from \"../compareAsc/index.js\";\nimport differenceInMonths from \"../differenceInMonths/index.js\";\nimport differenceInSeconds from \"../differenceInSeconds/index.js\";\nimport defaultLocale from \"../locale/en-US/index.js\";\nimport toDate from \"../toDate/index.js\";\nimport cloneObject from \"../_lib/cloneObject/index.js\";\nimport getTimezoneOffsetInMilliseconds from \"../_lib/getTimezoneOffsetInMilliseconds/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\nvar MINUTES_IN_DAY = 1440;\nvar MINUTES_IN_ALMOST_TWO_DAYS = 2520;\nvar MINUTES_IN_MONTH = 43200;\nvar MINUTES_IN_TWO_MONTHS = 86400;\n/**\n * @name formatDistance\n * @category Common Helpers\n * @summary Return the distance between the given dates in words.\n *\n * @description\n * Return the distance between the given dates in words.\n *\n * | Distance between dates | Result |\n * |-------------------------------------------------------------------|---------------------|\n * | 0 ... 30 secs | less than a minute |\n * | 30 secs ... 1 min 30 secs | 1 minute |\n * | 1 min 30 secs ... 44 mins 30 secs | [2..44] minutes |\n * | 44 mins ... 30 secs ... 89 mins 30 secs | about 1 hour |\n * | 89 mins 30 secs ... 23 hrs 59 mins 30 secs | about [2..24] hours |\n * | 23 hrs 59 mins 30 secs ... 41 hrs 59 mins 30 secs | 1 day |\n * | 41 hrs 59 mins 30 secs ... 29 days 23 hrs 59 mins 30 secs | [2..30] days |\n * | 29 days 23 hrs 59 mins 30 secs ... 44 days 23 hrs 59 mins 30 secs | about 1 month |\n * | 44 days 23 hrs 59 mins 30 secs ... 59 days 23 hrs 59 mins 30 secs | about 2 months |\n * | 59 days 23 hrs 59 mins 30 secs ... 1 yr | [2..12] months |\n * | 1 yr ... 1 yr 3 months | about 1 year |\n * | 1 yr 3 months ... 1 yr 9 month s | over 1 year |\n * | 1 yr 9 months ... 2 yrs | almost 2 years |\n * | N yrs ... N yrs 3 months | about N years |\n * | N yrs 3 months ... N yrs 9 months | over N years |\n * | N yrs 9 months ... N+1 yrs | almost N+1 years |\n *\n * With `options.includeSeconds == true`:\n * | Distance between dates | Result |\n * |------------------------|----------------------|\n * | 0 secs ... 5 secs | less than 5 seconds |\n * | 5 secs ... 10 secs | less than 10 seconds |\n * | 10 secs ... 20 secs | less than 20 seconds |\n * | 20 secs ... 40 secs | half a minute |\n * | 40 secs ... 60 secs | less than a minute |\n * | 60 secs ... 90 secs | 1 minute |\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * - The function was renamed from `distanceInWords ` to `formatDistance`\n * to make its name consistent with `format` and `formatRelative`.\n *\n * - The order of arguments is swapped to make the function\n * consistent with `differenceIn...` functions.\n *\n * ```javascript\n * // Before v2.0.0\n *\n * distanceInWords(\n * new Date(1986, 3, 4, 10, 32, 0),\n * new Date(1986, 3, 4, 11, 32, 0),\n * { addSuffix: true }\n * ) //=> 'in about 1 hour'\n *\n * // v2.0.0 onward\n *\n * formatDistance(\n * new Date(1986, 3, 4, 11, 32, 0),\n * new Date(1986, 3, 4, 10, 32, 0),\n * { addSuffix: true }\n * ) //=> 'in about 1 hour'\n * ```\n *\n * @param {Date|Number} date - the date\n * @param {Date|Number} baseDate - the date to compare with\n * @param {Object} [options] - an object with options.\n * @param {Boolean} [options.includeSeconds=false] - distances less than a minute are more detailed\n * @param {Boolean} [options.addSuffix=false] - result indicates if the second date is earlier or later than the first\n * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}\n * @returns {String} the distance in words\n * @throws {TypeError} 2 arguments required\n * @throws {RangeError} `date` must not be Invalid Date\n * @throws {RangeError} `baseDate` must not be Invalid Date\n * @throws {RangeError} `options.locale` must contain `formatDistance` property\n *\n * @example\n * // What is the distance between 2 July 2014 and 1 January 2015?\n * const result = formatDistance(new Date(2014, 6, 2), new Date(2015, 0, 1))\n * //=> '6 months'\n *\n * @example\n * // What is the distance between 1 January 2015 00:00:15\n * // and 1 January 2015 00:00:00, including seconds?\n * const result = formatDistance(\n * new Date(2015, 0, 1, 0, 0, 15),\n * new Date(2015, 0, 1, 0, 0, 0),\n * { includeSeconds: true }\n * )\n * //=> 'less than 20 seconds'\n *\n * @example\n * // What is the distance from 1 January 2016\n * // to 1 January 2015, with a suffix?\n * const result = formatDistance(new Date(2015, 0, 1), new Date(2016, 0, 1), {\n * addSuffix: true\n * })\n * //=> 'about 1 year ago'\n *\n * @example\n * // What is the distance between 1 August 2016 and 1 January 2015 in Esperanto?\n * import { eoLocale } from 'date-fns/locale/eo'\n * const result = formatDistance(new Date(2016, 7, 1), new Date(2015, 0, 1), {\n * locale: eoLocale\n * })\n * //=> 'pli ol 1 jaro'\n */\n\nexport default function formatDistance(dirtyDate, dirtyBaseDate) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n requiredArgs(2, arguments);\n var locale = options.locale || defaultLocale;\n\n if (!locale.formatDistance) {\n throw new RangeError('locale must contain formatDistance property');\n }\n\n var comparison = compareAsc(dirtyDate, dirtyBaseDate);\n\n if (isNaN(comparison)) {\n throw new RangeError('Invalid time value');\n }\n\n var localizeOptions = cloneObject(options);\n localizeOptions.addSuffix = Boolean(options.addSuffix);\n localizeOptions.comparison = comparison;\n var dateLeft;\n var dateRight;\n\n if (comparison > 0) {\n dateLeft = toDate(dirtyBaseDate);\n dateRight = toDate(dirtyDate);\n } else {\n dateLeft = toDate(dirtyDate);\n dateRight = toDate(dirtyBaseDate);\n }\n\n var seconds = differenceInSeconds(dateRight, dateLeft);\n var offsetInSeconds = (getTimezoneOffsetInMilliseconds(dateRight) - getTimezoneOffsetInMilliseconds(dateLeft)) / 1000;\n var minutes = Math.round((seconds - offsetInSeconds) / 60);\n var months; // 0 up to 2 mins\n\n if (minutes < 2) {\n if (options.includeSeconds) {\n if (seconds < 5) {\n return locale.formatDistance('lessThanXSeconds', 5, localizeOptions);\n } else if (seconds < 10) {\n return locale.formatDistance('lessThanXSeconds', 10, localizeOptions);\n } else if (seconds < 20) {\n return locale.formatDistance('lessThanXSeconds', 20, localizeOptions);\n } else if (seconds < 40) {\n return locale.formatDistance('halfAMinute', null, localizeOptions);\n } else if (seconds < 60) {\n return locale.formatDistance('lessThanXMinutes', 1, localizeOptions);\n } else {\n return locale.formatDistance('xMinutes', 1, localizeOptions);\n }\n } else {\n if (minutes === 0) {\n return locale.formatDistance('lessThanXMinutes', 1, localizeOptions);\n } else {\n return locale.formatDistance('xMinutes', minutes, localizeOptions);\n }\n } // 2 mins up to 0.75 hrs\n\n } else if (minutes < 45) {\n return locale.formatDistance('xMinutes', minutes, localizeOptions); // 0.75 hrs up to 1.5 hrs\n } else if (minutes < 90) {\n return locale.formatDistance('aboutXHours', 1, localizeOptions); // 1.5 hrs up to 24 hrs\n } else if (minutes < MINUTES_IN_DAY) {\n var hours = Math.round(minutes / 60);\n return locale.formatDistance('aboutXHours', hours, localizeOptions); // 1 day up to 1.75 days\n } else if (minutes < MINUTES_IN_ALMOST_TWO_DAYS) {\n return locale.formatDistance('xDays', 1, localizeOptions); // 1.75 days up to 30 days\n } else if (minutes < MINUTES_IN_MONTH) {\n var days = Math.round(minutes / MINUTES_IN_DAY);\n return locale.formatDistance('xDays', days, localizeOptions); // 1 month up to 2 months\n } else if (minutes < MINUTES_IN_TWO_MONTHS) {\n months = Math.round(minutes / MINUTES_IN_MONTH);\n return locale.formatDistance('aboutXMonths', months, localizeOptions);\n }\n\n months = differenceInMonths(dateRight, dateLeft); // 2 months up to 12 months\n\n if (months < 12) {\n var nearestMonth = Math.round(minutes / MINUTES_IN_MONTH);\n return locale.formatDistance('xMonths', nearestMonth, localizeOptions); // 1 year up to max Date\n } else {\n var monthsSinceStartOfYear = months % 12;\n var years = Math.floor(months / 12); // N years up to 1 years 3 months\n\n if (monthsSinceStartOfYear < 3) {\n return locale.formatDistance('aboutXYears', years, localizeOptions); // N years 3 months up to N years 9 months\n } else if (monthsSinceStartOfYear < 9) {\n return locale.formatDistance('overXYears', years, localizeOptions); // N years 9 months up to N year 12 months\n } else {\n return locale.formatDistance('almostXYears', years + 1, localizeOptions);\n }\n }\n}","\n import { Locale, format, formatDistance } from 'date-fns'\n import { PropType, defineComponent, ComputedRef, computed } from 'vue'\n\n import StaticMap from '@/components/Common/StaticMap.vue'\n import { ROOT_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { IWorkout } from '@/types/workouts'\n import { useStore } from '@/use/useStore'\n import { getApiUrl } from '@/utils'\n import { getDateWithTZ } from '@/utils/dates'\n\n export default defineComponent({\n name: 'WorkoutCard',\n components: {\n StaticMap,\n },\n props: {\n workout: {\n type: Object as PropType<IWorkout>,\n required: false,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n sport: {\n type: Object as PropType<ISport>,\n required: false,\n },\n },\n setup(props) {\n const store = useStore()\n\n const userPictureUrl: ComputedRef<string> = computed(() =>\n props.user.picture\n ? `${getApiUrl()}/users/${props.user.username}/picture?${Date.now()}`\n : ''\n )\n const locale: ComputedRef<Locale> = computed(\n () => store.getters[ROOT_STORE.GETTERS.LOCALE]\n )\n\n return {\n format,\n formatDistance,\n getDateWithTZ,\n locale,\n userPictureUrl,\n }\n },\n })\n","import { render } from \"./WorkoutCard.vue?vue&type=template&id=7846af32&scoped=true\"\nimport script from \"./WorkoutCard.vue?vue&type=script&lang=ts\"\nexport * from \"./WorkoutCard.vue?vue&type=script&lang=ts\"\n\nimport \"./WorkoutCard.vue?vue&type=style&index=0&id=7846af32&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7846af32\"\n\nexport default script","\n import {\n ComputedRef,\n PropType,\n computed,\n defineComponent,\n ref,\n onBeforeMount,\n } from 'vue'\n\n import WorkoutCard from '@/components/Workout/WorkoutCard.vue'\n import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'\n import { WORKOUTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { IWorkout } from '@/types/workouts'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'Timeline',\n components: {\n NoWorkouts,\n WorkoutCard,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n\n let page = ref(1)\n const per_page = 5\n const initWorkoutsCount =\n props.user.nb_workouts >= per_page ? per_page : props.user.nb_workouts\n onBeforeMount(() => loadWorkouts())\n\n const workouts: ComputedRef<IWorkout[]> = computed(\n () => store.getters[WORKOUTS_STORE.GETTERS.USER_WORKOUTS]\n )\n const moreWorkoutsExist: ComputedRef<boolean> = computed(() =>\n workouts.value.length > 0\n ? workouts.value[workouts.value.length - 1].previous_workout !== null\n : false\n )\n\n function loadWorkouts() {\n store.dispatch(WORKOUTS_STORE.ACTIONS.GET_USER_WORKOUTS, {\n page: page.value,\n per_page,\n })\n }\n function loadMoreWorkouts() {\n page.value += 1\n store.dispatch(WORKOUTS_STORE.ACTIONS.GET_MORE_USER_WORKOUTS, {\n page: page.value,\n per_page,\n })\n }\n\n return {\n initWorkoutsCount,\n moreWorkoutsExist,\n per_page,\n workouts,\n loadMoreWorkouts,\n }\n },\n })\n","import { render } from \"./Timeline.vue?vue&type=template&id=9b1e052a&scoped=true\"\nimport script from \"./Timeline.vue?vue&type=script&lang=ts\"\nexport * from \"./Timeline.vue?vue&type=script&lang=ts\"\n\nimport \"./Timeline.vue?vue&type=style&index=0&id=9b1e052a&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-9b1e052a\"\n\nexport default script","<template>\n <div id=\"user-calendar\">\n <div class=\"calendar-card box\">\n <CalendarHeader\n :day=\"day\"\n locale-options=\"enGB\"\n @displayNextMonth=\"displayNextMonth\"\n @displayPreviousMonth=\"displayPreviousMonth\"\n />\n <CalendarDays :start-date=\"calendarDates.start\" locale-options=\"enGB\" />\n <CalendarCells\n :currentDay=\"day\"\n :end-date=\"calendarDates.end\"\n :sports=\"sports\"\n :start-date=\"calendarDates.start\"\n :timezone=\"user.timezone\"\n :workouts=\"calendarWorkouts\"\n :weekStartingMonday=\"user.weekm\"\n />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { addMonths, format, subMonths } from 'date-fns'\n import {\n ComputedRef,\n PropType,\n computed,\n defineComponent,\n ref,\n onBeforeMount,\n } from 'vue'\n\n import CalendarCells from '@/components/Dashboard/UserCalendar/CalendarCells.vue'\n import CalendarDays from '@/components/Dashboard/UserCalendar/CalendarDays.vue'\n import CalendarHeader from '@/components/Dashboard/UserCalendar/CalendarHeader.vue'\n import { WORKOUTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { IWorkout, IWorkoutsPayload } from '@/types/workouts'\n import { useStore } from '@/use/useStore'\n import { getCalendarStartAndEnd } from '@/utils/dates'\n\n export default defineComponent({\n name: 'UserCalendar',\n components: {\n CalendarCells,\n CalendarDays,\n CalendarHeader,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n\n onBeforeMount(() => getCalendarWorkouts())\n\n const dateFormat = 'yyyy-MM-dd'\n let day = ref(new Date())\n let calendarDates = ref(\n getCalendarStartAndEnd(day.value, props.user.weekm)\n )\n const calendarWorkouts: ComputedRef<IWorkout[]> = computed(\n () => store.getters[WORKOUTS_STORE.GETTERS.CALENDAR_WORKOUTS]\n )\n\n function getCalendarWorkouts() {\n calendarDates.value = getCalendarStartAndEnd(\n day.value,\n props.user.weekm\n )\n const apiParams: IWorkoutsPayload = {\n from: format(calendarDates.value.start, dateFormat),\n to: format(calendarDates.value.end, dateFormat),\n order: 'desc',\n per_page: 100,\n }\n store.dispatch(WORKOUTS_STORE.ACTIONS.GET_CALENDAR_WORKOUTS, apiParams)\n }\n\n function displayNextMonth() {\n day.value = addMonths(day.value, 1)\n getCalendarWorkouts()\n }\n function displayPreviousMonth() {\n day.value = subMonths(day.value, 1)\n getCalendarWorkouts()\n }\n\n return {\n day,\n calendarDates,\n calendarWorkouts,\n displayNextMonth,\n displayPreviousMonth,\n }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n #user-calendar {\n .calendar-card {\n padding: 0;\n\n .card-content {\n padding: 0;\n }\n }\n }\n</style>\n","<template>\n <div class=\"calendar-cells\">\n <div class=\"calendar-row\" v-for=\"(row, index) in rows\" :key=\"index\">\n <div\n class=\"calendar-cell\"\n :class=\"{\n 'disabled-cell': !isSameMonth(day, currentDay),\n 'week-end': isWeekEnd(i),\n today: isToday(day),\n }\"\n v-for=\"(day, i) in row\"\n :key=\"i\"\n >\n <CalendarWorkouts\n :workouts=\"filterWorkouts(day, workouts)\"\n :sports=\"sports\"\n />\n <div class=\"calendar-cell-day\">\n {{ format(day, 'd') }}\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { addDays, format, isSameDay, isSameMonth, isToday } from 'date-fns'\n import {\n PropType,\n Ref,\n defineComponent,\n ref,\n toRefs,\n watch,\n onMounted,\n } from 'vue'\n\n import CalendarWorkouts from '@/components/Dashboard/UserCalendar/CalendarWorkouts.vue'\n import { ISport } from '@/types/sports'\n import { IWorkout } from '@/types/workouts'\n import { getDateWithTZ } from '@/utils/dates'\n\n export default defineComponent({\n name: 'CalendarCells',\n components: {\n CalendarWorkouts,\n },\n props: {\n currentDay: {\n type: Date,\n required: true,\n },\n endDate: {\n type: Date,\n required: true,\n },\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n startDate: {\n type: Date,\n required: true,\n },\n timezone: {\n type: String,\n required: true,\n },\n weekStartingMonday: {\n type: Boolean,\n required: true,\n },\n workouts: {\n type: Object as PropType<IWorkout[]>,\n required: true,\n },\n },\n setup(props) {\n const rows: Ref<Date[][]> = ref([])\n let { startDate, endDate, weekStartingMonday } = toRefs(props)\n\n onMounted(() => getDays())\n\n function getDays() {\n rows.value = []\n let day = startDate.value\n while (day <= endDate.value) {\n const days: Date[] = []\n for (let i = 0; i < 7; i++) {\n days.push(day)\n day = addDays(day, 1)\n }\n rows.value.push(days)\n }\n }\n\n function isWeekEnd(day: number): boolean {\n return weekStartingMonday.value\n ? [5, 6].includes(day)\n : [0, 6].includes(day)\n }\n\n function filterWorkouts(day: Date, workouts: IWorkout[]) {\n if (workouts) {\n return workouts\n .filter((workout) =>\n isSameDay(\n getDateWithTZ(workout.workout_date, props.timezone),\n day\n )\n )\n .reverse()\n }\n return []\n }\n\n watch(\n () => props.currentDay,\n () => getDays()\n )\n\n return { rows, format, isSameMonth, isToday, isWeekEnd, filterWorkouts }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n .calendar-cells {\n display: flex;\n flex-direction: column;\n width: 100%;\n\n .calendar-row {\n display: flex;\n flex-wrap: wrap;\n border-top: solid 1px var(--calendar-border-color);\n\n .calendar-cell {\n border-right: solid 1px var(--calendar-border-color);\n height: 40px;\n flex-grow: 1;\n flex-basis: 8%;\n padding: $default-padding * 0.5 $default-padding $default-padding * 0.5\n $default-padding * 0.5;\n width: 8%;\n position: relative;\n\n .calendar-cell-day {\n position: absolute;\n font-size: 0.8em;\n line-height: 1;\n top: 0.5em;\n right: 0.5em;\n font-weight: bold;\n }\n }\n .calendar-cell:last-child {\n border-right: 0;\n @media screen and (max-width: $small-limit) {\n .calendar-workouts {\n .more-workouts {\n left: -45px;\n }\n }\n }\n }\n .disabled-cell {\n color: var(--app-color-light);\n }\n .week-end {\n background: var(--calendar-week-end-color);\n }\n .today {\n background: var(--calendar-today-color);\n }\n }\n @media screen and (max-width: $small-limit) {\n .calendar-row:last-child {\n .calendar-workouts {\n .more-workouts {\n top: inherit;\n bottom: 20px;\n }\n }\n }\n }\n }\n</style>\n","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name startOfDay\n * @category Day Helpers\n * @summary Return the start of a day for the given date.\n *\n * @description\n * Return the start of a day for the given date.\n * The result will be in the local timezone.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the original date\n * @returns {Date} the start of a day\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // The start of a day for 2 September 2014 11:55:00:\n * const result = startOfDay(new Date(2014, 8, 2, 11, 55, 0))\n * //=> Tue Sep 02 2014 00:00:00\n */\n\nexport default function startOfDay(dirtyDate) {\n requiredArgs(1, arguments);\n var date = toDate(dirtyDate);\n date.setHours(0, 0, 0, 0);\n return date;\n}","import startOfDay from \"../startOfDay/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isSameDay\n * @category Day Helpers\n * @summary Are the given dates in the same day?\n *\n * @description\n * Are the given dates in the same day?\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the first date to check\n * @param {Date|Number} dateRight - the second date to check\n * @returns {Boolean} the dates are in the same day\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Are 4 September 06:00:00 and 4 September 18:00:00 in the same day?\n * var result = isSameDay(new Date(2014, 8, 4, 6, 0), new Date(2014, 8, 4, 18, 0))\n * //=> true\n */\n\nexport default function isSameDay(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeftStartOfDay = startOfDay(dirtyDateLeft);\n var dateRightStartOfDay = startOfDay(dirtyDateRight);\n return dateLeftStartOfDay.getTime() === dateRightStartOfDay.getTime();\n}","import toDate from \"../toDate/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isSameMonth\n * @category Month Helpers\n * @summary Are the given dates in the same month?\n *\n * @description\n * Are the given dates in the same month?\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} dateLeft - the first date to check\n * @param {Date|Number} dateRight - the second date to check\n * @returns {Boolean} the dates are in the same month\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Are 2 September 2014 and 25 September 2014 in the same month?\n * var result = isSameMonth(new Date(2014, 8, 2), new Date(2014, 8, 25))\n * //=> true\n */\n\nexport default function isSameMonth(dirtyDateLeft, dirtyDateRight) {\n requiredArgs(2, arguments);\n var dateLeft = toDate(dirtyDateLeft);\n var dateRight = toDate(dirtyDateRight);\n return dateLeft.getFullYear() === dateRight.getFullYear() && dateLeft.getMonth() === dateRight.getMonth();\n}","import isSameDay from \"../isSameDay/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name isToday\n * @category Day Helpers\n * @summary Is the given date today?\n * @pure false\n *\n * @description\n * Is the given date today?\n *\n * > ⚠️ Please note that this function is not present in the FP submodule as\n * > it uses `Date.now()` internally hence impure and can't be safely curried.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to check\n * @returns {Boolean} the date is today\n * @throws {TypeError} 1 argument required\n *\n * @example\n * // If today is 6 October 2014, is 6 October 14:00:00 today?\n * var result = isToday(new Date(2014, 9, 6, 14, 0))\n * //=> true\n */\n\nexport default function isToday(dirtyDate) {\n requiredArgs(1, arguments);\n return isSameDay(dirtyDate, Date.now());\n}","<template>\n <div class=\"calendar-workouts\">\n <div class=\"desktop-display\">\n <div\n class=\"workouts-display\"\n v-if=\"workouts.length <= displayedWorkoutCount\"\n >\n <CalendarWorkout\n v-for=\"(workout, index) in workouts.slice(0, displayedWorkoutCount)\"\n :key=\"index\"\n :workout=\"workout\"\n :sportLabel=\"getSportLabel(workout, sports)\"\n />\n </div>\n <div v-else class=\"donut-display\">\n <CalendarWorkoutsChart\n :workouts=\"workouts\"\n :sports=\"sports\"\n :datasets=\"chartDatasets\"\n :colors=\"colors\"\n />\n </div>\n </div>\n <div class=\"mobile-display\">\n <div class=\"donut-display\" v-if=\"workouts.length > 0\">\n <CalendarWorkoutsChart\n :workouts=\"workouts\"\n :sports=\"sports\"\n :datasets=\"chartDatasets\"\n :colors=\"colors\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { PropType, computed, defineComponent } from 'vue'\n\n import CalendarWorkout from '@/components/Dashboard/UserCalendar/CalendarWorkout.vue'\n import CalendarWorkoutsChart from '@/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue'\n import { ISport } from '@/types/sports'\n import { IWorkout } from '@/types/workouts'\n import { getSportLabel, sportIdColors } from '@/utils/sports'\n import { getDonutDatasets } from '@/utils/workouts'\n\n export default defineComponent({\n name: 'CalendarWorkouts',\n components: {\n CalendarWorkout,\n CalendarWorkoutsChart,\n },\n props: {\n workouts: {\n type: Object as PropType<IWorkout[]>,\n required: true,\n },\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n },\n setup(props) {\n return {\n chartDatasets: computed(() => getDonutDatasets(props.workouts)),\n colors: computed(() => sportIdColors(props.sports)),\n displayedWorkoutCount: 6,\n getSportLabel,\n }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n .calendar-workouts {\n .desktop-display {\n display: flex;\n }\n .mobile-display {\n display: none;\n }\n\n .workouts-display {\n display: flex;\n flex-wrap: wrap;\n position: relative;\n margin: 0 $default-padding 0 0;\n }\n .donut-display {\n display: flex;\n height: 34px;\n width: 34px;\n }\n\n @media screen and (max-width: $small-limit) {\n .desktop-display {\n display: none;\n }\n .mobile-display {\n display: flex;\n }\n }\n }\n</style>\n","<template>\n <div\n class=\"calendar-workout\"\n @click=\"\n $router.push({ name: 'Workout', params: { workoutId: workout.id } })\n \"\n >\n <SportImage :sport-label=\"sportLabel\" :title=\"workout.title\" />\n <sup>\n <i\n v-if=\"workout.records.length > 0\"\n class=\"fa fa-trophy custom-fa-small\"\n aria-hidden=\"true\"\n :title=\"\n workout.records.map(\n (record) => ` ${t(`workouts.RECORD_${record.record_type}`)}`\n )\n \"\n />\n </sup>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { defineComponent, PropType } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import { IWorkout } from '@/types/workouts'\n\n export default defineComponent({\n name: 'CalendarWorkout',\n props: {\n workout: {\n type: Object as PropType<IWorkout>,\n required: true,\n },\n sportLabel: {\n type: String,\n required: true,\n },\n },\n setup() {\n const { t } = useI18n()\n return { t }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n\n .calendar-workout {\n display: flex;\n padding: 1px;\n cursor: pointer;\n .sport-img {\n width: 18px;\n height: 18px;\n }\n sup {\n position: relative;\n top: -8px;\n left: -3px;\n width: 2px;\n .custom-fa-small {\n font-size: 0.7em;\n }\n }\n\n @media screen and (max-width: $small-limit) {\n .sport-img {\n padding: 3px;\n width: 20px;\n height: 20px;\n }\n sup {\n .custom-fa-small {\n font-size: 0.6em;\n }\n }\n }\n }\n</style>\n","\n import { defineComponent, PropType } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import { IWorkout } from '@/types/workouts'\n\n export default defineComponent({\n name: 'CalendarWorkout',\n props: {\n workout: {\n type: Object as PropType<IWorkout>,\n required: true,\n },\n sportLabel: {\n type: String,\n required: true,\n },\n },\n setup() {\n const { t } = useI18n()\n return { t }\n },\n })\n","import { render } from \"./CalendarWorkout.vue?vue&type=template&id=cf219d62\"\nimport script from \"./CalendarWorkout.vue?vue&type=script&lang=ts\"\nexport * from \"./CalendarWorkout.vue?vue&type=script&lang=ts\"\n\nimport \"./CalendarWorkout.vue?vue&type=style&index=0&id=cf219d62&lang=scss\"\nscript.render = render\n\nexport default script","<template>\n <div class=\"calendar-workouts-chart\">\n <div class=\"workouts-chart\" @click=\"togglePane\">\n <div class=\"workouts-count\">{{ workouts.length }}</div>\n <DonutChart :datasets=\"datasets\" :colors=\"colors\" />\n </div>\n <div class=\"workouts-pane\" v-if=\"!isHidden\">\n <div class=\"more-workouts\" v-click-outside=\"togglePane\">\n <i\n class=\"fa fa-times calendar-more\"\n aria-hidden=\"true\"\n @click=\"togglePane\"\n />\n <CalendarWorkout\n v-for=\"(workout, index) in workouts\"\n :key=\"index\"\n :workout=\"workout\"\n :sportLabel=\"getSportLabel(workout, sports)\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { PropType, defineComponent, ref } from 'vue'\n\n import CalendarWorkout from '@/components/Dashboard/UserCalendar/CalendarWorkout.vue'\n import DonutChart from '@/components/Dashboard/UserCalendar/DonutChart.vue'\n import { ISport } from '@/types/sports'\n import { IWorkout } from '@/types/workouts'\n import { getSportLabel } from '@/utils/sports'\n\n export default defineComponent({\n name: 'CalendarWorkoutsChart',\n components: {\n CalendarWorkout,\n DonutChart,\n },\n props: {\n colors: {\n type: Object as PropType<Record<number, string>>,\n required: true,\n },\n datasets: {\n type: Object as PropType<Record<number, Record<string, number>>>,\n required: true,\n },\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n workouts: {\n type: Object as PropType<IWorkout[]>,\n required: true,\n },\n },\n setup() {\n const isHidden = ref(true)\n function togglePane(event: Event & { target: HTMLElement }) {\n event.stopPropagation()\n isHidden.value = !isHidden.value\n }\n return { isHidden, getSportLabel, togglePane }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n .calendar-workouts-chart {\n display: flex;\n\n .workouts-chart {\n position: relative;\n .workouts-count {\n display: flex;\n justify-content: center;\n position: absolute;\n top: 4px;\n left: 6px;\n width: 20px;\n font-size: 1.1em;\n font-weight: bold;\n }\n @media screen and (max-width: $small-limit) {\n .workouts-count {\n top: 16px;\n left: 6px;\n }\n ::v-deep(.donut-chart) {\n padding-top: 12px;\n svg g circle {\n stroke-width: 2;\n stroke-opacity: 0.8;\n }\n }\n }\n }\n\n .workouts-pane {\n display: flex;\n padding-left: 40px;\n\n .more-workouts {\n background: whitesmoke;\n border-radius: 4px;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2),\n 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n position: absolute;\n top: 52px;\n left: 0;\n min-width: 60px;\n @media screen and (max-width: $small-limit) {\n min-width: 70px;\n }\n\n margin-bottom: 20px;\n padding: 10px 10px;\n\n display: flex;\n flex-wrap: wrap;\n z-index: 1000;\n\n .calendar-more {\n position: absolute;\n font-size: 0.9em;\n top: 5px;\n right: 5px;\n }\n }\n }\n }\n</style>\n","// adapted from: https://css-tricks.com/building-a-donut-chart-with-vue-and-svg/\n<template>\n <div class=\"donut-chart\">\n <svg height=\"34\" width=\"34\" viewBox=\"0 0 34 34\">\n <g v-for=\"(data, index) of Object.entries(datasets)\" :key=\"index\">\n <circle\n :cx=\"cx\"\n :cy=\"cy\"\n :r=\"radius\"\n fill=\"transparent\"\n :stroke=\"colors[+data[0]]\"\n :stroke-dashoffset=\"\n calculateStrokeDashOffset(data[1].percentage, circumference)\n \"\n :stroke-dasharray=\"circumference\"\n stroke-width=\"3\"\n stroke-opacity=\"0.8\"\n :transform=\"returnCircleTransformValue(index, data[1].percentage)\"\n />\n </g>\n </svg>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { PropType, defineComponent } from 'vue'\n\n export default defineComponent({\n name: 'DonutChart',\n props: {\n colors: {\n type: Object as PropType<Record<number, string>>,\n required: true,\n },\n datasets: {\n type: Object as PropType<Record<number, Record<string, number>>>,\n required: true,\n },\n },\n setup() {\n let angleOffset = -90\n const cx = 16\n const cy = 16\n const radius = 14\n const circumference = 2 * Math.PI * radius\n\n function calculateStrokeDashOffset(\n percentage: number,\n circumference: number\n ): number {\n return circumference - percentage * circumference\n }\n function returnCircleTransformValue(\n index: number,\n percentage: number\n ): string {\n const rotation = `rotate(${angleOffset}, ${cx}, ${cy})`\n angleOffset = percentage * 360 + angleOffset\n return rotation\n }\n\n return {\n angleOffset,\n circumference,\n cx,\n cy,\n radius,\n calculateStrokeDashOffset,\n returnCircleTransformValue,\n }\n },\n })\n</script>\n","\n import { PropType, defineComponent } from 'vue'\n\n export default defineComponent({\n name: 'DonutChart',\n props: {\n colors: {\n type: Object as PropType<Record<number, string>>,\n required: true,\n },\n datasets: {\n type: Object as PropType<Record<number, Record<string, number>>>,\n required: true,\n },\n },\n setup() {\n let angleOffset = -90\n const cx = 16\n const cy = 16\n const radius = 14\n const circumference = 2 * Math.PI * radius\n\n function calculateStrokeDashOffset(\n percentage: number,\n circumference: number\n ): number {\n return circumference - percentage * circumference\n }\n function returnCircleTransformValue(\n index: number,\n percentage: number\n ): string {\n const rotation = `rotate(${angleOffset}, ${cx}, ${cy})`\n angleOffset = percentage * 360 + angleOffset\n return rotation\n }\n\n return {\n angleOffset,\n circumference,\n cx,\n cy,\n radius,\n calculateStrokeDashOffset,\n returnCircleTransformValue,\n }\n },\n })\n","import { render } from \"./DonutChart.vue?vue&type=template&id=76d4f86b\"\nimport script from \"./DonutChart.vue?vue&type=script&lang=ts\"\nexport * from \"./DonutChart.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n import { PropType, defineComponent, ref } from 'vue'\n\n import CalendarWorkout from '@/components/Dashboard/UserCalendar/CalendarWorkout.vue'\n import DonutChart from '@/components/Dashboard/UserCalendar/DonutChart.vue'\n import { ISport } from '@/types/sports'\n import { IWorkout } from '@/types/workouts'\n import { getSportLabel } from '@/utils/sports'\n\n export default defineComponent({\n name: 'CalendarWorkoutsChart',\n components: {\n CalendarWorkout,\n DonutChart,\n },\n props: {\n colors: {\n type: Object as PropType<Record<number, string>>,\n required: true,\n },\n datasets: {\n type: Object as PropType<Record<number, Record<string, number>>>,\n required: true,\n },\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n workouts: {\n type: Object as PropType<IWorkout[]>,\n required: true,\n },\n },\n setup() {\n const isHidden = ref(true)\n function togglePane(event: Event & { target: HTMLElement }) {\n event.stopPropagation()\n isHidden.value = !isHidden.value\n }\n return { isHidden, getSportLabel, togglePane }\n },\n })\n","import { render } from \"./CalendarWorkoutsChart.vue?vue&type=template&id=b30dea28&scoped=true\"\nimport script from \"./CalendarWorkoutsChart.vue?vue&type=script&lang=ts\"\nexport * from \"./CalendarWorkoutsChart.vue?vue&type=script&lang=ts\"\n\nimport \"./CalendarWorkoutsChart.vue?vue&type=style&index=0&id=b30dea28&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-b30dea28\"\n\nexport default script","\n import { PropType, computed, defineComponent } from 'vue'\n\n import CalendarWorkout from '@/components/Dashboard/UserCalendar/CalendarWorkout.vue'\n import CalendarWorkoutsChart from '@/components/Dashboard/UserCalendar/CalendarWorkoutsChart.vue'\n import { ISport } from '@/types/sports'\n import { IWorkout } from '@/types/workouts'\n import { getSportLabel, sportIdColors } from '@/utils/sports'\n import { getDonutDatasets } from '@/utils/workouts'\n\n export default defineComponent({\n name: 'CalendarWorkouts',\n components: {\n CalendarWorkout,\n CalendarWorkoutsChart,\n },\n props: {\n workouts: {\n type: Object as PropType<IWorkout[]>,\n required: true,\n },\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n },\n setup(props) {\n return {\n chartDatasets: computed(() => getDonutDatasets(props.workouts)),\n colors: computed(() => sportIdColors(props.sports)),\n displayedWorkoutCount: 6,\n getSportLabel,\n }\n },\n })\n","import { render } from \"./CalendarWorkouts.vue?vue&type=template&id=3822f77d\"\nimport script from \"./CalendarWorkouts.vue?vue&type=script&lang=ts\"\nexport * from \"./CalendarWorkouts.vue?vue&type=script&lang=ts\"\n\nimport \"./CalendarWorkouts.vue?vue&type=style&index=0&id=3822f77d&lang=scss\"\nscript.render = render\n\nexport default script","\n import { addDays, format, isSameDay, isSameMonth, isToday } from 'date-fns'\n import {\n PropType,\n Ref,\n defineComponent,\n ref,\n toRefs,\n watch,\n onMounted,\n } from 'vue'\n\n import CalendarWorkouts from '@/components/Dashboard/UserCalendar/CalendarWorkouts.vue'\n import { ISport } from '@/types/sports'\n import { IWorkout } from '@/types/workouts'\n import { getDateWithTZ } from '@/utils/dates'\n\n export default defineComponent({\n name: 'CalendarCells',\n components: {\n CalendarWorkouts,\n },\n props: {\n currentDay: {\n type: Date,\n required: true,\n },\n endDate: {\n type: Date,\n required: true,\n },\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n startDate: {\n type: Date,\n required: true,\n },\n timezone: {\n type: String,\n required: true,\n },\n weekStartingMonday: {\n type: Boolean,\n required: true,\n },\n workouts: {\n type: Object as PropType<IWorkout[]>,\n required: true,\n },\n },\n setup(props) {\n const rows: Ref<Date[][]> = ref([])\n let { startDate, endDate, weekStartingMonday } = toRefs(props)\n\n onMounted(() => getDays())\n\n function getDays() {\n rows.value = []\n let day = startDate.value\n while (day <= endDate.value) {\n const days: Date[] = []\n for (let i = 0; i < 7; i++) {\n days.push(day)\n day = addDays(day, 1)\n }\n rows.value.push(days)\n }\n }\n\n function isWeekEnd(day: number): boolean {\n return weekStartingMonday.value\n ? [5, 6].includes(day)\n : [0, 6].includes(day)\n }\n\n function filterWorkouts(day: Date, workouts: IWorkout[]) {\n if (workouts) {\n return workouts\n .filter((workout) =>\n isSameDay(\n getDateWithTZ(workout.workout_date, props.timezone),\n day\n )\n )\n .reverse()\n }\n return []\n }\n\n watch(\n () => props.currentDay,\n () => getDays()\n )\n\n return { rows, format, isSameMonth, isToday, isWeekEnd, filterWorkouts }\n },\n })\n","import { render } from \"./CalendarCells.vue?vue&type=template&id=17e3f666\"\nimport script from \"./CalendarCells.vue?vue&type=script&lang=ts\"\nexport * from \"./CalendarCells.vue?vue&type=script&lang=ts\"\n\nimport \"./CalendarCells.vue?vue&type=style&index=0&id=17e3f666&lang=scss\"\nscript.render = render\n\nexport default script","<template>\n <div class=\"calendar-days\">\n <div class=\"calendar-day\" v-for=\"(day, index) in days\" :key=\"index\">\n {{ format(day, 'EEE', localeOptions) }}\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { format, addDays } from 'date-fns'\n import { defineComponent } from 'vue'\n\n export default defineComponent({\n name: 'CalendarDays',\n props: {\n startDate: {\n type: Date,\n required: true,\n },\n localeOptions: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n const days = []\n for (let i = 0; i < 7; i++) {\n days.push(addDays(props.startDate, i))\n }\n return { days, addDays, format }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n .calendar-days {\n display: flex;\n flex-direction: row;\n border-top: solid 1px var(--calendar-border-color);\n\n .calendar-day {\n flex-grow: 1;\n padding: $default-padding * 0.5;\n text-align: center;\n text-transform: uppercase;\n color: var(--app-color-light);\n }\n }\n</style>\n","\n import { format, addDays } from 'date-fns'\n import { defineComponent } from 'vue'\n\n export default defineComponent({\n name: 'CalendarDays',\n props: {\n startDate: {\n type: Date,\n required: true,\n },\n localeOptions: {\n type: String,\n required: true,\n },\n },\n setup(props) {\n const days = []\n for (let i = 0; i < 7; i++) {\n days.push(addDays(props.startDate, i))\n }\n return { days, addDays, format }\n },\n })\n","import { render } from \"./CalendarDays.vue?vue&type=template&id=8c842a34\"\nimport script from \"./CalendarDays.vue?vue&type=script&lang=ts\"\nexport * from \"./CalendarDays.vue?vue&type=script&lang=ts\"\n\nimport \"./CalendarDays.vue?vue&type=style&index=0&id=8c842a34&lang=scss\"\nscript.render = render\n\nexport default script","<template>\n <div class=\"calendar-header\">\n <div\n class=\"calendar-arrow calendar-arrow-left\"\n @click=\"emit('displayPreviousMonth')\"\n >\n <i class=\"fa fa-chevron-left\" aria-hidden=\"true\" />\n </div>\n <div class=\"calendar-month\">\n <span>\n {{ format(day, 'MMM yyyy', localeOptions) }}\n </span>\n </div>\n <div\n class=\"calendar-arrow calendar-arrow-right\"\n @click=\"emit('displayNextMonth')\"\n >\n <i class=\"fa fa-chevron-right\" aria-hidden=\"true\" />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { format } from 'date-fns'\n import { defineComponent } from 'vue'\n\n export default defineComponent({\n name: 'CalendarHeader',\n props: {\n day: {\n type: Date,\n required: true,\n },\n localeOptions: {\n type: String,\n required: true,\n },\n },\n emits: ['displayNextMonth', 'displayPreviousMonth'],\n setup(props, { emit }) {\n return { emit, format }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n .calendar-header {\n display: flex;\n flex-direction: row;\n\n .calendar-arrow,\n .calendar-month {\n flex-grow: 1;\n padding: $default-padding;\n }\n .calendar-arrow-left {\n text-align: left;\n cursor: pointer;\n }\n .calendar-arrow-right {\n text-align: right;\n cursor: pointer;\n }\n .calendar-month {\n font-weight: bold;\n text-align: center;\n text-transform: uppercase;\n }\n }\n</style>\n","\n import { format } from 'date-fns'\n import { defineComponent } from 'vue'\n\n export default defineComponent({\n name: 'CalendarHeader',\n props: {\n day: {\n type: Date,\n required: true,\n },\n localeOptions: {\n type: String,\n required: true,\n },\n },\n emits: ['displayNextMonth', 'displayPreviousMonth'],\n setup(props, { emit }) {\n return { emit, format }\n },\n })\n","import { render } from \"./CalendarHeader.vue?vue&type=template&id=4eabec52\"\nimport script from \"./CalendarHeader.vue?vue&type=script&lang=ts\"\nexport * from \"./CalendarHeader.vue?vue&type=script&lang=ts\"\n\nimport \"./CalendarHeader.vue?vue&type=style&index=0&id=4eabec52&lang=scss\"\nscript.render = render\n\nexport default script","\n import { addMonths, format, subMonths } from 'date-fns'\n import {\n ComputedRef,\n PropType,\n computed,\n defineComponent,\n ref,\n onBeforeMount,\n } from 'vue'\n\n import CalendarCells from '@/components/Dashboard/UserCalendar/CalendarCells.vue'\n import CalendarDays from '@/components/Dashboard/UserCalendar/CalendarDays.vue'\n import CalendarHeader from '@/components/Dashboard/UserCalendar/CalendarHeader.vue'\n import { WORKOUTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { IWorkout, IWorkoutsPayload } from '@/types/workouts'\n import { useStore } from '@/use/useStore'\n import { getCalendarStartAndEnd } from '@/utils/dates'\n\n export default defineComponent({\n name: 'UserCalendar',\n components: {\n CalendarCells,\n CalendarDays,\n CalendarHeader,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const store = useStore()\n\n onBeforeMount(() => getCalendarWorkouts())\n\n const dateFormat = 'yyyy-MM-dd'\n let day = ref(new Date())\n let calendarDates = ref(\n getCalendarStartAndEnd(day.value, props.user.weekm)\n )\n const calendarWorkouts: ComputedRef<IWorkout[]> = computed(\n () => store.getters[WORKOUTS_STORE.GETTERS.CALENDAR_WORKOUTS]\n )\n\n function getCalendarWorkouts() {\n calendarDates.value = getCalendarStartAndEnd(\n day.value,\n props.user.weekm\n )\n const apiParams: IWorkoutsPayload = {\n from: format(calendarDates.value.start, dateFormat),\n to: format(calendarDates.value.end, dateFormat),\n order: 'desc',\n per_page: 100,\n }\n store.dispatch(WORKOUTS_STORE.ACTIONS.GET_CALENDAR_WORKOUTS, apiParams)\n }\n\n function displayNextMonth() {\n day.value = addMonths(day.value, 1)\n getCalendarWorkouts()\n }\n function displayPreviousMonth() {\n day.value = subMonths(day.value, 1)\n getCalendarWorkouts()\n }\n\n return {\n day,\n calendarDates,\n calendarWorkouts,\n displayNextMonth,\n displayPreviousMonth,\n }\n },\n })\n","import { render } from \"./index.vue?vue&type=template&id=0f5eddb2\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=0f5eddb2&lang=scss\"\nscript.render = render\n\nexport default script","<template>\n <div class=\"user-month-stats\">\n <Card>\n <template #title>{{ $t('dashboard.THIS_MONTH') }}</template>\n <template #content>\n <StatChart\n :sports=\"sports\"\n :user=\"user\"\n :chart-params=\"chartParams\"\n :displayed-sport-ids=\"selectedSportIds\"\n :hide-chart-if-no-data=\"true\"\n />\n </template>\n </Card>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { endOfMonth, startOfMonth } from 'date-fns'\n import { PropType, defineComponent } from 'vue'\n\n import StatChart from '@/components/Common/StatsChart/index.vue'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n\n export default defineComponent({\n name: 'UserMonthStats',\n components: {\n StatChart,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const date = new Date()\n return {\n chartParams: {\n duration: 'week',\n start: startOfMonth(date),\n end: endOfMonth(date),\n },\n selectedSportIds: props.sports.map((sport) => sport.id),\n }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n .user-month-stats {\n ::v-deep(.card-content) {\n padding: $default-padding;\n }\n }\n</style>\n","\n import { endOfMonth, startOfMonth } from 'date-fns'\n import { PropType, defineComponent } from 'vue'\n\n import StatChart from '@/components/Common/StatsChart/index.vue'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n\n export default defineComponent({\n name: 'UserMonthStats',\n components: {\n StatChart,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const date = new Date()\n return {\n chartParams: {\n duration: 'week',\n start: startOfMonth(date),\n end: endOfMonth(date),\n },\n selectedSportIds: props.sports.map((sport) => sport.id),\n }\n },\n })\n","import { render } from \"./UserMonthStats.vue?vue&type=template&id=7958b39f&scoped=true\"\nimport script from \"./UserMonthStats.vue?vue&type=script&lang=ts\"\nexport * from \"./UserMonthStats.vue?vue&type=script&lang=ts\"\n\nimport \"./UserMonthStats.vue?vue&type=style&index=0&id=7958b39f&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-7958b39f\"\n\nexport default script","<template>\n <div class=\"user-records-section\">\n <div class=\"section-title\">\n <i class=\"fa fa-trophy custom-fa-small\" aria-hidden=\"true\" />\n {{ $t('workouts.RECORD', 2) }}\n </div>\n <div class=\"user-records\">\n <div v-if=\"Object.keys(recordsBySport).length === 0\" class=\"no-records\">\n {{ $t('workouts.NO_RECORDS') }}\n </div>\n <RecordsCard\n v-for=\"sportTranslatedLabel in Object.keys(recordsBySport).sort()\"\n :sportTranslatedLabel=\"sportTranslatedLabel\"\n :records=\"recordsBySport[sportTranslatedLabel]\"\n :key=\"sportTranslatedLabel\"\n />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { computed, defineComponent, PropType } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import RecordsCard from '@/components/Dashboard/UserRecords/RecordsCard.vue'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { getRecordsBySports } from '@/utils/records'\n import { translateSports } from '@/utils/sports'\n\n export default defineComponent({\n name: 'UserRecords',\n components: {\n RecordsCard,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n const recordsBySport = computed(() =>\n getRecordsBySports(\n props.user.records,\n translateSports(props.sports, t),\n props.user.timezone\n )\n )\n return { recordsBySport }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n .user-records {\n .no-records {\n border: solid 1px var(--card-border-color);\n border-radius: $border-radius;\n padding: $default-padding;\n margin: $default-margin;\n }\n }\n</style>\n","<template>\n <div class=\"records-card\">\n <Card>\n <template #title>\n <SportImage :sport-label=\"records.label\" />\n {{ sportTranslatedLabel }}\n </template>\n <template #content>\n <div class=\"record\" v-for=\"record in records.records\" :key=\"record.id\">\n <span class=\"record-type\">{{\n t(`workouts.RECORD_${record.record_type}`)\n }}</span>\n <span class=\"record-value\">{{ record.value }}</span>\n <span class=\"record-date\">\n <router-link\n :to=\"{\n name: 'Workout',\n params: { workoutId: record.workout_id },\n }\"\n >{{ record.workout_date }}</router-link\n >\n </span>\n </div>\n </template>\n </Card>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { PropType, defineComponent } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import { IRecord } from '@/types/workouts'\n\n export default defineComponent({\n name: 'RecordsCard',\n props: {\n records: {\n type: Object as PropType<IRecord[]>,\n required: true,\n },\n sportTranslatedLabel: {\n type: String,\n required: true,\n },\n },\n setup() {\n const { t } = useI18n()\n return { t }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n .records-card {\n width: 100%;\n padding-bottom: $default-padding * 0.3;\n\n ::v-deep(.card) {\n font-size: 0.9em;\n .card-title {\n display: flex;\n font-size: 0.9em;\n .sport-img {\n padding-right: $default-padding;\n height: 20px;\n width: 20px;\n }\n }\n .card-content {\n font-size: 0.9em;\n padding: $default-padding;\n .record {\n display: flex;\n justify-content: space-between;\n span {\n padding: 2px 5px;\n }\n .record-type {\n flex-grow: 1;\n }\n .record-value {\n font-weight: bold;\n padding-right: $default-padding * 2;\n }\n }\n }\n @media screen and (max-width: $medium-limit) {\n font-size: 1em;\n .card-title {\n font-size: 1em;\n .sport-img {\n height: 22px;\n width: 22px;\n }\n }\n }\n }\n }\n</style>\n","\n import { PropType, defineComponent } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import { IRecord } from '@/types/workouts'\n\n export default defineComponent({\n name: 'RecordsCard',\n props: {\n records: {\n type: Object as PropType<IRecord[]>,\n required: true,\n },\n sportTranslatedLabel: {\n type: String,\n required: true,\n },\n },\n setup() {\n const { t } = useI18n()\n return { t }\n },\n })\n","import { render } from \"./RecordsCard.vue?vue&type=template&id=db29ce96&scoped=true\"\nimport script from \"./RecordsCard.vue?vue&type=script&lang=ts\"\nexport * from \"./RecordsCard.vue?vue&type=script&lang=ts\"\n\nimport \"./RecordsCard.vue?vue&type=style&index=0&id=db29ce96&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-db29ce96\"\n\nexport default script","import { ITranslatedSport } from '@/types/sports'\nimport { IRecord, IRecordsBySports } from '@/types/workouts'\nimport { formatWorkoutDate, getDateWithTZ } from '@/utils/dates'\n\nexport const formatRecord = (\n record: IRecord,\n tz: string\n): Record<string, string | number> => {\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 case 'LD':\n value = record.value\n break\n default:\n throw new Error(\n `Invalid record type, expected: \"AS\", \"FD\", \"LD\", \"MD\", got: \"${record.record_type}\"`\n )\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: record.record_type,\n value: value,\n }\n}\n\nexport const getRecordsBySports = (\n records: IRecord[],\n translatedSports: ITranslatedSport[],\n tz: string\n): IRecordsBySports =>\n records.reduce((sportList: IRecordsBySports, record) => {\n const sport = translatedSports.find((s) => s.id === record.sport_id)\n if (sport && sport.label) {\n if (sportList[sport.translatedLabel] === void 0) {\n sportList[sport.translatedLabel] = {\n label: sport.label,\n records: [],\n }\n }\n sportList[sport.translatedLabel].records.push(formatRecord(record, tz))\n }\n return sportList\n }, {})\n","\n import { computed, defineComponent, PropType } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import RecordsCard from '@/components/Dashboard/UserRecords/RecordsCard.vue'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { getRecordsBySports } from '@/utils/records'\n import { translateSports } from '@/utils/sports'\n\n export default defineComponent({\n name: 'UserRecords',\n components: {\n RecordsCard,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n const recordsBySport = computed(() =>\n getRecordsBySports(\n props.user.records,\n translateSports(props.sports, t),\n props.user.timezone\n )\n )\n return { recordsBySport }\n },\n })\n","import { render } from \"./index.vue?vue&type=template&id=080b37ac&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=080b37ac&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-080b37ac\"\n\nexport default script","<template>\n <div id=\"user-stats\">\n <StatCard\n icon=\"calendar\"\n :value=\"user.nb_workouts\"\n :text=\"$t('workouts.WORKOUT', user.nb_workouts)\"\n />\n <StatCard\n icon=\"road\"\n :value=\"Number(user.total_distance).toFixed(2)\"\n :text=\"$t('workouts.KM')\"\n />\n <StatCard\n icon=\"clock-o\"\n :value=\"total_duration.days\"\n :text=\"total_duration.duration\"\n />\n <StatCard\n icon=\"tags\"\n :value=\"user.nb_sports\"\n :text=\"$t('workouts.SPORT', user.nb_sports)\"\n />\n </div>\n</template>\n\n<script lang=\"ts\">\n import { ComputedRef, PropType, defineComponent, computed } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import StatCard from '@/components/Common/StatCard.vue'\n import { IUserProfile } from '@/types/user'\n\n export default defineComponent({\n name: 'UserStatsCards',\n components: {\n StatCard,\n },\n props: {\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n const total_duration: ComputedRef<string> = computed(\n () => props.user.total_duration\n )\n\n function get_duration(total_duration: ComputedRef<string>) {\n const duration = total_duration.value.match(/day/g)\n ? total_duration.value.split(', ')[1]\n : total_duration.value\n return {\n days: total_duration.value.match(/day/g)\n ? `${total_duration.value.split(' ')[0]} ${\n total_duration.value.match(/days/g)\n ? t('common.DAY', 2)\n : t('common.DAY', 1)\n }`\n : `0 ${t('common.DAY', 2)},`,\n duration: `${duration.split(':')[0]}h ${duration.split(':')[1]}min`,\n }\n }\n\n return { total_duration: computed(() => get_duration(total_duration)) }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n #user-stats {\n display: flex;\n flex: 1 0 25%;\n justify-content: space-around;\n flex-wrap: wrap;\n }\n</style>\n","\n import { ComputedRef, PropType, defineComponent, computed } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import StatCard from '@/components/Common/StatCard.vue'\n import { IUserProfile } from '@/types/user'\n\n export default defineComponent({\n name: 'UserStatsCards',\n components: {\n StatCard,\n },\n props: {\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n const total_duration: ComputedRef<string> = computed(\n () => props.user.total_duration\n )\n\n function get_duration(total_duration: ComputedRef<string>) {\n const duration = total_duration.value.match(/day/g)\n ? total_duration.value.split(', ')[1]\n : total_duration.value\n return {\n days: total_duration.value.match(/day/g)\n ? `${total_duration.value.split(' ')[0]} ${\n total_duration.value.match(/days/g)\n ? t('common.DAY', 2)\n : t('common.DAY', 1)\n }`\n : `0 ${t('common.DAY', 2)},`,\n duration: `${duration.split(':')[0]}h ${duration.split(':')[1]}min`,\n }\n }\n\n return { total_duration: computed(() => get_duration(total_duration)) }\n },\n })\n","import { render } from \"./index.vue?vue&type=template&id=082d819e\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=082d819e&lang=scss\"\nscript.render = render\n\nexport default script","\n import {\n ComputedRef,\n Ref,\n computed,\n defineComponent,\n ref,\n onUnmounted,\n } from 'vue'\n\n import Timeline from '@/components/Dashboard/Timeline.vue'\n import UserCalendar from '@/components/Dashboard/UserCalendar/index.vue'\n import UserMonthStats from '@/components/Dashboard/UserMonthStats.vue'\n import UserRecords from '@/components/Dashboard/UserRecords/index.vue'\n import UserStatsCards from '@/components/Dashboard/UserStatsCards/index.vue'\n import { SPORTS_STORE, USER_STORE, WORKOUTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'Dashboard',\n components: {\n Timeline,\n UserCalendar,\n UserMonthStats,\n UserRecords,\n UserStatsCards,\n },\n setup() {\n const store = useStore()\n const authUser: ComputedRef<IUserProfile> = computed(\n () => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]\n )\n const sports: ComputedRef<ISport[]> = computed(\n () => store.getters[SPORTS_STORE.GETTERS.SPORTS]\n )\n const isSelected: Ref<string> = ref('chart')\n onUnmounted(() => {\n store.commit(WORKOUTS_STORE.MUTATIONS.EMPTY_WORKOUTS)\n })\n\n function updateDisplayColumn(target: string) {\n isSelected.value = target\n }\n\n return { authUser, sports, isSelected, updateDisplayColumn }\n },\n })\n","import { render } from \"./DashBoard.vue?vue&type=template&id=cc9648aa&scoped=true\"\nimport script from \"./DashBoard.vue?vue&type=script&lang=ts\"\nexport * from \"./DashBoard.vue?vue&type=script&lang=ts\"\n\nimport \"./DashBoard.vue?vue&type=style&index=0&id=cc9648aa&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-cc9648aa\"\n\nexport default script","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./DashBoard.vue?vue&type=style&index=0&id=cc9648aa&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./Timeline.vue?vue&type=style&index=0&id=9b1e052a&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=6eb9bb83&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./StatsSportsMenu.vue?vue&type=style&index=0&id=f34b0c5e&lang=scss\"","// https://github.com/zloirock/core-js/issues/280\nvar userAgent = require('../internals/engine-user-agent');\n\n// eslint-disable-next-line unicorn/no-unsafe-regex -- safe\nmodule.exports = /Version\\/10(?:\\.\\d+){1,2}(?: [\\w./]+)?(?: Mobile\\/\\w+)? Safari\\//.test(userAgent);\n","import toInteger from \"../_lib/toInteger/index.js\";\nimport addMonths from \"../addMonths/index.js\";\nimport requiredArgs from \"../_lib/requiredArgs/index.js\";\n/**\n * @name subMonths\n * @category Month Helpers\n * @summary Subtract the specified number of months from the given date.\n *\n * @description\n * Subtract the specified number of months from the given date.\n *\n * ### v2.0.0 breaking changes:\n *\n * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).\n *\n * @param {Date|Number} date - the date to be changed\n * @param {Number} amount - the amount of months to be subtracted. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.\n * @returns {Date} the new date with the months subtracted\n * @throws {TypeError} 2 arguments required\n *\n * @example\n * // Subtract 5 months from 1 February 2015:\n * const result = subMonths(new Date(2015, 1, 1), 5)\n * //=> Mon Sep 01 2014 00:00:00\n */\n\nexport default function subMonths(dirtyDate, dirtyAmount) {\n requiredArgs(2, arguments);\n var amount = toInteger(dirtyAmount);\n return addMonths(dirtyDate, -amount);\n}","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./LoginOrRegister.vue?vue&type=style&index=0&id=842fdaa2&lang=scss\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./StatsMenu.vue?vue&type=style&index=0&id=56f0f302&lang=scss&scoped=true\"","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=080b37ac&lang=scss&scoped=true\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./UserAuthForm.vue?vue&type=style&index=0&id=7717f19a&scoped=true&lang=scss\"","<template>\n <div id=\"loginOrRegister\">\n <div class=\"container\">\n <div class=\"container-sub\">\n <BikePic />\n </div>\n <div class=\"container-sub\">\n <LoginOrRegisterForm :action=\"action\" />\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { defineComponent } from 'vue'\n\n import BikePic from '@/components/BikePic.vue'\n import LoginOrRegisterForm from '@/components/User/UserAuthForm.vue'\n\n export default defineComponent({\n name: 'NavBar',\n components: {\n BikePic,\n LoginOrRegisterForm,\n },\n props: {\n action: {\n type: String,\n required: true,\n },\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base';\n\n #loginOrRegister {\n display: flex;\n height: 100%;\n\n .container {\n display: flex;\n flex-direction: row;\n justify-content: space-evenly;\n margin-bottom: $default-margin * 2;\n width: 100%;\n\n .container-sub {\n min-width: 50%;\n height: 100%;\n }\n }\n @media screen and (max-width: $medium-limit) {\n height: auto;\n .container {\n .container-sub {\n align-items: center;\n .bike-img {\n max-width: 60%;\n }\n }\n }\n }\n @media screen and (max-width: $small-limit) {\n .container {\n flex-direction: column;\n }\n }\n }\n</style>\n","<template>\n <div id=\"about\">\n <img class=\"bike-img\" :src=\"'/img/bike.svg'\" alt=\"mountain bike\" />\n </div>\n</template>\n\n<script>\n export default {\n name: 'About',\n }\n</script>\n\n<style scoped lang=\"scss\">\n @import '~@/scss/base';\n\n #about {\n display: flex;\n justify-content: center;\n\n padding: $default-padding;\n height: 100%;\n\n .bike-img {\n max-width: 40%;\n }\n }\n</style>\n","import { render } from \"./BikePic.vue?vue&type=template&id=645e8c6f&scoped=true\"\nimport script from \"./BikePic.vue?vue&type=script&lang=js\"\nexport * from \"./BikePic.vue?vue&type=script&lang=js\"\n\nimport \"./BikePic.vue?vue&type=style&index=0&id=645e8c6f&scoped=true&lang=scss\"\nscript.render = render\nscript.__scopeId = \"data-v-645e8c6f\"\n\nexport default script","\n import { defineComponent } from 'vue'\n\n import BikePic from '@/components/BikePic.vue'\n import LoginOrRegisterForm from '@/components/User/UserAuthForm.vue'\n\n export default defineComponent({\n name: 'NavBar',\n components: {\n BikePic,\n LoginOrRegisterForm,\n },\n props: {\n action: {\n type: String,\n required: true,\n },\n },\n })\n","import { render } from \"./LoginOrRegister.vue?vue&type=template&id=842fdaa2\"\nimport script from \"./LoginOrRegister.vue?vue&type=script&lang=ts\"\nexport * from \"./LoginOrRegister.vue?vue&type=script&lang=ts\"\n\nimport \"./LoginOrRegister.vue?vue&type=style&index=0&id=842fdaa2&lang=scss\"\nscript.render = render\n\nexport default script","<template>\n <div id=\"statistics\">\n <div class=\"container\" v-if=\"authUser.username\">\n <Card>\n <template #title>{{ $t('statistics.STATISTICS') }}</template>\n <template #content>\n <Statistics\n :class=\"{ 'stats-disabled': authUser.nb_workouts === 0 }\"\n :user=\"authUser\"\n :sports=\"sports\"\n />\n </template>\n </Card>\n <NoWorkouts v-if=\"authUser.nb_workouts === 0\"></NoWorkouts>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { ComputedRef, computed, defineComponent } from 'vue'\n\n import Statistics from '@/components/Statistics/index.vue'\n import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'\n import { USER_STORE, SPORTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'StatisticsView',\n components: {\n NoWorkouts,\n Statistics,\n },\n setup() {\n const store = useStore()\n const authUser: ComputedRef<IUserProfile> = computed(\n () => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]\n )\n const sports: ComputedRef<ISport[]> = computed(() =>\n store.getters[SPORTS_STORE.GETTERS.SPORTS].filter((sport) =>\n authUser.value.sports_list.includes(sport.id)\n )\n )\n return { authUser, sports }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n #statistics {\n display: flex;\n width: 100%;\n margin-bottom: 30px;\n .container {\n display: flex;\n flex-direction: column;\n width: 100%;\n }\n }\n</style>\n","<template>\n <div id=\"user-statistics\" v-if=\"translatedSports\">\n <StatsMenu\n @timeFrameUpdate=\"updateTimeFrame\"\n @arrowClick=\"handleOnClickArrows\"\n />\n <StatChart\n :sports=\"sports\"\n :user=\"user\"\n :chartParams=\"chartParams\"\n :displayed-sport-ids=\"selectedSportIds\"\n :fullStats=\"true\"\n />\n <SportsMenu\n :selected-sport-ids=\"selectedSportIds\"\n :user-sports=\"sports\"\n @selectedSportIdsUpdate=\"updateSelectedSportIds\"\n />\n </div>\n</template>\n\n<script lang=\"ts\">\n import {\n ComputedRef,\n PropType,\n Ref,\n computed,\n defineComponent,\n ref,\n watch,\n } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import StatChart from '@/components/Common/StatsChart/index.vue'\n import StatsMenu from '@/components/Statistics/StatsMenu.vue'\n import SportsMenu from '@/components/Statistics/StatsSportsMenu.vue'\n import { ISport, ITranslatedSport } from '@/types/sports'\n import { IStatisticsDateParams } from '@/types/statistics'\n import { IUserProfile } from '@/types/user'\n import { translateSports } from '@/utils/sports'\n import { getStatsDateParams, updateChartParams } from '@/utils/statistics'\n\n export default defineComponent({\n name: 'Statistics',\n components: {\n SportsMenu,\n StatChart,\n StatsMenu,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n let selectedTimeFrame = ref('month')\n const timeFrames = ['week', 'month', 'year']\n const chartParams: Ref<IStatisticsDateParams> = ref(\n getChartParams(selectedTimeFrame.value)\n )\n const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>\n translateSports(props.sports, t)\n )\n const selectedSportIds: Ref<number[]> = ref(getSports(props.sports))\n\n function updateTimeFrame(timeFrame: string) {\n selectedTimeFrame.value = timeFrame\n chartParams.value = getChartParams(selectedTimeFrame.value)\n }\n function getChartParams(timeFrame: string): IStatisticsDateParams {\n return getStatsDateParams(new Date(), timeFrame, props.user.weekm)\n }\n function handleOnClickArrows(backward: boolean) {\n chartParams.value = updateChartParams(\n chartParams.value,\n backward,\n props.user.weekm\n )\n }\n function getSports(sports: ISport[]) {\n return sports.map((sport) => sport.id)\n }\n function updateSelectedSportIds(sportId: number) {\n if (selectedSportIds.value.includes(sportId)) {\n selectedSportIds.value = selectedSportIds.value.filter(\n (id) => id !== sportId\n )\n } else {\n selectedSportIds.value.push(sportId)\n }\n }\n\n watch(\n () => props.sports,\n (newSports) => {\n selectedSportIds.value = getSports(newSports)\n }\n )\n\n return {\n chartParams,\n selectedTimeFrame,\n timeFrames,\n translatedSports,\n selectedSportIds,\n handleOnClickArrows,\n updateSelectedSportIds,\n updateTimeFrame,\n }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n #user-statistics {\n &.stats-disabled {\n opacity: 0.3;\n pointer-events: none;\n }\n\n ::v-deep(.chart-radio) {\n justify-content: space-around;\n padding: $default-padding * 3 $default-padding\n $default-padding$default-padding;\n }\n }\n</style>\n","<template>\n <div class=\"chart-menu\">\n <div class=\"chart-arrow\">\n <i\n class=\"fa fa-chevron-left\"\n aria-hidden=\"true\"\n @click=\"emit('arrowClick', true)\"\n />\n </div>\n <div class=\"time-frames custom-checkboxes-group\">\n <div class=\"time-frames-checkboxes custom-checkboxes\">\n <div\n v-for=\"frame in timeFrames\"\n class=\"time-frame custom-checkbox\"\n :key=\"frame\"\n >\n <label>\n <input\n type=\"radio\"\n :id=\"frame\"\n :name=\"frame\"\n :checked=\"selectedTimeFrame === frame\"\n @input=\"onUpdateTimeFrame(frame)\"\n />\n <span>{{ $t(`statistics.TIME_FRAMES.${frame}`) }}</span>\n </label>\n </div>\n </div>\n </div>\n <div class=\"chart-arrow\">\n <i\n class=\"fa fa-chevron-right\"\n aria-hidden=\"true\"\n @click=\"emit('arrowClick', false)\"\n />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { defineComponent, ref } from 'vue'\n\n export default defineComponent({\n name: 'StatsMenu',\n emits: ['arrowClick', 'timeFrameUpdate'],\n setup(props, { emit }) {\n let selectedTimeFrame = ref('month')\n const timeFrames = ['week', 'month', 'year']\n\n function onUpdateTimeFrame(timeFrame: string) {\n selectedTimeFrame.value = timeFrame\n emit('timeFrameUpdate', timeFrame)\n }\n\n return {\n selectedTimeFrame,\n timeFrames,\n onUpdateTimeFrame,\n emit,\n }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n\n .chart-menu {\n display: flex;\n\n .chart-arrow,\n .time-frames {\n flex-grow: 1;\n text-align: center;\n }\n\n .chart-arrow {\n cursor: pointer;\n }\n }\n</style>\n","\n import { defineComponent, ref } from 'vue'\n\n export default defineComponent({\n name: 'StatsMenu',\n emits: ['arrowClick', 'timeFrameUpdate'],\n setup(props, { emit }) {\n let selectedTimeFrame = ref('month')\n const timeFrames = ['week', 'month', 'year']\n\n function onUpdateTimeFrame(timeFrame: string) {\n selectedTimeFrame.value = timeFrame\n emit('timeFrameUpdate', timeFrame)\n }\n\n return {\n selectedTimeFrame,\n timeFrames,\n onUpdateTimeFrame,\n emit,\n }\n },\n })\n","import { render } from \"./StatsMenu.vue?vue&type=template&id=56f0f302&scoped=true\"\nimport script from \"./StatsMenu.vue?vue&type=script&lang=ts\"\nexport * from \"./StatsMenu.vue?vue&type=script&lang=ts\"\n\nimport \"./StatsMenu.vue?vue&type=style&index=0&id=56f0f302&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-56f0f302\"\n\nexport default script","<template>\n <div class=\"sports-menu\">\n <label\n v-for=\"sport in translatedSports\"\n type=\"checkbox\"\n :key=\"sport.id\"\n :style=\"{ color: sportColors[sport.label] }\"\n >\n <input\n type=\"checkbox\"\n :id=\"sport.id\"\n :name=\"sport.label\"\n :checked=\"selectedSportIds.includes(sport.id)\"\n @input=\"updateSelectedSportIds(sport.id)\"\n />\n <SportImage :sport-label=\"sport.label\" />\n <span class=\"sport-label\">{{ sport.translatedLabel }}</span>\n </label>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { ComputedRef, PropType, computed, defineComponent, inject } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import { ISport, ITranslatedSport } from '@/types/sports'\n import { translateSports } from '@/utils/sports'\n\n export default defineComponent({\n name: 'SportsMenu',\n props: {\n selectedSportIds: {\n type: Array as PropType<number[]>,\n default: () => [],\n },\n userSports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n },\n emits: ['selectedSportIdsUpdate'],\n setup(props, { emit }) {\n const { t } = useI18n()\n const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>\n translateSports(props.userSports, t)\n )\n\n function updateSelectedSportIds(sportId: number) {\n emit('selectedSportIdsUpdate', sportId)\n }\n\n return {\n sportColors: inject('sportColors'),\n translatedSports,\n updateSelectedSportIds,\n }\n },\n })\n</script>\n\n<style lang=\"scss\">\n @import '~@/scss/base.scss';\n .sports-menu {\n display: flex;\n justify-content: space-between;\n padding: $default-padding;\n @media screen and (max-width: $medium-limit) {\n justify-content: normal;\n flex-wrap: wrap;\n }\n\n label {\n display: flex;\n align-items: center;\n font-size: 0.9em;\n font-weight: normal;\n min-width: 120px;\n padding: $default-padding;\n @media screen and (max-width: $medium-limit) {\n min-width: 100px;\n }\n @media screen and (max-width: $x-small-limit) {\n min-width: 20px;\n .sport-label {\n display: none;\n }\n }\n }\n\n .sport-img {\n padding: 3px;\n width: 20px;\n height: 20px;\n }\n }\n</style>\n","\n import { ComputedRef, PropType, computed, defineComponent, inject } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import { ISport, ITranslatedSport } from '@/types/sports'\n import { translateSports } from '@/utils/sports'\n\n export default defineComponent({\n name: 'SportsMenu',\n props: {\n selectedSportIds: {\n type: Array as PropType<number[]>,\n default: () => [],\n },\n userSports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n },\n emits: ['selectedSportIdsUpdate'],\n setup(props, { emit }) {\n const { t } = useI18n()\n const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>\n translateSports(props.userSports, t)\n )\n\n function updateSelectedSportIds(sportId: number) {\n emit('selectedSportIdsUpdate', sportId)\n }\n\n return {\n sportColors: inject('sportColors'),\n translatedSports,\n updateSelectedSportIds,\n }\n },\n })\n","import { render } from \"./StatsSportsMenu.vue?vue&type=template&id=f34b0c5e\"\nimport script from \"./StatsSportsMenu.vue?vue&type=script&lang=ts\"\nexport * from \"./StatsSportsMenu.vue?vue&type=script&lang=ts\"\n\nimport \"./StatsSportsMenu.vue?vue&type=style&index=0&id=f34b0c5e&lang=scss\"\nscript.render = render\n\nexport default script","\n import {\n ComputedRef,\n PropType,\n Ref,\n computed,\n defineComponent,\n ref,\n watch,\n } from 'vue'\n import { useI18n } from 'vue-i18n'\n\n import StatChart from '@/components/Common/StatsChart/index.vue'\n import StatsMenu from '@/components/Statistics/StatsMenu.vue'\n import SportsMenu from '@/components/Statistics/StatsSportsMenu.vue'\n import { ISport, ITranslatedSport } from '@/types/sports'\n import { IStatisticsDateParams } from '@/types/statistics'\n import { IUserProfile } from '@/types/user'\n import { translateSports } from '@/utils/sports'\n import { getStatsDateParams, updateChartParams } from '@/utils/statistics'\n\n export default defineComponent({\n name: 'Statistics',\n components: {\n SportsMenu,\n StatChart,\n StatsMenu,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n let selectedTimeFrame = ref('month')\n const timeFrames = ['week', 'month', 'year']\n const chartParams: Ref<IStatisticsDateParams> = ref(\n getChartParams(selectedTimeFrame.value)\n )\n const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>\n translateSports(props.sports, t)\n )\n const selectedSportIds: Ref<number[]> = ref(getSports(props.sports))\n\n function updateTimeFrame(timeFrame: string) {\n selectedTimeFrame.value = timeFrame\n chartParams.value = getChartParams(selectedTimeFrame.value)\n }\n function getChartParams(timeFrame: string): IStatisticsDateParams {\n return getStatsDateParams(new Date(), timeFrame, props.user.weekm)\n }\n function handleOnClickArrows(backward: boolean) {\n chartParams.value = updateChartParams(\n chartParams.value,\n backward,\n props.user.weekm\n )\n }\n function getSports(sports: ISport[]) {\n return sports.map((sport) => sport.id)\n }\n function updateSelectedSportIds(sportId: number) {\n if (selectedSportIds.value.includes(sportId)) {\n selectedSportIds.value = selectedSportIds.value.filter(\n (id) => id !== sportId\n )\n } else {\n selectedSportIds.value.push(sportId)\n }\n }\n\n watch(\n () => props.sports,\n (newSports) => {\n selectedSportIds.value = getSports(newSports)\n }\n )\n\n return {\n chartParams,\n selectedTimeFrame,\n timeFrames,\n translatedSports,\n selectedSportIds,\n handleOnClickArrows,\n updateSelectedSportIds,\n updateTimeFrame,\n }\n },\n })\n","import { render } from \"./index.vue?vue&type=template&id=dad311d4&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=dad311d4&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-dad311d4\"\n\nexport default script","\n import { ComputedRef, computed, defineComponent } from 'vue'\n\n import Statistics from '@/components/Statistics/index.vue'\n import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'\n import { USER_STORE, SPORTS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import { IUserProfile } from '@/types/user'\n import { useStore } from '@/use/useStore'\n\n export default defineComponent({\n name: 'StatisticsView',\n components: {\n NoWorkouts,\n Statistics,\n },\n setup() {\n const store = useStore()\n const authUser: ComputedRef<IUserProfile> = computed(\n () => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]\n )\n const sports: ComputedRef<ISport[]> = computed(() =>\n store.getters[SPORTS_STORE.GETTERS.SPORTS].filter((sport) =>\n authUser.value.sports_list.includes(sport.id)\n )\n )\n return { authUser, sports }\n },\n })\n","import { render } from \"./StatisticsView.vue?vue&type=template&id=8e65b6c0&scoped=true\"\nimport script from \"./StatisticsView.vue?vue&type=script&lang=ts\"\nexport * from \"./StatisticsView.vue?vue&type=script&lang=ts\"\n\nimport \"./StatisticsView.vue?vue&type=style&index=0&id=8e65b6c0&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-8e65b6c0\"\n\nexport default script","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./index.vue?vue&type=style&index=0&id=082d819e&lang=scss\"","var defineWellKnownSymbol = require('../internals/define-well-known-symbol');\n\n// `Symbol.iterator` well-known symbol\n// https://tc39.es/ecma262/#sec-symbol.iterator\ndefineWellKnownSymbol('iterator');\n","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./StatisticsView.vue?vue&type=style&index=0&id=8e65b6c0&lang=scss&scoped=true\"","// `Symbol.prototype.description` getter\n// https://tc39.es/ecma262/#sec-symbol.prototype.description\n'use strict';\nvar $ = require('../internals/export');\nvar DESCRIPTORS = require('../internals/descriptors');\nvar global = require('../internals/global');\nvar has = require('../internals/has');\nvar isObject = require('../internals/is-object');\nvar defineProperty = require('../internals/object-define-property').f;\nvar copyConstructorProperties = require('../internals/copy-constructor-properties');\n\nvar NativeSymbol = global.Symbol;\n\nif (DESCRIPTORS && typeof NativeSymbol == 'function' && (!('description' in NativeSymbol.prototype) ||\n // Safari 12 bug\n NativeSymbol().description !== undefined\n)) {\n var EmptyStringDescriptionStore = {};\n // wrap Symbol constructor for correct work with undefined description\n var SymbolWrapper = function Symbol() {\n var description = arguments.length < 1 || arguments[0] === undefined ? undefined : String(arguments[0]);\n var result = this instanceof SymbolWrapper\n ? new NativeSymbol(description)\n // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'\n : description === undefined ? NativeSymbol() : NativeSymbol(description);\n if (description === '') EmptyStringDescriptionStore[result] = true;\n return result;\n };\n copyConstructorProperties(SymbolWrapper, NativeSymbol);\n var symbolPrototype = SymbolWrapper.prototype = NativeSymbol.prototype;\n symbolPrototype.constructor = SymbolWrapper;\n\n var symbolToString = symbolPrototype.toString;\n var native = String(NativeSymbol('test')) == 'Symbol(test)';\n var regexp = /^Symbol\\((.*)\\)[^)]+$/;\n defineProperty(symbolPrototype, 'description', {\n configurable: true,\n get: function description() {\n var symbol = isObject(this) ? this.valueOf() : this;\n var string = symbolToString.call(symbol);\n if (has(EmptyStringDescriptionStore, symbol)) return '';\n var desc = native ? string.slice(7, -1) : string.replace(regexp, '$1');\n return desc === '' ? undefined : desc;\n }\n });\n\n $({ global: true, forced: true }, {\n Symbol: SymbolWrapper\n });\n}\n","<template>\n <div class=\"not-found\">\n <NotFound />\n </div>\n</template>\n\n<script lang=\"ts\">\n import { defineComponent } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n\n export default defineComponent({\n name: 'NotFoundView',\n components: {\n NotFound,\n },\n })\n</script>\n","\n import { defineComponent } from 'vue'\n\n import NotFound from '@/components/Common/NotFound.vue'\n\n export default defineComponent({\n name: 'NotFoundView',\n components: {\n NotFound,\n },\n })\n","import { render } from \"./NotFoundView.vue?vue&type=template&id=68e1b1a0\"\nimport script from \"./NotFoundView.vue?vue&type=script&lang=ts\"\nexport * from \"./NotFoundView.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","export * from \"-!../../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--8-oneOf-1-0!../../../../node_modules/css-loader/dist/cjs.js??ref--8-oneOf-1-1!../../../../node_modules/vue-loader-v16/dist/stylePostLoader.js!../../../../node_modules/postcss-loader/src/index.js??ref--8-oneOf-1-2!../../../../node_modules/sass-loader/dist/cjs.js??ref--8-oneOf-1-3!../../../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../../../node_modules/vue-loader-v16/dist/index.js??ref--0-1!./CalendarHeader.vue?vue&type=style&index=0&id=4eabec52&lang=scss\"","<template>\n <div class=\"start-chart\">\n <div v-if=\"hideChartIfNoData && emptyStats\">\n {{ $t('workouts.NO_WORKOUTS') }}\n </div>\n <div v-else>\n <div class=\"chart-radio\">\n <label>\n <input\n type=\"radio\"\n name=\"total_distance\"\n :checked=\"displayedData === 'total_distance'\"\n @click=\"updateDisplayData\"\n />\n {{ $t('workouts.DISTANCE') }}\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"total_duration\"\n :checked=\"displayedData === 'total_duration'\"\n @click=\"updateDisplayData\"\n />\n {{ $t('workouts.DURATION') }}\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"nb_workouts\"\n :checked=\"displayedData === 'nb_workouts'\"\n @click=\"updateDisplayData\"\n />\n {{ $t('workouts.WORKOUT', 2) }}\n </label>\n </div>\n <Chart\n v-if=\"labels.length > 0\"\n :datasets=\"datasets\"\n :labels=\"labels\"\n :displayedData=\"displayedData\"\n :displayedSportIds=\"displayedSportIds\"\n :fullStats=\"fullStats\"\n />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\n import { format } from 'date-fns'\n import {\n ComputedRef,\n PropType,\n Ref,\n computed,\n defineComponent,\n ref,\n watch,\n onBeforeMount,\n } from 'vue'\n\n import Chart from '@/components/Common/StatsChart/Chart.vue'\n import { STATS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import {\n IStatisticsChartData,\n TStatisticsDatasetKeys,\n IStatisticsDateParams,\n TStatisticsFromApi,\n IStatisticsParams,\n } from '@/types/statistics'\n import { IUserProfile } from '@/types/user'\n import { useStore } from '@/use/useStore'\n import { formatStats } from '@/utils/statistics'\n\n export default defineComponent({\n name: 'UserMonthStats',\n components: {\n Chart,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n chartParams: {\n type: Object as PropType<IStatisticsDateParams>,\n required: true,\n },\n displayedSportIds: {\n type: Array as PropType<number[]>,\n default: () => [],\n },\n fullStats: {\n type: Boolean,\n default: false,\n },\n hideChartIfNoData: {\n type: Boolean,\n default: false,\n },\n },\n setup(props) {\n const store = useStore()\n\n let displayedData: Ref<TStatisticsDatasetKeys> = ref('total_distance')\n const statistics: ComputedRef<TStatisticsFromApi> = computed(\n () => store.getters[STATS_STORE.GETTERS.USER_STATS]\n )\n const formattedStats: ComputedRef<IStatisticsChartData> = computed(() =>\n formatStats(\n props.chartParams,\n props.user.weekm,\n props.sports,\n props.displayedSportIds,\n statistics.value\n )\n )\n\n onBeforeMount(() =>\n getStatistics(getApiParams(props.chartParams, props.user))\n )\n\n function getStatistics(apiParams: IStatisticsParams) {\n store.dispatch(STATS_STORE.ACTIONS.GET_USER_STATS, {\n username: props.user.username,\n filterType: 'by_time',\n params: apiParams,\n })\n }\n function updateDisplayData(\n event: Event & {\n target: HTMLInputElement & { name: TStatisticsDatasetKeys }\n }\n ) {\n displayedData.value = event.target.name\n }\n function getApiParams(\n chartParams: IStatisticsDateParams,\n user: IUserProfile\n ): IStatisticsParams {\n return {\n from: format(chartParams.start, 'yyyy-MM-dd'),\n to: format(chartParams.end, 'yyyy-MM-dd'),\n time:\n chartParams.duration === 'week'\n ? `week${user.weekm ? 'm' : ''}`\n : chartParams.duration,\n }\n }\n\n watch(\n () => props.chartParams,\n async (newParams) => {\n getStatistics(getApiParams(newParams, props.user))\n }\n )\n\n return {\n datasets: computed(\n () => formattedStats.value.datasets[displayedData.value]\n ),\n labels: computed(() => formattedStats.value.labels),\n emptyStats: computed(() => Object.keys(statistics.value).length === 0),\n displayedData,\n updateDisplayData,\n }\n },\n })\n</script>\n\n<style lang=\"scss\" scoped>\n @import '~@/scss/base';\n .start-chart {\n .chart-radio {\n display: flex;\n justify-content: space-between;\n padding: $default-padding;\n\n label {\n font-size: 0.85em;\n font-weight: normal;\n }\n }\n }\n</style>\n","<template>\n <div class=\"chart\">\n <BarChart v-bind=\"barChartProps\" class=\"bar-chart\" />\n </div>\n</template>\n\n<script lang=\"ts\">\n import { ChartData, ChartOptions, LayoutItem } from 'chart.js'\n import { ComputedRef, PropType, computed, defineComponent } from 'vue'\n import { BarChart, useBarChart } from 'vue-chart-3'\n import { useI18n } from 'vue-i18n'\n\n import { IChartDataset } from '@/types/chart'\n import { TStatisticsDatasetKeys } from '@/types/statistics'\n import { formatTooltipValue } from '@/utils/tooltip'\n\n export default defineComponent({\n name: 'Chart',\n components: {\n BarChart,\n },\n props: {\n datasets: {\n type: Object as PropType<IChartDataset[]>,\n required: true,\n },\n labels: {\n type: Object as PropType<unknown[]>,\n required: true,\n },\n displayedData: {\n type: String as PropType<TStatisticsDatasetKeys>,\n required: true,\n },\n displayedSportIds: {\n type: Array as PropType<number[]>,\n required: true,\n },\n fullStats: {\n type: Boolean,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function getNumber(value: any): number {\n return isNaN(value) ? 0 : +value\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function getSum(total: any, value: any): number {\n return getNumber(total) + getNumber(value)\n }\n let chartData: ComputedRef<ChartData<'bar'>> = computed(() => ({\n labels: props.labels,\n // workaround to avoid dataset modification\n datasets: JSON.parse(JSON.stringify(props.datasets)),\n }))\n const options = computed<ChartOptions<'bar'>>(() => ({\n responsive: true,\n maintainAspectRatio: true,\n animation: false,\n layout: {\n padding: {\n top: props.fullStats ? 40 : 22,\n },\n },\n scales: {\n x: {\n stacked: true,\n grid: {\n drawOnChartArea: false,\n },\n },\n y: {\n stacked: true,\n grid: {\n drawOnChartArea: false,\n },\n ticks: {\n maxTicksLimit: 6,\n callback: function (value) {\n return formatTooltipValue(props.displayedData, +value, false)\n },\n },\n afterFit: function (scale: LayoutItem) {\n scale.width = props.fullStats ? 75 : 60\n },\n },\n },\n plugins: {\n datalabels: {\n anchor: 'end',\n align: 'end',\n rotation: function (context) {\n return props.fullStats && context.chart.chartArea.width < 580\n ? 310\n : 0\n },\n display: function (context) {\n return !(props.fullStats && context.chart.chartArea.width < 300)\n },\n formatter: function (value, context) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const total: number = context.chart.data.datasets\n .map((d) => d.data[context.dataIndex])\n .reduce((total, value) => getSum(total, value), 0)\n return context.datasetIndex ===\n props.displayedSportIds.length - 1 && total > 0\n ? formatTooltipValue(props.displayedData, total, false)\n : null\n },\n },\n legend: {\n display: false,\n },\n tooltip: {\n interaction: {\n intersect: true,\n mode: 'index',\n },\n filter: function (tooltipItem) {\n return tooltipItem.formattedValue !== '0'\n },\n callbacks: {\n label: function (context) {\n let label = t(`sports.${context.dataset.label}.LABEL`) || ''\n if (label) {\n label += ': '\n }\n if (context.parsed.y !== null) {\n label += formatTooltipValue(\n props.displayedData,\n context.parsed.y\n )\n }\n return label\n },\n footer: function (tooltipItems) {\n let sum = 0\n tooltipItems.map((tooltipItem) => {\n sum += tooltipItem.parsed.y\n })\n return (\n `${t('statistics.TOTAL')}: ` +\n formatTooltipValue(props.displayedData, sum)\n )\n },\n },\n },\n },\n }))\n const { barChartProps } = useBarChart({\n chartData,\n options,\n })\n return { barChartProps }\n },\n })\n</script>\n","export const formatDuration = (\n totalSeconds: number,\n formatWithUnits = false\n): string => {\n let days = '0'\n if (formatWithUnits) {\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 (formatWithUnits) {\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","import { TStatisticsDatasetKeys } from '@/types/statistics'\nimport { formatDuration } from '@/utils/duration'\n\nexport const formatTooltipValue = (\n displayedData: TStatisticsDatasetKeys,\n value: number,\n formatWithUnits = true\n): string => {\n return displayedData === 'total_duration'\n ? formatDuration(value, formatWithUnits)\n : displayedData === 'total_distance'\n ? value.toFixed(2) + ' km'\n : value.toString()\n}\n","\n import { ChartData, ChartOptions, LayoutItem } from 'chart.js'\n import { ComputedRef, PropType, computed, defineComponent } from 'vue'\n import { BarChart, useBarChart } from 'vue-chart-3'\n import { useI18n } from 'vue-i18n'\n\n import { IChartDataset } from '@/types/chart'\n import { TStatisticsDatasetKeys } from '@/types/statistics'\n import { formatTooltipValue } from '@/utils/tooltip'\n\n export default defineComponent({\n name: 'Chart',\n components: {\n BarChart,\n },\n props: {\n datasets: {\n type: Object as PropType<IChartDataset[]>,\n required: true,\n },\n labels: {\n type: Object as PropType<unknown[]>,\n required: true,\n },\n displayedData: {\n type: String as PropType<TStatisticsDatasetKeys>,\n required: true,\n },\n displayedSportIds: {\n type: Array as PropType<number[]>,\n required: true,\n },\n fullStats: {\n type: Boolean,\n required: true,\n },\n },\n setup(props) {\n const { t } = useI18n()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function getNumber(value: any): number {\n return isNaN(value) ? 0 : +value\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function getSum(total: any, value: any): number {\n return getNumber(total) + getNumber(value)\n }\n let chartData: ComputedRef<ChartData<'bar'>> = computed(() => ({\n labels: props.labels,\n // workaround to avoid dataset modification\n datasets: JSON.parse(JSON.stringify(props.datasets)),\n }))\n const options = computed<ChartOptions<'bar'>>(() => ({\n responsive: true,\n maintainAspectRatio: true,\n animation: false,\n layout: {\n padding: {\n top: props.fullStats ? 40 : 22,\n },\n },\n scales: {\n x: {\n stacked: true,\n grid: {\n drawOnChartArea: false,\n },\n },\n y: {\n stacked: true,\n grid: {\n drawOnChartArea: false,\n },\n ticks: {\n maxTicksLimit: 6,\n callback: function (value) {\n return formatTooltipValue(props.displayedData, +value, false)\n },\n },\n afterFit: function (scale: LayoutItem) {\n scale.width = props.fullStats ? 75 : 60\n },\n },\n },\n plugins: {\n datalabels: {\n anchor: 'end',\n align: 'end',\n rotation: function (context) {\n return props.fullStats && context.chart.chartArea.width < 580\n ? 310\n : 0\n },\n display: function (context) {\n return !(props.fullStats && context.chart.chartArea.width < 300)\n },\n formatter: function (value, context) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const total: number = context.chart.data.datasets\n .map((d) => d.data[context.dataIndex])\n .reduce((total, value) => getSum(total, value), 0)\n return context.datasetIndex ===\n props.displayedSportIds.length - 1 && total > 0\n ? formatTooltipValue(props.displayedData, total, false)\n : null\n },\n },\n legend: {\n display: false,\n },\n tooltip: {\n interaction: {\n intersect: true,\n mode: 'index',\n },\n filter: function (tooltipItem) {\n return tooltipItem.formattedValue !== '0'\n },\n callbacks: {\n label: function (context) {\n let label = t(`sports.${context.dataset.label}.LABEL`) || ''\n if (label) {\n label += ': '\n }\n if (context.parsed.y !== null) {\n label += formatTooltipValue(\n props.displayedData,\n context.parsed.y\n )\n }\n return label\n },\n footer: function (tooltipItems) {\n let sum = 0\n tooltipItems.map((tooltipItem) => {\n sum += tooltipItem.parsed.y\n })\n return (\n `${t('statistics.TOTAL')}: ` +\n formatTooltipValue(props.displayedData, sum)\n )\n },\n },\n },\n },\n }))\n const { barChartProps } = useBarChart({\n chartData,\n options,\n })\n return { barChartProps }\n },\n })\n","import { render } from \"./Chart.vue?vue&type=template&id=6d221a79\"\nimport script from \"./Chart.vue?vue&type=script&lang=ts\"\nexport * from \"./Chart.vue?vue&type=script&lang=ts\"\nscript.render = render\n\nexport default script","\n import { format } from 'date-fns'\n import {\n ComputedRef,\n PropType,\n Ref,\n computed,\n defineComponent,\n ref,\n watch,\n onBeforeMount,\n } from 'vue'\n\n import Chart from '@/components/Common/StatsChart/Chart.vue'\n import { STATS_STORE } from '@/store/constants'\n import { ISport } from '@/types/sports'\n import {\n IStatisticsChartData,\n TStatisticsDatasetKeys,\n IStatisticsDateParams,\n TStatisticsFromApi,\n IStatisticsParams,\n } from '@/types/statistics'\n import { IUserProfile } from '@/types/user'\n import { useStore } from '@/use/useStore'\n import { formatStats } from '@/utils/statistics'\n\n export default defineComponent({\n name: 'UserMonthStats',\n components: {\n Chart,\n },\n props: {\n sports: {\n type: Object as PropType<ISport[]>,\n required: true,\n },\n user: {\n type: Object as PropType<IUserProfile>,\n required: true,\n },\n chartParams: {\n type: Object as PropType<IStatisticsDateParams>,\n required: true,\n },\n displayedSportIds: {\n type: Array as PropType<number[]>,\n default: () => [],\n },\n fullStats: {\n type: Boolean,\n default: false,\n },\n hideChartIfNoData: {\n type: Boolean,\n default: false,\n },\n },\n setup(props) {\n const store = useStore()\n\n let displayedData: Ref<TStatisticsDatasetKeys> = ref('total_distance')\n const statistics: ComputedRef<TStatisticsFromApi> = computed(\n () => store.getters[STATS_STORE.GETTERS.USER_STATS]\n )\n const formattedStats: ComputedRef<IStatisticsChartData> = computed(() =>\n formatStats(\n props.chartParams,\n props.user.weekm,\n props.sports,\n props.displayedSportIds,\n statistics.value\n )\n )\n\n onBeforeMount(() =>\n getStatistics(getApiParams(props.chartParams, props.user))\n )\n\n function getStatistics(apiParams: IStatisticsParams) {\n store.dispatch(STATS_STORE.ACTIONS.GET_USER_STATS, {\n username: props.user.username,\n filterType: 'by_time',\n params: apiParams,\n })\n }\n function updateDisplayData(\n event: Event & {\n target: HTMLInputElement & { name: TStatisticsDatasetKeys }\n }\n ) {\n displayedData.value = event.target.name\n }\n function getApiParams(\n chartParams: IStatisticsDateParams,\n user: IUserProfile\n ): IStatisticsParams {\n return {\n from: format(chartParams.start, 'yyyy-MM-dd'),\n to: format(chartParams.end, 'yyyy-MM-dd'),\n time:\n chartParams.duration === 'week'\n ? `week${user.weekm ? 'm' : ''}`\n : chartParams.duration,\n }\n }\n\n watch(\n () => props.chartParams,\n async (newParams) => {\n getStatistics(getApiParams(newParams, props.user))\n }\n )\n\n return {\n datasets: computed(\n () => formattedStats.value.datasets[displayedData.value]\n ),\n labels: computed(() => formattedStats.value.labels),\n emptyStats: computed(() => Object.keys(statistics.value).length === 0),\n displayedData,\n updateDisplayData,\n }\n },\n })\n","import { render } from \"./index.vue?vue&type=template&id=6eb9bb83&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=ts\"\nexport * from \"./index.vue?vue&type=script&lang=ts\"\n\nimport \"./index.vue?vue&type=style&index=0&id=6eb9bb83&lang=scss&scoped=true\"\nscript.render = render\nscript.__scopeId = \"data-v-6eb9bb83\"\n\nexport default script","'use strict';\nvar $ = require('../internals/export');\nvar isObject = require('../internals/is-object');\nvar isArray = require('../internals/is-array');\nvar toAbsoluteIndex = require('../internals/to-absolute-index');\nvar toLength = require('../internals/to-length');\nvar toIndexedObject = require('../internals/to-indexed-object');\nvar createProperty = require('../internals/create-property');\nvar wellKnownSymbol = require('../internals/well-known-symbol');\nvar arrayMethodHasSpeciesSupport = require('../internals/array-method-has-species-support');\n\nvar HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('slice');\n\nvar SPECIES = wellKnownSymbol('species');\nvar nativeSlice = [].slice;\nvar max = Math.max;\n\n// `Array.prototype.slice` method\n// https://tc39.es/ecma262/#sec-array.prototype.slice\n// fallback for not array-like ES3 strings and DOM objects\n$({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {\n slice: function slice(start, end) {\n var O = toIndexedObject(this);\n var length = toLength(O.length);\n var k = toAbsoluteIndex(start, length);\n var fin = toAbsoluteIndex(end === undefined ? length : end, length);\n // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible\n var Constructor, result, n;\n if (isArray(O)) {\n Constructor = O.constructor;\n // cross-realm fallback\n if (typeof Constructor == 'function' && (Constructor === Array || isArray(Constructor.prototype))) {\n Constructor = undefined;\n } else if (isObject(Constructor)) {\n Constructor = Constructor[SPECIES];\n if (Constructor === null) Constructor = undefined;\n }\n if (Constructor === Array || Constructor === undefined) {\n return nativeSlice.call(O, k, fin);\n }\n }\n result = new (Constructor === undefined ? Array : Constructor)(max(fin - k, 0));\n for (n = 0; k < fin; k++, n++) if (k in O) createProperty(result, n, O[k]);\n result.length = n;\n return result;\n }\n});\n"],"sourceRoot":""} |