From dca14e266e1378108c4505a9d35d98636736f689 Mon Sep 17 00:00:00 2001 From: RWEMAREMY <120011390+RWEMAREMY@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:40:08 +0200 Subject: [PATCH] advancing calender functionality (#480) --- package-lock.json | 97 ++- package.json | 12 +- src/Mutations/Attendance.tsx | 46 -- src/Mutations/MakeDefault.tsx | 15 +- src/Mutations/Ratings.tsx | 240 +------- src/Mutations/User.tsx | 129 +--- src/Mutations/event.tsx | 89 ++- src/Mutations/manageStudentMutations.tsx | 226 +------ src/Mutations/notificationMutation.tsx | 42 +- src/Mutations/replyMutation.tsx | 34 +- src/Mutations/resetPassword.tsx | 5 - src/Mutations/session.tsx | 28 - src/Mutations/teamMutation.tsx | 61 -- src/components/Calendar.tsx | 562 ++++++++++++++---- src/components/CalendarConfirmation.tsx | 87 +++ src/components/CoordinatorCard.tsx | 1 + src/components/DashHeader.tsx | 4 +- src/components/Docs/AdminDocs.tsx | 2 +- src/components/Docs/OthersDocs.tsx | 2 +- src/components/Docs/TraineeDocs.tsx | 2 +- src/components/EventGuestList.tsx | 106 ++++ src/components/LoginActivitiesTable.tsx | 2 +- src/components/ProfileCoverpage.tsx | 2 +- src/components/ProfileTabs.tsx | 12 +- src/components/TraineeAttendance.tsx | 4 +- src/components/TraineeHeader.tsx | 8 +- src/components/TraineePerformance.tsx | 2 +- src/components/TraineesHeader.tsx | 8 +- src/components/ratings/ViewWeeklyRatings.tsx | 8 +- .../ratings/hooks/useViewTraineeRatings.tsx | 2 +- src/components/teamDetails.tsx | 2 +- src/containers/Routes.tsx | 8 + .../admin-dashBoard/CohortTeamsModal.tsx | 1 - .../admin-dashBoard/CohortTraineeModal.tsx | 2 +- .../admin-dashBoard/ManagerRoles.tsx | 3 +- src/containers/admin-dashBoard/Sessions.tsx | 2 +- .../admin-dashBoard/TeamTraineeModal.tsx | 2 +- src/containers/admin-dashBoard/TtlsModal.tsx | 9 +- src/pages/AdminRatings.tsx | 2 +- src/pages/AdminTraineeDashboard.tsx | 47 +- src/pages/ForgotPassword.tsx | 6 +- src/pages/Profile.tsx | 2 +- src/pages/Settings.tsx | 4 +- src/pages/TraineeAttendance.tsx | 3 +- src/pages/TraineeDashboard.tsx | 2 +- src/pages/TraineeRatingDashboard.tsx | 7 +- src/pages/invitation.tsx | 18 +- src/pages/ratings/ViewTraineeRatings.tsx | 2 +- src/pages/ttlTraineeDashboard.tsx | 33 +- src/queries/DefaultGrading.queries.tsx | 15 + src/queries/attendance.queries.tsx | 47 ++ src/queries/event.queries.tsx | 37 ++ .../invitationStats.queries.tsx} | 0 src/queries/manageStudent.queries.tsx | 244 ++++++++ src/queries/notification.queries.tsx | 41 ++ src/queries/ratings.queries.tsx | 239 ++++++++ src/queries/reply.queries.tsx | 35 ++ src/queries/resetPassword.queries.tsx | 7 + src/queries/session.queries.tsx | 27 + src/queries/team.queries.tsx | 62 ++ src/queries/tickets.queries.tsx | 1 - src/queries/user.queries.tsx | 130 ++++ tests/components/Calendar.test.tsx | 266 +++++++-- .../components/CalendarConfirmation.test.tsx | 158 +++++ tests/components/DashHeader.test.tsx | 2 - tests/components/EventGuestList.test.tsx | 138 +++++ tests/components/TraineeAttendance.test.tsx | 2 +- .../AdminTraineeDashboard.test.tsx.snap | 32 +- tests/components/loginActivities.test.tsx | 2 +- .../admin-dashboard/Sessions.test.tsx | 2 +- .../__snapshots__/Cohorts.test.tsx.snap | 36 +- .../__snapshots__/Program.test.tsx.snap | 12 +- .../admin-dashboard/session.test.tsx | 2 +- .../admin-dashboard/sessionTest.test.tsx | 2 +- tests/other-tests/AdminDashboard.test.tsx | 1 + .../AdminTraineeDashboard.test.tsx.snap | 32 +- .../__snapshots__/Admindash.test.tsx.snap | 36 +- .../__snapshots__/Settings.test.tsx.snap | 2 + .../__snapshots__/userRegister.test.tsx.snap | 8 +- 79 files changed, 2369 insertions(+), 1242 deletions(-) create mode 100644 src/components/CalendarConfirmation.tsx create mode 100644 src/components/EventGuestList.tsx create mode 100644 src/queries/DefaultGrading.queries.tsx create mode 100644 src/queries/attendance.queries.tsx create mode 100644 src/queries/event.queries.tsx rename src/{Mutations/invitationStats.tsx => queries/invitationStats.queries.tsx} (100%) create mode 100644 src/queries/manageStudent.queries.tsx create mode 100644 src/queries/notification.queries.tsx create mode 100644 src/queries/ratings.queries.tsx create mode 100644 src/queries/reply.queries.tsx create mode 100644 src/queries/resetPassword.queries.tsx create mode 100644 src/queries/session.queries.tsx create mode 100644 src/queries/team.queries.tsx create mode 100644 src/queries/user.queries.tsx create mode 100644 tests/components/CalendarConfirmation.test.tsx create mode 100644 tests/components/EventGuestList.test.tsx diff --git a/package-lock.json b/package-lock.json index 4523d9f66..828a54c4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,12 +12,12 @@ "@babel/preset-react": "^7.22.5", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@fullcalendar/core": "^5.11.5", - "@fullcalendar/daygrid": "^5.11.5", - "@fullcalendar/interaction": "^5.11.5", - "@fullcalendar/list": "^5.11.5", - "@fullcalendar/react": "^5.11.5", - "@fullcalendar/timegrid": "^5.11.5", + "@fullcalendar/core": "^6.1.15", + "@fullcalendar/daygrid": "^6.1.15", + "@fullcalendar/interaction": "^6.1.15", + "@fullcalendar/list": "^6.1.15", + "@fullcalendar/react": "^6.1.15", + "@fullcalendar/timegrid": "^6.1.15", "@headlessui/react": "^1.7.15", "@heroicons/react": "^1.0.6", "@iconify/react": "^3.2.2", @@ -2670,72 +2670,63 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" }, - "node_modules/@fullcalendar/common": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.11.5.tgz", - "integrity": "sha512-3iAYiUbHXhjSVXnYWz27Od2cslztUPsOwiwKlfGvQxBixv2Kl6a8IPwaijKFYJHXdwYmfPoEgK7rvqAGVoIYwA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, "node_modules/@fullcalendar/core": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-5.11.5.tgz", - "integrity": "sha512-M/WQuq1+uUHxFDEIu2ib/aaPZ70VsRk2ITECo/WCLSLTVWcHPXwEg83reyP3G8JrMM4gRL4vScEHhX0U5aoNSw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.15.tgz", + "integrity": "sha512-BuX7o6ALpLb84cMw1FCB9/cSgF4JbVO894cjJZ6kP74jzbUZNjtwffwRdA+Id8rrLjT30d/7TrkW90k4zbXB5Q==", + "license": "MIT", "dependencies": { - "@fullcalendar/common": "~5.11.5", - "preact": "~10.12.1", - "tslib": "^2.1.0" + "preact": "~10.12.1" } }, "node_modules/@fullcalendar/daygrid": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-5.11.5.tgz", - "integrity": "sha512-hMpq0U3Nucys2jDD+crbkJCr+tVt3fDw04OE3fbpisuzqtrHxIzRmnUOdbWUjJQyToAAkt7UVUQ9E7hYdmvyGA==", - "dependencies": { - "@fullcalendar/common": "~5.11.5", - "tslib": "^2.1.0" + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.15.tgz", + "integrity": "sha512-j8tL0HhfiVsdtOCLfzK2J0RtSkiad3BYYemwQKq512cx6btz6ZZ2RNc/hVnIxluuWFyvx5sXZwoeTJsFSFTEFA==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.15" } }, "node_modules/@fullcalendar/interaction": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-5.11.5.tgz", - "integrity": "sha512-Vg9uw8zKXZc2RP7it88U8R/kxJIQsK4pyv+s+RhlvT5NBZ9KLOh5y2xGCS4A4hyY7qLrzugxnKYlu6NwNqJ/RQ==", - "dependencies": { - "@fullcalendar/common": "~5.11.5", - "tslib": "^2.1.0" + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.15.tgz", + "integrity": "sha512-DOTSkofizM7QItjgu7W68TvKKvN9PSEEvDJceyMbQDvlXHa7pm/WAVtAc6xSDZ9xmB1QramYoWGLHkCYbTW1rQ==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.15" } }, "node_modules/@fullcalendar/list": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-5.11.5.tgz", - "integrity": "sha512-ZYMPT4CVt9tIYkVVNx7CKkB2xc+n9L56+vgXkurptgYgPsacXYkcpF/1Hy/B5LKlg0ROEF9Qfftjow8xjANqaA==", - "dependencies": { - "@fullcalendar/common": "~5.11.5", - "tslib": "^2.1.0" + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.15.tgz", + "integrity": "sha512-U1bce04tYDwkFnuVImJSy2XalYIIQr6YusOWRPM/5ivHcJh67Gm8CIMSWpi3KdRSNKFkqBxLPkfZGBMaOcJYug==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.15" } }, "node_modules/@fullcalendar/react": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/react/-/react-5.11.5.tgz", - "integrity": "sha512-PbBlDyKJ8IQYf5mBdD1mjDas2v3eEU1UfWYLv0e6uGCktH+g4mgaG/LCDOwE65V5VH5FH8+kVkFjIScwA54WwA==", - "dependencies": { - "@fullcalendar/common": "~5.11.5", - "tslib": "^2.1.0" - }, + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/@fullcalendar/react/-/react-6.1.15.tgz", + "integrity": "sha512-L0b9hybS2J4e7lq6G2CD4nqriyLEqOH1tE8iI6JQjAMTVh5JicOo5Mqw+fhU5bJ7hLfMw2K3fksxX3Ul1ssw5w==", + "license": "MIT", "peerDependencies": { - "react": "^16.7.0 || ^17 || ^18", - "react-dom": "^16.7.0 || ^17 || ^18" + "@fullcalendar/core": "~6.1.15", + "react": "^16.7.0 || ^17 || ^18 || ^19", + "react-dom": "^16.7.0 || ^17 || ^18 || ^19" } }, "node_modules/@fullcalendar/timegrid": { - "version": "5.11.5", - "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-5.11.5.tgz", - "integrity": "sha512-OEH5mrTclwxgUbb51N6qr7ifzNkR74ygUEFpiMLyyUjkp7a76N6BsAP5mBQnTOpTTUZBu9tAOmfcnvi7skUayQ==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.15.tgz", + "integrity": "sha512-61ORr3A148RtxQ2FNG7JKvacyA/TEVZ7z6I+3E9Oeu3dqTf6M928bFcpehRTIK6zIA6Yifs7BeWHgOE9dFnpbw==", + "license": "MIT", "dependencies": { - "@fullcalendar/common": "~5.11.5", - "@fullcalendar/daygrid": "~5.11.5", - "tslib": "^2.1.0" + "@fullcalendar/daygrid": "~6.1.15" + }, + "peerDependencies": { + "@fullcalendar/core": "~6.1.15" } }, "node_modules/@graphql-typed-document-node/core": { diff --git a/package.json b/package.json index eeec242e5..82fba72c7 100644 --- a/package.json +++ b/package.json @@ -34,12 +34,12 @@ "@babel/preset-react": "^7.22.5", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@fullcalendar/core": "^5.11.5", - "@fullcalendar/daygrid": "^5.11.5", - "@fullcalendar/interaction": "^5.11.5", - "@fullcalendar/list": "^5.11.5", - "@fullcalendar/react": "^5.11.5", - "@fullcalendar/timegrid": "^5.11.5", + "@fullcalendar/core": "^6.1.15", + "@fullcalendar/daygrid": "^6.1.15", + "@fullcalendar/interaction": "^6.1.15", + "@fullcalendar/list": "^6.1.15", + "@fullcalendar/react": "^6.1.15", + "@fullcalendar/timegrid": "^6.1.15", "@headlessui/react": "^1.7.15", "@heroicons/react": "^1.0.6", "@iconify/react": "^3.2.2", diff --git a/src/Mutations/Attendance.tsx b/src/Mutations/Attendance.tsx index 85f6c9c5f..cb63dcafd 100644 --- a/src/Mutations/Attendance.tsx +++ b/src/Mutations/Attendance.tsx @@ -1,51 +1,5 @@ import { gql } from '@apollo/client'; -export const GET_ATTENDANCE = gql` - query ExampleQuery { - getTraineeAttendance { - id - trainees { - traineeId - traineeEmail - status { - days - value - } - } - week - } - } -`; - -export const GET_ATTENDANCE_BY_ID = gql` - query GetAttendance($id: ID!) { - getTraineeAttendanceByID(id: $id) { - id - week - trainees { - traineeId - traineeEmail - status { - days - value - } - } - } - } -`; - -export const GET_WEEKLY_ATTENDANCE = gql` - query GetTraineeAttendanceByID($traineeEmail: String!) { - getTraineeAttendanceByID(traineeEmail: $traineeEmail) { - weekNumber - traineeAttendance { - days - value - } - } - } -`; - export const UPDATE_ATTENDANCE = gql` mutation RecordAttendance( $week: String! diff --git a/src/Mutations/MakeDefault.tsx b/src/Mutations/MakeDefault.tsx index 0ba33a467..bc7c44f0f 100644 --- a/src/Mutations/MakeDefault.tsx +++ b/src/Mutations/MakeDefault.tsx @@ -1,22 +1,9 @@ import { gql } from '@apollo/client'; -export const DEFAULT_GRADE = gql` - query GetDefaultGrading { - getDefaultGrading { - id - name - grade - description - percentage - userId - defaultGrading - } - } -`; - const MAKE_DEFAULT_GRADING_SYSTEM = gql` mutation MakeRatingdefault($makeRatingdefaultId: ID) { makeRatingdefault(id: $makeRatingdefaultId) } `; + export default MAKE_DEFAULT_GRADING_SYSTEM; diff --git a/src/Mutations/Ratings.tsx b/src/Mutations/Ratings.tsx index 1062f24e4..78168db19 100644 --- a/src/Mutations/Ratings.tsx +++ b/src/Mutations/Ratings.tsx @@ -1,127 +1,5 @@ import { gql } from '@apollo/client'; -export const GET_RATINGS = gql` - query Query($orgToken: String) { - fetchRatings(orgToken: $orgToken) { - user { - id - email - } - sprint - quantity - bodyQuantity - quantityRemark - quality - bodyProfessional - qualityRemark - professional_Skills - professionalRemark - bodyQuality - coordinator - average - cohort { - name - phase { - name - } - } - } - } -`; -export const RATING_BY_COHORT = gql` - query GetAllCohorts($cohortName: String) { - fetchRatingByCohort(CohortName: $cohortName) { - sprint - quantity - approved - coordinator - average - cohort { - name - id - phase { - name - } - } - user { - id - email - profile { - name - } - } - quantityRemark - bodyQuantity - quality - qualityRemark - bodyQuality - professional_Skills - professionalRemark - bodyProfessional - feedbacks { - sender { - email - id - profile { - avatar - name - } - role - } - content - createdAt - } - user { - id - email - } - quantityRemark - bodyQuantity - quality - qualityRemark - bodyQuality - professional_Skills - professionalRemark - bodyProfessional - } - } -`; -export const FETCH_ALL_RATINGS = gql` - query FetchAllRatings($orgToken: String) { - fetchAllRatings(orgToken: $orgToken) { - user { - id - email - profile { - firstName - lastName - } - team { - name - } - } - sprint - quantity - quantityRemark - quality - qualityRemark - professional_Skills - professionalRemark - average - cohort { - name - phase { - name - } - } - coordinator - feedbacks { - content - } - } - } -`; - export const ADD_RATING = gql` mutation AddRatings( $user: String! @@ -247,6 +125,7 @@ export const ADD_FEEDBACK = gql` } } `; + export const GET_FEEDBACK_SUBSCRIPTION = gql` subscription Newfeedback($sprint: String, $user: String) { newfeedback(sprint: $sprint, user: $user) { @@ -260,6 +139,7 @@ export const GET_FEEDBACK_SUBSCRIPTION = gql` } } `; + export const GET_FEEDBACKS_SUBSCRIPTION = gql` subscription Newfeedbacks($sprintUser: String) { newfeedbacks(sprint_user: $sprintUser) { @@ -277,6 +157,7 @@ export const GET_FEEDBACKS_SUBSCRIPTION = gql` } } `; + export const APPROVE_RATING = gql` mutation Mutation($user: String!, $sprint: Int!) { approveRating(user: $user, sprint: $sprint) { @@ -298,118 +179,3 @@ export const REJECT_RATING = gql` rejectRating(user: $user, sprint: $sprint) } `; - -export const TRAINEE_RATING = gql` - query Query { - fetchRatingsTrainee { - user { - id - email - } - sprint - phase - sprint - quantity - quantityRemark - quality - qualityRemark - professional_Skills - professionalRemark - average - cohort { - name - phase { - name - } - coordinator { - email - profile { - name - } - } - } - feedbacks { - sender { - email - id - profile { - avatar - name - } - role - } - content - createdAt - } - } - } -`; - -export const GET_USERS = gql` - query GetAllUsers($cohortName: ID!) { - fetchCohortsCoordinator(cohortName: $cohortName) { - name - phase { - name - } - coordinator { - id - } - members { - id - role - email - } - program { - name - } - id - } - } -`; - -export const GET_COORDINATOR_COHORTS_QUERY = gql` - query GetCoordinatorCohorts($orgToken: String) { - getCoordinatorCohorts(orgToken: $orgToken) { - name - id - } - } -`; - -export const GET_ALL_TRAINEES = gql` - query GetAllUsers($orgToken: String) { - getAllUsers(orgToken: $orgToken) { - role - email - team { - name - cohort { - endDate - startDate - phase { - name - - description - } - name - program { - organization { - name - } - name - manager { - role - email - profile { - name - firstName - lastName - } - } - } - } - } - } - } -`; diff --git a/src/Mutations/User.tsx b/src/Mutations/User.tsx index aac7b8a48..71f94e661 100644 --- a/src/Mutations/User.tsx +++ b/src/Mutations/User.tsx @@ -1,134 +1,9 @@ import { gql } from '@apollo/client'; -export const GET_PROFILE = gql` - query { - getProfile { - firstName - lastName - phoneNumber - address - city - country - avatar - cover - name - biography - githubUsername - user { - organizations - email - role - team { - name - cohort { - name - phase { - name - } - program { - name - } - startDate - } - } - cohort { - name - program { - name - } - phase { - name - } - } - program { - name - } - } - } - } -`; - -export const GET_ALL_TTL_USERS = gql` - query GetAllTTLUsers($orgToken: String!) { - getAllTTLUsers(orgToken: $orgToken) { - profile { - name - } - email - team { - name - cohort { - name - } - } - } - } -`; - -export const GET_TTL_TRAINEES = gql` - query GetTTLTrainees($orgToken: String) { - getTTLTrainees(orgToken: $orgToken) { - profile { - firstName - lastName - city - country - phoneNumber - biography - avatar - id - user { - id - status { - status - date - reason - } - } - name - githubUsername - resume - } - email - role - team { - name - cohort { - id - startDate - program { - name - manager { - profile { - name - } - email - } - } - name - phase { - name - } - } - } - ratings { - average - } - cohort { - name - } - program { - name - manager { - email - } - } - } - } -`; export const DROP_TTL_USER = gql` mutation DropTTLUser($email: String!, $reason: String!) { dropTTLUser(email: $email, reason: $reason) } `; -export default GET_PROFILE; \ No newline at end of file + +export default DROP_TTL_USER; diff --git a/src/Mutations/event.tsx b/src/Mutations/event.tsx index 9c7d5e847..0dd7fe336 100644 --- a/src/Mutations/event.tsx +++ b/src/Mutations/event.tsx @@ -1,36 +1,63 @@ import { gql } from '@apollo/client'; -export const GET_EVENTS = gql` - query GetEvents($authToken: String) { - getEvents(authToken: $authToken) { + +export const ADD_EVENT = gql` + mutation CreateEvent( + $title: String! + $end: String! + $timeToStart: String! + $timeToEnd: String! + $hostName: String! + $start: String! + $authToken: String! + $orgToken: String! + $invitees: [String]! + ) { + createEvent( + title: $title + end: $end + timeToStart: $timeToStart + timeToEnd: $timeToEnd + hostName: $hostName + start: $start + authToken: $authToken + orgToken: $orgToken + invitees: $invitees + ) { end hostName start timeToEnd - timeToStart title + timeToStart } } `; -export const ADD_EVENT = gql` - mutation CreateEvent( +export const EDIT_EVENT = gql` +mutation EditEvent( + $eventId: String! $title: String! $end: String! $timeToStart: String! - $timeToFinish: String! + $timeToEnd: String! $hostName: String! $start: String! - $authToken: String + $authToken: String! + $orgToken: String! + $invitees: [String]! ) { - createEvent( + editEvent( + eventId: $eventId title: $title end: $end timeToStart: $timeToStart - timeToEnd: $timeToFinish + timeToEnd: $timeToEnd hostName: $hostName start: $start authToken: $authToken + orgToken: $orgToken + invitees: $invitees ) { end hostName @@ -41,3 +68,45 @@ export const ADD_EVENT = gql` } } `; + +export const CANCEL_EVENT = gql` + mutation CancelEvent( + $eventId: String! + $authToken: String! + ) { + cancelEvent( + eventId: $eventId + authToken: $authToken + ) { + end + hostName + start + timeToEnd + title + timeToStart + } + } +` + +export const RESPOND_TO_EVENT_INVITATION = gql` + mutation RespondToEventInvitation( + $eventToken: String! + $authToken: String! + ) { + respondToEventInvitation( + eventToken: $eventToken, + authToken: $authToken + ) { + end + hostName + start + timeToEnd + title + timeToStart + invitees { + email, + status + } + } + } +` diff --git a/src/Mutations/manageStudentMutations.tsx b/src/Mutations/manageStudentMutations.tsx index 91ed66327..51de5c018 100644 --- a/src/Mutations/manageStudentMutations.tsx +++ b/src/Mutations/manageStudentMutations.tsx @@ -3,14 +3,6 @@ import { gql, ApolloClient, InMemoryCache } from '@apollo/client'; import GET_PROFILE from './User'; -export const GET_USERS_QUERY = gql` - query GetUsers($orgToken: String) { - getUsers(orgToken: $orgToken) { - email - id - } - } -`; export const DROP_TRAINEE = gql` mutation DropTrainee( @@ -22,128 +14,6 @@ export const DROP_TRAINEE = gql` } `; -export const GET_TRAINEES_QUERY = gql` - query GetTrainees($orgToken: String) { - getTrainees(orgToken: $orgToken) { - profile { - firstName - lastName - city - country - phoneNumber - biography - avatar - id - user { - id - status { - status - date - reason - } - } - name - githubUsername - resume - } - email - cohort { - coordinator { - profile { - name - firstName - lastName - } - } - } - team { - name - cohort { - id - startDate - program { - name - manager { - profile { - name - } - email - } - } - name - phase { - name - } - } - } - ratings { - average - } - } - } -`; - -export const GET_COHORT_TRAINEES_QUERY = gql` - query GetCohortTrainees($cohort: String, $orgToken: String) { - getCohortTrainees(cohort: $cohort, orgToken: $orgToken) { - profile { - name - } - email - id - team { - name - cohort { - name - program { - name - } - } - } - } - } -`; - -export const GET_COHORTS_QUERY = gql` - query GetCohorts($orgToken: String) { - getCohorts(orgToken: $orgToken) { - name - id - } - } -`; - -export const GET_TRAINEE_PROFILE = gql` - query GetProfile { - getProfile { - firstName - name - city - country - address - phoneNumber - biography - avatar - cover - lastName - resume - } - } -`; - -export const GET_GITHUB_STATISTICS = gql` - query GitHubActivity($organisation: String!, $username: String!) { - gitHubActivity(organisation: $organisation, username: $username) { - totalCommits - pullRequest { - closed - merged - opened - } - } - } -`; - export const ADD_DOCUMENTATION = gql` mutation AddDocumentation( $title: String! @@ -177,21 +47,6 @@ export const ADD_SUB_DOCUMENTATION = gql` } `; -export const GET_DOCUMENTATION = gql` - query GetDocumentations { - getDocumentations { - description - for - id - subDocuments { - description - title - } - title - } - } -`; - export const UPDATE_DOCUMENTATION = gql` mutation UpdateDocumentation( $id: ID! @@ -242,39 +97,6 @@ export const DELETE_SUB_DOCUMENTATION = gql` } `; -export const GET_LOGIN_ACTIVITIES = gql` - query Query { - getProfile { - activity { - date - country_code - country_name - city - IPv4 - state - latitude - longitude - postal - failed - } - } - } -`; - -export const GET_ORGANISATION = gql` - query GetOrganization($name: String!) { - getOrganization(name: $name) { - name - activeRepos - gitHubOrganisation - description - admin { - email - } - } - } -`; - export const ADD_MEMBER_TO_COHORT_MUTATION = gql` mutation AddMemberToCohort( $cohortName: String! @@ -355,55 +177,9 @@ export const INVITE_USER_MUTATION = gql` inviteUser(email: $email, orgToken: $orgToken, type: $type) } `; -export const GET_TEAM_QUERY = gql` - query GetAllTeamInCohort($orgToken: String, $cohort: String) { - getAllTeamInCohort(orgToken: $orgToken, cohort: $cohort) { - cohort { - name - } - name - } - } -`; + export const ADD_MEMBER_TO_TEAM = gql` mutation Mutation($teamName: String!, $email: String!, $orgToken: String!) { addMemberToTeam(teamName: $teamName, email: $email, orgToken: $orgToken) } `; -export const GET_TEAM_TRAINEE_QUERY = gql` - query GetTeamTrainees($orgToken: String, $team: String) { - getTeamTrainees(orgToken: $orgToken, team: $team) { - profile { - firstName - lastName - city - country - phoneNumber - biography - avatar - id - name - } - email - team { - name - cohort { - startDate - program { - name - manager { - profile { - name - } - email - } - } - name - phase { - name - } - } - } - } - } -`; diff --git a/src/Mutations/notificationMutation.tsx b/src/Mutations/notificationMutation.tsx index f035efe44..c0309db48 100644 --- a/src/Mutations/notificationMutation.tsx +++ b/src/Mutations/notificationMutation.tsx @@ -1,32 +1,5 @@ import { gql, useSubscription } from '@apollo/client'; -export const getAllNotification = gql` - query Query { - getAllNotification { - message - id - receiver - createdAt - read - type - sender { - profile { - firstName - lastName - name - cover - country - address - phoneNumber - id - avatar - } - } - } - } -`; -export default getAllNotification; - export const NotificationSubscription = gql` subscription Subscription($receiver: String!) { newRating(receiver: $receiver) { @@ -45,6 +18,7 @@ export const NotificationSubscription = gql` } } `; + export const PUSH_NOTIFICATION_SUB = gql` subscription PushNotificationSub($receiverId: String!) { pushNotification(receiverId: $receiverId) { @@ -65,11 +39,13 @@ export const PUSH_NOTIFICATION_SUB = gql` } } `; + export const deleteNotification = gql` mutation Mutation($deleteNotificationsId: ID!) { deleteNotifications(id: $deleteNotificationsId) } `; + export const markAsRead = gql` mutation Mutation($markAsReadId: ID!) { markAsRead(id: $markAsReadId) @@ -93,15 +69,3 @@ export const updateEmailNotifications = gql` updateEmailNotifications(id: $updateEmailNotificationsId) } `; - -export const updatedEmailNotifications = gql` - query Query($getUpdatedEmailNotificationsId: ID!) { - getUpdatedEmailNotifications(id: $getUpdatedEmailNotificationsId) - } -`; - -export const updatedPushNotifications = gql` - query Query($getUpdatedPushNotificationsId: ID!) { - getUpdatedPushNotifications(id: $getUpdatedPushNotificationsId) - } -`; diff --git a/src/Mutations/replyMutation.tsx b/src/Mutations/replyMutation.tsx index 8327eeac3..eccbce259 100644 --- a/src/Mutations/replyMutation.tsx +++ b/src/Mutations/replyMutation.tsx @@ -1,38 +1,5 @@ import { gql } from '@apollo/client'; -export const GET_REPLIES = gql` - query Query { - getReplies { - id - user - sprint - quantityRemark - qualityRemark - professionalRemark - bodyQuantity - bodyQuality - bodyProfessional - createdAt - } - } -`; -export const GET_REPLIES_BY_USER = gql` - query Query($userId: String) { - getRepliesByUser(userId: $userId) { - id - user - sprint - quantityRemark - qualityRemark - professionalRemark - bodyQuantity - bodyQuality - bodyProfessional - createdAt - } - } -`; - export const ADD_REPLY = gql` mutation AddReply( $sprint: Int! @@ -59,6 +26,7 @@ export const ADD_REPLY = gql` } } `; + export const UPDATE_TO_REPLY = gql` mutation UpdateToReply( $user: String! diff --git a/src/Mutations/resetPassword.tsx b/src/Mutations/resetPassword.tsx index 9d5fbe909..41ab5265e 100644 --- a/src/Mutations/resetPassword.tsx +++ b/src/Mutations/resetPassword.tsx @@ -18,8 +18,3 @@ export const RESET_PASSWORD_EMAIL = gql` forgotPassword(email: $email) } `; -export const VERIFY_RESET_PASSWORD_TOKEN = gql` - query Query($token: String!) { - verifyResetPasswordToken(token: $token) - } -`; diff --git a/src/Mutations/session.tsx b/src/Mutations/session.tsx index 9576d6c39..eb471296f 100644 --- a/src/Mutations/session.tsx +++ b/src/Mutations/session.tsx @@ -1,33 +1,5 @@ import { gql } from '@apollo/client'; -// Query to get a single session by ID -export const GET_SESSION = gql` - query GetSession($ID: ID!) { - getSession(id: $ID) { - id - Sessionname - description - platform - duration - organizer - } - } -`; - -// Query to get a list of all sessions -export const GET_SESSIONS = gql` - query GetSessions { - getAllSessions { - id - Sessionname - description - platform - duration - organizer - } - } -`; - // Mutation to create a new session export const CREATE_SESSION = gql` mutation CreateSession($sessionInput: SessionInput) { diff --git a/src/Mutations/teamMutation.tsx b/src/Mutations/teamMutation.tsx index 79937c608..db368f2ff 100644 --- a/src/Mutations/teamMutation.tsx +++ b/src/Mutations/teamMutation.tsx @@ -1,15 +1,5 @@ import { gql } from '@apollo/client'; -export const GET_TEAMS = gql` - query Query($orgToken: String) { - getAllTeams(orgToken: $orgToken) { - id - name - } - } -`; -export default GET_TEAMS; - export const ADD_TEAMS = gql` mutation Mutation( $name: String! @@ -63,54 +53,3 @@ export const DeleteTeam = gql` } `; -export const GET_TEAMS_CARDS = gql` - query Query($orgToken: String!) { - getAllTeams(orgToken: $orgToken) { - name - manager { - email - team { - ttl { - email - } - } - } - ttl { - email - } - avgRatings { - quantity - quality - attendance - } - members { - profile { - name - } - } - active - startingPhase - cohort { - name - phase { - name - id - } - startDate - endDate - program { - name - manager { - email - profile { - name - lastName - firstName - } - } - } - } - id - } - } -`; diff --git a/src/components/Calendar.tsx b/src/components/Calendar.tsx index f4cc467f9..00238a8fc 100644 --- a/src/components/Calendar.tsx +++ b/src/components/Calendar.tsx @@ -1,7 +1,8 @@ /* eslint-disable */ import React, { useEffect, useState } from 'react'; -import FullCalendar, { EventInput, EventContentArg } from '@fullcalendar/react'; +import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; +import { EventContentArg, EventInput } from '@fullcalendar/core'; import { useTranslation } from 'react-i18next'; import interactionPlugin from '@fullcalendar/interaction'; import DatePicker from 'react-datepicker'; @@ -9,10 +10,12 @@ import 'react-datepicker/dist/react-datepicker.css'; import ReactTooltip from 'react-tooltip'; import useDocumentTitle from '../hook/useDocumentTitle'; import { useLazyQuery, useMutation } from '@apollo/client'; -import { ADD_EVENT, GET_EVENTS } from '../Mutations/event'; +import { ADD_EVENT, EDIT_EVENT, CANCEL_EVENT } from '../Mutations/event'; +import { GET_EVENTS } from '../queries/event.queries'; import moment from 'moment'; import CalendarSkeleton from '../Skeletons/Calender.skeleton' - +import { toast } from 'react-toastify'; +import EventGuestList from './EventGuestList'; /* istanbul ignore next */ const Calendar = () => { @@ -20,63 +23,54 @@ const Calendar = () => { const [addEventModel, setAddEventModel] = useState(false); const [newEvent, setNewEvent] = useState({ title: '', - start: '', - end: '', + start: new Date(), + end: new Date(), hostName: '', timeToStart: '', - timeToFinish: '', + timeToEnd: '', }); - const [data, setData] = useState([]); - const [loading, setLoading] = useState(true); - const [getEvents] = useLazyQuery(GET_EVENTS); + + const [getEvents, { loading, data }] = useLazyQuery(GET_EVENTS); const [createEvent] = useMutation(ADD_EVENT); - useEffect(() => { - const fetchData = async () => { - /* istanbul ignore next */ - try { - const { data: out } = await getEvents({ - variables: { - authToken: localStorage.getItem('auth_token'), - }, - }); - let all = out.getEvents.map((one: EventInput) => ({ - end: moment(one.end).format('YYYY-MM-DD'), - start: moment(one.start).format('YYYY-MM-DD'), - hostName: one.hostName, - timeToStart: one.timeToStart, - title: one.title, - timeToFinish: one.timeToEnd, - })); - setData(all); - } catch (error) { - console.log({ eventsError: data }); - // toast.error(error?.message || 'Something went wrong'); - }finally { - setLoading(false); - } - }; - fetchData(); - }, []); + + const [showTraineeDropdown, setShowTraineeDropdown] = useState(false); + const [selectedGuests, setSelectedGuests] = useState([]); + const { t } = useTranslation(); - const renderEvent = + + const fetchData = async () => { /* istanbul ignore next */ + try { + await getEvents({ + variables: { + authToken: localStorage.getItem('auth_token'), + }, + fetchPolicy: 'network-only', + }); + } catch (error: any) { + toast.error(error.message) + } + }; - (e: EventContentArg) => ( - /* istanbul ignore next */ -
${e.event.title}
${e.event.extendedProps.hostName}
${e.event.extendedProps.timeToStart} - ${e.event.extendedProps.timeToFinish}
`} - className="bg-primary text-white max-w-full min-w-full overflow-auto text-xs md:text-sm" - > -

{e.event.title}

-

{e.event.extendedProps.hostName}

-

- {e.event.extendedProps.timeToStart} -{' '} - {e.event.extendedProps.timeToFinish} -

- - - ); + useEffect(() => { + fetchData() + }, []); + + const renderEvent = (e: EventContentArg) => ( +
${e.event.title}
${e.event.extendedProps.hostName}
${e.event.extendedProps.timeToStart} - ${e.event.extendedProps.timeToEnd}
`} + className="bg-primary text-white max-w-full min-w-full overflow-auto text-xs md:text-sm" + > +

