From 7bedc99992e808923c4f99ada8c8e687106635bf Mon Sep 17 00:00:00 2001 From: alexander-schefe Date: Fri, 15 Aug 2025 13:17:28 +0200 Subject: [PATCH 01/11] chore: manually rebased lara-paper onto main fix: fixed remaining errors and modernized old dependency syntax fix: added exit button to trainer-edit-paper-page and moved the mentor page to root fix: regenerated the types fix: codegen issues fix: added navigation for mentor on desktop, fixed mentor id in paper seed, fixed other minor issues feat(all): ran yarn generate and i chore: implement profile picture changes to paper infrastructure feat: made papers saveable and fixed paper-briefing-page layout feat: added trainee feedback and saving feedback. cant submit feedback yet fix: test error and empty page text for trainee feat: node_env guard for this feature in prod and fixed navigation width scaling feat: centralized paper enable toggle, update progress bar and check mark on feedback submit --- packages/api/codegen.yml | 2 + packages/api/schema.gql | 190 ++++ packages/api/src/context.ts | 8 +- packages/api/src/email.ts | 16 + packages/api/src/graphql.ts | 306 +++++- packages/api/src/models.ts | 22 +- packages/api/src/print.ts | 34 +- packages/backend/seeds/papers.json | 32 + packages/backend/seeds/users.json | 16 + packages/backend/src/db/env.ts | 26 + packages/backend/src/i18n/de.ts | 11 + packages/backend/src/i18n/en.ts | 11 + packages/backend/src/permissions.ts | 15 +- .../backend/src/repositories/mentor.repo.ts | 13 + .../backend/src/repositories/paper.repo.ts | 43 + .../backend/src/resolvers/admin.resolver.ts | 53 +- packages/backend/src/resolvers/index.ts | 14 +- .../backend/src/resolvers/mentor.resolver.ts | 21 + .../backend/src/resolvers/paper.resolver.ts | 35 + .../backend/src/resolvers/trainee.resolver.ts | 8 +- .../backend/src/resolvers/trainer.resolver.ts | 76 +- .../backend/src/services/email.service.ts | 46 +- .../backend/src/services/mentor.service.ts | 52 ++ .../backend/src/services/paper.service.ts | 17 + .../backend/src/services/print.service.ts | 89 +- packages/backend/src/test/getEnv.js | 4 + .../backend/src/test/paper.service.test.ts | 67 ++ packages/components/src/button-layout.tsx | 2 +- packages/components/src/fab.tsx | 4 +- packages/components/src/icon-definitions.ts | 4 + packages/components/src/icons/blank.tsx | 5 + packages/components/src/icons/checkMark.tsx | 17 + packages/components/src/index.ts | 5 + .../components/src/navigation-button-link.tsx | 18 +- packages/components/src/navigation.tsx | 4 +- packages/components/src/paper-accordion.ts | 63 ++ .../src/paper-comment-bubble-layout.tsx | 39 + packages/components/src/paper-create.tsx | 26 + packages/components/src/paper-form.layout.tsx | 33 + packages/components/src/paper-form.tsx | 104 +++ packages/components/src/paper-text-input.tsx | 35 + packages/components/src/print/day.ts | 8 + packages/components/src/print/entry.ts | 7 + packages/components/src/text.ts | 2 +- packages/components/src/user-form.tsx | 39 + packages/email/package.json | 2 +- packages/email/src/handler.ts | 2 +- packages/email/src/mock.ts | 11 + .../src/assets/illustrations/empty-paper.tsx | 116 +++ .../illustrations/paper-modal-illustraion.tsx | 201 ++++ .../src/components/dev-role-dropdown.tsx | 18 +- .../src/components/edit-mentor-content.tsx | 53 ++ .../frontend/src/components/edit-user-row.tsx | 6 +- .../frontend/src/components/mentor-form.tsx | 178 ++++ .../src/components/navigation-button-link.tsx | 2 + .../frontend/src/components/navigation.tsx | 35 +- .../src/components/paper-accordion.tsx | 88 ++ .../src/components/paper-comment-bubble.tsx | 13 + .../src/components/paper-create-form.tsx | 241 +++++ .../src/components/paper-text-box.tsx | 32 + .../src/components/paper-text-input.tsx | 130 +++ packages/frontend/src/graphql/index.tsx | 878 +++++++++++++++++- .../src/graphql/mutations/create-mentor.gql | 12 + .../src/graphql/mutations/create-paper.gql | 29 + .../src/graphql/mutations/delete-paper.gql | 27 + .../graphql/mutations/get-user-by-email.gql | 39 + .../src/graphql/mutations/update-mentor.gql | 11 + .../src/graphql/mutations/update-paper.gql | 27 + .../src/graphql/queries/admin-mentor-page.gql | 10 + .../frontend/src/graphql/queries/get-user.gql | 6 + .../src/graphql/queries/mentor-data.gql | 9 + .../queries/mentor-paper-page-data.gql | 35 + .../src/graphql/queries/print-paper-data.gql | 5 + .../src/graphql/queries/trainee-page-data.gql | 27 + .../queries/trainee-paper-page-data.gql | 34 + .../src/graphql/queries/trainee-paper.gql | 34 + .../queries/trainer-paper-page-data.gql | 40 + packages/frontend/src/helper/paper-helper.ts | 22 + packages/frontend/src/hooks/use-fetch-pdf.ts | 27 +- packages/frontend/src/locales/de.ts | 153 ++- packages/frontend/src/locales/en.ts | 146 +++ packages/frontend/src/locales/translation.ts | 138 +++ .../src/pages/admin-edit-user-page.tsx | 18 + .../frontend/src/pages/admin-mentor-page.tsx | 85 ++ .../frontend/src/pages/mentor-paper-page.tsx | 104 +++ .../src/pages/paper-briefing-page.tsx | 255 +++++ .../src/pages/paper-create-briefing-page.tsx | 139 +++ .../src/pages/trainee-paper-feedback-page.tsx | 187 ++++ .../frontend/src/pages/trainee-paper-page.tsx | 132 +++ .../frontend/src/pages/trainer-paper-page.tsx | 269 ++++++ packages/frontend/src/routes.tsx | 41 +- packages/print/src/create-pdf.tsx | 41 +- packages/print/src/handler.ts | 72 +- packages/print/src/mock.ts | 202 +++- packages/print/src/template.tsx | 70 +- serverless.yml | 52 ++ 96 files changed, 6045 insertions(+), 101 deletions(-) create mode 100644 packages/backend/seeds/papers.json create mode 100644 packages/backend/src/repositories/mentor.repo.ts create mode 100644 packages/backend/src/repositories/paper.repo.ts create mode 100644 packages/backend/src/resolvers/mentor.resolver.ts create mode 100644 packages/backend/src/resolvers/paper.resolver.ts create mode 100644 packages/backend/src/services/mentor.service.ts create mode 100644 packages/backend/src/services/paper.service.ts create mode 100644 packages/backend/src/test/paper.service.test.ts create mode 100644 packages/components/src/icons/blank.tsx create mode 100644 packages/components/src/icons/checkMark.tsx create mode 100644 packages/components/src/paper-accordion.ts create mode 100644 packages/components/src/paper-comment-bubble-layout.tsx create mode 100644 packages/components/src/paper-create.tsx create mode 100644 packages/components/src/paper-form.layout.tsx create mode 100644 packages/components/src/paper-form.tsx create mode 100644 packages/components/src/paper-text-input.tsx create mode 100644 packages/frontend/src/assets/illustrations/empty-paper.tsx create mode 100644 packages/frontend/src/assets/illustrations/paper-modal-illustraion.tsx create mode 100644 packages/frontend/src/components/edit-mentor-content.tsx create mode 100644 packages/frontend/src/components/mentor-form.tsx create mode 100644 packages/frontend/src/components/paper-accordion.tsx create mode 100644 packages/frontend/src/components/paper-comment-bubble.tsx create mode 100644 packages/frontend/src/components/paper-create-form.tsx create mode 100644 packages/frontend/src/components/paper-text-box.tsx create mode 100644 packages/frontend/src/components/paper-text-input.tsx create mode 100644 packages/frontend/src/graphql/mutations/create-mentor.gql create mode 100644 packages/frontend/src/graphql/mutations/create-paper.gql create mode 100644 packages/frontend/src/graphql/mutations/delete-paper.gql create mode 100644 packages/frontend/src/graphql/mutations/get-user-by-email.gql create mode 100644 packages/frontend/src/graphql/mutations/update-mentor.gql create mode 100644 packages/frontend/src/graphql/mutations/update-paper.gql create mode 100644 packages/frontend/src/graphql/queries/admin-mentor-page.gql create mode 100644 packages/frontend/src/graphql/queries/mentor-data.gql create mode 100644 packages/frontend/src/graphql/queries/mentor-paper-page-data.gql create mode 100644 packages/frontend/src/graphql/queries/print-paper-data.gql create mode 100644 packages/frontend/src/graphql/queries/trainee-paper-page-data.gql create mode 100644 packages/frontend/src/graphql/queries/trainee-paper.gql create mode 100644 packages/frontend/src/graphql/queries/trainer-paper-page-data.gql create mode 100644 packages/frontend/src/helper/paper-helper.ts create mode 100644 packages/frontend/src/pages/admin-mentor-page.tsx create mode 100644 packages/frontend/src/pages/mentor-paper-page.tsx create mode 100644 packages/frontend/src/pages/paper-briefing-page.tsx create mode 100644 packages/frontend/src/pages/paper-create-briefing-page.tsx create mode 100644 packages/frontend/src/pages/trainee-paper-feedback-page.tsx create mode 100644 packages/frontend/src/pages/trainee-paper-page.tsx create mode 100644 packages/frontend/src/pages/trainer-paper-page.tsx 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..c82ce191 100644 --- a/packages/api/schema.gql +++ b/packages/api/schema.gql @@ -113,6 +113,63 @@ type UpdateReportPayload { report: Report! } +input MentorInput { + name: String + email: String + signature: String +} + +input PaperEntryInput { + id: ID! + questionId: ID! + question: String! + answer: String + hint: String +} + +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!]! + feedback: [PaperEntryInput!]! +} + +input PaperUpdateInput { + id: ID! + traineeId: ID! + trainerId: ID! + client: String! + mentorId: ID! + periodStart: String + periodEnd: String + schoolPeriodStart: String + schoolPeriodEnd: String + subject: String! + status: PaperStatus! + briefing: [PaperEntryInput!]! + feedback: [PaperEntryInput!]! +} + +input AnswerPaperInput { + id: ID! + questionId: ID! + question: String! + answer: String! + hint: String! +} + type Mutation { """ [DEV] Login as a user. @@ -236,6 +293,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 +328,11 @@ type Mutation { """ updateAdmin(input: UpdateAdminInput!, id: ID!): Admin + """ + Updates Mentor. + """ + updateMentor(input: UpdateMentorInput!, id: ID!): Mentor + """ Link Alexa account """ @@ -280,6 +352,36 @@ 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! } type LaraConfig { @@ -347,11 +449,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!]!): PrintPayload! + """ Get a User by ID """ @@ -425,6 +537,7 @@ type Trainee implements UserInterface { lastName: String! notification: Boolean reports: [Report!]! + papers: [Paper] signature: String startDate: String startOfToolUsage: String @@ -467,12 +580,28 @@ 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 Trainer implements UserInterface { createdAt: String! firstName: String! @@ -480,6 +609,7 @@ type Trainer implements UserInterface { language: String lastName: String! notification: Boolean + papers: [Paper] signature: String theme: String trainees: [Trainee!]! @@ -501,6 +631,25 @@ 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 + username: String! + email: String! + deleteAt: String + alexaSkillLinked: Boolean +} + type Admin implements UserInterface { createdAt: String! firstName: String! @@ -553,8 +702,49 @@ enum UserTypeEnum { """ Trainer + """ + User is a Mentor + """ + Mentor + """ User is an Admin """ Admin } + +enum PaperStatus { + NotStarted + InProgress + TraineeDone + MentorDone + InReview + Archived +} + +type PaperFormData { + id: ID! + questionId: ID! + question: String! + answer: String + hint: String +} + +type Paper { + id: ID! + traineeId: ID! + trainerId: ID! + status: PaperStatus! + briefing: [PaperFormData!]! + feedback: [PaperFormData!]! + conclusion: String + archivedAt: String + createdAt: String + client: String! + mentorId: ID! + periodStart: String + periodEnd: String + schoolPeriodStart: String + schoolPeriodEnd: String + subject: String! +} 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..bac514e8 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']; @@ -146,6 +162,32 @@ 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; + username: Scalars['String']['output']; +}; + +export type GqlMentorInput = { + email?: InputMaybe; + name?: InputMaybe; + signature?: InputMaybe; +}; + export type GqlMutateEntryPayload = { __typename?: 'MutateEntryPayload'; day: GqlDay; @@ -153,6 +195,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 +218,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 +238,14 @@ 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; /** Get Avatar Bucket Upload URL */ getAvatarSignedUrl?: Maybe; + /** Get a User by Email */ + getUserByEmail?: Maybe; /** Link Alexa account */ linkAlexa?: Maybe; /** Login via microsoft */ @@ -217,6 +276,12 @@ export type GqlMutation = { updateDay?: Maybe; updateEntry: GqlMutateEntryPayload; updateEntryOrder: GqlMutateEntryPayload; + /** 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 +338,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 +389,26 @@ export type GqlMutationDeleteEntryArgs = { }; +export type GqlMutationDeletePaperArgs = { + paperId: Scalars['ID']['input']; +}; + + +export type GqlMutationDeletePaperEntryArgs = { + 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 +500,22 @@ export type GqlMutationUpdateEntryOrderArgs = { }; +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,6 +542,82 @@ export type GqlOAuthPayload = { refreshToken?: Maybe; }; +export type GqlPaper = { + __typename?: 'Paper'; + archivedAt?: Maybe; + briefing: Array; + client: Scalars['String']['output']; + conclusion?: Maybe; + createdAt?: Maybe; + feedback: 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 GqlPaperEntryInput = { + answer?: InputMaybe; + hint?: InputMaybe; + id: Scalars['ID']['input']; + question: Scalars['String']['input']; + questionId: Scalars['ID']['input']; +}; + +export type GqlPaperFormData = { + __typename?: 'PaperFormData'; + answer?: Maybe; + hint?: Maybe; + id: Scalars['ID']['output']; + question: Scalars['String']['output']; + questionId: Scalars['ID']['output']; +}; + +export type GqlPaperInput = { + briefing: Array; + client: Scalars['String']['input']; + feedback: 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' + | 'TraineeDone'; + +export type GqlPaperUpdateInput = { + briefing: Array; + client: Scalars['String']['input']; + feedback: 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']; @@ -455,8 +642,12 @@ export type GqlQuery = { currentUser?: Maybe; /** Get a User by ID */ getUser?: Maybe; + /** Get all Trainers */ + 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. */ @@ -482,6 +673,11 @@ export type GqlQueryPrintArgs = { }; +export type GqlQueryPrintPaperArgs = { + ids: Array; +}; + + export type GqlQueryReportForTraineeArgs = { id: Scalars['ID']['input']; week: Scalars['Int']['input']; @@ -549,6 +745,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 +766,7 @@ export type GqlTrainer = GqlUserInterface & { language?: Maybe; lastName: Scalars['String']['output']; notification?: Maybe; + papers?: Maybe>>; signature?: Maybe; theme?: Maybe; trainees: Array; @@ -597,6 +795,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,6 +849,8 @@ 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 */ @@ -721,12 +929,14 @@ 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; Day: ResolverTypeWrapper; @@ -738,9 +948,18 @@ export type GqlResolversTypes = ResolversObject<{ 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; + PaperEntryInput: GqlPaperEntryInput; + PaperFormData: ResolverTypeWrapper; + PaperInput: GqlPaperInput; + PaperStatus: GqlPaperStatus; + PaperUpdateInput: GqlPaperUpdateInput; PrintPayload: ResolverTypeWrapper; PublishCommentsPayload: ResolverTypeWrapper & { report: GqlResolversTypes['Report'] }>; Query: ResolverTypeWrapper<{}>; @@ -754,6 +973,7 @@ 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; @@ -765,12 +985,14 @@ export type GqlResolversTypes = ResolversObject<{ /** 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; Day: Day; @@ -781,9 +1003,17 @@ export type GqlResolversParentTypes = ResolversObject<{ 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; + PaperEntryInput: GqlPaperEntryInput; + PaperFormData: GqlPaperFormData; + PaperInput: GqlPaperInput; + PaperUpdateInput: GqlPaperUpdateInput; PrintPayload: GqlPrintPayload; PublishCommentsPayload: Omit & { report: GqlResolversParentTypes['Report'] }; Query: {}; @@ -796,6 +1026,7 @@ 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; @@ -890,6 +1121,26 @@ 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; + username?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlMutateEntryPayloadResolvers = ResolversObject<{ day?: Resolver; entry?: Resolver, ParentType, ContextType>; @@ -897,6 +1148,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 +1162,20 @@ 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>; 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 +1192,9 @@ export type GqlMutationResolvers, ParentType, ContextType, RequireFields>; updateEntry?: Resolver>; updateEntryOrder?: Resolver>; + 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,6 +1207,35 @@ 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>; + feedback?: 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 GqlPaperFormDataResolvers = ResolversObject<{ + answer?: Resolver, ParentType, ContextType>; + hint?: Resolver, ParentType, ContextType>; + id?: Resolver; + question?: Resolver; + questionId?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export type GqlPrintPayloadResolvers = ResolversObject<{ estimatedWaitingTime?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -960,7 +1254,9 @@ export type GqlQueryResolvers; currentUser?: Resolver, ParentType, ContextType>; 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 +1303,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 +1324,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 +1351,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; @@ -1078,9 +1376,13 @@ export type GqlResolvers = ResolversObject<{ DevSetUserPayload?: GqlDevSetUserPayloadResolvers; Entry?: GqlEntryResolvers; LaraConfig?: GqlLaraConfigResolvers; + Mentor?: GqlMentorResolvers; MutateEntryPayload?: GqlMutateEntryPayloadResolvers; + MutatePaperPayload?: GqlMutatePaperPayloadResolvers; Mutation?: GqlMutationResolvers; OAuthPayload?: GqlOAuthPayloadResolvers; + Paper?: GqlPaperResolvers; + PaperFormData?: GqlPaperFormDataResolvers; PrintPayload?: GqlPrintPayloadResolvers; PublishCommentsPayload?: GqlPublishCommentsPayloadResolvers; Query?: GqlQueryResolvers; diff --git a/packages/api/src/models.ts b/packages/api/src/models.ts index cf7a5f3b..869a5431 100644 --- a/packages/api/src/models.ts +++ b/packages/api/src/models.ts @@ -4,13 +4,16 @@ import { GqlCommentableInterface, GqlDay, GqlEntry, + 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 +36,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 +69,16 @@ export type Report = Omit & { + briefing: GqlPaperFormData[] + feedback: GqlPaperFormData[] +} + +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..3dafb65b 100644 --- a/packages/api/src/print.ts +++ b/packages/api/src/print.ts @@ -19,11 +19,33 @@ export type PrintReport = { summary: string } +export type PrintPaper = { + status: string + briefing: PrintForm[] + feedback: PrintForm[] + client: string + periodStart: string + periodEnd: string + schoolPeriodStart: string + schoolPeriodEnd: string + subject: 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 +58,11 @@ export type PrintReportData = { signatureDate: string } +export type PrintPaperData = { + filename: string + paper: PrintPaper +} + export type PrintTranslations = { monday: string tuesday: string @@ -58,6 +85,11 @@ export type PrintTranslations = { signatureTrainee: string signatureTrainer: string hello: string + client: string + mentor: string + trainer: string + trainee: string + briefing: string } export type PrintPayload = { @@ -66,7 +98,7 @@ export type PrintPayload = { 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..caee6e09 --- /dev/null +++ b/packages/backend/seeds/papers.json @@ -0,0 +1,32 @@ +[ + { + "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": [], + "feedback": [] + }, + { + "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": [], + "feedback": [] + } +] diff --git a/packages/backend/seeds/users.json b/packages/backend/seeds/users.json index cc10e7f1..982e70d4 100644 --- a/packages/backend/seeds/users.json +++ b/packages/backend/seeds/users.json @@ -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/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..c5ec3465 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. 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,10 @@ export const GermanTranslations: Translations = { thursday: 'Donnerstag', friday: 'Freitag', hello: 'Hallo', + client: 'Kunde', + mentor: 'Ausbildungsbeauftragter', + trainer: 'Ausbilder', + trainee: 'Auszubildender', + briefing: 'Briefing', }, } diff --git a/packages/backend/src/i18n/en.ts b/packages/backend/src/i18n/en.ts index 62fed707..6d8aa30c 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. We hope you have a lot of fun with it.", }, link: { archive: 'Archive', + paperBriefing: 'Paper', report: 'Report', lara: 'Lara', settings: 'Settings', @@ -98,5 +104,10 @@ export const EnglishTranslations: Translations = { thursday: 'Thursday', friday: 'Friday', hello: 'Hello', + client: 'Client', + mentor: 'Mentor', + trainer: 'Trainer', + trainee: 'Trainee', + briefing: 'Briefing', }, } diff --git a/packages/backend/src/permissions.ts b/packages/backend/src/permissions.ts index c15e4668..2e322f25 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,10 @@ 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' +} + export const isAdmin = (user: User): user is Admin => { return user.type === 'Admin' } @@ -52,12 +56,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 +74,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 +94,9 @@ export const permissions = shield( // Trainer mutations claimTrainee: and(authenticated, trainer), unclaimTrainee: and(authenticated, trainer), + createPaper: and(authenticated, or(trainee, trainer)), + updatePaper: and(authenticated, or(trainee, trainer)), + deletePaper: and(authenticated, or(trainee, trainer)), //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..69d46abb 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,12 +14,16 @@ 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' export const adminResolver: GqlResolvers = { Admin: {}, Query: { admins: allAdmins, + mentors: allMentors, trainers: allTrainers, + trainees: allTrainees, async cleanup() { const users = await allUsers() @@ -50,6 +54,10 @@ export const adminResolver: GqlResolvers = { if (isAdmin(user)) { await deleteAdmin(user) } + + if (isMentor(user)) { + await deleteMentor(user) + } }) ) @@ -129,6 +137,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..5d2615e9 --- /dev/null +++ b/packages/backend/src/resolvers/mentor.resolver.ts @@ -0,0 +1,21 @@ +import { GqlResolvers, Mentor, MentorContext } from '@lara/api' + +import { alexaSkillLinked } from '../services/alexa.service' +import { username } from '../services/user.service' +import { parseISODateString } from '../utils/date' +import { papersByMentor } from '../repositories/paper.repo' + +export const mentorResolver: GqlResolvers = { + Mentor: { + username, + 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..2e062b81 --- /dev/null +++ b/packages/backend/src/resolvers/paper.resolver.ts @@ -0,0 +1,35 @@ +import { AuthenticatedContext, GqlPaperEntryInput, GqlResolvers } from '@lara/api' +import { generatePaper, generatePaperEntry } from '../services/paper.service' +import { deletePaper, papersByTrainer, savePaper, updatePaper } from '../repositories/paper.repo' +import { GraphQLError } from 'graphql' + +export const paperResolver: GqlResolvers = { + 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', 'feedback', '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) + }, + }, +} 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..be2ce921 100644 --- a/packages/backend/src/resolvers/trainer.resolver.ts +++ b/packages/backend/src/resolvers/trainer.resolver.ts @@ -1,12 +1,16 @@ 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, invokePrintLambda, savePrintData } from '../services/print.service' +import { mentorById } from '../repositories/mentor.repo' +import { trainerById } from '../repositories/trainer.repo' export const trainerResolver: GqlResolvers = { Trainer: { @@ -14,6 +18,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 +53,62 @@ export const trainerResolver: GqlResolvers = { return report }, + printPaper: async (_parent, { ids }, { currentUser }) => { + const paper = await paperById(ids[0]) + const data = [] + let trainee: Trainee | undefined + let mentor: Mentor | Trainer | undefined + if (paper) { + data.push(createPrintPaperData(paper)) + 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, + }) + + await invokePrintLambda({ + printDataHash: traineeHash, + }) + + userData = await createPrintUserData(mentor!) + + const mentorHash = await savePrintData({ + data, + userData, + printTranslations, + emailTranslations, + }) + + await invokePrintLambda({ + printDataHash: mentorHash, + }) + + userData = await createPrintUserData(currentUser) + + const trainerHash = await savePrintData({ + data, + userData, + printTranslations, + emailTranslations, + }) + + await invokePrintLambda({ + printDataHash: trainerHash, + }) + + return { + estimatedWaitingTime: Math.round(1.5 + 5), + } + }, }, Mutation: { claimTrainee: async (_parent, { id }, { 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..4bd13764 --- /dev/null +++ b/packages/backend/src/services/paper.service.ts @@ -0,0 +1,17 @@ +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)), + } +} diff --git a/packages/backend/src/services/print.service.ts b/packages/backend/src/services/print.service.ts index c601619d..b4babc93 100644 --- a/packages/backend/src/services/print.service.ts +++ b/packages/backend/src/services/print.service.ts @@ -5,15 +5,21 @@ 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' @@ -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,44 @@ 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): PrintPaper => { + return { + status: paper.status, + briefing: transformPaperForm(paper.briefing), + feedback: transformPaperForm(paper.feedback), + 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 +173,19 @@ 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): PrintPaperData => { + return { + filename: createPaperPDFName(paper), + paper: transformPaper(paper), + } +} + export const savePrintData = async (printData: PrintData): Promise => { const generatedKey = hash(printData) + '.json' 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..9c2c4694 --- /dev/null +++ b/packages/backend/src/test/paper.service.test.ts @@ -0,0 +1,67 @@ +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', + }, + ], + feedback: [], + } + + 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/fab.tsx b/packages/components/src/fab.tsx index 78a6b92f..02c8c324 100644 --- a/packages/components/src/fab.tsx +++ b/packages/components/src/fab.tsx @@ -17,7 +17,9 @@ const dangerStyles = css` } ` -const StyledFab = styled.button` +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..9606ceb2 100644 --- a/packages/components/src/icon-definitions.ts +++ b/packages/components/src/icon-definitions.ts @@ -48,10 +48,13 @@ 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' export const Icons = { Arrow: IconArrow, Archive: IconArchive, + Blank: IconBlank, Bulb: IconBulb, BurgerMenu: IconMenu, Camera: IconCamera, @@ -62,6 +65,7 @@ export const Icons = { ChevronLeft: IconChevronLeft, ChevronRight: IconChevronRight, CircleLoader: IconCircleLoader, + CheckMark: IconCheckMark, Claim: IconClaim, CloudUpload: IconCloudUpload, Comment: IconMessageDetails, 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/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..b80e1a57 --- /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} + + {firstNameMentorInput} + + {lastNameMentorInput} + + {emailMentorInput} + + {emptyFieldMentor} + + {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..58553bfe 100644 --- a/packages/components/src/print/day.ts +++ b/packages/components/src/print/day.ts @@ -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/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/dev-role-dropdown.tsx b/packages/frontend/src/components/dev-role-dropdown.tsx index 8d165d0e..9c6d6542 100644 --- a/packages/frontend/src/components/dev-role-dropdown.tsx +++ b/packages/frontend/src/components/dev-role-dropdown.tsx @@ -27,7 +27,9 @@ const Label = styled.label` margin-right: 4px; ` -const Selected = styled.div<{ open: boolean }>` +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..0a8a4052 --- /dev/null +++ b/packages/frontend/src/components/paper-create-form.tsx @@ -0,0 +1,241 @@ +import React 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 } 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 { + register, + handleSubmit, + formState: { errors }, + } = useForm() + + const onSubmit = handleSubmit((formdata) => { + 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 ( + + ) + })} + + + } + firstNameMentorInput={ + <> + + {strings.paper.createBriefing.firstnameMentor} + + + + } + emptyFieldTrainee={<>} + lastNameMentorInput={ + <> + + {strings.paper.createBriefing.lastnameMentor} + + + + } + emailMentorInput={ + <> + + {strings.paper.createBriefing.emailMentor} + + + + } + 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..031930ca --- /dev/null +++ b/packages/frontend/src/components/paper-text-input.tsx @@ -0,0 +1,130 @@ +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 : '', + }) + } + + 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..4750d37a 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']; @@ -145,6 +161,32 @@ 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; + username: Scalars['String']['output']; +}; + +export type MentorInput = { + email?: InputMaybe; + name?: InputMaybe; + signature?: InputMaybe; +}; + export type MutateEntryPayload = { __typename?: 'MutateEntryPayload'; day: Day; @@ -152,6 +194,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 +217,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 +237,14 @@ 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; /** Get Avatar Bucket Upload URL */ getAvatarSignedUrl?: Maybe; + /** Get a User by Email */ + getUserByEmail?: Maybe; /** Link Alexa account */ linkAlexa?: Maybe; /** Login via microsoft */ @@ -216,6 +275,12 @@ export type Mutation = { updateDay?: Maybe; updateEntry: MutateEntryPayload; updateEntryOrder: MutateEntryPayload; + /** 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 +337,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 +388,26 @@ export type MutationDeleteEntryArgs = { }; +export type MutationDeletePaperArgs = { + paperId: Scalars['ID']['input']; +}; + + +export type MutationDeletePaperEntryArgs = { + 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 +499,22 @@ export type MutationUpdateEntryOrderArgs = { }; +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,6 +541,83 @@ export type OAuthPayload = { refreshToken?: Maybe; }; +export type Paper = { + __typename?: 'Paper'; + archivedAt?: Maybe; + briefing: Array; + client: Scalars['String']['output']; + conclusion?: Maybe; + createdAt?: Maybe; + feedback: 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 PaperEntryInput = { + answer?: InputMaybe; + hint?: InputMaybe; + id: Scalars['ID']['input']; + question: Scalars['String']['input']; + questionId: Scalars['ID']['input']; +}; + +export type PaperFormData = { + __typename?: 'PaperFormData'; + answer?: Maybe; + hint?: Maybe; + id: Scalars['ID']['output']; + question: Scalars['String']['output']; + questionId: Scalars['ID']['output']; +}; + +export type PaperInput = { + briefing: Array; + client: Scalars['String']['input']; + feedback: 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', + TraineeDone = 'TraineeDone' +} + +export type PaperUpdateInput = { + briefing: Array; + client: Scalars['String']['input']; + feedback: 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']; @@ -454,8 +642,12 @@ export type Query = { currentUser?: Maybe; /** Get a User by ID */ getUser?: Maybe; + /** Get all Trainers */ + 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. */ @@ -481,6 +673,11 @@ export type QueryPrintArgs = { }; +export type QueryPrintPaperArgs = { + ids: Array; +}; + + export type QueryReportForTraineeArgs = { id: Scalars['ID']['input']; week: Scalars['Int']['input']; @@ -549,6 +746,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 +767,7 @@ export type Trainer = UserInterface & { language?: Maybe; lastName: Scalars['String']['output']; notification?: Maybe; + papers?: Maybe>>; signature?: Maybe; theme?: Maybe; trainees: Array; @@ -597,6 +796,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,6 +850,8 @@ 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 */ @@ -656,7 +865,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 +895,11 @@ export type CreateCommentOnDayMutationVariables = Exact<{ }>; +<<<<<<< HEAD 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, 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' } } }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type CreateCommentOnEntryMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -695,7 +908,11 @@ export type CreateCommentOnEntryMutationVariables = Exact<{ }>; +<<<<<<< HEAD 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, 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' } } }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type CreateCommentOnReportMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -704,7 +921,11 @@ export type CreateCommentOnReportMutationVariables = Exact<{ }>; +<<<<<<< HEAD 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, 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 } }> } } }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type CreateEntryMutationVariables = Exact<{ dayId: Scalars['String']['input']; @@ -714,11 +935,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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } }; + export type CreateTraineeMutationVariables = Exact<{ input: CreateTraineeInput; }>; @@ -753,7 +988,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']; @@ -789,13 +1024,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 }>, feedback: 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,6 +1058,7 @@ export type MarkUserForDeleteMutationVariables = Exact<{ }>; +<<<<<<< HEAD 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 PublishAllCommentsMutationVariables = Exact<{ @@ -818,13 +1068,16 @@ 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 MarkUserForDeleteMutation = { __typename?: 'Mutation', markUserForDeletion?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) 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,13 +1096,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']; }>; +<<<<<<< HEAD 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 UpdateAdminMutationVariables = Exact<{ @@ -889,6 +1143,9 @@ 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 UnmarkUserForDeleteMutation = { __typename?: 'Mutation', unmarkUserForDeletion?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type UpdateEntryOrderMutationVariables = Exact<{ entryId: Scalars['ID']['input']; @@ -907,6 +1164,21 @@ export type UpdateEntryMutationVariables = Exact<{ export type UpdateEntryMutation = { __typename?: 'Mutation', updateEntry: { __typename?: 'MutateEntryPayload', entry?: { __typename?: 'Entry', id: string, time: number, text: string } | undefined } }; +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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, answer?: string | undefined, hint?: string | undefined }> } }; + export type UpdateReportReportReviewPageMutationVariables = Exact<{ id: Scalars['ID']['input']; summary?: InputMaybe; @@ -943,10 +1215,17 @@ export type UpdateTrainerMutationVariables = Exact<{ export type UpdateTrainerMutation = { __typename?: 'Mutation', updateTrainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | undefined }; +<<<<<<< HEAD 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 }> }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type AdminTraineesPageQueryVariables = Exact<{ [key: string]: never; }>; @@ -966,17 +1245,21 @@ export type AlexaLinkingUrlQuery = { __typename?: 'Query', alexaLinkingUrl?: str export type ArchivePageDataQueryVariables = Exact<{ [key: string]: never; }>; +<<<<<<< HEAD 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, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time: number, text: string }> }> } | undefined> }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) 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 +1269,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 } | { __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 DashboardPageDataQueryVariables = Exact<{ currentYear: Scalars['Int']['input']; @@ -994,34 +1277,56 @@ export type DashboardPageDataQueryVariables = Exact<{ }>; +<<<<<<< HEAD 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, 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, 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 }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) 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; }>; +<<<<<<< HEAD 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, username: string } | { __typename?: 'Mentor', id: string, type: UserTypeEnum, firstName: string, lastName: string, username: string } | { __typename?: 'Trainee', id: string, type: UserTypeEnum, firstName: string, lastName: string, username: string } | { __typename?: 'Trainer', id: string, type: UserTypeEnum, firstName: string, lastName: string, username: string } | undefined }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type UserPageQueryVariables = Exact<{ id: Scalars['ID']['input']; }>; +<<<<<<< HEAD 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', 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 }; + +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, theme?: string | undefined } | { __typename?: 'Mentor', id: string, theme?: 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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined } | undefined }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) 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 PrintDataQueryVariables = Exact<{ ids: Array | Scalars['ID']['input']; @@ -1030,13 +1335,24 @@ export type PrintDataQueryVariables = Exact<{ export type PrintDataQuery = { __typename?: 'Query', print: { __typename?: 'PrintPayload', estimatedWaitingTime: number } }; +export type PrintPaperDataQueryVariables = Exact<{ + ids: Array | Scalars['ID']['input']; +}>; + + +export type PrintPaperDataQuery = { __typename?: 'Query', printPaper: { __typename?: 'PrintPayload', estimatedWaitingTime: number } }; + export type ReportPageDataQueryVariables = Exact<{ year: Scalars['Int']['input']; week: Scalars['Int']['input']; }>; +<<<<<<< HEAD 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, username: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainee', startOfToolUsage?: string | undefined, endOfToolUsage?: string | undefined, id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, username: 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, 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, 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, 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 }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type ReportReviewPageDataQueryVariables = Exact<{ year: Scalars['Int']['input']; @@ -1045,17 +1361,21 @@ export type ReportReviewPageDataQueryVariables = Exact<{ }>; +<<<<<<< HEAD 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, username: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, username: 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, 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, 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, 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 }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) 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 +1385,40 @@ export type SuggestionsDataQuery = { __typename?: 'Query', suggestions: Array<{ export type TraineePageDataQueryVariables = Exact<{ [key: string]: never; }>; +<<<<<<< HEAD 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, username: 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 }>, feedback: 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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | 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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | { __typename?: 'Trainer' } | undefined }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) 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', username: string, 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 }>, feedback: 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; }>; +<<<<<<< HEAD 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', username: string, 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 }; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type TrainersPageQueryVariables = Exact<{ [key: string]: never; }>; @@ -1252,6 +1595,25 @@ export function useCreateEntryMutation(baseOptions?: Apollo.MutationHookOptions< return Apollo.useMutation(CreateEntryDocument, options); } export type CreateEntryMutationHookResult = ReturnType; +export const CreateMentorDocument = gql` + mutation CreateMentor($input: CreateMentorInput!) { + createMentor(input: $input) { + id + firstName + lastName + startDate + endDate + email + type + deleteAt + } +} + `; +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 @@ -1262,6 +1624,42 @@ export function useCreateOAuthCodeMutation(baseOptions?: Apollo.MutationHookOpti 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 + } + feedback { + id + questionId + question + answer + hint + } + } +} + `; +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) { @@ -1441,6 +1839,84 @@ export function useDeleteEntryMutation(baseOptions?: Apollo.MutationHookOptions< 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 + } + feedback { + 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) { @@ -1753,6 +2229,58 @@ export function useUpdateEntryMutation(baseOptions?: Apollo.MutationHookOptions< return Apollo.useMutation(UpdateEntryDocument, options); } export type UpdateEntryMutationHookResult = 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 + } + feedback { + id + questionId + answer + hint + } + } +} + `; +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( @@ -1838,16 +2366,28 @@ export function useUpdateTrainerMutation(baseOptions?: Apollo.MutationHookOption return Apollo.useMutation(UpdateTrainerDocument, options); } export type UpdateTrainerMutationHookResult = ReturnType; +<<<<<<< HEAD export const AdminAdminsPageDocument = gql` query AdminAdminsPage { admins { id firstName lastName +======= +export const AdminMentorPageDocument = gql` + query AdminMentorPage { + mentors { + id + firstName + lastName + startDate + endDate +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) deleteAt } } `; +<<<<<<< HEAD export function useAdminAdminsPageQuery(baseOptions?: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} return Apollo.useQuery(AdminAdminsPageDocument, options); @@ -1863,6 +2403,23 @@ export function useAdminAdminsPageSuspenseQuery(baseOptions?: Apollo.SkipToken | export type AdminAdminsPageQueryHookResult = ReturnType; export type AdminAdminsPageLazyQueryHookResult = ReturnType; export type AdminAdminsPageSuspenseQueryHookResult = ReturnType; +======= +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; +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export const AdminTraineesPageDocument = gql` query AdminTraineesPage { trainees { @@ -2246,8 +2803,15 @@ export const UserPageDocument = gql` lastName } } +<<<<<<< HEAD ... on Admin { deleteAt +======= + ... on Mentor { + deleteAt + startDate + endDate +>>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) } } companies { @@ -2274,6 +2838,84 @@ export function useUserPageSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo export type UserPageQueryHookResult = ReturnType; export type UserPageLazyQueryHookResult = ReturnType; export type UserPageSuspenseQueryHookResult = 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 + theme + ... on Mentor { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + id + questionId + question + answer + hint + } + } + } + } +} + `; +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 { @@ -2345,6 +2987,28 @@ export function usePrintDataSuspenseQuery(baseOptions?: Apollo.SkipToken | Apoll export type PrintDataQueryHookResult = ReturnType; export type PrintDataLazyQueryHookResult = ReturnType; export type PrintDataSuspenseQueryHookResult = ReturnType; +export const PrintPaperDataDocument = gql` + query PrintPaperData($ids: [ID!]!) { + printPaper(ids: $ids) { + estimatedWaitingTime + } +} + `; +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 { @@ -2596,6 +3260,33 @@ export const TraineePageDataDocument = gql` firstName lastName } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + id + questionId + question + answer + hint + } + } company { id name @@ -2621,6 +3312,108 @@ export function useTraineePageDataSuspenseQuery(baseOptions?: Apollo.SkipToken | 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 + } + feedback { + id + questionId + question + answer + hint + } + } + } + } +} + `; +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 + } + feedback { + 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 { @@ -2659,6 +3452,63 @@ export function useTraineeSettingsDataSuspenseQuery(baseOptions?: Apollo.SkipTok export type TraineeSettingsDataQueryHookResult = ReturnType; export type TraineeSettingsDataLazyQueryHookResult = ReturnType; export type TraineeSettingsDataSuspenseQueryHookResult = ReturnType; +export const TrainerPaperPageDataDocument = gql` + query TrainerPaperPageData { + currentUser { + id + ... on Trainer { + trainees { + username + firstName + lastName + id + } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + 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 { 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..8484ffcb --- /dev/null +++ b/packages/frontend/src/graphql/mutations/create-paper.gql @@ -0,0 +1,29 @@ +mutation createPaper($input: PaperInput!) { + createPaper(input: $input) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + 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..87c86fb3 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/delete-paper.gql @@ -0,0 +1,27 @@ +mutation deletePaper($paperId: ID!) { + deletePaper(paperId: $paperId) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + answer + hint + } + feedback { + 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/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..a335e6f8 --- /dev/null +++ b/packages/frontend/src/graphql/mutations/update-paper.gql @@ -0,0 +1,27 @@ +mutation updatePaper($input: PaperUpdateInput!) { + updatePaper(input: $input) { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + answer + hint + } + feedback { + id + questionId + answer + hint + } + } +} 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/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/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..2f0aae16 --- /dev/null +++ b/packages/frontend/src/graphql/queries/mentor-paper-page-data.gql @@ -0,0 +1,35 @@ +query MentorPaperPageData { + currentUser { + id + theme + ... on Mentor { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + id + questionId + question + answer + hint + } + } + } + } +} 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..8f071051 --- /dev/null +++ b/packages/frontend/src/graphql/queries/print-paper-data.gql @@ -0,0 +1,5 @@ +query PrintPaperData($ids: [ID!]!) { + printPaper(ids: $ids) { + estimatedWaitingTime + } +} diff --git a/packages/frontend/src/graphql/queries/trainee-page-data.gql b/packages/frontend/src/graphql/queries/trainee-page-data.gql index ad88c855..e2b4aed7 100644 --- a/packages/frontend/src/graphql/queries/trainee-page-data.gql +++ b/packages/frontend/src/graphql/queries/trainee-page-data.gql @@ -10,6 +10,33 @@ query TraineePageData { firstName lastName } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + 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..58b8c827 --- /dev/null +++ b/packages/frontend/src/graphql/queries/trainee-paper-page-data.gql @@ -0,0 +1,34 @@ +query TraineePaperPageData { + currentUser { + id + ... on Trainee { + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + id + questionId + question + answer + hint + } + } + } + } +} 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..198b44e6 --- /dev/null +++ b/packages/frontend/src/graphql/queries/trainee-paper.gql @@ -0,0 +1,34 @@ +query TraineePaperData { + currentUser { + ... on Trainee { + id + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + 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..3b1b2dc9 --- /dev/null +++ b/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql @@ -0,0 +1,40 @@ +query TrainerPaperPageData { + currentUser { + id + ... on Trainer { + trainees { + username + firstName + lastName + id + } + papers { + id + traineeId + trainerId + client + mentorId + periodStart + periodEnd + schoolPeriodStart + schoolPeriodEnd + subject + status + briefing { + id + questionId + question + answer + hint + } + feedback { + 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..d1cccfe6 --- /dev/null +++ b/packages/frontend/src/helper/paper-helper.ts @@ -0,0 +1,22 @@ +import { PaperStatus } from '../graphql' + +export type Question = { question: string; hint: string } + +export const mapStatusToProgess = (status: PaperStatus): number => { + switch (status) { + case 'NotStarted': + return 0 + case 'InProgress': + return 0.3 + case 'TraineeDone': + return 0.6 + case 'MentorDone': + return 0.6 + default: + return 0 + } +} + +export const isPaperFeatureEnabled = (): boolean => { + return ENVIRONMENT.nodeEnv === 'development' || ENVIRONMENT.nodeEnv === 'staging' +} diff --git a/packages/frontend/src/hooks/use-fetch-pdf.ts b/packages/frontend/src/hooks/use-fetch-pdf.ts index d430b549..4d6f4412 100644 --- a/packages/frontend/src/hooks/use-fetch-pdf.ts +++ b/packages/frontend/src/hooks/use-fetch-pdf.ts @@ -1,10 +1,11 @@ import { useState } from 'react' -import { Report, usePrintDataLazyQuery } from '../graphql' +import { Paper, Report, usePrintDataLazyQuery, usePrintPaperDataLazyQuery } from '../graphql' import strings from '../locales/localization' import { useToastContext } from './use-toast-context' type UseFetchPdfPayload = [(reports: Pick[]) => void, boolean] +type UseFetchPaperPdfPayload = [(paper: Pick) => void, boolean] export const useFetchPdf = (): UseFetchPdfPayload => { const [loading, setLoading] = useState(false) @@ -29,3 +30,27 @@ export const useFetchPdf = (): UseFetchPdfPayload => { loading, ] } + +export const useFetchPaperPdf = (): UseFetchPaperPdfPayload => { + 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 [ + (paper) => { + setLoading(true) + fetchPrintPaperData({ variables: { ids: [paper.id] } }).catch((error) => { + console.log(error) + }) + }, + loading, + ] +} diff --git a/packages/frontend/src/locales/de.ts b/packages/frontend/src/locales/de.ts index 10579dfa..1135864e 100644 --- a/packages/frontend/src/locales/de.ts +++ b/packages/frontend/src/locales/de.ts @@ -13,10 +13,11 @@ const germanTranslation: Translation = { companyPick: 'Bitte wähle deine Firma:', continue: 'Weiter', save: 'Speichern', - edit: 'bearbeiten', - done: 'fertig', + edit: 'Bearbeiten', + done: 'Fertig', markDelete: 'für Löschung markieren', unmarkDelete: 'Löschmarkierung aufheben', + deleteAt: 'Löschen nach', cancel: 'Abbrechen', deactivate: 'Deaktivieren', traineeShipYear: 'Jahr der Ausbildung', @@ -24,6 +25,7 @@ const germanTranslation: Translation = { back: 'zurück', on: 'an', off: 'aus', + start: 'Starten', login: { userNotRegisteredError: { title: 'Fehler bei der Anmeldung', @@ -48,6 +50,139 @@ 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', + }, + feedbackQuestions: { + descriptionOfActivities: { + question: 'Berschreibung 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: 'Feedaback 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.', + }, + }, + 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', + }, + }, archivePage: { header: 'Archiv', tableHead: { @@ -330,7 +465,9 @@ const germanTranslation: Translation = { trainees: 'Auszubildende', trainer: 'Ausbilder', admin: 'Admins', + mentor: 'Ausbildungsbeauftragte', dashhboard: 'Dashboard', + paper: 'Paper', archive: 'Archiv', settings: 'Einstellungen', wiki: 'Wiki', @@ -412,12 +549,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..6d604c82 100644 --- a/packages/frontend/src/locales/en.ts +++ b/packages/frontend/src/locales/en.ts @@ -18,12 +18,14 @@ const englishTranslation: Translation = { done: 'done', 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 +47,136 @@ 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', + }, + 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', + }, + }, archivePage: { header: 'Archive', tableHead: { @@ -324,6 +456,8 @@ const englishTranslation: Translation = { trainees: 'Trainees', trainer: 'Trainer', admin: 'Admins', + mentor: 'mentor', + paper: 'Paper', dashhboard: 'Dashboard', archive: 'Archive', settings: 'Settings', @@ -406,12 +540,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..fe67290a 100644 --- a/packages/frontend/src/locales/translation.ts +++ b/packages/frontend/src/locales/translation.ts @@ -16,12 +16,14 @@ export default interface Translation { done: 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 +45,130 @@ export default interface Translation { reportToArciveAddedSuccessTitle: string reportToArciveAddedSuccess: string } + paper: { + 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 + } + 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 + } + } + 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 +440,8 @@ export default interface Translation { trainees: string trainer: string admin: string + mentor: string + paper: string dashhboard: string archive: string settings: string @@ -384,11 +512,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/mentor-paper-page.tsx b/packages/frontend/src/pages/mentor-paper-page.tsx new file mode 100644 index 00000000..ddb27403 --- /dev/null +++ b/packages/frontend/src/pages/mentor-paper-page.tsx @@ -0,0 +1,104 @@ +import { Container, H1, Paragraph, Spacer, StyledIcon, Text } from '@lara/components' +import React from 'react' +import { Template } from '../templates/template' +import { useMentorPaperPageDataQuery } from '../graphql' +import { Mentor } from '@lara/api' +import { Box, Flex } from '@lara/components' +import strings from '../locales/localization' +import ProgressBar from '../components/progress-bar' +import Loader from '../components/loader' + +export const MentorPaperPage: React.FC = () => { + const { loading, data } = useMentorPaperPageDataQuery() + + if (!data) { + return ( + + ) + } + + const currentUser = data?.currentUser as Mentor + + if (!currentUser) { + return ( + + ) + } + + 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..b4854167 --- /dev/null +++ b/packages/frontend/src/pages/paper-briefing-page.tsx @@ -0,0 +1,255 @@ +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'), + feedback: paper ? omitDeep(paper.feedback, '__typename') : [], + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + periodEnd: paper?.periodEnd, + periodStart: paper?.periodStart, + schoolPeriodEnd: paper?.schoolPeriodEnd, + schoolPeriodStart: paper?.schoolPeriodStart, + 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'), + feedback: paper?.feedback ?? [], + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + 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: { + 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..b19f78a9 --- /dev/null +++ b/packages/frontend/src/pages/paper-create-briefing-page.tsx @@ -0,0 +1,139 @@ +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: [], + feedback: [], + 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/trainee-paper-feedback-page.tsx b/packages/frontend/src/pages/trainee-paper-feedback-page.tsx new file mode 100644 index 00000000..9a875c57 --- /dev/null +++ b/packages/frontend/src/pages/trainee-paper-feedback-page.tsx @@ -0,0 +1,187 @@ +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.feedback.length > 0 && paperFeedback.length == 0) { + setPaperFeedback(paper.feedback) + setFilledFromSave(true) + } + }, [filledFromSave, paper, paperFeedback]) + + if (!currentUser) { + return null + } + + console.log(paperFeedback) + + const savePaper = async (paperFeedback: PaperFormData[]) => { + await updatePaperMutation({ + variables: { + input: { + briefing: paper ? omitDeep(paper.briefing, '__typename') : [], + feedback: omitDeep(paperFeedback, '__typename'), + client: paper?.client ?? '', + id: paperId ?? '', + mentorId: paper?.mentorId ?? '', + 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[]) => { + await updatePaperMutation({ + variables: { + input: { + briefing: paper ? omitDeep(paper.briefing, '__typename') : [], + feedback: omitDeep(paperFeedback, '__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, + }, + }, + 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..7beabd4a --- /dev/null +++ b/packages/frontend/src/pages/trainee-paper-page.tsx @@ -0,0 +1,132 @@ +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 { PaperStatus, useTraineePageDataQuery } 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 } = useTraineePageDataQuery() + const navigate = useNavigate() + + const navigateToPaperFeedbackPage = (paperId: string) => { + navigate('/paper/feedback/' + paperId) + } + + if (!data) { + return ( + + ) + } + + const { currentUser } = data + if (!currentUser) { + return ( + + ) + } + + 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..805c86fa --- /dev/null +++ b/packages/frontend/src/pages/trainer-paper-page.tsx @@ -0,0 +1,269 @@ +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) + } + + return ( + + ) +} diff --git a/packages/frontend/src/routes.tsx b/packages/frontend/src/routes.tsx index c4dd88b2..3456508a 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,25 @@ 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 { isPaperFeatureEnabled } from './helper/paper-helper' type RoutesProps = { currentUser?: | Pick | (Pick & { trainees: Pick[] }) | Pick + | Pick } const AppRoutes: React.FunctionComponent = ({ currentUser }) => { @@ -73,8 +82,17 @@ const AppRoutes: React.FunctionComponent = ({ currentUser }) => { } /> } /> } /> + } /> + {isWikiFeatureEnabled() && } />} + + {isPaperFeatureEnabled() && ( + <> + } /> + } /> + + )} ) : ( } /> @@ -90,7 +108,22 @@ const AppRoutes: React.FunctionComponent = ({ currentUser }) => { } /> } /> } /> + } /> + {isPaperFeatureEnabled() && ( + <> + } /> + } /> + } /> + + )} + + )} + + {/* Mentor Routes */} + {currentUser.type === UserTypeEnum.Mentor && currentUser.__typename === 'Mentor' && ( + <> + } /> )} @@ -104,6 +137,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..4ca69087 100644 --- a/packages/print/src/handler.ts +++ b/packages/print/src/handler.ts @@ -4,10 +4,10 @@ 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, EmailType, 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 +20,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) @@ -43,12 +43,12 @@ export const handler: Handler = async (payloa const exportData = await getExport(payload.printDataHash) - if (!exportData || exportData.reportsData.length === 0) { + if (!exportData || exportData.data.length === 0) { return 'error' } let browser: Browser | undefined - const { reportsData, userData, printTranslations, emailTranslations } = exportData + const { data, userData, printTranslations, emailTranslations } = exportData const headlessMode: boolean | 'shell' = IS_OFFLINE ? true : 'shell' @@ -63,16 +63,24 @@ export const handler: Handler = async (payloa // create empty browser page const page = await browser.newPage() - const isSingleExport = reportsData.length === 1 + const isSingleExport = data.length === 1 let outputFile: Buffer | undefined let filename = '' - + let emailType: EmailType = 'reportExport' + let isPaper = false if (isSingleExport) { - const [data] = reportsData - - outputFile = await createPDF(data, userData, printTranslations, page) - filename = data.filename + isPaper = data[0].filename.includes('Paper') + if (isPaper) { + const [paperData] = data as PrintPaperData[] + emailType = 'paperBriefing' + outputFile = await createPaperPDF(paperData, userData, printTranslations, page) + filename = paperData.filename + } else { + const [reportData] = data as PrintReportData[] + outputFile = await createPDF(reportData, userData, printTranslations, page) + filename = reportData.filename + } } else { outputFile = await generateBatch(exportData, page) filename = `batch-export-${new Date().getTime()}.zip` @@ -84,8 +92,44 @@ export const handler: Handler = async (payloa await saveAttachments(filename, outputFile) + if (isPaper) { + if (userData.type == 'Trainee') { + const emailTraineePayload: EmailPayload = { + emailType: emailType, + 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(emailTraineePayload), + }) + } else { + const emailMentorPayload: EmailPayload = { + emailType: emailType, + 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(emailMentorPayload), + }) + } + } + const emailPayload: EmailPayload = { - emailType: 'reportExport', + emailType, attachments: [{ filename }], userData: { receiverEmail: userData.receiverEmail, diff --git a/packages/print/src/mock.ts b/packages/print/src/mock.ts index 6fd9f44c..7234aabf 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,11 @@ export const DUMMY_DATA: PrintData = { thursday: 'Donnerstag', friday: 'Freitag', hello: 'Hallo', + client: 'Kunde', + mentor: 'Ausbildungsbeauftragter', + trainer: 'Ausbilder', + trainee: 'Auszubildender', + briefing: 'Briefing', }, emailTranslations: { hello: 'Hallo {{ USER }},', @@ -135,6 +140,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 +152,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 +169,193 @@ 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', + 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: '1', + answer: 'Test Antwort', + question: 'Gegenstand der Arbeit', + hint: 'Nenne hier bitte kurz die allgemeine Tätigkeit/Aufgabe, welche Inhalt der Projektstation ist.', + }, + { + id: '3', + 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: '1', + questionId: '2', + answer: 'Test Antwort', + question: 'Vorgehen', + hint: 'Nenne hier bitte unter welchen Rahmenbedingungen die Projektstation für den Azubi aufgebaut sein soll.', + }, + { + 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.', + }, + { + id: '1', + questionId: '3', + answer: 'Test Antwort', + question: 'Lerninhalte Station', + hint: 'Nenne hier welche allgemeinen Inhalte dem Azubi während dem Projekt Zeitraum vermittelt werden sollen.', + }, + { + id: '1', + questionId: '4', + answer: 'Test Antwort', + 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.', + }, + { + id: '2', + questionId: '4', + answer: 'Test Antwort', + 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.', + }, + { + id: '3', + questionId: '4', + answer: 'Test Antwort', + question: 'Test Frage', + hint: 'Test Hinweis', + }, + ], + feedback: [ + { + id: '3', + questionId: '4', + answer: 'Test Antwort', + question: 'Test Frage', + hint: 'Test Hinweis', + }, + ], + 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: 'Trainee 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', + }, + 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 +365,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..bfd46f04 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, @@ -144,3 +150,63 @@ export const Template: React.FC = ({ ) } + +export const PaperTemplate: React.FC = ({ + userData: { firstName, lastName, course }, + paper, + i18n, +}) => { + return ( + + + + + + + + {i18n.trainee}: + {firstName} {lastName} + + + {i18n.apprenticeCourse}: + {course} + + + {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} + + ) + })} +
    +
    + ) +} 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: From c1e8eff0d0c7171e7ffbae86cc4cf48c0c1204d8 Mon Sep 17 00:00:00 2001 From: alexander-schefe Date: Wed, 8 Oct 2025 09:43:39 +0200 Subject: [PATCH 02/11] chore: rebase onto main --- packages/api/schema.gql | 1 - packages/api/src/graphql.ts | 4 +- .../backend/src/resolvers/mentor.resolver.ts | 2 - packages/frontend/src/graphql/index.tsx | 132 +++++------------- .../queries/trainer-paper-page-data.gql | 1 - 5 files changed, 37 insertions(+), 103 deletions(-) diff --git a/packages/api/schema.gql b/packages/api/schema.gql index c82ce191..9c5a7e78 100644 --- a/packages/api/schema.gql +++ b/packages/api/schema.gql @@ -644,7 +644,6 @@ type Mentor implements UserInterface { papers: [Paper] startDate: String endDate: String - username: String! email: String! deleteAt: String alexaSkillLinked: Boolean diff --git a/packages/api/src/graphql.ts b/packages/api/src/graphql.ts index bac514e8..ec9895c5 100644 --- a/packages/api/src/graphql.ts +++ b/packages/api/src/graphql.ts @@ -179,7 +179,6 @@ export type GqlMentor = GqlUserInterface & { startDate?: Maybe; theme?: Maybe; type: GqlUserTypeEnum; - username: Scalars['String']['output']; }; export type GqlMentorInput = { @@ -642,7 +641,7 @@ export type GqlQuery = { currentUser?: Maybe; /** Get a User by ID */ getUser?: Maybe; - /** Get all Trainers */ + /** Get all Mentors */ mentors: Array; /** Print single report or report batch */ print: GqlPrintPayload; @@ -1137,7 +1136,6 @@ export type GqlMentorResolvers, ParentType, ContextType>; theme?: Resolver, ParentType, ContextType>; type?: Resolver; - username?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }>; diff --git a/packages/backend/src/resolvers/mentor.resolver.ts b/packages/backend/src/resolvers/mentor.resolver.ts index 5d2615e9..6fcece71 100644 --- a/packages/backend/src/resolvers/mentor.resolver.ts +++ b/packages/backend/src/resolvers/mentor.resolver.ts @@ -1,13 +1,11 @@ import { GqlResolvers, Mentor, MentorContext } from '@lara/api' import { alexaSkillLinked } from '../services/alexa.service' -import { username } from '../services/user.service' import { parseISODateString } from '../utils/date' import { papersByMentor } from '../repositories/paper.repo' export const mentorResolver: GqlResolvers = { Mentor: { - username, alexaSkillLinked, deleteAt: (model) => model.endDate, papers: async (model) => { diff --git a/packages/frontend/src/graphql/index.tsx b/packages/frontend/src/graphql/index.tsx index 4750d37a..16d1905f 100644 --- a/packages/frontend/src/graphql/index.tsx +++ b/packages/frontend/src/graphql/index.tsx @@ -178,7 +178,6 @@ export type Mentor = UserInterface & { startDate?: Maybe; theme?: Maybe; type: UserTypeEnum; - username: Scalars['String']['output']; }; export type MentorInput = { @@ -642,7 +641,7 @@ export type Query = { currentUser?: Maybe; /** Get a User by ID */ getUser?: Maybe; - /** Get all Trainers */ + /** Get all Mentors */ mentors: Array; /** Print single report or report batch */ print: PrintPayload; @@ -895,11 +894,7 @@ export type CreateCommentOnDayMutationVariables = Exact<{ }>; -<<<<<<< HEAD -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, 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' } } }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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']; @@ -908,11 +903,7 @@ export type CreateCommentOnEntryMutationVariables = Exact<{ }>; -<<<<<<< HEAD -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, 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' } } }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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']; @@ -921,11 +912,7 @@ export type CreateCommentOnReportMutationVariables = Exact<{ }>; -<<<<<<< HEAD -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, 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 } }> } } }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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']; @@ -997,7 +984,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']; @@ -1006,7 +993,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']; @@ -1015,7 +1002,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']; @@ -1058,8 +1045,7 @@ export type MarkUserForDeleteMutationVariables = Exact<{ }>; -<<<<<<< HEAD -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 PublishAllCommentsMutationVariables = Exact<{ id: Scalars['ID']['input']; @@ -1067,10 +1053,7 @@ 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 MarkUserForDeleteMutation = { __typename?: 'Mutation', markUserForDeletion?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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; @@ -1103,8 +1086,7 @@ export type UnmarkUserForDeleteMutationVariables = Exact<{ }>; -<<<<<<< HEAD -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; @@ -1122,7 +1104,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']; @@ -1132,7 +1114,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']; @@ -1142,10 +1124,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 UnmarkUserForDeleteMutation = { __typename?: 'Mutation', unmarkUserForDeletion?: { __typename?: 'Admin', id: string } | { __typename?: 'Mentor', id: string } | { __typename?: 'Trainee', deleteAt?: string | undefined, id: string } | { __typename?: 'Trainer', deleteAt?: string | undefined, id: string } | undefined }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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']; @@ -1215,17 +1194,15 @@ export type UpdateTrainerMutationVariables = Exact<{ export type UpdateTrainerMutation = { __typename?: 'Mutation', updateTrainer?: { __typename?: 'Trainer', id: string, firstName: string, lastName: string, email: string, type: UserTypeEnum } | undefined }; -<<<<<<< HEAD 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 }> }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type AdminTraineesPageQueryVariables = Exact<{ [key: string]: never; }>; @@ -1245,11 +1222,7 @@ export type AlexaLinkingUrlQuery = { __typename?: 'Query', alexaLinkingUrl?: str export type ArchivePageDataQueryVariables = Exact<{ [key: string]: never; }>; -<<<<<<< HEAD -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, days: Array<{ __typename?: 'Day', status?: DayStatusEnum | undefined, entries: Array<{ __typename?: 'Entry', id: string, time: number, text: string }> }> } | undefined> }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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; }>; @@ -1277,11 +1250,7 @@ export type DashboardPageDataQueryVariables = Exact<{ }>; -<<<<<<< HEAD -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, 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, 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 }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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; }>; @@ -1291,21 +1260,14 @@ export type DayInputDataQuery = { __typename?: 'Query', currentUser?: { __typena export type EntryInputDataQueryVariables = Exact<{ [key: string]: never; }>; -<<<<<<< HEAD -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, username: string } | { __typename?: 'Mentor', id: string, type: UserTypeEnum, firstName: string, lastName: string, username: string } | { __typename?: 'Trainee', id: string, type: UserTypeEnum, firstName: string, lastName: string, username: string } | { __typename?: 'Trainer', id: string, type: UserTypeEnum, firstName: string, lastName: string, username: string } | undefined }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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 UserPageQueryVariables = Exact<{ id: Scalars['ID']['input']; }>; -<<<<<<< HEAD -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', 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 }; +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 MentorsPageQueryVariables = Exact<{ [key: string]: never; }>; @@ -1316,7 +1278,6 @@ export type MentorPaperPageDataQueryVariables = Exact<{ [key: string]: never; }> export type MentorPaperPageDataQuery = { __typename?: 'Query', currentUser?: { __typename?: 'Admin', id: string, theme?: string | undefined } | { __typename?: 'Mentor', id: string, theme?: 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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | { __typename?: 'Trainee', id: string, theme?: string | undefined } | { __typename?: 'Trainer', id: string, theme?: string | undefined } | undefined }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type NavigationDataQueryVariables = Exact<{ [key: string]: never; }>; @@ -1348,11 +1309,7 @@ export type ReportPageDataQueryVariables = Exact<{ }>; -<<<<<<< HEAD -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, username: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainee', startOfToolUsage?: string | undefined, endOfToolUsage?: string | undefined, id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, username: 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, 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, 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, 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 }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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']; @@ -1361,11 +1318,7 @@ export type ReportReviewPageDataQueryVariables = Exact<{ }>; -<<<<<<< HEAD -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, username: string } | { __typename?: 'Mentor', id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainee', id: string, firstName: string, lastName: string, username: string } | { __typename?: 'Trainer', id: string, firstName: string, lastName: string, username: 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, 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, 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, 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 }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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; }>; @@ -1385,10 +1338,7 @@ export type SuggestionsDataQuery = { __typename?: 'Query', suggestions: Array<{ export type TraineePageDataQueryVariables = Exact<{ [key: string]: never; }>; -<<<<<<< HEAD -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, username: 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 }>, feedback: 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 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 }>, feedback: 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; }>; @@ -1399,7 +1349,6 @@ 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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | { __typename?: 'Trainer' } | undefined }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export type TraineeSettingsDataQueryVariables = Exact<{ [key: string]: never; }>; @@ -1409,16 +1358,12 @@ export type TraineeSettingsDataQuery = { __typename?: 'Query', currentUser?: { _ 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', username: string, 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 }>, feedback: Array<{ __typename?: 'PaperFormData', id: string, questionId: string, question: string, answer?: string | undefined, hint?: string | undefined }> } | undefined> | undefined } | undefined }; +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 }>, feedback: 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; }>; -<<<<<<< HEAD -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', username: string, 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 }; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) +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; }>; @@ -2366,28 +2311,16 @@ export function useUpdateTrainerMutation(baseOptions?: Apollo.MutationHookOption return Apollo.useMutation(UpdateTrainerDocument, options); } export type UpdateTrainerMutationHookResult = ReturnType; -<<<<<<< HEAD export const AdminAdminsPageDocument = gql` query AdminAdminsPage { admins { id firstName lastName -======= -export const AdminMentorPageDocument = gql` - query AdminMentorPage { - mentors { - id - firstName - lastName - startDate - endDate ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) deleteAt } } `; -<<<<<<< HEAD export function useAdminAdminsPageQuery(baseOptions?: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} return Apollo.useQuery(AdminAdminsPageDocument, options); @@ -2403,7 +2336,18 @@ export function useAdminAdminsPageSuspenseQuery(baseOptions?: Apollo.SkipToken | 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); @@ -2419,7 +2363,6 @@ export function useAdminMentorPageSuspenseQuery(baseOptions?: Apollo.SkipToken | export type AdminMentorPageQueryHookResult = ReturnType; export type AdminMentorPageLazyQueryHookResult = ReturnType; export type AdminMentorPageSuspenseQueryHookResult = ReturnType; ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) export const AdminTraineesPageDocument = gql` query AdminTraineesPage { trainees { @@ -2803,15 +2746,13 @@ export const UserPageDocument = gql` lastName } } -<<<<<<< HEAD ... on Admin { deleteAt -======= + } ... on Mentor { deleteAt startDate endDate ->>>>>>> a2f4f37 (chore: manually rebased lara-paper onto main) } } companies { @@ -3458,7 +3399,6 @@ export const TrainerPaperPageDataDocument = gql` id ... on Trainer { trainees { - username firstName lastName id diff --git a/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql b/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql index 3b1b2dc9..47007d9a 100644 --- a/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql +++ b/packages/frontend/src/graphql/queries/trainer-paper-page-data.gql @@ -3,7 +3,6 @@ query TrainerPaperPageData { id ... on Trainer { trainees { - username firstName lastName id From 56695a8a46393cf953d6eca5510d7cc7113ded77 Mon Sep 17 00:00:00 2001 From: alexander-schefe Date: Wed, 8 Oct 2025 10:23:48 +0200 Subject: [PATCH 03/11] fix: fixed trainee paper dashboard page spaghetti code. Why did it show papers and placeholder if no papers for every trainee in the db? trainees sould only be able to view their own papers --- .../frontend/src/pages/trainee-paper-page.tsx | 173 +++++++++--------- 1 file changed, 84 insertions(+), 89 deletions(-) diff --git a/packages/frontend/src/pages/trainee-paper-page.tsx b/packages/frontend/src/pages/trainee-paper-page.tsx index 7beabd4a..c5364395 100644 --- a/packages/frontend/src/pages/trainee-paper-page.tsx +++ b/packages/frontend/src/pages/trainee-paper-page.tsx @@ -2,7 +2,7 @@ import { Container, H1, Paragraph, Spacer, StyledIcon, Text } from '@lara/compon import React from 'react' import Loader from '../components/loader' import { Template } from '../templates/template' -import { PaperStatus, useTraineePageDataQuery } from '../graphql' +import { PaperStatus, Trainee, useTraineePaperPageDataQuery } from '../graphql' import { Box, Flex } from '@lara/components' import strings from '../locales/localization' import ProgressBar from '../components/progress-bar' @@ -12,7 +12,7 @@ import { useNavigate } from 'react-router' import { mapStatusToProgess } from '../helper/paper-helper' export const TraineePaperPage: React.FC = () => { - const { loading, data } = useTraineePageDataQuery() + const { loading, data } = useTraineePaperPageDataQuery() const navigate = useNavigate() const navigateToPaperFeedbackPage = (paperId: string) => { @@ -27,7 +27,7 @@ export const TraineePaperPage: React.FC = () => { ) } - const { currentUser } = data + const currentUser = data.currentUser as Trainee if (!currentUser) { return (