Client - init utils methods needed for charts

This commit is contained in:
Sam
2021-08-22 20:16:04 +02:00
parent 0c516b9986
commit 3b8ac44433
15 changed files with 888 additions and 20 deletions

View File

@ -0,0 +1,42 @@
import {
addDays,
addMonths,
addYears,
startOfMonth,
startOfWeek,
startOfYear,
} from 'date-fns'
export const startDate = (
duration: string,
day: Date,
weekStartingMonday: boolean
): Date => {
switch (duration) {
case 'week':
return startOfWeek(day, { weekStartsOn: weekStartingMonday ? 1 : 0 })
case 'year':
return startOfYear(day)
case 'month':
return startOfMonth(day)
default:
throw new Error(
`Invalid duration, expected: "week", "month", "year", got: "${duration}"`
)
}
}
export const incrementDate = (duration: string, day: Date): Date => {
switch (duration) {
case 'week':
return addDays(day, 7)
case 'year':
return addYears(day, 1)
case 'month':
return addMonths(day, 1)
default:
throw new Error(
`Invalid duration, expected: "week", "month", "year", got: "${duration}"`
)
}
}

View File

@ -0,0 +1,47 @@
import { AxiosError } from 'axios'
import { ActionContext } from 'vuex'
import { ROOT_STORE } from '@/store/constants'
import { IRootState } from '@/store/modules/root/interfaces'
import { IStatisticsState } from '@/store/modules/statistics/interfaces'
import { IUserState } from '@/store/modules/user/interfaces'
export const getApiUrl = (): string => {
return process.env.NODE_ENV === 'production'
? '/api'
: `${process.env.VUE_APP_API_URL}/api/`
}
// TODO: update api error messages to remove these workarounds
const removeLastEndOfLine = (text: string): string => text.replace(/\n$/gm, '')
const removeLastDot = (text: string): string => text.replace(/\.$/gm, '')
export const handleError = (
context:
| ActionContext<IRootState, IRootState>
| ActionContext<IUserState, IRootState>
| ActionContext<IStatisticsState, IRootState>,
error: AxiosError | null,
msg = 'UNKNOWN'
): void => {
let errorMessages = !error
? msg
: error.response
? error.response.data.message
? error.response.data.message
: msg
: error.message
? error.message
: msg
errorMessages = removeLastEndOfLine(errorMessages)
context.commit(
ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES,
errorMessages.includes('\n')
? errorMessages
.split('\n')
.map((m: string) => `api.ERROR.${removeLastDot(m)}`)
: `api.ERROR.${removeLastDot(errorMessages)}`
)
}
export const capitalize = (text: string): string =>
text.charAt(0).toUpperCase() + text.slice(1)

View File

@ -0,0 +1,103 @@
import { format } from 'date-fns'
import { genericObject } from '@/types/generic'
import {
IStatisticsChartData,
IStatisticsChartDataset,
IStatisticsDateParams,
TDatasetKeys,
TStatisticsDatasets,
TStatisticsFromApi,
} from '@/types/statistics'
import { ISport } from '@/types/workouts'
import { incrementDate, startDate } from '@/utils/dates'
// date format from api
const dateFormats: genericObject = {
week: 'yyyy-MM-dd',
month: 'yyyy-MM',
year: 'yyyy',
}
const data: TDatasetKeys[] = ['nb_workouts', 'total_duration', 'total_distance']
export const getDateKeys = (
params: IStatisticsDateParams,
weekStartingMonday: boolean
): Date[] => {
const days = []
for (
let day = startDate(params.duration, params.start, weekStartingMonday);
day <= params.end;
day = incrementDate(params.duration, day)
) {
days.push(day)
}
return days
}
const getStatisticsChartDataset = (
sportLabel: string
): IStatisticsChartDataset =>
Object.assign(
{},
{
label: sportLabel,
backgroundColor: [],
data: [],
}
)
export const getDatasets = (displayedSports: ISport[]): TStatisticsDatasets => {
const datasets: TStatisticsDatasets = {
nb_workouts: [],
total_distance: [],
total_duration: [],
}
displayedSports.map((sport) => {
datasets.nb_workouts.push(getStatisticsChartDataset(sport.label))
datasets.total_distance.push(getStatisticsChartDataset(sport.label))
datasets.total_duration.push(getStatisticsChartDataset(sport.label))
})
return datasets
}
export const formatStats = (
params: IStatisticsDateParams,
weekStartingMonday: boolean,
sports: ISport[],
displayedSportsId: number[],
apiStats: TStatisticsFromApi
): IStatisticsChartData => {
const dayKeys = getDateKeys(params, weekStartingMonday)
const dateFormat = dateFormats[params.duration]
const displayedSports = sports.filter((sport) =>
displayedSportsId.length == 0 ? true : displayedSportsId.includes(sport.id)
)
const labels: string[] = []
const datasets = getDatasets(displayedSports)
const sportsId: Record<string, number> = {}
displayedSports.map(
(displayedSport) => (sportsId[displayedSport.label] = displayedSport.id)
)
dayKeys.map((key) => {
const date: string = format(key, dateFormat)
labels.push(date)
data.map((datasetKey) => {
datasets[datasetKey].map((dataset) =>
dataset.data.push(
apiStats !== {} &&
date in apiStats &&
sportsId[dataset.label] in apiStats[date]
? apiStats[date][sportsId[dataset.label]][datasetKey]
: null
)
)
})
})
return {
labels,
datasets,
}
}