{e.event.title}

+

{e.event.extendedProps.hostName}

+

+ {e.event.extendedProps.timeToStart} - {e.event.extendedProps.timeToEnd} +

+ + + ); const removeModel = (e: any) => { e.preventDefault(); @@ -84,38 +78,171 @@ const Calendar = () => { setAddEventModel(newState); }; - const handleDateClick = () => { + const handleAddEventModal = () => { const newState = !addEventModel; setAddEventModel(newState); }; - /* istanbul ignore next */ const handleAddEvent = (e: any) => { e.preventDefault(); createEvent({ - variables: { ...newEvent, authToken: localStorage.getItem('auth_token') }, - }); - setData([...data, newEvent]); - setNewEvent({ - title: '', - start: '', - end: '', - hostName: '', - timeToStart: '', - timeToFinish: '', - }); - setTimeout(() => { - setAddEventModel(false); - }, 1000); + variables: { + ...newEvent, + authToken: localStorage.getItem('auth_token'), + orgToken: localStorage.getItem('orgToken'), + invitees: selectedGuests, + } + }) + .then(() => { + fetchData() + toast.success('Event has been added!'); // {{ edit_1 }} + setNewEvent({ + title: '', + start: new Date(), + end: new Date(), + hostName: '', + timeToStart: '', + timeToEnd: '', + }); + setSelectedGuests([]) + setTimeout(() => { + setAddEventModel(false); + }, 1000); + + }) + .catch((error) => { + toast.error(error.message); // Handle error if needed + }); + }; + + const handleAddGuest = (guestEmail: string) => { + setSelectedGuests((prev) => + prev.includes(guestEmail) + ? prev.filter((id) => id !== guestEmail) + : [...prev, guestEmail], + ); + }; + + //edit section + const [editEvent] = useMutation(EDIT_EVENT) + const [editEventModel, setEditEventModel] = useState(false) + const [editedEvent, setEditedEvent] = useState({ + id: '', + title: '', + start: '', + end: '', + hostName: '', + timeToStart: '', + timeToEnd: '', + }); + + const handleEditEventModel = async (e: EventInput) => { + const event = data?.getEvents.find((event: any)=> event.id === e.event?.id) + if (event) { + if(event.user !== JSON.parse(localStorage.getItem('auth')!).userId) return + setEditedEvent((prev) => { + return { + ...prev, + id: event.id, + title: event.title, + start: event.start, + end: event.end, + hostName: event.hostName, + timeToStart: event.timeToStart, + timeToEnd: event.timeToEnd, + } + }) + setSelectedGuests(event.invitees.map((invitee: any) => invitee.email)) + setEditEventModel(true); + } }; + const handleEditEvent = async (e: any) => { + e.preventDefault() + const { id, ...rest } = editedEvent + editEvent({ + variables: { + eventId: id, + ...rest, + authToken: localStorage.getItem('auth_token'), + orgToken: localStorage.getItem('orgToken'), + invitees: selectedGuests, + }, + }) + .then(() => { + fetchData() + toast.success('Event has been updated!'); + setEditedEvent({ + id: '', + title: '', + start: '', + end: '', + hostName: '', + timeToStart: '', + timeToEnd: '', + }); + setSelectedGuests([]) + setTimeout(() => { + setEditEventModel(false); + }, 1000); + }) + .catch((error) => { + toast.error(error.message); // Handle error if needed + }); + } + + const removeEditModel = (e: any) => { + e.preventDefault() + setSelectedGuests([]) + setEditEventModel(!editEventModel) + } + + // delete section + const [showDeleteModal, setShowDeleteModal] = useState(false) + const [cancelEvent] = useMutation(CANCEL_EVENT) + + const handleDeleteConfirmation = (e: any) => { + e.preventDefault() + setShowDeleteModal(prev => !prev) + } + + const handleDelete = async (e: any) => { + e.preventDefault() + cancelEvent({ + variables: { + eventId: editedEvent.id, + authToken: localStorage.getItem('auth_token') + }, + }) + .then(() => { + fetchData() + toast.success('Event cancelled successfully') + setEditedEvent({ + id: '', + title: '', + start: '', + end: '', + hostName: '', + timeToStart: '', + timeToEnd: '', + }); + setSelectedGuests([]) + setTimeout(() => { + setShowDeleteModal(false) + setEditEventModel(false); + }, 1000); + } + ) + .catch(err => { + toast.error(err.message) + }) + } + return ( <> - {/* =========================== Start:: RegisterTraineeModel =========================== */}
@@ -125,14 +252,10 @@ const Calendar = () => {
- {/* istanbul ignore next */}
- /* istanbul ignore next */ - handleAddEvent(e) - } + data-testid="addEventForm" + className=" py-3 px-8 overflow-y-auto h-full " + onSubmit={(e) => handleAddEvent(e)} >
@@ -143,7 +266,6 @@ const Calendar = () => { className=" dark:bg-dark-tertiary border dark:text-white border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full" placeholder={t('Event title')} value={newEvent.title} - // eslint-disable-next-line prettier/prettier onChange={(e) => setNewEvent({ ...newEvent, title: e.target.value }) } @@ -159,8 +281,8 @@ const Calendar = () => { className=" dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full" placeholder={t('Host name')} value={newEvent.hostName} - onChange /* istanbul ignore next */={(e) => - /* istanbul ignore next */ setNewEvent({ + onChange={(e) => + setNewEvent({ ...newEvent, hostName: e.target.value, }) @@ -176,8 +298,8 @@ const Calendar = () => { placeholderText={t('Start Date')} style={{ marginRight: '10px' }} selected={newEvent.start} - onChange /* istanbul ignore next */={(start: any) => - /* istanbul ignore next */ setNewEvent({ + onChange={(start: any) => + setNewEvent({ ...newEvent, start, }) @@ -193,25 +315,109 @@ const Calendar = () => { placeholderText={t('End Date')} style={{ marginRight: '10px' }} selected={newEvent.end} - onChange=/* istanbul ignore next */ {(end: any) => - /* istanbul ignore next */ - setNewEvent({ ...newEvent, end }) - } + onChange={(end: any) => setNewEvent({ ...newEvent, end })} />
+
+
+
+ + setNewEvent({ + ...newEvent, + timeToStart: e.target.value, + }) + } + /> +
+
+ + setNewEvent({ + ...newEvent, + timeToEnd: e.target.value, + }) + } + /> +
+
+
+ +
+
+ {t('Add guests')} + +
+ {showTraineeDropdown ? + : ''} +
+ +
+ + +
+
+
+
+
+ +
+
+
+

+ {t('Edit event')} +

+
+
+
+
handleEditEvent(e)} + >
- /* istanbul ignore next */ - setNewEvent({ ...newEvent, timeToStart: e.target.value }) + type="text" + data-testid="editEventTitle" + name="eventTitle" + className=" dark:bg-dark-tertiary border dark:text-white border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full" + placeholder={t('Event title')} + value={editedEvent.title} + onChange={(e) => + setEditedEvent({ ...editedEvent, title: e.target.value }) } />
@@ -220,56 +426,186 @@ const Calendar = () => {
- /* istanbul ignore next */ - setNewEvent({ ...newEvent, timeToFinish: e.target.value }) + className=" dark:bg-dark-tertiary dark:text-white border border-primary rounded outline-none px-5 font-sans text-xs py-2 w-full" + placeholder={t('Host name')} + value={editedEvent.hostName} + onChange={(e) => + setEditedEvent({ + ...editedEvent, + hostName: e.target.value, + }) + } + /> +
+
+ +
+
+ + setEditedEvent({ + ...editedEvent, + start, + }) } />
+
+
+ setEditedEvent({ ...editedEvent, end })} + /> +
+
+ +
+
+
+ + setEditedEvent({ + ...editedEvent, + timeToStart: e.target.value, + }) + } + /> +
+
+ + setEditedEvent({ + ...editedEvent, + timeToEnd: e.target.value, + }) + } + /> +
+
+
+ +
+
+ {t('Add guests')} + +
+ {showTraineeDropdown ? + : ''} +
+
- +
+ + +
- {/* =========================== End:: RegisterTraineeModel =============================== */} + +
+
+
+

+ {t('Confirm Dialog')} +

+
+
+

Please confirm the cancellation of event {editedEvent.title}.

+
+ + +
+
+

{t('Calendar')}

- + :''} {loading ? ( ) : ( ({ + id: event.id, + end: moment(event.end).add({days:1}).format('YYYY-MM-DD'), + start: moment(event.start).format('YYYY-MM-DD'), + hostName: event.hostName, + timeToStart: event.timeToStart, + title: event.title, + timeToEnd: event.timeToEnd, + allDay: true, + }))} plugins={[dayGridPlugin, interactionPlugin]} initialView="dayGridMonth" + eventClick={handleEditEventModel} /> )}
diff --git a/src/components/CalendarConfirmation.tsx b/src/components/CalendarConfirmation.tsx new file mode 100644 index 000000000..d6fc3ad3f --- /dev/null +++ b/src/components/CalendarConfirmation.tsx @@ -0,0 +1,87 @@ +import { useMutation } from "@apollo/client"; +import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { toast } from "react-toastify" +import moment from "moment"; +import { Link } from "react-router-dom"; +import { RESPOND_TO_EVENT_INVITATION } from "../Mutations/event"; + +function CalendarConfirmation() { + const { t } = useTranslation() + const [respondToEventInvitation, { data, loading, error }] = useMutation(RESPOND_TO_EVENT_INVITATION) + const params = new URLSearchParams(window.location.search) + const respond = async () => { + try { + await respondToEventInvitation({ + variables: { + eventToken: params.get('eventToken') || 'missing_token', + authToken: localStorage.getItem('auth_token'), + }, + }) + toast.success("Successfully responded to invitation") + } catch (err: any) { + toast.error(err.message) + } + } + useEffect(() => { + respond() + }, []) + return ( +
+
+
+

+ {t('Event Response')} +

+
+
+ { + loading ? +
+

..Loading

+
+ : '' + } + { + error ? +
+

An Error Occured!

+
+ : '' + } + { + data ? +
+
    +
  • + Title: {data?.respondToEventInvitation.title} +
  • +
  • + Hostname: {data?.respondToEventInvitation.hostName} +
  • +
  • + When: {moment(data?.respondToEventInvitation.start).format("YYYY-MM-DD")} to {moment(data?.respondToEventInvitation.end).format("YYYY-MM-DD")} +
  • +
  • + Time: {data?.respondToEventInvitation.timeToStart} to {data?.respondToEventInvitation.timeToEnd} +
  • +
  • + Guests: +
      + {data?.respondToEventInvitation.invitees?.map((invitee: any) => ( +
    • {invitee.email} {invitee.status}
    • + ))} +
    +
  • +
+
+ : '' + } + Go to calendar +
+
+ + ) +} + +export default CalendarConfirmation \ No newline at end of file diff --git a/src/components/CoordinatorCard.tsx b/src/components/CoordinatorCard.tsx index d1a1bb38b..3eb33e30c 100644 --- a/src/components/CoordinatorCard.tsx +++ b/src/components/CoordinatorCard.tsx @@ -55,6 +55,7 @@ export const GET_TEAMS_CARDS = gql` coordinator { email + role profile { name firstName diff --git a/src/components/DashHeader.tsx b/src/components/DashHeader.tsx index 3aadddf09..dfc24d5a1 100644 --- a/src/components/DashHeader.tsx +++ b/src/components/DashHeader.tsx @@ -7,13 +7,13 @@ import { toast } from 'react-toastify'; import Avatar from '../assets/avatar.png'; import Notification from './Notification'; import ProfileDropdown from './ProfileDropdown'; -import { GET_PROFILE } from '../Mutations/User'; +import { GET_PROFILE } from '../queries/user.queries'; import { UserContext } from '../hook/useAuth'; import { - getAllNotification, NotificationSubscription, PUSH_NOTIFICATION_SUB, } from '../Mutations/notificationMutation'; +import { getAllNotification } from '../queries/notification.queries'; import { MenuContext } from '../hook/menuProvider'; import ToggleThemeButton from './TogglethemeIcon'; import LogoIcon from './logoIcon'; diff --git a/src/components/Docs/AdminDocs.tsx b/src/components/Docs/AdminDocs.tsx index 294b87b77..4dfaeee9a 100644 --- a/src/components/Docs/AdminDocs.tsx +++ b/src/components/Docs/AdminDocs.tsx @@ -15,9 +15,9 @@ import { ADD_SUB_DOCUMENTATION, DELETE_DOCUMENTATION, DELETE_SUB_DOCUMENTATION, - GET_DOCUMENTATION, UPDATE_DOCUMENTATION, } from '../../Mutations/manageStudentMutations'; +import { GET_DOCUMENTATION } from '../../queries/manageStudent.queries'; function AdminDocs() { useDocumentTitle('Documentation'); diff --git a/src/components/Docs/OthersDocs.tsx b/src/components/Docs/OthersDocs.tsx index 7efbe7de2..7441922fc 100644 --- a/src/components/Docs/OthersDocs.tsx +++ b/src/components/Docs/OthersDocs.tsx @@ -8,7 +8,7 @@ import DataTable from '../DataTable'; import Modal from './DocModel'; import Button from '../Buttons'; import useDocumentTitle from '../../hook/useDocumentTitle'; -import { GET_DOCUMENTATION } from '../../Mutations/manageStudentMutations'; +import { GET_DOCUMENTATION } from '../../queries/manageStudent.queries'; import { UserContext } from '../../hook/useAuth'; function TraineeDocs() { diff --git a/src/components/Docs/TraineeDocs.tsx b/src/components/Docs/TraineeDocs.tsx index 0e25255e5..7214b41ae 100644 --- a/src/components/Docs/TraineeDocs.tsx +++ b/src/components/Docs/TraineeDocs.tsx @@ -8,7 +8,7 @@ import DataTable from '../DataTable'; import Modal from './DocModel'; import Button from '../Buttons'; import useDocumentTitle from '../../hook/useDocumentTitle'; -import { GET_DOCUMENTATION } from '../../Mutations/manageStudentMutations'; +import { GET_DOCUMENTATION } from '../../queries/manageStudent.queries'; import { UserContext } from '../../hook/useAuth'; function TraineeDocs() { diff --git a/src/components/EventGuestList.tsx b/src/components/EventGuestList.tsx new file mode 100644 index 000000000..f9a532046 --- /dev/null +++ b/src/components/EventGuestList.tsx @@ -0,0 +1,106 @@ +import React from "react"; +import { useQuery } from "@apollo/client"; +import { toast } from "react-toastify"; +import { GET_ALL_USERS_QUERY } from "../Mutations/manageStudentMutations"; + +export const getRoleColor = (role: string) => { + switch (role) { + case 'admin': + return 'bg-red-500'; + case 'ttl': + return 'bg-yellow-500'; + case 'trainee': + return 'bg-green-500'; + case 'coordinator': + return 'bg-blue-500'; + case 'manager': + return 'bg-violet-500'; + default: + return 'bg-gray-500'; + } +}; + +export const getRoleTitle = (role: string) => { + switch (role) { + case 'admin': + return 'Admins'; + case 'ttl': + return 'TTLs'; + case 'trainee': + return 'Trainees'; + case 'coordinator': + return 'Coordinators'; + case 'manager': + return 'Managers'; + default: + return 'Others'; + } +} + +function EventGuestList({ selectedGuests, handleAddGuest }: { selectedGuests: string[], handleAddGuest: any }) { + const { loading: guestDataLoading, data: guestData } = useQuery( + GET_ALL_USERS_QUERY, + { + variables: { + orgToken: localStorage.getItem('orgToken'), + }, + fetchPolicy: 'network-only', + onError: (error) => { + toast.error(error.message); + }, + }, + ); + + const roles = ["admin", "trainee", "ttl", "coordinator","manager"] + const authUser = JSON.parse(localStorage.getItem('auth')!) + + return ( +
+ {guestDataLoading ? ( +

Loading...

+ ) : ( + <> + {roles.map((role: string, index: number) => ( +
+

{getRoleTitle(role)}

+ {guestData?.getAllUsers + .filter((user: any) => user.role === role) + .map((guest: any) => ( +
+ handleAddGuest(guest.email)} + disabled={guest.email === authUser?.email} + className="mr-2" + /> + +
+ ))} + {index === roles.length-1 ? ' ':
} +
+ ))} + + )} +
+ ) +} + +export default EventGuestList \ No newline at end of file diff --git a/src/components/LoginActivitiesTable.tsx b/src/components/LoginActivitiesTable.tsx index 1177660a8..45884d406 100644 --- a/src/components/LoginActivitiesTable.tsx +++ b/src/components/LoginActivitiesTable.tsx @@ -5,7 +5,7 @@ import React, { useState, useEffect } from 'react'; import { useQuery } from '@apollo/client'; -import { GET_LOGIN_ACTIVITIES } from '../Mutations/manageStudentMutations'; +import { GET_LOGIN_ACTIVITIES } from '../queries/manageStudent.queries'; interface LoginActivitiesData { loginActivities: LoginActivity[]; diff --git a/src/components/ProfileCoverpage.tsx b/src/components/ProfileCoverpage.tsx index 39605508c..1b9f97663 100644 --- a/src/components/ProfileCoverpage.tsx +++ b/src/components/ProfileCoverpage.tsx @@ -14,7 +14,7 @@ import { CameraIcon } from '@heroicons/react/outline'; import { useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; import Button from './Buttons'; -import { GET_PROFILE } from '../Mutations/User'; +import { GET_PROFILE } from '../queries/user.queries'; import Avatar from '../assets/avatar.png'; import Spinner from '../components/ButtonLoading'; import { UserContext } from '../hook/useAuth'; diff --git a/src/components/ProfileTabs.tsx b/src/components/ProfileTabs.tsx index 4d7058031..4665d4f3e 100644 --- a/src/components/ProfileTabs.tsx +++ b/src/components/ProfileTabs.tsx @@ -21,7 +21,7 @@ import { passwordFields } from '../constants/formFields'; import { UserContext } from '../hook/useAuth'; import { CountryComponent } from '../pages/Profile'; -import { GET_ALL_TRAINEES } from '../Mutations/Ratings'; +import { GET_ALL_TRAINEES } from '../queries/ratings.queries'; import { FaEdit, FaEraser, @@ -33,12 +33,14 @@ import { } from 'react-icons/fa'; import { ADD_REPO, - GET_GITHUB_STATISTICS, - GET_ORGANISATION, REMOVE_REPO, UPDATE_ORGANISATION_NAME, - GET_TRAINEE_PROFILE, } from '../Mutations/manageStudentMutations'; +import { + GET_GITHUB_STATISTICS, + GET_ORGANISATION, + GET_TRAINEE_PROFILE, +} from '../queries/manageStudent.queries'; import Spinner from './Spinner'; import GitHubActivityChart from './chartGitHub'; import BookOpenIcon from '@heroicons/react/outline/BookOpenIcon'; @@ -948,4 +950,4 @@ Add New */} {/* =========================== End:: EditOrganisationModal & AddNewRepositoryModel & RemoveRepositoryModel =============================== */}
); -} \ No newline at end of file +} diff --git a/src/components/TraineeAttendance.tsx b/src/components/TraineeAttendance.tsx index 48eca9ab3..9d15608f0 100644 --- a/src/components/TraineeAttendance.tsx +++ b/src/components/TraineeAttendance.tsx @@ -5,7 +5,7 @@ import { useQuery } from '@apollo/client'; import Pagination from '../components/Pagination'; import AttendanceData from '../dummyData/attendance.json'; import useDocumentTitle from '../hook/useDocumentTitle'; -import { GET_WEEKLY_ATTENDANCE } from '../Mutations/Attendance'; +import { GET_WEEKLY_ATTENDANCE } from '../queries/attendance.queries'; interface TraineeAttendanceData { getTraineeAttendanceByID: { @@ -205,4 +205,4 @@ const TraineeAttendance: React.FC = () => { ); }; -export default TraineeAttendance; \ No newline at end of file +export default TraineeAttendance; diff --git a/src/components/TraineeHeader.tsx b/src/components/TraineeHeader.tsx index de0b82b26..a91d48bc8 100644 --- a/src/components/TraineeHeader.tsx +++ b/src/components/TraineeHeader.tsx @@ -14,12 +14,10 @@ import useDarkMode from '../hook/useDarkMode'; import Sidebar from './Sidebar'; import Notification from './Notification'; import ProfileDropdown from './ProfileDropdown'; -import { GET_PROFILE } from '../Mutations/User'; +import { GET_PROFILE } from '../queries/user.queries'; import { UserContext } from '../hook/useAuth'; -import { - getAllNotification, - NotificationSubscription, -} from '../Mutations/notificationMutation'; +import { NotificationSubscription } from '../Mutations/notificationMutation'; +import { getAllNotification } from '../queries/notification.queries'; export const TICKETS_NOTS_SUB = gql` subscription OnTicket { diff --git a/src/components/TraineePerformance.tsx b/src/components/TraineePerformance.tsx index b7bbc986b..1c69435f2 100644 --- a/src/components/TraineePerformance.tsx +++ b/src/components/TraineePerformance.tsx @@ -4,7 +4,7 @@ import { useLazyQuery, gql, useQuery } from '@apollo/client'; import { toast } from 'react-toastify'; import Pagination from './Pagination'; import PerformanceData from '../dummyData/performance.json'; -import { TRAINEE_RATING } from '../Mutations/Ratings'; +import { TRAINEE_RATING } from '../queries/ratings.queries'; import RemarksModal from '../pages/ratings/CoordinatorRemarks'; import { UserContext } from '../hook/useAuth'; import { rowsType } from '../pages/ratings/frame'; diff --git a/src/components/TraineesHeader.tsx b/src/components/TraineesHeader.tsx index b7a2ecef4..6f8e9a589 100644 --- a/src/components/TraineesHeader.tsx +++ b/src/components/TraineesHeader.tsx @@ -14,12 +14,10 @@ import useDarkMode from '../hook/useDarkMode'; import Sidebar from './Sidebar'; import Notification from './Notification'; import ProfileDropdown from './ProfileDropdown'; -import { GET_PROFILE } from '../Mutations/User'; +import { GET_PROFILE } from '../queries/user.queries'; import { UserContext } from '../hook/useAuth'; -import { - getAllNotification, - NotificationSubscription, -} from '../Mutations/notificationMutation'; +import { NotificationSubscription } from '../Mutations/notificationMutation'; +import { getAllNotification } from '../queries/notification.queries'; export const TICKETS_NOTS_SUB = gql` subscription OnTicket { diff --git a/src/components/ratings/ViewWeeklyRatings.tsx b/src/components/ratings/ViewWeeklyRatings.tsx index 9a0035e07..c60bf9ab2 100644 --- a/src/components/ratings/ViewWeeklyRatings.tsx +++ b/src/components/ratings/ViewWeeklyRatings.tsx @@ -11,7 +11,7 @@ import Dropout from './Dropout'; import useViewTraineeRatings from './hooks/useViewTraineeRatings'; import Button from '../Buttons'; import { UPDATE_RATING } from '../../Mutations/Ratings'; -import { DEFAULT_GRADE } from '../../Mutations/MakeDefault'; +import { DEFAULT_GRADE } from '../../queries/DefaultGrading.queries'; function ViewSprintRatings({ traineeName, @@ -350,8 +350,8 @@ function ViewSprintRatings({ loggedUserRole === 'ttl') || loggedUserRole === 'coordinator' ? ( - + className={`${row.original?.Status?.status === 'drop' + ? 'bg-gray-500' + : 'bg-black' + } text-white rounded-xl px-3`} + onClick={() => { + setSelectedTraineeId(row.original?.email); + handleClickOpen2(); + }} + > + {row.original?.Status?.status === 'drop' ? 'Dropped' : 'View'} + ); }, @@ -293,9 +293,9 @@ function AdminTraineeDashboard() { /> {selectedRow === row.original.email && (
- <> + ref={modalRef} + className="absolute z-50 w-64 p-4 mt-2 overflow-hidden border border-gray-300 rounded-lg shadow-md dropdown right-4 bg-light-bg max-h-30 dark:bg-dark-bg"> + <>
@@ -1524,4 +1523,4 @@ function AdminTraineeDashboard() { ); } -export default AdminTraineeDashboard; \ No newline at end of file +export default AdminTraineeDashboard; diff --git a/src/pages/ForgotPassword.tsx b/src/pages/ForgotPassword.tsx index db7531401..69cfbdfae 100644 --- a/src/pages/ForgotPassword.tsx +++ b/src/pages/ForgotPassword.tsx @@ -8,10 +8,8 @@ import { toast } from 'react-toastify'; import Button from '../components/Buttons'; import useDocumentTitle from '../hook/useDocumentTitle'; import ButtonLoading from '../components/ButtonLoading'; -import { - FORGOT_PASSWORD, - VERIFY_RESET_PASSWORD_TOKEN, -} from '../Mutations/resetPassword'; +import { FORGOT_PASSWORD } from '../Mutations/resetPassword'; +import { VERIFY_RESET_PASSWORD_TOKEN } from '../queries/resetPassword.queries'; export default function ForgotPassword() { const navigate = useNavigate(); diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index 60ed051de..159532519 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -6,7 +6,7 @@ import ProfileCoverPage from '../components/ProfileCoverpage'; import ProfileTabs from '../components/ProfileTabs'; import { COUNTRIES } from '../constants/countries'; import useDocumentTitle from '../hook/useDocumentTitle'; -import { GET_PROFILE } from '../Mutations/User'; +import { GET_PROFILE } from '../queries/user.queries'; import Square from '../Skeletons/Square'; export function CountryComponent({ country }: any) { diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index b4da2a3ba..74af41c70 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -9,9 +9,11 @@ import useDocumentTitle from '../hook/useDocumentTitle'; import { updatePushNotifications, updateEmailNotifications, +} from '../Mutations/notificationMutation'; +import { updatedEmailNotifications, updatedPushNotifications, -} from '../Mutations/notificationMutation'; +} from '../queries/notification.queries'; import { UserContext } from '../hook/useAuth'; import { ThemeContext } from '../hook/ThemeProvider'; diff --git a/src/pages/TraineeAttendance.tsx b/src/pages/TraineeAttendance.tsx index 7e93774a7..624e78539 100644 --- a/src/pages/TraineeAttendance.tsx +++ b/src/pages/TraineeAttendance.tsx @@ -8,7 +8,8 @@ import { toast } from 'react-toastify'; import { useForm } from 'react-hook-form'; import { CircularProgressbar, buildStyles } from 'react-circular-progressbar'; import Pagination from '../components/Pagination'; -import { GET_ATTENDANCE, UPDATE_ATTENDANCE } from '../Mutations/Attendance'; +import { UPDATE_ATTENDANCE } from '../Mutations/Attendance'; +import { GET_ATTENDANCE } from '../queries/attendance.queries'; import 'react-circular-progressbar/dist/styles.css'; import ButtonLoading from '../components/ButtonLoading'; diff --git a/src/pages/TraineeDashboard.tsx b/src/pages/TraineeDashboard.tsx index 13e1e71f5..4a39a9096 100644 --- a/src/pages/TraineeDashboard.tsx +++ b/src/pages/TraineeDashboard.tsx @@ -26,7 +26,7 @@ import { gql, useQuery, useLazyQuery } from '@apollo/client'; import { useTranslation } from 'react-i18next'; import TraineeChart from '../components/TraineeDashboardChart'; import Table from '../components/TraineeTable'; -import { TRAINEE_RATING } from '../Mutations/Ratings'; +import { TRAINEE_RATING } from '../queries/ratings.queries'; // import { AiOutlineEye } from 'react-icons/ai'; import Comment from '../components/ViewComment'; import DataTable from '../components/DataTable'; diff --git a/src/pages/TraineeRatingDashboard.tsx b/src/pages/TraineeRatingDashboard.tsx index 8bef56836..c3873c695 100644 --- a/src/pages/TraineeRatingDashboard.tsx +++ b/src/pages/TraineeRatingDashboard.tsx @@ -13,17 +13,18 @@ import { Icon } from '@iconify/react'; import useDocumentTitle from '../hook/useDocumentTitle'; import Sidebar from '../components/Sidebar'; import Button from '../components/Buttons'; -import { DEFAULT_GRADE } from '../Mutations/MakeDefault'; +import { DEFAULT_GRADE } from '../queries/DefaultGrading.queries'; import { ADD_RATING, UPDATE_RATING, - RATING_BY_COHORT, GET_FEEDBACKS_SUBSCRIPTION, } from '../Mutations/Ratings'; import { GET_COHORTS_QUERY, GET_COHORT_TRAINEES_QUERY, -} from '../Mutations/manageStudentMutations'; +} from '../queries/manageStudent.queries'; + +import { RATING_BY_COHORT } from '../queries/ratings.queries'; import { sprint } from '../dummyData/ratings'; import DataTable from '../components/DataTable'; diff --git a/src/pages/invitation.tsx b/src/pages/invitation.tsx index e1598608b..d515caf47 100644 --- a/src/pages/invitation.tsx +++ b/src/pages/invitation.tsx @@ -11,7 +11,7 @@ import { toast } from 'react-toastify'; import InvitationCard from '../components/InvitationCard'; import DataTableStats from '../components/InvitationTable'; import InvitationModal from './invitationModalComponet'; -import { GET_INVITATIONS_STATISTICS_QUERY } from '../Mutations/invitationStats'; +import { GET_INVITATIONS_STATISTICS_QUERY } from '../queries/invitationStats.queries'; import InvitationCardSkeleton from '../Skeletons/InvitationCardSkeleton'; import { useTranslation } from 'react-i18next'; import { Icon } from '@iconify/react'; @@ -86,7 +86,7 @@ function Invitation() { const modalRef = useRef(null); const organizationToken = localStorage.getItem('orgToken'); - + const parseRange = (range: string) => { switch (range) { case 'Last 7 days': @@ -200,9 +200,9 @@ function Invitation() { { data: searchData, loading: searchLoading, error: searchError }, ] = useLazyQuery(GET_INVITATIONS, { variables: { - query: searchQuery, - orgToken: organizationToken, - }, + query: searchQuery, + orgToken: organizationToken, + }, fetchPolicy: 'network-only', }); @@ -360,9 +360,9 @@ function Invitation() { /> {selectedRow === row.id && (
- <> + ref={modalRef} + className="absolute z-50 w-64 p-4 mt-2 overflow-hidden border border-gray-300 rounded-lg shadow-md dropdown right-4 bg-light-bg max-h-30 dark:bg-dark-bg"> + <>
{ const [open, setOpen] = React.useState(false); const [open2, setOpen2] = React.useState(false); - const [selectedTraineeId, setSelectedTraineeId]= useState() + const [selectedTraineeId, setSelectedTraineeId] = useState() const handleClickOpen2 = async () => { setIsLoaded(true); @@ -124,18 +124,17 @@ const TtlTraineeDashboard = () => { } > - + className={`${row.original?.Status?.status === 'drop' + ? 'bg-gray-500' + : 'bg-black' + } text-white rounded-xl px-3`} + onClick={() => { + setSelectedTraineeId(row.original?.email); + handleClickOpen2(); + }} + > + {row.original?.Status?.status === 'drop' ? 'Dropped' : 'View'} +
); }, @@ -202,7 +201,7 @@ const TtlTraineeDashboard = () => { }); }, []); - console.log("trainee data ig",traineeData) + console.log('trainee data ig', traineeData); return ( <> @@ -216,7 +215,7 @@ const TtlTraineeDashboard = () => { className="rounded-lg relative" fullWidth > - {traineeData.map(data => { + {traineeData.map(data => { if (data.email === selectedTraineeId) { return true, + result: { + data: { + createEvent: { + end: "2024-09-12T00:00:00.000Z", + hostName: "Morales", + start: "2024-09-12T00:00:00.000Z", + timeToEnd: "08:00", + timeToStart: "09:00", + title: "Another Event", + } + } + } +} + +const addEventErrorMock: MockedResponse = { + request: { + query: ADD_EVENT, + }, + variableMatcher: () => true, + error: new Error("An error occured") +} + +const editEventMock = { + request: { + query: EDIT_EVENT + }, + variableMatcher: () => true, + result: { + data: { + editEvent: { + end: "2024-09-12T00:00:00.000Z", + hostName: "Jack", + start: "2024-09-12T00:00:00.000Z", + timeToEnd: "10:00", + timeToStart: "09:00", + title: "Edited Mock Event", + } + } + } +} + +const cancelEventMock: MockedResponse = { + request: { + query: CANCEL_EVENT, + variables: { + eventId: '1', + authToken: 'mocked_auth_token' + } + }, + result: { + data: { + cancelEvent: { + end: "2024-09-12T00:00:00.000Z", + hostName: "Jack", + start: "2024-09-12T00:00:00.000Z", + timeToEnd: "10:00", + timeToStart: "09:00", + title: "Mock Event", + } + } + } +} + +jest.mock('react-toastify',()=>({ + toast: { + success: jest.fn(), + error: jest.fn(), + } +})) + +beforeEach(()=>{ + localStorage.setItem('auth_token','mocked_auth_token') + localStorage.setItem('orgToken','mocked_org_token') + localStorage.setItem('auth', JSON.stringify({ + auth: true, + email: "testing@gmail.com", + firstName: "Jack", + role: "admin", + userId: "1" + })) + jest.useFakeTimers() +}) + +afterEach(()=>{ + localStorage.clear() + jest.runAllTimers() + cleanup() +}) describe('Calendar Tests', () => { - it('should open Calendar model', () => { - const removeModelMck = jest.fn(); - const { getByTestId } = render( - - - - - , + it('should display Calendar events', async () => { + render( + + + ); - const removeModel = getByTestId('removeModel'); - fireEvent.click(removeModel); - expect(removeModelMck).toBeCalledTimes(0); + await waitFor(() => { + expect(screen.getByText("Mocked Event")).toBeInTheDocument() + expect(screen.getByText("Jack")).toBeInTheDocument() + expect(screen.getByText("Another Mocked Event")).toBeInTheDocument() + expect(screen.getByText("Jones")).toBeInTheDocument() + }) }); - it('should handle add event', () => { - const handleAddEventMck = jest.fn(); - const { getByTestId } = render( - - - - - , + + it('should add event when addEventForm is submitted', async () => { + render( + + + ); - const handleAddEvent = getByTestId('handleAddEvent'); - fireEvent.click(handleAddEvent); - expect(handleAddEventMck).toBeCalledTimes(0); + + const addEventModal = screen.getByTestId('addEventModal'); + const handleAddEventModal = screen.getByTestId('handleAddEventModal'); + const addEventForm = screen.getByTestId("addEventForm") + expect(addEventForm).toBeInTheDocument() + await waitFor(async()=>{ + fireEvent.click(handleAddEventModal); + fireEvent.submit(addEventForm) + expect(toast.success).toHaveBeenCalledWith('Event has been added!') + expect(addEventModal).toHaveClass("hidden") + }) + screen.debug() }); - it('should handle Date Click', () => { - const handleDateClickMck = jest.fn(); - const { getByTestId } = render( - - - - - , + + it('should show an error toast when addEvent fails', async () => { + render( + + + ); - const handleDateClick = getByTestId('handleDateClick'); - fireEvent.click(handleDateClick); - expect(handleDateClickMck).toBeCalledTimes(0); + + const handleAddEventModal = screen.getByTestId('handleAddEventModal'); + const addEventForm = screen.getByTestId("addEventForm") + expect(addEventForm).toBeInTheDocument() + await waitFor(async()=>{ + fireEvent.click(handleAddEventModal); + fireEvent.submit(addEventForm) + expect(toast.error).toHaveBeenCalledWith('An error occured') + }) }); - it('should set new event', () => { - const setNewEventMck = jest.fn(); - const { getByTestId } = render( - - - - - , + it('should edit event when editEventForm is submitted', async () => { + render( + + + ); - const setNewEvent = getByTestId('setNewEvent'); - fireEvent.click(setNewEvent); - expect(setNewEventMck).toBeCalledTimes(0); - }); - it('should set add event model', () => { - const setAddEventModelMck = jest.fn(); - expect(setAddEventModelMck).toBeCalledTimes(0); + const editEventModal = screen.getByTestId('editEventModal') + const editEventForm = screen.getByTestId("editEventForm") + expect(editEventModal).toHaveClass("hidden") + await waitFor(() => { + const event = screen.getByTestId("event-1") + fireEvent.click(event) + expect(editEventModal).toHaveClass("block") + fireEvent.submit(editEventForm) + expect(toast.success).toHaveBeenCalledWith('Event has been updated!') + }) }); - it('should set data', () => { - const setDataMck = jest.fn(); - expect(setDataMck).toBeCalledTimes(0); + it('should delete event when delete button is clicked', async () => { + render( + + + + ); + + const deleteEventModal = screen.getByTestId("deleteEventModal") + const handleDeleteModal = screen.getByTestId("handleDeleteModal") + const handleDelete = screen.getByTestId("handleDelete") + await waitFor(() => { + const event = screen.getByTestId("event-1") + fireEvent.click(event) + fireEvent.click(handleDeleteModal) + expect(deleteEventModal).toHaveClass("block") + fireEvent.click(handleDelete) + expect(toast.success).toHaveBeenCalledWith('Event cancelled successfully') + }) }); }); diff --git a/tests/components/CalendarConfirmation.test.tsx b/tests/components/CalendarConfirmation.test.tsx new file mode 100644 index 000000000..c84fbd246 --- /dev/null +++ b/tests/components/CalendarConfirmation.test.tsx @@ -0,0 +1,158 @@ +import "@testing-library/jest-dom" +import { screen, render, waitFor, cleanup } from '@testing-library/react'; +import React from 'react'; +import { MockedProvider } from "@apollo/client/testing"; +import { toast } from "react-toastify"; +import CalendarConfirmation from "../../src/components/CalendarConfirmation"; +import { RESPOND_TO_EVENT_INVITATION } from "../../src/Mutations/event"; +import { MemoryRouter } from "react-router"; + +const acceptedEventInvitationMock = [ + { + request: { + query: RESPOND_TO_EVENT_INVITATION, + variables: { + eventToken: "mocked_event_token", + authToken: "mocked_auth_token", + } + }, + result: { + data: { + respondToEventInvitation: { + end: "2024-09-12T00:00:00.000Z", + hostName: "Jack", + start: "2024-09-12T00:00:00.000Z", + timeToEnd: "09:30", + title: "Mock Event", + timeToStart: "08:30", + invitees: [ + { + email: "testing@gmail.com", + status: "accepted" + } + ] + } + } + } + } +] + +const declinedEventInvitationMock = [ + { + request: { + query: RESPOND_TO_EVENT_INVITATION, + variables: { + eventToken: "mocked_event_token", + authToken: "mocked_auth_token", + } + }, + result: { + data: { + respondToEventInvitation: { + end: "2024-09-12T00:00:00.000Z", + hostName: "Jack", + start: "2024-09-12T00:00:00.000Z", + timeToEnd: "09:30", + title: "Mock Event", + timeToStart: "08:30", + invitees: [ + { + email: "testing@gmail.com", + status: "declined" + } + ] + } + } + } + } +] + +const eventInvitationResponseErrorMock = [ + { + request: { + query: RESPOND_TO_EVENT_INVITATION, + variables: { + eventToken: "mocked_event_token", + authToken: "mocked_auth_token", + } + }, + error: new Error("An error occured") + } +] + +jest.mock('react-toastify',()=>({ + toast: { + success: jest.fn(), + error: jest.fn(), + } +})) + +beforeEach(()=>{ + localStorage.setItem('auth_token','mocked_auth_token') + localStorage.setItem('orgToken','mocked_org_token') + localStorage.setItem('auth', JSON.stringify({ + auth: true, + email: "testing@gmail.com", + firstName: "Jack", + role: "admin", + userId: "1" + })) + }) + +afterEach(()=>{ + localStorage.clear() + cleanup() +}) + +describe("CalendarConfirmation Tests", () => { + + it("should render accepted event invitation", () => { + window.location.search = "?eventToken=mocked_event_token" + render( + + + + + + ) + waitFor(()=>{ + expect(toast.success).toHaveBeenCalledWith("Successfully responded to invitation") + expect(screen.getByText("Mock Event")).toBeInTheDocument() + expect(screen.getByText("testing@gmail.com")).toBeInTheDocument() + expect(screen.getByText("accepted")).toBeInTheDocument() + }) + }) + + it("should render declined event invitation", () => { + window.location.search = "?eventToken=mocked_event_token" + render( + + + + + + ) + waitFor(()=>{ + expect(toast.success).toHaveBeenCalledWith("Successfully responded to invitation") + expect(screen.getByText("Mock Event")).toBeInTheDocument() + expect(screen.getByText("testing@gmail.com")).toBeInTheDocument() + expect(screen.getByText("declined")).toBeInTheDocument() + }) + }) + + it("should render error when mutation returns an error", () => { + window.location.search = "?eventToken=mocked_event_token" + render( + + + + + + ) + waitFor(()=>{ + expect(toast.error).toHaveBeenCalledWith("An error occured") + }) + }) + + +}) \ No newline at end of file diff --git a/tests/components/DashHeader.test.tsx b/tests/components/DashHeader.test.tsx index 38df82626..d498156c7 100644 --- a/tests/components/DashHeader.test.tsx +++ b/tests/components/DashHeader.test.tsx @@ -13,8 +13,6 @@ import renderer from 'react-test-renderer'; import '../../test/jest/__mocks__/matchMedia'; import DashHeader from '../../src/components/DashHeader'; -import { GET_PROFILE } from '../../src/Mutations/User'; - const client = new ApolloClient({ cache: new InMemoryCache() }); describe('DashHeader test ', () => { diff --git a/tests/components/EventGuestList.test.tsx b/tests/components/EventGuestList.test.tsx new file mode 100644 index 000000000..3e0237368 --- /dev/null +++ b/tests/components/EventGuestList.test.tsx @@ -0,0 +1,138 @@ +import "@testing-library/jest-dom" +import { fireEvent, screen, render, waitFor, cleanup } from '@testing-library/react'; +import React from 'react'; +import { MockedProvider } from "@apollo/client/testing"; +import { toast } from "react-toastify"; +import { GET_ALL_USERS_QUERY } from "../../src/Mutations/manageStudentMutations"; +import EventGuestList, { getRoleColor, getRoleTitle } from "../../src/components/EventGuestList"; + +const getAllUsersMock = [{ + request: { + query: GET_ALL_USERS_QUERY, + }, + variableMatcher: () => true, + result: { + data: { + getAllUsers: [ + { + id: "1", + email: "testing@gmail.com", + role: "trainee", + profile: { + firstName: "Jack", + lastName: "Mukundwa" + } + } + ] + } + }, +}] + +const getAllUsersErrorMock = [{ + request: { + query: GET_ALL_USERS_QUERY, + variables: { + orgToken: "mocked_org_token" + } + }, + error: new Error("An error occured") +}] + +jest.mock('react-toastify',()=>({ + toast: { + success: jest.fn(), + error: jest.fn(), + } +})) + +beforeEach(()=>{ + localStorage.setItem('auth_token','mocked_auth_token') + localStorage.setItem('orgToken','mocked_org_token') + localStorage.setItem('auth', JSON.stringify({ + auth: true, + email: "testing@gmail.com", + firstName: "Jack", + role: "admin", + userId: "1" + })) + }) + +afterEach(()=>{ + localStorage.clear() + cleanup() +}) + +describe("EventGuestList Tests", () => { + it("renders event guest list", () => { + const selectedGuestsMock: string[] = [] + const handleAddGuestMock = jest.fn() + + render( + + + + ) + waitFor(()=>{ + expect(screen.getByText("Trainees")).toBeInTheDocument() + expect(screen.getByText("Jack")).toBeInTheDocument() + expect(screen.getByText("Mukundwa")).toBeInTheDocument() + }) + }) + it("should select invitees", () => { + const selectedGuestsMock: string[] = [] + const handleAddGuestMock = jest.fn() + + render( + + + + ) + waitFor(()=>{ + const input1 = screen.getByTestId("input-1") + const span1 = screen.getByTestId("span-1") + fireEvent.click(input1) + expect(handleAddGuestMock).toHaveBeenCalledWith("testing@gmail.com") + expect(span1).toHaveClass("bg-green-500") + }) + }) + it("should display errors", () => { + const selectedGuestsMock: string[] = [] + const handleAddGuestMock = jest.fn() + + render( + + + + ) + waitFor(()=>{ + expect(toast.error).toHaveBeenCalledWith("An error occured") + }) + }) + + it("should return the correct tailwind background class",()=>{ + expect(getRoleColor("admin")).toEqual('bg-red-500') + expect(getRoleColor("ttl")).toEqual('bg-yellow-500') + expect(getRoleColor("trainee")).toEqual('bg-green-500') + expect(getRoleColor("coordinator")).toEqual('bg-blue-500') + expect(getRoleColor("manager")).toEqual('bg-violet-500') + expect(getRoleColor("hello")).toEqual('bg-gray-500') + }) + + it("should return the correct role title",()=>{ + expect(getRoleTitle("admin")).toEqual('Admins') + expect(getRoleTitle("ttl")).toEqual('TTLs') + expect(getRoleTitle("trainee")).toEqual('Trainees') + expect(getRoleTitle("coordinator")).toEqual('Coordinators') + expect(getRoleTitle("manager")).toEqual('Managers') + expect(getRoleTitle("hello")).toEqual('Others') + }) +}) \ No newline at end of file diff --git a/tests/components/TraineeAttendance.test.tsx b/tests/components/TraineeAttendance.test.tsx index 69f7c0dbf..3beab36ec 100644 --- a/tests/components/TraineeAttendance.test.tsx +++ b/tests/components/TraineeAttendance.test.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { render, waitFor, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import TraineeAttendance, { optimizeWeekData } from '../../src/components/TraineeAttendance'; // Adjust the import path accordingly -import { GET_WEEKLY_ATTENDANCE } from '../../src/Mutations/Attendance'; +import { GET_WEEKLY_ATTENDANCE } from '../../src/queries/attendance.queries'; const mockData = { getTraineeAttendanceByID: [ diff --git a/tests/components/__snapshots__/AdminTraineeDashboard.test.tsx.snap b/tests/components/__snapshots__/AdminTraineeDashboard.test.tsx.snap index d19fbdd52..09654d8a0 100644 --- a/tests/components/__snapshots__/AdminTraineeDashboard.test.tsx.snap +++ b/tests/components/__snapshots__/AdminTraineeDashboard.test.tsx.snap @@ -141,13 +141,13 @@ Array [ onTouchEnd={[Function]} >
({ diff --git a/tests/containers/admin-dashboard/sessionTest.test.tsx b/tests/containers/admin-dashboard/sessionTest.test.tsx index c17c025b3..75bcd0742 100644 --- a/tests/containers/admin-dashboard/sessionTest.test.tsx +++ b/tests/containers/admin-dashboard/sessionTest.test.tsx @@ -4,11 +4,11 @@ import { MockedProvider } from '@apollo/client/testing'; import '@testing-library/jest-dom'; import AdminSission from '../../../src/containers/admin-dashBoard/Sessions'; import { - GET_SESSIONS, CREATE_SESSION, DELETE_SESSION, EDIT_SESSION, } from '../../../src/Mutations/session'; +import{ GET_SESSIONS} from '../../../src/queries/session.queries' jest.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => key }), diff --git a/tests/other-tests/AdminDashboard.test.tsx b/tests/other-tests/AdminDashboard.test.tsx index 84848c08f..98110d903 100644 --- a/tests/other-tests/AdminDashboard.test.tsx +++ b/tests/other-tests/AdminDashboard.test.tsx @@ -9,6 +9,7 @@ import { waitFor, waitForElementToBeRemoved, } from '@testing-library/react'; +import '@testing-library/jest-dom' import { act } from 'react-dom/test-utils'; import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client'; import AdminDashboard from '../../src/pages/AdminDashboard'; diff --git a/tests/pages/__snapshots__/AdminTraineeDashboard.test.tsx.snap b/tests/pages/__snapshots__/AdminTraineeDashboard.test.tsx.snap index 4818c0175..0b988d269 100644 --- a/tests/pages/__snapshots__/AdminTraineeDashboard.test.tsx.snap +++ b/tests/pages/__snapshots__/AdminTraineeDashboard.test.tsx.snap @@ -141,13 +141,13 @@ Array [ onTouchEnd={[Function]} >