From d818c66900e8bb5df03be95a6d3ccfc26e11be7e Mon Sep 17 00:00:00 2001
From: Daniel Fusimoto Pires <84727721+FusiDaniel@users.noreply.github.com>
Date: Mon, 20 Nov 2023 18:33:00 -0300
Subject: [PATCH] test: reviews page (#177)
---
.../CommentsList/CommentList.test.ts | 81 +
.../ConceptsHorizontalChart.test.ts | 39 +
.../ConceptsHorizontalChart.vue | 7 +-
.../ConceptsPieChart/ConceptsPieChart.test.ts | 21 +
.../FeedbackAlert/FeedbackAlert.vue | 1 +
.../PendingReviewEnrollment.test.ts | 39 +
.../PendingReviewEnrollment.vue | 2 +-
.../PendingReviewEnrollmentList.test.ts | 40 +
.../ReviewDialog/ReviewDialog.test.ts | 262 +++
.../components/ReviewDialog/ReviewDialog.vue | 84 +-
.../ReviewsWelcome/ReviewsWelcome.test.ts | 22 +
.../components/SearchBar/SearchBar.test.ts | 125 ++
.../src/components/SearchBar/SearchBar.vue | 2 +
.../SingleComment/SingleComment.test.ts | 197 ++
.../SingleComment/SingleComment.vue | 33 +-
.../SubjectReview/SubjectReview.test.ts | 119 ++
.../SubjectReview/SubjectReview.vue | 6 +-
.../TeacherReview/TeacherReview.test.ts | 103 +
apps/container/src/mocks/enrollments.ts | 210 +-
apps/container/src/mocks/handlers.ts | 17 +-
apps/container/src/mocks/reviews.ts | 1765 +++++++++++++++++
apps/container/src/test-utils.ts | 10 +-
.../src/views/Admin/AdminView.test.ts | 11 +
.../views/Confirmation/ConfirmationView.vue | 19 +-
.../src/views/History/HistoryView.vue | 1 +
.../src/views/Planning/PlanningView.test.ts | 11 +
.../src/views/Recovery/RecoveryView.test.ts | 6 +-
.../src/views/Reviews/ReviewsView.test.ts | 95 +
.../container/src/views/SignUp/SignUpView.vue | 18 +-
packages/services/src/comments.ts | 23 +-
packages/services/src/reviews.ts | 14 +-
packages/types/src/comments.ts | 18 +-
packages/types/src/enrollments.ts | 1 +
packages/types/src/subjects.ts | 8 +-
packages/types/src/teachers.ts | 9 +-
35 files changed, 3272 insertions(+), 147 deletions(-)
create mode 100644 apps/container/src/components/CommentsList/CommentList.test.ts
create mode 100644 apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.test.ts
create mode 100644 apps/container/src/components/ConceptsPieChart/ConceptsPieChart.test.ts
create mode 100644 apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.test.ts
create mode 100644 apps/container/src/components/PendingReviewEnrollmentList/PendingReviewEnrollmentList.test.ts
create mode 100644 apps/container/src/components/ReviewDialog/ReviewDialog.test.ts
create mode 100644 apps/container/src/components/ReviewsWelcome/ReviewsWelcome.test.ts
create mode 100644 apps/container/src/components/SearchBar/SearchBar.test.ts
create mode 100644 apps/container/src/components/SingleComment/SingleComment.test.ts
create mode 100644 apps/container/src/components/SubjectReview/SubjectReview.test.ts
create mode 100644 apps/container/src/components/TeacherReview/TeacherReview.test.ts
create mode 100644 apps/container/src/mocks/reviews.ts
create mode 100644 apps/container/src/views/Admin/AdminView.test.ts
create mode 100644 apps/container/src/views/Planning/PlanningView.test.ts
create mode 100644 apps/container/src/views/Reviews/ReviewsView.test.ts
diff --git a/apps/container/src/components/CommentsList/CommentList.test.ts b/apps/container/src/components/CommentsList/CommentList.test.ts
new file mode 100644
index 00000000..3daca06c
--- /dev/null
+++ b/apps/container/src/components/CommentsList/CommentList.test.ts
@@ -0,0 +1,81 @@
+import { render, screen } from '@/test-utils';
+import { CommentsList } from '.';
+import { comments } from '@/mocks/reviews';
+import { server } from '@/mocks/server';
+import { HttpResponse, http } from 'msw';
+
+describe('', () => {
+ test('render Comments List', async () => {
+ render(CommentsList, {
+ props: {
+ teacherId: '111',
+ selectedSubject: 'Todas as matérias',
+ },
+ });
+ expect(
+ await screen.findByText(RegExp(comments.data[0].comment, 'i')),
+ ).toBeInTheDocument();
+ expect(
+ screen.getAllByText(RegExp(comments.data[0].subject.name, 'i'))[0],
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(RegExp(comments.data[1].comment, 'i')),
+ ).toBeInTheDocument();
+ expect(
+ screen.getAllByText(RegExp(comments.data[1].subject.name, 'i'))[0],
+ ).toBeInTheDocument();
+ });
+ test('render empty Comments List', async () => {
+ server.use(
+ http.get(`*/comments/*`, () =>
+ HttpResponse.json({
+ data: [],
+ total: 0,
+ }),
+ ),
+ );
+ render(CommentsList, {
+ props: {
+ teacherId: '111',
+ selectedSubject: 'Todas as matérias',
+ },
+ });
+ expect(
+ await screen.findByText(
+ /Infelizmente, nenhum comentário foi encontrado/i,
+ ),
+ ).toBeInTheDocument();
+ });
+ test('show toaster when Fetching Teacher Data Error', async () => {
+ server.use(
+ http.get(`*/reviews/teachers/*`, () =>
+ HttpResponse.json(null, { status: 500 }),
+ ),
+ );
+
+ render(CommentsList, {
+ props: {
+ teacherId: '111',
+ selectedSubject: 'Todas as matérias',
+ },
+ });
+ expect(
+ await screen.findByText('Erro ao carregar o(a) professor(a)'),
+ ).toBeInTheDocument();
+ });
+ test('show toaster when Fetching Comments Error', async () => {
+ server.use(
+ http.get(`*/comments/*`, () => HttpResponse.json(null, { status: 500 })),
+ );
+ render(CommentsList, {
+ props: {
+ teacherId: '111',
+ selectedSubject: 'Todas as matérias',
+ },
+ });
+
+ expect(
+ await screen.findByText('Erro ao carregar comentários'),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.test.ts b/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.test.ts
new file mode 100644
index 00000000..f75a3284
--- /dev/null
+++ b/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.test.ts
@@ -0,0 +1,39 @@
+import { render, screen } from '@/test-utils';
+import { ConceptsHorizontalChart } from '.';
+import { subjectInfo } from '@/mocks/reviews';
+
+describe('', () => {
+ test('render Concepts Horizontal Chart with regular found teacher', async () => {
+ render(ConceptsHorizontalChart, {
+ props: {
+ gradeData: subjectInfo.specific[2],
+ },
+ });
+
+ const tooltipTextPercentage = `${
+ subjectInfo.specific[2].distribution[0].conceito
+ }: ${(
+ (100 * subjectInfo.specific[2].distribution[0].count) /
+ subjectInfo.specific[2].count
+ ).toFixed(1)}%`;
+
+ const tooltipTextAmount = `${subjectInfo.specific[2].distribution[0].count} notas`;
+ expect(
+ await screen.findByText(RegExp(tooltipTextPercentage, 'i')),
+ ).toBeInTheDocument();
+ expect(
+ await screen.getByText(RegExp(tooltipTextAmount, 'i')),
+ ).toBeInTheDocument();
+ });
+
+ test('render Concepts Horizontal Chart with untrustable threshold ', async () => {
+ render(ConceptsHorizontalChart, {
+ props: {
+ gradeData: subjectInfo.specific[1],
+ },
+ });
+ expect(
+ await screen.findByText('Dados sem muitas amostras'),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.vue b/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.vue
index 2e5a8c0e..b0fc2384 100644
--- a/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.vue
+++ b/apps/container/src/components/ConceptsHorizontalChart/ConceptsHorizontalChart.vue
@@ -6,9 +6,10 @@
:key="grade.conceito"
:hide-after="0"
:content="`
- ${grade.conceito}: ${grades[grade.conceito].toFixed(1)}% (${
- grade.count
- } notas)`"
+ ${grade.conceito}: ${(
+ (100 * grades[grade.conceito]) /
+ gradeData.count
+ ).toFixed(1)}% (${grade.count} notas)`"
>
acc + curr, 0);
+
+describe('', () => {
+ test('render Concepts Pie Highchart', async () => {
+ render(ConceptsPieChart, {
+ props: {
+ grades: concepts,
+ },
+ });
+
+ Object.values(concepts).forEach((concept) => {
+ expect(
+ screen.getByText(RegExp(((100 * concept) / total).toFixed(1), 'i')),
+ ).toBeInTheDocument();
+ });
+ });
+});
diff --git a/apps/container/src/components/FeedbackAlert/FeedbackAlert.vue b/apps/container/src/components/FeedbackAlert/FeedbackAlert.vue
index 4aaed266..49f29268 100644
--- a/apps/container/src/components/FeedbackAlert/FeedbackAlert.vue
+++ b/apps/container/src/components/FeedbackAlert/FeedbackAlert.vue
@@ -30,6 +30,7 @@ const props = defineProps({
onMounted(() => {
ElMessage({
+ showClose: true,
message: props.text,
type: props.type,
duration: props.duration,
diff --git a/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.test.ts b/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.test.ts
new file mode 100644
index 00000000..775f6ff2
--- /dev/null
+++ b/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.test.ts
@@ -0,0 +1,39 @@
+import { render, screen } from '@/test-utils';
+import { PendingReviewEnrollment } from '.';
+import { enrollments } from '@/mocks/enrollments';
+
+describe('', () => {
+ test('render the Pending Review Enrollment with a theorical only subject', async () => {
+ render(PendingReviewEnrollment, {
+ props: {
+ enrollment: enrollments[1],
+ },
+ });
+ expect(
+ await screen.findByText(enrollments[1].disciplina),
+ ).toBeInTheDocument();
+ expect(screen.getByText('teoria')).toBeInTheDocument();
+ });
+ test('render the Pending Review Enrollment with a pratical only subject', async () => {
+ render(PendingReviewEnrollment, {
+ props: {
+ enrollment: enrollments[30],
+ },
+ });
+ expect(
+ await screen.findByText(enrollments[30].disciplina),
+ ).toBeInTheDocument();
+ expect(screen.getByText('prática')).toBeInTheDocument();
+ });
+ test('render the Pending Review Enrollment with a theorical and pratical subject', async () => {
+ render(PendingReviewEnrollment, {
+ props: {
+ enrollment: enrollments[0],
+ },
+ });
+ expect(
+ await screen.findByText(enrollments[0].disciplina),
+ ).toBeInTheDocument();
+ expect(screen.getByText('teoria e prática')).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.vue b/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.vue
index 4c3f96b6..7e80e78a 100644
--- a/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.vue
+++ b/apps/container/src/components/PendingReviewEnrollment/PendingReviewEnrollment.vue
@@ -64,7 +64,7 @@ import { Enrollment } from 'types';
const showDialog = ref(false);
const conceptStyle = computed(() => ({
- backgroundColor: conceptsColor[props.enrollment.conceito ?? ''],
+ backgroundColor: conceptsColor[props.enrollment.conceito],
height: '54px',
width: '54px',
fontSize: '34px',
diff --git a/apps/container/src/components/PendingReviewEnrollmentList/PendingReviewEnrollmentList.test.ts b/apps/container/src/components/PendingReviewEnrollmentList/PendingReviewEnrollmentList.test.ts
new file mode 100644
index 00000000..aa17ca4c
--- /dev/null
+++ b/apps/container/src/components/PendingReviewEnrollmentList/PendingReviewEnrollmentList.test.ts
@@ -0,0 +1,40 @@
+import { render, screen, userEvent } from '@/test-utils';
+import { PendingReviewEnrollmentList } from '.';
+import { enrollments } from '@/mocks/enrollments';
+import { server } from '@/mocks/server';
+import { HttpResponse, http } from 'msw';
+
+describe('', () => {
+ test('render Pending Review Enrollments List with a reviewable subjects', async () => {
+ render(PendingReviewEnrollmentList);
+ expect(
+ await screen.findByText(/Seus professores para avaliar/i),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(enrollments[26].subject.name),
+ ).toBeInTheDocument();
+ expect(screen.getByText('teoria')).toBeInTheDocument();
+ expect(screen.getByText(enrollments[27].subject.name)).toBeInTheDocument();
+ expect(screen.getByText('prática')).toBeInTheDocument();
+ expect(screen.getByText(enrollments[28].subject.name)).toBeInTheDocument();
+ expect(screen.getByText('teoria e prática')).toBeInTheDocument();
+ });
+ test('render Pending Review Enrollments List with error', async () => {
+ server.use(
+ http.get(`*/enrollments`, () => HttpResponse.json(null, { status: 500 })),
+ );
+ render(PendingReviewEnrollmentList);
+ expect(
+ await screen.findByText('Erro ao buscar suas disciplinas cursadas'),
+ ).toBeInTheDocument();
+ });
+ test('open Review Dialog when click on Enrollment and close when click on clos', async () => {
+ render(PendingReviewEnrollmentList);
+ await userEvent.click(
+ screen.getByRole('button', {
+ name: RegExp(enrollments[26].subject.name, 'i'),
+ }),
+ );
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/ReviewDialog/ReviewDialog.test.ts b/apps/container/src/components/ReviewDialog/ReviewDialog.test.ts
new file mode 100644
index 00000000..0c8e92c9
--- /dev/null
+++ b/apps/container/src/components/ReviewDialog/ReviewDialog.test.ts
@@ -0,0 +1,262 @@
+import {
+ render,
+ screen,
+ userEvent,
+ waitFor,
+ expectToasterToHaveText,
+} from '@/test-utils';
+import { ReviewDialog } from '.';
+import { userCreateComment, userUpdateComment } from '@/mocks/reviews';
+import { enrollment } from '@/mocks/enrollments';
+import { formatSeason } from 'utils';
+import { server } from '@/mocks/server';
+import { HttpResponse, http } from 'msw';
+import { ElMessage } from 'element-plus';
+
+const commentAreaPlaceholder =
+ 'Faça aqui um comentário em relação ao docente e sua disciplina.';
+
+describe('', () => {
+ beforeEach(() => {
+ vitest.resetAllMocks();
+ server.resetHandlers();
+ ElMessage('');
+ });
+
+ test.each([
+ { tagName: 'teoria', subjectType: 'teoria' },
+ { tagName: 'prática', subjectType: 'pratica' },
+ ])(
+ 'render Review Dialog and be able to comment (%s)%#',
+ async ({ tagName, subjectType }) => {
+ server.use(
+ http.get(`*/enrollments/*`, () => {
+ return HttpResponse.json({
+ ...enrollment,
+ comments: [],
+ teoria: {},
+ pratica: {},
+ [subjectType]: {
+ ...enrollment[subjectType as 'teoria' | 'pratica'],
+ comment: undefined,
+ },
+ });
+ }),
+ );
+ render(ReviewDialog, {
+ props: {
+ enrollment: enrollment,
+ showDialog: true,
+ tags: [
+ tagName,
+ formatSeason(enrollment.year + ':' + enrollment.quad),
+ ],
+ },
+ });
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+ expect(await screen.findByText(tagName)).toBeInTheDocument();
+ await userEvent.type(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ userCreateComment.comment,
+ );
+ await userEvent.click(screen.getByRole('button', { name: /Enviar/i }));
+ await expectToasterToHaveText('Comentário enviado com sucesso');
+ },
+ );
+ test.each([
+ { tagName: 'teoria', commentAvaliable: ['teoria'] },
+ { tagName: 'prática', commentAvaliable: ['pratica'] },
+ { tagName: 'teoria e prática', commentAvaliable: ['teoria', 'pratica'] },
+ ])(
+ 'render Review Dialog with user comment and be able to edit comment %s %#',
+ async ({ tagName, commentAvaliable }) => {
+ server.use(
+ http.get(`*/enrollments/*`, () => {
+ return HttpResponse.json({
+ ...enrollment,
+ comments: commentAvaliable,
+ teoria: {},
+ pratica: {},
+ [commentAvaliable[0]]: {
+ ...enrollment[commentAvaliable[0] as 'teoria' | 'pratica'],
+ comment: {
+ ...enrollment[commentAvaliable[0] as 'teoria' | 'pratica']
+ ?.comment,
+ comment: userCreateComment.comment,
+ },
+ },
+ });
+ }),
+ );
+
+ render(ReviewDialog, {
+ props: {
+ enrollment: enrollment,
+ showDialog: true,
+ tags: [
+ tagName,
+ formatSeason(enrollment.year + ':' + enrollment.quad),
+ ],
+ },
+ });
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+ await waitFor(() =>
+ expect(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ ).toHaveProperty('value', userCreateComment.comment),
+ );
+
+ await userEvent.clear(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ );
+ await userEvent.type(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ userUpdateComment.comment,
+ );
+ await userEvent.click(
+ screen.getByRole('button', { name: /Atualizar comentário/i }),
+ );
+
+ await expectToasterToHaveText('Comentário editado com sucesso');
+ },
+ );
+ test.each([
+ { tagName: 'teoria', commentAvaliable: ['teoria'] },
+ { tagName: 'prática', commentAvaliable: ['pratica'] },
+ { tagName: 'teoria e prática', commentAvaliable: ['teoria', 'pratica'] },
+ ])(
+ 'render Review Dialog with theorical subject type and missing atributes %s %#',
+ async ({ tagName, commentAvaliable }) => {
+ render(ReviewDialog, {
+ props: {
+ enrollment: {
+ ...enrollment,
+ _id: undefined,
+ teoria: {},
+ pratica: {},
+ ...commentAvaliable.reduce(
+ (acc, comment) => ({
+ ...acc,
+ [comment]: {
+ ...enrollment[comment as 'teoria' | 'pratica'],
+ _id: undefined,
+ name: undefined,
+ },
+ }),
+ {},
+ ),
+ },
+ showDialog: true,
+ tags: [tagName],
+ },
+ });
+
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+ expect(screen.getByText(tagName)).toBeInTheDocument();
+ await expectToasterToHaveText(
+ 'Erro ao carregar as informações do professor desta disciplina',
+ );
+ },
+ );
+ test('show error alert when fetching Teacher Enrollment Error', async () => {
+ server.use(
+ http.get(`*/enrollments/*`, () =>
+ HttpResponse.json(null, { status: 500 }),
+ ),
+ );
+ render(ReviewDialog, {
+ props: {
+ enrollment: enrollment,
+ showDialog: true,
+ tags: [],
+ },
+ });
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+
+ await expectToasterToHaveText(
+ 'Erro ao carregar as informações do professor desta disciplina',
+ );
+ });
+ test('show error alert when create comment error', async () => {
+ server.use(
+ http.get(`*/enrollments/*`, () => {
+ return HttpResponse.json({
+ ...enrollment,
+ comments: [],
+ teoria: {},
+ pratica: {},
+ });
+ }),
+ http.post(`*/comments/*`, () => HttpResponse.json(null, { status: 500 })),
+ );
+ render(ReviewDialog, {
+ props: {
+ enrollment: enrollment,
+ showDialog: true,
+ tags: ['teoria', formatSeason(enrollment.year + ':' + enrollment.quad)],
+ },
+ });
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+ expect(await screen.findByText('teoria')).toBeInTheDocument();
+ await userEvent.type(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ userCreateComment.comment,
+ );
+ await userEvent.click(screen.getByRole('button', { name: /Enviar/i }));
+ await expectToasterToHaveText('Ocorreu um erro ao enviar o comentário');
+ });
+ test('show error alert when update comment error', async () => {
+ server.use(
+ http.put(`*/comments/*`, () => HttpResponse.json(null, { status: 500 })),
+ http.get(`*/enrollments/*`, () => {
+ return HttpResponse.json({
+ ...enrollment,
+ comments: ['teoria'],
+
+ pratica: {},
+ teoria: {
+ ...enrollment.teoria,
+ comment: {
+ ...enrollment.teoria?.comment,
+ comment: userCreateComment.comment,
+ },
+ },
+ });
+ }),
+ );
+ render(ReviewDialog, {
+ props: {
+ enrollment: enrollment,
+ showDialog: true,
+ tags: ['teoria', formatSeason(enrollment.year + ':' + enrollment.quad)],
+ },
+ });
+ expect(await screen.findByRole('dialog')).toBeInTheDocument();
+ await waitFor(() =>
+ expect(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ ).toHaveProperty('value', userCreateComment.comment),
+ );
+
+ await userEvent.clear(screen.getByPlaceholderText(commentAreaPlaceholder));
+ await userEvent.type(
+ screen.getByPlaceholderText(commentAreaPlaceholder),
+ userUpdateComment.comment,
+ );
+ await userEvent.click(
+ screen.getByRole('button', { name: /Atualizar comentário/i }),
+ );
+
+ await expectToasterToHaveText('Ocorreu um erro ao editar o comentário');
+ });
+ test('not render Dialog if props is false', async () => {
+ render(ReviewDialog, {
+ props: {
+ enrollment: enrollment,
+ showDialog: false,
+ tags: ['teoria', formatSeason(enrollment.year + ':' + enrollment.quad)],
+ },
+ });
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/ReviewDialog/ReviewDialog.vue b/apps/container/src/components/ReviewDialog/ReviewDialog.vue
index 76250665..52304eb4 100644
--- a/apps/container/src/components/ReviewDialog/ReviewDialog.vue
+++ b/apps/container/src/components/ReviewDialog/ReviewDialog.vue
@@ -1,7 +1,7 @@
@@ -69,7 +69,7 @@
-
+
props.enrollment?._id || '');
-const subjectType = computed(() => props.tags[0]);
+const subjectType = computed(() => {
+ if (props.tags[0] === 'teoria e prática') return 'teoria';
+ return props.tags[0];
+});
+
const teacherId = computed(() => {
+ let id = '';
if (subjectType.value === 'teoria e prática')
- return (
- props.enrollment?.pratica?._id || props.enrollment?.teoria?._id || ''
- );
- if (subjectType.value === 'prática')
- return props.enrollment?.pratica?._id || '';
- return props.enrollment?.teoria?._id || '';
+ id = props.enrollment?.pratica?._id || props.enrollment?.teoria?._id || '';
+ else if (subjectType.value === 'prática')
+ id = props.enrollment?.pratica?._id || '';
+ else id = props.enrollment?.teoria?._id || '';
+
+ return id;
});
+const teacherIdError = ref(false);
+if (!teacherId.value) {
+ teacherIdError.value = true;
+}
+
const teacherName = computed(() => {
if (subjectType.value === 'teoria e prática')
return (
@@ -155,19 +165,15 @@ const {
});
const comment = ref('');
-const teacherEnrollmentCommentTeoria = computed(
- () => teacherEnrollment.value?.data.teoria?.comment?.comment,
-);
-const teacherEnrollmentCommentPratica = computed(
- () => teacherEnrollment.value?.data.pratica?.comment?.comment,
-);
+const teacherEnrollmentComment = computed(() => ({
+ teoria: teacherEnrollment.value?.data.teoria?.comment?.comment,
+ prática: teacherEnrollment.value?.data.pratica?.comment?.comment,
+}));
+
const userCommentMessage = computed({
get: () => {
const currentComment =
- subjectType.value === 'prática'
- ? teacherEnrollmentCommentPratica.value
- : teacherEnrollmentCommentTeoria.value;
-
+ teacherEnrollmentComment.value[subjectType.value as 'teoria' | 'prática'];
return comment.value ? comment.value : currentComment ?? '';
},
set: (value: string) => {
@@ -178,17 +184,15 @@ const userCommentMessage = computed({
const disableMutateComment = computed(() => {
return (
!userCommentMessage.value ||
- [
- teacherEnrollmentCommentTeoria.value,
- teacherEnrollmentCommentPratica.value,
- ].includes(userCommentMessage.value)
+ teacherEnrollmentComment.value[
+ subjectType.value as 'teoria' | 'prática'
+ ] === userCommentMessage.value
);
});
-const hasUserComment = computed(() =>
- subjectType.value === 'prática'
- ? !!teacherEnrollmentCommentPratica.value
- : !!teacherEnrollmentCommentTeoria.value,
+const hasUserComment = computed(
+ () =>
+ !!teacherEnrollmentComment.value[subjectType.value as 'teoria' | 'prática'],
);
const queryClient = useQueryClient();
@@ -206,10 +210,18 @@ const { mutate: mutateCreate, isPending: isCreatingComment } = useMutation({
queryClient.invalidateQueries({
queryKey: ['enrollments', 'get', subjectId],
});
- ElMessage.success('Comentário enviado com sucesso');
+ ElMessage({
+ message: 'Comentário enviado com sucesso',
+ type: 'success',
+ showClose: true,
+ });
},
onError: () => {
- ElMessage.error('Ocorreu um erro ao enviar o comentário');
+ ElMessage({
+ message: 'Ocorreu um erro ao enviar o comentário',
+ type: 'error',
+ showClose: true,
+ });
},
});
@@ -229,10 +241,18 @@ const { mutate: mutateUpdate, isPending: isUpdatingComment } = useMutation({
queryClient.invalidateQueries({
queryKey: ['enrollments', 'get', enrollmentId],
});
- ElMessage.success('Comentário editado com sucesso');
+ ElMessage({
+ message: 'Comentário editado com sucesso',
+ type: 'success',
+ showClose: true,
+ });
},
onError: () => {
- ElMessage.error('Ocorreu um erro ao editar o comentário');
+ ElMessage({
+ message: 'Ocorreu um erro ao editar o comentário',
+ type: 'error',
+ showClose: true,
+ });
},
});
diff --git a/apps/container/src/components/ReviewsWelcome/ReviewsWelcome.test.ts b/apps/container/src/components/ReviewsWelcome/ReviewsWelcome.test.ts
new file mode 100644
index 00000000..fd84c54f
--- /dev/null
+++ b/apps/container/src/components/ReviewsWelcome/ReviewsWelcome.test.ts
@@ -0,0 +1,22 @@
+import { render, screen } from '@/test-utils';
+import { ReviewsWelcome } from '.';
+
+describe('', () => {
+ test('render Reviews Welcome', () => {
+ render(ReviewsWelcome);
+ expect(
+ screen.getByRole('img', { name: /Animação de review/i }),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ /coletando informações públicas como turmas de uma disciplinas e unimos com as informações fornecidas pelos usuários./i,
+ ),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(/Todos nossos dados de comentários e conceitos estão armazenados em nuvem e estão criptografados./i),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(/Interface responsiva, acesse pelo celular/i),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/SearchBar/SearchBar.test.ts b/apps/container/src/components/SearchBar/SearchBar.test.ts
new file mode 100644
index 00000000..28da8ee9
--- /dev/null
+++ b/apps/container/src/components/SearchBar/SearchBar.test.ts
@@ -0,0 +1,125 @@
+import { render, screen, userEvent } from '@/test-utils';
+import { SearchBar } from '.';
+import { useRouter } from 'vue-router';
+import { subjectSearch, teacherSearch } from '@/mocks/reviews';
+import { server } from '@/mocks/server';
+import { HttpResponse, http } from 'msw';
+
+vi.mock('vue-router', async () => ({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ createWebHistory: vi.fn(),
+}));
+
+const replaceMock = vi.fn();
+
+describe('', () => {
+ beforeEach(() => {
+ vi.mocked(useRouter).mockReturnValue({
+ go: vi.fn(),
+ push: vi.fn(),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {},
+ },
+ },
+ } as unknown as ReturnType);
+ });
+
+ test('type must replace current route', async () => {
+ render(SearchBar);
+ await userEvent.type(
+ await screen.findByPlaceholderText(
+ /Digite o nome do professor ou disciplina/i,
+ ),
+ 'teste',
+ );
+ expect(replaceMock).toHaveBeenCalledWith({
+ name: 'reviews',
+ query: { q: 'teste' },
+ });
+ });
+ test('render SearchBar, type something, and click on teacher result', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ name: 'reviews',
+ query: { q: 'teste' },
+ },
+ },
+ } as unknown as ReturnType);
+ render(SearchBar);
+
+ await userEvent.click(
+ await screen.findByPlaceholderText(
+ /Digite o nome do professor ou disciplina/i,
+ ),
+ );
+ expect(
+ screen.getByRole('button', { name: subjectSearch.data[0].name }),
+ ).toBeInTheDocument();
+
+ await userEvent.click(
+ screen.getByRole('button', { name: teacherSearch.data[0].name }),
+ );
+ expect(replaceMock).toHaveBeenCalledWith({
+ name: 'reviews',
+ query: { q: teacherSearch.data[0].name, teacherId: teacherSearch.data[0]._id },
+ });
+ });
+ test('render SearchBar, type something, and click on subject result', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ name: 'reviews',
+ query: { q: 'teste' },
+ },
+ },
+ } as unknown as ReturnType);
+ render(SearchBar);
+
+ await userEvent.click(
+ await screen.findByPlaceholderText(
+ /Digite o nome do professor ou disciplina/i,
+ ),
+ );
+ expect(
+ screen.getByRole('button', { name: subjectSearch.data[0].name }),
+ ).toBeInTheDocument();
+
+ await userEvent.click(
+ screen.getByRole('button', { name: subjectSearch.data[0].name }),
+ );
+ expect(replaceMock).toHaveBeenCalledWith({
+ name: 'reviews',
+ query: { q: subjectSearch.data[0].name, subjectId: subjectSearch.data[0]._id },
+ });
+ });
+ test('show Error Teachers and Error Subjects toasters', async () => {
+ server.use(
+ http.get(`*/teachers/search`, () => HttpResponse.json(null, { status: 500 })),
+ http.get(`*/subjects/search`, () => HttpResponse.json(null, { status: 500 })),
+ );
+ vi.mocked(useRouter).mockReturnValue({
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ name: 'reviews',
+ query: { q: 'teste' },
+ },
+ },
+ } as unknown as ReturnType);
+ render(SearchBar);
+ expect(
+ await screen.findByText(/Erro ao buscar professores/i),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(/Erro ao buscar disciplinas/i),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/SearchBar/SearchBar.vue b/apps/container/src/components/SearchBar/SearchBar.vue
index 5b5c421e..2fdd7a1a 100644
--- a/apps/container/src/components/SearchBar/SearchBar.vue
+++ b/apps/container/src/components/SearchBar/SearchBar.vue
@@ -29,6 +29,8 @@
variant="plain"
@click="enterSearch(item.id, item.type, item.name)"
class="item"
+ role="button"
+ :name="item.name"
>
', () => {
+ test('render Comment, give like and recommendation, them remove like and recomendation', async () => {
+ server.use(
+ http.post(`*/reactions/*`, () => HttpResponse.json(), {
+ once: true,
+ }),
+ http.post(`*/reactions/*`, () => HttpResponse.json(), {
+ once: true,
+ }),
+ );
+ render(SingleComment, {
+ props: {
+ comment: {
+ ...comments.data[0],
+ myReactions: {},
+ reactionsCount: {
+ like: 50,
+ recommendation: 150,
+ },
+ },
+ },
+ });
+ expect(
+ await screen.findByText(RegExp(comments.data[0].comment, 'i')),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(RegExp(comments.data[0].subject.name, 'i')),
+ ).toBeInTheDocument();
+
+ await userEvent.click(screen.getByRole('button', { name: /Deixar like/i }));
+ await userEvent.click(
+ screen.getByRole('button', { name: /Deixar recomendação/i }),
+ );
+ await waitFor(() => {
+ expect(screen.getByText('51')).toBeInTheDocument();
+ });
+ await waitFor(() => {
+ expect(screen.getByText('151')).toBeInTheDocument();
+ });
+ await userEvent.click(
+ screen.getByRole('button', { name: /Remover like/i }),
+ );
+ await userEvent.click(
+ screen.getByRole('button', { name: /Remover recomendação/i }),
+ );
+ await waitFor(() => {
+ expect(screen.getByText('50')).toBeInTheDocument();
+ });
+ await waitFor(() => {
+ expect(screen.getByText('150')).toBeInTheDocument();
+ });
+ });
+ test('render Comment, give like and recommendation and show error toaster', async () => {
+ server.use(
+ http.post(
+ `*/reactions/*`,
+ () =>
+ HttpResponse.json(
+ {
+ status: 400,
+ name: 'BadRequest',
+ type: 'BadRequest',
+ error: 'Reaction like error',
+ },
+ {
+ status: 400,
+ },
+ ),
+ {
+ once: true,
+ },
+ ),
+ http.post(
+ `*/reactions/*`,
+ () =>
+ HttpResponse.json(
+ {
+ status: 400,
+ name: 'BadRequest',
+ type: 'BadRequest',
+ error: 'Reaction recommendation error',
+ },
+ {
+ status: 400,
+ },
+ ),
+ {
+ once: true,
+ },
+ ),
+ );
+ render(SingleComment, {
+ props: {
+ comment: {
+ ...comments.data[0],
+ reactionsCount: {
+ like: 50,
+ recommendation: 150,
+ },
+ },
+ },
+ });
+ expect(
+ await screen.findByText(RegExp(comments.data[0].comment, 'i')),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(RegExp(comments.data[0].subject.name, 'i')),
+ ).toBeInTheDocument();
+ await userEvent.click(screen.getByRole('button', { name: /Deixar like/i }));
+ await userEvent.click(
+ screen.getByRole('button', { name: /Deixar recomendação/i }),
+ );
+ expect(await screen.findByText('Reaction like error')).toBeInTheDocument();
+ expect(
+ await screen.findByText('Reaction recommendation error'),
+ ).toBeInTheDocument();
+ });
+ test('render Comment, remove like and recommendation and show error toaster', async () => {
+ server.use(
+ http.delete(
+ `*/reactions/*`,
+ () =>
+ HttpResponse.json(
+ {
+ status: 400,
+ name: 'BadRequest',
+ type: 'BadRequest',
+ error: 'Reaction remove like error',
+ },
+ {
+ status: 400,
+ },
+ ),
+ {
+ once: true,
+ },
+ ),
+ http.delete(
+ `*/reactions/*`,
+ () =>
+ HttpResponse.json(
+ {
+ status: 400,
+ name: 'BadRequest',
+ type: 'BadRequest',
+ error: 'Reaction remove recommendation error',
+ },
+ {
+ status: 400,
+ },
+ ),
+ {
+ once: true,
+ },
+ ),
+ );
+ render(SingleComment, {
+ props: {
+ comment: {
+ ...comments.data[0],
+ myReactions: {
+ like: true,
+ recommendation: true,
+ },
+ reactionsCount: {
+ like: 50,
+ recommendation: 150,
+ },
+ },
+ },
+ });
+ expect(
+ await screen.findByText(RegExp(comments.data[0].comment, 'i')),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(RegExp(comments.data[0].subject.name, 'i')),
+ ).toBeInTheDocument();
+ await userEvent.click(
+ screen.getByRole('button', { name: /Remover like/i }),
+ );
+ await userEvent.click(
+ screen.getByRole('button', { name: /Remover recomendação/i }),
+ );
+ expect(
+ await screen.findByText('Reaction remove like error'),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText('Reaction remove recommendation error'),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/components/SingleComment/SingleComment.vue b/apps/container/src/components/SingleComment/SingleComment.vue
index fbd4b38d..0a988e53 100644
--- a/apps/container/src/components/SingleComment/SingleComment.vue
+++ b/apps/container/src/components/SingleComment/SingleComment.vue
@@ -59,6 +59,7 @@
>
) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
@@ -144,7 +152,11 @@ const { mutate: mutateRecommendation, isPending: isPendingRecommendation } =
recommendationCount.value++;
},
onError: (error: AxiosError) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
@@ -156,7 +168,11 @@ const { mutate: mutateRemoveLike, isPending: isPendingRemoveLike } =
likeCount.value--;
},
onError: (error: AxiosError) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
@@ -170,7 +186,11 @@ const {
recommendationCount.value--;
},
onError: (error: AxiosError) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
@@ -183,8 +203,9 @@ const season = computed(() => {
const [year, quad] = props.comment.enrollment.season?.split(':') ?? [];
return formatSeason(
- (year ?? props.comment.enrollment.year) + ':' +
- (quad ?? props.comment.enrollment.quad)
+ (year ?? props.comment.enrollment.year) +
+ ':' +
+ (quad ?? props.comment.enrollment.quad),
);
});
diff --git a/apps/container/src/components/SubjectReview/SubjectReview.test.ts b/apps/container/src/components/SubjectReview/SubjectReview.test.ts
new file mode 100644
index 00000000..028fad5b
--- /dev/null
+++ b/apps/container/src/components/SubjectReview/SubjectReview.test.ts
@@ -0,0 +1,119 @@
+import { render, screen } from '@/test-utils';
+import { SubjectReview } from '.';
+import { useRouter } from 'vue-router';
+import { subjectSearch } from '@/mocks/reviews';
+import { server } from '@/mocks/server';
+import { HttpResponse, http } from 'msw';
+
+vi.mock('vue-router', async () => ({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ createWebHistory: vi.fn(),
+}));
+
+const replaceMock = vi.fn();
+
+describe('', () => {
+ beforeEach(() => {
+ vi.mocked(useRouter).mockReturnValue({
+ go: vi.fn(),
+ push: vi.fn(),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: 'test name',
+ subjectId: 'test id',
+ },
+ },
+ },
+ } as unknown as ReturnType);
+ });
+
+ test('render subject review', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: subjectSearch.data[0].name,
+ subjectId: subjectSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+
+ render(SubjectReview, {
+ props: {
+ subjectId: subjectSearch.data[0]._id,
+ },
+ });
+ expect(
+ await screen.findByText(subjectSearch.data[0].name),
+ ).toBeInTheDocument();
+ expect(await screen.findByText(/Nome do Professor/i)).toBeInTheDocument();
+ });
+ test('render subject that demands review', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: subjectSearch.data[0].name,
+ subjectId: subjectSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+
+ render(SubjectReview, {
+ props: {
+ subjectId: subjectSearch.data[0]._id,
+ },
+ });
+ expect(
+ await screen.findByText(subjectSearch.data[0].name),
+ ).toBeInTheDocument();
+ expect(await screen.findByText(/Nome do Professor/i)).toBeInTheDocument();
+ });
+ test('fetching teacher error toaster', async () => {
+ server.use(
+ http.get(`*/reviews/subjects/*`, () =>
+ HttpResponse.json(null, { status: 500 }),
+ ),
+ );
+
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: subjectSearch.data[0].name,
+ subjectId: subjectSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+
+ render(SubjectReview, {
+ props: {
+ subjectId: subjectSearch.data[0]._id,
+ },
+ });
+ expect(await screen.findByText('Erro ao carregar dados da disciplina'));
+ });
+});
diff --git a/apps/container/src/components/SubjectReview/SubjectReview.vue b/apps/container/src/components/SubjectReview/SubjectReview.vue
index 9b6c2e38..7af0c3f3 100644
--- a/apps/container/src/components/SubjectReview/SubjectReview.vue
+++ b/apps/container/src/components/SubjectReview/SubjectReview.vue
@@ -171,7 +171,11 @@ watch(
() => isFetchingSubjectError.value,
() => {
isFetchingSubjectError.value &&
- ElMessage.error('Erro ao carregar dados da disciplina');
+ ElMessage({
+ message: 'Erro ao carregar dados da disciplina',
+ type: 'error',
+ showClose: true,
+ });
},
);
diff --git a/apps/container/src/components/TeacherReview/TeacherReview.test.ts b/apps/container/src/components/TeacherReview/TeacherReview.test.ts
new file mode 100644
index 00000000..50ae5697
--- /dev/null
+++ b/apps/container/src/components/TeacherReview/TeacherReview.test.ts
@@ -0,0 +1,103 @@
+import { render, screen } from '@/test-utils';
+import { TeacherReview } from '.';
+import { useRouter } from 'vue-router';
+import { concepts, teacherSearch } from '@/mocks/reviews';
+import { HttpResponse, http } from 'msw';
+import { server } from '@/mocks/server';
+
+vi.mock('vue-router', async () => ({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ createWebHistory: vi.fn(),
+}));
+
+const replaceMock = vi.fn();
+
+const total = Object.values(concepts).reduce((acc, curr) => acc + curr, 0);
+
+describe('', () => {
+ beforeEach(() => {
+ vi.mocked(useRouter).mockReturnValue({
+ go: vi.fn(),
+ push: vi.fn(),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: 'test name',
+ teacherId: 'test id',
+ },
+ },
+ },
+ } as unknown as ReturnType);
+ });
+
+ test.skip('render teacher review', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: teacherSearch.data[0].name,
+ teacherId: teacherSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+
+ render(TeacherReview, {
+ props: {
+ teacherId: teacherSearch.data[0]._id,
+ },
+ });
+ expect(
+ await screen.findByText(/Provavelmente esse professor cobra presença/i),
+ ).toBeInTheDocument();
+
+ Object.values(concepts).forEach(async (concept) => {
+ expect(
+ await screen.findByText(
+ RegExp(((100 * concept) / total).toFixed(1), 'i'),
+ ),
+ ).toBeInTheDocument();
+ });
+ });
+ test('fetching teacher error toaster', async () => {
+ server.use(
+ http.get(`*/reviews/teachers/*`, () =>
+ HttpResponse.json(null, { status: 500 }),
+ ),
+ );
+
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: teacherSearch.data[0].name,
+ teacherId: teacherSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+
+ render(TeacherReview, {
+ props: {
+ teacherId: teacherSearch.data[0]._id,
+ },
+ });
+ expect(
+ await screen.findByText('Erro ao carregar dados do(a) professor(a)'),
+ );
+ });
+});
diff --git a/apps/container/src/mocks/enrollments.ts b/apps/container/src/mocks/enrollments.ts
index cd8322b0..33674091 100644
--- a/apps/container/src/mocks/enrollments.ts
+++ b/apps/container/src/mocks/enrollments.ts
@@ -671,92 +671,92 @@ export const enrollments: Enrollment[] = [
year: 2022,
},
{
- _id: '649520e035f8a7217a0c21ae',
+ _id: '65038416216580ff36b3c280',
comments: [],
- disciplina: 'Linguagens Formais e Automata',
- pratica: null,
- quad: 1,
+ conceito: 'A',
+ creditos: 4,
+ disciplina: 'Sistemas Inteligentes',
+ quad: 2,
subject: {
- _id: '5bf5fbdc436c414f35a8f15c',
- name: 'Linguagens Formais e Automata',
- search: 'Linguagens Formais E Automata',
- updatedAt: '2018-11-22T00:44:12.281Z',
- createdAt: '2018-11-22T00:44:12.281Z',
+ _id: '5bf5fbdc436c414f35a8f2b8',
+ name: 'Sistemas Inteligentes',
+ search: 'Sistemas Inteligentes',
+ updatedAt: '2018-11-22T00:44:12.286Z',
+ createdAt: '2018-11-22T00:44:12.286Z',
__v: 0,
creditos: 4,
},
+ updatedAt: '2023-10-27T00:29:19.916Z',
+ year: 2023,
+ pratica: {
+ _id: '5bf5fb65d741524f090c918f',
+ name: 'Joao Henrique Ranhel Ribeiro',
+ updatedAt: '2018-11-22T00:42:13.858Z',
+ createdAt: '2018-11-22T00:42:13.858Z',
+ __v: 0,
+ },
teoria: {
- _id: '5bf5fb65d741524f090c9022',
- name: 'Alexandre Donizeti Alves',
- updatedAt: '2018-11-22T00:42:13.855Z',
- createdAt: '2018-11-22T00:42:13.855Z',
+ _id: '5bf5fb65d741524f090c918f',
+ name: 'Joao Henrique Ranhel Ribeiro',
+ updatedAt: '2018-11-22T00:42:13.858Z',
+ createdAt: '2018-11-22T00:42:13.858Z',
__v: 0,
},
- updatedAt: '2023-08-21T22:03:46.888Z',
- year: 2023,
- conceito: 'A',
- creditos: 4,
},
{
- _id: '649520e035f8a7217a0c21b0',
+ _id: '65038416216580ff36b3c28b',
comments: [],
- disciplina: 'Redes Convergentes',
- pratica: null,
- quad: 1,
+ conceito: 'A',
+ creditos: 4,
+ disciplina: 'Prática Avançada de Programação A',
+ quad: 2,
subject: {
- _id: '60d9dd4a882a2a00180ff26e',
- name: 'Redes Convergentes',
- search: 'Redes Convergentes',
- updatedAt: '2021-06-28T14:31:38.013Z',
- createdAt: '2021-06-28T14:31:38.013Z',
- __v: 0,
- },
- teoria: {
- _id: '5bf5fb65d741524f090c908a',
- name: 'Carlos Alberto Kamienski',
- updatedAt: '2018-11-22T00:42:13.856Z',
- createdAt: '2018-11-22T00:42:13.856Z',
+ _id: '5bf5fbdc436c414f35a8f244',
+ name: 'Prática Avançada de Programação A',
+ search: 'Pratica Avancada De Programacao A',
+ updatedAt: '2018-11-22T00:44:12.284Z',
+ createdAt: '2018-11-22T00:44:12.284Z',
__v: 0,
+ creditos: 4,
},
- updatedAt: '2023-08-21T22:03:46.940Z',
+ updatedAt: '2023-10-17T13:15:03.084Z',
year: 2023,
- conceito: 'A',
- creditos: 4,
- },
- {
- _id: '649520e035f8a7217a0c21b2',
- comments: [],
- disciplina: 'Segurança de Dados',
pratica: {
- _id: '63726e627b18ad001887f1a3',
+ _id: '62c415928059c2001800d454',
alias: [],
- name: 'Rodrigo Izidoro Tinini',
- updatedAt: '2022-11-14T16:35:46.576Z',
- createdAt: '2022-11-14T16:35:46.576Z',
+ name: 'Geiza Cristina Da Silva',
+ updatedAt: '2022-07-05T10:42:26.686Z',
+ createdAt: '2022-07-05T10:42:26.686Z',
__v: 0,
},
- quad: 1,
+ teoria: null,
+ },
+ {
+ _id: '65038416216580ff36b3c282',
+ comments: [],
+ conceito: 'A',
+ creditos: 2,
+ disciplina: 'Vida Artificial na Computação',
+ quad: 2,
subject: {
- _id: '5bf5fbdc436c414f35a8f29a',
- name: 'Segurança de Dados',
- search: 'Seguranca De Dados',
- updatedAt: '2018-11-22T00:44:12.285Z',
- createdAt: '2018-11-22T00:44:12.285Z',
+ _id: '5bf5fbdc436c414f35a8f343',
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ createdAt: '2018-11-22T00:44:12.287Z',
__v: 0,
- creditos: 4,
+ creditos: 2,
},
+ updatedAt: '2023-10-17T13:15:03.079Z',
+ year: 2023,
+ pratica: null,
teoria: {
- _id: '63726e507b18ad001887f0a9',
- alias: [],
- name: 'Rodrigo Augusto Cardoso Da Silva',
- updatedAt: '2022-11-14T16:35:28.363Z',
- createdAt: '2022-11-14T16:35:28.363Z',
+ _id: '5bf5fb65d741524f090c91be',
+ name: 'Karla Vittori',
+ updatedAt: '2018-11-22T00:42:13.859Z',
+ createdAt: '2018-11-22T00:42:13.859Z',
__v: 0,
},
- updatedAt: '2023-08-21T22:03:46.904Z',
- year: 2023,
- conceito: 'A',
- creditos: 4,
},
{
_id: '64a48fb1aeef6acbbe79937e',
@@ -777,4 +777,92 @@ export const enrollments: Enrollment[] = [
updatedAt: '2023-08-21T22:03:46.923Z',
year: 2023,
},
+ {
+ _id: '5dd86bfeb4a9dea3166d32ea',
+ conceito: 'A',
+ creditos: 2,
+ disciplina: 'Bases Computacionais da Ciência',
+ quad: 2,
+ subject: {
+ _id: '5bf5fbdb436c414f35a8ef81',
+ name: 'Bases Computacionais da Ciência',
+ search: 'Bases Computacionais Da Ciencia',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 2,
+ },
+ updatedAt: '2023-10-17T13:15:01.822Z',
+ year: 2019,
+ pratica: {
+ _id: '5bf5fb65d741524f090c90e3',
+ name: 'Diogo Santana Martins',
+ updatedAt: '2018-11-22T00:42:13.857Z',
+ createdAt: '2018-11-22T00:42:13.857Z',
+ __v: 0,
+ },
+ teoria: null,
+ },
];
+
+export const enrollment: Enrollment = {
+ _id: '60d9f16dbc569f2438814f82',
+ disciplina: 'Bioquímica: Estrutura, Propriedade e Funções de Biomoléculas',
+ pratica: {
+ _id: '5bf5fb65d741524f090c932c',
+ name: 'Viviane Viana Silva',
+ updatedAt: '2018-11-22T00:42:13.862Z',
+ createdAt: '2018-11-22T00:42:13.862Z',
+ __v: 0,
+ comment: {
+ _id: '6520225d0f76921ac3322bd2',
+ comment: 'Fiz matéria com ela no EAD, um pouco difícil.',
+ viewers: 57,
+ enrollment: '60d9f16dbc569f2438814f82',
+ type: 'pratica',
+ ra: '11201921874',
+ active: true,
+ teacher: '5bf5fb65d741524f090c932c',
+ subject: '5bf5fbdb436c414f35a8ef9b',
+ updatedAt: '2023-10-06T15:06:05.445Z',
+ createdAt: '2023-10-06T15:06:05.445Z',
+ __v: 0,
+ },
+ },
+ quad: 1,
+ subject: {
+ _id: '5bf5fbdb436c414f35a8ef9b',
+ name: 'Bioquímica: Estrutura, Propriedade e Funções de Biomoléculas',
+ search: 'Bioquimica Estrutura Propriedade E Funcoes De Biomoleculas',
+ updatedAt: '2018-11-22T00:44:12.264Z',
+ createdAt: '2018-11-22T00:44:12.264Z',
+ __v: 0,
+ creditos: 5,
+ },
+ teoria: {
+ _id: '5bf5fb65d741524f090c90fa',
+ name: 'Eloah Rabello Suarez',
+ updatedAt: '2018-11-22T00:42:13.857Z',
+ createdAt: '2018-11-22T00:42:13.857Z',
+ __v: 0,
+ comment: {
+ _id: '652015990f76921ac33216e7',
+ comment: 'Fiz matéria com ela no EAD, relativamente simples',
+ viewers: 1306,
+ enrollment: '60d9f16dbc569f2438814f82',
+ type: 'teoria',
+ ra: '11201921874',
+ active: true,
+ teacher: '5bf5fb65d741524f090c90fa',
+ subject: '5bf5fbdb436c414f35a8ef9b',
+ updatedAt: '2023-11-18T11:57:48.061Z',
+ createdAt: '2023-10-06T14:11:37.932Z',
+ __v: 0,
+ },
+ },
+ updatedAt: '2023-11-18T11:57:48.067Z',
+ year: 2021,
+ conceito: 'A',
+ creditos: 5,
+ comments: ['teoria', 'pratica'],
+};
diff --git a/apps/container/src/mocks/handlers.ts b/apps/container/src/mocks/handlers.ts
index e486906f..a3e233e0 100644
--- a/apps/container/src/mocks/handlers.ts
+++ b/apps/container/src/mocks/handlers.ts
@@ -1,6 +1,6 @@
import { http, HttpResponse } from 'msw';
import { user, userGrades } from './users';
-import { enrollments } from './enrollments';
+import { enrollment, enrollments } from './enrollments';
import {
usage,
courses,
@@ -12,12 +12,17 @@ import {
grades,
} from './stats';
import { historiesGraduations } from './performance';
+import { comments, subject, subjectSearch, teacher, teacherSearch } from './reviews';
const baseUrl = 'https://api.ufabcnext.com/v1';
export const handlers = [
http.get(`${baseUrl}/users/info`, () => HttpResponse.json(user)),
http.get(`${baseUrl}/enrollments`, () => HttpResponse.json(enrollments)),
+ http.get(`${baseUrl}/enrollments/*`, () => HttpResponse.json(enrollment)),
+ http.get(`${baseUrl}/reviews/teachers/*`, () => HttpResponse.json(teacher)),
+ http.get(`${baseUrl}/reviews/subjects/*`, () => HttpResponse.json(subject)),
+ http.get(`${baseUrl}/comments/*`, () => HttpResponse.json(comments)),
http.get(`${baseUrl}/stats/usage`, () => HttpResponse.json(usage)),
http.get(`${baseUrl}/stats/disciplinas/courses`, () =>
HttpResponse.json(courses),
@@ -43,9 +48,19 @@ export const handlers = [
http.get(`${baseUrl}/historiesGraduations`, () =>
HttpResponse.json(historiesGraduations),
),
+ http.get(`${baseUrl}/teachers/search`, () => {
+ return HttpResponse.json(teacherSearch);
+ }),
+ http.get(`${baseUrl}/subjects/search`, () =>
+ HttpResponse.json(subjectSearch),
+ ),
http.delete(`${baseUrl}/users/me/delete`, () => HttpResponse.json({})),
http.post(`${baseUrl}/account/confirm`, () => HttpResponse.json({})),
http.post(`${baseUrl}/users/me/recover`, () => HttpResponse.json({})),
http.post(`${baseUrl}/users/me/resend`, () => HttpResponse.json({})),
http.put(`${baseUrl}/users/complete`, () => HttpResponse.json({})),
+ http.post(`${baseUrl}/comments`, () => HttpResponse.json({})),
+ http.put(`${baseUrl}/comments/*`, () => HttpResponse.json({})),
+ http.post(`${baseUrl}/reactions/*`, () => HttpResponse.json({})),
+ http.delete(`${baseUrl}/reactions/*`, () => HttpResponse.json({})),
];
diff --git a/apps/container/src/mocks/reviews.ts b/apps/container/src/mocks/reviews.ts
new file mode 100644
index 00000000..40106be7
--- /dev/null
+++ b/apps/container/src/mocks/reviews.ts
@@ -0,0 +1,1765 @@
+import {
+ CreateCommentRequest,
+ GetCommentResponse,
+ SearchSubject,
+ SearchTeacher,
+ SubjectInfo,
+ TeacherReview,
+ UpdateCommentRequest,
+} from 'types';
+export const subjectInfo = {
+ subject: {
+ _id: '5bf5fbdb436c414f35a8ef48',
+ name: 'Aerodinâmica I',
+ search: 'Aerodinamica I',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ general: {
+ cr_medio: 2.407155565941171,
+ cr_professor: 2.0296296296296297,
+ count: 405,
+ amount: 405,
+ numeric: 974.8980042061743,
+ numericWeight: 822,
+ distribution: [
+ {
+ conceito: 'D',
+ cr_medio: 2.360373166132844,
+ cr_professor: 1,
+ count: 49,
+ amount: 49,
+ numeric: 115.65828514050936,
+ numericWeight: 49,
+ },
+ {
+ conceito: 'F',
+ cr_medio: 2.0558825193260097,
+ cr_professor: 0,
+ count: 69,
+ amount: 69,
+ numeric: 141.85589383349466,
+ numericWeight: 0,
+ },
+ {
+ conceito: 'C',
+ cr_medio: 2.6365305916693753,
+ cr_professor: 2,
+ count: 67,
+ amount: 67,
+ numeric: 176.64754964184814,
+ numericWeight: 134,
+ },
+ {
+ conceito: 'B',
+ cr_medio: 3.005419733465605,
+ cr_professor: 3,
+ count: 37,
+ amount: 37,
+ numeric: 111.20053013822738,
+ numericWeight: 111,
+ },
+ {
+ conceito: 'O',
+ cr_medio: 1.6150335103001014,
+ cr_professor: 0,
+ count: 51,
+ amount: 51,
+ numeric: 82.36670902530517,
+ numericWeight: 0,
+ },
+ {
+ conceito: 'A',
+ cr_medio: 2.6300684577787092,
+ cr_professor: 4,
+ count: 132,
+ amount: 132,
+ numeric: 347.1690364267896,
+ numericWeight: 528,
+ },
+ ],
+ },
+ specific: [
+ {
+ _id: {
+ mainTeacher: null,
+ },
+ distribution: [
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 1,
+ cr_medio: 1.255980861244019,
+ numeric: 1.255980861244019,
+ numericWeight: 1,
+ amount: 1,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 1,
+ cr_medio: 2.0692307692307694,
+ numeric: 2.0692307692307694,
+ numericWeight: 1,
+ amount: 1,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 3,
+ cr_medio: 1.7962982929020666,
+ numeric: 5.3888948787062,
+ numericWeight: 0,
+ amount: 3,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 2,
+ cr_medio: 1.7457752837977296,
+ numeric: 3.4915505675954592,
+ numericWeight: 4,
+ amount: 2,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 3,
+ cr_medio: 2.370878500451671,
+ numeric: 7.1126355013550135,
+ numericWeight: 9,
+ amount: 3,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 3,
+ cr_medio: 0.8697409915266298,
+ numeric: 2.609222974579889,
+ numericWeight: 0,
+ amount: 3,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 57,
+ cr_medio: 2.1725711610983938,
+ numeric: 123.83655618260845,
+ numericWeight: 228,
+ amount: 57,
+ },
+ ],
+ numericWeight: 243,
+ numeric: 145.7640717353198,
+ amount: 70,
+ count: 70,
+ cr_professor: 3.4714285714285715,
+ teacher: null,
+ cr_medio: 2.0823438819331397,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c91cb',
+ },
+ distribution: [
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 1,
+ cr_medio: 2.5047619047619047,
+ numeric: 2.5047619047619047,
+ numericWeight: 2,
+ amount: 1,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 1,
+ cr_medio: 1.5719298245614035,
+ numeric: 1.5719298245614035,
+ numericWeight: 0,
+ amount: 1,
+ },
+ ],
+ numericWeight: 2,
+ numeric: 4.076691729323308,
+ amount: 2,
+ count: 2,
+ cr_professor: 1,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c91cb',
+ name: 'Leonardo De Olive Ferreira',
+ updatedAt: '2018-11-22T00:42:13.859Z',
+ createdAt: '2018-11-22T00:42:13.859Z',
+ __v: 0,
+ },
+ cr_medio: 2.038345864661654,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c9302',
+ },
+ distribution: [
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 3,
+ cr_medio: 1.5287111051411684,
+ numeric: 4.586133315423505,
+ numericWeight: 0,
+ amount: 3,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 5,
+ cr_medio: 2.4295174311766643,
+ numeric: 12.147587155883322,
+ numericWeight: 10,
+ amount: 5,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 3,
+ cr_medio: 2.622262187394013,
+ numeric: 7.866786562182039,
+ numericWeight: 3,
+ amount: 3,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 48,
+ cr_medio: 2.7993004615414345,
+ numeric: 134.36642215398885,
+ numericWeight: 192,
+ amount: 48,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 3,
+ cr_medio: 2.3054677827084764,
+ numeric: 6.91640334812543,
+ numericWeight: 9,
+ amount: 3,
+ },
+ ],
+ numericWeight: 214,
+ numeric: 165.88333253560316,
+ amount: 62,
+ count: 62,
+ cr_professor: 3.4516129032258065,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c9302',
+ name: 'Sungki Jung',
+ updatedAt: '2018-11-22T00:42:13.862Z',
+ createdAt: '2018-11-22T00:42:13.862Z',
+ __v: 0,
+ },
+ cr_medio: 2.6755376215419866,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c92a8',
+ },
+ distribution: [
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 2,
+ cr_medio: 2.913249765698219,
+ numeric: 5.826499531396438,
+ numericWeight: 6,
+ amount: 2,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 3,
+ cr_medio: 2.638529185863743,
+ numeric: 7.91558755759123,
+ numericWeight: 6,
+ amount: 3,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 3,
+ cr_medio: 3.026478315374133,
+ numeric: 9.079434946122399,
+ numericWeight: 3,
+ amount: 3,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 2,
+ cr_medio: 3.011052486809532,
+ numeric: 6.022104973619064,
+ numericWeight: 8,
+ amount: 2,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 9,
+ cr_medio: 1.6712077454614223,
+ numeric: 15.040869709152801,
+ numericWeight: 0,
+ amount: 9,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 2,
+ cr_medio: 2.087941859465038,
+ numeric: 4.175883718930076,
+ numericWeight: 0,
+ amount: 2,
+ },
+ ],
+ numericWeight: 23,
+ numeric: 48.06038043681201,
+ amount: 21,
+ count: 21,
+ cr_professor: 1.0952380952380953,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c92a8',
+ name: 'Reinaldo Marcondes Orselli',
+ updatedAt: '2018-11-22T00:42:13.861Z',
+ createdAt: '2018-11-22T00:42:13.861Z',
+ __v: 0,
+ },
+ cr_medio: 2.2885895446100957,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c91bd',
+ },
+ distribution: [
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 7,
+ cr_medio: 2.029054682446616,
+ numeric: 14.203382777126311,
+ numericWeight: 0,
+ amount: 7,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 9,
+ cr_medio: 2.492458997802586,
+ numeric: 22.432130980223274,
+ numericWeight: 18,
+ amount: 9,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 8,
+ cr_medio: 2.1145306053186297,
+ numeric: 16.916244842549037,
+ numericWeight: 8,
+ amount: 8,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 4,
+ cr_medio: 2.8162601814715784,
+ numeric: 11.265040725886314,
+ numericWeight: 12,
+ amount: 4,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 7,
+ cr_medio: 1.8213120787001844,
+ numeric: 12.74918455090129,
+ numericWeight: 0,
+ amount: 7,
+ },
+ ],
+ numericWeight: 38,
+ numeric: 77.56598387668623,
+ amount: 35,
+ count: 35,
+ cr_professor: 1.0857142857142856,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c91bd',
+ name: 'Karl Peter Burr',
+ updatedAt: '2018-11-22T00:42:13.859Z',
+ createdAt: '2018-11-22T00:42:13.859Z',
+ __v: 0,
+ },
+ cr_medio: 2.2161709679053208,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c920d',
+ },
+ distribution: [
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 33,
+ cr_medio: 2.3778971866418517,
+ numeric: 78.4706071591811,
+ numericWeight: 33,
+ amount: 33,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 32,
+ cr_medio: 1.6239822434584745,
+ numeric: 51.967431790671185,
+ numericWeight: 0,
+ amount: 32,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 47,
+ cr_medio: 2.726721946293467,
+ numeric: 128.15593147579295,
+ numericWeight: 94,
+ amount: 47,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 25,
+ cr_medio: 3.3177581246629297,
+ numeric: 82.94395311657324,
+ numericWeight: 100,
+ amount: 25,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 25,
+ cr_medio: 3.203198041258567,
+ numeric: 80.07995103146418,
+ numericWeight: 75,
+ amount: 25,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 53,
+ cr_medio: 2.1118805531839087,
+ numeric: 111.92966931874716,
+ numericWeight: 0,
+ amount: 53,
+ },
+ ],
+ numericWeight: 302,
+ numeric: 533.5475438924298,
+ amount: 215,
+ count: 215,
+ cr_professor: 1.4046511627906977,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c920d',
+ name: 'Marcelo Tanaka Hayashi',
+ updatedAt: '2018-11-22T00:42:13.860Z',
+ createdAt: '2018-11-22T00:42:13.860Z',
+ __v: 0,
+ },
+ cr_medio: 2.4816164832206034,
+ },
+ ],
+};
+
+export const concepts = { A: 14, B: 17, C: 3, F: 1, O: 2 };
+
+export const teacher: TeacherReview = {
+ teacher: {
+ _id: '5bf5fb65d741524f090c91be',
+ name: 'Karla Vittori',
+ updatedAt: '2018-11-22T00:42:13.859Z',
+ createdAt: '2018-11-22T00:42:13.859Z',
+ __v: 0,
+ },
+ general: {
+ cr_medio: 2.381250966603433,
+ cr_professor: 2.8438914027149322,
+ count: 477,
+ amount: 442,
+ numeric: 1052.5129272387173,
+ numericWeight: 1257,
+ distribution: [
+ {
+ conceito: 'O',
+ cr_medio: 1.829642065509002,
+ cr_professor: 0,
+ count: 43,
+ amount: 43,
+ numeric: 78.67460881688709,
+ numericWeight: 0,
+ },
+ {
+ conceito: 'F',
+ cr_medio: 2.1344707333247914,
+ cr_professor: 0,
+ count: 9,
+ amount: 9,
+ numeric: 19.21023659992312,
+ numericWeight: 0,
+ },
+ {
+ conceito: 'A',
+ cr_medio: 2.6546099177023366,
+ cr_professor: 4,
+ count: 189,
+ amount: 183,
+ numeric: 485.79361493952763,
+ numericWeight: 732,
+ },
+ {
+ conceito: 'B',
+ cr_medio: 2.348015230313539,
+ cr_professor: 3,
+ count: 143,
+ amount: 127,
+ numeric: 298.19793424981947,
+ numericWeight: 381,
+ },
+ {
+ conceito: 'C',
+ cr_medio: 2.109904873021149,
+ cr_professor: 2,
+ count: 73,
+ amount: 64,
+ numeric: 135.03391187335353,
+ numericWeight: 128,
+ },
+ {
+ conceito: 'D',
+ cr_medio: 2.2251637974503997,
+ cr_professor: 1,
+ count: 20,
+ amount: 16,
+ numeric: 35.602620759206395,
+ numericWeight: 16,
+ },
+ ],
+ },
+ specific: [
+ {
+ _id: {
+ _id: '5bf5fbdb436c414f35a8ef81',
+ name: 'Bases Computacionais da Ciência',
+ search: 'Bases Computacionais Da Ciencia',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 2,
+ },
+ distribution: [
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 6,
+ cr_medio: 1.7834472054327541,
+ numeric: 10.700683232596525,
+ numericWeight: 0,
+ amount: 6,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 3,
+ cr_medio: 2.627950766300281,
+ numeric: 7.883852298900843,
+ numericWeight: 0,
+ amount: 3,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 13,
+ cr_medio: 3.5952380952380953,
+ numeric: 25.166666666666668,
+ numericWeight: 28,
+ amount: 7,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 36,
+ cr_medio: 2.936745009044853,
+ numeric: 58.73490018089706,
+ numericWeight: 60,
+ amount: 20,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 28,
+ cr_medio: 2.6278609160973843,
+ numeric: 49.929357405850304,
+ numericWeight: 38,
+ amount: 19,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 14,
+ cr_medio: 2.482704172912374,
+ numeric: 24.827041729123742,
+ numericWeight: 10,
+ amount: 10,
+ },
+ ],
+ numericWeight: 136,
+ numeric: 177.24250151403515,
+ amount: 65,
+ count: 100,
+ cr_professor: 2.0923076923076924,
+ cr_medio: 2.726807715600541,
+ },
+ {
+ _id: {
+ _id: '5bf5fbdb436c414f35a8efbf',
+ name: 'Computadores, Ética e Sociedade',
+ search: 'Computadores Etica E Sociedade',
+ updatedAt: '2018-11-22T00:44:12.264Z',
+ createdAt: '2018-11-22T00:44:12.264Z',
+ __v: 0,
+ creditos: 2,
+ },
+ distribution: [
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 6,
+ cr_medio: 1.677317620309859,
+ numeric: 10.063905721859154,
+ numericWeight: 0,
+ amount: 6,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 12,
+ cr_medio: 1.8462099100572271,
+ numeric: 22.154518920686726,
+ numericWeight: 24,
+ amount: 12,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 35,
+ cr_medio: 2.0536460638137584,
+ numeric: 71.87761223348154,
+ numericWeight: 105,
+ amount: 35,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 64,
+ cr_medio: 2.5509685977610466,
+ numeric: 163.26199025670698,
+ numericWeight: 256,
+ amount: 64,
+ },
+ ],
+ numericWeight: 385,
+ numeric: 267.3580271327344,
+ amount: 117,
+ count: 117,
+ cr_professor: 3.2905982905982905,
+ cr_medio: 2.2851113430148238,
+ },
+ {
+ _id: {
+ _id: '5bf5fbdc436c414f35a8f22f',
+ name: 'Projeto Dirigido',
+ search: 'Projeto Dirigido',
+ updatedAt: '2018-11-22T00:44:12.284Z',
+ createdAt: '2018-11-22T00:44:12.284Z',
+ __v: 0,
+ creditos: 2,
+ },
+ distribution: [
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 8,
+ cr_medio: 1.8119407195179942,
+ numeric: 14.495525756143953,
+ numericWeight: 16,
+ amount: 8,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 2,
+ cr_medio: 2.152001475742483,
+ numeric: 4.304002951484966,
+ numericWeight: 0,
+ amount: 2,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 20,
+ cr_medio: 2.333077795701602,
+ numeric: 46.661555914032036,
+ numericWeight: 60,
+ amount: 20,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 18,
+ cr_medio: 1.7989161885423732,
+ numeric: 32.38049139376272,
+ numericWeight: 0,
+ amount: 18,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 56,
+ cr_medio: 2.590186145530678,
+ numeric: 145.05042414971797,
+ numericWeight: 224,
+ amount: 56,
+ },
+ ],
+ numericWeight: 300,
+ numeric: 242.89200016514164,
+ amount: 104,
+ count: 104,
+ cr_professor: 2.8846153846153846,
+ cr_medio: 2.3355000015879,
+ },
+ {
+ _id: {
+ _id: '5bf5fbdc436c414f35a8f119',
+ name: 'Inteligência Artificial',
+ search: 'Inteligencia Artificial',
+ updatedAt: '2018-11-22T00:44:12.280Z',
+ createdAt: '2018-11-22T00:44:12.280Z',
+ __v: 0,
+ creditos: 4,
+ },
+ distribution: [
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 1,
+ cr_medio: 2.533333333333333,
+ numeric: 2.533333333333333,
+ numericWeight: 0,
+ amount: 1,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 1,
+ cr_medio: 1.3488372093023255,
+ numeric: 1.3488372093023255,
+ numericWeight: 1,
+ amount: 1,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 4,
+ cr_medio: 3.164214466749767,
+ numeric: 12.656857866999069,
+ numericWeight: 16,
+ amount: 4,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 5,
+ cr_medio: 2.2947105608020495,
+ numeric: 11.473552804010247,
+ numericWeight: 15,
+ amount: 5,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 3,
+ cr_medio: 2.2402424489605757,
+ numeric: 6.720727346881727,
+ numericWeight: 6,
+ amount: 3,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 1,
+ cr_medio: 3.7045454545454546,
+ numeric: 3.7045454545454546,
+ numericWeight: 0,
+ amount: 1,
+ },
+ ],
+ numericWeight: 38,
+ numeric: 38.437854015072155,
+ amount: 15,
+ count: 15,
+ cr_professor: 2.533333333333333,
+ cr_medio: 2.5625236010048105,
+ },
+ {
+ _id: {
+ _id: '5bf5fbdc436c414f35a8f343',
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ createdAt: '2018-11-22T00:44:12.287Z',
+ __v: 0,
+ creditos: 2,
+ },
+ distribution: [
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 5,
+ cr_medio: 1.8853483641560658,
+ numeric: 9.426741820780329,
+ numericWeight: 5,
+ amount: 5,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 47,
+ cr_medio: 2.32873006632763,
+ numeric: 109.4503131173986,
+ numericWeight: 141,
+ amount: 47,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 12,
+ cr_medio: 1.818748584510269,
+ numeric: 21.82498301412323,
+ numericWeight: 0,
+ amount: 12,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 3,
+ cr_medio: 1.49634933873466,
+ numeric: 4.48904801620398,
+ numericWeight: 0,
+ amount: 3,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 52,
+ cr_medio: 2.6857245384507107,
+ numeric: 139.65767599943695,
+ numericWeight: 208,
+ amount: 52,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 22,
+ cr_medio: 1.8969901110814016,
+ numeric: 41.73378244379084,
+ numericWeight: 44,
+ amount: 22,
+ },
+ ],
+ numericWeight: 398,
+ numeric: 326.5825444117339,
+ amount: 141,
+ count: 141,
+ cr_professor: 2.8226950354609928,
+ cr_medio: 2.3161882582392477,
+ },
+ ],
+};
+
+export const subject: SubjectInfo = {
+ subject: {
+ _id: '5bf5fbdb436c414f35a8ef4a',
+ name: 'Aeroelasticidade',
+ search: 'Aeroelasticidade',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ general: {
+ cr_medio: 2.4342071459792094,
+ cr_professor: 1.964401294498382,
+ count: 310,
+ amount: 309,
+ numeric: 752.1700081075757,
+ numericWeight: 607,
+ distribution: [
+ {
+ conceito: 'B',
+ cr_medio: 2.8044017496119342,
+ cr_professor: 3,
+ count: 71,
+ amount: 71,
+ numeric: 199.11252422244732,
+ numericWeight: 213,
+ },
+ {
+ conceito: 'F',
+ cr_medio: 2.0032813601784296,
+ cr_professor: 0,
+ count: 35,
+ amount: 35,
+ numeric: 70.11484760624504,
+ numericWeight: 0,
+ },
+ {
+ conceito: 'A',
+ cr_medio: 3.0051039407995486,
+ cr_professor: 4,
+ count: 49,
+ amount: 49,
+ numeric: 147.2500930991779,
+ numericWeight: 196,
+ },
+ {
+ conceito: 'C',
+ cr_medio: 2.3277327594269224,
+ cr_professor: 2,
+ count: 72,
+ amount: 71,
+ numeric: 165.26902591931147,
+ numericWeight: 142,
+ },
+ {
+ conceito: 'O',
+ cr_medio: 1.7865796477501363,
+ cr_professor: 0,
+ count: 27,
+ amount: 27,
+ numeric: 48.23765048925368,
+ numericWeight: 0,
+ },
+ {
+ conceito: 'D',
+ cr_medio: 2.1818904780560753,
+ cr_professor: 1,
+ count: 56,
+ amount: 56,
+ numeric: 122.18586677114021,
+ numericWeight: 56,
+ },
+ ],
+ },
+ specific: [
+ {
+ _id: {
+ mainTeacher: null,
+ },
+ distribution: [
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 6,
+ cr_medio: 3.0549797572950452,
+ numeric: 18.32987854377027,
+ numericWeight: 18,
+ amount: 6,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 1,
+ cr_medio: 2.66839378238342,
+ numeric: 2.66839378238342,
+ numericWeight: 0,
+ amount: 1,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 4,
+ cr_medio: 3.212172920692641,
+ numeric: 12.848691682770564,
+ numericWeight: 16,
+ amount: 4,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 4,
+ cr_medio: 2.4165580021043382,
+ numeric: 7.249674006313015,
+ numericWeight: 6,
+ amount: 3,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 4,
+ cr_medio: 2.1508032437203104,
+ numeric: 8.603212974881242,
+ numericWeight: 8,
+ amount: 4,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 2,
+ cr_medio: 2.6039356799358804,
+ numeric: 5.207871359871761,
+ numericWeight: 0,
+ amount: 2,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 1,
+ cr_medio: 1.3221476510067114,
+ numeric: 1.3221476510067114,
+ numericWeight: 0,
+ amount: 1,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 1,
+ cr_medio: 2.4755244755244754,
+ numeric: 2.4755244755244754,
+ numericWeight: 1,
+ amount: 1,
+ },
+ ],
+ numericWeight: 49,
+ numeric: 58.705394476521455,
+ amount: 22,
+ count: 23,
+ cr_professor: 2.227272727272727,
+ teacher: null,
+ cr_medio: 2.668427021660066,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c900e',
+ },
+ distribution: [
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 1,
+ cr_medio: 2.5098039215686274,
+ numeric: 2.5098039215686274,
+ numericWeight: 2,
+ amount: 1,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 10,
+ cr_medio: 2.10913750783631,
+ numeric: 21.0913750783631,
+ numericWeight: 0,
+ amount: 10,
+ },
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 10,
+ cr_medio: 2.2888836900477765,
+ numeric: 22.888836900477763,
+ numericWeight: 10,
+ amount: 10,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 9,
+ cr_medio: 1.9015945763788669,
+ numeric: 17.114351187409802,
+ numericWeight: 0,
+ amount: 9,
+ },
+ ],
+ numericWeight: 12,
+ numeric: 63.60436708781929,
+ amount: 30,
+ count: 30,
+ cr_professor: 0.4,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c900e',
+ name: 'Adrian Marcel Zalmanovici',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ cr_medio: 2.1201455695939764,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c90a0',
+ },
+ distribution: [
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 42,
+ cr_medio: 2.1538375420077838,
+ numeric: 90.46117676432692,
+ numericWeight: 42,
+ amount: 42,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 16,
+ cr_medio: 1.7888415094273231,
+ numeric: 28.62146415083717,
+ numericWeight: 0,
+ amount: 16,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 20,
+ cr_medio: 1.882662301648487,
+ numeric: 37.65324603296974,
+ numericWeight: 0,
+ amount: 20,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 35,
+ cr_medio: 3.21469852801272,
+ numeric: 112.5144484804452,
+ numericWeight: 140,
+ amount: 35,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 56,
+ cr_medio: 2.840074780127966,
+ numeric: 159.0441876871661,
+ numericWeight: 168,
+ amount: 56,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 57,
+ cr_medio: 2.3640026347376506,
+ numeric: 134.74815018004608,
+ numericWeight: 114,
+ amount: 57,
+ },
+ ],
+ numericWeight: 464,
+ numeric: 563.0426732957912,
+ amount: 226,
+ count: 226,
+ cr_professor: 2.0530973451327434,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c90a0',
+ name: 'Cesar Monzu Freire',
+ updatedAt: '2018-11-22T00:42:13.856Z',
+ createdAt: '2018-11-22T00:42:13.856Z',
+ __v: 0,
+ },
+ cr_medio: 2.4913392623707575,
+ },
+ {
+ _id: {
+ mainTeacher: '5bf5fb65d741524f090c91cb',
+ },
+ distribution: [
+ {
+ conceito: 'D',
+ weight: 1,
+ count: 3,
+ cr_medio: 2.120109543603686,
+ numeric: 6.360328630811058,
+ numericWeight: 3,
+ amount: 3,
+ },
+ {
+ conceito: 'C',
+ weight: 2,
+ count: 6,
+ cr_medio: 2.026364139417082,
+ numeric: 12.158184836502492,
+ numericWeight: 12,
+ amount: 6,
+ },
+ {
+ conceito: 'A',
+ weight: 4,
+ count: 10,
+ cr_medio: 2.188695293596213,
+ numeric: 21.88695293596213,
+ numericWeight: 40,
+ amount: 10,
+ },
+ {
+ conceito: 'F',
+ weight: 0,
+ count: 2,
+ cr_medio: 1.7469806763285023,
+ numeric: 3.4939613526570046,
+ numericWeight: 0,
+ amount: 2,
+ },
+ {
+ conceito: 'O',
+ weight: 0,
+ count: 1,
+ cr_medio: 1.1796875,
+ numeric: 1.1796875,
+ numericWeight: 0,
+ amount: 1,
+ },
+ {
+ conceito: 'B',
+ weight: 3,
+ count: 9,
+ cr_medio: 2.415384221278995,
+ numeric: 21.738457991510955,
+ numericWeight: 27,
+ amount: 9,
+ },
+ ],
+ numericWeight: 82,
+ numeric: 66.81757324744365,
+ amount: 31,
+ count: 31,
+ cr_professor: 2.6451612903225805,
+ teacher: {
+ alias: [],
+ _id: '5bf5fb65d741524f090c91cb',
+ name: 'Leonardo De Olive Ferreira',
+ updatedAt: '2018-11-22T00:42:13.859Z',
+ createdAt: '2018-11-22T00:42:13.859Z',
+ __v: 0,
+ },
+ cr_medio: 2.1554055886272145,
+ },
+ ],
+};
+
+export const comments: GetCommentResponse = {
+ data: [
+ {
+ _id: '5cceea2a69de150010bf5153',
+ comment:
+ 'A matéria foi basicamente apresentações, ela disponibilizou todas as aulas no TIDIA e os grupos tinham que apresentar o tema da aula utilizando notícias e outras fontes. A principal dificuldade foi organizar o que cada grupo iria apresentar e como eram muitos grupos, era uma apresentação a cada 2 semanas. Apesar dela criticar bastante as apresentações, as notas foram altas.',
+ createdAt: '2019-05-05T13:50:34.815Z',
+ enrollment: {
+ _id: '5c952debc76d7b768b47ef63',
+ conceito: 'A',
+ creditos: 2,
+ quad: 2,
+ season: '2018:2',
+ year: 2018,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ reactionsCount: {
+ like: 1,
+ recommendation: 2,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdb436c414f35a8efbf',
+ createdAt: '2018-11-22T00:44:12.264Z',
+ creditos: 2,
+ name: 'Computadores, Ética e Sociedade',
+ search: 'Computadores Etica E Sociedade',
+ updatedAt: '2018-11-22T00:44:12.264Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-07-02T16:36:35.766Z',
+ },
+ {
+ _id: '5cd8c0ba396fcc00101b8a4e',
+ comment:
+ 'As aulas consistem em apresentações dos alunos sobre matérias, notícias de jornais, etc, sobre o tema que ela pediu. Professora exigente nos trabalhos, sempre irá reclamar de algo, dificilmente estará satisfeita, mas no geral, apesar das reclamações na apresentação, as notas não são tão ruins quanto parecem e dá para passar tranquilamente fazendo tudo. As notas das apresentações são em grupo, então mesmo caso você não fale nada durante a apresentação ganhará nota mesmo assim.',
+ createdAt: '2019-05-13T00:56:26.759Z',
+ enrollment: {
+ _id: '5cd714b02dc71de1d62769ad',
+ conceito: 'C',
+ creditos: 2,
+ quad: 1,
+ year: 2019,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ reactionsCount: {
+ recommendation: 1,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f343',
+ createdAt: '2018-11-22T00:44:12.287Z',
+ creditos: 2,
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2019-05-17T03:46:04.255Z',
+ },
+ {
+ _id: '5cd0a138a3b6cc00108a5b42',
+ comment:
+ 'Professora tranquila; Aulas com slides; Cobra presença; Nas provas apenas cobrou coisas sobre robomind nada de programação (java).',
+ createdAt: '2019-05-06T21:03:52.607Z',
+ enrollment: {
+ _id: '5caf5b24b0632af0b0d7bd00',
+ conceito: 'B',
+ creditos: 2,
+ quad: 3,
+ year: 2017,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ reactionsCount: {
+ like: 0,
+ recommendation: 1,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdb436c414f35a8ef81',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ creditos: 2,
+ name: 'Bases Computacionais da Ciência',
+ search: 'Bases Computacionais Da Ciencia',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-07-04T15:44:44.317Z',
+ },
+ {
+ _id: '6552548e0796105c52752e20',
+ comment: 'tanto faz tanto fez essa matéria. muito legal e A fácil.',
+ createdAt: '2023-11-13T16:53:34.417Z',
+ enrollment: {
+ _id: '65034c97216580ff36b128bd',
+ conceito: 'A',
+ creditos: 2,
+ quad: 2,
+ year: 2023,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f343',
+ createdAt: '2018-11-22T00:44:12.287Z',
+ creditos: 2,
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-11-13T16:53:34.417Z',
+ },
+ {
+ _id: '654962d8a2778980c8958ae9',
+ comment:
+ 'Meio questionável kkkk, a gente tinha que pesquisar sobre o assunto antes da aula e fazer uma apresentação, sendo que ela nem explicava nada. Nas apresentações, parecia que ela ia cansando durante a aula e sempre era mais chata com os últimos grupos. A avaliação foi a criação de um livro jogo sobre os conceitos da matéria (que na verdade foi bem legal), mas as aulas em si eram estranhas, provavelmente não iria de novo.',
+ createdAt: '2023-11-06T22:04:08.615Z',
+ enrollment: {
+ _id: '651a1bf74afb2cda9f2f3290',
+ conceito: 'A',
+ creditos: 2,
+ quad: 2,
+ year: 2023,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f343',
+ createdAt: '2018-11-22T00:44:12.287Z',
+ creditos: 2,
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-11-06T22:04:08.615Z',
+ },
+ {
+ _id: '6546bb37a2778980c89067d7',
+ comment:
+ 'Não tem prova, teve só um projeto para criar um jogo no figma com temas sobre vida artificial. Ela não dá aula, faz vários trabalhos em grupo e discussões ao longo das aulas. Cobra presença.',
+ createdAt: '2023-11-04T21:44:23.253Z',
+ enrollment: {
+ _id: '65051963ae2f956c1b127b18',
+ conceito: 'A',
+ creditos: 2,
+ quad: 2,
+ year: 2023,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f343',
+ createdAt: '2018-11-22T00:44:12.287Z',
+ creditos: 2,
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-11-04T21:44:23.253Z',
+ },
+ {
+ _id: '6532fa967e651fb5741f06f4',
+ comment:
+ 'Matéria mais nada a ver que eu tive na UFABC. Mandou a gente fazer um projeto de IA pra ajudar a automatizar duas hortas, uma delas nao tinha nem energia elétrica, enquanto a outra o orçamento não podia passar de 500 reais contabilizando mão de obra e material. Ela não gosta de dar aula e vai fazer de tudo pra não dar mesmo',
+ createdAt: '2023-10-20T22:09:26.446Z',
+ enrollment: {
+ _id: '63b6eba472540f2687f83b7d',
+ conceito: 'A',
+ creditos: 4,
+ quad: 3,
+ year: 2022,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f119',
+ createdAt: '2018-11-22T00:44:12.280Z',
+ creditos: 4,
+ name: 'Inteligência Artificial',
+ search: 'Inteligencia Artificial',
+ updatedAt: '2018-11-22T00:44:12.280Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-10-20T22:09:26.446Z',
+ },
+ {
+ _id: '652ed4973dcd041534e821c6',
+ comment:
+ 'A disciplina foi basicamente apresentações e desenvolver um projeto de irrigação automática para uma horta. O problema é que de IA não teve nada, a horta sequer tinha energia elétrica e tínhamos que fazer tudo dentro de um orçamento apertado, parecia mais uma disciplina de engenharia unificada com algumas citações de IA. Recomendo se quer passar facilmente, pois ela dava uma de louca durante os feedbacks das apresentações mas não dava nota baixa pra ninguém. Agora se quer aprender alguma coisa sobre IA ou alguma coisa da área da computação, não recomendo, você aprenderia 10 vezes mais sobre IA com qualquer professor aleatório da licenciatura do que com ela.',
+ createdAt: '2023-10-17T18:38:15.285Z',
+ enrollment: {
+ _id: '63cac02011c84dda9d4225da',
+ conceito: 'A',
+ creditos: 4,
+ quad: 3,
+ year: 2022,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f119',
+ createdAt: '2018-11-22T00:44:12.280Z',
+ creditos: 4,
+ name: 'Inteligência Artificial',
+ search: 'Inteligencia Artificial',
+ updatedAt: '2018-11-22T00:44:12.280Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-10-17T18:38:15.285Z',
+ },
+ {
+ _id: '62c738366e34310011b73c9e',
+ comment: 'doente da cabeça',
+ createdAt: '2022-07-07T19:47:02.533Z',
+ enrollment: {
+ _id: '5c953defc76d7b768b4c5be5',
+ conceito: 'B',
+ creditos: 2,
+ quad: 2,
+ season: '2018:2',
+ year: 2018,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ reactionsCount: {
+ like: 0,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdb436c414f35a8efbf',
+ createdAt: '2018-11-22T00:44:12.264Z',
+ creditos: 2,
+ name: 'Computadores, Ética e Sociedade',
+ search: 'Computadores Etica E Sociedade',
+ updatedAt: '2018-11-22T00:44:12.264Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2023-07-04T15:44:40.248Z',
+ },
+ {
+ _id: '62c736d76e34310011b7202f',
+ comment: 'doente da cabeça.',
+ createdAt: '2022-07-07T19:41:11.713Z',
+ enrollment: {
+ _id: '5cd714a62dc71de1d6273f97',
+ conceito: 'B',
+ creditos: 2,
+ quad: 1,
+ year: 2019,
+ },
+ myReactions: {
+ like: false,
+ recommendation: false,
+ star: false,
+ },
+ subject: {
+ __v: 0,
+ _id: '5bf5fbdc436c414f35a8f343',
+ createdAt: '2018-11-22T00:44:12.287Z',
+ creditos: 2,
+ name: 'Vida Artificial na Computação',
+ search: 'Vida Artificial Na Computacao',
+ updatedAt: '2018-11-22T00:44:12.287Z',
+ },
+ teacher: '5bf5fb65d741524f090c91be',
+ updatedAt: '2022-07-07T19:41:11.713Z',
+ },
+ ],
+ total: 24,
+};
+
+export const userCreateComment: CreateCommentRequest = {
+ enrollment: '123123123123fffff',
+ comment: 'Test Comment',
+ type: 'teoria',
+};
+
+export const userUpdateComment: UpdateCommentRequest = {
+ id: '111',
+ comment: 'Test Comment 2',
+};
+
+export const teacherSearch: SearchTeacher = {
+ total: 207,
+ data: [
+ {
+ _id: '5bf5fb65d741524f090c900a',
+ name: 'Acacio Sidinei Almeida Santos',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c9010',
+ name: 'Adriana Capuano De Oliveira',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c9020',
+ name: 'Alexandre Acacio De Andrade',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ alias: ['Alexandre Acacio'],
+ },
+ {
+ _id: '5bf5fb65d741524f090c9025',
+ name: 'Alexandre Jose De Castro Lanfredi',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c9027',
+ name: 'Alexandre Zatkovskis Carvalho',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c902e',
+ name: 'Aline Diniz Cabral',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c9036',
+ name: 'Ana Carolina Boero',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c9037',
+ name: 'Ana Carolina Quirino Simoes',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c9038',
+ name: 'Ana Carolina Santos De Souza Galvao',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ {
+ _id: '5bf5fb65d741524f090c903a',
+ name: 'Ana Keila Mosca Pinezi',
+ updatedAt: '2018-11-22T00:42:13.855Z',
+ createdAt: '2018-11-22T00:42:13.855Z',
+ __v: 0,
+ },
+ ],
+};
+
+export const subjectSearch: SearchSubject = {
+ total: 760,
+ data: [
+ {
+ _id: '5bf5fbdb436c414f35a8ef4a',
+ name: 'Aeroelasticidade',
+ search: 'Aeroelasticidade',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef46',
+ name: 'Administração Municipal e Desenvolvimento Local',
+ search: 'Administracao Municipal E Desenvolvimento Local',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef47',
+ name: 'Administração Pública e Reforma do Estado em Perspectiva Comparada',
+ search:
+ 'Administracao Publica E Reforma Do Estado Em Perspectiva Comparada',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef48',
+ name: 'Aerodinâmica I',
+ search: 'Aerodinamica I',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef49',
+ name: 'Aerodinâmica II',
+ search: 'Aerodinamica Ii',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef4b',
+ name: 'Aeronáutica I-A',
+ search: 'Aeronautica IA',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef4c',
+ name: 'Aeronáutica I-B',
+ search: 'Aeronautica IB',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef4d',
+ name: 'Aeronáutica II',
+ search: 'Aeronautica Ii',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 6,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef50',
+ name: 'Antropologia Filosófica',
+ search: 'Antropologia Filosofica',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 4,
+ },
+ {
+ _id: '5bf5fbdb436c414f35a8ef54',
+ name: 'Análise Econômica de Projetos',
+ search: 'Analise Economica De Projetos',
+ updatedAt: '2018-11-22T00:44:12.263Z',
+ createdAt: '2018-11-22T00:44:12.263Z',
+ __v: 0,
+ creditos: 3,
+ },
+ ],
+};
diff --git a/apps/container/src/test-utils.ts b/apps/container/src/test-utils.ts
index 8a342a9b..110b82e1 100644
--- a/apps/container/src/test-utils.ts
+++ b/apps/container/src/test-utils.ts
@@ -3,7 +3,7 @@ import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
-import { render } from '@testing-library/vue';
+import { render, waitFor, within, screen } from '@testing-library/vue';
import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query';
import { Plugin } from 'vue';
@@ -43,3 +43,11 @@ const customRender: typeof render = (component, options) => {
export { customRender as render };
export * from '@testing-library/vue';
+
+export const expectToasterToHaveText = async (text: string) => {
+ await waitFor(() => {
+ expect(
+ within(screen.getAllByRole('alert').at(-1)!).getByText(RegExp(text, 'i')),
+ ).toBeInTheDocument();
+ });
+};
\ No newline at end of file
diff --git a/apps/container/src/views/Admin/AdminView.test.ts b/apps/container/src/views/Admin/AdminView.test.ts
new file mode 100644
index 00000000..41cad6e2
--- /dev/null
+++ b/apps/container/src/views/Admin/AdminView.test.ts
@@ -0,0 +1,11 @@
+import { render, screen } from '@/test-utils';
+import { AdminView } from '.';
+
+describe('', () => {
+ test('render admin view', () => {
+ render(AdminView);
+ expect(
+ screen.getByRole('heading', { name: 'Admin' }),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/views/Confirmation/ConfirmationView.vue b/apps/container/src/views/Confirmation/ConfirmationView.vue
index 9f6768ef..60b27653 100644
--- a/apps/container/src/views/Confirmation/ConfirmationView.vue
+++ b/apps/container/src/views/Confirmation/ConfirmationView.vue
@@ -60,12 +60,20 @@ const { mutate: mutateConfirmToken, isPending: isPendingConfirmToken } =
useMutation({
mutationFn: Users.confirmSignup,
onSuccess: (data) => {
- ElMessage.success('Conta confirmada com sucesso');
+ ElMessage({
+ message: 'Conta confirmada com sucesso',
+ type: 'success',
+ showClose: true,
+ });
authenticate.value(data.data.token);
router.push('/');
},
onError: (error: AxiosError) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
@@ -73,7 +81,12 @@ onMounted(async () => {
await router.isReady();
const token = router.currentRoute.value.query.token as string;
if (!token) {
- return ElMessage.error('Token de confirmação não encontrado');
+ ElMessage({
+ message: 'Token de confirmação não encontrado',
+ type: 'error',
+ showClose: true,
+ });
+ return;
}
mutateConfirmToken(token);
});
diff --git a/apps/container/src/views/History/HistoryView.vue b/apps/container/src/views/History/HistoryView.vue
index 4bd5676c..7a22214a 100644
--- a/apps/container/src/views/History/HistoryView.vue
+++ b/apps/container/src/views/History/HistoryView.vue
@@ -2,6 +2,7 @@
', () => {
+ test('render admin view', () => {
+ render(PlanningView);
+ expect(
+ screen.getByRole('heading', { name: 'Planning' }),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/views/Recovery/RecoveryView.test.ts b/apps/container/src/views/Recovery/RecoveryView.test.ts
index fd30fdb9..4afbc49f 100644
--- a/apps/container/src/views/Recovery/RecoveryView.test.ts
+++ b/apps/container/src/views/Recovery/RecoveryView.test.ts
@@ -23,9 +23,9 @@ describe('', () => {
test('render recovery', () => {
render(RecoveryView);
- screen.getByAltText(/logo do UFABC Next/i);
- screen.getByAltText(/Imagem minimalista de dois estudantes/i);
- screen.getByRole('textbox', { name: /Insira seu email institucional/i });
+ expect(screen.getByAltText(/logo do UFABC Next/i)).toBeInTheDocument();
+ expect(screen.getByAltText(/Imagem minimalista de dois estudantes/i)).toBeInTheDocument();
+ expect(screen.getByRole('textbox', { name: /Insira seu email institucional/i })).toBeInTheDocument();
});
test('click go back button', async () => {
const user = await userEvent.setup();
diff --git a/apps/container/src/views/Reviews/ReviewsView.test.ts b/apps/container/src/views/Reviews/ReviewsView.test.ts
new file mode 100644
index 00000000..720ba39e
--- /dev/null
+++ b/apps/container/src/views/Reviews/ReviewsView.test.ts
@@ -0,0 +1,95 @@
+import { render, screen } from '@/test-utils';
+import { ReviewsView } from '.';
+import { useRouter } from 'vue-router';
+import { subjectSearch, teacherSearch } from '@/mocks/reviews';
+
+vi.mock('vue-router', async () => ({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ currentRoute: {
+ value: {
+ query: {},
+ },
+ },
+}));
+
+const replaceMock = vi.fn();
+
+describe('', () => {
+ beforeEach(() => {
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ currentRoute: {
+ value: {
+ query: {},
+ },
+ },
+ } as unknown as ReturnType);
+ });
+
+ test('render reviews', async () => {
+ render(ReviewsView);
+
+ expect(
+ await screen.findByPlaceholderText(
+ /Digite o nome do professor ou disciplina/i,
+ ),
+ ).toBeInTheDocument();
+ expect(
+ screen.getByText(/Centralização da informação/i),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(/Seus professores para avaliar/i),
+ ).toBeInTheDocument();
+ });
+ test.skip('render teacher search', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: teacherSearch.data[0].name,
+ teacherId: teacherSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+ render(ReviewsView);
+ expect(
+ await screen.findByText(/Provavelmente esse professor cobra presença/i),
+ ).toBeInTheDocument();
+ });
+ test('render subject search', async () => {
+ vi.mocked(useRouter).mockReturnValue({
+ useRouter: vi.fn(),
+ createRouter: vi.fn(() => ({
+ beforeEach: vi.fn(),
+ })),
+ replace: replaceMock,
+ currentRoute: {
+ value: {
+ query: {
+ q: subjectSearch.data[0].name,
+ subjectId: subjectSearch.data[0]._id,
+ },
+ },
+ },
+ } as unknown as ReturnType);
+ render(ReviewsView);
+ expect(
+ await screen.findByText(subjectSearch.data[0].name),
+ ).toBeInTheDocument();
+ expect(
+ await screen.findByText(/Nome do Professor/i),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/apps/container/src/views/SignUp/SignUpView.vue b/apps/container/src/views/SignUp/SignUpView.vue
index cee465c2..4f46bb41 100644
--- a/apps/container/src/views/SignUp/SignUpView.vue
+++ b/apps/container/src/views/SignUp/SignUpView.vue
@@ -372,7 +372,11 @@ const { mutate: mutateSignUp, isPending: isPendingSubmit } = useMutation({
step.value = 3;
},
onError: (error: AxiosError) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
const onSubmit = handleSubmit(({ email, ra }) =>
@@ -383,11 +387,19 @@ const { mutate: mutateResendEmail, isPending: isPendingResendEmail } =
useMutation({
mutationFn: Users.resendEmail,
onSuccess: () => {
- ElMessage.success('Email reenviado com sucesso');
+ ElMessage({
+ message: 'Email reenviado com sucesso',
+ type: 'success',
+ showClose: true,
+ });
enableResendEmail.value = false;
},
onError: (error: AxiosError) => {
- ElMessage.error(error.response?.data.error);
+ ElMessage({
+ message: error.response?.data.error,
+ type: 'error',
+ showClose: true,
+ });
},
});
diff --git a/packages/services/src/comments.ts b/packages/services/src/comments.ts
index ae418542..0939aa50 100644
--- a/packages/services/src/comments.ts
+++ b/packages/services/src/comments.ts
@@ -1,23 +1,12 @@
-import { Comment } from 'types';
+import {
+ Comment,
+ CreateCommentRequest,
+ GetCommentResponse,
+ UpdateCommentRequest,
+} from 'types';
import { api } from './api';
-type GetCommentResponse = {
- data: Comment[];
- total: number;
-};
-
-type CreateCommentRequest = {
- comment: string;
- enrollment: string;
- type: string;
-};
-
-type UpdateCommentRequest = {
- id: string;
- comment: string;
-};
-
export const Comments = {
get: (teacherId: string, subjectId: string, pageParam = 0) =>
api.get(`/comments/${teacherId}/${subjectId}`, {
diff --git a/packages/services/src/reviews.ts b/packages/services/src/reviews.ts
index 245663a9..6285bc55 100644
--- a/packages/services/src/reviews.ts
+++ b/packages/services/src/reviews.ts
@@ -1,22 +1,12 @@
import {
- SearchSubjectItem,
- SearchTeacherItem,
+ SearchSubject,
+ SearchTeacher,
SubjectInfo,
TeacherReview,
} from 'types';
import { api } from './api';
-type SearchTeacher = {
- data: SearchTeacherItem[];
- total: number;
-};
-
-type SearchSubject = {
- data: SearchSubjectItem[];
- total: number;
-};
-
export const Reviews = {
searchTeachers: async (q: string) =>
api.get('/teachers/search', {
diff --git a/packages/types/src/comments.ts b/packages/types/src/comments.ts
index 7cc4cf1b..97f72dc6 100644
--- a/packages/types/src/comments.ts
+++ b/packages/types/src/comments.ts
@@ -26,7 +26,23 @@ export type Comment = {
search: string;
updatedAt: string;
};
- reactionsCount?: { like: number; recommendation: number };
+ reactionsCount?: { like?: number; recommendation?: number };
teacher: string;
updatedAt: string;
};
+
+export type GetCommentResponse = {
+ data: Comment[];
+ total: number;
+};
+
+export type CreateCommentRequest = {
+ comment: string;
+ enrollment: string;
+ type: string;
+};
+
+export type UpdateCommentRequest = {
+ id: string;
+ comment: string;
+};
diff --git a/packages/types/src/enrollments.ts b/packages/types/src/enrollments.ts
index 9c6c1386..edea303d 100644
--- a/packages/types/src/enrollments.ts
+++ b/packages/types/src/enrollments.ts
@@ -13,6 +13,7 @@ type EnrollmentTeacherComment = {
updatedAt: string;
createdAt: string;
__v: number;
+ reactionsCount?: { like?: number; recommendation?: number };
};
type EnrollmentTeacher = {
diff --git a/packages/types/src/subjects.ts b/packages/types/src/subjects.ts
index 1dd2ec57..e2bc29f8 100644
--- a/packages/types/src/subjects.ts
+++ b/packages/types/src/subjects.ts
@@ -1,4 +1,5 @@
import { ConceptData } from './teachers';
+import { SearchSubjectItem } from '.';
export type SubjectSpecific = {
_id: { mainTeacher: string | null };
@@ -15,7 +16,7 @@ export type SubjectSpecific = {
updatedAt: string;
createdAt: string;
__v: number;
- };
+ } | null;
cr_medio: number;
};
@@ -40,3 +41,8 @@ export type SubjectInfo = {
};
specific: SubjectSpecific[];
};
+
+export type SearchSubject = {
+ data: SearchSubjectItem[];
+ total: number;
+};
diff --git a/packages/types/src/teachers.ts b/packages/types/src/teachers.ts
index d0eb83b2..284051e6 100644
--- a/packages/types/src/teachers.ts
+++ b/packages/types/src/teachers.ts
@@ -1,9 +1,11 @@
import { Concept } from './concepts';
+import { SearchTeacherItem } from '.';
export type ConceptData = {
conceito: Concept;
+ weight?: number;
cr_medio: number;
- cr_professor: number;
+ cr_professor?: number;
count: number;
amount: number;
numeric: number;
@@ -48,3 +50,8 @@ export type TeacherReview = {
};
specific: TeacherReviewSubject[];
};
+
+export type SearchTeacher = {
+ data: SearchTeacherItem[];
+ total: number;
+};