diff --git a/packages/api/codegen.yml b/packages/api/codegen.yml index e9fda41b..cf35d78d 100644 --- a/packages/api/codegen.yml +++ b/packages/api/codegen.yml @@ -21,4 +21,6 @@ generates: Report: ./models#Report Trainer: ./models#Trainer Trainee: ./models#Trainee + Mentor: ./models#Mentor UserInterface: ./models#UserInterface + Paper: ./models#Paper diff --git a/packages/api/schema.gql b/packages/api/schema.gql index 738a33ef..ea8d6f91 100644 --- a/packages/api/schema.gql +++ b/packages/api/schema.gql @@ -6,6 +6,14 @@ type Comment { published: Boolean! } +type PaperComment { + text: String! + userId: ID! + lastName: String! + firstName: String! + published: Boolean! +} + """ An object that can have comments """ @@ -113,6 +121,70 @@ type UpdateReportPayload { report: Report! } +input MentorInput { + name: String + email: String + signature: String +} + +input PaperEntryInput { + id: ID! + questionId: ID! + question: String! + answer: String + hint: String + comments: [PaperCommentInput!]! +} + +type MutatePaperPayload { + papers: [Paper] +} + +input PaperInput { + traineeId: ID! + trainerId: ID! + client: String! + mentorId: ID! + periodStart: String + periodEnd: String + schoolPeriodStart: String + schoolPeriodEnd: String + subject: String! + status: PaperStatus! + briefing: [PaperEntryInput!]! + feedbackTrainee: [PaperEntryInput!]! + feedbackMentor: [PaperEntryInput!]! +} + +input PaperUpdateInput { + id: ID! + traineeId: ID! + trainerId: ID! + client: String! + mentorId: ID! + periodStart: String + periodEnd: String + schoolPeriodStart: String + schoolPeriodEnd: String + subject: String! + didSendEmail: Boolean! + status: PaperStatus! + briefing: [PaperEntryInput!]! + feedbackTrainee: [PaperEntryInput!]! + feedbackMentor: [PaperEntryInput!]! + fazit: FazitUpdateInput + mentorDone: Boolean + traineeDone: Boolean +} + +input AnswerPaperInput { + id: ID! + questionId: ID! + question: String! + answer: String! + hint: String! +} + type Mutation { """ [DEV] Login as a user. @@ -236,6 +308,16 @@ type Mutation { """ createAdmin(input: CreateAdminInput!): Admin + """ + Creates Mentor. + """ + createMentor(input: CreateMentorInput!): Mentor + + """ + Get a User by Email + """ + getUserByEmail(email: String!): UserInterface + """ Marks User to be deleted """ @@ -261,6 +343,11 @@ type Mutation { """ updateAdmin(input: UpdateAdminInput!, id: ID!): Admin + """ + Updates Mentor. + """ + updateMentor(input: UpdateMentorInput!, id: ID!): Mentor + """ Link Alexa account """ @@ -280,6 +367,55 @@ type Mutation { Get Avatar Bucket Upload URL """ getAvatarSignedUrl(id: String!): String + + """ + Create Paper + """ + createPaper(input: PaperInput!): Paper! + + """ + Update Paper + """ + updatePaper(input: PaperUpdateInput!): Paper! + + """ + Delete Paper + """ + deletePaper(paperId: ID!): [Paper]! + + """ + Updates Entry for Lara Paper + """ + updatePaperEntry(input: AnswerPaperInput!): PaperFormData! + + """ + Creates Entry for Lara Paper + """ + createPaperEntry(input: AnswerPaperInput!): PaperFormData! + + """ + Deletes Entry for Lara Paper + """ + deletePaperEntry(id: ID!): PaperFormData! + + """ + Updates a Fazit + """ + updateFazit(id: ID! content: String! version: Int! cursorPosition: CursorInput! mentorDone: Boolean traineeDone: Boolean): FazitUpdateResponse! + + """ + Update Fazit cursor position + """ + updateFazitCursorPos(id: ID!, cursorPosition: CursorInput!): Cursor + + """ + Updates if the pdf email was already sent + """ + didSendEmail(id: ID!, didSendEmail: Boolean!): didSendEmailResponse +} + +type didSendEmailResponse { + didSendEmail: Boolean } type LaraConfig { @@ -347,11 +483,21 @@ type Query { """ admins: [Admin!]! + """ + Get all Mentors + """ + mentors: [Mentor!]! + """ Print single report or report batch """ print(ids: [ID!]!): PrintPayload! + """ + Print single paper + """ + printPaper(ids: [ID!]! userType: UserTypeEnum!): PrintPayload! + """ Get a User by ID """ @@ -366,10 +512,21 @@ type Query { Get the alexa account linking url """ alexaLinkingUrl: String + + """ + Get the fazit with Id + """ + getFazit(id: ID!): Fazit + + """ + Get Paper with Id + """ + getPaper(id: ID!): Paper } type PrintPayload { estimatedWaitingTime: Int! + pdfUrl: String } type Report implements CommentableInterface { @@ -388,6 +545,14 @@ type Report implements CommentableInterface { nextReportLink: String } +input PaperCommentInput { + text: String! + userId: ID! + firstName: String! + lastName: String! + published: Boolean! +} + """ Represents the current state of the report """ @@ -425,6 +590,7 @@ type Trainee implements UserInterface { lastName: String! notification: Boolean reports: [Report!]! + papers: [Paper] signature: String startDate: String startOfToolUsage: String @@ -467,12 +633,61 @@ input CreateTrainerInput { lastName: String! } +input CreateMentorInput { + email: String! + firstName: String! + lastName: String! + startDate: String + endDate: String +} + input UpdateTrainerInput { email: String firstName: String lastName: String } +input UpdateMentorInput { + email: String + firstName: String + lastName: String + startDate: String + endDate: String +} + +type Cursor { + position: Int! + owner: String! +} + +input CursorInput { + position: Int! + owner: String! +} + +type Fazit { + id: ID! + content: String! + version: Int! + cursorPositions: [Cursor!]! + mentorDone: Boolean + traineeDone: Boolean +} + +type FazitUpdateResponse { + success: Boolean! + newFazit: Fazit! +} + +input FazitUpdateInput { + id: ID! + content: String! + version: Int! + cursorPositions: [CursorInput!]! + mentorDone: Boolean + traineeDone: Boolean +} + type Trainer implements UserInterface { createdAt: String! firstName: String! @@ -480,6 +695,7 @@ type Trainer implements UserInterface { language: String lastName: String! notification: Boolean + papers: [Paper] signature: String theme: String trainees: [Trainee!]! @@ -501,6 +717,24 @@ input UpdateAdminInput { lastName: String } +type Mentor implements UserInterface { + createdAt: String! + firstName: String! + id: ID! + language: String + lastName: String! + notification: Boolean + signature: String + theme: String + type: UserTypeEnum! + papers: [Paper] + startDate: String + endDate: String + email: String! + deleteAt: String + alexaSkillLinked: Boolean +} + type Admin implements UserInterface { createdAt: String! firstName: String! @@ -553,8 +787,54 @@ enum UserTypeEnum { """ Trainer + """ + User is a Mentor + """ + Mentor + """ User is an Admin """ Admin } + +enum PaperStatus { + NotStarted + InProgress + TraineeDone + MentorDone + InReview + ReviewDone + Archived +} + +type PaperFormData { + id: ID! + questionId: ID! + question: String! + answer: String + hint: String + comments: [PaperComment!]! +} + +type Paper { + id: ID! + traineeId: ID! + trainerId: ID! + status: PaperStatus! + briefing: [PaperFormData!]! + feedbackTrainee: [PaperFormData!]! + feedbackMentor: [PaperFormData!]! + conclusion: String + archivedAt: String + createdAt: String + client: String! + mentorId: ID! + didSendEmail: Boolean! + periodStart: String + periodEnd: String + schoolPeriodStart: String + schoolPeriodEnd: String + subject: String! + fazit: Fazit +} diff --git a/packages/api/src/context.ts b/packages/api/src/context.ts index 9de45bb2..6a05d34f 100644 --- a/packages/api/src/context.ts +++ b/packages/api/src/context.ts @@ -1,14 +1,14 @@ import { APIGatewayProxyEvent, Context as AWSContext } from 'aws-lambda' import { Request, Response } from 'express' -import { Trainee, Trainer, Admin, User } from './models' +import { Trainee, Trainer, Admin, Mentor, User } from './models' type ExpressContext = { req: Request res: Response } -type BaseContext = { +export type BaseContext = { event: APIGatewayProxyEvent express: ExpressContext } @@ -29,6 +29,10 @@ export type TraineeContext = BaseContext & { currentUser: Trainee } +export type MentorContext = BaseContext & { + currentUser: Mentor +} + export type AdminContext = BaseContext & { currentUser: Admin } diff --git a/packages/api/src/email.ts b/packages/api/src/email.ts index 88781702..57699f8d 100644 --- a/packages/api/src/email.ts +++ b/packages/api/src/email.ts @@ -47,6 +47,16 @@ export type ExportMailPayload = BaseEmailPayload & { ] } +export type PaperBriefingMailPayload = BaseEmailPayload & { + emailType: 'paperBriefing' + userData: BaseMailUserData + attachments: [ + { + filename: string + }, + ] +} + export type SimpleMailPayload = BaseEmailPayload & { emailType: 'deleteAccount' | 'error' | 'alexa' userData: BaseMailUserData @@ -59,6 +69,7 @@ export type EmailPayload = | SimpleMailPayload | ExportMailPayload | ReportInReviewPayload + | PaperBriefingMailPayload export type EmailType = EmailPayload['emailType'] @@ -76,6 +87,8 @@ export type EmailTranslations = { deleteUser: string reportInReview: string alexa: string + paperBriefing: string + paperBriefingMail: string } headline: { export: string @@ -86,6 +99,7 @@ export type EmailTranslations = { deleteUser: string handOver: string alexa: string + paperBriefing: string } message: { error: string @@ -97,10 +111,12 @@ export type EmailTranslations = { deleteUser: string handOver: string alexa: string + paperBriefing: string } link: { archive: string report: string + paperBriefing: string lara: string settings: string } diff --git a/packages/api/src/graphql.ts b/packages/api/src/graphql.ts index 26dfc8a5..fa68b9ee 100644 --- a/packages/api/src/graphql.ts +++ b/packages/api/src/graphql.ts @@ -1,5 +1,5 @@ import { GraphQLResolveInfo } from 'graphql'; -import { CommentableInterface, Comment, Entry, Day, Report, Trainer, Trainee, UserInterface } from './models'; +import { CommentableInterface, Comment, Entry, Day, Report, Trainer, Trainee, Mentor, UserInterface, Paper } from './models'; import { Context } from './context'; export type Maybe = T | undefined; export type InputMaybe = T | undefined; @@ -35,6 +35,14 @@ export type GqlAdmin = GqlUserInterface & { type: GqlUserTypeEnum; }; +export type GqlAnswerPaperInput = { + answer: Scalars['String']['input']; + hint: Scalars['String']['input']; + id: Scalars['ID']['input']; + question: Scalars['String']['input']; + questionId: Scalars['ID']['input']; +}; + export type GqlComment = { __typename?: 'Comment'; createdAt: Scalars['String']['output']; @@ -69,6 +77,14 @@ export type GqlCreateCommentPayload = { commentable: GqlCommentableInterface; }; +export type GqlCreateMentorInput = { + email: Scalars['String']['input']; + endDate?: InputMaybe; + firstName: Scalars['String']['input']; + lastName: Scalars['String']['input']; + startDate?: InputMaybe; +}; + export type GqlCreateTraineeInput = { companyId: Scalars['String']['input']; email: Scalars['String']['input']; @@ -85,6 +101,17 @@ export type GqlCreateTrainerInput = { lastName: Scalars['String']['input']; }; +export type GqlCursor = { + __typename?: 'Cursor'; + owner: Scalars['String']['output']; + position: Scalars['Int']['output']; +}; + +export type GqlCursorInput = { + owner: Scalars['String']['input']; + position: Scalars['Int']['input']; +}; + export type GqlDay = GqlCommentableInterface & { __typename?: 'Day'; comments: Array; @@ -134,6 +161,31 @@ export type GqlEntryInput = { time: Scalars['Int']['input']; }; +export type GqlFazit = { + __typename?: 'Fazit'; + content: Scalars['String']['output']; + cursorPositions: Array; + id: Scalars['ID']['output']; + mentorDone?: Maybe; + traineeDone?: Maybe; + version: Scalars['Int']['output']; +}; + +export type GqlFazitUpdateInput = { + content: Scalars['String']['input']; + cursorPositions: Array; + id: Scalars['ID']['input']; + mentorDone?: InputMaybe; + traineeDone?: InputMaybe; + version: Scalars['Int']['input']; +}; + +export type GqlFazitUpdateResponse = { + __typename?: 'FazitUpdateResponse'; + newFazit: GqlFazit; + success: Scalars['Boolean']['output']; +}; + export type GqlLaraConfig = { __typename?: 'LaraConfig'; expectedWorkDayMinutes: Scalars['Int']['output']; @@ -146,6 +198,31 @@ export type GqlLaraConfig = { minWorkDayMinutes: Scalars['Int']['output']; }; +export type GqlMentor = GqlUserInterface & { + __typename?: 'Mentor'; + alexaSkillLinked?: Maybe; + createdAt: Scalars['String']['output']; + deleteAt?: Maybe; + email: Scalars['String']['output']; + endDate?: Maybe; + firstName: Scalars['String']['output']; + id: Scalars['ID']['output']; + language?: Maybe; + lastName: Scalars['String']['output']; + notification?: Maybe; + papers?: Maybe>>; + signature?: Maybe; + startDate?: Maybe; + theme?: Maybe; + type: GqlUserTypeEnum; +}; + +export type GqlMentorInput = { + email?: InputMaybe; + name?: InputMaybe; + signature?: InputMaybe; +}; + export type GqlMutateEntryPayload = { __typename?: 'MutateEntryPayload'; day: GqlDay; @@ -153,6 +230,11 @@ export type GqlMutateEntryPayload = { report: GqlReport; }; +export type GqlMutatePaperPayload = { + __typename?: 'MutatePaperPayload'; + papers?: Maybe>>; +}; + export type GqlMutation = { __typename?: 'Mutation'; /** [DEV] Login as a user. */ @@ -171,8 +253,14 @@ export type GqlMutation = { createCommentOnReport: GqlCreateCommentPayload; /** Creates a new entry which is assigned to the matching report based on the day Id */ createEntry: GqlMutateEntryPayload; + /** Creates Mentor. */ + createMentor?: Maybe; /** Create OAuth Code */ createOAuthCode: Scalars['String']['output']; + /** Create Paper */ + createPaper: GqlPaper; + /** Creates Entry for Lara Paper */ + createPaperEntry: GqlPaperFormData; /** Creates Trainee. */ createTrainee?: Maybe; /** Creates Trainer. */ @@ -185,8 +273,16 @@ export type GqlMutation = { deleteCommentOnReport: GqlDeleteCommentPayload; /** Deletes an entry by the given ID. Only considers entries made by the current user. Returns the ID of the deleted entry. */ deleteEntry: GqlMutateEntryPayload; + /** Delete Paper */ + deletePaper: Array>; + /** Deletes Entry for Lara Paper */ + deletePaperEntry: GqlPaperFormData; + /** Updates if the pdf email was already sent */ + didSendEmail?: Maybe; /** Get Avatar Bucket Upload URL */ getAvatarSignedUrl?: Maybe; + /** Get a User by Email */ + getUserByEmail?: Maybe; /** Link Alexa account */ linkAlexa?: Maybe; /** Login via microsoft */ @@ -217,6 +313,16 @@ export type GqlMutation = { updateDay?: Maybe; updateEntry: GqlMutateEntryPayload; updateEntryOrder: GqlMutateEntryPayload; + /** Updates a Fazit */ + updateFazit: GqlFazitUpdateResponse; + /** Update Fazit cursor position */ + updateFazitCursorPos?: Maybe; + /** Updates Mentor. */ + updateMentor?: Maybe; + /** Update Paper */ + updatePaper: GqlPaper; + /** Updates Entry for Lara Paper */ + updatePaperEntry: GqlPaperFormData; /** Updates report which is identified by the id argument. */ updateReport?: Maybe; /** Updates Trainee. */ @@ -273,6 +379,21 @@ export type GqlMutationCreateEntryArgs = { }; +export type GqlMutationCreateMentorArgs = { + input: GqlCreateMentorInput; +}; + + +export type GqlMutationCreatePaperArgs = { + input: GqlPaperInput; +}; + + +export type GqlMutationCreatePaperEntryArgs = { + input: GqlAnswerPaperInput; +}; + + export type GqlMutationCreateTraineeArgs = { input: GqlCreateTraineeInput; }; @@ -309,11 +430,32 @@ export type GqlMutationDeleteEntryArgs = { }; +export type GqlMutationDeletePaperArgs = { + paperId: Scalars['ID']['input']; +}; + + +export type GqlMutationDeletePaperEntryArgs = { + id: Scalars['ID']['input']; +}; + + +export type GqlMutationDidSendEmailArgs = { + didSendEmail: Scalars['Boolean']['input']; + id: Scalars['ID']['input']; +}; + + export type GqlMutationGetAvatarSignedUrlArgs = { id: Scalars['String']['input']; }; +export type GqlMutationGetUserByEmailArgs = { + email: Scalars['String']['input']; +}; + + export type GqlMutationLinkAlexaArgs = { code: Scalars['String']['input']; state: Scalars['String']['input']; @@ -405,6 +547,38 @@ export type GqlMutationUpdateEntryOrderArgs = { }; +export type GqlMutationUpdateFazitArgs = { + content: Scalars['String']['input']; + cursorPosition: GqlCursorInput; + id: Scalars['ID']['input']; + mentorDone?: InputMaybe; + traineeDone?: InputMaybe; + version: Scalars['Int']['input']; +}; + + +export type GqlMutationUpdateFazitCursorPosArgs = { + cursorPosition: GqlCursorInput; + id: Scalars['ID']['input']; +}; + + +export type GqlMutationUpdateMentorArgs = { + id: Scalars['ID']['input']; + input: GqlUpdateMentorInput; +}; + + +export type GqlMutationUpdatePaperArgs = { + input: GqlPaperUpdateInput; +}; + + +export type GqlMutationUpdatePaperEntryArgs = { + input: GqlAnswerPaperInput; +}; + + export type GqlMutationUpdateReportArgs = { department?: InputMaybe; id: Scalars['ID']['input']; @@ -431,9 +605,113 @@ export type GqlOAuthPayload = { refreshToken?: Maybe; }; +export type GqlPaper = { + __typename?: 'Paper'; + archivedAt?: Maybe; + briefing: Array; + client: Scalars['String']['output']; + conclusion?: Maybe; + createdAt?: Maybe; + didSendEmail: Scalars['Boolean']['output']; + fazit?: Maybe; + feedbackMentor: Array; + feedbackTrainee: Array; + id: Scalars['ID']['output']; + mentorId: Scalars['ID']['output']; + periodEnd?: Maybe; + periodStart?: Maybe; + schoolPeriodEnd?: Maybe; + schoolPeriodStart?: Maybe; + status: GqlPaperStatus; + subject: Scalars['String']['output']; + traineeId: Scalars['ID']['output']; + trainerId: Scalars['ID']['output']; +}; + +export type GqlPaperComment = { + __typename?: 'PaperComment'; + firstName: Scalars['String']['output']; + lastName: Scalars['String']['output']; + published: Scalars['Boolean']['output']; + text: Scalars['String']['output']; + userId: Scalars['ID']['output']; +}; + +export type GqlPaperCommentInput = { + firstName: Scalars['String']['input']; + lastName: Scalars['String']['input']; + published: Scalars['Boolean']['input']; + text: Scalars['String']['input']; + userId: Scalars['ID']['input']; +}; + +export type GqlPaperEntryInput = { + answer?: InputMaybe; + comments: Array; + hint?: InputMaybe; + id: Scalars['ID']['input']; + question: Scalars['String']['input']; + questionId: Scalars['ID']['input']; +}; + +export type GqlPaperFormData = { + __typename?: 'PaperFormData'; + answer?: Maybe; + comments: Array; + hint?: Maybe; + id: Scalars['ID']['output']; + question: Scalars['String']['output']; + questionId: Scalars['ID']['output']; +}; + +export type GqlPaperInput = { + briefing: Array; + client: Scalars['String']['input']; + feedbackMentor: Array; + feedbackTrainee: Array; + mentorId: Scalars['ID']['input']; + periodEnd?: InputMaybe; + periodStart?: InputMaybe; + schoolPeriodEnd?: InputMaybe; + schoolPeriodStart?: InputMaybe; + status: GqlPaperStatus; + subject: Scalars['String']['input']; + traineeId: Scalars['ID']['input']; + trainerId: Scalars['ID']['input']; +}; + +export type GqlPaperStatus = + | 'Archived' + | 'InProgress' + | 'InReview' + | 'MentorDone' + | 'NotStarted' + | 'ReviewDone' + | 'TraineeDone'; + +export type GqlPaperUpdateInput = { + briefing: Array; + client: Scalars['String']['input']; + didSendEmail: Scalars['Boolean']['input']; + fazit?: InputMaybe; + feedbackMentor: Array; + feedbackTrainee: Array; + id: Scalars['ID']['input']; + mentorId: Scalars['ID']['input']; + periodEnd?: InputMaybe; + periodStart?: InputMaybe; + schoolPeriodEnd?: InputMaybe; + schoolPeriodStart?: InputMaybe; + status: GqlPaperStatus; + subject: Scalars['String']['input']; + traineeId: Scalars['ID']['input']; + trainerId: Scalars['ID']['input']; +}; + export type GqlPrintPayload = { __typename?: 'PrintPayload'; estimatedWaitingTime: Scalars['Int']['output']; + pdfUrl?: Maybe; }; export type GqlPublishCommentsPayload = { @@ -453,10 +731,18 @@ export type GqlQuery = { config: GqlLaraConfig; /** Returns the logged in user. This user can be either a Trainee or a Trainer. */ currentUser?: Maybe; + /** Get the fazit with Id */ + getFazit?: Maybe; + /** Get Paper with Id */ + getPaper?: Maybe; /** Get a User by ID */ getUser?: Maybe; + /** Get all Mentors */ + mentors: Array; /** Print single report or report batch */ print: GqlPrintPayload; + /** Print single paper */ + printPaper: GqlPrintPayload; /** Finds the report for a specifig trainee on the requested year and week. */ reportForTrainee?: Maybe; /** Finds the report for the requested year and week. */ @@ -472,6 +758,16 @@ export type GqlQuery = { }; +export type GqlQueryGetFazitArgs = { + id: Scalars['ID']['input']; +}; + + +export type GqlQueryGetPaperArgs = { + id: Scalars['ID']['input']; +}; + + export type GqlQueryGetUserArgs = { id: Scalars['ID']['input']; }; @@ -482,6 +778,12 @@ export type GqlQueryPrintArgs = { }; +export type GqlQueryPrintPaperArgs = { + ids: Array; + userType: GqlUserTypeEnum; +}; + + export type GqlQueryReportForTraineeArgs = { id: Scalars['ID']['input']; week: Scalars['Int']['input']; @@ -549,6 +851,7 @@ export type GqlTrainee = GqlUserInterface & { lastName: Scalars['String']['output']; notification?: Maybe; openReportsCount: Scalars['Int']['output']; + papers?: Maybe>>; reports: Array; signature?: Maybe; startDate?: Maybe; @@ -569,6 +872,7 @@ export type GqlTrainer = GqlUserInterface & { language?: Maybe; lastName: Scalars['String']['output']; notification?: Maybe; + papers?: Maybe>>; signature?: Maybe; theme?: Maybe; trainees: Array; @@ -597,6 +901,14 @@ export type GqlUpdateCurrentTraineeInput = { course?: InputMaybe; }; +export type GqlUpdateMentorInput = { + email?: InputMaybe; + endDate?: InputMaybe; + firstName?: InputMaybe; + lastName?: InputMaybe; + startDate?: InputMaybe; +}; + export type GqlUpdateReportPayload = { __typename?: 'UpdateReportPayload'; report: GqlReport; @@ -643,11 +955,18 @@ export type GqlUserInterface = { export type GqlUserTypeEnum = /** User is an Admin */ | 'Admin' + /** User is a Mentor */ + | 'Mentor' /** User is a Trainee */ | 'Trainee' /** User is a Trainer */ | 'Trainer'; +export type GqlDidSendEmailResponse = { + __typename?: 'didSendEmailResponse'; + didSendEmail?: Maybe; +}; + export type WithIndex = TObject & Record; export type ResolversObject = WithIndex; @@ -721,26 +1040,44 @@ export type DirectiveResolverFn; + AnswerPaperInput: GqlAnswerPaperInput; Boolean: ResolverTypeWrapper; Comment: ResolverTypeWrapper; CommentableInterface: ResolverTypeWrapper; Company: ResolverTypeWrapper; CreateAdminInput: GqlCreateAdminInput; CreateCommentPayload: ResolverTypeWrapper & { comment: GqlResolversTypes['Comment'], commentable: GqlResolversTypes['CommentableInterface'] }>; + CreateMentorInput: GqlCreateMentorInput; CreateTraineeInput: GqlCreateTraineeInput; CreateTrainerInput: GqlCreateTrainerInput; + Cursor: ResolverTypeWrapper; + CursorInput: GqlCursorInput; Day: ResolverTypeWrapper; DayStatusEnum: GqlDayStatusEnum; DeleteCommentPayload: ResolverTypeWrapper & { comment: GqlResolversTypes['Comment'], commentable: GqlResolversTypes['CommentableInterface'] }>; DevSetUserPayload: ResolverTypeWrapper & { user?: Maybe }>; Entry: ResolverTypeWrapper; EntryInput: GqlEntryInput; + Fazit: ResolverTypeWrapper; + FazitUpdateInput: GqlFazitUpdateInput; + FazitUpdateResponse: ResolverTypeWrapper; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; LaraConfig: ResolverTypeWrapper; + Mentor: ResolverTypeWrapper; + MentorInput: GqlMentorInput; MutateEntryPayload: ResolverTypeWrapper & { day: GqlResolversTypes['Day'], entry?: Maybe, report: GqlResolversTypes['Report'] }>; + MutatePaperPayload: ResolverTypeWrapper & { papers?: Maybe>> }>; Mutation: ResolverTypeWrapper<{}>; OAuthPayload: ResolverTypeWrapper; + Paper: ResolverTypeWrapper; + PaperComment: ResolverTypeWrapper; + PaperCommentInput: GqlPaperCommentInput; + PaperEntryInput: GqlPaperEntryInput; + PaperFormData: ResolverTypeWrapper; + PaperInput: GqlPaperInput; + PaperStatus: GqlPaperStatus; + PaperUpdateInput: GqlPaperUpdateInput; PrintPayload: ResolverTypeWrapper; PublishCommentsPayload: ResolverTypeWrapper & { report: GqlResolversTypes['Report'] }>; Query: ResolverTypeWrapper<{}>; @@ -754,36 +1091,55 @@ export type GqlResolversTypes = ResolversObject<{ UpdateAdminInput: GqlUpdateAdminInput; UpdateCommentPayload: ResolverTypeWrapper & { comment: GqlResolversTypes['Comment'], commentable: GqlResolversTypes['CommentableInterface'] }>; UpdateCurrentTraineeInput: GqlUpdateCurrentTraineeInput; + UpdateMentorInput: GqlUpdateMentorInput; UpdateReportPayload: ResolverTypeWrapper & { report: GqlResolversTypes['Report'], trainee: GqlResolversTypes['Trainee'] }>; UpdateTraineeInput: GqlUpdateTraineeInput; UpdateTrainerInput: GqlUpdateTrainerInput; UserInput: GqlUserInput; UserInterface: ResolverTypeWrapper; UserTypeEnum: GqlUserTypeEnum; + didSendEmailResponse: ResolverTypeWrapper; }>; /** Mapping between all available schema types and the resolvers parents */ export type GqlResolversParentTypes = ResolversObject<{ Admin: GqlAdmin; + AnswerPaperInput: GqlAnswerPaperInput; Boolean: Scalars['Boolean']['output']; Comment: Comment; CommentableInterface: CommentableInterface; Company: GqlCompany; CreateAdminInput: GqlCreateAdminInput; CreateCommentPayload: Omit & { comment: GqlResolversParentTypes['Comment'], commentable: GqlResolversParentTypes['CommentableInterface'] }; + CreateMentorInput: GqlCreateMentorInput; CreateTraineeInput: GqlCreateTraineeInput; CreateTrainerInput: GqlCreateTrainerInput; + Cursor: GqlCursor; + CursorInput: GqlCursorInput; Day: Day; DeleteCommentPayload: Omit & { comment: GqlResolversParentTypes['Comment'], commentable: GqlResolversParentTypes['CommentableInterface'] }; DevSetUserPayload: Omit & { user?: Maybe }; Entry: Entry; EntryInput: GqlEntryInput; + Fazit: GqlFazit; + FazitUpdateInput: GqlFazitUpdateInput; + FazitUpdateResponse: GqlFazitUpdateResponse; ID: Scalars['ID']['output']; Int: Scalars['Int']['output']; LaraConfig: GqlLaraConfig; + Mentor: Mentor; + MentorInput: GqlMentorInput; MutateEntryPayload: Omit & { day: GqlResolversParentTypes['Day'], entry?: Maybe, report: GqlResolversParentTypes['Report'] }; + MutatePaperPayload: Omit & { papers?: Maybe>> }; Mutation: {}; OAuthPayload: GqlOAuthPayload; + Paper: Paper; + PaperComment: GqlPaperComment; + PaperCommentInput: GqlPaperCommentInput; + PaperEntryInput: GqlPaperEntryInput; + PaperFormData: GqlPaperFormData; + PaperInput: GqlPaperInput; + PaperUpdateInput: GqlPaperUpdateInput; PrintPayload: GqlPrintPayload; PublishCommentsPayload: Omit & { report: GqlResolversParentTypes['Report'] }; Query: {}; @@ -796,11 +1152,13 @@ export type GqlResolversParentTypes = ResolversObject<{ UpdateAdminInput: GqlUpdateAdminInput; UpdateCommentPayload: Omit & { comment: GqlResolversParentTypes['Comment'], commentable: GqlResolversParentTypes['CommentableInterface'] }; UpdateCurrentTraineeInput: GqlUpdateCurrentTraineeInput; + UpdateMentorInput: GqlUpdateMentorInput; UpdateReportPayload: Omit & { report: GqlResolversParentTypes['Report'], trainee: GqlResolversParentTypes['Trainee'] }; UpdateTraineeInput: GqlUpdateTraineeInput; UpdateTrainerInput: GqlUpdateTrainerInput; UserInput: GqlUserInput; UserInterface: UserInterface; + didSendEmailResponse: GqlDidSendEmailResponse; }>; export type GqlAdminResolvers = ResolversObject<{ @@ -847,6 +1205,12 @@ export type GqlCreateCommentPayloadResolvers; }>; +export type GqlCursorResolvers = ResolversObject<{ + owner?: Resolver; + position?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlDayResolvers = ResolversObject<{ comments?: Resolver, ParentType, ContextType>; createdAt?: Resolver; @@ -878,6 +1242,22 @@ export type GqlEntryResolvers; }>; +export type GqlFazitResolvers = ResolversObject<{ + content?: Resolver; + cursorPositions?: Resolver, ParentType, ContextType>; + id?: Resolver; + mentorDone?: Resolver, ParentType, ContextType>; + traineeDone?: Resolver, ParentType, ContextType>; + version?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + +export type GqlFazitUpdateResponseResolvers = ResolversObject<{ + newFazit?: Resolver; + success?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlLaraConfigResolvers = ResolversObject<{ expectedWorkDayMinutes?: Resolver; finishedWeekDayCount?: Resolver; @@ -890,6 +1270,25 @@ export type GqlLaraConfigResolvers; }>; +export type GqlMentorResolvers = ResolversObject<{ + alexaSkillLinked?: Resolver, ParentType, ContextType>; + createdAt?: Resolver; + deleteAt?: Resolver, ParentType, ContextType>; + email?: Resolver; + endDate?: Resolver, ParentType, ContextType>; + firstName?: Resolver; + id?: Resolver; + language?: Resolver, ParentType, ContextType>; + lastName?: Resolver; + notification?: Resolver, ParentType, ContextType>; + papers?: Resolver>>, ParentType, ContextType>; + signature?: Resolver, ParentType, ContextType>; + startDate?: Resolver, ParentType, ContextType>; + theme?: Resolver, ParentType, ContextType>; + type?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlMutateEntryPayloadResolvers = ResolversObject<{ day?: Resolver; entry?: Resolver, ParentType, ContextType>; @@ -897,6 +1296,11 @@ export type GqlMutateEntryPayloadResolvers; }>; +export type GqlMutatePaperPayloadResolvers = ResolversObject<{ + papers?: Resolver>>, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlMutationResolvers = ResolversObject<{ _devloginuser?: Resolver, ParentType, ContextType, RequireFields>; _devsetusertype?: Resolver>; @@ -906,14 +1310,21 @@ export type GqlMutationResolvers>; createCommentOnReport?: Resolver>; createEntry?: Resolver>; + createMentor?: Resolver, ParentType, ContextType, RequireFields>; createOAuthCode?: Resolver; + createPaper?: Resolver>; + createPaperEntry?: Resolver>; createTrainee?: Resolver, ParentType, ContextType, RequireFields>; createTrainer?: Resolver, ParentType, ContextType, RequireFields>; deleteCommentOnDay?: Resolver>; deleteCommentOnEntry?: Resolver>; deleteCommentOnReport?: Resolver>; deleteEntry?: Resolver>; + deletePaper?: Resolver>, ParentType, ContextType, RequireFields>; + deletePaperEntry?: Resolver>; + didSendEmail?: Resolver, ParentType, ContextType, RequireFields>; getAvatarSignedUrl?: Resolver, ParentType, ContextType, RequireFields>; + getUserByEmail?: Resolver, ParentType, ContextType, RequireFields>; linkAlexa?: Resolver, ParentType, ContextType, RequireFields>; login?: Resolver, ParentType, ContextType, RequireFields>; markUserForDeletion?: Resolver, ParentType, ContextType, RequireFields>; @@ -930,6 +1341,11 @@ export type GqlMutationResolvers, ParentType, ContextType, RequireFields>; updateEntry?: Resolver>; updateEntryOrder?: Resolver>; + updateFazit?: Resolver>; + updateFazitCursorPos?: Resolver, ParentType, ContextType, RequireFields>; + updateMentor?: Resolver, ParentType, ContextType, RequireFields>; + updatePaper?: Resolver>; + updatePaperEntry?: Resolver>; updateReport?: Resolver, ParentType, ContextType, RequireFields>; updateTrainee?: Resolver, ParentType, ContextType, RequireFields>; updateTrainer?: Resolver, ParentType, ContextType, RequireFields>; @@ -942,8 +1358,51 @@ export type GqlOAuthPayloadResolvers; }>; +export type GqlPaperResolvers = ResolversObject<{ + archivedAt?: Resolver, ParentType, ContextType>; + briefing?: Resolver, ParentType, ContextType>; + client?: Resolver; + conclusion?: Resolver, ParentType, ContextType>; + createdAt?: Resolver, ParentType, ContextType>; + didSendEmail?: Resolver; + fazit?: Resolver, ParentType, ContextType>; + feedbackMentor?: Resolver, ParentType, ContextType>; + feedbackTrainee?: Resolver, ParentType, ContextType>; + id?: Resolver; + mentorId?: Resolver; + periodEnd?: Resolver, ParentType, ContextType>; + periodStart?: Resolver, ParentType, ContextType>; + schoolPeriodEnd?: Resolver, ParentType, ContextType>; + schoolPeriodStart?: Resolver, ParentType, ContextType>; + status?: Resolver; + subject?: Resolver; + traineeId?: Resolver; + trainerId?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + +export type GqlPaperCommentResolvers = ResolversObject<{ + firstName?: Resolver; + lastName?: Resolver; + published?: Resolver; + text?: Resolver; + userId?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + +export type GqlPaperFormDataResolvers = ResolversObject<{ + answer?: Resolver, ParentType, ContextType>; + comments?: Resolver, ParentType, ContextType>; + hint?: Resolver, ParentType, ContextType>; + id?: Resolver; + question?: Resolver; + questionId?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlPrintPayloadResolvers = ResolversObject<{ estimatedWaitingTime?: Resolver; + pdfUrl?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; }>; @@ -959,8 +1418,12 @@ export type GqlQueryResolvers>, ParentType, ContextType>; config?: Resolver; currentUser?: Resolver, ParentType, ContextType>; + getFazit?: Resolver, ParentType, ContextType, RequireFields>; + getPaper?: Resolver, ParentType, ContextType, RequireFields>; getUser?: Resolver, ParentType, ContextType, RequireFields>; + mentors?: Resolver, ParentType, ContextType>; print?: Resolver>; + printPaper?: Resolver>; reportForTrainee?: Resolver, ParentType, ContextType, RequireFields>; reportForYearAndWeek?: Resolver, ParentType, ContextType, RequireFields>; reports?: Resolver>, ParentType, ContextType, Partial>; @@ -1007,6 +1470,7 @@ export type GqlTraineeResolvers; notification?: Resolver, ParentType, ContextType>; openReportsCount?: Resolver; + papers?: Resolver>>, ParentType, ContextType>; reports?: Resolver, ParentType, ContextType>; signature?: Resolver, ParentType, ContextType>; startDate?: Resolver, ParentType, ContextType>; @@ -1027,6 +1491,7 @@ export type GqlTrainerResolvers, ParentType, ContextType>; lastName?: Resolver; notification?: Resolver, ParentType, ContextType>; + papers?: Resolver>>, ParentType, ContextType>; signature?: Resolver, ParentType, ContextType>; theme?: Resolver, ParentType, ContextType>; trainees?: Resolver, ParentType, ContextType>; @@ -1053,7 +1518,7 @@ export type GqlUpdateReportPayloadResolvers; export type GqlUserInterfaceResolvers = ResolversObject<{ - __resolveType: TypeResolveFn<'Admin' | 'Trainee' | 'Trainer', ParentType, ContextType>; + __resolveType: TypeResolveFn<'Admin' | 'Mentor' | 'Trainee' | 'Trainer', ParentType, ContextType>; alexaSkillLinked?: Resolver, ParentType, ContextType>; createdAt?: Resolver; email?: Resolver; @@ -1067,20 +1532,33 @@ export type GqlUserInterfaceResolvers; }>; +export type GqlDidSendEmailResponseResolvers = ResolversObject<{ + didSendEmail?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlResolvers = ResolversObject<{ Admin?: GqlAdminResolvers; Comment?: GqlCommentResolvers; CommentableInterface?: GqlCommentableInterfaceResolvers; Company?: GqlCompanyResolvers; CreateCommentPayload?: GqlCreateCommentPayloadResolvers; + Cursor?: GqlCursorResolvers; Day?: GqlDayResolvers; DeleteCommentPayload?: GqlDeleteCommentPayloadResolvers; DevSetUserPayload?: GqlDevSetUserPayloadResolvers; Entry?: GqlEntryResolvers; + Fazit?: GqlFazitResolvers; + FazitUpdateResponse?: GqlFazitUpdateResponseResolvers; LaraConfig?: GqlLaraConfigResolvers; + Mentor?: GqlMentorResolvers; MutateEntryPayload?: GqlMutateEntryPayloadResolvers; + MutatePaperPayload?: GqlMutatePaperPayloadResolvers; Mutation?: GqlMutationResolvers; OAuthPayload?: GqlOAuthPayloadResolvers; + Paper?: GqlPaperResolvers; + PaperComment?: GqlPaperCommentResolvers; + PaperFormData?: GqlPaperFormDataResolvers; PrintPayload?: GqlPrintPayloadResolvers; PublishCommentsPayload?: GqlPublishCommentsPayloadResolvers; Query?: GqlQueryResolvers; @@ -1092,5 +1570,6 @@ export type GqlResolvers = ResolversObject<{ UpdateCommentPayload?: GqlUpdateCommentPayloadResolvers; UpdateReportPayload?: GqlUpdateReportPayloadResolvers; UserInterface?: GqlUserInterfaceResolvers; + didSendEmailResponse?: GqlDidSendEmailResponseResolvers; }>; diff --git a/packages/api/src/models.ts b/packages/api/src/models.ts index cf7a5f3b..bf1c48a5 100644 --- a/packages/api/src/models.ts +++ b/packages/api/src/models.ts @@ -4,13 +4,17 @@ import { GqlCommentableInterface, GqlDay, GqlEntry, + GqlFazit, + GqlMentor, + GqlPaper, + GqlPaperFormData, GqlReport, GqlTrainee, GqlTrainer, GqlUserInterface, } from './graphql' -export type User = Trainee | Trainer | Admin +export type User = Trainee | Trainer | Mentor | Admin /** * This values, that are omited from the gql types, @@ -33,13 +37,15 @@ export type UserInterface = Omit & { } export type Trainee = UserInterface & - Omit & { + Omit & { trainerId?: string companyId?: string } export type Trainer = UserInterface & Omit +export type Mentor = UserInterface & Omit + export type Admin = UserInterface & Omit export type Comment = Omit & { @@ -64,3 +70,19 @@ export type Report = Omit & { + briefing: GqlPaperFormData[] + feedbackTrainee: GqlPaperFormData[] + feedbackMentor: GqlPaperFormData[] +} + +export type Fazit = GqlFazit + +export type PaperFormData = Omit & { + answer?: string + hint?: string + id: string + question: string + questionId: string +} diff --git a/packages/api/src/print.ts b/packages/api/src/print.ts index 4aeb3ee2..ec29cc3a 100644 --- a/packages/api/src/print.ts +++ b/packages/api/src/print.ts @@ -19,11 +19,39 @@ export type PrintReport = { summary: string } +export type PrintPaper = { + status: string + briefing: PrintForm[] + feedbackTrainee: PrintForm[] + feedbackMentor: PrintForm[] + fazit: string + client: string + periodStart: string + periodEnd: string + schoolPeriodStart: string + schoolPeriodEnd: string + subject: string + mentorFirstName: string + mentorLastName: string + traineeFirstName: string + traineeLastName: string + //department: string +} + +export type PrintForm = { + question: string + questionId: string + hint: string + answer: string + id: string +} + export type PrintUserData = { firstName: string lastName: string receiverEmail: string course: string + type?: string traineeSignature?: string trainerSignature?: string } @@ -36,6 +64,11 @@ export type PrintReportData = { signatureDate: string } +export type PrintPaperData = { + filename: string + paper: PrintPaper +} + export type PrintTranslations = { monday: string tuesday: string @@ -58,15 +91,26 @@ export type PrintTranslations = { signatureTrainee: string signatureTrainer: string hello: string + client: string + mentor: string + trainer: string + trainee: string + briefing: string + feedbackTrainee: string + feedbackMentor: string + fazit: string } export type PrintPayload = { printDataHash: string + action?: 'pageLoad' | 'download' + mentorName?: string + mentorEmail?: string } export type PrintData = { userData: PrintUserData - reportsData: PrintReportData[] + data: PrintReportData[] | PrintPaperData[] printTranslations: PrintTranslations emailTranslations: EmailTranslations } diff --git a/packages/backend/seeds/papers.json b/packages/backend/seeds/papers.json new file mode 100644 index 00000000..3f952c30 --- /dev/null +++ b/packages/backend/seeds/papers.json @@ -0,0 +1,34 @@ +[ + { + "id": "1", + "traineeId": "123", + "trainerId": "456", + "client": "Test Kunde", + "mentorId": "101112", + "periodStart": "2022-08-07T05:14:28.000Z", + "periodEnd": "2025-08-07T05:14:28.000Z", + "schoolPeriodEnd": null, + "schoolPeriodStart": null, + "subject": "Android Entwicklung", + "status": "NotStarted", + "briefing": [], + "feedbackTrainee": [], + "feedbackMentor": [] + }, + { + "id": "2", + "traineeId": "123", + "trainerId": "456", + "client": "Test Kunde", + "mentorId": "101112", + "periodStart": "2022-08-07T05:14:28.000Z", + "periodEnd": "2025-08-07T05:14:28.000Z", + "schoolPeriodEnd": null, + "schoolPeriodStart": null, + "subject": "IOS Entwicklung", + "status": "NotStarted", + "briefing": [], + "feedbackTrainee": [], + "feedbackMentor": [] + } +] diff --git a/packages/backend/seeds/users.json b/packages/backend/seeds/users.json index cc10e7f1..95ff4bbc 100644 --- a/packages/backend/seeds/users.json +++ b/packages/backend/seeds/users.json @@ -20,14 +20,14 @@ "companyId": "expGermany", "course": "Trainee Course", "createdAt": "2019-08-01T11:25:18.000Z", - "email": "trainee@exampleCompany.com", + "email": "traineeZwei@exampleCompany.com", "firstName": "Trainee", - "lastName": "Traineeson", + "lastName": "Zwei", "language": "de", "startDate": "2022-08-01T22:00:00.000Z", "endDate": "2027-07-31T22:00:00.000Z", "theme": "light", - "token": "123", + "token": "1234", "type": "Trainee", "trainerId": "456" }, @@ -36,14 +36,14 @@ "companyId": "expGermany", "course": "Trainee Course", "createdAt": "2019-08-01T11:25:18.000Z", - "email": "trainee@exampleCompany.com", + "email": "traineeDrei@exampleCompany.com", "firstName": "Trainee", - "lastName": "Traineeson", + "lastName": "Drei", "language": "de", "startDate": "2022-08-01T22:00:00.000Z", "endDate": "2027-07-31T22:00:00.000Z", "theme": "light", - "token": "123", + "token": "12345", "type": "Trainee", "trainerId": "456" }, @@ -74,5 +74,21 @@ "theme": "light", "email": "admin@exampleCompany.com", "token": "789" + }, + { + "id": "101112", + "type": "Mentor", + "companyId": "expGermany", + "createdAt": "2021-04-08T12:43:48.736Z", + "firstName": "Men", + "language": "de", + "startDate": "2021-04-08T12:43:48.736Z", + "endDate": "2025-05-06T22:00:00.000Z", + "lastName": "Tor", + "notification": true, + "deleteAt": "2025-05-06T22:00:00.000Z", + "theme": "light", + "email": "mentor@exampleCompany.com", + "token": "101112" } ] diff --git a/packages/backend/src/aws/lambda.ts b/packages/backend/src/aws/lambda.ts index fc151ebb..78fcd256 100644 --- a/packages/backend/src/aws/lambda.ts +++ b/packages/backend/src/aws/lambda.ts @@ -24,6 +24,7 @@ const functionNameMapping: Record = { } type LambdaOptions = { functionName: 'email'; payload: EmailPayload } | { functionName: 'print'; payload: PrintPayload } +type LambdaOutput = undefined | { success: 'error' | 'success'; filename: string | undefined } /** * Invokes a lambda and doesn't wait for a response. @@ -37,3 +38,18 @@ export const invokeLambda = async ({ functionName, payload }: LambdaOptions): Pr Payload: JSON.stringify(payload), }) } + +/** + * Invokes a lambda and returns a response + * @param payload Lambda Payload + * @param functionName Defines between print and email Lambda + */ +export const invokeLambdaWithOutput = async ({ functionName, payload }: LambdaOptions): Promise => { + const result = await lambda.invoke({ + FunctionName: functionNameMapping[functionName], + InvocationType: 'RequestResponse', + Payload: JSON.stringify(payload), + }) + + return JSON.parse(new TextDecoder().decode(result.Payload)) +} diff --git a/packages/backend/src/aws/s3.ts b/packages/backend/src/aws/s3.ts index f41ff9ac..b6e9d064 100644 --- a/packages/backend/src/aws/s3.ts +++ b/packages/backend/src/aws/s3.ts @@ -1,4 +1,5 @@ -import { S3Client, PutObjectCommand, PutObjectCommandOutput } from '@aws-sdk/client-s3' +import { S3Client, PutObjectCommand, PutObjectCommandOutput, GetObjectCommand } from '@aws-sdk/client-s3' +import { getSignedUrl } from '@aws-sdk/s3-request-presigner' const { IS_OFFLINE, EXPORT_BUCKET } = process.env @@ -28,3 +29,15 @@ export const saveExport = async (key: string, body: string): Promise => { + const command = new GetObjectCommand({ + Bucket: EXPORT_BUCKET, + Key: key, + }) + + const url = await getSignedUrl(s3Client, command, { expiresIn: 60 * 10 }) + if (!url) throw new Error('Could not generate signed URL') + + return url +} diff --git a/packages/backend/src/db/env.ts b/packages/backend/src/db/env.ts index fc91715a..c245ad07 100644 --- a/packages/backend/src/db/env.ts +++ b/packages/backend/src/db/env.ts @@ -4,8 +4,12 @@ const { USER_TABLE, COMPANY_TABLE, REPORT_TABLE, + PAPER_TABLE, REPORT_WEEK_TRAINEEID_INDEX, REPORT_TRAINEEID_STATUS_INDEX, + PAPER_TRAINEE_ID_INDEX, + PAPER_TRAINER_ID_INDEX, + PAPER_MENTOR_ID_INDEX, USER_TYPE_INDEX, USER_EMAIL_INDEX, USER_TRAINER_ID_INDEX, @@ -24,6 +28,22 @@ if (!COMPANY_TABLE) { throw new Error('Missing Env Variable: "COMPANY_TABLE"') } +if (!PAPER_TABLE) { + throw new Error('Missing Env Variable: "PAPER_TABLE"') +} + +if (!PAPER_TRAINEE_ID_INDEX) { + throw new Error('Missing Env Variable: "PAPER_TRAINEE_ID_INDEX"') +} + +if (!PAPER_TRAINER_ID_INDEX) { + throw new Error('Missing Env Variable: "PAPER_TRAINER_ID_INDEX"') +} + +if (!PAPER_MENTOR_ID_INDEX) { + throw new Error('Missing Env Variable: "PAPER_MENTOR_ID_INDEX"') +} + if (!REPORT_WEEK_TRAINEEID_INDEX) { throw new Error('Missing Env Variable: "REPORT_WEEK_TRAINEEID_INDEX"') } @@ -52,11 +72,17 @@ if (!USER_OAUTH_CODE_INDEX) { export const userTableName = USER_TABLE export const companyTabelName = COMPANY_TABLE export const reportTableName = REPORT_TABLE +export const paperTableName = PAPER_TABLE // GSI's for the report table export const reportWeekTraineeIdIndex = REPORT_WEEK_TRAINEEID_INDEX export const reportTraineeIdStatusIndex = REPORT_TRAINEEID_STATUS_INDEX +// GSI's for the paper table +export const paperTraineeIdIndex = PAPER_TRAINEE_ID_INDEX +export const paperTrainerIdIndex = PAPER_TRAINER_ID_INDEX +export const paperMentorIdIndex = PAPER_MENTOR_ID_INDEX + // GSI'S for the user table export const userTypeIndex = USER_TYPE_INDEX export const userEmailIndex = USER_EMAIL_INDEX diff --git a/packages/backend/src/i18n/de.ts b/packages/backend/src/i18n/de.ts index ba8d3191..606e64c1 100644 --- a/packages/backend/src/i18n/de.ts +++ b/packages/backend/src/i18n/de.ts @@ -43,6 +43,8 @@ export const GermanTranslations: Translations = { deleteUser: 'Ein Benutzer wird bald gelöscht', reportInReview: 'Ein Bericht wurde abgegeben', alexa: 'Deine Accounts wurden verknüpft', + paperBriefing: 'Dein Paper Briefing', + paperBriefingMail: 'Dein Paper Briefing', }, headline: { export: 'Dein Lara-Export!', @@ -53,6 +55,7 @@ export const GermanTranslations: Translations = { deleteUser: 'Ein Benutzer wird bald gelöscht', handOver: 'Ein Bericht wurde übergeben', alexa: 'Lara wurde mit Amazon Alexa verknüpft!', + paperBriefing: 'Paper Briefing', }, message: { error: 'etwas ist schiefgegangen. Bitte wende dich an einen Lara Admin oder Entwickler.', @@ -69,9 +72,12 @@ export const GermanTranslations: Translations = { handOver: 'dein Azubi {{ trainee }} hat KW {{ week }} seines Berichtsheft zur Überprüfung abgegeben.', alexa: 'Dein Lara Account wurde mit deinem Amazon Alexa Account verknüpft. Sollte dies ein Fehler sein bitte öffne deine Lara Einstellungen und löse die Verknüpfung wieder auf. Außerdem solltest du dein Lara Passwort ändern.', + paperBriefing: + 'im Anhang findest du das Briefing-PDF zu der Ausbildungsstation. Der Link ist 10 Minuten gültig. Wir wünschen dir ganz viel Spaß damit.', }, link: { archive: 'zum Archiv', + paperBriefing: 'zum Paper', report: 'zum Bericht', lara: 'zu Lara', settings: 'Einstellungen', @@ -99,5 +105,13 @@ export const GermanTranslations: Translations = { thursday: 'Donnerstag', friday: 'Freitag', hello: 'Hallo', + client: 'Kunde', + mentor: 'Ausbildungsbeauftragter', + trainer: 'Ausbilder', + trainee: 'Auszubildender', + briefing: 'Briefing', + feedbackTrainee: 'Azubi Feedback', + feedbackMentor: 'Mentor Feedback', + fazit: 'Fazit', }, } diff --git a/packages/backend/src/i18n/en.ts b/packages/backend/src/i18n/en.ts index 62fed707..5d72326e 100644 --- a/packages/backend/src/i18n/en.ts +++ b/packages/backend/src/i18n/en.ts @@ -43,6 +43,8 @@ export const EnglishTranslations: Translations = { deleteUser: 'A User will be deleted soon', reportInReview: 'A new report was handed in', alexa: 'Your Account have been linked', + paperBriefing: 'Your Paper Briefing', + paperBriefingMail: 'Your Paper Briefing', }, headline: { export: 'Your Lara export!', @@ -53,6 +55,7 @@ export const EnglishTranslations: Translations = { deleteUser: 'A User will be deleted soon', handOver: 'A new report was handed in', alexa: 'Lara has been linked with Amazon Alexa!', + paperBriefing: 'Paper Briefing', }, message: { error: 'Something went wring. Please conteact your Lara admin.', @@ -68,9 +71,12 @@ export const EnglishTranslations: Translations = { handOver: 'your Trainee {{ trainee }} handed in week {{ week }} report for review.', alexa: "Your Lara Account has been linked to your Amazon Alexa Account. If you didn't initiate the Account Linking please open you Lara Settings and remove the Amazon Account. You should also change you Password for Lara.", + paperBriefing: + "attached you will find the briefing PDF for Anna's training station. The link is valid for 10 minutes. We hope you have a lot of fun with it.", }, link: { archive: 'Archive', + paperBriefing: 'Paper', report: 'Report', lara: 'Lara', settings: 'Settings', @@ -98,5 +104,13 @@ export const EnglishTranslations: Translations = { thursday: 'Thursday', friday: 'Friday', hello: 'Hello', + client: 'Client', + mentor: 'Mentor', + trainer: 'Trainer', + trainee: 'Trainee', + briefing: 'Briefing', + feedbackTrainee: 'Trainee Feedback', + feedbackMentor: 'Mentor Feedback', + fazit: 'Conclusion', }, } diff --git a/packages/backend/src/permissions.ts b/packages/backend/src/permissions.ts index c15e4668..bd66d072 100644 --- a/packages/backend/src/permissions.ts +++ b/packages/backend/src/permissions.ts @@ -1,6 +1,6 @@ import { and, or, rule, shield } from 'graphql-shield' -import { Admin, AuthenticatedContext, Context, Trainee, Trainer, User } from '@lara/api' +import { Admin, AuthenticatedContext, Context, Mentor, Trainee, Trainer, User } from '@lara/api' const { DEBUG } = process.env @@ -22,6 +22,14 @@ const trainer = rule({ cache: 'contextual' })( (_parent, _args, ctx: AuthenticatedContext) => isTrainer(ctx.currentUser) || 'Wrong Usertype' ) +export const isMentor = (user: User): user is Mentor => { + return user.type === 'Mentor' +} + +const mentor = rule({ cache: 'contextual' })( + (_parent, _args, ctx: AuthenticatedContext) => isMentor(ctx.currentUser) || 'Wrong Usertype' +) + export const isAdmin = (user: User): user is Admin => { return user.type === 'Admin' } @@ -52,12 +60,13 @@ export const permissions = shield( reportForTrainee: and(authenticated, trainer), // Trainer and Admin Queries - trainees: and(authenticated, or(trainer, admin)), + trainees: authenticated, getUser: and(authenticated, or(admin, trainer)), // Admin Queris trainers: and(authenticated, admin), admins: and(authenticated, admin), + mentors: and(authenticated, admin), }, Mutation: { _devsetusertype: and(authenticated, debug), @@ -69,6 +78,9 @@ export const permissions = shield( unlinkAlexa: authenticated, createOAuthCode: authenticated, + createMentor: and(authenticated, or(trainer, admin, trainee)), + updateMentor: and(authenticated, or(trainer, admin, trainee)), + // Trainee and Trainer mutations updateReport: and(authenticated, or(trainee, trainer)), createCommentOnEntry: and(authenticated, or(trainee, trainer)), @@ -86,6 +98,11 @@ export const permissions = shield( // Trainer mutations claimTrainee: and(authenticated, trainer), unclaimTrainee: and(authenticated, trainer), + createPaper: and(authenticated, or(trainee, trainer)), + deletePaper: and(authenticated, or(trainee, trainer)), + + // Trainer and Trainee and Mentor mutations + updatePaper: and(authenticated, or(trainee, trainer, mentor)), //Admin mutations createTrainee: and(authenticated, admin), diff --git a/packages/backend/src/repositories/mentor.repo.ts b/packages/backend/src/repositories/mentor.repo.ts new file mode 100644 index 00000000..dd322267 --- /dev/null +++ b/packages/backend/src/repositories/mentor.repo.ts @@ -0,0 +1,13 @@ +import { Mentor } from '@lara/api' + +import { queryObjects, userTableName, userTypeIndex } from '../db' +import { userById } from './user.repo' + +export const allMentors = async (): Promise => { + return queryObjects(userTableName, userTypeIndex, { type: 'Mentor' }) +} + +export const mentorById = async (id: string): Promise => { + const user = await userById(id) + return user?.type === 'Mentor' ? user : undefined +} diff --git a/packages/backend/src/repositories/paper.repo.ts b/packages/backend/src/repositories/paper.repo.ts new file mode 100644 index 00000000..3996e3c1 --- /dev/null +++ b/packages/backend/src/repositories/paper.repo.ts @@ -0,0 +1,43 @@ +import { GqlPaper, GqlPaperUpdateInput, Paper } from '@lara/api' + +import { + deleteItem, + paperMentorIdIndex, + paperTableName, + paperTraineeIdIndex, + paperTrainerIdIndex, + putItem, + queryObjects, + updateObject, + UpdateObjectOptions, + getItem, +} from '../db' + +export const updatePaper = async ( + updatedPaper: GqlPaperUpdateInput, + options: UpdateObjectOptions +): Promise => { + return updateObject(paperTableName, updatedPaper, options) +} + +export const savePaper = (paper: GqlPaper): Promise => { + return putItem(paperTableName, paper) +} + +export const deletePaper = async (paperId: string): Promise => { + return deleteItem(paperTableName, { id: paperId }) +} + +export const paperById = (id: string): Promise => { + return getItem(paperTableName, { id }) +} + +export const papersByTrainee = (traineeId: string): Promise => { + return queryObjects(paperTableName, paperTraineeIdIndex, { traineeId }) +} +export const papersByTrainer = (trainerId: string): Promise => { + return queryObjects(paperTableName, paperTrainerIdIndex, { trainerId }) +} +export const papersByMentor = (mentorId: string): Promise => { + return queryObjects(paperTableName, paperMentorIdIndex, { mentorId }) +} diff --git a/packages/backend/src/resolvers/admin.resolver.ts b/packages/backend/src/resolvers/admin.resolver.ts index 7ede0a0f..b197d2ff 100644 --- a/packages/backend/src/resolvers/admin.resolver.ts +++ b/packages/backend/src/resolvers/admin.resolver.ts @@ -1,11 +1,11 @@ import { addMonths, isFuture, isToday, subWeeks } from 'date-fns' import { GraphQLError } from 'graphql' -import { Admin, AdminContext, GqlResolvers, Trainee, Trainer, User } from '@lara/api' +import { Admin, AdminContext, GqlResolvers, Mentor, Trainee, Trainer, User } from '@lara/api' -import { isAdmin, isTrainee, isTrainer } from '../permissions' -import { traineeById } from '../repositories/trainee.repo' -import { trainerById, allTrainers } from '../repositories/trainer.repo' +import { isAdmin, isMentor, isTrainee, isTrainer } from '../permissions' +import { allTrainees, traineeById } from '../repositories/trainee.repo' +import { allTrainers, trainerById } from '../repositories/trainer.repo' import { allAdmins } from '../repositories/admin.repo' import { deleteAdmin, generateAdmin, validateAdmin } from '../services/admin.service' import { allUsers, saveUser, updateUser, userByEmail, userById } from '../repositories/user.repo' @@ -14,17 +14,27 @@ import { deleteTrainee, generateReports, generateTrainee, validateTrainee } from import { deleteTrainer, generateTrainer, validateTrainer } from '../services/trainer.service' import { parseISODateString } from '../utils/date' import { t } from '../i18n' +import { deleteMentor, generateMentor, validateMentor } from '../services/mentor.service' +import { allMentors, mentorById } from '../repositories/mentor.repo' +import { papersByMentor } from '../repositories/paper.repo' export const adminResolver: GqlResolvers = { Admin: {}, Query: { admins: allAdmins, + mentors: allMentors, trainers: allTrainers, + trainees: allTrainees, async cleanup() { const users = await allUsers() await Promise.all( users.map(async (user) => { + if (isMentor(user)) { + const papers = await papersByMentor(user.id) + if (!papers || papers.filter((paper) => paper.status !== 'Archived').length === 0) await deleteMentor(user) + } + if (!user.deleteAt) { return } @@ -50,6 +60,10 @@ export const adminResolver: GqlResolvers = { if (isAdmin(user)) { await deleteAdmin(user) } + + if (isMentor(user)) { + await deleteMentor(user) + } }) ) @@ -129,6 +143,43 @@ export const trainerAdminResolver: GqlResolvers = { // if we use update DDB would throw an error return saveUser(updatedTrainer) }, + getUserByEmail: async (_parent, { email }) => { + return userByEmail(email) + }, + }, +} +export const mentorAdminResolver: GqlResolvers = { + Mutation: { + createMentor: async (_parent, { input }, { currentUser }) => { + const existingUser = await userByEmail(input.email) + + if (existingUser) { + throw new GraphQLError(t('errors.userAlreadyExists', currentUser.language)) + } + + const newMentor = await generateMentor(input) + + return saveUser(newMentor) + }, + updateMentor: async (_parent, { input, id }, { currentUser }) => { + const mentor = await mentorById(id) + + if (!mentor) { + throw new GraphQLError(t('errors.missingUser', currentUser.language)) + } + + const updatedMentor: Mentor = { + ...mentor, + ...input, + } + + await validateMentor(updatedMentor) + + // we need to save the user and not update it + // because we don't know what exactly changed + // if we use update DDB would throw an error + return saveUser(updatedMentor) + }, }, } diff --git a/packages/backend/src/resolvers/index.ts b/packages/backend/src/resolvers/index.ts index 2f259f42..89a6e30f 100644 --- a/packages/backend/src/resolvers/index.ts +++ b/packages/backend/src/resolvers/index.ts @@ -1,15 +1,23 @@ import { alexaResolver } from './alexa.resolver' -import { adminAdminResolver, adminResolver, traineeAdminResolver, trainerAdminResolver } from './admin.resolver' +import { + adminAdminResolver, + adminResolver, + traineeAdminResolver, + trainerAdminResolver, + mentorAdminResolver, +} from './admin.resolver' import { authResolver } from './auth.resolver' import { commentResolver } from './comment.resolver' import { configResolver } from './config.resolver' import { dayResolver, dayTraineeResolver } from './day.resolver' import { entryTraineeResolver } from './entry.resolver' +import { paperResolver } from './paper.resolver' import { reportResolver, reportTraineeResolver } from './report.resolver' import { traineeResolver, traineeTraineeResolver } from './trainee.resolver' import { trainerResolver } from './trainer.resolver' import { userResolver } from './user.resolver' import { avatarResolver } from './avatar.resolver' +import { mentorResolver } from './mentor.resolver' export const resolvers = [ configResolver, @@ -29,6 +37,8 @@ export const resolvers = [ trainerResolver, + mentorResolver, + userResolver, authResolver, @@ -36,8 +46,10 @@ export const resolvers = [ traineeAdminResolver, trainerAdminResolver, adminAdminResolver, + mentorAdminResolver, alexaResolver, avatarResolver, + paperResolver, ] diff --git a/packages/backend/src/resolvers/mentor.resolver.ts b/packages/backend/src/resolvers/mentor.resolver.ts new file mode 100644 index 00000000..6fcece71 --- /dev/null +++ b/packages/backend/src/resolvers/mentor.resolver.ts @@ -0,0 +1,19 @@ +import { GqlResolvers, Mentor, MentorContext } from '@lara/api' + +import { alexaSkillLinked } from '../services/alexa.service' +import { parseISODateString } from '../utils/date' +import { papersByMentor } from '../repositories/paper.repo' + +export const mentorResolver: GqlResolvers = { + Mentor: { + alexaSkillLinked, + deleteAt: (model) => model.endDate, + papers: async (model) => { + return papersByMentor(model.id) + }, + }, +} +export const endOfToolUsage = (mentor: Mentor): Date => { + const endDate = mentor.endDate ? parseISODateString(mentor.endDate) : '' + return endDate +} diff --git a/packages/backend/src/resolvers/paper.resolver.ts b/packages/backend/src/resolvers/paper.resolver.ts new file mode 100644 index 00000000..b2a22dff --- /dev/null +++ b/packages/backend/src/resolvers/paper.resolver.ts @@ -0,0 +1,193 @@ +import { AuthenticatedContext, Fazit, GqlCursor, GqlPaperEntryInput, GqlResolvers } from '@lara/api' +import { generatePaper, generatePaperEntry } from '../services/paper.service' +import { deletePaper, paperById, papersByTrainer, savePaper, updatePaper } from '../repositories/paper.repo' +import { GraphQLError } from 'graphql' + +export const paperResolver: GqlResolvers = { + Query: { + getFazit: async (_parent, { id }) => { + const paper = await paperById(id) + if (!paper) { + throw new GraphQLError('Paper does not exist') + } + if (!paper.fazit) { + const newFazit: Fazit = { + id, + content: '', + version: 0, + cursorPositions: [], + mentorDone: false, + traineeDone: false, + } + const newPaper = await updatePaper( + { ...paper, fazit: newFazit }, + { + updateKeys: ['fazit'], + } + ) + return newPaper.fazit + } + return paper.fazit + }, + getPaper: async (_parent, { id }) => { + const paper = await paperById(id) + if (!paper) { + throw new GraphQLError('Paper does not exist') + } + return paper + }, + }, + Mutation: { + createPaper: async (_parent, { input }) => { + return savePaper(generatePaper(input)) + }, + updatePaper: async (_parent, { input }) => { + const briefing = input.briefing.map((entry: GqlPaperEntryInput) => generatePaperEntry(entry)) + return await updatePaper( + { ...input, briefing }, + { updateKeys: ['briefing', 'feedbackTrainee', 'feedbackMentor', 'status'] } + ) + }, + deletePaper: async (_parent, { paperId }, { currentUser }) => { + const papers = await papersByTrainer(currentUser.id) + + if (!papers) { + throw new GraphQLError('current Trainer has no papers') + } + + const paperById = papers.find((paper) => paper.id === paperId) + + if (!paperById) { + throw new GraphQLError('PaperId belongs not to current Trainer') + } + const success = await deletePaper(paperById.id) + if (!success) { + throw new GraphQLError('current Trainer has no papers') + } + + return papers.filter((paper) => paper.id !== paperId) + }, + didSendEmail: async (_parent, { id, didSendEmail }) => { + const paper = await paperById(id) + if (paper) { + await updatePaper( + { + ...paper, + didSendEmail, + }, + { updateKeys: ['didSendEmail'] } + ) + + return { didSendEmail: true } + } + + return { didSendEmail: false } + }, + updateFazitCursorPos: async (_parent, { id, cursorPosition }) => { + const paper = await paperById(id) + if (!paper) { + throw new GraphQLError('Paper does not exist') + } + + const fazit = paper?.fazit + + const newFazit: Fazit = { + id, + content: fazit?.content ?? '', + version: fazit?.version ?? 0, + cursorPositions: [...(fazit?.cursorPositions ?? []), cursorPosition], + mentorDone: fazit?.mentorDone ?? false, + traineeDone: fazit?.traineeDone ?? false, + } + console.log('Updating Fazit before DB save:', newFazit) + + const cursorMap: Map = new Map() + fazit?.cursorPositions.forEach((cp) => { + cursorMap.set(cp.owner, cp.position) + }) + cursorMap.set(cursorPosition.owner, cursorPosition.position) + + const cursors: GqlCursor[] = [] + cursorMap.forEach((v, k) => { + const cursor = { + owner: k, + position: v, + } + + cursors.push(cursor) + }) + + const newPaper = await updatePaper( + { ...paper, fazit: newFazit }, + { + updateKeys: ['fazit'], + } + ) + + return newPaper.fazit?.cursorPositions.filter((cp) => cp.owner !== cursorPosition.owner)[0] + }, + updateFazit: async (_parent, { id, content, version, cursorPosition, mentorDone, traineeDone }) => { + const paper = await paperById(id) + if (!paper) { + throw new GraphQLError('Paper does not exist') + } + + const fazit = paper.fazit + + const newFazit: Fazit = { + id, + content, + version, + cursorPositions: fazit?.cursorPositions ?? [], + mentorDone: mentorDone ?? fazit?.mentorDone ?? false, + traineeDone: traineeDone ?? fazit?.traineeDone ?? false, + } + + const cursorMap: Map = new Map() + + const cursor: GqlCursor = { + ...cursorPosition, + } + + if (fazit === undefined) { + newFazit.cursorPositions = [cursor] + const newPaper = await updatePaper({ ...paper, fazit: newFazit }, { updateKeys: ['fazit'] }) + return { newFazit: newPaper.fazit!, success: true } + } else { + if (version >= fazit.version) { + //const newContent = merge(fazit.content, content) + const newContent = content + newFazit.content = newContent + fazit.cursorPositions.forEach((cp) => { + cursorMap.set(cp.owner, cp.position) + }) + cursorMap.set(cursor.owner, cursor.position) + + const cursors: GqlCursor[] = [] + cursorMap.forEach((v, k) => { + const cursor = { + owner: k, + position: v, + } + + cursors.push(cursor) + }) + + const newPaper = await updatePaper( + { ...paper, fazit: newFazit }, + { + updateKeys: ['fazit'], + } + ) + + return { success: true, newFazit: newPaper.fazit! } + } else { + return { + success: false, + newFazit: fazit, + } + } + } + }, + }, +} diff --git a/packages/backend/src/resolvers/trainee.resolver.ts b/packages/backend/src/resolvers/trainee.resolver.ts index 8054d1af..7e6133ce 100644 --- a/packages/backend/src/resolvers/trainee.resolver.ts +++ b/packages/backend/src/resolvers/trainee.resolver.ts @@ -19,6 +19,7 @@ import { createPrintReportData, createPrintUserData, invokePrintLambda, savePrin import { reportsWithinApprenticeship } from '../services/report.service' import { endOfToolUsage, startOfToolUsage, validateTrainee } from '../services/trainee.service' import { filterNullish } from '../utils/array' +import { papersByTrainee } from '../repositories/paper.repo' export const traineeResolver: GqlResolvers = { Trainee: { @@ -32,6 +33,9 @@ export const traineeResolver: GqlResolvers = { openReportsCount: async (model) => { return reportsWithinApprenticeship(model, ['reopened', 'todo']).then((reports) => reports.length) }, + papers: async (model) => { + return papersByTrainee(model.id) + }, }, } @@ -108,14 +112,14 @@ export const traineeTraineeResolver: GqlResolvers = { throw new GraphQLError(t('errors.missingReport', currentUser.language)) } - const reportsData = filteredReports.map((report) => createPrintReportData(report, currentUser)) + const data = filteredReports.map((report) => createPrintReportData(report, currentUser)) const userData = await createPrintUserData(currentUser) const printTranslations = t('print', currentUser.language) const emailTranslations = t('email', currentUser.language) const hash = await savePrintData({ - reportsData, + data, userData, printTranslations, emailTranslations, diff --git a/packages/backend/src/resolvers/trainer.resolver.ts b/packages/backend/src/resolvers/trainer.resolver.ts index 62648903..57494756 100644 --- a/packages/backend/src/resolvers/trainer.resolver.ts +++ b/packages/backend/src/resolvers/trainer.resolver.ts @@ -1,12 +1,22 @@ import { GraphQLError } from 'graphql' -import { GqlResolvers, TrainerContext } from '@lara/api' +import { EmailTranslations, GqlResolvers, Mentor, PrintTranslations, Trainee, Trainer, TrainerContext } from '@lara/api' import { reportByYearAndWeek } from '../repositories/report.repo' import { allTrainees, traineeById, traineesByTrainerId } from '../repositories/trainee.repo' import { updateUser } from '../repositories/user.repo' import { alexaSkillLinked } from '../services/alexa.service' -import { createT } from '../i18n' +import { createT, t } from '../i18n' +import { paperById, papersByMentor, papersByTrainer } from '../repositories/paper.repo' +import { + createPrintPaperData, + createPrintUserData, + getPrintData, + invokePrintLambdaResponse, + savePrintData, +} from '../services/print.service' +import { mentorById } from '../repositories/mentor.repo' +import { trainerById } from '../repositories/trainer.repo' export const trainerResolver: GqlResolvers = { Trainer: { @@ -14,6 +24,18 @@ export const trainerResolver: GqlResolvers = { return traineesByTrainerId(model.id) }, alexaSkillLinked, + papers: async (model) => { + const trainerPapers = await papersByTrainer(model.id) + if (trainerPapers?.length) { + const mentorPapers = await papersByMentor(model.id) + if (mentorPapers?.length) { + return [...trainerPapers, ...mentorPapers] + } + } else { + return await papersByMentor(model.id) + } + return trainerPapers + }, }, Query: { trainees: allTrainees, @@ -37,6 +59,87 @@ export const trainerResolver: GqlResolvers = { return report }, + printPaper: async (_parent, { ids, userType }, { currentUser }) => { + const paper = await paperById(ids[0]) + const data = [] + let trainee: Trainee | undefined + let mentor: Mentor | Trainer | undefined + if (paper) { + trainee = await traineeById(paper?.traineeId) + mentor = (await mentorById(paper?.mentorId)) ?? (await trainerById(paper?.mentorId)) + + const mentorName = { + firstName: mentor?.firstName ?? '', + lastName: mentor?.lastName ?? '', + } + + const traineeName = { + firstName: trainee?.firstName ?? '', + lastName: trainee?.lastName ?? '', + } + + data.push(createPrintPaperData(paper, mentorName, traineeName)) + trainee = await traineeById(paper?.traineeId) + mentor = (await mentorById(paper?.mentorId)) ?? (await trainerById(paper?.mentorId)) + } + + let userData = await createPrintUserData(trainee!) + const printTranslations: PrintTranslations = t('print', currentUser.language) + const emailTranslations: EmailTranslations = t('email', currentUser.language) + + const traineeHash = await savePrintData({ + data, + userData, + printTranslations, + emailTranslations, + }) + + const filenameTrainee = await invokePrintLambdaResponse({ + printDataHash: traineeHash, + action: 'pageLoad', + }) + + const traineeURL = await getPrintData(filenameTrainee?.filename ?? '') + + userData = await createPrintUserData(mentor!) + + const mentorHash = await savePrintData({ + data, + userData, + printTranslations, + emailTranslations, + }) + + const filenameMentor = await invokePrintLambdaResponse({ + printDataHash: mentorHash, + action: 'pageLoad', + }) + + const mentorURL = await getPrintData(filenameMentor?.filename ?? '') + + userData = await createPrintUserData(currentUser) + + const trainerHash = await savePrintData({ + data, + userData, + printTranslations, + emailTranslations, + }) + + const filenameTrainer = await invokePrintLambdaResponse({ + printDataHash: trainerHash, + action: 'download', + }) + + const trainerURL = await getPrintData(filenameTrainer?.filename ?? '') + + const url = userType === 'Trainee' ? traineeURL : userType === 'Trainer' ? trainerURL : mentorURL + + return { + estimatedWaitingTime: Math.round(1.5 + 5), + pdfUrl: url, + } + }, }, Mutation: { claimTrainee: async (_parent, { id }, { currentUser }) => { diff --git a/packages/backend/src/resolvers/user.resolver.ts b/packages/backend/src/resolvers/user.resolver.ts index ec6eb04d..180ec05f 100644 --- a/packages/backend/src/resolvers/user.resolver.ts +++ b/packages/backend/src/resolvers/user.resolver.ts @@ -1,12 +1,13 @@ import { AuthenticatedContext, GqlResolvers, User } from '@lara/api' -import { isAdmin, isTrainee, isTrainer } from '../permissions' +import { isAdmin, isTrainee, isTrainer, isMentor } from '../permissions' import { allTrainees } from '../repositories/trainee.repo' import { saveUser } from '../repositories/user.repo' import { generateAdmin } from '../services/admin.service' import { alexaSkillLinked } from '../services/alexa.service' import { generateTrainee } from '../services/trainee.service' import { generateTrainer } from '../services/trainer.service' +import { generateMentor } from '../services/mentor.service' export const userResolver: GqlResolvers = { UserInterface: { @@ -41,6 +42,14 @@ export const userResolver: GqlResolvers = { } } + if (!isMentor(currentUser) && type === 'Mentor') { + newUser = { + ...(await generateMentor(currentUser)), + ...currentUser, + type, + } + } + if (!isAdmin(currentUser) && type === 'Admin') { newUser = { ...generateAdmin(currentUser), diff --git a/packages/backend/src/services/email.service.ts b/packages/backend/src/services/email.service.ts index 73176268..a5101b8c 100644 --- a/packages/backend/src/services/email.service.ts +++ b/packages/backend/src/services/email.service.ts @@ -1,4 +1,4 @@ -import { Admin, EmailPayload, EmailTranslations, Report, Trainee, Trainer, User } from '@lara/api' +import { Admin, EmailPayload, EmailTranslations, Mentor, Report, Trainee, Trainer, User } from '@lara/api' import { invokeLambda } from '../aws/lambda' import { t } from '../i18n' @@ -10,7 +10,12 @@ import { trainerById } from '../repositories/trainer.repo' const { FRONTEND_URL } = process.env const translations = (user: User): EmailTranslations => - t('email', user.language, { interpolation: { prefix: 'turnOff', suffix: 'turnOff' } }) + t('email', user.language, { + interpolation: { + prefix: 'turnOff', + suffix: 'turnOff', + }, + }) const envLink = (path: string) => { return `${FRONTEND_URL}${path}` @@ -50,19 +55,25 @@ export const sendNotificationMail = async (report: Report, sender: User): Promis const receiver = sender.trainerId && (await trainerById(sender.trainerId)) if (!receiver || !receiver.notification) return - await invokeLambda({ payload: trainerNotificationMailPayload(receiver, sender, report), functionName: 'email' }) + await invokeLambda({ + payload: trainerNotificationMailPayload(receiver, sender, report), + functionName: 'email', + }) } if (isTrainer(sender) && (report.status === 'reopened' || report.status === 'archived')) { const receiver = await traineeById(report.traineeId) if (!receiver || !receiver.notification) return - await invokeLambda({ payload: traineeNoficationMailPayload(receiver, sender, report), functionName: 'email' }) + await invokeLambda({ + payload: traineeNoficationMailPayload(receiver, sender, report), + functionName: 'email', + }) } } // creates Payload for admin if a user will be deleted -export const adminDeletionMailPayload = (admin: Admin, user: Trainee | Trainer | Admin): EmailPayload => { +export const adminDeletionMailPayload = (admin: Admin, user: Trainee | Trainer | Admin | Mentor): EmailPayload => { const link = isTrainee(user) ? envLink(`/trainees/${user.id}`) : envLink(`/trainer/${user.id}`) return { emailType: 'deleteUser', @@ -91,7 +102,7 @@ export const trainerDeletionMailPayload = (trainer: Trainer, user: Trainee): Ema } // creates Payload for the user that will be deleted -export const userToDeleteDeletionMailPayload = (userToDelete: Trainee | Trainer | Admin): EmailPayload => { +export const userToDeleteDeletionMailPayload = (userToDelete: Trainee | Trainer | Admin | Mentor): EmailPayload => { return { emailType: 'deleteAccount', userData: { @@ -108,13 +119,16 @@ export const userToDeleteDeletionMailPayload = (userToDelete: Trainee | Trainer * If UserToDelete is a Trainee the Trainer will be notified too. * @param userToDelete */ -export const sendDeletionMail = async (userToDelete: Trainee | Trainer | Admin): Promise => { +export const sendDeletionMail = async (userToDelete: Trainee | Mentor | Trainer | Admin): Promise => { const admins = await allAdmins() // notify admins await Promise.all( admins.map((admin) => { - return invokeLambda({ payload: adminDeletionMailPayload(admin, userToDelete), functionName: 'email' }) + return invokeLambda({ + payload: adminDeletionMailPayload(admin, userToDelete), + functionName: 'email', + }) }) ) @@ -125,11 +139,17 @@ export const sendDeletionMail = async (userToDelete: Trainee | Trainer | Admin): return } - await invokeLambda({ payload: trainerDeletionMailPayload(trainer, userToDelete), functionName: 'email' }) + await invokeLambda({ + payload: trainerDeletionMailPayload(trainer, userToDelete), + functionName: 'email', + }) } // notify user that will be deleted - await invokeLambda({ payload: userToDeleteDeletionMailPayload(userToDelete), functionName: 'email' }) + await invokeLambda({ + payload: userToDeleteDeletionMailPayload(userToDelete), + functionName: 'email', + }) } /** @@ -146,7 +166,11 @@ export const sendAlexaNotificationMail = async (user: User): Promise => { payload: { emailType: 'alexa', translations: translations(user), - userData: { buttonLink: envLink('/settings'), receiverEmail: user.email, receiverName: user.firstName }, + userData: { + buttonLink: envLink('/settings'), + receiverEmail: user.email, + receiverName: user.firstName, + }, }, }) } diff --git a/packages/backend/src/services/mentor.service.ts b/packages/backend/src/services/mentor.service.ts new file mode 100644 index 00000000..a596fcfc --- /dev/null +++ b/packages/backend/src/services/mentor.service.ts @@ -0,0 +1,52 @@ +import { v4 } from 'uuid' + +import { Mentor } from '@lara/api' + +import { deleteUser } from '../repositories/user.repo' + +type GenerateMentorOptions = { + firstName: string + lastName: string + email: string + startDate?: string + endDate?: string +} + +/** + * Generates a new mentor object. + * The mentor isn't saved to the DB yet + * @param options Generate Options + * @returns New Mentor + */ +export const generateMentor = async (options: GenerateMentorOptions): Promise => { + const date = new Date() + + const mentor: Mentor = { + id: v4(), + createdAt: date.toISOString(), + type: 'Mentor', + ...options, + } + + await validateMentor(mentor) + + return mentor +} + +/** + * Validates that the mentor attributes are all + * correct. Throws an error if not + * @param _mentor Mentor to validate + */ +export const validateMentor = async (_mentor: Mentor): Promise => { + // function for validations in the future +} + +/** + * Deletes a mentor and all it's references from the DB + * @returns Boolean indicating success + * @param mentor + */ +export const deleteMentor = async (mentor: Mentor): Promise => { + return await deleteUser(mentor) +} diff --git a/packages/backend/src/services/paper.service.ts b/packages/backend/src/services/paper.service.ts new file mode 100644 index 00000000..be38e75e --- /dev/null +++ b/packages/backend/src/services/paper.service.ts @@ -0,0 +1,20 @@ +import { v4 } from 'uuid' + +import { GqlPaper, GqlPaperEntryInput, GqlPaperFormData, GqlPaperInput } from '@lara/api' + +export const generatePaperEntry = (entryInput: GqlPaperEntryInput): GqlPaperFormData => { + return { + ...entryInput, + } +} +export const generatePaper = (paperInput: GqlPaperInput): GqlPaper => { + return { + id: v4(), + createdAt: new Date().toISOString(), + ...paperInput, + briefing: paperInput.briefing.map((entry) => generatePaperEntry(entry)), + feedbackTrainee: paperInput.feedbackTrainee.map((entry) => generatePaperEntry(entry)), + feedbackMentor: paperInput.feedbackMentor.map((entry) => generatePaperEntry(entry)), + didSendEmail: false, + } +} diff --git a/packages/backend/src/services/print.service.ts b/packages/backend/src/services/print.service.ts index c601619d..46acc49f 100644 --- a/packages/backend/src/services/print.service.ts +++ b/packages/backend/src/services/print.service.ts @@ -5,19 +5,25 @@ import hash from 'object-hash' import { Day, Entry, + Paper, + PaperFormData, PrintData, PrintDay, PrintEntry, + PrintForm, + PrintPaper, + PrintPaperData, PrintPayload, PrintReport, PrintReportData, PrintUserData, Report, Trainee, + User, } from '@lara/api' -import { invokeLambda } from '../aws/lambda' -import { saveExport } from '../aws/s3' +import { invokeLambda, invokeLambdaWithOutput } from '../aws/lambda' +import { getExport, saveExport } from '../aws/s3' import { trainerById } from '../repositories/trainer.repo' import { parseISODateString } from '../utils/date' import { dayStatus } from './day.service' @@ -34,23 +40,37 @@ export const createPDFName = (report: Report, trainee: Trainee): string => { return `${report.year}_KW${report.week}_Berichtsheft_${trainee.firstName}${trainee.lastName}.pdf` } +/** + * Creates PDF name for a print export + * @returns String of the PDF name + * @param paper + */ +export const createPaperPDFName = (paper: Paper): string => { + return `Paper_Briefing_${paper.id}.pdf` +} + /** * Creates the user data that is needed by the print lambda * for generating the PDF - * @param trainee Trainee for PDF + * @param user Trainee for PDF * @returns Userdata */ -export const createPrintUserData = async (trainee: Trainee): Promise => { +export const createPrintUserData = async (user: User): Promise => { const trainerSignature = - trainee.trainerId && (await trainerById(trainee.trainerId).then((trainer) => trainer?.signature)) + user.__typename == 'Trainee' && + user.trainerId && + (await trainerById(user.trainerId).then((trainer) => trainer?.signature)) return { - receiverEmail: trainee.email, - firstName: trainee.firstName, - lastName: trainee.lastName, - course: trainee.course ?? '', - traineeSignature: trainee.signature && `data:image/svg+xml;base64,${trainee.signature}`, - trainerSignature: trainerSignature && `data:image/svg+xml;base64,${trainerSignature}`, + receiverEmail: user.email, + firstName: user.firstName, + lastName: user.lastName, + type: user.__typename, + course: user.__typename == 'Trainee' && user.course ? user.course : '', + traineeSignature: + user.__typename == 'Trainee' ? user.signature && `data:image/svg+xml;base64,${user.signature}` : '', + trainerSignature: + user.__typename == 'Trainee' && trainerSignature ? `data:image/svg+xml;base64,${trainerSignature}` : '', } } @@ -88,6 +108,55 @@ const transformReport = (report: Report): PrintReport => { } } +/** + * Turns a paper from the DB into a paper for the print paper + * @returns Paper for print + * @param paperBriefing + */ +const transformPaperForm = (paperForm: PaperFormData[]): PrintForm[] => { + const printForm: PrintForm[] = [] + paperForm.map((form: PaperFormData) => { + printForm.push({ + question: form.question, + questionId: form.questionId, + hint: form.hint ?? '', + answer: form.answer ?? '', + id: form.id, + }) + }) + return printForm +} + +/** + * Turns a paper from the DB into a paper for the print export + * @returns Paper for print + * @param paper + */ +const transformPaper = ( + paper: Paper, + mentorName: { firstName: string; lastName: string }, + traineeName: { firstName: string; lastName: string } +): PrintPaper => { + return { + status: paper.status, + mentorFirstName: mentorName.firstName, + mentorLastName: mentorName.lastName, + traineeFirstName: traineeName.firstName, + traineeLastName: traineeName.lastName, + briefing: transformPaperForm(paper.briefing), + feedbackTrainee: transformPaperForm(paper.feedbackTrainee), + feedbackMentor: transformPaperForm(paper.feedbackMentor), + fazit: typeof paper.fazit === 'string' ? paper.fazit : (paper.fazit?.content ?? ''), + + client: paper.client, + periodStart: paper.periodStart ?? '', + periodEnd: paper.periodEnd ?? '', + schoolPeriodStart: paper.schoolPeriodStart ?? '', + schoolPeriodEnd: paper.schoolPeriodEnd ?? '', + subject: paper.subject, + } +} + /** * Creates the report data that is needed by the print lambda * for generating the PDF @@ -115,6 +184,23 @@ export const createPrintReportData = (report: Report, trainee: Trainee): PrintRe } } +/** + * Creates the paper data that is needed by the print lambda + * for generating the PDF + * @returns Paperdata + * @param paper + */ +export const createPrintPaperData = ( + paper: Paper, + mentorName: { firstName: string; lastName: string }, + traineeName: { firstName: string; lastName: string } +): PrintPaperData => { + return { + filename: createPaperPDFName(paper), + paper: transformPaper(paper, mentorName, traineeName), + } +} + export const savePrintData = async (printData: PrintData): Promise => { const generatedKey = hash(printData) + '.json' @@ -123,9 +209,23 @@ export const savePrintData = async (printData: PrintData): Promise => { return generatedKey } +export const getPrintData = async (key: string): Promise => { + return await getExport(key) +} + /** * Calls the print lambda and doesn't wait for a response. * @param payload Print data */ export const invokePrintLambda = async (payload: PrintPayload): Promise => await invokeLambda({ payload, functionName: 'print' }) + +type LambdaOutput = undefined | { success: 'error' | 'success'; filename: string | undefined } + +/** + * Calls the print lambda and returns a response. + * @param payload Print data + * @returns Returns the filename and wether or not it was successful + */ +export const invokePrintLambdaResponse = async (payload: PrintPayload): Promise => + await invokeLambdaWithOutput({ payload, functionName: 'print' }) diff --git a/packages/backend/src/test/getEnv.js b/packages/backend/src/test/getEnv.js index a80fc7e6..ad8bdbf4 100644 --- a/packages/backend/src/test/getEnv.js +++ b/packages/backend/src/test/getEnv.js @@ -2,8 +2,12 @@ process.env = { USER_TABLE: 'foo', COMPANY_TABLE: 'foo', REPORT_TABLE: 'foo', + PAPER_TABLE: 'foo', REPORT_WEEK_TRAINEEID_INDEX: 'foo', REPORT_TRAINEEID_STATUS_INDEX: 'foo', + PAPER_TRAINEE_ID_INDEX: 'foo', + PAPER_TRAINER_ID_INDEX: 'foo', + PAPER_MENTOR_ID_INDEX: 'foo', USER_TYPE_INDEX: 'foo', USER_EMAIL_INDEX: 'foo', USER_TRAINER_ID_INDEX: 'foo', diff --git a/packages/backend/src/test/paper.service.test.ts b/packages/backend/src/test/paper.service.test.ts new file mode 100644 index 00000000..5a132bcf --- /dev/null +++ b/packages/backend/src/test/paper.service.test.ts @@ -0,0 +1,69 @@ +import { GqlPaper, GqlPaperInput } from '@lara/api' +import { generateTrainee } from '../services/trainee.service' +import { generatePaper } from '../services/paper.service' +import { generateMentor } from '../services/mentor.service' +import { generateTrainer } from '../services/trainer.service' + +describe('createPaperData', () => { + let paperInput: GqlPaperInput + let paper: GqlPaper + + beforeAll(async () => { + const trainee = await generateTrainee({ + firstName: 'Trainee', + lastName: 'Traineeson', + email: 'trainee@sinnerschrader.com', + startDate: '2023-08-01T22:00:00.000Z', + endDate: '2028-07-31T22:00:00.000Z', + }) + const trainer = await generateTrainer({ + firstName: 'Trainer', + lastName: 'Trainerson', + email: 'trainer@sinnerschrader.com', + }) + const mentor = await generateMentor({ + firstName: 'Men', + lastName: 'Tor', + email: 'mentor@sinnerschrader.com', + startDate: '2023-08-01T22:00:00.000Z', + endDate: '2028-07-31T22:00:00.000Z', + }) + + paperInput = { + traineeId: trainee.id, + trainerId: trainer.id, + client: 'TestClient', + mentorId: mentor.id, + periodStart: '2022-08-07T05:14:28.000Z', + periodEnd: '2025-08-07T05:14:28.000Z', + subject: 'Test Subject', + status: 'InProgress', + briefing: [ + { + id: '1', + questionId: '1', + answer: 'TestAnswer', + question: 'TestQuestion', + hint: 'TestHint', + comments: [], + }, + ], + feedbackTrainee: [], + feedbackMentor: [], + } + + paper = generatePaper(paperInput) + }) + + it('returns correct paper status', () => { + expect(paperInput.status).toBe(paper.status) + }) + + it('returns true when the paper has been created by checking if paperId has been created', () => { + expect(paper.id).toBeTruthy() + }) + + it('check if mentor has been assigned correctly', () => { + expect(paperInput.mentorId).toBe(paper.mentorId) + }) +}) diff --git a/packages/components/src/button-layout.tsx b/packages/components/src/button-layout.tsx index 0d605c81..3aff1519 100644 --- a/packages/components/src/button-layout.tsx +++ b/packages/components/src/button-layout.tsx @@ -175,7 +175,7 @@ const buttonStyle = (props: ButtonLayoutProps) => css` ` const ButtonWrapper = styled.button.withConfig({ - shouldForwardProp: (prop) => !['styling', 'fullsize'].includes(prop), + shouldForwardProp: (prop) => !['styling', 'fullsize', 'danger'].includes(prop), })` font-size: ${FontSizes.button}; border: none; diff --git a/packages/components/src/comment-bubble-layout.tsx b/packages/components/src/comment-bubble-layout.tsx index b0e07fce..41887174 100644 --- a/packages/components/src/comment-bubble-layout.tsx +++ b/packages/components/src/comment-bubble-layout.tsx @@ -98,7 +98,7 @@ export const CommentBubbleLayout: React.FC = ({ return ( - {author}: + {author} {updateMessage ? ( ` +const StyledFab = styled.button.withConfig({ + shouldForwardProp: (prop) => !['large'].includes(prop), +})` position: fixed; cursor: pointer; border-radius: 50%; diff --git a/packages/components/src/icon-definitions.ts b/packages/components/src/icon-definitions.ts index 9ada78ae..22d34c2d 100644 --- a/packages/components/src/icon-definitions.ts +++ b/packages/components/src/icon-definitions.ts @@ -48,10 +48,14 @@ import { IconVaccation } from './icons/vacation' import { IconWork } from './icons/work' import { IconX } from './icons/x' import { IconOptions } from './icons/options' +import { IconCheckMark } from './icons/checkMark' +import { IconBlank } from './icons/blank' +import { IconInfo } from './icons/info' export const Icons = { Arrow: IconArrow, Archive: IconArchive, + Blank: IconBlank, Bulb: IconBulb, BurgerMenu: IconMenu, Camera: IconCamera, @@ -62,6 +66,7 @@ export const Icons = { ChevronLeft: IconChevronLeft, ChevronRight: IconChevronRight, CircleLoader: IconCircleLoader, + CheckMark: IconCheckMark, Claim: IconClaim, CloudUpload: IconCloudUpload, Comment: IconMessageDetails, @@ -100,4 +105,5 @@ export const Icons = { Alexa: Alexa, QuestionMark: QuestionMark, Options: IconOptions, + Info: IconInfo, } diff --git a/packages/components/src/icons/blank.tsx b/packages/components/src/icons/blank.tsx new file mode 100644 index 00000000..0d302295 --- /dev/null +++ b/packages/components/src/icons/blank.tsx @@ -0,0 +1,5 @@ +import React from 'react' + +export const IconBlank: React.FC = () => { + return +} diff --git a/packages/components/src/icons/checkMark.tsx b/packages/components/src/icons/checkMark.tsx new file mode 100644 index 00000000..376b01df --- /dev/null +++ b/packages/components/src/icons/checkMark.tsx @@ -0,0 +1,17 @@ +import React from 'react' + +export const IconCheckMark: React.FC = () => { + return ( + + + + + + + + + ) +} diff --git a/packages/components/src/icons/info.tsx b/packages/components/src/icons/info.tsx new file mode 100644 index 00000000..ea186b85 --- /dev/null +++ b/packages/components/src/icons/info.tsx @@ -0,0 +1,27 @@ +import React from 'react' + +export const IconInfo: React.FC = () => { + return ( + + + + + {' '} + {' '} + {' '} + {' '} + + + ) +} diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index bc5d4eb5..f93bc99d 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -14,6 +14,7 @@ export * from './container' export * from './button-layout' export * from './dropdown-layout' export * from './comment-bubble-layout' +export * from './paper-comment-bubble-layout' export * from './toggle-switch' export * from './toast' export * from './tag' @@ -71,6 +72,10 @@ export * from './settings' export * from './alexa-settings' export * from './splash-page' export * from './faq' +export * from './paper-form' +export * from './paper-create' +export * from './paper-accordion' +export * from './paper-form.layout' export * from './flex' export * from './box' export { DefaultTheme, ThemeProvider } from 'styled-components' diff --git a/packages/components/src/navigation-button-link.tsx b/packages/components/src/navigation-button-link.tsx index 94e23bce..f328d4f7 100644 --- a/packages/components/src/navigation-button-link.tsx +++ b/packages/components/src/navigation-button-link.tsx @@ -7,18 +7,19 @@ import { FontSizes } from './font-size' export interface StyledLinkProps extends LinkProps { isLeft?: boolean + alignLeft?: boolean } // isLeft props needs to be removed from LinkProps const StyledLink = styled(Link) .withConfig({ - shouldForwardProp: (prop) => !['isLeft'].includes(prop), + shouldForwardProp: (prop) => !['isLeft', 'alignLeft'].includes(prop), }) - .attrs(({ isLeft: _isLeft }) => ({}))` + .attrs(({ isLeft: _isLeft, alignLeft: _alignLeft }) => ({}))` display: flex; align-items: center; - justify-content: center; + justify-content: ${(props) => (props.alignLeft ? 'flex-start' : 'center')}; flex-direction: ${(props) => (props.isLeft ? 'row' : 'row-reverse')}; border-radius: ${BorderRadii.xxs}; text-decoration: none; @@ -35,12 +36,19 @@ interface NavigationButtonLinkLayoutProps { icon: JSX.Element label: string isLeft: boolean + alignLeft: boolean to: string } -export const NavigationButtonLinkLayout: React.FC = ({ icon, isLeft, label, to }) => { +export const NavigationButtonLinkLayout: React.FC = ({ + icon, + isLeft, + alignLeft, + label, + to, +}) => { return ( - + {icon} diff --git a/packages/components/src/navigation.tsx b/packages/components/src/navigation.tsx index 3faf5bdd..ffb4bd6d 100644 --- a/packages/components/src/navigation.tsx +++ b/packages/components/src/navigation.tsx @@ -130,10 +130,10 @@ export const StyledAvatarMenuItem = styled.button` color: ${(props) => props.theme.buttonPrimaryFont}; ` -export const StyledAvatarText = styled.div` +export const StyledAvatarText = styled.div<{ $minScreenWidth: number }>` font-size: ${FontSizes.copy}; margin-right: ${Spacings.m}; - @media (max-width: 720px) { + @media (max-width: ${(props) => props.$minScreenWidth + 'px'}) { display: none; } ` diff --git a/packages/components/src/paper-accordion.ts b/packages/components/src/paper-accordion.ts new file mode 100644 index 00000000..e3c33872 --- /dev/null +++ b/packages/components/src/paper-accordion.ts @@ -0,0 +1,63 @@ +import styled, { css } from 'styled-components' +import { Container } from './container' +import { FontSizes } from './font-size' +import { StyledIcon } from './icons' +import { Paragraph } from './paragraph' +import { Spacings } from './spacing' + +interface PaperAccordionState { + active: boolean +} + +export const StyledPaperAccordionContainer = styled(Container)` + width: 100%; + padding: ${Spacings.s} ${Spacings.s} ${Spacings.s} ${Spacings.s}; + margin-bottom: ${Spacings.l}; + + :hover { + & svg { + fill: ${(props) => props.theme.iconBlue}; + } + } +` + +export const StyledPaperAccordionText = styled(Paragraph)` + font-size: ${FontSizes.copy}; + margin: ${Spacings.s} ${Spacings.l} 0 ${Spacings.l}; +` + +export const StyledPaperAccordionHeader = styled.div` + cursor: pointer; + display: flex; + justify-content: space-between; + align-items: center; + font-size: ${FontSizes.h2}; + margin-left: ${Spacings.l}; +` + +export const StyledPaperAccordionTitle = styled(Paragraph).withConfig({ + shouldForwardProp: (prop) => !['active'].includes(prop), +})` + font-size: ${FontSizes.h2}; + transition: font-weight 0.1s; + user-select: none; + cursor: pointer; + margin: ${Spacings.s} 0; + + ${(props) => + props.active && + css` + font-size: ${FontSizes.h2}; + color: ${props.theme.darkFont}; + font-weight: bold; + letter-spacing: 0.3px; + transition: font-weight 0.1s; + `} +` + +export const StyledPaperAccordionIcon = styled(StyledIcon).withConfig({ + shouldForwardProp: (prop) => !['active'].includes(prop), +})` + transform: rotate(${(props) => (props.active ? '180deg' : '0deg')}); + transition: all 0.2s; +` diff --git a/packages/components/src/paper-comment-bubble-layout.tsx b/packages/components/src/paper-comment-bubble-layout.tsx new file mode 100644 index 00000000..b594d288 --- /dev/null +++ b/packages/components/src/paper-comment-bubble-layout.tsx @@ -0,0 +1,39 @@ +import React from 'react' +import styled from 'styled-components' + +import { BorderRadii } from './border-radius' +import { FontSizes } from './font-size' +import { Spacings } from './spacing' + +const MessageContainer = styled.div<{ right?: boolean }>` + display: flex; + padding: ${Spacings.m} ${Spacings.l}; + flex-direction: ${(props) => (props.right ? 'row-reverse' : 'row')}; +` + +const Bubble = styled.div<{ right?: boolean }>` + flex: 1; + padding: ${Spacings.m}; + font-size: ${FontSizes.copy}; + color: ${(props) => props.theme.mediumFont}; + line-height: 1.4; + background-color: ${(props) => props.theme.background}; + border-radius: ${BorderRadii.xxs}; + margin-left: ${(props) => props.right && Spacings.m}; + margin-right: ${(props) => !props.right && Spacings.m}; + position: relative; + word-break: break-word; + } +` + +interface PaperCommentBubbleLayoutProps { + message?: string +} + +export const PaperCommentBubbleLayout: React.FC = ({ message }) => { + return ( + + {message} + + ) +} diff --git a/packages/components/src/paper-create.tsx b/packages/components/src/paper-create.tsx new file mode 100644 index 00000000..3b306beb --- /dev/null +++ b/packages/components/src/paper-create.tsx @@ -0,0 +1,26 @@ +import React, { ReactNode } from 'react' +import styled from 'styled-components' + +import { Spacings } from './spacing' + +const PaperCreateGrid = styled.div` + display: grid; + grid-gap: ${Spacings.l}; + background: ${(props) => props.theme.surface}; + border-radius: 5px; + padding: ${Spacings.l}; +` + +type PaperCreateLayoutProps = { + headline: ReactNode + children: ReactNode +} + +export const PaperCreateLayout: React.FC = ({ headline, children }) => { + return ( + + {headline} + {children} + + ) +} diff --git a/packages/components/src/paper-form.layout.tsx b/packages/components/src/paper-form.layout.tsx new file mode 100644 index 00000000..3f7fcaab --- /dev/null +++ b/packages/components/src/paper-form.layout.tsx @@ -0,0 +1,33 @@ +import React, { ReactNode } from 'react' +import styled from 'styled-components' + +import { Spacings } from './spacing' + +export const StyledPaperTitle = styled.h1` + font-size: 200px; + color: ${(props) => props.theme.faq}; + margin: 0; + z-index: 0; +` + +const StyledPaperLayout = styled.div` + display: grid; + justify-items: center; + grid-gap: ${Spacings.s}; +` + +interface PaperLayoutProps { + children: ReactNode +} + +export const PaperLayout: React.FC = ({ children }) => { + return {children} +} + +export const PaperH2 = styled.h2` + font-weight: 700; + letter-spacing: 1.2px; + color: ${(props) => props.theme.mediumFont}; + text-transform: uppercase; + margin: ${Spacings.xxl} 0 ${Spacings.l} 0; +` diff --git a/packages/components/src/paper-form.tsx b/packages/components/src/paper-form.tsx new file mode 100644 index 00000000..3e2779d6 --- /dev/null +++ b/packages/components/src/paper-form.tsx @@ -0,0 +1,104 @@ +import React, { JSX } from 'react' +import styled from 'styled-components' + +import { Spacings } from './spacing' + +const StyledFormContainer = styled.div` + display: grid; + grid-gap: ${Spacings.xl}; +` + +const StyledFormGrid = styled.div` + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: ${Spacings.l}; +` + +const StyledFormGridItem = styled.div` + display: grid; + grid-gap: ${Spacings.xxs}; +` + +const StyledFormGridDateItem = styled.div` + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: end; + grid-gap: ${Spacings.s}; +` + +const StyledButtonControls = styled.div` + display: grid; + grid-auto-flow: column; + grid-gap: ${Spacings.l}; + justify-self: end; +` + +type CreateBriefingLayoutProps = { + traineeInput: JSX.Element + firstNameMentorInput: JSX.Element + lastNameMentorInput: JSX.Element + emailMentorInput: JSX.Element + customerInput: JSX.Element + startDateProjectInput: JSX.Element + endDateProjectInput: JSX.Element + startDateSchoolInput: JSX.Element + endDateSchoolInput: JSX.Element + departmentInput: JSX.Element + periodProjectSpacer: JSX.Element + periodSchoolSpacer: JSX.Element + buttonControls?: JSX.Element + emptyFieldTrainee?: JSX.Element + emptyFieldMentor?: JSX.Element +} +export const CreateBriefingLayout: React.FC = ({ + traineeInput, + firstNameMentorInput, + lastNameMentorInput, + emailMentorInput, + customerInput, + startDateProjectInput, + endDateProjectInput, + startDateSchoolInput, + endDateSchoolInput, + departmentInput, + periodProjectSpacer, + periodSchoolSpacer, + buttonControls, + emptyFieldTrainee, + emptyFieldMentor, +}) => { + return ( + + + {traineeInput} + + {emptyFieldTrainee} + + {emailMentorInput} + + {emptyFieldMentor} + + {firstNameMentorInput} + + {lastNameMentorInput} + + {customerInput} + + + {startDateProjectInput} + {periodProjectSpacer} +
{endDateProjectInput}
+
+ + {departmentInput} + + + {startDateSchoolInput} + {periodSchoolSpacer} +
{endDateSchoolInput}
+
+
+ {buttonControls && {buttonControls} } +
+ ) +} diff --git a/packages/components/src/paper-text-input.tsx b/packages/components/src/paper-text-input.tsx new file mode 100644 index 00000000..cc940505 --- /dev/null +++ b/packages/components/src/paper-text-input.tsx @@ -0,0 +1,35 @@ +import { FlexProps } from '@rebass/grid' +import styled, { css } from 'styled-components' +import { StyledEntryValueWrapper } from './entry-input-layout' +import { FontSizes } from './font-size' +import { Spacings } from './spacing' + +interface WrapperProps extends FlexProps { + readonly focused: boolean +} + +export const StyledPaperTextInputWrapper = styled(({ focused: _focused, ...rest }: WrapperProps) => ( + +))` + border-bottom: 1px solid ${({ focused, theme }) => (focused ? theme.blueFont : theme.inputBorderEmpty)}; +` + +export const StyledInputBase = css` + border: none; + background-color: ${(props) => props.theme.surface}; + font-size: ${FontSizes.copy}; + color: ${(props) => props.theme.mediumFont}; + ::placeholder { + color: ${(props) => props.theme.lightFont}; + } +` + +export const StyledInputTextArea = styled.textarea` + ${StyledInputBase}; + flex: 1; + outline: none; + padding: ${Spacings.m} 0 ${Spacings.m} 0; + resize: none; + line-height: 1.4; + width: 100%; +` diff --git a/packages/components/src/print/day.ts b/packages/components/src/print/day.ts index 96efa214..e3e9548e 100644 --- a/packages/components/src/print/day.ts +++ b/packages/components/src/print/day.ts @@ -4,7 +4,7 @@ import { FontSizes } from '../font-size' import { Spacings } from '../spacing' export const StyledPrintDay = styled.div` - break-inside: avoid; + break-inside: auto; border-bottom: 1px solid ${(props) => props.theme.inputBorderEmpty}; margin-bottom: ${Spacings.l}; @@ -33,6 +33,14 @@ export const StyledPrintDaySubHeadline = styled.h3` letter-spacing: 1.2px; ` +export const StyledPrintPaperSubHeadline = styled.h3` + font-size: ${FontSizes.copy}; + margin-bottom: ${Spacings.m}; + color: ${(props) => props.theme.darkFont}; + text-transform: uppercase; + letter-spacing: 1.2px; +` + export const StyledPrintDayStatus = styled.span` font-size: ${FontSizes.copy}; font-weight: 700; diff --git a/packages/components/src/print/entry.ts b/packages/components/src/print/entry.ts index 9c1019bf..267ecc3b 100644 --- a/packages/components/src/print/entry.ts +++ b/packages/components/src/print/entry.ts @@ -13,6 +13,13 @@ export const StyledPrintEntry = styled.div` } ` +export const StyledPrintPaperEntry = styled.div` + display: flex; + justify-content: space-between; + padding: ${Spacings.s}; + background-color: ${(props) => props.theme.reportGrey}; +` + export const StyledPrintEntryText = styled.span` color: ${(props) => props.theme.mediumFont}; font-size: ${FontSizes.copy}; diff --git a/packages/components/src/print/user-info.ts b/packages/components/src/print/user-info.ts index ac66d4b9..9e165608 100644 --- a/packages/components/src/print/user-info.ts +++ b/packages/components/src/print/user-info.ts @@ -11,10 +11,10 @@ export const StyledPrintUserInfo = styled.div` margin-bottom: ${Spacings.xxl}; ` -export const StyledPrintUserInfoRow = styled.span<{ fullsize?: boolean }>` +export const StyledPrintUserInfoRow = styled.span<{ $fullsize?: boolean }>` color: ${(props) => props.theme.darkFont}; font-size: ${FontSizes.copy}; - ${(props) => props.fullsize && 'grid-column: 1/3'}; + ${(props) => props.$fullsize && 'grid-column: 1/3'}; ` export const StyledPrintUserInfoRowHeadline = styled.span` font-weight: bold; diff --git a/packages/components/src/text-area.ts b/packages/components/src/text-area.ts index 56f355db..246c8668 100644 --- a/packages/components/src/text-area.ts +++ b/packages/components/src/text-area.ts @@ -23,3 +23,24 @@ export const StyledTextArea = styled.textarea` color: ${(props) => props.theme.lightFont}; } ` + +export const StyledTextFazitArea = styled.textarea` + margin: ${Spacings.l}; + box-sizing: border-box; + width: 90%; + min-height: auto; + font-family: ${Fonts.primary}; + font-size: ${FontSizes.copy}; + border: none; + outline: none; + resize: vertical; + border-bottom: 1px solid #b8b8b8; + color: ${(props) => props.theme.mediumFont}; + background-color: ${(props) => props.theme.surface}; + :focus { + color: ${(props) => props.theme.darkFont}; + } + ::placeholder { + color: ${(props) => props.theme.lightFont}; + } +` diff --git a/packages/components/src/text.ts b/packages/components/src/text.ts index 2a47deca..7873902c 100644 --- a/packages/components/src/text.ts +++ b/packages/components/src/text.ts @@ -17,7 +17,7 @@ export type TextProps = { } export const Text = styled.span.withConfig({ - shouldForwardProp: (prop) => !['noLineHeight'].includes(prop), + shouldForwardProp: (prop) => !['noLineHeight', 'uppercase', 'spacing', 'background'].includes(prop), })` font-size: ${(props) => (props.size ? FontSizes[props.size] : FontSizes.label)}; font-weight: ${(props) => props.weight}; diff --git a/packages/components/src/user-form.tsx b/packages/components/src/user-form.tsx index 3108ffdd..0cc2b344 100644 --- a/packages/components/src/user-form.tsx +++ b/packages/components/src/user-form.tsx @@ -112,3 +112,42 @@ export const TrainerFormLayout: React.FC = ({ ) } + +type MentorFormLayoutProps = { + firstNameInput: JSX.Element + lastNameInput: JSX.Element + emailInput: JSX.Element + startDateInput: JSX.Element + endDateInput: JSX.Element + periodSpacer: JSX.Element + buttonControls?: JSX.Element +} +export const MentorFormLayout: React.FC = ({ + firstNameInput, + lastNameInput, + emailInput, + startDateInput, + endDateInput, + periodSpacer, + buttonControls, +}) => { + return ( + + + {firstNameInput} + + {lastNameInput} + + {emailInput} + + + {startDateInput} + {periodSpacer} +
{endDateInput}
+
+
+ + {buttonControls && {buttonControls}} +
+ ) +} diff --git a/packages/email/package.json b/packages/email/package.json index 07b1372c..7c8976a7 100644 --- a/packages/email/package.json +++ b/packages/email/package.json @@ -2,7 +2,7 @@ "name": "@lara/email", "version": "1.0.0", "private": true, - "description": "Generats ands sends emails", + "description": "Generates ands sends emails", "license": "MIT", "author": "", "main": "index.js", diff --git a/packages/email/src/handler.ts b/packages/email/src/handler.ts index 088c5d52..778f5207 100644 --- a/packages/email/src/handler.ts +++ b/packages/email/src/handler.ts @@ -41,7 +41,7 @@ const streamToBuffer = async (stream: Readable): Promise => { } const handleGettingAttachements = async (payload: EmailPayload): Promise => { - if (payload.emailType !== 'reportExport') { + if (payload.emailType !== 'reportExport' && payload.emailType !== 'paperBriefing') { return [] } diff --git a/packages/email/src/mock.ts b/packages/email/src/mock.ts index f0a336b7..4c0ced01 100644 --- a/packages/email/src/mock.ts +++ b/packages/email/src/mock.ts @@ -25,6 +25,8 @@ export const DUMMY_DATA: EmailPayload = { deleteUser: 'Ein Benutzer wird bald gelöscht', reportInReview: 'Ein Bericht wurde abgegeben', alexa: 'Deine Accounts wurden verknüpft', + paperBriefing: 'Dein Paper Briefing', + paperBriefingMail: 'Dein Paper Briefing', }, headline: { export: 'Dein Lara-Export!', @@ -35,6 +37,7 @@ export const DUMMY_DATA: EmailPayload = { deleteUser: 'Ein Benutzer wird bald gelöscht', handOver: 'Ein Bericht wurde übergeben', alexa: 'Lara wurde mit Amazon Alexa verknüpft!', + paperBriefing: 'Paper Briefing', }, message: { error: 'etwas ist schiefgegangen. Bitte wende dich an einen Lara Admin oder Entwickler.', @@ -51,10 +54,13 @@ export const DUMMY_DATA: EmailPayload = { handOver: 'dein Azubi {{ trainee }} hat KW {{ week }} seines Berichtsheft zur Überprüfung abgegeben.', alexa: 'Dein Lara Account wurde mit deinem Amazon Alexa Account verknüpft. Sollte dies ein Fehler sein bitte öffne deine Lara Einstellungen und löse die Verknüpfung wieder auf. Außerdem solltest du dein Passwort ändern.', + paperBriefing: + 'im Anhang findest du das Briefing-PDF zu der Ausbildungsstation. Wir wünschen dir ganz viel Spaß damit.', }, link: { archive: 'Zum Archive', report: 'Zum Report', + paperBriefing: 'Zum Briefing', lara: 'Lara', settings: 'Einstellungen', }, @@ -101,6 +107,10 @@ const requestListener: RequestListener = (_req, res) => { res.writeHead(200) res.end(generateEmailTemplate('reportInReview', translations)) break + case '/paperBriefing': + res.writeHead(200) + res.end(generateEmailTemplate('paperBriefing', translations)) + break default: res.writeHead(200) res.end(` @@ -115,6 +125,7 @@ const requestListener: RequestListener = (_req, res) => {
  • deleteAccount
  • deleteUser
  • reportInReview
  • +
  • paperBriefing
  • `) break diff --git a/packages/frontend/src/assets/illustrations/empty-paper.tsx b/packages/frontend/src/assets/illustrations/empty-paper.tsx new file mode 100644 index 00000000..dcee0ad4 --- /dev/null +++ b/packages/frontend/src/assets/illustrations/empty-paper.tsx @@ -0,0 +1,116 @@ +import React from 'react' + +const EmptyPaper: React.FunctionComponent = () => ( + + + + + + + + + + + + + + + + + + + + +) + +export default EmptyPaper diff --git a/packages/frontend/src/assets/illustrations/paper-modal-illustraion.tsx b/packages/frontend/src/assets/illustrations/paper-modal-illustraion.tsx new file mode 100644 index 00000000..6842b51e --- /dev/null +++ b/packages/frontend/src/assets/illustrations/paper-modal-illustraion.tsx @@ -0,0 +1,201 @@ +import React from 'react' + +const PaperModal: React.FunctionComponent = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export default PaperModal diff --git a/packages/frontend/src/components/comment-box.tsx b/packages/frontend/src/components/comment-box.tsx index a00b8c60..d23ecbbd 100644 --- a/packages/frontend/src/components/comment-box.tsx +++ b/packages/frontend/src/components/comment-box.tsx @@ -1,13 +1,25 @@ import React from 'react' -import { Comment, useCommentBoxDataQuery, UserInterface } from '../graphql' +import { Comment, PaperComment, useCommentBoxDataQuery, UserInterface } from '../graphql' import CommentBubble from './comment-bubble' import Loader from './loader' +type TransformedCommentArray = + | Array< + Pick & { + user: Pick + } + > + | Array> + +type TransformedComment = + | (Pick & { + user: Pick + }) + | Pick + interface CommentBoxProps { - comments?: (Pick & { - user: Pick - })[] + comments?: TransformedCommentArray updateMessage?: (message: string, commentId: string) => void } @@ -20,18 +32,50 @@ const CommentBox: React.FunctionComponent = ({ comments, update const { currentUser } = data + const getFirstName = (comment: TransformedComment) => { + if ('user' in comment) { + return comment.user.firstName + } else { + return comment.firstName + } + } + + const getLastName = (comment: TransformedComment) => { + if ('user' in comment) { + return comment.user.lastName + } else { + return comment.lastName + } + } + + const getUserId = (comment: TransformedComment) => { + if ('user' in comment) { + return comment.user.id + } else { + return comment.userId + } + } + + const getId = (comment: TransformedComment) => { + if ('id' in comment) { + return comment.id + } else { + return comment.userId + } + } + return ( <> {comments ? comments.map((comment) => ( )) : null} diff --git a/packages/frontend/src/components/comment-section.tsx b/packages/frontend/src/components/comment-section.tsx index d184f385..c80639e5 100644 --- a/packages/frontend/src/components/comment-section.tsx +++ b/packages/frontend/src/components/comment-section.tsx @@ -3,17 +3,24 @@ import { useForm } from 'react-hook-form' import { ErrorText, Input, Spacer, StyledTextInputLabel } from '@lara/components' -import { Comment, UserInterface } from '../graphql' +import { Comment, PaperComment, UserInterface } from '../graphql' import strings from '../locales/localization' import CommentBox from './comment-box' +type TransformedCommentArray = + | Array< + Pick & { + user: Pick + } + > + | Array> + interface CommentSectionProps { - comments: (Pick & { - user: Pick - })[] + comments: TransformedCommentArray onSubmit: onSubmitType displayTextInput: boolean bottomSpace?: boolean + spacingM?: boolean updateMessage?: (message: string, commentId: string) => void } @@ -23,6 +30,7 @@ const CommentSection: React.FunctionComponent = ({ comments, bottomSpace, displayTextInput, + spacingM, onSubmit: submit, updateMessage, }) => { @@ -43,7 +51,7 @@ const CommentSection: React.FunctionComponent = ({ <> {displayTextInput && ( - +
    {strings.report.comments.addComment} ` +const Selected = styled.div.withConfig({ + shouldForwardProp: (prop) => !['open'].includes(prop), +})<{ open: boolean }>` position: relative; width: 100%; height: 100%; @@ -52,8 +54,10 @@ const Selected = styled.div<{ open: boolean }>` } ` -const Menu = styled.ul<{ yOffset: number }>` - position: relative +const Menu = styled.ul.withConfig({ + shouldForwardProp: (prop) => !['yOffset'].includes(prop), +})<{ yOffset: number }>` + position: relative; width: 100%; height: 100%; background: #fff; @@ -64,7 +68,9 @@ const Menu = styled.ul<{ yOffset: number }>` transform: ${({ yOffset }) => 'translateY(-' + yOffset + '%)'}; ` -const Option = styled.li<{ selected: boolean }>` +const Option = styled.li.withConfig({ + shouldForwardProp: (prop) => !['selected'].includes(prop), +})<{ selected: boolean }>` width: 100px; height: 100%; background: ${({ selected }) => (selected ? '#ddd' : '#fff')}; @@ -87,7 +93,7 @@ export function CustomDropdown({ }) { const [open, setOpen] = useState(false) const dropdownRef = useRef(null) - const options = ['Trainee', 'Trainer', 'Admin'] + const options = ['Trainee', 'Trainer', 'Mentor', 'Admin'] const setOpenState = useCallback( (newOpen: boolean) => { @@ -110,7 +116,7 @@ export function CustomDropdown({ }, [setOpenState]) const getYOffset = () => { - return (options.indexOf(value) + 1) * 100 + return options.length * 50 + 50 } return ( diff --git a/packages/frontend/src/components/edit-mentor-content.tsx b/packages/frontend/src/components/edit-mentor-content.tsx new file mode 100644 index 00000000..9a2883b2 --- /dev/null +++ b/packages/frontend/src/components/edit-mentor-content.tsx @@ -0,0 +1,53 @@ +import { GraphQLError } from 'graphql' +import React from 'react' + +import { EditUserContentLayout } from '@lara/components' + +import { useToastContext } from '../hooks/use-toast-context' +import strings from '../locales/localization' +import { MentorForm, EditMentorFormData } from './mentor-form' +import { UserInfo } from './user-info' +import { Mentor, useUpdateMentorMutation } from '../graphql' + +interface EditMentorProps { + mentor: Pick +} + +export const EditMentor: React.FC = ({ mentor }) => { + const [mutate] = useUpdateMentorMutation() + const { addToast } = useToastContext() + + const updateMentor = async (data: EditMentorFormData) => { + await mutate({ + variables: { + id: mentor.id, + input: data, + }, + }) + .then(() => { + addToast({ + icon: 'Settings', + title: strings.settings.saveSuccessTitle, + text: strings.settings.saveSuccess, + type: 'success', + }) + }) + .catch((exception: GraphQLError) => { + addToast({ + title: strings.errors.error, + text: exception.message, + type: 'error', + }) + }) + } + + return ( + + } + form={} + relatedUsers={<>} + /> + ) +} diff --git a/packages/frontend/src/components/edit-user-row.tsx b/packages/frontend/src/components/edit-user-row.tsx index 0d122eea..8465a2fd 100644 --- a/packages/frontend/src/components/edit-user-row.tsx +++ b/packages/frontend/src/components/edit-user-row.tsx @@ -3,16 +3,16 @@ import { useNavigate } from 'react-router' import { EditUserRowLayout } from '@lara/components' -import { Admin, Trainee, Trainer } from '../graphql' +import { Admin, Mentor, Trainee, Trainer } from '../graphql' import strings from '../locales/localization' import { SecondaryButton } from './button' import { UserInfo } from './user-info' -type EditUser = Pick +type EditUser = Pick interface EditUserRowProps { user: EditUser - baseUrl: 'trainees' | 'trainer' | 'admins' + baseUrl: 'trainees' | 'trainer' | 'admins' | 'mentor' } export const EditUserRow: React.FunctionComponent = ({ user, baseUrl }) => { diff --git a/packages/frontend/src/components/mentor-form.tsx b/packages/frontend/src/components/mentor-form.tsx new file mode 100644 index 00000000..3add2d35 --- /dev/null +++ b/packages/frontend/src/components/mentor-form.tsx @@ -0,0 +1,178 @@ +import React from 'react' +import { useForm } from 'react-hook-form' +import { Input, Text, TextProps, DefaultTheme, MentorFormLayout } from '@lara/components' + +import strings from '../locales/localization' +import { PrimaryButton, SecondaryButton } from './button' +import { useValidationHelper } from '../helper/validation-helper' +import { format, parseISO } from 'date-fns' +import { Mentor } from '../graphql' + +interface EditMentorFormProps { + mentor?: Pick + submit: (data: EditMentorFormData) => Promise + cancel?: () => void + blurSubmit: boolean +} + +export interface EditMentorFormData { + firstName: string + lastName: string + email: string + startDate: string + endDate: string + deleteAt: string +} + +const inputLabelProps: TextProps = { + spacing: '1.2px', + weight: 700, + size: 'label', + uppercase: true, +} + +export const MentorForm: React.FC = ({ mentor, submit, blurSubmit, cancel }) => { + const { validateEmail, validateStartDate, validateEndDate } = useValidationHelper() + + const { + register, + handleSubmit, + formState: { errors }, + reset, + } = useForm() + + const onSubmit = handleSubmit((formdata) => { + setUpdating(true) + + submit(formdata).then(() => { + setUpdating(false) + }) + }) + + const onCancel = () => { + reset() + + if (cancel) { + cancel() + } + } + + const [updating, setUpdating] = React.useState(false) + + const getFontColor = (hasError: unknown): keyof DefaultTheme => (hasError ? 'errorRed' : 'darkFont') + return ( + + {} + + + {strings.settings.firstname} + + + + } + lastNameInput={ + <> + + {strings.settings.lastname} + + + + } + emailInput={ + <> + + {strings.settings.email} + + + + } + startDateInput={ + <> + + {strings.period} + + + + } + periodSpacer={ + + {strings.periodTo} + + } + endDateInput={ + <> + + + } + buttonControls={ + !blurSubmit ? ( + <> + + {strings.cancel} + + + {strings.continue} + + + ) : undefined + } + /> + + ) +} diff --git a/packages/frontend/src/components/navigation-button-link.tsx b/packages/frontend/src/components/navigation-button-link.tsx index 48f96e93..246a1934 100644 --- a/packages/frontend/src/components/navigation-button-link.tsx +++ b/packages/frontend/src/components/navigation-button-link.tsx @@ -15,9 +15,11 @@ const NavigationButtonLink: React.FunctionComponent = iconColor, to, isLeft, + alignLeft, }: NavigationButtonLinkProps) => ( {icon && }} diff --git a/packages/frontend/src/components/navigation.tsx b/packages/frontend/src/components/navigation.tsx index 736b3add..6d1dc6fd 100644 --- a/packages/frontend/src/components/navigation.tsx +++ b/packages/frontend/src/components/navigation.tsx @@ -19,6 +19,7 @@ import strings from '../locales/localization' import Avatar from './avatar' import Dropdown from './dropdown' import { isWikiFeatureEnabled } from '../helper/wiki-helper' +import { isPaperFeatureEnabled } from '../helper/paper-helper' const Navigation: React.FC = () => { const { data, loading } = useNavigationDataQuery() @@ -67,6 +68,11 @@ const Navigation: React.FC = () => { {strings.navigation.archive} + {isPaperFeatureEnabled() && ( + + {strings.navigation.paper} + + )} {strings.navigation.settings} @@ -89,12 +95,30 @@ const Navigation: React.FC = () => { {strings.navigation.archive} + {isPaperFeatureEnabled() && ( + + {strings.navigation.paper} + + )} {strings.navigation.settings} ) + const renderMentorNav = () => { + return ( + <> + + {strings.navigation.paper} + + + {strings.navigation.settings} + + + ) + } + const renderAdminNav = () => ( <> @@ -106,6 +130,11 @@ const Navigation: React.FC = () => { {strings.navigation.admin} + {isPaperFeatureEnabled() && ( + + {strings.navigation.mentor} + + )} {strings.navigation.settings} @@ -134,6 +163,7 @@ const Navigation: React.FC = () => { {data.currentUser?.type === UserTypeEnum.Trainer && renderTrainerNav()} {data.currentUser?.type === UserTypeEnum.Trainee && renderTraineeNav()} + {data.currentUser?.type === UserTypeEnum.Mentor && renderMentorNav()} {data.currentUser?.type === UserTypeEnum.Admin && renderAdminNav()} )} @@ -150,7 +180,9 @@ const Navigation: React.FC = () => { setShowDropdown((prev) => !prev) }} > - {data.currentUser?.firstName + ' ' + data.currentUser?.lastName} + + {data.currentUser?.firstName + ' ' + data.currentUser?.lastName} + @@ -165,6 +197,7 @@ const Navigation: React.FC = () => { {data.currentUser?.type === UserTypeEnum.Trainer && renderTrainerNav()} {data.currentUser?.type === UserTypeEnum.Trainee && renderTraineeNav()} + {data.currentUser?.type === UserTypeEnum.Mentor && renderMentorNav()} {data.currentUser?.type === UserTypeEnum.Admin && renderAdminNav()} {renderGeneralMobileNav()} diff --git a/packages/frontend/src/components/paper-accordion.tsx b/packages/frontend/src/components/paper-accordion.tsx new file mode 100644 index 00000000..2b4279b4 --- /dev/null +++ b/packages/frontend/src/components/paper-accordion.tsx @@ -0,0 +1,88 @@ +import { motion } from 'framer-motion' +import React from 'react' + +import { + Spacer, + StyledAccordionIcon, + StyledPaperAccordionContainer, + StyledPaperAccordionHeader, + StyledPaperAccordionText, + StyledPaperAccordionTitle, +} from '@lara/components' +import PaperTextInput from './paper-text-input' +import { Mentor, PaperFormData, Trainee, Trainer } from '../graphql' +import PaperTextBox from './paper-text-box' + +interface PaperAccordionProps { + paperInput: PaperFormData + completedInput: PaperFormData[] + setPaperForm: (value: PaperFormData[]) => void + setPaperFormInput: (value: PaperFormData) => void + title: string + children?: React.ReactNode + forceActive?: boolean + currentUser: Trainer | Trainee | Mentor +} + +const PaperAccordion: React.FunctionComponent = ({ + paperInput, + setPaperForm, + completedInput, + setPaperFormInput, + title, + forceActive, + currentUser, +}) => { + const [activeState, setActiveState] = React.useState(false) + + if (!currentUser) { + return null + } + + const handleClick = () => { + setActiveState(!activeState) + } + + const active = forceActive || activeState + const handleDelete = (entry: PaperFormData) => { + const filteredInputs: PaperFormData[] = [] + completedInput.forEach((input) => { + if (input.id !== entry.id) { + filteredInputs.push(input) + } + }) + setPaperForm(filteredInputs) + } + + return ( + + + + {title} + + + + + + {paperInput.hint} + + + + {completedInput.length ? ( + + ) : null} + + + + ) +} + +export default PaperAccordion diff --git a/packages/frontend/src/components/paper-comment-bubble.tsx b/packages/frontend/src/components/paper-comment-bubble.tsx new file mode 100644 index 00000000..0832a128 --- /dev/null +++ b/packages/frontend/src/components/paper-comment-bubble.tsx @@ -0,0 +1,13 @@ +import React from 'react' + +import { PaperCommentBubbleLayout } from '@lara/components' + +interface CommentBubbleProps { + message?: string +} + +const CommentBubble: React.FunctionComponent = ({ message }) => { + return +} + +export default CommentBubble diff --git a/packages/frontend/src/components/paper-create-form.tsx b/packages/frontend/src/components/paper-create-form.tsx new file mode 100644 index 00000000..20e0b184 --- /dev/null +++ b/packages/frontend/src/components/paper-create-form.tsx @@ -0,0 +1,262 @@ +import React, { useState } from 'react' +import { useForm } from 'react-hook-form' +import { Input, Text, TextProps, DefaultTheme, Spacer, StyledSelect } from '@lara/components' + +import strings from '../locales/localization' +import { PrimaryButton } from './button' +import { useValidationHelper } from '../helper/validation-helper' +import { Trainer, useUserEmailPageMutation } from '../graphql' +import { CreateBriefingLayout } from '@lara/components/lib/paper-form' + +interface CreateBriefingFormProps { + trainer?: Trainer + submit: (data: CreateBriefingFormData) => Promise + blurSubmit: boolean +} + +export interface CreateBriefingFormData { + trainee: string + firstNameMentor: string + lastNameMentor: string + emailMentor: string + customer: string + startDateProject: string + endDateProject: string + startDateSchool: string + endDateSchool: string + department: string +} + +const inputLabelProps: TextProps = { + spacing: '1.2px', + weight: 700, + size: 'label', + uppercase: true, +} + +export const PaperCreateForm: React.FC = ({ trainer, submit, blurSubmit }) => { + const { validateEmail } = useValidationHelper() + const [getUserByEmail] = useUserEmailPageMutation() + const [nameInputDisabled, setNameInputDisabled] = useState(false) + + const { + register, + setValue, + handleSubmit, + formState: { errors }, + } = useForm() + + const onSubmit = handleSubmit((formdata) => { + console.log('HELLO') + setUpdating(true) + submit(formdata).then(() => { + setUpdating(false) + }) + }) + + const [updating, setUpdating] = React.useState(false) + const currentUser = trainer + const getFontColor = (hasError: unknown): keyof DefaultTheme => (hasError ? 'errorRed' : 'darkFont') + return ( +
    + + + {strings.paper.createBriefing.trainee} + + + {currentUser?.trainees.map((trainee, index) => { + return ( + + ) + })} + + + } + emailMentorInput={ + <> + + {strings.paper.createBriefing.emailMentor} + + { + if (e.target.value.trim() === '') { + setNameInputDisabled(false) + return + } + await getUserByEmail({ + variables: { + email: e.target.value, + }, + }).then((response) => { + if (response.data?.getUserByEmail) { + setValue('firstNameMentor', response.data.getUserByEmail.firstName, { shouldValidate: true }) + setValue('lastNameMentor', response.data.getUserByEmail.lastName, { shouldValidate: true }) + setNameInputDisabled(true) + } else setNameInputDisabled(false) + }) + if (blurSubmit) onSubmit() + }} + /> + + } + firstNameMentorInput={ + <> + + {strings.paper.createBriefing.firstnameMentor} + + + + } + emptyFieldTrainee={<>} + lastNameMentorInput={ + <> + + {strings.paper.createBriefing.lastnameMentor} + + + + } + emptyFieldMentor={<>} + customerInput={ + <> + + + {strings.paper.createBriefing.customer} + + + + + } + startDateProjectInput={ + <> + + {strings.paper.createBriefing.projectPeriod} + + + + } + periodProjectSpacer={ + + {strings.periodTo} + + } + endDateProjectInput={ + <> + + + } + startDateSchoolInput={ + <> + + {strings.paper.createBriefing.schoolPeriod} + + + + } + periodSchoolSpacer={ + + {strings.periodTo} + + } + endDateSchoolInput={ + <> + + + } + departmentInput={ + <> + + + {strings.paper.createBriefing.department} + + + + + } + buttonControls={ + !blurSubmit ? ( + <> + + {strings.continue} + + + ) : undefined + } + /> + + ) +} diff --git a/packages/frontend/src/components/paper-text-box.tsx b/packages/frontend/src/components/paper-text-box.tsx new file mode 100644 index 00000000..5a9e4059 --- /dev/null +++ b/packages/frontend/src/components/paper-text-box.tsx @@ -0,0 +1,32 @@ +import React from 'react' + +import { PaperFormData } from '../graphql' +import PaperCommentBubble from './paper-comment-bubble' +import { StyledAction, StyledIcon, Flex } from '@lara/components' + +interface TextBoxProps { + paperInput: PaperFormData + paperEntries: PaperFormData[] + handleDelete: (value: PaperFormData) => void +} + +const PaperTextBox: React.FunctionComponent = ({ paperEntries, paperInput, handleDelete }) => { + return ( + <> + {paperEntries + ? paperEntries.map((entry) => + entry.question == paperInput.question ? ( + + + handleDelete(entry)}> + + + + ) : null + ) + : null} + + ) +} + +export default PaperTextBox diff --git a/packages/frontend/src/components/paper-text-input.tsx b/packages/frontend/src/components/paper-text-input.tsx new file mode 100644 index 00000000..8e26dae0 --- /dev/null +++ b/packages/frontend/src/components/paper-text-input.tsx @@ -0,0 +1,131 @@ +import React from 'react' + +import { StyledEntryContainer, StyledInputTextArea, StyledTextTimeInputWrapper } from '@lara/components' + +import { PaperFormData } from '../graphql' +import strings from '../locales/localization' +import { useFocusState } from '../hooks/use-focus-state' + +interface PaperTextInputProps { + onSave: (paperInput: PaperFormData) => unknown + onDelete?: () => unknown + clearOnSave?: boolean + entry: PaperFormData + disabled?: boolean + autoFocus?: boolean +} + +const PaperTextInput: React.FC = ({ + entry, + disabled, + onDelete, + onSave, + clearOnSave, + autoFocus, +}) => { + const textInput = React.useRef(null) + const textInputFocus = useFocusState(textInput) + + const textKeyDown = (event: React.KeyboardEvent) => { + if (!textInput.current) { + return + } + if (event.key === 'Enter') { + textInput.current?.blur() + } else if (event.key === 'Backspace' && onDelete && textInput.current?.value === '') { + onDelete() + } + } + + const handleBlur = () => { + setTimeout(() => { + if (!textInput.current) { + return + } + + if (textInput.current.value !== '' && document.activeElement !== textInput.current) { + submit() + + if (clearOnSave) { + textInput.current.value = '' + } + + if (textInput.current) { + textInput.current.focus() + } + } + }) + } + + const setCursorToEnd = (input: HTMLInputElement | HTMLTextAreaElement) => { + if (input.setSelectionRange) { + const pos = input.value.length + input.setSelectionRange(pos, pos) + } + } + + const submit = () => { + if (!textInput.current) { + return + } + onSave({ + answer: textInput.current.value, + questionId: entry.questionId, + question: entry.question, + id: entry.id, + hint: entry.hint ? entry.hint : '', + comments: [], + }) + } + + React.useEffect(() => { + if (!textInput.current) { + return + } + + if (autoFocus) { + textInput.current.focus() + setCursorToEnd(textInput.current) + } + }, [autoFocus]) + + const resizeInput = () => { + if (!textInput.current) { + return + } + + const { scrollHeight, clientHeight, style } = textInput.current + + if (!textInput.current.value) { + style.height = 'auto' + } + + if (scrollHeight > clientHeight) { + style.height = scrollHeight.toString() + 'px' + } + } + + const textDefaultValue = entry ? entry.answer : '' + + return ( + <> + + + + + + + ) +} + +export default PaperTextInput diff --git a/packages/frontend/src/graphql/index.tsx b/packages/frontend/src/graphql/index.tsx index 794047dc..1da84998 100644 --- a/packages/frontend/src/graphql/index.tsx +++ b/packages/frontend/src/graphql/index.tsx @@ -33,6 +33,14 @@ export type Admin = UserInterface & { type: UserTypeEnum; }; +export type AnswerPaperInput = { + answer: Scalars['String']['input']; + hint: Scalars['String']['input']; + id: Scalars['ID']['input']; + question: Scalars['String']['input']; + questionId: Scalars['ID']['input']; +}; + export type Comment = { __typename?: 'Comment'; createdAt: Scalars['String']['output']; @@ -67,6 +75,14 @@ export type CreateCommentPayload = { commentable: CommentableInterface; }; +export type CreateMentorInput = { + email: Scalars['String']['input']; + endDate?: InputMaybe; + firstName: Scalars['String']['input']; + lastName: Scalars['String']['input']; + startDate?: InputMaybe; +}; + export type CreateTraineeInput = { companyId: Scalars['String']['input']; email: Scalars['String']['input']; @@ -83,6 +99,17 @@ export type CreateTrainerInput = { lastName: Scalars['String']['input']; }; +export type Cursor = { + __typename?: 'Cursor'; + owner: Scalars['String']['output']; + position: Scalars['Int']['output']; +}; + +export type CursorInput = { + owner: Scalars['String']['input']; + position: Scalars['Int']['input']; +}; + export type Day = CommentableInterface & { __typename?: 'Day'; comments: Array; @@ -133,6 +160,27 @@ export type EntryInput = { time: Scalars['Int']['input']; }; +export type Fazit = { + __typename?: 'Fazit'; + content: Scalars['String']['output']; + cursorPositions: Array; + id: Scalars['ID']['output']; + version: Scalars['Int']['output']; +}; + +export type FazitUpdateInput = { + content: Scalars['String']['input']; + cursorPositions: Array; + id: Scalars['ID']['input']; + version: Scalars['Int']['input']; +}; + +export type FazitUpdateResponse = { + __typename?: 'FazitUpdateResponse'; + newFazit: Fazit; + success: Scalars['Boolean']['output']; +}; + export type LaraConfig = { __typename?: 'LaraConfig'; expectedWorkDayMinutes: Scalars['Int']['output']; @@ -145,6 +193,31 @@ export type LaraConfig = { minWorkDayMinutes: Scalars['Int']['output']; }; +export type Mentor = UserInterface & { + __typename?: 'Mentor'; + alexaSkillLinked?: Maybe; + createdAt: Scalars['String']['output']; + deleteAt?: Maybe; + email: Scalars['String']['output']; + endDate?: Maybe; + firstName: Scalars['String']['output']; + id: Scalars['ID']['output']; + language?: Maybe; + lastName: Scalars['String']['output']; + notification?: Maybe; + papers?: Maybe>>; + signature?: Maybe; + startDate?: Maybe; + theme?: Maybe; + type: UserTypeEnum; +}; + +export type MentorInput = { + email?: InputMaybe; + name?: InputMaybe; + signature?: InputMaybe; +}; + export type MutateEntryPayload = { __typename?: 'MutateEntryPayload'; day: Day; @@ -152,6 +225,11 @@ export type MutateEntryPayload = { report: Report; }; +export type MutatePaperPayload = { + __typename?: 'MutatePaperPayload'; + papers?: Maybe>>; +}; + export type Mutation = { __typename?: 'Mutation'; /** [DEV] Login as a user. */ @@ -170,8 +248,14 @@ export type Mutation = { createCommentOnReport: CreateCommentPayload; /** Creates a new entry which is assigned to the matching report based on the day Id */ createEntry: MutateEntryPayload; + /** Creates Mentor. */ + createMentor?: Maybe; /** Create OAuth Code */ createOAuthCode: Scalars['String']['output']; + /** Create Paper */ + createPaper: Paper; + /** Creates Entry for Lara Paper */ + createPaperEntry: PaperFormData; /** Creates Trainee. */ createTrainee?: Maybe; /** Creates Trainer. */ @@ -184,8 +268,16 @@ export type Mutation = { deleteCommentOnReport: DeleteCommentPayload; /** Deletes an entry by the given ID. Only considers entries made by the current user. Returns the ID of the deleted entry. */ deleteEntry: MutateEntryPayload; + /** Delete Paper */ + deletePaper: Array>; + /** Deletes Entry for Lara Paper */ + deletePaperEntry: PaperFormData; + /** Updates if the pdf email was already sent */ + didSendEmail?: Maybe; /** Get Avatar Bucket Upload URL */ getAvatarSignedUrl?: Maybe; + /** Get a User by Email */ + getUserByEmail?: Maybe; /** Link Alexa account */ linkAlexa?: Maybe; /** Login via microsoft */ @@ -216,6 +308,16 @@ export type Mutation = { updateDay?: Maybe; updateEntry: MutateEntryPayload; updateEntryOrder: MutateEntryPayload; + /** Updates a Fazit */ + updateFazit: FazitUpdateResponse; + /** Update Fazit cursor position */ + updateFazitCursorPos?: Maybe; + /** Updates Mentor. */ + updateMentor?: Maybe; + /** Update Paper */ + updatePaper: Paper; + /** Updates Entry for Lara Paper */ + updatePaperEntry: PaperFormData; /** Updates report which is identified by the id argument. */ updateReport?: Maybe; /** Updates Trainee. */ @@ -272,6 +374,21 @@ export type MutationCreateEntryArgs = { }; +export type MutationCreateMentorArgs = { + input: CreateMentorInput; +}; + + +export type MutationCreatePaperArgs = { + input: PaperInput; +}; + + +export type MutationCreatePaperEntryArgs = { + input: AnswerPaperInput; +}; + + export type MutationCreateTraineeArgs = { input: CreateTraineeInput; }; @@ -308,11 +425,32 @@ export type MutationDeleteEntryArgs = { }; +export type MutationDeletePaperArgs = { + paperId: Scalars['ID']['input']; +}; + + +export type MutationDeletePaperEntryArgs = { + id: Scalars['ID']['input']; +}; + + +export type MutationDidSendEmailArgs = { + didSendEmail: Scalars['Boolean']['input']; + id: Scalars['ID']['input']; +}; + + export type MutationGetAvatarSignedUrlArgs = { id: Scalars['String']['input']; }; +export type MutationGetUserByEmailArgs = { + email: Scalars['String']['input']; +}; + + export type MutationLinkAlexaArgs = { code: Scalars['String']['input']; state: Scalars['String']['input']; @@ -404,6 +542,36 @@ export type MutationUpdateEntryOrderArgs = { }; +export type MutationUpdateFazitArgs = { + content: Scalars['String']['input']; + cursorPosition: CursorInput; + id: Scalars['ID']['input']; + version: Scalars['Int']['input']; +}; + + +export type MutationUpdateFazitCursorPosArgs = { + cursorPosition: CursorInput; + id: Scalars['ID']['input']; +}; + + +export type MutationUpdateMentorArgs = { + id: Scalars['ID']['input']; + input: UpdateMentorInput; +}; + + +export type MutationUpdatePaperArgs = { + input: PaperUpdateInput; +}; + + +export type MutationUpdatePaperEntryArgs = { + input: AnswerPaperInput; +}; + + export type MutationUpdateReportArgs = { department?: InputMaybe; id: Scalars['ID']['input']; @@ -430,9 +598,114 @@ export type OAuthPayload = { refreshToken?: Maybe; }; +export type Paper = { + __typename?: 'Paper'; + archivedAt?: Maybe; + briefing: Array; + client: Scalars['String']['output']; + conclusion?: Maybe; + createdAt?: Maybe; + didSendEmail: Scalars['Boolean']['output']; + fazit?: Maybe; + feedbackMentor: Array; + feedbackTrainee: Array; + id: Scalars['ID']['output']; + mentorId: Scalars['ID']['output']; + periodEnd?: Maybe; + periodStart?: Maybe; + schoolPeriodEnd?: Maybe; + schoolPeriodStart?: Maybe; + status: PaperStatus; + subject: Scalars['String']['output']; + traineeId: Scalars['ID']['output']; + trainerId: Scalars['ID']['output']; +}; + +export type PaperComment = { + __typename?: 'PaperComment'; + firstName: Scalars['String']['output']; + lastName: Scalars['String']['output']; + published: Scalars['Boolean']['output']; + text: Scalars['String']['output']; + userId: Scalars['ID']['output']; +}; + +export type PaperCommentInput = { + firstName: Scalars['String']['input']; + lastName: Scalars['String']['input']; + published: Scalars['Boolean']['input']; + text: Scalars['String']['input']; + userId: Scalars['ID']['input']; +}; + +export type PaperEntryInput = { + answer?: InputMaybe; + comments: Array; + hint?: InputMaybe; + id: Scalars['ID']['input']; + question: Scalars['String']['input']; + questionId: Scalars['ID']['input']; +}; + +export type PaperFormData = { + __typename?: 'PaperFormData'; + answer?: Maybe; + comments: Array; + hint?: Maybe; + id: Scalars['ID']['output']; + question: Scalars['String']['output']; + questionId: Scalars['ID']['output']; +}; + +export type PaperInput = { + briefing: Array; + client: Scalars['String']['input']; + feedbackMentor: Array; + feedbackTrainee: Array; + mentorId: Scalars['ID']['input']; + periodEnd?: InputMaybe; + periodStart?: InputMaybe; + schoolPeriodEnd?: InputMaybe; + schoolPeriodStart?: InputMaybe; + status: PaperStatus; + subject: Scalars['String']['input']; + traineeId: Scalars['ID']['input']; + trainerId: Scalars['ID']['input']; +}; + +export enum PaperStatus { + Archived = 'Archived', + InProgress = 'InProgress', + InReview = 'InReview', + MentorDone = 'MentorDone', + NotStarted = 'NotStarted', + ReviewDone = 'ReviewDone', + TraineeDone = 'TraineeDone' +} + +export type PaperUpdateInput = { + briefing: Array; + client: Scalars['String']['input']; + didSendEmail: Scalars['Boolean']['input']; + fazit?: InputMaybe; + feedbackMentor: Array; + feedbackTrainee: Array; + id: Scalars['ID']['input']; + mentorId: Scalars['ID']['input']; + periodEnd?: InputMaybe; + periodStart?: InputMaybe; + schoolPeriodEnd?: InputMaybe; + schoolPeriodStart?: InputMaybe; + status: PaperStatus; + subject: Scalars['String']['input']; + traineeId: Scalars['ID']['input']; + trainerId: Scalars['ID']['input']; +}; + export type PrintPayload = { __typename?: 'PrintPayload'; estimatedWaitingTime: Scalars['Int']['output']; + pdfUrl?: Maybe; }; export type PublishCommentsPayload = { @@ -452,10 +725,18 @@ export type Query = { config: LaraConfig; /** Returns the logged in user. This user can be either a Trainee or a Trainer. */ currentUser?: Maybe; + /** Get the fazit with Id */ + getFazit?: Maybe; + /** Get Paper with Id */ + getPaper?: Maybe; /** Get a User by ID */ getUser?: Maybe; + /** Get all Mentors */ + mentors: Array; /** Print single report or report batch */ print: PrintPayload; + /** Print single paper */ + printPaper: PrintPayload; /** Finds the report for a specifig trainee on the requested year and week. */ reportForTrainee?: Maybe; /** Finds the report for the requested year and week. */ @@ -471,6 +752,16 @@ export type Query = { }; +export type QueryGetFazitArgs = { + id: Scalars['ID']['input']; +}; + + +export type QueryGetPaperArgs = { + id: Scalars['ID']['input']; +}; + + export type QueryGetUserArgs = { id: Scalars['ID']['input']; }; @@ -481,6 +772,12 @@ export type QueryPrintArgs = { }; +export type QueryPrintPaperArgs = { + ids: Array; + userType: UserTypeEnum; +}; + + export type QueryReportForTraineeArgs = { id: Scalars['ID']['input']; week: Scalars['Int']['input']; @@ -549,6 +846,7 @@ export type Trainee = UserInterface & { lastName: Scalars['String']['output']; notification?: Maybe; openReportsCount: Scalars['Int']['output']; + papers?: Maybe>>; reports: Array; signature?: Maybe; startDate?: Maybe; @@ -569,6 +867,7 @@ export type Trainer = UserInterface & { language?: Maybe; lastName: Scalars['String']['output']; notification?: Maybe; + papers?: Maybe>>; signature?: Maybe; theme?: Maybe; trainees: Array; @@ -597,6 +896,14 @@ export type UpdateCurrentTraineeInput = { course?: InputMaybe; }; +export type UpdateMentorInput = { + email?: InputMaybe; + endDate?: InputMaybe; + firstName?: InputMaybe; + lastName?: InputMaybe; + startDate?: InputMaybe; +}; + export type UpdateReportPayload = { __typename?: 'UpdateReportPayload'; report: Report; @@ -643,12 +950,19 @@ export type UserInterface = { export enum UserTypeEnum { /** User is an Admin */ Admin = 'Admin', + /** User is a Mentor */ + Mentor = 'Mentor', /** User is a Trainee */ Trainee = 'Trainee', /** User is a Trainer */ Trainer = 'Trainer' } +export type DidSendEmailResponse = { + __typename?: 'didSendEmailResponse'; + didSendEmail?: Maybe; +}; + export type ApplicationSettingsUpdateUserMutationVariables = Exact<{ language?: InputMaybe; theme?: InputMaybe; @@ -656,7 +970,7 @@ export type ApplicationSettingsUpdateUserMutationVariables = Exact<{ }>; -export type ApplicationSettingsUpdateUserMutation = { __typename?: 'Mutation', updateCurrentUser?: { __typename: 'Admin', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | { __typename: 'Trainee', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | { __typename: 'Trainer', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | undefined }; +export type ApplicationSettingsUpdateUserMutation = { __typename?: 'Mutation', updateCurrentUser?: { __typename: 'Admin', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | { __typename: 'Mentor', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | { __typename: 'Trainee', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | { __typename: 'Trainer', language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, id: string } | undefined }; export type AvatarSettingsGetSignedUrlMutationVariables = Exact<{ id: Scalars['String']['input']; @@ -686,7 +1000,7 @@ export type CreateCommentOnDayMutationVariables = Exact<{ }>; -export type CreateCommentOnDayMutation = { __typename?: 'Mutation', createCommentOnDay: { __typename?: 'CreateCommentPayload', commentable: { __typename?: 'Day', id: 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 } }> } | { __typename?: 'Entry' } | { __typename?: 'Report' } } }; +export type CreateCommentOnDayMutation = { __typename?: 'Mutation', createCommentOnDay: { __typename?: 'CreateCommentPayload', commentable: { __typename?: 'Day', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } | { __typename?: 'Entry' } | { __typename?: 'Report' } } }; export type CreateCommentOnEntryMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -695,7 +1009,7 @@ export type CreateCommentOnEntryMutationVariables = Exact<{ }>; -export type CreateCommentOnEntryMutation = { __typename?: 'Mutation', createCommentOnEntry: { __typename?: 'CreateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry', id: 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 } }> } | { __typename?: 'Report' } } }; +export type CreateCommentOnEntryMutation = { __typename?: 'Mutation', createCommentOnEntry: { __typename?: 'CreateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } | { __typename?: 'Report' } } }; export type CreateCommentOnReportMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -704,7 +1018,7 @@ export type CreateCommentOnReportMutationVariables = Exact<{ }>; -export type CreateCommentOnReportMutation = { __typename?: 'Mutation', createCommentOnReport: { __typename?: 'CreateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry' } | { __typename?: 'Report', id: 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 } }> } } }; +export type CreateCommentOnReportMutation = { __typename?: 'Mutation', createCommentOnReport: { __typename?: 'CreateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry' } | { __typename?: 'Report', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } } }; export type CreateEntryMutationVariables = Exact<{ dayId: Scalars['String']['input']; @@ -714,11 +1028,25 @@ 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, time: number, orderId: number, comments: Array<{ __typename?: 'Comment', id: string }> }> } } }; +export type CreateMentorMutationVariables = Exact<{ + input: CreateMentorInput; +}>; + + +export type CreateMentorMutation = { __typename?: 'Mutation', createMentor?: { __typename?: 'Mentor', id: string, firstName: string, lastName: string, startDate?: string | undefined, endDate?: string | undefined, email: string, type: UserTypeEnum, deleteAt?: string | undefined } | undefined }; + export type CreateOAuthCodeMutationVariables = Exact<{ [key: string]: never; }>; export type CreateOAuthCodeMutation = { __typename?: 'Mutation', createOAuthCode: string }; +export type CreatePaperMutationVariables = Exact<{ + input: PaperInput; +}>; + + +export type CreatePaperMutation = { __typename?: 'Mutation', createPaper: { __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } }; + export type CreateTraineeMutationVariables = Exact<{ input: CreateTraineeInput; }>; @@ -753,7 +1081,7 @@ export type DebugSetUsertypeMutationVariables = Exact<{ }>; -export type DebugSetUsertypeMutation = { __typename?: 'Mutation', _devsetusertype: { __typename?: 'DevSetUserPayload', user?: { __typename: 'Admin', id: string } | { __typename: 'Trainee', id: string } | { __typename: 'Trainer', id: string } | undefined } }; +export type DebugSetUsertypeMutation = { __typename?: 'Mutation', _devsetusertype: { __typename?: 'DevSetUserPayload', user?: { __typename: 'Admin', id: string } | { __typename: 'Mentor', id: string } | { __typename: 'Trainee', id: string } | { __typename: 'Trainer', id: string } | undefined } }; export type DeleteCommentOnDayMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -762,7 +1090,7 @@ export type DeleteCommentOnDayMutationVariables = Exact<{ }>; -export type DeleteCommentOnDayMutation = { __typename?: 'Mutation', deleteCommentOnDay: { __typename?: 'DeleteCommentPayload', commentable: { __typename?: 'Day', id: 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 } }> } | { __typename?: 'Entry' } | { __typename?: 'Report' } } }; +export type DeleteCommentOnDayMutation = { __typename?: 'Mutation', deleteCommentOnDay: { __typename?: 'DeleteCommentPayload', commentable: { __typename?: 'Day', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } | { __typename?: 'Entry' } | { __typename?: 'Report' } } }; export type DeleteCommentOnEntryMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -771,7 +1099,7 @@ export type DeleteCommentOnEntryMutationVariables = Exact<{ }>; -export type DeleteCommentOnEntryMutation = { __typename?: 'Mutation', deleteCommentOnEntry: { __typename?: 'DeleteCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry', id: 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 } }> } | { __typename?: 'Report' } } }; +export type DeleteCommentOnEntryMutation = { __typename?: 'Mutation', deleteCommentOnEntry: { __typename?: 'DeleteCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } | { __typename?: 'Report' } } }; export type DeleteCommentOnReportMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -780,7 +1108,7 @@ export type DeleteCommentOnReportMutationVariables = Exact<{ }>; -export type DeleteCommentOnReportMutation = { __typename?: 'Mutation', deleteCommentOnReport: { __typename?: 'DeleteCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry' } | { __typename?: 'Report', id: 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 } }> } } }; +export type DeleteCommentOnReportMutation = { __typename?: 'Mutation', deleteCommentOnReport: { __typename?: 'DeleteCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry' } | { __typename?: 'Report', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } } }; export type DeleteEntryMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -789,13 +1117,27 @@ export type DeleteEntryMutationVariables = Exact<{ export type DeleteEntryMutation = { __typename?: 'Mutation', deleteEntry: { __typename?: 'MutateEntryPayload', day: { __typename: 'Day', id: string, entries: Array<{ __typename?: 'Entry', id: string }> } } }; +export type DeletePaperMutationVariables = Exact<{ + paperId: Scalars['ID']['input']; +}>; + + +export type DeletePaperMutation = { __typename?: 'Mutation', deletePaper: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> }; + +export type UserEmailPageMutationVariables = Exact<{ + email: Scalars['String']['input']; +}>; + + +export type UserEmailPageMutation = { __typename?: 'Mutation', getUserByEmail?: { __typename?: 'Admin', id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | { __typename?: 'Mentor', deleteAt?: string | undefined, startDate?: string | undefined, endDate?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | { __typename?: 'Trainee', startDate?: string | undefined, startOfToolUsage?: string | undefined, endDate?: string | undefined, deleteAt?: string | undefined, course?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum, company: { __typename?: 'Company', id: string }, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum, trainees: Array<{ __typename?: 'Trainee', id: string, firstName: string, lastName: string }> } | undefined }; + export type LinkAlexaMutationVariables = Exact<{ code: Scalars['String']['input']; state: Scalars['String']['input']; }>; -export type LinkAlexaMutation = { __typename?: 'Mutation', linkAlexa?: { __typename?: 'Admin', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainee', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainer', id: string, alexaSkillLinked?: boolean | undefined } | undefined }; +export type LinkAlexaMutation = { __typename?: 'Mutation', linkAlexa?: { __typename?: 'Admin', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Mentor', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainee', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainer', id: string, alexaSkillLinked?: boolean | undefined } | undefined }; export type LoginPageLoginMutationVariables = Exact<{ email: Scalars['String']['input']; @@ -809,7 +1151,15 @@ export type MarkUserForDeleteMutationVariables = Exact<{ }>; -export type MarkUserForDeleteMutation = { __typename?: 'Mutation', markUserForDeletion?: { __typename?: 'Admin', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; +export type MarkUserForDeleteMutation = { __typename?: 'Mutation', markUserForDeletion?: { __typename?: 'Admin', deleteAt?: string | undefined, id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; + +export type DidSendEmailMutationVariables = Exact<{ + id: Scalars['ID']['input']; + didSendEmail: Scalars['Boolean']['input']; +}>; + + +export type DidSendEmailMutation = { __typename?: 'Mutation', didSendEmail?: { __typename?: 'didSendEmailResponse', didSendEmail?: boolean | undefined } | undefined }; export type PublishAllCommentsMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -817,14 +1167,14 @@ export type PublishAllCommentsMutationVariables = Exact<{ }>; -export type PublishAllCommentsMutation = { __typename?: 'Mutation', publishAllComments: { __typename?: 'PublishCommentsPayload', report: { __typename?: 'Report', id: 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 } }> } } }; +export type PublishAllCommentsMutation = { __typename?: 'Mutation', publishAllComments: { __typename?: 'PublishCommentsPayload', report: { __typename?: 'Report', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } } }; export type SignatureSettingsUpdateSignatureMutationVariables = Exact<{ signature?: InputMaybe; }>; -export type SignatureSettingsUpdateSignatureMutation = { __typename?: 'Mutation', updateCurrentUser?: { __typename?: 'Admin', id: string, signature?: string | undefined } | { __typename?: 'Trainee', id: string, signature?: string | undefined } | { __typename?: 'Trainer', id: string, signature?: string | undefined } | undefined }; +export type SignatureSettingsUpdateSignatureMutation = { __typename?: 'Mutation', updateCurrentUser?: { __typename?: 'Admin', id: string, signature?: string | undefined } | { __typename?: 'Mentor', id: string, signature?: string | undefined } | { __typename?: 'Trainee', id: string, signature?: string | undefined } | { __typename?: 'Trainer', id: string, signature?: string | undefined } | undefined }; export type TraineeSettingsUpdateTraineeMutationVariables = Exact<{ course?: InputMaybe; @@ -843,14 +1193,14 @@ export type UnclaimTraineeMutation = { __typename?: 'Mutation', unclaimTrainee?: export type UnlinkAlexaMutationVariables = Exact<{ [key: string]: never; }>; -export type UnlinkAlexaMutation = { __typename?: 'Mutation', unlinkAlexa?: { __typename?: 'Admin', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainee', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainer', id: string, alexaSkillLinked?: boolean | undefined } | undefined }; +export type UnlinkAlexaMutation = { __typename?: 'Mutation', unlinkAlexa?: { __typename?: 'Admin', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Mentor', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainee', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainer', id: string, alexaSkillLinked?: boolean | undefined } | undefined }; export type UnmarkUserForDeleteMutationVariables = Exact<{ id: Scalars['ID']['input']; }>; -export type UnmarkUserForDeleteMutation = { __typename?: 'Mutation', unmarkUserForDeletion?: { __typename?: 'Admin', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; +export type UnmarkUserForDeleteMutation = { __typename?: 'Mutation', unmarkUserForDeletion?: { __typename?: 'Admin', deleteAt?: string | undefined, id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; export type UpdateAdminMutationVariables = Exact<{ input: UpdateAdminInput; @@ -868,7 +1218,7 @@ export type UpdateCommentOnDayMutationVariables = Exact<{ }>; -export type UpdateCommentOnDayMutation = { __typename?: 'Mutation', updateCommentOnDay: { __typename?: 'UpdateCommentPayload', commentable: { __typename?: 'Day', id: 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 } }> } | { __typename?: 'Entry' } | { __typename?: 'Report' } } }; +export type UpdateCommentOnDayMutation = { __typename?: 'Mutation', updateCommentOnDay: { __typename?: 'UpdateCommentPayload', commentable: { __typename?: 'Day', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } | { __typename?: 'Entry' } | { __typename?: 'Report' } } }; export type UpdateCommentOnEntryMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -878,7 +1228,7 @@ export type UpdateCommentOnEntryMutationVariables = Exact<{ }>; -export type UpdateCommentOnEntryMutation = { __typename?: 'Mutation', updateCommentOnEntry: { __typename?: 'UpdateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry', id: 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 } }> } | { __typename?: 'Report' } } }; +export type UpdateCommentOnEntryMutation = { __typename?: 'Mutation', updateCommentOnEntry: { __typename?: 'UpdateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } | { __typename?: 'Report' } } }; export type UpdateCommentOnReportMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -888,7 +1238,7 @@ export type UpdateCommentOnReportMutationVariables = Exact<{ }>; -export type UpdateCommentOnReportMutation = { __typename?: 'Mutation', updateCommentOnReport: { __typename?: 'UpdateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry' } | { __typename?: 'Report', id: 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 } }> } } }; +export type UpdateCommentOnReportMutation = { __typename?: 'Mutation', updateCommentOnReport: { __typename?: 'UpdateCommentPayload', commentable: { __typename?: 'Day' } | { __typename?: 'Entry' } | { __typename?: 'Report', id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }> } } }; export type UpdateEntryOrderMutationVariables = Exact<{ entryId: Scalars['ID']['input']; @@ -907,6 +1257,41 @@ export type UpdateEntryMutationVariables = Exact<{ export type UpdateEntryMutation = { __typename?: 'Mutation', updateEntry: { __typename?: 'MutateEntryPayload', entry?: { __typename?: 'Entry', id: string, time: number, text: string } | undefined } }; +export type UpdateFazitCursorPosMutationVariables = Exact<{ + id: Scalars['ID']['input']; + cursorPosition: CursorInput; +}>; + + +export type UpdateFazitCursorPosMutation = { __typename?: 'Mutation', updateFazitCursorPos?: { __typename?: 'Cursor', position: number, owner: string } | undefined }; + +export type FazitUpdateMutationVariables = Exact<{ + id: Scalars['ID']['input']; + content: Scalars['String']['input']; + version: Scalars['Int']['input']; + cursorPosition: CursorInput; + mentorDone?: InputMaybe; + traineeDone?: InputMaybe; +}>; + + +export type FazitUpdateMutation = { __typename?: 'Mutation', updateFazit: { __typename?: 'FazitUpdateResponse', success: boolean, newFazit: { __typename?: 'Fazit', id: string, content: string, version: number, mentorDone: boolean, traineeDone: boolean, cursorPositions: Array<{ __typename?: 'Cursor', position: number, owner: string }> } } }; + +export type UpdateMentorMutationVariables = Exact<{ + input: UpdateMentorInput; + id: Scalars['ID']['input']; +}>; + + +export type UpdateMentorMutation = { __typename?: 'Mutation', updateMentor?: { __typename?: 'Mentor', id: string, startDate?: string | undefined, endDate?: string | undefined, firstName: string, lastName: string, email: string, type: UserTypeEnum } | undefined }; + +export type UpdatePaperMutationVariables = Exact<{ + input: PaperUpdateInput; +}>; + + +export type UpdatePaperMutation = { __typename?: 'Mutation', updatePaper: { __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string }> }> } }; + export type UpdateReportReportReviewPageMutationVariables = Exact<{ id: Scalars['ID']['input']; summary?: InputMaybe; @@ -948,6 +1333,11 @@ export type AdminAdminsPageQueryVariables = Exact<{ [key: string]: never; }>; export type AdminAdminsPageQuery = { __typename?: 'Query', admins: Array<{ __typename?: 'Admin', id: string, firstName: string, lastName: string, deleteAt?: string | undefined }> }; +export type AdminMentorPageQueryVariables = Exact<{ [key: string]: never; }>; + + +export type AdminMentorPageQuery = { __typename?: 'Query', mentors: Array<{ __typename?: 'Mentor', id: string, firstName: string, lastName: string, startDate?: string | undefined, endDate?: string | undefined, deleteAt?: string | undefined }> }; + export type AdminTraineesPageQueryVariables = Exact<{ [key: string]: never; }>; @@ -966,17 +1356,17 @@ 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, text: string }> }> } | undefined> }; +export type ArchivePageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined, firstName: string, lastName: string, language?: string | undefined } | { __typename?: 'Mentor', 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, text: string }> }> } | undefined> }; export type AvatarSettingsDataQueryVariables = Exact<{ [key: string]: never; }>; -export type AvatarSettingsDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; +export type AvatarSettingsDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; export type CommentBoxDataQueryVariables = Exact<{ [key: string]: never; }>; -export type CommentBoxDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; +export type CommentBoxDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; export type ConfigQueryVariables = Exact<{ [key: string]: never; }>; @@ -986,7 +1376,7 @@ export type ConfigQuery = { __typename?: 'Query', config: { __typename?: 'LaraCo export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>; -export type CurrentUserQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum } | { __typename?: 'Trainee', startDate?: string | undefined, endDate?: string | undefined, course?: string | undefined, id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum, company: { __typename?: 'Company', id: string } } | { __typename?: 'Trainer', id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum, trainees: Array<{ __typename?: 'Trainee', id: string }> } | undefined }; +export type CurrentUserQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum } | { __typename?: 'Mentor', id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, text: string, firstName: string, lastName: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, firstName: string, lastName: string, text: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, firstName: string, text: string, lastName: string, published: boolean }> }> } | undefined> | undefined } | { __typename?: 'Trainee', startDate?: string | undefined, endDate?: string | undefined, course?: string | undefined, id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum, company: { __typename?: 'Company', id: string }, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, text: string, firstName: string, lastName: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, firstName: string, lastName: string, text: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, text: string, firstName: string, lastName: string, published: boolean }> }> } | undefined> | undefined } | { __typename?: 'Trainer', id: string, language?: string | undefined, theme?: string | undefined, type: UserTypeEnum, trainees: Array<{ __typename?: 'Trainee', id: string }>, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, firstName: string, text: string, lastName: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, firstName: string, text: string, lastName: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string, firstName: string, text: string, lastName: string, published: boolean }> }> } | undefined> | undefined } | undefined }; export type DashboardPageDataQueryVariables = Exact<{ currentYear: Scalars['Int']['input']; @@ -994,34 +1384,70 @@ 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>, 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, time: number, 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?: 'Mentor', 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>, 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, time: number, orderId: number, comments: Array<{ __typename?: 'Comment', id: string, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', 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?: 'Mentor', 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; }>; -export type DayInputDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string, lastName: string, type: UserTypeEnum } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string, type: UserTypeEnum } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, type: UserTypeEnum } | undefined }; +export type DayInputDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string, lastName: string, type: UserTypeEnum } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string, type: UserTypeEnum } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string, type: UserTypeEnum } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, type: UserTypeEnum } | undefined }; export type EntryInputDataQueryVariables = Exact<{ [key: string]: never; }>; -export type EntryInputDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, type: UserTypeEnum, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, type: UserTypeEnum, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, type: UserTypeEnum, firstName: string, lastName: string } | undefined }; +export type EntryInputDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, type: UserTypeEnum, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, type: UserTypeEnum, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, type: UserTypeEnum, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, type: UserTypeEnum, firstName: string, lastName: string } | undefined }; + +export type FeedbackDoneQueryVariables = Exact<{ + id: Scalars['ID']['input']; +}>; + + +export type FeedbackDoneQuery = { __typename?: 'Query', getPaper?: { __typename?: 'Paper', didSendEmail: boolean } | undefined }; export type UserPageQueryVariables = Exact<{ id: Scalars['ID']['input']; }>; -export type UserPageQuery = { __typename?: 'Query', getUser?: { __typename?: 'Admin', deleteAt?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | { __typename?: 'Trainee', startDate?: string | undefined, startOfToolUsage?: string | undefined, endDate?: string | undefined, deleteAt?: string | undefined, course?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum, company: { __typename?: 'Company', id: string }, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum, trainees: Array<{ __typename?: 'Trainee', id: string, firstName: string, lastName: string }> } | undefined, companies?: Array<{ __typename?: 'Company', id: string, name: string }> | undefined, currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; +export type UserPageQuery = { __typename?: 'Query', getUser?: { __typename?: 'Admin', deleteAt?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | { __typename?: 'Mentor', deleteAt?: string | undefined, startDate?: string | undefined, endDate?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | { __typename?: 'Trainee', startDate?: string | undefined, startOfToolUsage?: string | undefined, endDate?: string | undefined, deleteAt?: string | undefined, course?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum, company: { __typename?: 'Company', id: string }, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum, trainees: Array<{ __typename?: 'Trainee', id: string, firstName: string, lastName: string }> } | undefined, companies?: Array<{ __typename?: 'Company', id: string, name: string }> | undefined, currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; + +export type GetFazitQueryVariables = Exact<{ + id: Scalars['ID']['input']; +}>; + + +export type GetFazitQuery = { __typename?: 'Query', getFazit?: { __typename?: 'Fazit', id: string, content: string, version: number, cursorPositions: Array<{ __typename?: 'Cursor', owner: string, position: number }> } | undefined }; + +export type MentorsPageQueryVariables = Exact<{ [key: string]: never; }>; + + +export type MentorsPageQuery = { __typename?: 'Query', mentors: Array<{ __typename?: 'Mentor', id: string, firstName: string, lastName: string, startDate?: string | undefined, endDate?: string | undefined }> }; + +export type MentorPaperPageDataQueryVariables = Exact<{ [key: string]: never; }>; + + +export type MentorPaperPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; export type NavigationDataQueryVariables = Exact<{ [key: string]: never; }>; -export type NavigationDataQuery = { __typename?: 'Query', currentUser?: { __typename: 'Admin', type: UserTypeEnum, id: string, firstName: string, lastName: string } | { __typename: 'Trainee', type: UserTypeEnum, id: string, firstName: string, lastName: string } | { __typename: 'Trainer', type: UserTypeEnum, id: string, firstName: string, lastName: string } | undefined }; +export type NavigationDataQuery = { __typename?: 'Query', currentUser?: { __typename: 'Admin', type: UserTypeEnum, id: string, firstName: string, lastName: string } | { __typename: 'Mentor', type: UserTypeEnum, id: string, firstName: string, lastName: string } | { __typename: 'Trainee', type: UserTypeEnum, id: string, firstName: string, lastName: string } | { __typename: 'Trainer', type: UserTypeEnum, id: string, firstName: string, lastName: string } | undefined }; export type OnboardingPageDataQueryVariables = Exact<{ [key: string]: never; }>; -export type OnboardingPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string } | { __typename?: 'Trainee', id: string, firstName: string } | { __typename?: 'Trainer', id: string, firstName: string } | undefined }; +export type OnboardingPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string } | { __typename?: 'Mentor', id: string, firstName: string } | { __typename?: 'Trainee', id: string, firstName: string } | { __typename?: 'Trainer', id: string, firstName: string } | undefined }; + +export type PaperFazitPageQueryVariables = Exact<{ + id: Scalars['ID']['input']; +}>; + + +export type PaperFazitPageQuery = { __typename?: 'Query', getPaper?: { __typename?: 'Paper', id: string, traineeId: string, trainerId: string, status: PaperStatus, conclusion?: string | undefined, archivedAt?: string | undefined, createdAt?: string | undefined, client: string, mentorId: string, didSendEmail: boolean, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, fazit?: { __typename?: 'Fazit', id: string, content: string, version: number, cursorPositions: Array<{ __typename?: 'Cursor', position: number, owner: string }> } | undefined } | undefined }; + +export type FeedbackDiscussionPageDataQueryVariables = Exact<{ [key: string]: never; }>; + + +export type FeedbackDiscussionPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, lastName: string, firstName: string, userId: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }> } | undefined> | undefined } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }> } | undefined> | undefined } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', text: string, userId: string, lastName: string, firstName: string, published: boolean }> }> } | undefined> | undefined } | undefined }; export type PrintDataQueryVariables = Exact<{ ids: Array | Scalars['ID']['input']; @@ -1030,13 +1456,21 @@ export type PrintDataQueryVariables = Exact<{ export type PrintDataQuery = { __typename?: 'Query', print: { __typename?: 'PrintPayload', estimatedWaitingTime: number } }; +export type PrintPaperDataQueryVariables = Exact<{ + ids: Array | Scalars['ID']['input']; + userType: UserTypeEnum; +}>; + + +export type PrintPaperDataQuery = { __typename?: 'Query', printPaper: { __typename?: 'PrintPayload', estimatedWaitingTime: number, pdfUrl?: string | undefined } }; + export type ReportPageDataQueryVariables = Exact<{ year: Scalars['Int']['input']; week: Scalars['Int']['input']; }>; -export type ReportPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', startOfToolUsage?: string | undefined, endOfToolUsage?: string | undefined, id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined, reportForYearAndWeek?: { __typename?: 'Report', id: string, week: number, year: number, summary?: string | undefined, department?: string | undefined, status: ReportStatus, previousReportLink?: string | undefined, nextReportLink?: string | undefined, 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 } }>, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, date: string, id: 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 } }>, entries: Array<{ __typename?: 'Entry', id: string, text: string, time: number, orderId: number, 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 ReportPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', startOfToolUsage?: string | undefined, endOfToolUsage?: string | undefined, id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined, reportForYearAndWeek?: { __typename?: 'Report', id: string, week: number, year: number, summary?: string | undefined, department?: string | undefined, status: ReportStatus, previousReportLink?: string | undefined, nextReportLink?: string | undefined, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }>, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, date: string, id: string, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }>, entries: Array<{ __typename?: 'Entry', id: string, text: string, time: number, orderId: number, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', 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 ReportReviewPageDataQueryVariables = Exact<{ year: Scalars['Int']['input']; @@ -1045,17 +1479,17 @@ export type ReportReviewPageDataQueryVariables = Exact<{ }>; -export type ReportReviewPageDataQuery = { __typename?: 'Query', currentUser?: { __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, reportForTrainee?: { __typename?: 'Report', id: string, week: number, year: number, summary?: string | undefined, department?: string | undefined, status: ReportStatus, 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 } }>, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, date: string, id: string, entries: Array<{ __typename?: 'Entry', id: string, text: string, time: number, orderId: number, 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 } }> }>, 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 ReportReviewPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined, reportForTrainee?: { __typename?: 'Report', id: string, week: number, year: number, summary?: string | undefined, department?: string | undefined, status: ReportStatus, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string } }>, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, date: string, id: string, entries: Array<{ __typename?: 'Entry', id: string, text: string, time: number, orderId: number, comments: Array<{ __typename?: 'Comment', id: string, text?: string | undefined, published: boolean, user: { __typename?: 'Admin', id: string, firstName: string, lastName: string } | { __typename?: 'Mentor', 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?: 'Mentor', 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 SettingsPageDataQueryVariables = Exact<{ [key: string]: never; }>; -export type SettingsPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined } | { __typename?: 'Trainee', startDate?: string | undefined, endDate?: string | undefined, course?: string | undefined, alexaSkillLinked?: boolean | undefined, id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, company: { __typename?: 'Company', id: string, name: string } } | { __typename?: 'Trainer', id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined } | undefined, companies?: Array<{ __typename?: 'Company', id: string, name: string }> | undefined }; +export type SettingsPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined } | { __typename?: 'Mentor', id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined } | { __typename?: 'Trainee', startDate?: string | undefined, endDate?: string | undefined, course?: string | undefined, alexaSkillLinked?: boolean | undefined, id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined, company: { __typename?: 'Company', id: string, name: string } } | { __typename?: 'Trainer', id: string, type: UserTypeEnum, language?: string | undefined, theme?: string | undefined, notification?: boolean | undefined } | undefined, companies?: Array<{ __typename?: 'Company', id: string, name: string }> | undefined }; export type SignatureSettingsDataQueryVariables = Exact<{ [key: string]: never; }>; -export type SignatureSettingsDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, signature?: string | undefined } | { __typename?: 'Trainee', id: string, signature?: string | undefined } | { __typename?: 'Trainer', id: string, signature?: string | undefined } | undefined }; +export type SignatureSettingsDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, signature?: string | undefined } | { __typename?: 'Mentor', id: string, signature?: string | undefined } | { __typename?: 'Trainee', id: string, signature?: string | undefined } | { __typename?: 'Trainer', id: string, signature?: string | undefined } | undefined }; export type SuggestionsDataQueryVariables = Exact<{ [key: string]: never; }>; @@ -1065,17 +1499,32 @@ export type SuggestionsDataQuery = { __typename?: 'Query', suggestions: Array<{ export type TraineePageDataQueryVariables = Exact<{ [key: string]: never; }>; -export type TraineePageDataQuery = { __typename?: 'Query', trainees: Array<{ __typename?: 'Trainee', id: string, firstName: string, lastName: string, course?: string | undefined, startDate?: string | undefined, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined, company: { __typename?: 'Company', id: string, name: string } }>, currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; +export type TraineePageDataQuery = { __typename?: 'Query', trainees: Array<{ __typename?: 'Trainee', id: string, firstName: string, lastName: string, course?: string | undefined, startDate?: string | undefined, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined, company: { __typename?: 'Company', id: string, name: string } }>, currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string } | undefined }; + +export type TraineePaperPageDataQueryVariables = Exact<{ [key: string]: never; }>; + + +export type TraineePaperPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', id: string, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string }> }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string }> }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined, comments: Array<{ __typename?: 'PaperComment', userId: string }> }> } | undefined> | undefined } | { __typename?: 'Trainer', id: string } | undefined }; + +export type TraineePaperDataQueryVariables = Exact<{ [key: string]: never; }>; + + +export type TraineePaperDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin' } | { __typename?: 'Mentor' } | { __typename?: 'Trainee', id: string, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | { __typename?: 'Trainer' } | undefined }; export type TraineeSettingsDataQueryVariables = Exact<{ [key: string]: never; }>; -export type TraineeSettingsDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin' } | { __typename: 'Trainee', id: string, startDate?: string | undefined, endDate?: string | undefined, course?: string | undefined, company: { __typename?: 'Company', id: string, name: string }, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined } | { __typename?: 'Trainer' } | undefined }; +export type TraineeSettingsDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin' } | { __typename?: 'Mentor' } | { __typename: 'Trainee', id: string, startDate?: string | undefined, endDate?: string | undefined, course?: string | undefined, company: { __typename?: 'Company', id: string, name: string }, trainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string } | undefined } | { __typename?: 'Trainer' } | undefined }; + +export type TrainerPaperPageDataQueryVariables = Exact<{ [key: string]: never; }>; + + +export type TrainerPaperPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', id: string } | { __typename?: 'Trainer', id: string, trainees: Array<{ __typename?: 'Trainee', firstName: string, lastName: string, id: string }>, papers?: Array<{ __typename?: 'Paper', id: string, traineeId: string, trainerId: string, client: string, mentorId: string, periodStart?: string | undefined, periodEnd?: string | undefined, schoolPeriodStart?: string | undefined, schoolPeriodEnd?: string | undefined, subject: string, status: PaperStatus, briefing: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackTrainee: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }>, feedbackMentor: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | undefined }; export type TrainerReportsPageDataQueryVariables = Exact<{ [key: string]: never; }>; -export type TrainerReportsPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined, trainees: Array<{ __typename?: 'Trainee', firstName: string, lastName: string, id: string, openReportsCount: number, reports: Array<{ __typename?: 'Report', id: string, status: ReportStatus, week: number, year: number, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined }> }> }> } | undefined }; +export type TrainerReportsPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined } | { __typename?: 'Mentor', id: string, theme?: string | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined, trainees: Array<{ __typename?: 'Trainee', firstName: string, lastName: string, id: string, openReportsCount: number, reports: Array<{ __typename?: 'Report', id: string, status: ReportStatus, week: number, year: number, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined }> }> }> } | undefined }; export type TrainersPageQueryVariables = Exact<{ [key: string]: never; }>; @@ -1097,9 +1546,9 @@ export const ApplicationSettingsUpdateUserDocument = gql` } `; export function useApplicationSettingsUpdateUserMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(ApplicationSettingsUpdateUserDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(ApplicationSettingsUpdateUserDocument, options); +} export type ApplicationSettingsUpdateUserMutationHookResult = ReturnType; export const AvatarSettingsGetSignedUrlDocument = gql` mutation AvatarSettingsGetSignedUrl($id: String!) { @@ -1107,9 +1556,9 @@ export const AvatarSettingsGetSignedUrlDocument = gql` } `; export function useAvatarSettingsGetSignedUrlMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(AvatarSettingsGetSignedUrlDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(AvatarSettingsGetSignedUrlDocument, options); +} export type AvatarSettingsGetSignedUrlMutationHookResult = ReturnType; export const ClaimTraineeDocument = gql` mutation claimTrainee($id: ID!) { @@ -1130,9 +1579,9 @@ export const ClaimTraineeDocument = gql` } `; export function useClaimTraineeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(ClaimTraineeDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(ClaimTraineeDocument, options); +} export type ClaimTraineeMutationHookResult = ReturnType; export const CreateAdminDocument = gql` mutation CreateAdmin($input: CreateAdminInput!) { @@ -1146,9 +1595,9 @@ export const CreateAdminDocument = gql` } `; export function useCreateAdminMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateAdminDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateAdminDocument, options); +} export type CreateAdminMutationHookResult = ReturnType; export const CreateCommentOnDayDocument = gql` mutation createCommentOnDay($id: ID!, $text: String!, $traineeId: ID!) { @@ -1172,9 +1621,9 @@ export const CreateCommentOnDayDocument = gql` } `; export function useCreateCommentOnDayMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateCommentOnDayDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateCommentOnDayDocument, options); +} export type CreateCommentOnDayMutationHookResult = ReturnType; export const CreateCommentOnEntryDocument = gql` mutation createCommentOnEntry($id: ID!, $text: String!, $traineeId: ID!) { @@ -1198,9 +1647,9 @@ export const CreateCommentOnEntryDocument = gql` } `; export function useCreateCommentOnEntryMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateCommentOnEntryDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateCommentOnEntryDocument, options); +} export type CreateCommentOnEntryMutationHookResult = ReturnType; export const CreateCommentOnReportDocument = gql` mutation createCommentOnReport($id: ID!, $text: String!, $traineeId: ID!) { @@ -1224,9 +1673,9 @@ export const CreateCommentOnReportDocument = gql` } `; export function useCreateCommentOnReportMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateCommentOnReportDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateCommentOnReportDocument, options); +} export type CreateCommentOnReportMutationHookResult = ReturnType; export const CreateEntryDocument = gql` mutation createEntry($dayId: String!, $input: EntryInput!) { @@ -1248,43 +1697,126 @@ export const CreateEntryDocument = gql` } `; export function useCreateEntryMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateEntryDocument, options); - } -export type CreateEntryMutationHookResult = ReturnType; -export const CreateOAuthCodeDocument = gql` - mutation createOAuthCode { - createOAuthCode + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateEntryDocument, options); } - `; -export function useCreateOAuthCodeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateOAuthCodeDocument, options); - } -export type CreateOAuthCodeMutationHookResult = ReturnType; -export const CreateTraineeDocument = gql` - mutation CreateTrainee($input: CreateTraineeInput!) { - createTrainee(input: $input) { +export type CreateEntryMutationHookResult = ReturnType; +export const CreateMentorDocument = gql` + mutation CreateMentor($input: CreateMentorInput!) { + createMentor(input: $input) { id - company { - id - } - startDate - startOfToolUsage - endDate - course firstName lastName + startDate + endDate email type deleteAt } } `; -export function useCreateTraineeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateTraineeDocument, options); +export function useCreateMentorMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateMentorDocument, options); +} +export type CreateMentorMutationHookResult = ReturnType; +export const CreateOAuthCodeDocument = gql` + mutation createOAuthCode { + createOAuthCode +} + `; +export function useCreateOAuthCodeMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateOAuthCodeDocument, options); +} +export type CreateOAuthCodeMutationHookResult = ReturnType; +export const CreatePaperDocument = gql` + mutation createPaper($input: PaperInput!) { + createPaper(input: $input) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + text + firstName + lastName + userId + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + firstName + lastName + userId + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + firstName + lastName + userId + published } + } + } +} + `; +export function useCreatePaperMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreatePaperDocument, options); +} +export type CreatePaperMutationHookResult = ReturnType; +export const CreateTraineeDocument = gql` + mutation CreateTrainee($input: CreateTraineeInput!) { + createTrainee(input: $input) { + id + company { + id + } + startDate + startOfToolUsage + endDate + course + firstName + lastName + email + type + deleteAt + } +} + `; +export function useCreateTraineeMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateTraineeDocument, options); +} export type CreateTraineeMutationHookResult = ReturnType; export const CreateTrainerDocument = gql` mutation CreateTrainer($input: CreateTrainerInput!) { @@ -1298,9 +1830,9 @@ export const CreateTrainerDocument = gql` } `; export function useCreateTrainerMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateTrainerDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(CreateTrainerDocument, options); +} export type CreateTrainerMutationHookResult = ReturnType; export const DayStatusSelectUpdateDayDocument = gql` mutation DayStatusSelectUpdateDay($id: ID!, $status: String) { @@ -1312,9 +1844,9 @@ export const DayStatusSelectUpdateDayDocument = gql` } `; export function useDayStatusSelectUpdateDayMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DayStatusSelectUpdateDayDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DayStatusSelectUpdateDayDocument, options); +} export type DayStatusSelectUpdateDayMutationHookResult = ReturnType; export const DebugLoginDocument = gql` mutation DebugLogin($id: String!) { @@ -1326,9 +1858,9 @@ export const DebugLoginDocument = gql` } `; export function useDebugLoginMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DebugLoginDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DebugLoginDocument, options); +} export type DebugLoginMutationHookResult = ReturnType; export const DebugSetUsertypeDocument = gql` mutation DebugSetUsertype($usertype: String!) { @@ -1341,9 +1873,9 @@ export const DebugSetUsertypeDocument = gql` } `; export function useDebugSetUsertypeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DebugSetUsertypeDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DebugSetUsertypeDocument, options); +} export type DebugSetUsertypeMutationHookResult = ReturnType; export const DeleteCommentOnDayDocument = gql` mutation deleteCommentOnDay($id: ID!, $traineeId: ID!, $commentId: ID!) { @@ -1367,9 +1899,9 @@ export const DeleteCommentOnDayDocument = gql` } `; export function useDeleteCommentOnDayMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteCommentOnDayDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DeleteCommentOnDayDocument, options); +} export type DeleteCommentOnDayMutationHookResult = ReturnType; export const DeleteCommentOnEntryDocument = gql` mutation deleteCommentOnEntry($id: ID!, $traineeId: ID!, $commentId: ID!) { @@ -1393,9 +1925,9 @@ export const DeleteCommentOnEntryDocument = gql` } `; export function useDeleteCommentOnEntryMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteCommentOnEntryDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DeleteCommentOnEntryDocument, options); +} export type DeleteCommentOnEntryMutationHookResult = ReturnType; export const DeleteCommentOnReportDocument = gql` mutation deleteCommentOnReport($id: ID!, $traineeId: ID!, $commentId: ID!) { @@ -1419,9 +1951,9 @@ export const DeleteCommentOnReportDocument = gql` } `; export function useDeleteCommentOnReportMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteCommentOnReportDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DeleteCommentOnReportDocument, options); +} export type DeleteCommentOnReportMutationHookResult = ReturnType; export const DeleteEntryDocument = gql` mutation deleteEntry($id: ID!) { @@ -1437,10 +1969,94 @@ export const DeleteEntryDocument = gql` } `; export function useDeleteEntryMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteEntryDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DeleteEntryDocument, options); +} export type DeleteEntryMutationHookResult = ReturnType; +export const DeletePaperDocument = gql` + mutation deletePaper($paperId: ID!) { + deletePaper(paperId: $paperId) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + answer + hint + } + feedbackTrainee { + id + questionId + answer + hint + } + feedbackMentor { + id + questionId + answer + hint + } + } +} + `; +export function useDeletePaperMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DeletePaperDocument, options); +} +export type DeletePaperMutationHookResult = ReturnType; +export const UserEmailPageDocument = gql` + mutation UserEmailPage($email: String!) { + getUserByEmail(email: $email) { + id + firstName + lastName + email + type + ... on Trainee { + startDate + startOfToolUsage + endDate + deleteAt + course + company { + id + } + trainer { + id + firstName + lastName + } + } + ... on Trainer { + deleteAt + trainees { + id + firstName + lastName + } + } + ... on Mentor { + deleteAt + startDate + endDate + } + } +} + `; +export function useUserEmailPageMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UserEmailPageDocument, options); +} +export type UserEmailPageMutationHookResult = ReturnType; export const LinkAlexaDocument = gql` mutation linkAlexa($code: String!, $state: String!) { linkAlexa(code: $code, state: $state) { @@ -1450,9 +2066,9 @@ export const LinkAlexaDocument = gql` } `; export function useLinkAlexaMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(LinkAlexaDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(LinkAlexaDocument, options); +} export type LinkAlexaMutationHookResult = ReturnType; export const LoginPageLoginDocument = gql` mutation LoginPageLogin($email: String!) { @@ -1464,9 +2080,9 @@ export const LoginPageLoginDocument = gql` } `; export function useLoginPageLoginMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(LoginPageLoginDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(LoginPageLoginDocument, options); +} export type LoginPageLoginMutationHookResult = ReturnType; export const MarkUserForDeleteDocument = gql` mutation MarkUserForDelete($id: ID!) { @@ -1485,10 +2101,22 @@ export const MarkUserForDeleteDocument = gql` } `; export function useMarkUserForDeleteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(MarkUserForDeleteDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(MarkUserForDeleteDocument, options); +} export type MarkUserForDeleteMutationHookResult = ReturnType; +export const DidSendEmailDocument = gql` + mutation DidSendEmail($id: ID!, $didSendEmail: Boolean!) { + didSendEmail(id: $id, didSendEmail: $didSendEmail) { + didSendEmail + } +} + `; +export function useDidSendEmailMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(DidSendEmailDocument, options); +} +export type DidSendEmailMutationHookResult = ReturnType; export const PublishAllCommentsDocument = gql` mutation publishAllComments($id: ID!, $traineeId: ID!) { publishAllComments(id: $id, traineeId: $traineeId) { @@ -1509,9 +2137,9 @@ export const PublishAllCommentsDocument = gql` } `; export function usePublishAllCommentsMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(PublishAllCommentsDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(PublishAllCommentsDocument, options); +} export type PublishAllCommentsMutationHookResult = ReturnType; export const SignatureSettingsUpdateSignatureDocument = gql` mutation SignatureSettingsUpdateSignature($signature: String) { @@ -1522,9 +2150,9 @@ export const SignatureSettingsUpdateSignatureDocument = gql` } `; export function useSignatureSettingsUpdateSignatureMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(SignatureSettingsUpdateSignatureDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(SignatureSettingsUpdateSignatureDocument, options); +} export type SignatureSettingsUpdateSignatureMutationHookResult = ReturnType; export const TraineeSettingsUpdateTraineeDocument = gql` mutation TraineeSettingsUpdateTrainee($course: String) { @@ -1535,9 +2163,9 @@ export const TraineeSettingsUpdateTraineeDocument = gql` } `; export function useTraineeSettingsUpdateTraineeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(TraineeSettingsUpdateTraineeDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(TraineeSettingsUpdateTraineeDocument, options); +} export type TraineeSettingsUpdateTraineeMutationHookResult = ReturnType; export const UnclaimTraineeDocument = gql` mutation unclaimTrainee($id: ID!) { @@ -1558,9 +2186,9 @@ export const UnclaimTraineeDocument = gql` } `; export function useUnclaimTraineeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UnclaimTraineeDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UnclaimTraineeDocument, options); +} export type UnclaimTraineeMutationHookResult = ReturnType; export const UnlinkAlexaDocument = gql` mutation unlinkAlexa { @@ -1571,9 +2199,9 @@ export const UnlinkAlexaDocument = gql` } `; export function useUnlinkAlexaMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UnlinkAlexaDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UnlinkAlexaDocument, options); +} export type UnlinkAlexaMutationHookResult = ReturnType; export const UnmarkUserForDeleteDocument = gql` mutation UnmarkUserForDelete($id: ID!) { @@ -1592,9 +2220,9 @@ export const UnmarkUserForDeleteDocument = gql` } `; export function useUnmarkUserForDeleteMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UnmarkUserForDeleteDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UnmarkUserForDeleteDocument, options); +} export type UnmarkUserForDeleteMutationHookResult = ReturnType; export const UpdateAdminDocument = gql` mutation UpdateAdmin($input: UpdateAdminInput!, $id: ID!) { @@ -1608,9 +2236,9 @@ export const UpdateAdminDocument = gql` } `; export function useUpdateAdminMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateAdminDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateAdminDocument, options); +} export type UpdateAdminMutationHookResult = ReturnType; export const UpdateCommentOnDayDocument = gql` mutation updateCommentOnDay($id: ID!, $text: String!, $traineeId: ID!, $commentId: ID!) { @@ -1639,9 +2267,9 @@ export const UpdateCommentOnDayDocument = gql` } `; export function useUpdateCommentOnDayMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateCommentOnDayDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateCommentOnDayDocument, options); +} export type UpdateCommentOnDayMutationHookResult = ReturnType; export const UpdateCommentOnEntryDocument = gql` mutation updateCommentOnEntry($id: ID!, $text: String!, $traineeId: ID!, $commentId: ID!) { @@ -1670,9 +2298,9 @@ export const UpdateCommentOnEntryDocument = gql` } `; export function useUpdateCommentOnEntryMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateCommentOnEntryDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateCommentOnEntryDocument, options); +} export type UpdateCommentOnEntryMutationHookResult = ReturnType; export const UpdateCommentOnReportDocument = gql` mutation updateCommentOnReport($id: ID!, $text: String!, $traineeId: ID!, $commentId: ID!) { @@ -1701,9 +2329,9 @@ export const UpdateCommentOnReportDocument = gql` } `; export function useUpdateCommentOnReportMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateCommentOnReportDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateCommentOnReportDocument, options); +} export type UpdateCommentOnReportMutationHookResult = ReturnType; export const UpdateEntryOrderDocument = gql` mutation updateEntryOrder($entryId: ID!, $dayId: ID!, $orderId: Int!) { @@ -1733,9 +2361,9 @@ export const UpdateEntryOrderDocument = gql` } `; export function useUpdateEntryOrderMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateEntryOrderDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateEntryOrderDocument, options); +} export type UpdateEntryOrderMutationHookResult = ReturnType; export const UpdateEntryDocument = gql` mutation updateEntry($id: ID!, $input: EntryInput!) { @@ -1749,10 +2377,121 @@ export const UpdateEntryDocument = gql` } `; export function useUpdateEntryMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateEntryDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateEntryDocument, options); +} export type UpdateEntryMutationHookResult = ReturnType; +export const UpdateFazitCursorPosDocument = gql` + mutation updateFazitCursorPos($id: ID!, $cursorPosition: CursorInput!) { + updateFazitCursorPos(id: $id, cursorPosition: $cursorPosition) { + position + owner + } +} + `; +export function useUpdateFazitCursorPosMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateFazitCursorPosDocument, options); +} +export type UpdateFazitCursorPosMutationHookResult = ReturnType; +export const FazitUpdateDocument = gql` + mutation FazitUpdate($id: ID!, $content: String!, $version: Int!, $cursorPosition: CursorInput!, $mentorDone: Boolean, $traineeDone: Boolean) { + updateFazit( + id: $id + content: $content + version: $version + cursorPosition: $cursorPosition + mentorDone: $mentorDone + traineeDone: $traineeDone + + ) { + success + newFazit { + id + content + version + mentorDone + traineeDone + + cursorPositions { + position + owner + } + } + } +} + `; +export function useFazitUpdateMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(FazitUpdateDocument, options); +} +export type FazitUpdateMutationHookResult = ReturnType; +export const UpdateMentorDocument = gql` + mutation UpdateMentor($input: UpdateMentorInput!, $id: ID!) { + updateMentor(input: $input, id: $id) { + id + startDate + endDate + firstName + lastName + email + type + } +} + `; +export function useUpdateMentorMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateMentorDocument, options); +} +export type UpdateMentorMutationHookResult = ReturnType; +export const UpdatePaperDocument = gql` + mutation updatePaper($input: PaperUpdateInput!) { + updatePaper(input: $input) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + answer + hint + } + feedbackTrainee { + id + questionId + answer + hint + comments { + text + userId + } + } + feedbackMentor { + id + questionId + answer + hint + comments { + text + userId + } + } + } +} + `; +export function useUpdatePaperMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdatePaperDocument, options); +} +export type UpdatePaperMutationHookResult = ReturnType; export const UpdateReportReportReviewPageDocument = gql` mutation updateReportReportReviewPage($id: ID!, $summary: String, $department: String, $status: String) { updateReport( @@ -1775,9 +2514,9 @@ export const UpdateReportReportReviewPageDocument = gql` } `; export function useUpdateReportReportReviewPageMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateReportReportReviewPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateReportReportReviewPageDocument, options); +} export type UpdateReportReportReviewPageMutationHookResult = ReturnType; export const UpdateReportDocument = gql` mutation updateReport($id: ID!, $summary: String, $department: String, $status: String) { @@ -1797,9 +2536,9 @@ export const UpdateReportDocument = gql` } `; export function useUpdateReportMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateReportDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateReportDocument, options); +} export type UpdateReportMutationHookResult = ReturnType; export const UpdateTraineeDocument = gql` mutation UpdateTrainee($input: UpdateTraineeInput!, $id: ID!) { @@ -1818,9 +2557,9 @@ export const UpdateTraineeDocument = gql` } `; export function useUpdateTraineeMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateTraineeDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateTraineeDocument, options); +} export type UpdateTraineeMutationHookResult = ReturnType; export const UpdateTrainerDocument = gql` mutation UpdateTrainer($input: UpdateTrainerInput!, $id: ID!) { @@ -1834,9 +2573,9 @@ export const UpdateTrainerDocument = gql` } `; export function useUpdateTrainerMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateTrainerDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useMutation(UpdateTrainerDocument, options); +} export type UpdateTrainerMutationHookResult = ReturnType; export const AdminAdminsPageDocument = gql` query AdminAdminsPage { @@ -1849,20 +2588,47 @@ export const AdminAdminsPageDocument = gql` } `; export function useAdminAdminsPageQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(AdminAdminsPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(AdminAdminsPageDocument, options); +} export function useAdminAdminsPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(AdminAdminsPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(AdminAdminsPageDocument, options); +} export function useAdminAdminsPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(AdminAdminsPageDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(AdminAdminsPageDocument, options); +} export type AdminAdminsPageQueryHookResult = ReturnType; export type AdminAdminsPageLazyQueryHookResult = ReturnType; export type AdminAdminsPageSuspenseQueryHookResult = ReturnType; +export const AdminMentorPageDocument = gql` + query AdminMentorPage { + mentors { + id + firstName + lastName + startDate + endDate + deleteAt + } +} + `; +export function useAdminMentorPageQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(AdminMentorPageDocument, options); +} +export function useAdminMentorPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(AdminMentorPageDocument, options); +} +export function useAdminMentorPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(AdminMentorPageDocument, options); +} +export type AdminMentorPageQueryHookResult = ReturnType; +export type AdminMentorPageLazyQueryHookResult = ReturnType; +export type AdminMentorPageSuspenseQueryHookResult = ReturnType; export const AdminTraineesPageDocument = gql` query AdminTraineesPage { trainees { @@ -1878,17 +2644,17 @@ export const AdminTraineesPageDocument = gql` } `; export function useAdminTraineesPageQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(AdminTraineesPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(AdminTraineesPageDocument, options); +} export function useAdminTraineesPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(AdminTraineesPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(AdminTraineesPageDocument, options); +} export function useAdminTraineesPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(AdminTraineesPageDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(AdminTraineesPageDocument, options); +} export type AdminTraineesPageQueryHookResult = ReturnType; export type AdminTraineesPageLazyQueryHookResult = ReturnType; export type AdminTraineesPageSuspenseQueryHookResult = ReturnType; @@ -1903,17 +2669,17 @@ export const AdminTrainersPageDocument = gql` } `; export function useAdminTrainersPageQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(AdminTrainersPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(AdminTrainersPageDocument, options); +} export function useAdminTrainersPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(AdminTrainersPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(AdminTrainersPageDocument, options); +} export function useAdminTrainersPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(AdminTrainersPageDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(AdminTrainersPageDocument, options); +} export type AdminTrainersPageQueryHookResult = ReturnType; export type AdminTrainersPageLazyQueryHookResult = ReturnType; export type AdminTrainersPageSuspenseQueryHookResult = ReturnType; @@ -1923,17 +2689,17 @@ export const AlexaLinkingUrlDocument = gql` } `; export function useAlexaLinkingUrlQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(AlexaLinkingUrlDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(AlexaLinkingUrlDocument, options); +} export function useAlexaLinkingUrlLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(AlexaLinkingUrlDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(AlexaLinkingUrlDocument, options); +} export function useAlexaLinkingUrlSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(AlexaLinkingUrlDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(AlexaLinkingUrlDocument, options); +} export type AlexaLinkingUrlQueryHookResult = ReturnType; export type AlexaLinkingUrlLazyQueryHookResult = ReturnType; export type AlexaLinkingUrlSuspenseQueryHookResult = ReturnType; @@ -1967,17 +2733,17 @@ export const ArchivePageDataDocument = gql` } `; export function useArchivePageDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ArchivePageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(ArchivePageDataDocument, options); +} export function useArchivePageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ArchivePageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(ArchivePageDataDocument, options); +} export function useArchivePageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(ArchivePageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(ArchivePageDataDocument, options); +} export type ArchivePageDataQueryHookResult = ReturnType; export type ArchivePageDataLazyQueryHookResult = ReturnType; export type ArchivePageDataSuspenseQueryHookResult = ReturnType; @@ -1989,17 +2755,17 @@ export const AvatarSettingsDataDocument = gql` } `; export function useAvatarSettingsDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(AvatarSettingsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(AvatarSettingsDataDocument, options); +} export function useAvatarSettingsDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(AvatarSettingsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(AvatarSettingsDataDocument, options); +} export function useAvatarSettingsDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(AvatarSettingsDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(AvatarSettingsDataDocument, options); +} export type AvatarSettingsDataQueryHookResult = ReturnType; export type AvatarSettingsDataLazyQueryHookResult = ReturnType; export type AvatarSettingsDataSuspenseQueryHookResult = ReturnType; @@ -2011,17 +2777,17 @@ export const CommentBoxDataDocument = gql` } `; export function useCommentBoxDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(CommentBoxDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(CommentBoxDataDocument, options); +} export function useCommentBoxDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(CommentBoxDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(CommentBoxDataDocument, options); +} export function useCommentBoxDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(CommentBoxDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(CommentBoxDataDocument, options); +} export type CommentBoxDataQueryHookResult = ReturnType; export type CommentBoxDataLazyQueryHookResult = ReturnType; export type CommentBoxDataSuspenseQueryHookResult = ReturnType; @@ -2040,17 +2806,17 @@ export const ConfigDocument = gql` } `; export function useConfigQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ConfigDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(ConfigDocument, options); +} export function useConfigLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ConfigDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(ConfigDocument, options); +} export function useConfigSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(ConfigDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(ConfigDocument, options); +} export type ConfigQueryHookResult = ReturnType; export type ConfigLazyQueryHookResult = ReturnType; export type ConfigSuspenseQueryHookResult = ReturnType; @@ -2068,28 +2834,196 @@ export const CurrentUserDocument = gql` startDate endDate course + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + text + firstName + lastName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + firstName + lastName + text + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + text + firstName + lastName + published + } + } + } } ... on Trainer { id trainees { id } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + } + } + ... on Mentor { + id + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + text + firstName + lastName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + firstName + lastName + text + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + } } } } `; export function useCurrentUserQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(CurrentUserDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(CurrentUserDocument, options); +} export function useCurrentUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(CurrentUserDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(CurrentUserDocument, options); +} export function useCurrentUserSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(CurrentUserDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(CurrentUserDocument, options); +} export type CurrentUserQueryHookResult = ReturnType; export type CurrentUserLazyQueryHookResult = ReturnType; export type CurrentUserSuspenseQueryHookResult = ReturnType; @@ -2150,18 +3084,18 @@ export const DashboardPageDataDocument = gql` } } `; -export function useDashboardPageDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: DashboardPageDataQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(DashboardPageDataDocument, options); - } +export function useDashboardPageDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: DashboardPageDataQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(DashboardPageDataDocument, options); +} export function useDashboardPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(DashboardPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(DashboardPageDataDocument, options); +} export function useDashboardPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(DashboardPageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(DashboardPageDataDocument, options); +} export type DashboardPageDataQueryHookResult = ReturnType; export type DashboardPageDataLazyQueryHookResult = ReturnType; export type DashboardPageDataSuspenseQueryHookResult = ReturnType; @@ -2176,17 +3110,17 @@ export const DayInputDataDocument = gql` } `; export function useDayInputDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(DayInputDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(DayInputDataDocument, options); +} export function useDayInputDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(DayInputDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(DayInputDataDocument, options); +} export function useDayInputDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(DayInputDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(DayInputDataDocument, options); +} export type DayInputDataQueryHookResult = ReturnType; export type DayInputDataLazyQueryHookResult = ReturnType; export type DayInputDataSuspenseQueryHookResult = ReturnType; @@ -2201,20 +3135,42 @@ export const EntryInputDataDocument = gql` } `; export function useEntryInputDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(EntryInputDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(EntryInputDataDocument, options); +} export function useEntryInputDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(EntryInputDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(EntryInputDataDocument, options); +} export function useEntryInputDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(EntryInputDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(EntryInputDataDocument, options); +} export type EntryInputDataQueryHookResult = ReturnType; export type EntryInputDataLazyQueryHookResult = ReturnType; export type EntryInputDataSuspenseQueryHookResult = ReturnType; +export const FeedbackDoneDocument = gql` + query FeedbackDone($id: ID!) { + getPaper(id: $id) { + didSendEmail + } +} + `; +export function useFeedbackDoneQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: FeedbackDoneQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(FeedbackDoneDocument, options); +} +export function useFeedbackDoneLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(FeedbackDoneDocument, options); +} +export function useFeedbackDoneSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(FeedbackDoneDocument, options); +} +export type FeedbackDoneQueryHookResult = ReturnType; +export type FeedbackDoneLazyQueryHookResult = ReturnType; +export type FeedbackDoneSuspenseQueryHookResult = ReturnType; export const UserPageDocument = gql` query UserPage($id: ID!) { getUser(id: $id) { @@ -2249,6 +3205,11 @@ export const UserPageDocument = gql` ... on Admin { deleteAt } + ... on Mentor { + deleteAt + startDate + endDate + } } companies { id @@ -2259,21 +3220,144 @@ export const UserPageDocument = gql` } } `; -export function useUserPageQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: UserPageQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(UserPageDocument, options); - } +export function useUserPageQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: UserPageQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(UserPageDocument, options); +} export function useUserPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(UserPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(UserPageDocument, options); +} export function useUserPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(UserPageDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(UserPageDocument, options); +} export type UserPageQueryHookResult = ReturnType; export type UserPageLazyQueryHookResult = ReturnType; export type UserPageSuspenseQueryHookResult = ReturnType; +export const GetFazitDocument = gql` + query GetFazit($id: ID!) { + getFazit(id: $id) { + id + content + version + mentorDone + traineeDone + cursorPositions { + owner + position + } + } +} + `; +export function useGetFazitQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: GetFazitQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(GetFazitDocument, options); +} +export function useGetFazitLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(GetFazitDocument, options); +} +export function useGetFazitSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(GetFazitDocument, options); +} +export type GetFazitQueryHookResult = ReturnType; +export type GetFazitLazyQueryHookResult = ReturnType; +export type GetFazitSuspenseQueryHookResult = ReturnType; +export const MentorsPageDocument = gql` + query MentorsPage { + mentors { + id + firstName + lastName + startDate + endDate + } +} + `; +export function useMentorsPageQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(MentorsPageDocument, options); +} +export function useMentorsPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(MentorsPageDocument, options); +} +export function useMentorsPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(MentorsPageDocument, options); +} +export type MentorsPageQueryHookResult = ReturnType; +export type MentorsPageLazyQueryHookResult = ReturnType; +export type MentorsPageSuspenseQueryHookResult = ReturnType; +export const MentorPaperPageDataDocument = gql` + query MentorPaperPageData { + currentUser { + id + ... on Mentor { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + } + } + } + } + } +} + `; +export function useMentorPaperPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(MentorPaperPageDataDocument, options); +} +export function useMentorPaperPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(MentorPaperPageDataDocument, options); +} +export function useMentorPaperPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(MentorPaperPageDataDocument, options); +} +export type MentorPaperPageDataQueryHookResult = ReturnType; +export type MentorPaperPageDataLazyQueryHookResult = ReturnType; +export type MentorPaperPageDataSuspenseQueryHookResult = ReturnType; export const NavigationDataDocument = gql` query NavigationData { currentUser { @@ -2286,17 +3370,17 @@ export const NavigationDataDocument = gql` } `; export function useNavigationDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(NavigationDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(NavigationDataDocument, options); +} export function useNavigationDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(NavigationDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(NavigationDataDocument, options); +} export function useNavigationDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(NavigationDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(NavigationDataDocument, options); +} export type NavigationDataQueryHookResult = ReturnType; export type NavigationDataLazyQueryHookResult = ReturnType; export type NavigationDataSuspenseQueryHookResult = ReturnType; @@ -2309,20 +3393,322 @@ export const OnboardingPageDataDocument = gql` } `; export function useOnboardingPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(OnboardingPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(OnboardingPageDataDocument, options); +} export function useOnboardingPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(OnboardingPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(OnboardingPageDataDocument, options); +} export function useOnboardingPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(OnboardingPageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(OnboardingPageDataDocument, options); +} export type OnboardingPageDataQueryHookResult = ReturnType; export type OnboardingPageDataLazyQueryHookResult = ReturnType; export type OnboardingPageDataSuspenseQueryHookResult = ReturnType; +export const PaperFazitPageDocument = gql` + query PaperFazitPage($id: ID!) { + getPaper(id: $id) { + id + traineeId + trainerId + status + briefing { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + conclusion + archivedAt + createdAt + client + mentorId + didSendEmail + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + fazit { + id + content + version + mentorDone + traineeDone + cursorPositions { + position + owner + } + } + } +} + `; +export function usePaperFazitPageQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: PaperFazitPageQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(PaperFazitPageDocument, options); +} +export function usePaperFazitPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(PaperFazitPageDocument, options); +} +export function usePaperFazitPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(PaperFazitPageDocument, options); +} +export type PaperFazitPageQueryHookResult = ReturnType; +export type PaperFazitPageLazyQueryHookResult = ReturnType; +export type PaperFazitPageSuspenseQueryHookResult = ReturnType; +export const FeedbackDiscussionPageDataDocument = gql` + query FeedbackDiscussionPageData { + currentUser { + id + firstName + lastName + ... on Mentor { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + fazit { + content + version + mentorDone + traineeDone + } + briefing { + id + questionId + question + answer + hint + comments { + text + lastName + firstName + userId + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } + } + ... on Trainee { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + fazit { + content + version + mentorDone + traineeDone + } + briefing { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } + } + ... on Trainer { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + fazit { + content + version + mentorDone + traineeDone + } + briefing { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } + } + } +} + `; +export function useFeedbackDiscussionPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(FeedbackDiscussionPageDataDocument, options); +} +export function useFeedbackDiscussionPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(FeedbackDiscussionPageDataDocument, options); +} +export function useFeedbackDiscussionPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(FeedbackDiscussionPageDataDocument, options); +} +export type FeedbackDiscussionPageDataQueryHookResult = ReturnType; +export type FeedbackDiscussionPageDataLazyQueryHookResult = ReturnType; +export type FeedbackDiscussionPageDataSuspenseQueryHookResult = ReturnType; export const PrintDataDocument = gql` query PrintData($ids: [ID!]!) { print(ids: $ids) { @@ -2330,21 +3716,44 @@ export const PrintDataDocument = gql` } } `; -export function usePrintDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: PrintDataQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(PrintDataDocument, options); - } +export function usePrintDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: PrintDataQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(PrintDataDocument, options); +} export function usePrintDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(PrintDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(PrintDataDocument, options); +} export function usePrintDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(PrintDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(PrintDataDocument, options); +} export type PrintDataQueryHookResult = ReturnType; export type PrintDataLazyQueryHookResult = ReturnType; export type PrintDataSuspenseQueryHookResult = ReturnType; +export const PrintPaperDataDocument = gql` + query PrintPaperData($ids: [ID!]!, $userType: UserTypeEnum!) { + printPaper(ids: $ids, userType: $userType) { + estimatedWaitingTime + pdfUrl + } +} + `; +export function usePrintPaperDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: PrintPaperDataQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(PrintPaperDataDocument, options); +} +export function usePrintPaperDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(PrintPaperDataDocument, options); +} +export function usePrintPaperDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(PrintPaperDataDocument, options); +} +export type PrintPaperDataQueryHookResult = ReturnType; +export type PrintPaperDataLazyQueryHookResult = ReturnType; +export type PrintPaperDataSuspenseQueryHookResult = ReturnType; export const ReportPageDataDocument = gql` query ReportPageData($year: Int!, $week: Int!) { currentUser { @@ -2409,18 +3818,18 @@ export const ReportPageDataDocument = gql` } } `; -export function useReportPageDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: ReportPageDataQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ReportPageDataDocument, options); - } +export function useReportPageDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: ReportPageDataQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(ReportPageDataDocument, options); +} export function useReportPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ReportPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(ReportPageDataDocument, options); +} export function useReportPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(ReportPageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(ReportPageDataDocument, options); +} export type ReportPageDataQueryHookResult = ReturnType; export type ReportPageDataLazyQueryHookResult = ReturnType; export type ReportPageDataSuspenseQueryHookResult = ReturnType; @@ -2482,18 +3891,18 @@ export const ReportReviewPageDataDocument = gql` } } `; -export function useReportReviewPageDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: ReportReviewPageDataQueryVariables; skip?: boolean; } | { skip: boolean; }) ) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(ReportReviewPageDataDocument, options); - } +export function useReportReviewPageDataQuery(baseOptions: Apollo.QueryHookOptions & ({ variables: ReportReviewPageDataQueryVariables; skip?: boolean; } | { skip: boolean; })) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(ReportReviewPageDataDocument, options); +} export function useReportReviewPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(ReportReviewPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(ReportReviewPageDataDocument, options); +} export function useReportReviewPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(ReportReviewPageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(ReportReviewPageDataDocument, options); +} export type ReportReviewPageDataQueryHookResult = ReturnType; export type ReportReviewPageDataLazyQueryHookResult = ReturnType; export type ReportReviewPageDataSuspenseQueryHookResult = ReturnType; @@ -2523,17 +3932,17 @@ export const SettingsPageDataDocument = gql` } `; export function useSettingsPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SettingsPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(SettingsPageDataDocument, options); +} export function useSettingsPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SettingsPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(SettingsPageDataDocument, options); +} export function useSettingsPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(SettingsPageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(SettingsPageDataDocument, options); +} export type SettingsPageDataQueryHookResult = ReturnType; export type SettingsPageDataLazyQueryHookResult = ReturnType; export type SettingsPageDataSuspenseQueryHookResult = ReturnType; @@ -2546,17 +3955,17 @@ export const SignatureSettingsDataDocument = gql` } `; export function useSignatureSettingsDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SignatureSettingsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(SignatureSettingsDataDocument, options); +} export function useSignatureSettingsDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SignatureSettingsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(SignatureSettingsDataDocument, options); +} export function useSignatureSettingsDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(SignatureSettingsDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(SignatureSettingsDataDocument, options); +} export type SignatureSettingsDataQueryHookResult = ReturnType; export type SignatureSettingsDataLazyQueryHookResult = ReturnType; export type SignatureSettingsDataSuspenseQueryHookResult = ReturnType; @@ -2569,17 +3978,17 @@ export const SuggestionsDataDocument = gql` } `; export function useSuggestionsDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SuggestionsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(SuggestionsDataDocument, options); +} export function useSuggestionsDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SuggestionsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(SuggestionsDataDocument, options); +} export function useSuggestionsDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(SuggestionsDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(SuggestionsDataDocument, options); +} export type SuggestionsDataQueryHookResult = ReturnType; export type SuggestionsDataLazyQueryHookResult = ReturnType; export type SuggestionsDataSuspenseQueryHookResult = ReturnType; @@ -2596,6 +4005,54 @@ export const TraineePageDataDocument = gql` firstName lastName } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } company { id name @@ -2607,20 +4064,145 @@ export const TraineePageDataDocument = gql` } `; export function useTraineePageDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(TraineePageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TraineePageDataDocument, options); +} export function useTraineePageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(TraineePageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TraineePageDataDocument, options); +} export function useTraineePageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(TraineePageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TraineePageDataDocument, options); +} export type TraineePageDataQueryHookResult = ReturnType; export type TraineePageDataLazyQueryHookResult = ReturnType; export type TraineePageDataSuspenseQueryHookResult = ReturnType; +export const TraineePaperPageDataDocument = gql` + query TraineePaperPageData { + currentUser { + id + ... on Trainee { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + } + } + } + } + } +} + `; +export function useTraineePaperPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TraineePaperPageDataDocument, options); +} +export function useTraineePaperPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TraineePaperPageDataDocument, options); +} +export function useTraineePaperPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TraineePaperPageDataDocument, options); +} +export type TraineePaperPageDataQueryHookResult = ReturnType; +export type TraineePaperPageDataLazyQueryHookResult = ReturnType; +export type TraineePaperPageDataSuspenseQueryHookResult = ReturnType; +export const TraineePaperDataDocument = gql` + query TraineePaperData { + currentUser { + ... on Trainee { + id + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } + } + } +} + `; +export function useTraineePaperDataQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TraineePaperDataDocument, options); +} +export function useTraineePaperDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TraineePaperDataDocument, options); +} +export function useTraineePaperDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TraineePaperDataDocument, options); +} +export type TraineePaperDataQueryHookResult = ReturnType; +export type TraineePaperDataLazyQueryHookResult = ReturnType; +export type TraineePaperDataSuspenseQueryHookResult = ReturnType; export const TraineeSettingsDataDocument = gql` query TraineeSettingsData { currentUser { @@ -2645,20 +4227,83 @@ export const TraineeSettingsDataDocument = gql` } `; export function useTraineeSettingsDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(TraineeSettingsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TraineeSettingsDataDocument, options); +} export function useTraineeSettingsDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(TraineeSettingsDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TraineeSettingsDataDocument, options); +} export function useTraineeSettingsDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(TraineeSettingsDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TraineeSettingsDataDocument, options); +} export type TraineeSettingsDataQueryHookResult = ReturnType; export type TraineeSettingsDataLazyQueryHookResult = ReturnType; export type TraineeSettingsDataSuspenseQueryHookResult = ReturnType; +export const TrainerPaperPageDataDocument = gql` + query TrainerPaperPageData { + currentUser { + id + ... on Trainer { + trainees { + firstName + lastName + id + } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } + } + } +} + `; +export function useTrainerPaperPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TrainerPaperPageDataDocument, options); +} +export function useTrainerPaperPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TrainerPaperPageDataDocument, options); +} +export function useTrainerPaperPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TrainerPaperPageDataDocument, options); +} +export type TrainerPaperPageDataQueryHookResult = ReturnType; +export type TrainerPaperPageDataLazyQueryHookResult = ReturnType; +export type TrainerPaperPageDataSuspenseQueryHookResult = ReturnType; export const TrainerReportsPageDataDocument = gql` query TrainerReportsPageData { currentUser { @@ -2685,17 +4330,17 @@ export const TrainerReportsPageDataDocument = gql` } `; export function useTrainerReportsPageDataQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(TrainerReportsPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TrainerReportsPageDataDocument, options); +} export function useTrainerReportsPageDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(TrainerReportsPageDataDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TrainerReportsPageDataDocument, options); +} export function useTrainerReportsPageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(TrainerReportsPageDataDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TrainerReportsPageDataDocument, options); +} export type TrainerReportsPageDataQueryHookResult = ReturnType; export type TrainerReportsPageDataLazyQueryHookResult = ReturnType; export type TrainerReportsPageDataSuspenseQueryHookResult = ReturnType; @@ -2709,17 +4354,17 @@ export const TrainersPageDocument = gql` } `; export function useTrainersPageQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(TrainersPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useQuery(TrainersPageDocument, options); +} export function useTrainersPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(TrainersPageDocument, options); - } + const options = { ...defaultOptions, ...baseOptions } + return Apollo.useLazyQuery(TrainersPageDocument, options); +} export function useTrainersPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { - const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(TrainersPageDocument, options); - } + const options = baseOptions === Apollo.skipToken ? baseOptions : { ...defaultOptions, ...baseOptions } + return Apollo.useSuspenseQuery(TrainersPageDocument, options); +} export type TrainersPageQueryHookResult = ReturnType; export type TrainersPageLazyQueryHookResult = ReturnType; -export type TrainersPageSuspenseQueryHookResult = ReturnType; \ No newline at end of file +export type TrainersPageSuspenseQueryHookResult = ReturnType; diff --git a/packages/frontend/src/graphql/mutations/create-mentor.gql b/packages/frontend/src/graphql/mutations/create-mentor.gql new file mode 100644 index 00000000..72bf9cd0 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/create-mentor.gql @@ -0,0 +1,12 @@ +mutation CreateMentor($input: CreateMentorInput!) { + createMentor(input: $input) { + id + firstName + lastName + startDate + endDate + email + type + deleteAt + } +} diff --git a/packages/frontend/src/graphql/mutations/create-paper.gql b/packages/frontend/src/graphql/mutations/create-paper.gql new file mode 100644 index 00000000..99e05e83 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/create-paper.gql @@ -0,0 +1,36 @@ +mutation createPaper($input: PaperInput!) { + createPaper(input: $input) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } +} diff --git a/packages/frontend/src/graphql/mutations/delete-paper.gql b/packages/frontend/src/graphql/mutations/delete-paper.gql new file mode 100644 index 00000000..c6e2d4b9 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/delete-paper.gql @@ -0,0 +1,33 @@ +mutation deletePaper($paperId: ID!) { + deletePaper(paperId: $paperId) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + answer + hint + } + feedbackTrainee { + id + questionId + answer + hint + } + feedbackMentor { + id + questionId + answer + hint + } + } +} diff --git a/packages/frontend/src/graphql/mutations/get-user-by-email.gql b/packages/frontend/src/graphql/mutations/get-user-by-email.gql new file mode 100644 index 00000000..5a372ca5 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/get-user-by-email.gql @@ -0,0 +1,39 @@ +mutation UserEmailPage($email: String!) { + getUserByEmail(email: $email) { + id + firstName + lastName + email + type + + ... on Trainee { + startDate + startOfToolUsage + endDate + deleteAt + course + company { + id + } + trainer { + id + firstName + lastName + } + } + + ... on Trainer { + deleteAt + trainees { + id + firstName + lastName + } + } + ... on Mentor { + deleteAt + startDate + endDate + } + } +} diff --git a/packages/frontend/src/graphql/mutations/paper-did-send-email.gql b/packages/frontend/src/graphql/mutations/paper-did-send-email.gql new file mode 100644 index 00000000..c7c72d28 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/paper-did-send-email.gql @@ -0,0 +1,5 @@ +mutation DidSendEmail($id: ID!, $didSendEmail: Boolean!) { + didSendEmail(id: $id, didSendEmail: $didSendEmail) { + didSendEmail + } +} \ No newline at end of file diff --git a/packages/frontend/src/graphql/mutations/update-fazit-cursor-pos.gql b/packages/frontend/src/graphql/mutations/update-fazit-cursor-pos.gql new file mode 100644 index 00000000..e4dae647 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/update-fazit-cursor-pos.gql @@ -0,0 +1,6 @@ +mutation updateFazitCursorPos($id: ID! $cursorPosition: CursorInput!) { + updateFazitCursorPos(id: $id cursorPosition: $cursorPosition) { + position + owner + } +} \ No newline at end of file diff --git a/packages/frontend/src/graphql/mutations/update-fazit.gql b/packages/frontend/src/graphql/mutations/update-fazit.gql new file mode 100644 index 00000000..35847827 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/update-fazit.gql @@ -0,0 +1,16 @@ +mutation FazitUpdate($id: ID! $content: String! $version: Int! $cursorPosition: CursorInput! $mentorDone: Boolean, $traineeDone: Boolean) { + updateFazit(id: $id content: $content version: $version cursorPosition: $cursorPosition mentorDone: $mentorDone traineeDone: $traineeDone) { + success + newFazit { + id + content + version + mentorDone + traineeDone + cursorPositions { + position + owner + } + } + } +} diff --git a/packages/frontend/src/graphql/mutations/update-mentor.gql b/packages/frontend/src/graphql/mutations/update-mentor.gql new file mode 100644 index 00000000..8eac1938 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/update-mentor.gql @@ -0,0 +1,11 @@ +mutation UpdateMentor($input: UpdateMentorInput!, $id: ID!) { + updateMentor(input: $input, id: $id) { + id + startDate + endDate + firstName + lastName + email + type + } +} diff --git a/packages/frontend/src/graphql/mutations/update-paper.gql b/packages/frontend/src/graphql/mutations/update-paper.gql new file mode 100644 index 00000000..1a4569b9 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/update-paper.gql @@ -0,0 +1,41 @@ +mutation updatePaper($input: PaperUpdateInput!) { + updatePaper(input: $input) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + answer + hint + } + feedbackTrainee { + id + questionId + answer + hint + comments { + text + userId + } + } + feedbackMentor { + id + questionId + answer + hint + comments { + text + userId + } + } + } +} diff --git a/packages/frontend/src/graphql/queries/admin-mentor-page.gql b/packages/frontend/src/graphql/queries/admin-mentor-page.gql new file mode 100644 index 00000000..9050f809 --- /dev/null +++ b/packages/frontend/src/graphql/queries/admin-mentor-page.gql @@ -0,0 +1,10 @@ +query AdminMentorPage { + mentors { + id + firstName + lastName + startDate + endDate + deleteAt + } +} diff --git a/packages/frontend/src/graphql/queries/current-user.gql b/packages/frontend/src/graphql/queries/current-user.gql index d5425661..20995000 100644 --- a/packages/frontend/src/graphql/queries/current-user.gql +++ b/packages/frontend/src/graphql/queries/current-user.gql @@ -11,12 +11,180 @@ query CurrentUser { startDate endDate course + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + text + firstName + lastName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + firstName + lastName + text + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + text + firstName + lastName + published + } + } + } } ... on Trainer { id trainees { id } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + } + } + ... on Mentor { + id + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + text + firstName + lastName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + firstName + lastName + text + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + firstName + text + lastName + published + } + } + } } } } diff --git a/packages/frontend/src/graphql/queries/feedback-done.gql b/packages/frontend/src/graphql/queries/feedback-done.gql new file mode 100644 index 00000000..c7f4276c --- /dev/null +++ b/packages/frontend/src/graphql/queries/feedback-done.gql @@ -0,0 +1,5 @@ +query FeedbackDone($id: ID!) { + getPaper(id: $id) { + didSendEmail + } +} \ No newline at end of file diff --git a/packages/frontend/src/graphql/queries/get-user.gql b/packages/frontend/src/graphql/queries/get-user.gql index 9c0fc4a1..80ec068c 100644 --- a/packages/frontend/src/graphql/queries/get-user.gql +++ b/packages/frontend/src/graphql/queries/get-user.gql @@ -34,6 +34,12 @@ query UserPage($id: ID!) { ... on Admin { deleteAt } + + ... on Mentor { + deleteAt + startDate + endDate + } } companies { id diff --git a/packages/frontend/src/graphql/queries/getFazit.gql b/packages/frontend/src/graphql/queries/getFazit.gql new file mode 100644 index 00000000..2951ae24 --- /dev/null +++ b/packages/frontend/src/graphql/queries/getFazit.gql @@ -0,0 +1,11 @@ +query GetFazit($id: ID!) { + getFazit(id: $id) { + id + content + version + cursorPositions { + owner + position + } + } +} \ No newline at end of file diff --git a/packages/frontend/src/graphql/queries/mentor-data.gql b/packages/frontend/src/graphql/queries/mentor-data.gql new file mode 100644 index 00000000..46ee23bf --- /dev/null +++ b/packages/frontend/src/graphql/queries/mentor-data.gql @@ -0,0 +1,9 @@ +query MentorsPage { + mentors { + id + firstName + lastName + startDate + endDate + } +} diff --git a/packages/frontend/src/graphql/queries/mentor-paper-page-data.gql b/packages/frontend/src/graphql/queries/mentor-paper-page-data.gql new file mode 100644 index 00000000..c2710e8c --- /dev/null +++ b/packages/frontend/src/graphql/queries/mentor-paper-page-data.gql @@ -0,0 +1,41 @@ +query MentorPaperPageData { + currentUser { + id + ... on Mentor { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } + } + } +} diff --git a/packages/frontend/src/graphql/queries/paper-fazit-page.gql b/packages/frontend/src/graphql/queries/paper-fazit-page.gql new file mode 100644 index 00000000..bde8ffc7 --- /dev/null +++ b/packages/frontend/src/graphql/queries/paper-fazit-page.gql @@ -0,0 +1,70 @@ +query PaperFazitPage($id: ID!) { + getPaper(id: $id) { + id + traineeId + trainerId + status + briefing { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + conclusion + archivedAt + createdAt + client + mentorId + didSendEmail + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + fazit { + id + content + version + cursorPositions { + position + owner + } + } + } +} \ No newline at end of file diff --git a/packages/frontend/src/graphql/queries/paper-feedback-discussion-page-data.gql b/packages/frontend/src/graphql/queries/paper-feedback-discussion-page-data.gql new file mode 100644 index 00000000..a86c6723 --- /dev/null +++ b/packages/frontend/src/graphql/queries/paper-feedback-discussion-page-data.gql @@ -0,0 +1,178 @@ +query FeedbackDiscussionPageData { + currentUser { + id + firstName + lastName + ... on Mentor { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + text + lastName + firstName + userId + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } + } + ... on Trainee { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } + } + ... on Trainer { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + text + userId + lastName + firstName + published + } + } + } + } + } +} diff --git a/packages/frontend/src/graphql/queries/print-paper-data.gql b/packages/frontend/src/graphql/queries/print-paper-data.gql new file mode 100644 index 00000000..ec6a874e --- /dev/null +++ b/packages/frontend/src/graphql/queries/print-paper-data.gql @@ -0,0 +1,6 @@ +query PrintPaperData($ids: [ID!]! $userType: UserTypeEnum!) { + printPaper(ids: $ids userType: $userType) { + estimatedWaitingTime + pdfUrl + } +} diff --git a/packages/frontend/src/graphql/queries/trainee-page-data.gql b/packages/frontend/src/graphql/queries/trainee-page-data.gql index ad88c855..05b45206 100644 --- a/packages/frontend/src/graphql/queries/trainee-page-data.gql +++ b/packages/frontend/src/graphql/queries/trainee-page-data.gql @@ -10,6 +10,40 @@ query TraineePageData { firstName lastName } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } company { id name diff --git a/packages/frontend/src/graphql/queries/trainee-paper-page-data.gql b/packages/frontend/src/graphql/queries/trainee-paper-page-data.gql new file mode 100644 index 00000000..cabf4c26 --- /dev/null +++ b/packages/frontend/src/graphql/queries/trainee-paper-page-data.gql @@ -0,0 +1,50 @@ +query TraineePaperPageData { + currentUser { + id + ... on Trainee { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + comments { + userId + } + } + feedbackTrainee { + id + questionId + question + answer + hint + comments { + userId + } + } + feedbackMentor { + id + questionId + question + answer + hint + comments { + userId + } + } + } + } + } +} diff --git a/packages/frontend/src/graphql/queries/trainee-paper.gql b/packages/frontend/src/graphql/queries/trainee-paper.gql new file mode 100644 index 00000000..5454faf3 --- /dev/null +++ b/packages/frontend/src/graphql/queries/trainee-paper.gql @@ -0,0 +1,41 @@ +query TraineePaperData { + currentUser { + ... on Trainee { + id + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } + } + } +} diff --git a/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql b/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql new file mode 100644 index 00000000..224aab2c --- /dev/null +++ b/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql @@ -0,0 +1,46 @@ +query TrainerPaperPageData { + currentUser { + id + ... on Trainer { + trainees { + firstName + lastName + id + } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedbackTrainee { + id + questionId + question + answer + hint + } + feedbackMentor { + id + questionId + question + answer + hint + } + } + } + } +} diff --git a/packages/frontend/src/helper/paper-helper.ts b/packages/frontend/src/helper/paper-helper.ts new file mode 100644 index 00000000..00cc306b --- /dev/null +++ b/packages/frontend/src/helper/paper-helper.ts @@ -0,0 +1,28 @@ +import { PaperStatus } from '../graphql' + +export type Question = { question: string; hint: string } + +export const mapStatusToProgess = (status: PaperStatus): number => { + switch (status) { + case 'Archived': + return 1 + case 'InProgress': + return 0.2 + case 'InReview': + return 0.7 + case 'MentorDone': + return 0.4 + case 'NotStarted': + return 0 + case 'ReviewDone': + return 0.9 + case 'TraineeDone': + return 0.4 + default: + return 0 + } +} + +export const isPaperFeatureEnabled = (): boolean => { + return ENVIRONMENT.nodeEnv === 'development' || ENVIRONMENT.nodeEnv === 'staging' +} diff --git a/packages/frontend/src/hooks/use-both-done.tsx b/packages/frontend/src/hooks/use-both-done.tsx new file mode 100644 index 00000000..af48da2e --- /dev/null +++ b/packages/frontend/src/hooks/use-both-done.tsx @@ -0,0 +1,111 @@ +import { useCallback, useEffect, useState } from 'react' +import { FazitUpdateMutation, GetFazitDocument, FazitUpdateMutationVariables } from '../graphql' +import { MutationFunctionOptions, FetchResult } from '@apollo/client' + +interface UseBothDoneProps { + fazit: { + mentorDone: boolean + traineeDone: boolean + } | null + currentRole: 'Mentor' | 'Trainee' + paperId: string + localContent: string + localVersion: number + currentUserId: string + updateFazit: ( + options: MutationFunctionOptions + ) => Promise> +} + +export function useBothDone({ + fazit, + currentRole, + paperId, + localContent, + localVersion, + currentUserId, + updateFazit, +}: UseBothDoneProps) { + // Local state for optimistic UI + const [mentorDone, setMentorDone] = useState(fazit?.mentorDone ?? false) + const [traineeDone, setTraineeDone] = useState(fazit?.traineeDone ?? false) + + // Sync local state with server whenever fazit changes + useEffect(() => { + if (fazit) { + setMentorDone(fazit.mentorDone) + setTraineeDone(fazit.traineeDone) + } + }, [fazit]) + + const bothDone = mentorDone && traineeDone + const currentRoleDone = currentRole === 'Mentor' ? mentorDone : traineeDone + const otherRoleDone = currentRole === 'Mentor' ? traineeDone : mentorDone + + const handleToggleDone = useCallback(async () => { + const newValue = !currentRoleDone + + const updatedMentorDone = currentRole === 'Mentor' ? newValue : mentorDone + const updatedTraineeDone = currentRole === 'Trainee' ? newValue : traineeDone + + // Optimistic local update + setMentorDone(updatedMentorDone) + setTraineeDone(updatedTraineeDone) + + // Log after computing new state + console.log('Checkbox clicked (after update):', { + currentRole, + updatedMentorDone, + updatedTraineeDone, + bothDoneAfterClick: updatedMentorDone && updatedTraineeDone, + }) + + // Send mutation + await updateFazit({ + variables: { + id: paperId, + content: localContent, + version: localVersion + 1, + mentorDone: updatedMentorDone, + traineeDone: updatedTraineeDone, + cursorPosition: { position: 0, owner: currentUserId }, + }, + optimisticResponse: { + __typename: 'Mutation', + updateFazit: { + __typename: 'FazitUpdateResponse', + success: true, + newFazit: { + __typename: 'Fazit', + id: paperId, + content: localContent, + version: localVersion + 1, + mentorDone: updatedMentorDone, + traineeDone: updatedTraineeDone, + cursorPositions: [], + }, + }, + }, + update: (cache, { data }) => { + if (!data?.updateFazit?.newFazit) return + cache.writeQuery({ + query: GetFazitDocument, + variables: { id: paperId }, + data: { getFazit: data.updateFazit.newFazit }, + }) + }, + }) + }, [ + currentRole, + currentRoleDone, + mentorDone, + traineeDone, + paperId, + localContent, + localVersion, + currentUserId, + updateFazit, + ]) + + return { bothDone, currentRoleDone, otherRoleDone, handleToggleDone } +} diff --git a/packages/frontend/src/hooks/use-fetch-pdf.ts b/packages/frontend/src/hooks/use-fetch-pdf.ts index d430b549..6874c9f7 100644 --- a/packages/frontend/src/hooks/use-fetch-pdf.ts +++ b/packages/frontend/src/hooks/use-fetch-pdf.ts @@ -1,10 +1,18 @@ import { useState } from 'react' -import { Report, usePrintDataLazyQuery } from '../graphql' +import { + Paper, + Report, + useCurrentUserLazyQuery, + usePrintDataLazyQuery, + usePrintPaperDataLazyQuery, + UserTypeEnum, +} from '../graphql' import strings from '../locales/localization' import { useToastContext } from './use-toast-context' type UseFetchPdfPayload = [(reports: Pick[]) => void, boolean] +type UseFetchPaperPdfPayload = [(paper: Pick) => Promise, boolean] export const useFetchPdf = (): UseFetchPdfPayload => { const [loading, setLoading] = useState(false) @@ -29,3 +37,36 @@ export const useFetchPdf = (): UseFetchPdfPayload => { loading, ] } + +export const useFetchPaperPdf = (): UseFetchPaperPdfPayload => { + const [fetchCurrentUser] = useCurrentUserLazyQuery() + const [loading, setLoading] = useState(false) + const { addToast } = useToastContext() + const [fetchPrintPaperData] = usePrintPaperDataLazyQuery({ + fetchPolicy: 'no-cache', + onCompleted: async ({ printPaper }) => { + const text = strings.formatString(strings.archivePage.export, printPaper.estimatedWaitingTime) as string + addToast({ icon: 'Export', title: strings.archivePage.exportTitle, text, type: 'success' }) + setLoading(false) + }, + }) + + return [ + async (paper) => { + setLoading(true) + const v = await fetchCurrentUser() + const userData = v.data + try { + const data = await fetchPrintPaperData({ + variables: { ids: [paper.id], userType: userData?.currentUser?.type ?? UserTypeEnum.Trainee }, + }) + + return data.data?.printPaper.pdfUrl + } catch (error) { + console.log(error) + return undefined + } + }, + loading, + ] +} diff --git a/packages/frontend/src/locales/de.ts b/packages/frontend/src/locales/de.ts index 10579dfa..28038ee0 100644 --- a/packages/frontend/src/locales/de.ts +++ b/packages/frontend/src/locales/de.ts @@ -13,10 +13,12 @@ const germanTranslation: Translation = { companyPick: 'Bitte wähle deine Firma:', continue: 'Weiter', save: 'Speichern', - edit: 'bearbeiten', - done: 'fertig', + edit: 'Bearbeiten', + done: 'Fertig', + comment: 'Kommentiere', markDelete: 'für Löschung markieren', unmarkDelete: 'Löschmarkierung aufheben', + deleteAt: 'Löschen nach', cancel: 'Abbrechen', deactivate: 'Deaktivieren', traineeShipYear: 'Jahr der Ausbildung', @@ -24,6 +26,7 @@ const germanTranslation: Translation = { back: 'zurück', on: 'an', off: 'aus', + start: 'Starten', login: { userNotRegisteredError: { title: 'Fehler bei der Anmeldung', @@ -48,6 +51,179 @@ const germanTranslation: Translation = { reportToArciveAddedSuccess: 'Dein Bericht über {0}{1} wurde von {name} genehmigt und befindet sich jetzt in deinem Archiv.', }, + paper: { + empty: { + headline: 'Briefing/Kick-Off Gespräch', + description: + 'Dein Azubi kommt auf eine neue Station und es steht das Kick-Off Gespräch an? Hier kannst du das Briefing für die Station ausfüllen und vorbereiten. Damit kannst du einene Rahmen über den Umfang und die Themen der Ausbildungssation deines Azubis festlegen.', + createBriefing: 'Briefing erstellen', + }, + emptyTrainee: { + headline: 'Hier gibt es noch nichts', + description: + 'Nach deinem Ersten Kick-Off/Briefing Gespräch für eine Station, wirst du dieses hier finden und herunterladen können und dein Stationsfeedback zu dieser geben können.', + }, + createBriefing: { + title: 'Briefing', + firstnameMentor: 'Vorname Ausbildungsbeauftragten', + lastnameMentor: 'Nachname Ausbildungsbeauftragten', + emailMentor: 'Email Ausbildungsbeauftragten', + trainee: 'Auszubildender', + department: 'Abteilung', + customer: 'Kunde', + projectPeriod: 'Stationszeitraum', + schoolPeriod: 'Schulzeitraum', + }, + briefingQuestions: { + objectOfTheWork: { + question: 'Gegenstand der Arbeit', + hint: 'Nenne hier bitte die allgemeine Tätigkeit/Aufgabe, die Inhalt der Projektstation ist.', + }, + procedure: { + question: 'Vorgehen', + hint: 'Nenne hier bitte unter welchen Rahmenbedingungen die Projektstation für den Azubi aufgebaut sein soll.', + }, + learningContent: { + question: 'Lerninhalte Station', + hint: 'Nenne hier welche allgemeinen Inhalte dem Azubi während dem Projekt Zeitraum vermittelt werden sollen.', + }, + frameworkPlan: { + question: 'Rahmenplan Lerninhalte', + hint: 'Ergänze hier (falls gewollt) zusätzliche Punkte aus dem Rahmenplan, welche du als besonders wichtig erachtest, dass diese im Briefing erwähnt werden.', + }, + tasksAndDutiesTrainee: { + question: 'Aufgaben und Pflichten des Azubis', + hint: 'Nenne hier (falls gewollt), welche Aufgaben und Pflichten dein Azubi zu erfüllen hat. ', + }, + tasksAndDutiesMentor: { + question: 'Aufgaben und Pflichten des Ausbildungsbeauftragten', + hint: 'Nenne hier (falls gewollt), welche Aufgaben und Pflichten der Ausbildungsbeauftragte zu erfüllen hat.', + }, + primeBlueAntMyTe: { + question: 'Prime / BlueAnt', + hint: 'Fasse hier kurz zusammen auf welchen Posten der Azubi seine Stunden/Aufwände buchen kann/soll.', + }, + feedback: { + question: 'Feedback', + hint: 'Hier ist im Briefing einmal kurz zusammenefasst, was unter Feedback zu verstehen ist. Du kannst den Vorlagen Text bei Bedarf natürlich noch ergänzen.', + }, + otherRemarks: { + question: 'Sonstige Anmerkungen', + hint: 'Falls du noch zusätzliche Punkte hast, welche ins Breifing aufgenommen werden sollen, kannst du diese hier festhalten.', + }, + }, + feedback: { + headlineEvaluationByTrainee: 'Bewertung durch den Auszubildenden', + headlineEvaluationByMentor: 'Bewertung durch den Ausbildungsbeauftragten', + }, + feedbackQuestions: { + descriptionOfActivities: { + question: 'Beschreibung der Tätigkeiten', + hint: 'Nenne hier bitte die Tätigkeiten oder Aufgaben, die du in der Station gemacht hast.', + }, + feedbackOnProjectTeam: { + question: 'Feedback zu deinem Projekt Team ', + hint: 'Bitte beschreibe hier wie du dich ins Team aufgenommen gefühlt hast und wie der Einstieg und die Zusammenarbeit lief.', + }, + feedbackOnTasksAndProject: { + question: 'Feedback zu deinen Aufgaben und Projekt', + hint: 'Was lief gut? Was war herausfordernd? Welche Aufgaben hast du mit besonderem Interesse und Erfolg ausgeübt? Was hat dich weitergebracht? Was war weniger erfolgreich? Was macht zufrieden? Was erzeugt Frust? Hierbei beschreibe möglichst an konkreten Beispielen vornehmlich dich und nicht dein Umfeld.', + }, + periodOfTime: { + question: 'Zeitumfang', + hint: 'Damit ist gemeint, ob die Dauer der Ausbildungsstation angemessen war, zu kurz oder zu lang.', + }, + learningContent: { + question: 'Lerninhalte', + hint: 'Wurden die zu Beginn deiner Station vereinbarten Lerninhalte behandelt?Diese sind hier nochmal automatisch aufgeführt. Ergänze hier, ob du ausreichend Gelegenheit hattest, die Inhalte zu lernen.', + }, + }, + mentorFeedbackQuestions: { + integrationIntoTeam: { + question: 'Integration ins Team', + hint: 'Bitte beschreibe das Sozialverhalten des Azubis gegenüber den Kollegen und ggf. externen Mitarbeitern.', + }, + communicationWithCustomers: { + question: 'Kommunikation mit Kunden oder Dienstleistern', + hint: 'Bitte beschreibe, wie sich der Azubi gegenüber Kunden oder Dienstleistern verhalten hat.', + }, + willingnessToWork: { + question: 'Arbeitsbereitschaft/Arbeitsweise', + hint: 'Bitte beschreibe die Arbeitsbereitschaft und Arbeitsweise des Azubis im Projekt- und Teamkontext.', + }, + abilities: { + question: 'Arbeitsbefähigung/Können', + hint: 'Welche Kompetenzen (Hard- und Softskills) hast du besonders wahrgenommen? \n Welche Aufgaben werden mit Interesse und Erfolg ausgeübt? \n Bitte beschreibe die Fähigkeiten und Kompetenzen konkret anhand von Beobachtungen.', + }, + goalAchieved: { + question: 'Lerninhalte', + hint: 'Hat der Azubi die vorher vereinbarten Lerninhalte und Kompetenzen erwerben können? Diese sind hier nochmal automatisiert aufgeführt.', + }, + }, + modal: { + title: 'Bist du sicher, dass du das Briefing beenden möchtest?', + description: + '' + + 'Wenn du auf “Briefing erstellen” drückst, kannst du das Briefing nicht mehr bearbeiten. Das Briefing wird daraufhin als PDF an deinen Azubi und den Ausbildungsbeauftragten per E-Mail gesendet.\n' + + '\n' + + 'Du kannst das Briefing stattdessen speichern, damit du es später nochmal bearbeiten kannst.', + createBriefing: 'Briefing erstellen', + backToPaperTitle: 'Briefing wird exportiert', + backToPaperDescription: + 'Das Lara Paper Briefing wird exportiert und anschließend als PDF an alle Teilnehmer verschickt. Es kann sein, dass du später Lara neuladen musst, um das neu erstellte Paper sehen zu. \n' + + 'Hab jetzt etwas Geduld während das Briefing exportiert wird.', + backToPaperButton: 'Züruck zur Paper Übersicht', + deletePaperTitle: 'Paper löschen für {kunde}', + deletePaperDescription: + 'Bist du sicher, dass du das Paper für den Kunden {kunde} löschen willst? Es kann nicht mehr rückgängig gemacht werden.', + deletePaperButtonAgree: 'bestätigen', + deletePaperButtonDisagree: 'abbrechen', + }, + dashboard: { + title: 'Station', + description: 'Für die Station von ihrem Azubi steht das Stationsfeedbackgespräch an. Du kannst es hier starten.', + traineeDiscription: { + a: 'Für deine Station ', + b: ' liegt ein Briefing vor, mit allen Eckdaten zu deiner Station. Falls dein Stationsfeedbackgespräch ansteht, kannst du dies hier starten.', + }, + briefing: 'Briefing', + feedback: 'Stationsfeedback', + conclusion: 'Fazit', + pdfFeedback: 'PDF Stationsfeedback', + trainee: 'Auszubildender', + trainer: 'Ausbilder', + editPaper: 'Paper bearbeiten', + }, + createPaper: { + title: 'Briefing erstellt', + text: 'Das Briefing wurde erstellt', + }, + deletePaper: { + title: 'Paper gelöscht', + text: 'Das Lara Paper wurde gelöscht', + }, + briefing: { + toastTitle: 'Lara Paper Briefing wird erstellt', + toastDescription: 'Das Briefing wird jetzt erstellt und wird den Teilnehmern per Mail als PDF verschickt', + }, + fazit: { + headline: 'Gemeinsames Fazit', + subline: + 'Welche Optimierungsbereiche haben Sie identifiziert und was wird zur Optimierung unternommen/vereinbart?', + secondarySubline: + 'Wie sieht der Plan dafür aus? Was muss dafür getan werden? Was wäre eine gute Unterstützung? Bitte beschreiben Sie dies konkret.', + placeholder: 'Schreibe etwas', + info: 'Der Abschluss erfolgt im Mehrspielermodus. Das bedeutet, dass Sie und Ihr Auszubildender gleichzeitig Änderungen vornehmen können. Es wird jedoch empfohlen, dass einer von Ihnen das Formular ausfüllt, damit es nicht zu Überschreibungen kommt.', + completeFeedback: 'Vervollständige Feedback', + reloadPage: 'Seite neu laden', + }, + fazitDone: { + downloadPDF: 'Downloade PDF', + text: 'Sie haben die Feedback-Sitzung an der Station erfolgreich abgeschlossen. \n Sie können das PDF mit Ihrem Feedback hier oder später aus der E-Mail, die Sie erhalten werden, herunterladen.', + headline: 'Yeah, Ihr Feedback wurde erfolgreich übermittelt!', + info: 'Der Link zu diesem Feedback wird ungültig, sobald Sie das Fenster schließen!', + }, + }, archivePage: { header: 'Archiv', tableHead: { @@ -330,7 +506,9 @@ const germanTranslation: Translation = { trainees: 'Auszubildende', trainer: 'Ausbilder', admin: 'Admins', + mentor: 'Ausbildungsbeauftragte', dashhboard: 'Dashboard', + paper: 'Paper', archive: 'Archiv', settings: 'Einstellungen', wiki: 'Wiki', @@ -412,12 +590,24 @@ const germanTranslation: Translation = { 'Trage hier die Daten des neuen Admins ein, damit er/sie sich anmelden kann. Die Daten können später noch überarbeitet werden.', success: 'Admin {0} wurde erfolgreich angelegt und kann den Account jetzt nutzen.', }, + createMentor: { + title: 'Neuer Ausbildungsbeauftragte', + description: + 'Trage hier die Daten des neuen Ausbilders / der neuen Ausbilderin ein, damit er/sie sich anmelden kann. Die Daten können später noch überarbeitet werden.', + success: 'Der/Die Ausbilder:in {0} wurde erfolgreich angelegt und kann den Account jetzt nutzen.', + }, deleteTrainer: { title: '{0} wirklich löschen?', description: 'Wenn du den Benutzer löscht, wird der Account zunächst für 24 Stunden deaktiviert. Danach erhälst du eine E-mail mit der Möglichkeit den Account entgültig zu löschen. ', success: 'Du erhältst in Kürze eine E-mail mit der Option den Nutzer zu Löschen.', }, + deleteMentor: { + title: '{0} wirklich löschen?', + description: + 'Wenn du den Benutzer löscht, wird der Account zunächst für 24 Stunden deaktiviert. Danach erhälst du eine E-mail mit der Möglichkeit den Account entgültig zu löschen. ', + success: 'Du erhältst in Kürze eine E-mail mit der Option den Nutzer zu Löschen.', + }, admin: { marking: 'Markiert zur Löschung', }, diff --git a/packages/frontend/src/locales/en.ts b/packages/frontend/src/locales/en.ts index 3e323513..289b49af 100644 --- a/packages/frontend/src/locales/en.ts +++ b/packages/frontend/src/locales/en.ts @@ -16,14 +16,17 @@ const englishTranslation: Translation = { cancel: 'Cancel', edit: 'edit', done: 'done', + comment: 'Comment', markDelete: 'mark for deletion', unmarkDelete: 'remove deletion mark', + deleteAt: 'delete at', deactivate: 'deactivate', traineeShipYear: 'Year of Traineeship', claimed: 'Claimed', back: 'back', on: 'on', off: 'off', + start: 'Start', login: { userNotRegisteredError: { title: 'Login failed', @@ -45,6 +48,175 @@ const englishTranslation: Translation = { reportToArciveAddedSuccessTitle: 'New report in your archive', reportToArciveAddedSuccess: 'Your report about {0}{1} was approved by {name} and is now stored in your archive.', }, + paper: { + empty: { + headline: 'Briefing/Kick-Off Meeting', + description: + "Your apprentice is coming to a new station, and it iss time for the kick-off meeting? Here you can fill out and prepare the briefing for the station. This way, you can set a framework for the scope and topics of your apprentice's training station.", + createBriefing: 'Create briefing', + }, + emptyTrainee: { + headline: "There's nothing here yet", + description: + 'After your first kick-off/briefing for a station, you will be able to find it here, download it and give your station feedback on it.', + }, + createBriefing: { + title: 'Briefing', + firstnameMentor: "Mentor's First Name", + lastnameMentor: "Mentor's Last Name", + emailMentor: "Mentor's Email", + trainee: 'Trainee', + department: 'Department', + customer: 'Customer', + projectPeriod: 'Station Period', + schoolPeriod: 'School Period', + }, + briefingQuestions: { + objectOfTheWork: { + question: 'Object of the Work', + hint: 'Please specify the general activity/task that is the subject of the project station.', + }, + procedure: { + question: 'Procedure', + hint: 'Please specify the framework conditions under which the project station should be set up for the apprentice.', + }, + learningContent: { + question: 'Learning Content Station', + hint: 'Please specify the general content that the apprentice should be taught during the project period.', + }, + frameworkPlan: { + question: 'Framework Plan Learning Content', + hint: 'Add additional points from the framework plan here (if desired) that you consider particularly important to mention in the briefing.', + }, + tasksAndDutiesTrainee: { + question: 'Tasks and Duties of the Trainee', + hint: 'Please specify (if desired) the tasks and duties that your apprentice has to fulfill.', + }, + tasksAndDutiesMentor: { + question: 'Tasks and Duties of the Mentor', + hint: 'Please specify (if desired) the tasks and duties that the mentor has to fulfill.', + }, + primeBlueAntMyTe: { + question: 'Prime / BlueAnt', + hint: 'Briefly summarize the positions where the apprentice can/should book hours/efforts.', + }, + feedback: { + question: 'Feedback', + hint: 'Here is a brief summary of what is understood by feedback in the briefing. You can supplement the template text as needed.', + }, + otherRemarks: { + question: 'Other Remarks', + hint: 'If you have any additional points to be included in the briefing, you can note them here.', + }, + }, + feedback: { + headlineEvaluationByTrainee: 'Evaluation by the trainee', + headlineEvaluationByMentor: 'Assessment by the training officer', + }, + feedbackQuestions: { + descriptionOfActivities: { + question: 'Description of activities', + hint: 'Please name the activities or tasks that you did in the ward.', + }, + feedbackOnProjectTeam: { + question: 'Feedback on your project team', + hint: 'Please describe here how you felt as part of the team and how the start and the cooperation went.', + }, + feedbackOnTasksAndProject: { + question: 'Feedback on your tasks and project', + hint: 'What went well? What was challenging? Which tasks have you carried out with particular interest and success? What got you going? What was less successful? What makes you happy? What creates frustration? If possible, use concrete examples to describe yourself and not your environment.', + }, + periodOfTime: { + question: 'Period of time', + hint: 'This means whether the duration of the training station was appropriate, too short or too long.', + }, + learningContent: { + question: 'Learning content', + hint: 'Was the learning content agreed at the beginning of your station covered? These are automatically listed here again. Add here if you had enough opportunity to learn the content.', + }, + }, + modal: { + title: 'Are you sure you want to finish the briefing?', + description: + 'Once you click "Create briefing," you won\'t be able to edit the briefing anymore. The briefing will be sent as a PDF to your apprentice and the training officer via email.\n\nYou can choose to save the briefing instead, so you can edit it later.', + createBriefing: 'Create briefing', + backToPaperTitle: 'Briefing is being exported', + backToPaperDescription: + 'The Lara Paper briefing is being exported and will be sent as an email to all participants. You may need to reload Lara later to see the newly created paper.\n' + + 'Please be patient while the briefing is being exported.', + backToPaperButton: 'Back to Paper Overview', + deletePaperTitle: 'Delete Paper for {0}', + deletePaperDescription: + 'Are you sure you want to delete the paper for customer {1}? This action cannot be undone.', + deletePaperButtonAgree: 'Confirm', + deletePaperButtonDisagree: 'Cancel', + }, + dashboard: { + title: 'Station', + description: "It's time for the feedback meeting for your apprentice's station. You can start it here.", + traineeDiscription: { + a: 'There is a briefing for your station ', + b: ', with all the key data about your station. If your station feedback session is pending, you can start it here.', + }, + briefing: 'Briefing', + feedback: 'Station Feedback', + conclusion: 'Conclusion', + pdfFeedback: 'PDF Station Feedback', + trainee: 'Trainee', + trainer: 'Trainer', + editPaper: 'Edit Paper', + }, + createPaper: { + title: 'Briefing Created', + text: 'The briefing has been created', + }, + deletePaper: { + title: 'Paper Deleted', + text: 'The Lara Paper has been deleted', + }, + briefing: { + toastTitle: 'Creating Lara Paper briefing', + toastDescription: 'The briefing is being created now and will be sent to the participants as a PDF via email', + }, + mentorFeedbackQuestions: { + integrationIntoTeam: { + question: 'Assesment by the Training Officer', + hint: "Please describe the trainee's social behavior towards colleagues and, if applicable, external employees.", + }, + communicationWithCustomers: { + question: 'Communication with customers and service providers', + hint: 'Please describe how the trainee behaved towards customers or service providers.', + }, + willingnessToWork: { + question: 'Willigness to work / Way of working', + hint: "Please describe the trainee's willingness to work and working methods in the project and team context.", + }, + abilities: { + question: 'Work ability/Skills', + hint: 'What competencies (hard and soft skills) did you particularly notice? Which tasks are carried out with interest and success? Please describe the skills and competences specifically based on observations', + }, + goalAchieved: { + question: 'Learning content', + hint: 'Was the trainee able to acquire the previously agreed learning content and skills? These are listed here again automatically.', + }, + }, + fazit: { + headline: 'Common conclusion', + subline: 'Which optimization fields have you identified and what is being done/agreed to optimize?', + secondarySubline: + 'What is the plan for this? What needs to be done for it? What would be good support? Please describe specifically.', + placeholder: 'Type something', + info: 'The conclusion is carried out in multiplayer mode. This means that you and your trainee can make changes at the same time. However, it is recommended that one of you fill it out so that no overwriting occurs.', + completeFeedback: 'Complete Feedback', + reloadPage: 'Reload page', + }, + fazitDone: { + headline: 'Yeah, your feedback was successfully submitted!', + info: 'The link to this feedback is invalid as soon as you close the window!', + downloadPDF: 'Download PDF', + text: 'You have successfully completed the feedback session on the station. \n You can download the PDF for your feedback here or later from the E-Mail you will recive.', + }, + }, archivePage: { header: 'Archive', tableHead: { @@ -324,6 +496,8 @@ const englishTranslation: Translation = { trainees: 'Trainees', trainer: 'Trainer', admin: 'Admins', + mentor: 'mentor', + paper: 'Paper', dashhboard: 'Dashboard', archive: 'Archive', settings: 'Settings', @@ -406,12 +580,24 @@ const englishTranslation: Translation = { 'Please enter the informations of the new Admin here so she/he can login. You can still change the data later.', success: 'The admin {0} has been created', }, + createMentor: { + title: 'New Mentor', + description: + 'Please enter the informations of the new Trainer here so she/he can login. You can still change the data later.', + success: 'The trainer {0} has been created', + }, deleteTrainer: { title: 'Delete {0}?', description: 'If you delete the user, the account will be deactivated for 24 hours. After that you will receive an email with the possibility to delete the account. ', success: 'Du erhältst in Kürze eine E-mail mit der Option den Nutzer zu Löschen.', }, + deleteMentor: { + title: 'Delete {0}?', + description: + 'If you delete the user, the account will be deactivated for 24 hours. After that you will receive an email with the possibility to delete the account. ', + success: 'Du erhältst in Kürze eine E-mail mit der Option den Nutzer zu Löschen.', + }, userDelete: { title: 'User deactivated', description: 'Shortly you will receive an email with the option to delete the user. ', diff --git a/packages/frontend/src/locales/translation.ts b/packages/frontend/src/locales/translation.ts index 20e9f211..06f3e8c3 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -14,14 +14,17 @@ export default interface Translation { cancel: string edit: string done: string + comment: string markDelete: string unmarkDelete: string + deleteAt: string deactivate: string traineeShipYear: string claimed: string back: string on: string off: string + start: string login: { userNotRegisteredError: { title: string @@ -43,6 +46,168 @@ export default interface Translation { reportToArciveAddedSuccessTitle: string reportToArciveAddedSuccess: string } + paper: { + fazit: { + headline: string + subline: string + secondarySubline: string + placeholder: string + info: string + completeFeedback: string + reloadPage: string + } + fazitDone: { + headline: string + info: string + downloadPDF: string + text: string + } + empty: { + headline: string + description: string + createBriefing: string + } + emptyTrainee: { + headline: string + description: string + } + createBriefing: { + title: string + firstnameMentor: string + lastnameMentor: string + emailMentor: string + trainee: string + department: string + customer: string + projectPeriod: string + schoolPeriod: string + } + briefingQuestions: { + objectOfTheWork: { + question: string + hint: string + } + procedure: { + question: string + hint: string + } + learningContent: { + question: string + hint: string + } + frameworkPlan: { + question: string + hint: string + } + tasksAndDutiesTrainee: { + question: string + hint: string + } + tasksAndDutiesMentor: { + question: string + hint: string + } + primeBlueAntMyTe: { + question: string + hint: string + } + feedback: { + question: string + hint: string + } + otherRemarks: { + question: string + hint: string + } + } + feedback: { + headlineEvaluationByTrainee: string + headlineEvaluationByMentor: string + } + feedbackQuestions: { + descriptionOfActivities: { + question: string + hint: string + } + feedbackOnProjectTeam: { + question: string + hint: string + } + feedbackOnTasksAndProject: { + question: string + hint: string + } + periodOfTime: { + question: string + hint: string + } + learningContent: { + question: string + hint: string + } + } + mentorFeedbackQuestions: { + integrationIntoTeam: { + question: string + hint: string + } + communicationWithCustomers: { + question: string + hint: string + } + willingnessToWork: { + question: string + hint: string + } + abilities: { + question: string + hint: string + } + goalAchieved: { + question: string + hint: string + } + } + modal: { + title: string + description: string + createBriefing: string + backToPaperTitle: string + backToPaperDescription: string + backToPaperButton: string + deletePaperTitle: string + deletePaperDescription: string + deletePaperButtonAgree: string + deletePaperButtonDisagree: string + } + dashboard: { + title: string + description: string + traineeDiscription: { + b: string + a: string + } + briefing: string + feedback: string + conclusion: string + pdfFeedback: string + trainee: string + trainer: string + editPaper: string + } + createPaper: { + title: string + text: string + } + deletePaper: { + title: string + text: string + } + briefing: { + toastTitle: string + toastDescription: string + } + } archivePage: { header: string tableHead: { @@ -314,6 +479,8 @@ export default interface Translation { trainees: string trainer: string admin: string + mentor: string + paper: string dashhboard: string archive: string settings: string @@ -384,11 +551,21 @@ export default interface Translation { description: string success: string } + createMentor: { + title: string + description: string + success: string + } deleteTrainer: { title: string description: string success: string } + deleteMentor: { + title: string + description: string + success: string + } admin: { marking: string } diff --git a/packages/frontend/src/pages/admin-edit-user-page.tsx b/packages/frontend/src/pages/admin-edit-user-page.tsx index 11a43a9d..8d2737b9 100644 --- a/packages/frontend/src/pages/admin-edit-user-page.tsx +++ b/packages/frontend/src/pages/admin-edit-user-page.tsx @@ -15,6 +15,7 @@ import Modal from '../components/modal' import { useToastContext } from '../hooks/use-toast-context' import { EditAdmin } from '../components/edit-admin-content' import { GraphQLError } from 'graphql' +import { EditMentor } from '../components/edit-mentor-content' type AdminEditUserPageParams = { id: string @@ -110,6 +111,23 @@ export const AdminEditUserPage: React.FunctionComponent = () => { /> )} + {/* Edit Mentor page */} + {!loading && data?.getUser?.__typename === 'Mentor' && ( + + } + content={} + actions={renderDeleteAction(data.getUser.deleteAt)} + /> + )} + {!loading && (

    diff --git a/packages/frontend/src/pages/admin-mentor-page.tsx b/packages/frontend/src/pages/admin-mentor-page.tsx new file mode 100644 index 00000000..60c91cfb --- /dev/null +++ b/packages/frontend/src/pages/admin-mentor-page.tsx @@ -0,0 +1,85 @@ +import { GraphQLError } from 'graphql' +import React from 'react' + +import { AdminCreateUserLayout, AdminOverviewLayout, H1, Paragraph } from '@lara/components' + +import { EditUserRow } from '../components/edit-user-row' +import { Fab } from '../components/fab' +import Loader from '../components/loader' +import Modal from '../components/modal' + +import { useAdminMentorPageQuery, useCreateMentorMutation } from '../graphql' +import { useToastContext } from '../hooks/use-toast-context' +import strings from '../locales/localization' +import { Template } from '../templates/template' +import { EditMentorFormData, MentorForm } from '../components/mentor-form' + +export const AdminMentorPage: React.FC = () => { + const { loading, data } = useAdminMentorPageQuery() + const [mutate] = useCreateMentorMutation() + + const { addToast } = useToastContext() + + const [showModal, setShowModal] = React.useState(false) + + const createMentor = async (data: EditMentorFormData) => { + await mutate({ + variables: { input: data }, + updateQueries: { + AdminMentorPage: (prevData, { mutationResult }) => { + return { + ...prevData, + mentors: [...prevData.mentors, mutationResult.data?.createMentor], + } + }, + }, + }) + .then(() => { + addToast({ + icon: 'PersonNew', + title: strings.createMentor.title, + text: strings.formatString(strings.createMentor.success, `${data?.firstName} ${data?.lastName}`).toString(), + type: 'success', + }) + + setShowModal(false) + }) + .catch((exception: GraphQLError) => { + addToast({ + title: strings.errors.error, + text: exception.message, + type: 'error', + }) + }) + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/feedback-done.tsx b/packages/frontend/src/pages/feedback-done.tsx new file mode 100644 index 00000000..a58803f1 --- /dev/null +++ b/packages/frontend/src/pages/feedback-done.tsx @@ -0,0 +1,83 @@ +import React, { useState } from 'react' +import { Template } from '../templates/template' +import EmptyStateHappy from '../assets/illustrations/empty-state-happy' +import { Spacer, Spacings, StyledIcon } from '@lara/components' +import NavigationButtonLink from '../components/navigation-button-link' +import strings from '../locales/localization' +import { styled } from 'styled-components' +import { PaperFazitHeadline, PaperFazitSubline, PaperSecondarySubline } from './paper-fazit-page' +import { PrimaryButton } from '../components/button' +import { Flex } from '@rebass/grid' +import { useFetchPaperPdf } from '../hooks/use-fetch-pdf' +import { useParams } from 'react-router' +import { useDidSendEmailMutation, useFeedbackDoneQuery } from '../graphql' + +const Container = styled.div` + padding: ${Spacings.xxxl}; + display: flex; + flex-direction: column; +` +export const PaperFeedbackDone: React.FC = () => { + const { paperId } = useParams<{ paperId: string }>() + const [fetchPdf] = useFetchPaperPdf() + const { data } = useFeedbackDoneQuery({ variables: { id: paperId ?? '' } }) + const [didSendEmail] = useDidSendEmailMutation() + const [fetchedPDF, setFetchedPDF] = useState(data?.getPaper?.didSendEmail ?? false) + const [url, setUrl] = useState(undefined) + + const fetchPdfFn = async () => { + if (!data?.getPaper?.didSendEmail && !fetchedPDF) { + setFetchedPDF(true) + didSendEmail({ variables: { id: paperId ?? '', didSendEmail: true } }) + const url = await fetchPdf({ id: paperId ?? '' }) + setUrl(url) + } + } + + fetchPdfFn() + + const downloadPDF = async () => { + if (url !== undefined && fetchedPDF) { + const link = document.createElement('a') + link.href = url ?? '' + link.download = 'Briefing.pdf' + link.target = '_blank' + + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + } + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/mentor-paper-feedback-page.tsx b/packages/frontend/src/pages/mentor-paper-feedback-page.tsx new file mode 100644 index 00000000..0d73f2b1 --- /dev/null +++ b/packages/frontend/src/pages/mentor-paper-feedback-page.tsx @@ -0,0 +1,183 @@ +import { Box, Flex, PaperH2, PaperLayout, Spacer } from '@lara/components' +import NavigationButtonLink from '../components/navigation-button-link' +import { Template } from '../templates/template' +import strings from '../locales/localization' +import { Question } from '../helper/paper-helper' +import { useEffect, useState } from 'react' +import { useNavigate, useParams } from 'react-router' +import { PrimaryButton, SecondaryButton } from '../components/button' +import PaperAccordion from '../components/paper-accordion' +import React from 'react' +import { Mentor, PaperFormData, PaperStatus, useMentorPaperPageDataQuery, useUpdatePaperMutation } from '../graphql' +import { omitDeep } from '@apollo/client/utilities' + +const mentorFeedbackQuestions = (): Question[] => { + const q = strings.paper.mentorFeedbackQuestions + return [q.integrationIntoTeam, q.communicationWithCustomers, q.willingnessToWork, q.abilities, q.goalAchieved] +} + +export const MentorPaperFeedbackPage: React.FunctionComponent = () => { + const navigate = useNavigate() + const { paperId } = useParams() + const [paperFeedbackInput, setPaperFeedbackInput] = React.useState() + const [paperFeedback, setPaperFeedback] = React.useState([]) + const [filledFromSave, setFilledFromSave] = React.useState(false) + + const { data } = useMentorPaperPageDataQuery() + const [updatePaperMutation] = useUpdatePaperMutation() + + const QAs = mentorFeedbackQuestions() + const [filteredQAs] = useState(QAs) + + const currentUser = data?.currentUser as Mentor + const paper = (currentUser?.papers || []).find((p) => p?.id == paperId) + + useEffect(() => { + if (paperFeedbackInput) { + setPaperFeedback((oldArray: PaperFormData[]) => [...oldArray, paperFeedbackInput]) + } + }, [paperFeedbackInput]) + + useEffect(() => { + if (!filledFromSave && paper && paper.feedbackMentor.length > 0 && paperFeedback.length == 0) { + setPaperFeedback(paper.feedbackMentor) + setFilledFromSave(true) + } + }, [filledFromSave, paper, paperFeedback]) + + if (!currentUser) return null + + const savePaper = async (feedback: PaperFormData[]) => { + await updatePaperMutation({ + variables: { + input: { + id: paperId ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: paper?.trainerId ?? '', + client: paper?.client ?? '', + mentorId: paper?.mentorId ?? '', + periodEnd: paper?.periodEnd, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + subject: paper?.subject ?? '', + status: PaperStatus.TraineeDone, + briefing: paper ? omitDeep(paper.briefing, '__typename') : [], + didSendEmail: false, + feedbackTrainee: paper?.feedbackTrainee + ? omitDeep(paper.feedbackTrainee, '__typename').map((trainee) => ({ + ...trainee, + comments: trainee.comments ? trainee.comments : [], + })) + : [], + feedbackMentor: omitDeep(feedback, '__typename'), + }, + }, + updateQueries: { + MentorPaperPageData: ({ mutationResult }) => { + return { currentUser: { papers: mutationResult?.data?.updatePaper } } + }, + }, + }) + } + + const submitPaper = async (feedback: PaperFormData[]) => { + await updatePaperMutation({ + variables: { + input: { + id: paperId ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: paper?.trainerId ?? '', + client: paper?.client ?? '', + mentorId: paper?.mentorId ?? '', + periodEnd: paper?.periodEnd, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + subject: paper?.subject ?? '', + status: PaperStatus.MentorDone, + didSendEmail: false, + briefing: paper ? omitDeep(paper.briefing, '__typename') : [], + feedbackTrainee: paper?.feedbackTrainee + ? omitDeep(paper.feedbackTrainee, '__typename').map((trainee) => ({ + ...trainee, + comments: trainee.comments ? trainee.comments : [], + })) + : [], + feedbackMentor: omitDeep(feedback, '__typename'), + }, + }, + updateQueries: { + MentorPaperPageData: ({ mutationResult }) => { + return { currentUser: { papers: mutationResult?.data?.updatePaper } } + }, + }, + }) + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/mentor-paper-page.tsx b/packages/frontend/src/pages/mentor-paper-page.tsx new file mode 100644 index 00000000..99356285 --- /dev/null +++ b/packages/frontend/src/pages/mentor-paper-page.tsx @@ -0,0 +1,209 @@ +import { Container, H1, Paragraph, Spacer, StyledIcon, Text } from '@lara/components' +import React from 'react' +import { Template } from '../templates/template' +import { Mentor, Paper, PaperStatus, useMentorPaperPageDataQuery } from '../graphql' +import { Box, Flex } from '@lara/components' +import strings from '../locales/localization' +import ProgressBar from '../components/progress-bar' +import Loader from '../components/loader' +import { useNavigate } from 'react-router' +import { PrimaryButton } from '../components/button' +import { mapStatusToProgess } from '../helper/paper-helper' + +export const MentorPaperPage: React.FC = () => { + const { loading, data } = useMentorPaperPageDataQuery() + const navigate = useNavigate() + + const navigateToPaperFeedbackPage = (paperId: string) => { + navigate('/paper/feedback/' + paperId) + } + + const navigateToPaperDiscussionPage = (paperId: string) => { + navigate('/paper/feedback/discussion/' + paperId) + } + + const navigateToFazitPage = (paperId: string) => { + navigate('/paper/fazit/' + paperId) + } + + const navigateToFazitDonePage = (paperId: string) => { + navigate('/paper/fazit/done/' + paperId) + } + + if (!data) { + return ( + + ) + } + + const currentUser = data?.currentUser as Mentor + + if (!currentUser) { + return ( + + ) + } + + const getContinueButtonText = (paperStatus: PaperStatus) => { + switch (paperStatus) { + case PaperStatus.NotStarted: + return strings.start + break + case PaperStatus.InProgress: + return strings.edit + break + case PaperStatus.TraineeDone: + return strings.start + break + case PaperStatus.MentorDone: + return strings.start + break + case PaperStatus.InReview: + return strings.edit + break + case PaperStatus.ReviewDone: + return strings.continue + break + case PaperStatus.Archived: + return 'You should not be able to see this, report as a bug' + break + } + } + + const hasCommented = (paper: Paper) => { + const foundUserIds: Array = [] + paper.feedbackMentor.forEach((feedback) => { + feedback.comments?.forEach((comment) => { + if (!foundUserIds.includes(comment.userId)) { + foundUserIds.push(comment.userId) + } + }) + }) + paper.feedbackTrainee.forEach((feedback) => { + feedback.comments?.forEach((comment) => { + if (!foundUserIds.includes(comment.userId)) { + foundUserIds.push(comment.userId) + } + }) + }) + if (foundUserIds.length >= 2) { + return true + } + return false + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/paper-briefing-page.tsx b/packages/frontend/src/pages/paper-briefing-page.tsx new file mode 100644 index 00000000..fca0973d --- /dev/null +++ b/packages/frontend/src/pages/paper-briefing-page.tsx @@ -0,0 +1,260 @@ +import React, { useEffect, useState } from 'react' + +import { H2, PaperLayout, Paragraph, Spacer } from '@lara/components' + +import strings from '../locales/localization' +import { Template } from '../templates/template' +import PaperAccordion from '../components/paper-accordion' +import { PrimaryButton, SecondaryButton } from '../components/button' +import { useNavigate, useParams } from 'react-router' +import { PaperFormData, PaperStatus, Trainer, useTrainerPaperPageDataQuery, useUpdatePaperMutation } from '../graphql' +import Modal from '../components/modal' +import { Box, Flex } from '@lara/components' +import PaperModal from '../assets/illustrations/paper-modal-illustraion' +import { useFetchPaperPdf } from '../hooks/use-fetch-pdf' +import { useToastContext } from '../hooks/use-toast-context' +import { omitDeep } from '@apollo/client/utilities' +import NavigationButtonLink from '../components/navigation-button-link' +import { Question } from '../helper/paper-helper' + +const briefingQuestions = (): Question[] => { + const questions = strings.paper.briefingQuestions + + return [ + questions.objectOfTheWork, + questions.procedure, + questions.learningContent, + questions.frameworkPlan, + questions.tasksAndDutiesTrainee, + questions.tasksAndDutiesMentor, + questions.primeBlueAntMyTe, + questions.feedback, + questions.otherRemarks, + ] +} + +export const PaperBriefingPage: React.FunctionComponent = () => { + const navigate = useNavigate() + const { paperId } = useParams() + const [paperBriefingInput, setPaperBriefingInput] = React.useState() + const [paperBriefing, setPaperBriefing] = React.useState([]) + const [fetchPdf, loading] = useFetchPaperPdf() + + const QAs = briefingQuestions() + const [filteredQAs] = useState(QAs) + const [showHandoverModal, setShowHandoverModal] = React.useState(false) + const [showBackToPaperModal, setShowBackToPaperModal] = React.useState(false) + const [filledFromSave, setFilledFromSave] = React.useState(false) + + const toggleHandoverModal = () => setShowHandoverModal(!showHandoverModal) + const toggleBackToPaperModal = () => setShowBackToPaperModal(!showBackToPaperModal) + const trainerPaperPageData = useTrainerPaperPageDataQuery() + const [updatePaperMutation] = useUpdatePaperMutation() + const { addToast } = useToastContext() + + const currentUser = trainerPaperPageData?.data?.currentUser as Trainer + + const paper = currentUser?.papers?.find((paper) => paper?.id == paperId) + useEffect(() => { + if (paperBriefingInput) { + setPaperBriefing((oldArray: PaperFormData[]) => [...oldArray, paperBriefingInput]) + } + }, [paperBriefingInput]) + + useEffect(() => { + if (!filledFromSave && paper && paper.briefing.length > 0 && paperBriefing.length == 0) { + setPaperBriefing(paper.briefing) + setFilledFromSave(true) + } + }, [filledFromSave, paper, paperBriefing]) + + if (!currentUser) { + return null + } + + const savePaper = async (paperBriefing: PaperFormData[]) => { + await updatePaperMutation({ + variables: { + input: { + briefing: omitDeep(paperBriefing, '__typename'), + feedbackTrainee: paper ? omitDeep(paper.feedbackTrainee, '__typename') : [], + feedbackMentor: paper ? omitDeep(paper.feedbackMentor, '__typename') : [], + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + periodEnd: paper?.periodEnd, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + didSendEmail: false, + status: PaperStatus.NotStarted, + subject: paper?.subject ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: currentUser.id, + }, + }, + updateQueries: { + TrainerPaperPageData: (prevData, { mutationResult }) => { + return { + currentUser: { + ...prevData, + papers: mutationResult.data?.updatePaper, + }, + } + }, + }, + }) + } + + const submitPaper = async (paperBriefing: PaperFormData[]) => { + await updatePaperMutation({ + variables: { + input: { + briefing: omitDeep(paperBriefing, '__typename'), + feedbackTrainee: paper?.feedbackTrainee ?? [], + feedbackMentor: paper?.feedbackMentor ?? [], + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + periodEnd: paper?.periodEnd, + didSendEmail: false, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + status: PaperStatus.InProgress, + subject: paper?.subject ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: currentUser.id, + }, + }, + updateQueries: { + TrainerPaperPageData: (prevData, { mutationResult }) => { + return { + currentUser: { + ...prevData, + papers: mutationResult.data?.updatePaper, + }, + } + }, + }, + }) + .then((result) => { + const updatedPaper = result?.data?.updatePaper + if (updatedPaper) { + fetchPdf(updatedPaper) + } + }) + .finally(() => { + addToast({ + icon: 'Export', + title: strings.paper.briefing.toastTitle, + text: strings.paper.briefing.toastDescription, + type: 'success', + }) + toggleBackToPaperModal() + }) + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/paper-create-briefing-page.tsx b/packages/frontend/src/pages/paper-create-briefing-page.tsx new file mode 100644 index 00000000..721b0129 --- /dev/null +++ b/packages/frontend/src/pages/paper-create-briefing-page.tsx @@ -0,0 +1,140 @@ +import React from 'react' + +import { H1, PaperCreateLayout, Spacer } from '@lara/components' +import strings from '../locales/localization' +import { Template } from '../templates/template' +import { GraphQLError } from 'graphql/index' +import { + PaperStatus, + Trainer, + useAdminMentorPageQuery, + useCreateMentorMutation, + useCreatePaperMutation, + useTrainerPaperPageDataQuery, + useUserEmailPageMutation, +} from '../graphql' +import { useToastContext } from '../hooks/use-toast-context' +import Loader from '../components/loader' +import { CreateBriefingFormData, PaperCreateForm } from '../components/paper-create-form' +import NavigationButtonLink from '../components/navigation-button-link' +import { useNavigate } from 'react-router' + +export const PaperCreateBriefingPage: React.FunctionComponent = () => { + const navigate = useNavigate() + const { loading } = useAdminMentorPageQuery() + const [createMentorMutation] = useCreateMentorMutation() + const [createPaperMutation] = useCreatePaperMutation() + const [getUserByEmail] = useUserEmailPageMutation() + const traineePaperPageData = useTrainerPaperPageDataQuery() + + const { addToast } = useToastContext() + let mentorId = '' + + if (!traineePaperPageData) { + return null + } + + const currentUser = traineePaperPageData?.data?.currentUser as Trainer + if (!currentUser) { + return null + } + + const getUserEmail = async (email: string) => { + await getUserByEmail({ + variables: { + email: email, + }, + }).then((response) => { + mentorId = response?.data?.getUserByEmail?.id ?? '' + }) + } + + const createPaper = async (data: CreateBriefingFormData) => { + await createPaperMutation({ + variables: { + input: { + briefing: [], + feedbackTrainee: [], + feedbackMentor: [], + client: data.customer, + mentorId: mentorId, + traineeId: data.trainee, + trainerId: currentUser.id, + periodStart: data.startDateProject, + periodEnd: data.endDateProject, + schoolPeriodStart: data.startDateSchool, + schoolPeriodEnd: data.endDateSchool, + status: PaperStatus.NotStarted, + subject: data.department, + }, + }, + }).then((response) => { + const paperId = response?.data?.createPaper.id + navigate('/paper/briefing/' + paperId) + }) + } + + const createMentor = async (data: CreateBriefingFormData) => { + await getUserEmail(data.emailMentor) + if (!mentorId) { + await createMentorMutation({ + variables: { + input: { + email: data.emailMentor, + endDate: data.endDateProject, + firstName: data.firstNameMentor, + lastName: data.lastNameMentor, + startDate: data.startDateProject, + }, + }, + updateQueries: { + AdminMentorPage: (prevData, { mutationResult }) => { + return { + ...prevData, + Mentors: [...prevData.mentors, mutationResult.data?.createMentor], + } + }, + }, + }) + .then((result) => { + mentorId = result?.data?.createMentor?.id ? result?.data?.createMentor?.id : '' + addToast({ + icon: 'PersonNew', + title: strings.createMentor.title, + text: strings + .formatString(strings.createMentor.success, `${data?.firstNameMentor} ${data?.lastNameMentor}`) + .toString(), + type: 'success', + }) + createPaper(data) + }) + .catch((exception: GraphQLError) => { + addToast({ + title: strings.errors.error, + text: exception.message, + type: 'error', + }) + }) + } else { + await createPaper(data) + } + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/paper-fazit-page.tsx b/packages/frontend/src/pages/paper-fazit-page.tsx new file mode 100644 index 00000000..fabdfd00 --- /dev/null +++ b/packages/frontend/src/pages/paper-fazit-page.tsx @@ -0,0 +1,259 @@ +import { useNavigate, useParams } from 'react-router' +import { Template } from '../templates/template' +import { Container, Flex, Spacer, Spacings, StyledTextFazitArea } from '@lara/components' +import NavigationButtonLink from '../components/navigation-button-link' +import strings from '../locales/localization' +import { useCallback, useEffect, useRef, useState } from 'react' +import { useQuery } from '@apollo/client' +import { + CursorInput, + GetFazitDocument, + GetFazitQuery, + PaperStatus, + useCurrentUserQuery, + useFazitUpdateMutation, + useUpdateFazitCursorPosMutation, + useUpdatePaperMutation, +} from '../graphql' +import { styled } from 'styled-components' +import { PrimaryButton, SecondaryButton } from '../components/button' +import { omitDeep } from '@apollo/client/utilities' +import { CheckBox } from '../components/checkbox' +import { useBothDone } from '../hooks/use-both-done' + +export const PaperFazitHeadline = styled.p` + margin: 0; + white-space: pre-wrap; + word-break: break-word; + font-weight: 600; + text-align: center; + padding: ${Spacings.m}; + font-size: 20px; + color: ${(props) => props.theme.mediumFont}; + line-height: 1.2; +` + +export const PaperFazitSubline = styled.p` + margin: 0; + white-space: pre-wrap; + font-weight: 500; + word-break: break-word; + text-align: center; + padding-top: ${Spacings.m}; + padding-left: ${Spacings.m}; + font-size: 16px; + color: ${(props) => props.theme.mediumFont}; + line-height: 100%; +` + +export const PaperSecondarySubline = styled.p` + margin: ${Spacings.m}; + align-content: center; + white-space: pre-wrap; + word-break: break-word; + font-weight: 400; + font-size: 12px; + color: #757575; + line-height: 100%; +` + +export const PaperFazitPage: React.FC = () => { + const { paperId } = useParams<{ paperId: string }>() + const navigate = useNavigate() + + const [localContent, setLocalContent] = useState('') + const [localVersion, setLocalVersion] = useState(0) + + const [updateFazit] = useFazitUpdateMutation() + const [updateCursorPosition] = useUpdateFazitCursorPosMutation() + const [updatePaperMutation] = useUpdatePaperMutation() + + const { data: currentUser } = useCurrentUserQuery() + const currentRole = currentUser?.currentUser?.__typename as 'Mentor' | 'Trainee' + + const textArea = useRef(null) + + const { data } = useQuery(GetFazitDocument, { + variables: { id: paperId }, + pollInterval: 500, + fetchPolicy: 'cache-and-network', + skip: !paperId, + }) + + const fazit = data?.getFazit + + const { bothDone, currentRoleDone, handleToggleDone } = useBothDone({ + fazit: { + mentorDone: fazit?.mentorDone ?? false, + traineeDone: fazit?.traineeDone ?? false, + }, + currentRole, + paperId: paperId!, + localContent, + localVersion, + currentUserId: currentUser?.currentUser?.id ?? '', + updateFazit, + }) + + useEffect(() => { + const fazit: GetFazitQuery | undefined = data as GetFazitQuery + if (fazit?.getFazit && fazit.getFazit.version > localVersion) { + const remote = fazit.getFazit + + if (remote.content !== localContent) { + const cp = textArea.current?.selectionStart || 0 + + setLocalContent(remote.content) + setLocalVersion(remote.version) + + requestAnimationFrame(() => { + if (textArea.current) { + textArea.current.selectionStart = cp + textArea.current.selectionEnd = cp + } + }) + } else { + setLocalVersion(remote.version) + } + } + }, [data, localVersion, localContent]) + + const handleChange = useCallback( + (e: React.ChangeEvent) => { + const newContent = e.target.value + const cursorPos = e.target.selectionStart + + setLocalContent(newContent) + setLocalVersion(localVersion + 1) + + const newCursorPos: CursorInput = { + position: cursorPos, + owner: currentUser?.currentUser?.id ?? '', + } + + updateFazit({ + variables: { id: paperId ?? '', content: newContent, version: localVersion + 1, cursorPosition: newCursorPos }, + }) + }, + [paperId, updateFazit, localVersion, currentUser?.currentUser?.id] + ) + + const syncFinal = () => { + const newCursorPos: CursorInput = { + position: textArea.current?.selectionStart ?? 0, + owner: currentUser?.currentUser?.id ?? '', + } + updateFazit({ + variables: { id: paperId ?? '', content: localContent, version: localVersion + 1, cursorPosition: newCursorPos }, + }).then(() => { + if ( + currentUser?.currentUser?.__typename === 'Trainee' || + currentUser?.currentUser?.__typename === 'Trainer' || + currentUser?.currentUser?.__typename === 'Mentor' + ) { + const paper = currentUser.currentUser.papers?.filter((paper) => paper?.id === paperId)[0] + console.log(paper) + updatePaperMutation({ + variables: { + input: { + briefing: omitDeep(paper?.briefing ?? [], '__typename'), + client: paper?.client ?? '', + didSendEmail: false, + feedbackMentor: omitDeep(paper?.feedbackMentor ?? [], '__typename'), + feedbackTrainee: omitDeep(paper?.feedbackTrainee ?? [], '__typename'), + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + status: PaperStatus.ReviewDone, + subject: paper?.subject ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: paper?.trainerId ?? '', + }, + }, + }).then(() => navigate('/paper/fazit/done/' + paperId)) + } + }) + } + + const handleCursorMove = useCallback(() => { + const cursorPos = textArea.current?.selectionStart || 0 + updateCursorPosition({ + variables: { + id: paperId ?? '', + cursorPosition: { owner: currentUser?.currentUser?.id ?? '', position: cursorPos }, + }, + }) + }, [paperId, updateCursorPosition, currentUser?.currentUser?.id]) + + return ( + + ) +} diff --git a/packages/frontend/src/pages/paper-feedback-discussion-page.tsx b/packages/frontend/src/pages/paper-feedback-discussion-page.tsx new file mode 100644 index 00000000..37258342 --- /dev/null +++ b/packages/frontend/src/pages/paper-feedback-discussion-page.tsx @@ -0,0 +1,228 @@ +import React from 'react' +import { useNavigate, useParams } from 'react-router' +import { Box, Container, PaperH2, PaperLayout, Spacer, Spacings } from '@lara/components' +import NavigationButtonLink from '../components/navigation-button-link' +import { Template } from '../templates/template' +import strings from '../locales/localization' + +import { PaperFormData, useUpdatePaperMutation, useFeedbackDiscussionPageDataQuery, PaperStatus } from '../graphql' +import { omitDeep } from '@apollo/client/utilities' +import CommentSection from '../components/comment-section' +import { styled } from 'styled-components' +import { PrimaryButton } from '../components/button' + +export const PaperTextQuestion = styled.p` + margin: 0; + white-space: pre-wrap; + word-break: break-word; + font-weight: 600; + padding: ${Spacings.m}; + font-size: 16px; + color: ${(props) => props.theme.mediumFont}; + line-height: 1.2; +` + +export const PaperTextHint = styled.p` + margin: 0; + white-space: pre-wrap; + word-break: break-word; + padding: ${Spacings.m}; + font-size: 16px; + color: ${(props) => props.theme.mediumFont}; + line-height: 100%; +` + +export const PaperText = styled.p` + margin: ${Spacings.m}; + white-space: pre-wrap; + word-break: break-word; + font-size: 16px; + padding-bottom: 12px; + color: ${(props) => props.theme.mediumFont}; + line-height: 100%; + border-bottom: 1px solid black; +` + +interface FeedbackEntryProps { + entry: PaperFormData + onSubmit: (comment: string) => void + displayTextInput: boolean +} + +export const FeedbackEntry: React.FC = ({ entry, onSubmit, displayTextInput }) => { + return ( + + + {entry.question} + {entry.hint} + {entry.answer} + + + + + ) +} + +export const PaperFeedbackDiscussionPage: React.FC = () => { + const { paperId } = useParams<{ paperId: string }>() + const data = useFeedbackDiscussionPageDataQuery() + const navigate = useNavigate() + + const currentUser = + data.data?.currentUser?.__typename === 'Mentor' || + data.data?.currentUser?.__typename === 'Trainee' || + data.data?.currentUser?.__typename === 'Trainer' + ? data.data.currentUser + : undefined + + const papers = currentUser?.papers + + const paper = papers?.find((p) => String(p?.id) === String(paperId)) + + const [updatePaper] = useUpdatePaperMutation() + + if (!paper || !currentUser) { + return ( + + ) + } + + const handleCommentSubmit = async (side: 'trainee' | 'mentor', entryId: string, text: string) => { + const t = text?.trim() + if (!t) return + + const newComment = { + text: t, + firstName: currentUser.firstName, + lastName: currentUser.lastName, + userId: currentUser.id, + published: true, + } + + const nextTrainee: PaperFormData[] = (paper.feedbackTrainee ?? []).map((e) => + e.id === entryId && side === 'trainee' + ? { + ...e, + comments: [...e.comments, newComment], + } + : e + ) + + const nextMentor: PaperFormData[] = (paper.feedbackMentor ?? []).map((e) => + e.id === entryId && side === 'mentor' + ? { + ...e, + comments: [...e.comments, newComment], + } + : e + ) + + await updatePaper({ + variables: { + input: { + id: paper.id, + traineeId: paper.traineeId ?? '', + mentorId: paper.mentorId ?? '', + trainerId: paper.trainerId ?? '', + client: paper.client ?? '', + subject: paper.subject ?? '', + periodStart: paper.periodStart, + periodEnd: paper.periodEnd, + didSendEmail: false, + schoolPeriodStart: paper.schoolPeriodStart, + schoolPeriodEnd: paper.schoolPeriodEnd, + status: paper.status, + briefing: omitDeep(paper.briefing ?? [], '__typename'), + feedbackTrainee: omitDeep(nextTrainee, '__typename'), + feedbackMentor: omitDeep(nextMentor, '__typename'), + }, + }, + refetchQueries: ['TraineePaperPageData', 'MentorPaperPageData'], + }) + } + + const finish = () => { + updatePaper({ + variables: { + input: { + id: paper.id, + traineeId: paper.traineeId ?? '', + mentorId: paper.mentorId ?? '', + trainerId: paper.trainerId ?? '', + client: paper.client ?? '', + subject: paper.subject ?? '', + periodStart: paper.periodStart, + periodEnd: paper.periodEnd, + didSendEmail: false, + schoolPeriodStart: paper.schoolPeriodStart, + schoolPeriodEnd: paper.schoolPeriodEnd, + status: PaperStatus.InReview, + briefing: omitDeep(paper.briefing ?? [], '__typename'), + feedbackTrainee: omitDeep(paper.feedbackTrainee, '__typename'), + feedbackMentor: omitDeep(paper.feedbackMentor, '__typename'), + }, + }, + }).then(() => navigate('/paper')) + } + + return ( + + ) +} + +export default PaperFeedbackDiscussionPage diff --git a/packages/frontend/src/pages/trainee-paper-feedback-page.tsx b/packages/frontend/src/pages/trainee-paper-feedback-page.tsx new file mode 100644 index 00000000..6ccc33ef --- /dev/null +++ b/packages/frontend/src/pages/trainee-paper-feedback-page.tsx @@ -0,0 +1,202 @@ +import { Box, Flex, PaperH2, PaperLayout, Spacer } from '@lara/components' +import NavigationButtonLink from '../components/navigation-button-link' +import { Template } from '../templates/template' +import strings from '../locales/localization' +import { Question } from '../helper/paper-helper' +import { useEffect, useState } from 'react' +import { useNavigate, useParams } from 'react-router' +import { PrimaryButton, SecondaryButton } from '../components/button' +import PaperAccordion from '../components/paper-accordion' +import React from 'react' +import { PaperFormData, PaperStatus, Trainee, useTraineePaperPageDataQuery, useUpdatePaperMutation } from '../graphql' +import { omitDeep } from '@apollo/client/utilities' + +const briefingQuestions = (): Question[] => { + const questions = strings.paper.feedbackQuestions + + return [ + questions.descriptionOfActivities, + questions.feedbackOnProjectTeam, + questions.feedbackOnTasksAndProject, + questions.periodOfTime, + questions.learningContent, + ] +} + +export const TraineePaperFeedbackPage: React.FunctionComponent = () => { + const navigate = useNavigate() + const { paperId } = useParams() + const [paperFeedbackInput, setPaperFeedbackInput] = React.useState() + const [paperFeedback, setPaperFeedback] = React.useState([]) + const [filledFromSave, setFilledFromSave] = React.useState(false) + + const traineePaperPageData = useTraineePaperPageDataQuery() + const [updatePaperMutation] = useUpdatePaperMutation() + + const QAs = briefingQuestions() + const [filteredQAs] = useState(QAs) + + const currentUser = traineePaperPageData?.data?.currentUser as Trainee + + const paper = currentUser?.papers?.find((paper) => paper?.id == paperId) + useEffect(() => { + if (paperFeedbackInput) { + setPaperFeedback((oldArray: PaperFormData[]) => [...oldArray, paperFeedbackInput]) + } + }, [paperFeedbackInput]) + + useEffect(() => { + if (!filledFromSave && paper && paper.feedbackTrainee.length > 0 && paperFeedback.length == 0) { + setPaperFeedback(paper.feedbackTrainee) + setFilledFromSave(true) + } + }, [filledFromSave, paper, paperFeedback]) + + if (!currentUser) { + return null + } + + const savePaper = async (paperFeedback: PaperFormData[]) => { + paperFeedback = paperFeedback.map((feedback) => { + if (!feedback.comments) { + return { ...feedback, comments: [] } + } + return feedback + }) + await updatePaperMutation({ + variables: { + input: { + briefing: paper ? omitDeep(paper.briefing, '__typename') : [], + feedbackTrainee: omitDeep(paperFeedback, '__typename'), + feedbackMentor: paper?.feedbackMentor ? omitDeep(paper.feedbackMentor, '__typename') : [], + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + didSendEmail: false, + periodEnd: paper?.periodEnd, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + status: PaperStatus.InProgress, + subject: paper?.subject ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: currentUser.id, + }, + }, + updateQueries: { + TraineePaperPageData: ({ mutationResult }) => { + return { + currentUser: { + papers: mutationResult?.data?.updatePaper, + }, + } + }, + }, + }) + } + + const submitPaper = async (paperFeedback: PaperFormData[]) => { + paperFeedback = paperFeedback.map((feedback) => { + if (!feedback.comments) { + return { ...feedback, comments: [] } + } + return feedback + }) + await updatePaperMutation({ + variables: { + input: { + briefing: paper ? omitDeep(paper.briefing, '__typename') : [], + feedbackTrainee: omitDeep(paperFeedback, '__typename'), + feedbackMentor: paper?.feedbackMentor ? omitDeep(paper.feedbackMentor, '__typename') : [], + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + periodEnd: paper?.periodEnd, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + status: PaperStatus.TraineeDone, + subject: paper?.subject ?? '', + traineeId: paper?.traineeId ?? '', + trainerId: currentUser.id, + didSendEmail: false, + }, + }, + updateQueries: { + TraineePaperPageData: ({ mutationResult }) => { + return { + currentUser: { + papers: mutationResult?.data?.updatePaper, + }, + } + }, + }, + }) + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/trainee-paper-page.tsx b/packages/frontend/src/pages/trainee-paper-page.tsx new file mode 100644 index 00000000..833a406f --- /dev/null +++ b/packages/frontend/src/pages/trainee-paper-page.tsx @@ -0,0 +1,220 @@ +import { Container, H1, Paragraph, Spacer, StyledIcon, Text } from '@lara/components' +import React from 'react' +import Loader from '../components/loader' +import { Template } from '../templates/template' +import { Paper, PaperStatus, Trainee, useTraineePaperPageDataQuery } from '../graphql' +import { Box, Flex } from '@lara/components' +import strings from '../locales/localization' +import ProgressBar from '../components/progress-bar' +import { PrimaryButton } from '../components/button' +import EmptyPaper from '../assets/illustrations/empty-paper' +import { useNavigate } from 'react-router' +import { mapStatusToProgess } from '../helper/paper-helper' + +export const TraineePaperPage: React.FC = () => { + const { loading, data } = useTraineePaperPageDataQuery() + const navigate = useNavigate() + + const navigateToPaperFeedbackPage = (paperId: string) => { + navigate('/paper/feedback/' + paperId) + } + + const navigateToPaperDiscussionPage = (paperId: string) => { + navigate('/paper/feedback/discussion/' + paperId) + } + + const navigateToFazitPage = (paperId: string) => { + navigate('/paper/fazit/' + paperId) + } + + const navigateToFazitDonePage = (paperId: string) => { + navigate('/paper/fazit/done/' + paperId) + } + + if (!data) { + return ( + + ) + } + + const currentUser = data.currentUser as Trainee + if (!currentUser) { + return ( + + ) + } + + const getContinueButtonText = (paperStatus: PaperStatus) => { + switch (paperStatus) { + case PaperStatus.NotStarted: + return strings.start + break + case PaperStatus.InProgress: + return strings.edit + break + case PaperStatus.TraineeDone: + return strings.start + break + case PaperStatus.MentorDone: + return strings.start + break + case PaperStatus.InReview: + return strings.edit + break + case PaperStatus.ReviewDone: + return strings.continue + break + case PaperStatus.Archived: + return 'You should not be able to see this, report as a bug' + break + } + } + + const hasCommented = (paper: Paper) => { + const foundUserIds: Array = [] + paper.feedbackMentor.forEach((feedback) => { + feedback.comments?.forEach((comment) => { + if (!foundUserIds.includes(comment.userId)) { + foundUserIds.push(comment.userId) + } + }) + }) + paper.feedbackTrainee.forEach((feedback) => { + feedback.comments?.forEach((comment) => { + if (!foundUserIds.includes(comment.userId)) { + foundUserIds.push(comment.userId) + } + }) + }) + paper.briefing.forEach((feedback) => { + feedback.comments?.forEach((comment) => { + if (!foundUserIds.includes(comment.userId)) { + foundUserIds.push(comment.userId) + } + }) + }) + + if (foundUserIds.length >= 2) { + return true + } + return false + } + + return ( + + ) +} diff --git a/packages/frontend/src/pages/trainer-paper-page.tsx b/packages/frontend/src/pages/trainer-paper-page.tsx new file mode 100644 index 00000000..6a385487 --- /dev/null +++ b/packages/frontend/src/pages/trainer-paper-page.tsx @@ -0,0 +1,279 @@ +import React from 'react' + +import { + Container, + H1, + H2, + Paragraph, + Spacer, + StyledAction, + StyledIcon, + StyledName, + Text, + Box, + Flex, +} from '@lara/components' + +import { PrimaryButton, SecondaryButton } from '../components/button' +import strings from '../locales/localization' +import { Template } from '../templates/template' +import EmptyPaper from '../assets/illustrations/empty-paper' +import { PaperStatus, Trainer, useDeletePaperMutation, useTrainerPaperPageDataQuery } from '../graphql' +import Loader from '../components/loader' +import ProgressBar from '../components/progress-bar' +import Avatar from '../components/avatar' +import { GraphQLError } from 'graphql/index' +import { useToastContext } from '../hooks/use-toast-context' +import PaperModal from '../assets/illustrations/paper-modal-illustraion' +import Modal from '../components/modal' +import { Paper } from '@lara/api' +import { useNavigate } from 'react-router' +import { mapStatusToProgess } from '../helper/paper-helper' + +export const TrainerPaperPage: React.FC = () => { + const navigate = useNavigate() + const { loading, data } = useTrainerPaperPageDataQuery() + const [showDeletePaperModal, setShowDeletePaperModal] = React.useState(false) + const [toDeletePaper, setToDeletePaper] = React.useState(undefined) + + const [deletePaper] = useDeletePaperMutation() + const { addToast } = useToastContext() + const toggleDeletePaperModal = (paper: Paper | undefined) => { + setShowDeletePaperModal(!showDeletePaperModal) + setToDeletePaper(paper) + } + + if (!data) { + return ( + + ) + } + + const currentUser = data?.currentUser as Trainer + + if (!currentUser) { + return ( + + ) + } + + const handleDelete = async (paperId: string | undefined) => { + if (!paperId) return + await deletePaper({ + variables: { + paperId, + }, + updateQueries: { + TrainerPaperPageData: (prevData, { mutationResult }) => { + return { + currentUser: { + ...prevData, + papers: mutationResult.data?.deletePaper, + }, + } + }, + }, + }) + .then(() => { + addToast({ + icon: 'Bulb', + title: strings.paper.deletePaper.title, + text: strings.paper.deletePaper.text, + type: 'success', + }) + toggleDeletePaperModal(undefined) + }) + .catch((exception: GraphQLError) => { + addToast({ + title: strings.errors.error, + text: exception.message, + type: 'error', + }) + }) + } + + const navigateToEditPaperPage = (paperId: string) => { + navigate('/paper/briefing/' + paperId) + } + + const navigateToPaperDiscussionPage = (paperId: string) => { + navigate('/paper/feedback/discussion/' + paperId) + } + + return ( + + ) +} diff --git a/packages/frontend/src/routes.tsx b/packages/frontend/src/routes.tsx index c4dd88b2..1c1cc2a6 100644 --- a/packages/frontend/src/routes.tsx +++ b/packages/frontend/src/routes.tsx @@ -1,12 +1,13 @@ import React from 'react' import { Navigate, Route, Routes } from 'react-router' -import { Admin, Trainee, Trainer, UserTypeEnum } from './graphql' +import { Admin, Trainee, Trainer, Mentor, UserTypeEnum } from './graphql' import { useAuthentication } from './hooks/use-authentication' import strings from './locales/localization' import { AdminEditUserPage } from './pages/admin-edit-user-page' import { AdminTraineesPage } from './pages/admin-trainees-page' import { AdminTrainerPage } from './pages/admin-trainer-page' +import { AdminMentorPage } from './pages/admin-mentor-page' import { AlexaPage } from './pages/alexa-page' import ArchivePage from './pages/archive-page' import DashboardPage from './pages/dashboard-page' @@ -21,17 +22,29 @@ import ReportPage from './pages/report-page' import ReportReviewPage from './pages/report-review-page' import SettingsPage from './pages/settings-page' import SupportPage from './pages/support-page' +import { TrainerPaperPage } from './pages/trainer-paper-page' import TraineePage from './pages/trainee-page' import TrainerReportsPage from './pages/trainer-reports-page' +import { PaperCreateBriefingPage } from './pages/paper-create-briefing-page' +import { PaperBriefingPage } from './pages/paper-briefing-page' +import { TraineePaperPage } from './pages/trainee-paper-page' +import { MentorPaperPage } from './pages/mentor-paper-page' import AzubiWikiPage from './pages/azubi-wiki-page' import { isWikiFeatureEnabled } from './helper/wiki-helper' import { AdminAdminsPage } from './pages/admin-admins-page' +import { TraineePaperFeedbackPage } from './pages/trainee-paper-feedback-page' +import { MentorPaperFeedbackPage } from './pages/mentor-paper-feedback-page' +import PaperFeedbackDiscussionPage from './pages/paper-feedback-discussion-page' +import { isPaperFeatureEnabled } from './helper/paper-helper' +import { PaperFazitPage } from './pages/paper-fazit-page' +import { PaperFeedbackDone } from './pages/feedback-done' type RoutesProps = { currentUser?: | Pick | (Pick & { trainees: Pick[] }) | Pick + | Pick } const AppRoutes: React.FunctionComponent = ({ currentUser }) => { @@ -73,8 +86,20 @@ const AppRoutes: React.FunctionComponent = ({ currentUser }) => { } /> } /> } /> + } /> + {isWikiFeatureEnabled() && } />} + + {isPaperFeatureEnabled() && ( + <> + } /> + } /> + } /> + } /> + } /> + + )} ) : ( } /> @@ -90,7 +115,28 @@ const AppRoutes: React.FunctionComponent = ({ currentUser }) => { } /> } /> } /> + } /> + {isPaperFeatureEnabled() && ( + <> + } /> + } /> + } /> + } /> + + )} + + )} + + {/* Mentor Routes */} + {currentUser.type === UserTypeEnum.Mentor && currentUser.__typename === 'Mentor' && ( + <> + } /> + } /> + } /> + } /> + } /> + } /> )} @@ -104,6 +150,12 @@ const AppRoutes: React.FunctionComponent = ({ currentUser }) => { } /> } /> } /> + {isPaperFeatureEnabled() && ( + <> + } /> + } /> + + )} )} diff --git a/packages/print/src/create-pdf.tsx b/packages/print/src/create-pdf.tsx index 866b73e6..4e2ea183 100644 --- a/packages/print/src/create-pdf.tsx +++ b/packages/print/src/create-pdf.tsx @@ -3,9 +3,9 @@ import { JSX } from 'react' import ReactServerDOM from 'react-dom/server' import { ServerStyleSheet } from 'styled-components' -import { PrintReportData, PrintTranslations, PrintUserData } from '@lara/api' +import { PrintPaperData, PrintReportData, PrintTranslations, PrintUserData } from '@lara/api' -import { Template } from './template' +import { PaperTemplate, Template } from './template' export const renderComponent = (component: JSX.Element, styleSheet?: ServerStyleSheet): string => { let element = component @@ -37,6 +37,25 @@ export const createPage = ( ` } +export const createPaperPage = ( + paperData: PrintPaperData, + userData: PrintUserData, + translations: PrintTranslations +): string => { + const styleSheet = new ServerStyleSheet() + const htmlBody = renderComponent(, styleSheet) + + return ` + + + + + ${styleSheet.getStyleTags()} + + ${htmlBody} + ` +} + export const createPDF = async ( reportData: PrintReportData, userData: PrintUserData, @@ -54,3 +73,21 @@ export const createPDF = async ( return Buffer.from(pdfData) } + +export const createPaperPDF = async ( + paperData: PrintPaperData, + userData: PrintUserData, + translations: PrintTranslations, + page: Page +): Promise => { + const templateString = createPaperPage(paperData, userData, translations) + + await page.setContent(templateString, { + waitUntil: ['load', 'domcontentloaded', 'networkidle0'], + timeout: 30000, + }) + + const pdfData = await page.pdf({ format: 'a4', printBackground: true }) + + return Buffer.from(pdfData) +} diff --git a/packages/print/src/handler.ts b/packages/print/src/handler.ts index 2820fa78..31133156 100644 --- a/packages/print/src/handler.ts +++ b/packages/print/src/handler.ts @@ -1,13 +1,11 @@ import { Lambda } from '@aws-sdk/client-lambda' import AdmZip from 'adm-zip' import { Handler } from 'aws-lambda' -import chromium from '@sparticuz/chromium' import { launch, Browser, Page } from 'puppeteer-core' -import { EmailPayload, PrintData, PrintPayload } from '@lara/api' - +import { EmailPayload, PrintData, PrintPaperData, PrintPayload, PrintReportData } from '@lara/api' import { getExport, saveAttachments } from './s3' -import { createPDF } from './create-pdf' +import { createPaperPDF, createPDF } from './create-pdf' const { IS_OFFLINE, EMAIL_FUNCTION, FRONTEND_URL } = process.env @@ -20,11 +18,11 @@ const lambda = new Lambda({ endpoint: IS_OFFLINE ? 'http://localhost:3002' : undefined, }) -const generateBatch = async ({ userData, reportsData, printTranslations }: PrintData, page: Page): Promise => { +const generateBatch = async ({ userData, data, printTranslations }: PrintData, page: Page): Promise => { const zip = new AdmZip() - for (let index = 0; index < reportsData.length; index++) { - const reportData = reportsData[index] + for (let index = 0; index < data.length; index++) { + const reportData = data[index] as PrintReportData const buffer = await createPDF(reportData, userData, printTranslations, page) @@ -32,82 +30,120 @@ const generateBatch = async ({ userData, reportsData, printTranslations }: Print zip.addFile(reportData.filename, buffer) } } - return zip.toBuffer() } -export const handler: Handler = async (payload) => { +export const handler: Handler = async ( + payload +): Promise<{ success: 'error' | 'success'; filename: string | undefined }> => { if (!payload || !payload.printDataHash) { - return 'error' + return { success: 'error', filename: undefined } } const exportData = await getExport(payload.printDataHash) - if (!exportData || exportData.reportsData.length === 0) { - return 'error' + if (!exportData || exportData.data.length === 0) { + return { success: 'error', filename: undefined } } - let browser: Browser | undefined - const { reportsData, userData, printTranslations, emailTranslations } = exportData + const { data, userData, printTranslations, emailTranslations } = exportData - const headlessMode: boolean | 'shell' = IS_OFFLINE ? true : 'shell' + const isSingleExport = data.length === 1 + let filename = '' + let isPaper = false + + if (isSingleExport) { + isPaper = data[0].filename.includes('Paper') + if (isPaper) { + const emailType = 'paperBriefing' + console.log(emailType) + filename = (data[0] as PrintPaperData).filename + } else { + filename = (data[0] as PrintReportData).filename + } + } else { + filename = `batch-export-${payload.printDataHash}.zip` + } + let browser: Browser | undefined try { + if (payload.action === 'pageLoad') { + console.log('Sending Trainee Email') + const traineeEmailPayload: EmailPayload = { + emailType: 'reportExport', + attachments: [{ filename: '' }], + userData: { + receiverEmail: userData.receiverEmail, + receiverName: userData.firstName, + buttonLink: `${FRONTEND_URL}/archive`, + }, + translations: emailTranslations, + } + + await lambda.invoke({ + FunctionName: EMAIL_FUNCTION, + InvocationType: 'Event', + Payload: JSON.stringify(traineeEmailPayload), + }) + + if (payload.mentorEmail && payload.mentorName) { + console.log('mentor email') + const mentorEmailPayload: EmailPayload = { + emailType: 'reportExport', + attachments: [{ filename: '' }], + userData: { + receiverEmail: payload.mentorEmail, + receiverName: payload.mentorName, + buttonLink: `${FRONTEND_URL}/archive`, + }, + translations: emailTranslations, + } + + console.log('Sending mentor email') + await lambda.invoke({ + FunctionName: EMAIL_FUNCTION, + InvocationType: 'Event', + Payload: JSON.stringify(mentorEmailPayload), + }) + } + + return { success: 'success', filename } + } + browser = await launch({ - args: chromium.args, - executablePath: await chromium.executablePath(), - headless: headlessMode, + args: ['--no-sandbox', '--disable-setuid-sandbox'], + executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', + headless: false, acceptInsecureCerts: true, }) - // create empty browser page const page = await browser.newPage() - - const isSingleExport = reportsData.length === 1 + await new Promise((res) => setTimeout(res, 300)) + await page.createCDPSession() let outputFile: Buffer | undefined - let filename = '' if (isSingleExport) { - const [data] = reportsData - - outputFile = await createPDF(data, userData, printTranslations, page) - filename = data.filename + if (isPaper) { + const [paperData] = data as PrintPaperData[] + outputFile = await createPaperPDF(paperData, userData, printTranslations, page) + } else { + const [reportData] = data as PrintReportData[] + outputFile = await createPDF(reportData, userData, printTranslations, page) + } } else { outputFile = await generateBatch(exportData, page) - filename = `batch-export-${new Date().getTime()}.zip` - } - - if (!outputFile) { - throw new Error('"generatedReport" is undefined') } + if (!outputFile) throw new Error('"generatedReport" is undefined') await saveAttachments(filename, outputFile) - const emailPayload: EmailPayload = { - emailType: 'reportExport', - attachments: [{ filename }], - userData: { - receiverEmail: userData.receiverEmail, - receiverName: userData.firstName, - buttonLink: `${FRONTEND_URL}/archive`, - }, - translations: emailTranslations, - } - - await lambda.invoke({ - FunctionName: EMAIL_FUNCTION, - InvocationType: 'RequestResponse', - Payload: JSON.stringify(emailPayload), - }) - - return 'success' + return { success: 'success', filename } } catch (e) { - console.error('Error while rendering PDF: ', e) - + console.error('Error while processing request:', e) await lambda.invoke({ FunctionName: EMAIL_FUNCTION, - InvocationType: 'RequestResponse', + InvocationType: 'Event', Payload: JSON.stringify({ emailType: 'error', userData, @@ -115,7 +151,7 @@ export const handler: Handler = async (payloa }), }) - return 'error' + return { success: 'error', filename } } finally { await browser?.close() } diff --git a/packages/print/src/mock.ts b/packages/print/src/mock.ts index 6fd9f44c..39fd948b 100644 --- a/packages/print/src/mock.ts +++ b/packages/print/src/mock.ts @@ -1,11 +1,11 @@ import http, { RequestListener } from 'http' -import { PrintData } from '@lara/api' +import { PrintData, PrintPaperData } from '@lara/api' -import { createPage } from './create-pdf' +import { createPaperPage } from './create-pdf' export const DUMMY_DATA: PrintData = { - reportsData: [ + data: [ { filename: 'file.pdf', reportPeriod: '01.01.2001 - 01.01.2002', @@ -120,6 +120,14 @@ export const DUMMY_DATA: PrintData = { thursday: 'Donnerstag', friday: 'Freitag', hello: 'Hallo', + client: 'Kunde', + mentor: 'Ausbildungsbeauftragter', + trainer: 'Ausbilder', + trainee: 'Auszubildender', + briefing: 'Briefing', + feedbackTrainee: 'Azubi Feedback', + feedbackMentor: 'Mentor Feedback', + fazit: 'Fazit', }, emailTranslations: { hello: 'Hallo {{ USER }},', @@ -135,6 +143,8 @@ export const DUMMY_DATA: PrintData = { deleteUser: 'Ein Benutzer wird bald gelöscht', reportInReview: 'Ein Bericht wurde abgegeben', alexa: 'Deine Accounts wurden verknüpft', + paperBriefing: 'Dein Paper Briefing', + paperBriefingMail: 'Dein Paper Briefing', }, headline: { export: 'Dein Lara-Export!', @@ -145,6 +155,7 @@ export const DUMMY_DATA: PrintData = { deleteUser: 'Ein Benutzer wird bald gelöscht', handOver: 'Ein Bericht wurde übergeben', alexa: 'Lara wurde mit Amazon Alexa verknüpft!', + paperBriefing: 'Paper Briefing', }, message: { error: 'etwas ist schiefgegangen. Bitte wende dich an einen Lara Admin oder Entwickler.', @@ -161,9 +172,162 @@ export const DUMMY_DATA: PrintData = { handOver: 'dein Azubi {{ trainee }} hat KW {{ week }} seines Berichtsheft zur Überprüfung abgegeben.', alexa: 'Dein Lara Account wurde mit deinem Amazon Alexa Account verknüpft. Sollte dies ein Fehler sein bitte öffne deine Lara Einstellungen und löse die Verknüpfung wieder auf. Außerdem solltest du dein Passwort ändern.', + paperBriefing: + 'im Anhang findest du das Briefing-PDF zu der Ausbildungsstation von Anna. Wir wünschen dir ganz viel Spaß damit.', }, link: { archive: 'Zum Archive', + paperBriefing: 'Zum Paper', + report: 'Zum Report', + lara: 'Lara', + settings: 'Einstellungen', + }, + }, +} + +export const DUMMY_PAPER_DATA: PrintData = { + data: [ + { + filename: 'paperBriefingFile.pdf', + + paper: { + status: 'InProgress', + mentorFirstName: 'Men', + mentorLastName: 'Tor', + traineeFirstName: 'Trainee', + traineeLastName: 'Traineeson', + briefing: [ + { + id: '1', + questionId: '1', + answer: 'Test Antwort', + question: 'Gegenstand der Arbeit', + hint: 'Nenne hier bitte kurz die allgemeine Tätigkeit/Aufgabe, welche Inhalt der Projektstation ist.', + }, + { + id: '2', + questionId: '2', + answer: 'Test Antwort', + question: 'Vorgehen', + hint: 'Nenne hier bitte unter welchen Rahmenbedingungen die Projektstation für den Azubi aufgebaut sein soll.', + }, + ], + feedbackTrainee: [ + { + id: '3', + questionId: '4', + answer: 'Test Antwort', + question: 'Test Frage', + hint: 'Test Hinweis', + }, + ], + feedbackMentor: [ + { + id: '4', + questionId: '5', + answer: 'Mentor Antwort', + question: 'Mentor Frage', + hint: 'Mentor Hinweis', + }, + ], + fazit: 'Das ist das Fazit', + client: 'Kunde', + periodStart: '2022-08-07T05:14:28.000Z', + periodEnd: '2025-08-07T05:14:28.000Z', + schoolPeriodStart: '2022-08-07T05:14:28.000Z', + schoolPeriodEnd: '2025-08-07T05:14:28.000Z', + subject: 'Entwicklung', + }, + }, + ], + userData: { + receiverEmail: 'test@test.com', + firstName: 'testName', + course: 'Mediengestalter Digital und Print', + lastName: 'Trai nee Trainee', + traineeSignature: 'TRAINEE', + trainerSignature: 'TRAINER', + }, + printTranslations: { + name: 'Name', + apprenticeCourse: 'Ausbildungsgang', + department: 'Abteilung', + apprenticeYear: 'Ausbildungsjahr', + period: 'Zeitraum', + description: 'Beschreibung', + duration: 'Dauer', + holiday: 'Feiertag', + sick: 'Krank', + vacation: 'Urlaub', + total: 'Gesamt', + totalWeek: 'Wochenstunden', + date: 'DATUM', + signatureTrainee: 'UNTERSCHRIFT AUSZUBILDENDE/R', + signatureTrainer: 'UNTERSCHRIFT AUSBILDER/IN', + monday: 'Montag', + tuesday: 'Dienstag', + wednesday: 'Mittwoch', + thursday: 'Donnerstag', + friday: 'Freitag', + hello: 'Hallo', + client: 'Kunde', + mentor: 'Ausbildungsbeauftragter', + trainer: 'Ausbilder', + trainee: 'Auszubildender', + briefing: 'Briefing', + feedbackTrainee: 'Azubi Feedback', + feedbackMentor: 'Mentor Feedback', + fazit: 'Fazit', + }, + emailTranslations: { + hello: 'Hallo {{ USER }},', + comment: 'Zu dieser Woche gibt es einen Kommentar.', + comment_plural: 'Zu dieser Woche gibt es {{ COUNT }} Kommentare.', + subject: { + error: 'Fehler bei der pdf Generierung', + reportExport: 'Dein Lara Export', + acceptReport: 'Dein Bericht wurde genehmigt', + needChanges: 'Bericht zurückgegeben', + deleteYourTrainee: 'Dein Azubi wird bald gelöscht', + deleteAccount: 'Dein Account wird bald gelöscht', + deleteUser: 'Ein Benutzer wird bald gelöscht', + reportInReview: 'Ein Bericht wurde abgegeben', + alexa: 'Deine Accounts wurden verknüpft', + paperBriefing: 'Dein Paper Briefing', + paperBriefingMail: 'Dein Paper Briefing', + }, + headline: { + export: 'Dein Lara-Export!', + accepted: 'Report genehmigt!', + needChanges: 'Änderungen erforderlich!', + deleteTrainee: 'Dein Azubi wird bald gelöscht', + deleteAccount: 'Dein Account wird bald gelöscht', + deleteUser: 'Ein Benutzer wird bald gelöscht', + handOver: 'Ein Bericht wurde übergeben', + alexa: 'Lara wurde mit Amazon Alexa verknüpft!', + paperBriefing: 'Paper Briefing', + }, + message: { + error: 'etwas ist schiefgegangen. Bitte wende dich an einen Lara Admin oder Entwickler.', + success: 'im Anhang findest du deinen Lara-Export. Wir wünschen dir ganz viel Spaß damit.', + accepted: '{{ trainer }} hat dein Berichtsheft erhalten und genehmigt', + needChanges: + '{{ trainer }} hat dein Berichtsheft erhalten und es zurückgegeben. Zu dieser Woche gibt es einen Kommentar.', + deleteTrainee: + 'Dein Auszubildener {{ trainee }} wird in 3 Monaten gelöscht. Sollte dies ein Fehler sein kannst du dich mit deinem Admin in Verbindung setzen, damit er die Löschung abbricht.', + deleteAccount: + 'Dein Account bei Lara wird in 3 Monaten gelöscht. Sollte dies ein Fehler sein kannst du dich mit deinem Admin in Verbindung setzen, damit er die Löschung abbricht.', + deleteUser: + 'Der Benutzer {{ user }} wird in 3 Monaten gelöscht. Sollte dies ein Fehler sein kannst du über den Button, in die Einstellungen gehen und dort die Löschung abbrechen.', + handOver: 'dein Azubi {{ trainee }} hat KW {{ week }} seines Berichtsheft zur Überprüfung abgegeben.', + alexa: + 'Dein Lara Account wurde mit deinem Amazon Alexa Account verknüpft. Sollte dies ein Fehler sein bitte öffne deine Lara Einstellungen und löse die Verknüpfung wieder auf. Außerdem solltest du dein Passwort ändern.', + paperBriefing: + 'im Anhang findest du das Briefing-PDF zu der Ausbildungsstation von Anna. Wir wünschen dir ganz viel Spaß damit.', + }, + link: { + archive: 'Zum Archive', + paperBriefing: 'Zum Paper', report: 'Zum Report', lara: 'Lara', settings: 'Einstellungen', @@ -173,11 +337,11 @@ export const DUMMY_DATA: PrintData = { const host = 'localhost' const port = 9000 -const { reportsData, userData, printTranslations } = DUMMY_DATA +const { data, userData, printTranslations } = DUMMY_PAPER_DATA const requestListener: RequestListener = (_req, res) => { res.writeHead(200) - res.end(createPage(reportsData[0], userData, printTranslations)) + res.end(createPaperPage(data[0] as PrintPaperData, userData, printTranslations)) } const server = http.createServer(requestListener) diff --git a/packages/print/src/template.tsx b/packages/print/src/template.tsx index 03136787..6bc53667 100644 --- a/packages/print/src/template.tsx +++ b/packages/print/src/template.tsx @@ -1,9 +1,9 @@ import React from 'react' import { createGlobalStyle } from 'styled-components' -import { lightTheme, ThemeProvider } from '@lara/components' +import { lightTheme, StyledPrintPaperEntry, StyledPrintPaperSubHeadline, ThemeProvider } from '@lara/components' -import { PrintUserData, PrintReport, PrintTranslations } from '@lara/api' +import { PrintUserData, PrintReport, PrintTranslations, PrintPaper, PrintForm } from '@lara/api' import { Spacings, StyledPrintDay, @@ -50,6 +50,12 @@ type TemplateProps = { signatureDate: string } +type PaperTemplateProps = { + userData: PrintUserData + i18n: PrintTranslations + paper: PrintPaper +} + export const Template: React.FC = ({ userData: { traineeSignature, trainerSignature, firstName, lastName, course }, reportPeriod, @@ -69,7 +75,7 @@ export const Template: React.FC = ({ - + {i18n.name}: {firstName} {lastName} @@ -144,3 +150,107 @@ export const Template: React.FC = ({ ) } + +export const PaperTemplate: React.FC = ({ paper, i18n }) => { + console.log(paper.briefing) + return ( + + + + + + + + {i18n.trainee}: + {paper.traineeFirstName} {paper.traineeLastName} + + + {i18n.mentor}: + {paper.mentorFirstName} {paper.mentorLastName} + + + {i18n.department}: + {paper.subject} + + {paper.periodStart ? ( + + {i18n.period}: + {paper.periodStart + ' -' + paper.periodEnd} + + ) : null} + + {i18n.client}: + {paper.client} + + {paper.schoolPeriodStart ? ( + + {i18n.period}: + {paper.schoolPeriodStart + ' -' + paper.schoolPeriodEnd} + + ) : null} + +
    + {paper.briefing.map((briefing: PrintForm, index, array) => { + return ( + + {index == 0 || array[index].questionId !== array[index - 1].questionId ? ( + <> + {briefing.question} + {briefing.hint} + + ) : null} + {briefing.answer} + + ) + })} + + {paper.feedbackTrainee.length > 0 && ( + + {i18n.feedbackTrainee} + + {paper.feedbackTrainee.map((feedback: PrintForm, index: number) => { + return ( +
    + + {feedback.question} + + + {feedback.hint} + + {feedback.answer} +
    + ) + })} +
    + )} + + {paper.feedbackMentor && paper.feedbackMentor.length > 0 && ( + + {i18n.feedbackMentor} + + {paper.feedbackMentor.map((feedback: PrintForm, index: number) => { + return ( +
    + + {feedback.question} + + + {feedback.hint} + + {feedback.answer} +
    + ) + })} +
    + )} + + {paper.fazit && ( + + {i18n.fazit} + {paper.fazit} + + )} +
    +
    + ) +} diff --git a/serverless.yml b/serverless.yml index 0fa71d10..39a9d8ef 100644 --- a/serverless.yml +++ b/serverless.yml @@ -47,6 +47,10 @@ custom: sources: - table: ${self:custom.config.table.report} sources: [packages/backend/seeds/reports.json] + papers: + sources: + - table: ${self:custom.config.table.paper} + sources: [packages/backend/seeds/papers.json] jetpack: preInclude: - '!**' @@ -65,6 +69,7 @@ custom: user: ${self:custom.stage}-lara-user-table report: ${self:custom.stage}-lara-report-table company: ${self:custom.stage}-lara-company-table + paper: ${self:custom.stage}-lara-paper-table lambda: print: ${self:service}-${self:custom.stage}-print email: ${self:service}-${self:custom.stage}-email @@ -73,6 +78,9 @@ custom: reportTraineeIdStatus: reportGSI2 userType: userGSI1 userEmail: userGSI4 + paperTraineeId: paperGSI1 + paperTrainerId: paperGSI2 + paperMentorId: paperGSI3 userTrainerId: userGSI6 userOAuthCode: userOAuthCode s3: @@ -136,6 +144,8 @@ functions: Resource: - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.company}' - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.company}/index/*' + - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.paper}' + - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.paper}/index/*' - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.user}' - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.user}/index/*' - 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:custom.config.table.report}' @@ -153,12 +163,16 @@ functions: USER_TABLE: ${self:custom.config.table.user} REPORT_TABLE: ${self:custom.config.table.report} COMPANY_TABLE: ${self:custom.config.table.company} + PAPER_TABLE: ${self:custom.config.table.paper} PRINT_FUNCTION: ${self:custom.config.lambda.print} EMAIL_FUNCTION: ${self:custom.config.lambda.email} REPORT_WEEK_TRAINEEID_INDEX: ${self:custom.config.gsi.reportWeekTraineeId} REPORT_TRAINEEID_STATUS_INDEX: ${self:custom.config.gsi.reportTraineeIdStatus} USER_TYPE_INDEX: ${self:custom.config.gsi.userType} USER_EMAIL_INDEX: ${self:custom.config.gsi.userEmail} + PAPER_TRAINEE_ID_INDEX: ${self:custom.config.gsi.paperTraineeId} + PAPER_TRAINER_ID_INDEX: ${self:custom.config.gsi.paperTrainerId} + PAPER_MENTOR_ID_INDEX: ${self:custom.config.gsi.paperMentorId} USER_TRAINER_ID_INDEX: ${self:custom.config.gsi.userTrainerId} USER_OAUTH_CODE_INDEX: ${self:custom.config.gsi.userOAuthCode} EXPORT_BUCKET: ${self:custom.config.s3.export} @@ -360,6 +374,44 @@ resources: BillingMode: PAY_PER_REQUEST TableName: ${self:custom.config.table.company} + PaperTable: + Type: 'AWS::DynamoDB::Table' + DeletionPolicy: Delete + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + - AttributeName: traineeId + AttributeType: S + - AttributeName: trainerId + AttributeType: S + - AttributeName: mentorId + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + GlobalSecondaryIndexes: + - IndexName: ${self:custom.config.gsi.paperTraineeId} + KeySchema: + - AttributeName: traineeId + KeyType: HASH + Projection: + ProjectionType: ALL + - IndexName: ${self:custom.config.gsi.paperTrainerId} + KeySchema: + - AttributeName: trainerId + KeyType: HASH + Projection: + ProjectionType: ALL + - IndexName: ${self:custom.config.gsi.paperMentorId} + KeySchema: + - AttributeName: mentorId + KeyType: HASH + Projection: + ProjectionType: ALL + BillingMode: PAY_PER_REQUEST + TableName: ${self:custom.config.table.paper} + AttachmentsBucket: Type: AWS::S3::Bucket Properties: