Skip to content
Merged
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
5 changes: 3 additions & 2 deletions packages/alexa/src/helpers/report.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Report, Day, Entry } from '@lara/api'
import { getLaraConfig } from '../graphql/config'

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

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

export const finishedDays = async (days: ReducedDay[]): Promise<number> => {
const config = await getLaraConfig()
Expand Down
15 changes: 10 additions & 5 deletions packages/api/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Day implements CommentableInterface {
entries: [Entry!]!
id: ID!
status: DayStatusEnum
status_split: DayStatusEnum
}

enum DayStatusEnum {
Expand Down Expand Up @@ -87,13 +88,17 @@ type Entry implements CommentableInterface {
createdAt: String!
id: ID!
orderId: Int!
text: String!
time: Int!
text: String
time: Int
text_split: String
time_split: Int
}

input EntryInput {
text: String!
time: Int!
text: String
time: Int
text_split: String
time_split: Int
}

type OAuthPayload {
Expand Down Expand Up @@ -212,7 +217,7 @@ type Mutation {
"""
Updates day which is identified by the id argument.
"""
updateDay(status: String, id: ID!): Day
updateDay(status: String, status_split: String, id: ID!): Day
updateEntry(id: ID!, input: EntryInput!): MutateEntryPayload!
updateEntryOrder(entryId: ID!, dayId: ID!, orderId: Int!): MutateEntryPayload!

Expand Down
21 changes: 15 additions & 6 deletions packages/api/src/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type GqlDay = GqlCommentableInterface & {
entries: Array<GqlEntry>;
id: Scalars['ID']['output'];
status?: Maybe<GqlDayStatusEnum>;
status_split?: Maybe<GqlDayStatusEnum>;
};

export type GqlDayStatusEnum =
Expand Down Expand Up @@ -125,13 +126,17 @@ export type GqlEntry = GqlCommentableInterface & {
createdAt: Scalars['String']['output'];
id: Scalars['ID']['output'];
orderId: Scalars['Int']['output'];
text: Scalars['String']['output'];
time: Scalars['Int']['output'];
text?: Maybe<Scalars['String']['output']>;
text_split?: Maybe<Scalars['String']['output']>;
time?: Maybe<Scalars['Int']['output']>;
time_split?: Maybe<Scalars['Int']['output']>;
};

export type GqlEntryInput = {
text: Scalars['String']['input'];
time: Scalars['Int']['input'];
text?: InputMaybe<Scalars['String']['input']>;
text_split?: InputMaybe<Scalars['String']['input']>;
time?: InputMaybe<Scalars['Int']['input']>;
time_split?: InputMaybe<Scalars['Int']['input']>;
};

export type GqlLaraConfig = {
Expand Down Expand Up @@ -389,6 +394,7 @@ export type GqlMutationUpdateCurrentUserArgs = {
export type GqlMutationUpdateDayArgs = {
id: Scalars['ID']['input'];
status?: InputMaybe<Scalars['String']['input']>;
status_split?: InputMaybe<Scalars['String']['input']>;
};


Expand Down Expand Up @@ -854,6 +860,7 @@ export type GqlDayResolvers<ContextType = Context, ParentType extends GqlResolve
entries?: Resolver<Array<GqlResolversTypes['Entry']>, ParentType, ContextType>;
id?: Resolver<GqlResolversTypes['ID'], ParentType, ContextType>;
status?: Resolver<Maybe<GqlResolversTypes['DayStatusEnum']>, ParentType, ContextType>;
status_split?: Resolver<Maybe<GqlResolversTypes['DayStatusEnum']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;

Expand All @@ -873,8 +880,10 @@ export type GqlEntryResolvers<ContextType = Context, ParentType extends GqlResol
createdAt?: Resolver<GqlResolversTypes['String'], ParentType, ContextType>;
id?: Resolver<GqlResolversTypes['ID'], ParentType, ContextType>;
orderId?: Resolver<GqlResolversTypes['Int'], ParentType, ContextType>;
text?: Resolver<GqlResolversTypes['String'], ParentType, ContextType>;
time?: Resolver<GqlResolversTypes['Int'], ParentType, ContextType>;
text?: Resolver<Maybe<GqlResolversTypes['String']>, ParentType, ContextType>;
text_split?: Resolver<Maybe<GqlResolversTypes['String']>, ParentType, ContextType>;
time?: Resolver<Maybe<GqlResolversTypes['Int']>, ParentType, ContextType>;
time_split?: Resolver<Maybe<GqlResolversTypes['Int']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;

Expand Down
8 changes: 3 additions & 5 deletions packages/backend/src/resolvers/day.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const dayResolver: GqlResolvers<AuthenticatedContext> = {

export const dayTraineeResolver: GqlResolvers<TraineeContext> = {
Mutation: {
updateDay: async (_parent, { id, status }, { currentUser }) => {
updateDay: async (_parent, { id, status, status_split }, { currentUser }) => {
const reports = await reportsWithinApprenticeship(currentUser)

const { report, day } = reportDayByDayId(id, reports)
Expand All @@ -37,15 +37,13 @@ export const dayTraineeResolver: GqlResolvers<TraineeContext> = {
throw new GraphQLError(t('errors.wrongDayStatus'))
}

if (!status || !isDayStatus(status) || status === 'holiday') {
throw new GraphQLError(t('errors.wrongDayStatus'))
}
if (status && isDayStatus(status)) day.status = status

if (status === 'vacation' || status === 'sick') {
day.entries = []
}

day.status = status
if (status_split && isDayStatus(status_split)) day.status_split = status_split

await updateReport(report, { updateKeys: ['days'] })

Expand Down
6 changes: 5 additions & 1 deletion packages/backend/src/resolvers/entry.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export const entryTraineeResolver: GqlResolvers<TraineeContext> = {
report.days.forEach((day) => {
day.entries.forEach((entry) => {
const text = entry.text
tmp[text] = tmp[text] ? tmp[text] + 1 : 1
tmp[text ? text : entry.text_split!] = tmp[text ? text : entry.text_split!]
? tmp[text ? text : entry.text_split!] + 1
: 1
})
})
})
Expand Down Expand Up @@ -99,6 +101,8 @@ export const entryTraineeResolver: GqlResolvers<TraineeContext> = {

entry.text = input.text
entry.time = input.time
entry.text_split = input.text_split
entry.time_split = input.time_split

await updateReport(report, { updateKeys: ['days'] })

Expand Down
16 changes: 10 additions & 6 deletions packages/backend/src/resolvers/trainee.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,17 @@ export const traineeTraineeResolver: GqlResolvers<TraineeContext> = {
reports.forEach((report) => {
report.days.forEach((day) => {
day.entries.forEach((entry) => {
const { text, time } = entry

if (!textCountsWithTime[text]) {
textCountsWithTime[text] = { count: 0, duration: time, text: text }
const { text, time, text_split, time_split } = entry

if (!textCountsWithTime[text ? text : text_split!]) {
textCountsWithTime[text ? text : text_split!] = {
count: 0,
duration: time ? time : time_split!,
text: text ? text : text_split!,
}
}
textCountsWithTime[text].count += 1
textCountsWithTime[text].duration = time
textCountsWithTime[text ? text : text_split!].count += 1
textCountsWithTime[text ? text : text_split!].duration = time ? time : time_split!
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/services/day.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const dayMinutes = (day: Day): number => {
const status = dayStatus(day)

if (status === 'education' || status === 'work') {
return day.entries.reduce((accumulator, entry) => accumulator + entry.time, 0)
return day.entries.reduce((accumulator, entry) => accumulator + (entry.time ? entry.time : entry.time_split!), 0)
} else {
return 0
}
Expand Down
10 changes: 8 additions & 2 deletions packages/backend/src/services/entry.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,17 @@ export const validateEntryUpdate = (report: Report, day: Day, newEntry: Entry, l
entries: day.entries.filter((d) => d.id !== newEntry.id),
})

if (day.status === 'work' && minutes + newEntry.time > LaraConfig.maxWorkDayMinutes) {
if (
day.status === 'work' &&
minutes + (newEntry.time ? newEntry.time : newEntry.time_split!) > LaraConfig.maxWorkDayMinutes
) {
throw new GraphQLError(t('errors.dayTimeLimit'))
}

if (day.status === 'education' && minutes + newEntry.time > LaraConfig.maxEducationDayMinutes) {
if (
day.status === 'education' &&
minutes + (newEntry.time ? newEntry.time : newEntry.time_split!) > LaraConfig.maxEducationDayMinutes
) {
throw new GraphQLError(t('errors.dayTimeLimit'))
}

Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/services/print.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export const createPrintUserData = async (trainee: Trainee): Promise<PrintUserDa
* @returns Entry for print
*/
const transformEntry = (entry: Entry): PrintEntry => ({
text: entry.text,
time: entry.time,
text: entry.text ? entry.text : entry.text_split!,
time: entry.time ? entry.time : entry.time_split!,
orderId: entry.orderId,
})

Expand Down
1 change: 0 additions & 1 deletion packages/components/src/entry-input-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ export const EntryInputLayout: React.FC<EntryInputLayoutProps> = ({
clickHandler,
...rest
}) => {
console.log(term)
return (
<>
<StyledEntryContainer {...rest}>
Expand Down
1 change: 0 additions & 1 deletion packages/components/src/highlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const Highlighter: React.FC<highlighterProps> = ({ term, children }) => {
}
const regex = new RegExp(`(${term})`, 'gi')
const parts = children.split(regex)
console.log(parts)

return (
<>
Expand Down
15 changes: 10 additions & 5 deletions packages/frontend/src/components/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import { StyledCheckboxIcon, IconName, StyledCheckBox, StyledCheckBoxInput } fro
interface CheckBoxProps {
iconName: IconName
checked: boolean
disabled: boolean
onClick: () => void
}

export const CheckBox: React.FunctionComponent<CheckBoxProps> = ({ checked, iconName, onClick }) => {
export const CheckBox: React.FunctionComponent<CheckBoxProps> = ({ checked, iconName, disabled, onClick }) => {
return (
<StyledCheckBox onClick={onClick} checked={checked}>
<StyledCheckBoxInput type="checkbox" />
<StyledCheckboxIcon checked={checked} name={iconName} size={'44px'} />
</StyledCheckBox>
<>
{disabled || (
<StyledCheckBox onClick={onClick} checked={checked}>
<StyledCheckBoxInput type="checkbox" />
<StyledCheckboxIcon checked={checked} name={iconName} size={'44px'} />
</StyledCheckBox>
)}
</>
)
}
61 changes: 58 additions & 3 deletions packages/frontend/src/components/day-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ReportStatus,
useCreateCommentOnDayMutation,
useDayInputDataQuery,
useDayStatusSelectUpdateDayMutation,
UserInterface,
UserTypeEnum,
} from '../graphql'
Expand All @@ -22,6 +23,15 @@ import Loader from './loader'
import Total from './total'
import { useDayHelper } from '../helper/day-helper'
import { useToastContext } from '../hooks/use-toast-context'
import { CheckBox } from './checkbox'
import styled from 'styled-components'

const SecondaryWrapper = styled.div`
display: flex;
padding: 24px 24px;
justify-content: end;
align-items: center;
`

export interface EntryStatusType {
message?: string
Expand Down Expand Up @@ -51,12 +61,12 @@ export const StatusTypes = {
}

interface DayInputProps {
day?: Pick<Day, 'id' | 'date' | 'status'> & {
day: Pick<Day, 'id' | 'date' | 'status'> & {
comments: (Pick<Comment, 'id' | 'text' | 'published'> & {
user: Pick<UserInterface, 'id' | 'firstName' | 'lastName'>
})[]
} & {
entries: (Pick<Entry, 'id' | 'text' | 'time' | 'orderId'> & {
entries: (Pick<Entry, 'id' | 'text' | 'time' | 'orderId' | 'text_split'> & {
comments: (Pick<Comment, 'id' | 'text' | 'published'> & {
user: Pick<UserInterface, 'id' | 'firstName' | 'lastName'>
})[]
Expand Down Expand Up @@ -90,6 +100,7 @@ const DayInput: React.FunctionComponent<DayInputProps> = ({
term,
}) => {
const { getTotalMinutes } = useDayHelper()
const [mutate] = useDayStatusSelectUpdateDayMutation()
const { addToast } = useToastContext()

const { loading, data } = useDayInputDataQuery()
Expand All @@ -101,6 +112,11 @@ const DayInput: React.FunctionComponent<DayInputProps> = ({
icon: 'Loader',
})

const check_initial = () => day?.entries.reduce((acc, current) => (acc ? true : !!current.text_split), false)

const initial: boolean = check_initial() === true

const [halfDays, setHalfDays] = React.useState<boolean>(initial)
const [statusVisible, setStatusVisible] = React.useState(false)
const [statusTimeout, setStatusTimeout] = React.useState<number>()

Expand Down Expand Up @@ -200,6 +216,26 @@ const DayInput: React.FunctionComponent<DayInputProps> = ({
return null
}

const checkBox = () => {
setHalfDays(!halfDays)
const value = !halfDays ? 'work' : 'undefined'
const id = day.id
const status_split = value as DayStatusEnum
void mutate({
variables: {
id,
status_split,
},
optimisticResponse: {
updateDay: {
__typename: 'Day',
id,
status_split,
},
},
})
}

const InputHeading = primary ? H1 : H2

return (
Expand All @@ -208,7 +244,8 @@ const DayInput: React.FunctionComponent<DayInputProps> = ({
inputHeader={
<>
<InputHeading noMargin>{getHeading()}</InputHeading>
{day && <DayStatusSelect disabled={disabled} day={day} />}
<CheckBox disabled={!!disabled} iconName={'Checkbox'} checked={halfDays} onClick={checkBox} />
{day && <DayStatusSelect disabled={disabled} day={day} secondary={false} />}
</>
}
statusVisibility={statusVisible}
Expand Down Expand Up @@ -240,8 +277,26 @@ const DayInput: React.FunctionComponent<DayInputProps> = ({
reportStatus={reportStatus ?? ReportStatus.Todo}
disabled={Boolean(disabled)}
trainee={data.currentUser}
secondary={false}
updateMessage={updateMessageEntry}
/>
{halfDays && (
<>
<SecondaryWrapper>
{day && halfDays === true && <DayStatusSelect disabled={disabled} day={day} secondary={true} />}
</SecondaryWrapper>
<EntriesInput
term={term}
handleStatusChange={handleStatusChange}
day={day}
secondary={true}
reportStatus={reportStatus ?? ReportStatus.Todo}
disabled={Boolean(disabled)}
trainee={data.currentUser}
updateMessage={updateMessageEntry}
/>
</>
)}
</DayInputLayout>
)
}
Expand Down
Loading