Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/alexa/src/graphql/get-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const query = gql`
entries {
id
time
time_split
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/alexa/src/helpers/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getLaraConfig } from '../graphql/config'
type ReducedDay = Pick<Day, 'id' | 'status'> & { entries: Pick<Entry, 'time' | 'time_split'>[] }

const totalDayMinutes = (day: ReducedDay) =>
day.entries.reduce((acc, entry) => acc + (entry.time ? entry.time : entry.time_split!), 0)
day.entries.reduce((acc, entry) => acc + (entry.time ?? entry.time_split ?? 0), 0)

export const finishedDays = async (days: ReducedDay[]): Promise<number> => {
const config = await getLaraConfig()
Expand Down
13 changes: 9 additions & 4 deletions packages/frontend/src/components/entry-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,19 @@ const EntryInput: React.FC<EntryDisplayFieldProps> = ({
const handleSave = (newEntry: EntryInputType) => {
setEditing(false)

if (
!isValidTimeUpdate(day, newEntry.time ? newEntry.time - entry.time! : newEntry.time_split! - entry.time_split!)
) {
const previousTime = !secondary ? (entry.time ?? 0) : (entry.time_split ?? 0)
const nextTime = !secondary ? (newEntry.time ?? 0) : (newEntry.time_split ?? 0)

if (!isValidTimeUpdate(day, nextTime - previousTime)) {
addToast({ text: strings.entryStatus.changeError, type: 'error' })
return
}

if (newEntry.text === entry.text && newEntry.time === entry.time) {
const isUnchanged = !secondary
? newEntry.text === entry.text && newEntry.time === entry.time
: newEntry.text_split === entry.text_split && newEntry.time_split === entry.time_split

if (isUnchanged) {
return
}

Expand Down
11 changes: 9 additions & 2 deletions packages/frontend/src/components/suggestions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,14 @@ const Suggestions: React.FC<SuggestionProps> = ({ submitTextSuggestion, submitTi
case 'Enter':
// submit the suggestion if shift isn't pressed
if (!event.shiftKey && focusIndex > -1) {
setWaitingForBlur(suggestions[focusIndex])
event.preventDefault()
const suggestionsTextWithTime = suggestionsWithTimes[focusIndex]
if (suggestionsTextWithTime) {
setWaitingForBlur(suggestionsTextWithTime.text)
setWaitingForBlurTimeSuggestion(suggestionsTextWithTime.time)
} else {
setWaitingForBlur(suggestions[focusIndex])
}
}
break
case 'ArrowUp':
Expand Down Expand Up @@ -104,7 +111,7 @@ const Suggestions: React.FC<SuggestionProps> = ({ submitTextSuggestion, submitTi
break
}
},
[setWaitingForBlur, focusIndex, inputRef, suggestions]
[setWaitingForBlur, focusIndex, inputRef, suggestions, suggestionsWithTimes]
)

React.useEffect(() => {
Expand Down
13 changes: 9 additions & 4 deletions packages/frontend/src/graphql/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ export type CreateEntryMutationVariables = Exact<{
}>;


export type CreateEntryMutation = { __typename?: 'Mutation', createEntry: { __typename?: 'MutateEntryPayload', day: { __typename: 'Day', id: string, entries: Array<{ __typename?: 'Entry', id: string, text?: string | undefined, time?: number | undefined, orderId: number, comments: Array<{ __typename?: 'Comment', id: string }> }> } } };
export type CreateEntryMutation = { __typename?: 'Mutation', createEntry: { __typename?: 'MutateEntryPayload', day: { __typename: 'Day', id: string, entries: Array<{ __typename?: 'Entry', id: string, text?: string | undefined, time?: number | undefined, text_split?: string | undefined, time_split?: number | undefined, orderId: number, comments: Array<{ __typename?: 'Comment', id: string }> }> } } };

export type CreateOAuthCodeMutationVariables = Exact<{ [key: string]: never; }>;

Expand Down Expand Up @@ -973,7 +973,7 @@ export type AlexaLinkingUrlQuery = { __typename?: 'Query', alexaLinkingUrl?: str
export type ArchivePageDataQueryVariables = Exact<{ [key: string]: never; }>;


export type ArchivePageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | undefined, reports: Array<{ __typename: 'Report', id: string, week: number, year: number, status: ReportStatus, department?: string | undefined, summary?: string | undefined, traineeId: string, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time?: number | undefined, time_split?: number | undefined, text?: string | undefined, text_split?: string | undefined }> }> } | undefined> };
export type ArchivePageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | undefined, reports: Array<{ __typename: 'Report', id: string, week: number, year: number, status: ReportStatus, department?: string | undefined, summary?: string | undefined, traineeId: string, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time?: number | undefined, time_split?: number | undefined, text?: string | undefined }> }> } | undefined> };

export type AvatarSettingsDataQueryVariables = Exact<{ [key: string]: never; }>;

Expand Down Expand Up @@ -1001,7 +1001,7 @@ export type DashboardPageDataQueryVariables = Exact<{
}>;


export type DashboardPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined } | undefined, reports: Array<{ __typename: 'Report', id: string, week: number, year: number, status: ReportStatus, department?: string | undefined, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time?: number | undefined }> }> } | undefined>, reportForYearAndWeek?: { __typename?: 'Report', id: string, status: ReportStatus, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, date: string, id: string, entries: Array<{ __typename?: 'Entry', id: string, text?: string | undefined, time?: number | undefined, orderId: number, comments: Array<{ __typename?: 'Comment', id: string, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> }>, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> }> } | undefined };
export type DashboardPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined } | undefined, reports: Array<{ __typename: 'Report', id: string, week: number, year: number, status: ReportStatus, department?: string | undefined, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time?: number | undefined, time_split?: number | undefined }> }> } | undefined>, reportForYearAndWeek?: { __typename?: 'Report', id: string, status: ReportStatus, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, date: string, id: string, entries: Array<{ __typename?: 'Entry', id: string, text?: string | undefined, time?: number | undefined, time_split?: number | undefined, orderId: number, comments: Array<{ __typename?: 'Comment', id: string, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> }>, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> }> } | undefined };

export type DayInputDataQueryVariables = Exact<{ [key: string]: never; }>;

Expand Down Expand Up @@ -1245,6 +1245,9 @@ export const CreateEntryDocument = gql`
id
text
time
text_split
time_split
text_split
orderId
comments {
id
Expand Down Expand Up @@ -1971,7 +1974,7 @@ export const ArchivePageDataDocument = gql`
time
time_split
text
text_split
time_split
}
}
__typename
Expand Down Expand Up @@ -2122,6 +2125,7 @@ export const DashboardPageDataDocument = gql`
entries {
id
time
time_split
}
}
__typename
Expand All @@ -2137,6 +2141,7 @@ export const DashboardPageDataDocument = gql`
id
text
time
time_split
orderId
comments {
id
Expand Down
3 changes: 3 additions & 0 deletions packages/frontend/src/graphql/mutations/create-entry.gql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ mutation createEntry($dayId: String!, $input: EntryInput!) {
id
text
time
text_split
time_split
text_split
orderId
comments {
id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ query ArchivePageData {
time
time_split
text
text_split
time_split
}
}
__typename
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/src/graphql/queries/dashboard-page-data.gql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ query DashboardPageData($currentYear: Int!, $currentWeek: Int!) {
entries {
id
time
time_split
}
}
__typename
Expand All @@ -29,6 +30,7 @@ query DashboardPageData($currentYear: Int!, $currentWeek: Int!) {
id
text
time
time_split
orderId
comments {
id
Expand Down
25 changes: 16 additions & 9 deletions packages/frontend/src/helper/report-helper.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { DefaultTheme } from '@lara/components'

import { Day, DayStatusEnum, Entry, ReportStatus, useConfigQuery } from '../graphql'
import { useDayHelper } from './day-helper'

type ReportDay = Pick<Day, 'status'> & {
entries: Pick<Entry, 'time' | 'time_split'>[]
}

type UseReportHelper = {
getFinishedDays: (report: { days: (Pick<Day, 'status'> & { entries: Pick<Entry, 'time'>[] })[] }) => number
getProgress: (report: { days: (Pick<Day, 'status'> & { entries: Pick<Entry, 'time'>[] })[] }, value: number) => number
getFinishedDays: (report: { days: ReportDay[] }) => number
getProgress: (report: { days: ReportDay[] }, value: number) => number
getStatusColor: (reportStatus: ReportStatus) => keyof DefaultTheme
getTotalMinutes: (report: { days: (Pick<Day, 'status'> & { entries: Pick<Entry, 'time'>[] })[] }) => number
getTotalMinutes: (report: { days: ReportDay[] }) => number
}

const TraineeReportStatusColors: Record<ReportStatus, keyof DefaultTheme> = {
Expand All @@ -19,48 +22,52 @@ const TraineeReportStatusColors: Record<ReportStatus, keyof DefaultTheme> = {

export const useReportHelper = (): UseReportHelper => {
const { data } = useConfigQuery()
const { getTotalMinutes: getTotalDayMinutes } = useDayHelper()

const getStatusColor: UseReportHelper['getStatusColor'] = (reportStatus) => TraineeReportStatusColors[reportStatus]

const getDayMinutes = (day: ReportDay): number =>
day.entries.reduce((acc, entry) => acc + (entry.time ?? entry.time_split ?? 0), 0)

const getFinishedDays: UseReportHelper['getFinishedDays'] = (report) => {
let finishedDays = 0

const minEducationMinutes = data?.config.minEducationDayMinutes ?? 0
const minWorkMinutes = data?.config.minWorkDayMinutes ?? 180

report.days.forEach((day) => {
const minutes = getDayMinutes(day)

switch (day.status) {
case DayStatusEnum.Sick:
case DayStatusEnum.Vacation:
case DayStatusEnum.Holiday:
finishedDays++
break
case DayStatusEnum.Education:
if (getTotalDayMinutes(day) > minEducationMinutes) {
if (minutes > minEducationMinutes) {
finishedDays++
}
break
default:
if (getTotalDayMinutes(day) >= minWorkMinutes) {
if (minutes >= minWorkMinutes) {
finishedDays++
}
break
}
})

return finishedDays
}

const getProgress: UseReportHelper['getProgress'] = (report, value) => {
const done = value || getFinishedDays(report)

const finishedWeekDayCount = data?.config.finishedWeekDayCount ?? 5

return (done / finishedWeekDayCount) * 100
}

const getTotalMinutes: UseReportHelper['getTotalMinutes'] = (report) => {
return report.days.reduce((accumulator, day) => accumulator + getTotalDayMinutes(day), 0)
return report.days.reduce((accumulator, day) => accumulator + getDayMinutes(day), 0)
}

return {
Expand Down
6 changes: 5 additions & 1 deletion packages/frontend/src/helper/time-conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ class TimeConversion {
return parseInt(input, 10)
}
}
public static minutesToString(minutes: number): string {
public static minutesToString(minutes: number | null | undefined): string {
if (minutes === null || minutes === undefined || Number.isNaN(minutes)) {
return ''
}

const rest = minutes % 60
const hours = (minutes - rest) / 60
return `${hours}:${rest < 10 ? `0${rest}` : rest}`
Expand Down