diff --git a/app/graphql/resolvers/categories_query_resolver.rb b/app/graphql/resolvers/categories_query_resolver.rb new file mode 100644 index 0000000..e0a013d --- /dev/null +++ b/app/graphql/resolvers/categories_query_resolver.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +module Resolvers + class CategoriesQueryResolver + def initialize(context) + @context = context + end + + def resolve + CategoryPolicy::Scope.new(@context[:current_user], Category).resolve + end + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 4e0b278..010a527 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -7,6 +7,7 @@ module Types argument :where, Inputs::QuestionWhereInput, required: false end field :subjects, SubjectType.connection_type, null: false + field :categories, CategoryType.connection_type, null: false field :reviewers, UserType.connection_type, null: false field :question_filter_options, QuestionFilterOptionsType, null: false field :current_user, Types::UserType, null: true @@ -19,6 +20,10 @@ module Types Resolvers::SubjectsQueryResolver.new(context).resolve end + def categories + Resolvers::CategoriesQueryResolver.new(context).resolve + end + def reviewers Resolvers::ReviewersQueryResolver.new(context).resolve end diff --git a/app/javascript/__generated__/graphql-schema.ts b/app/javascript/__generated__/graphql-schema.ts index db76e2d..72f6aa8 100644 --- a/app/javascript/__generated__/graphql-schema.ts +++ b/app/javascript/__generated__/graphql-schema.ts @@ -3,37 +3,60 @@ export type InputMaybe = Maybe; export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +export type MakeEmpty = { [_ in K]?: never }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } /** An ISO 8601-encoded date */ - ISO8601Date: any; + ISO8601Date: { input: any; output: any; } /** An ISO 8601-encoded datetime */ - ISO8601DateTime: any; + ISO8601DateTime: { input: any; output: any; } }; export type Axis = { __typename?: 'Axis'; - id: Scalars['ID']; - name: Scalars['String']; + id: Scalars['ID']['output']; + name: Scalars['String']['output']; subjects: Array; }; export type Category = { __typename?: 'Category'; - id: Scalars['ID']; - name: Scalars['String']; + id: Scalars['ID']['output']; + name: Scalars['String']['output']; subjects: Array; }; +/** The connection type for Category. */ +export type CategoryConnection = { + __typename?: 'CategoryConnection'; + /** A list of edges. */ + edges: Array; + /** A list of nodes. */ + nodes: Array; + /** Information to aid in pagination. */ + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + +/** An edge in a connection. */ +export type CategoryEdge = { + __typename?: 'CategoryEdge'; + /** A cursor for use in pagination. */ + cursor: Scalars['String']['output']; + /** The item at the end of the edge. */ + node?: Maybe; +}; + /** Autogenerated input type of CreateQuestion */ export type CreateQuestionInput = { /** A unique identifier for the client performing the mutation. */ - clientMutationId?: InputMaybe; + clientMutationId?: InputMaybe; question: QuestionCreateInput; }; @@ -41,16 +64,16 @@ export type CreateQuestionInput = { export type CreateQuestionPayload = { __typename?: 'CreateQuestionPayload'; /** A unique identifier for the client performing the mutation. */ - clientMutationId?: Maybe; + clientMutationId?: Maybe; /** Errors encountered during execution of the mutation. */ - errors: Array; + errors: Array; question?: Maybe; }; /** Autogenerated input type of CreateReviewMessage */ export type CreateReviewMessageInput = { /** A unique identifier for the client performing the mutation. */ - clientMutationId?: InputMaybe; + clientMutationId?: InputMaybe; message: ReviewMessageInput; }; @@ -58,48 +81,48 @@ export type CreateReviewMessageInput = { export type CreateReviewMessagePayload = { __typename?: 'CreateReviewMessagePayload'; /** A unique identifier for the client performing the mutation. */ - clientMutationId?: Maybe; + clientMutationId?: Maybe; /** Errors encountered during execution of the mutation. */ - errors: Array; + errors: Array; reviewMessage?: Maybe; }; export type DateRangeInput = { - endAt: Scalars['ISO8601Date']; - startAt: Scalars['ISO8601Date']; + endAt: Scalars['ISO8601Date']['input']; + startAt: Scalars['ISO8601Date']['input']; }; /** Autogenerated input type of DestroyQuestion */ export type DestroyQuestionInput = { /** A unique identifier for the client performing the mutation. */ - clientMutationId?: InputMaybe; - questionId: Scalars['ID']; + clientMutationId?: InputMaybe; + questionId: Scalars['ID']['input']; }; /** Autogenerated return type of DestroyQuestion */ export type DestroyQuestionPayload = { __typename?: 'DestroyQuestionPayload'; /** A unique identifier for the client performing the mutation. */ - clientMutationId?: Maybe; - deletedQuestionId?: Maybe; + clientMutationId?: Maybe; + deletedQuestionId?: Maybe; /** Errors encountered during execution of the mutation. */ - errors: Array; + errors: Array; }; /** Autogenerated input type of FinishQuestion */ export type FinishQuestionInput = { /** A unique identifier for the client performing the mutation. */ - clientMutationId?: InputMaybe; - questionId: Scalars['ID']; + clientMutationId?: InputMaybe; + questionId: Scalars['ID']['input']; }; /** Autogenerated return type of FinishQuestion */ export type FinishQuestionPayload = { __typename?: 'FinishQuestionPayload'; /** A unique identifier for the client performing the mutation. */ - clientMutationId?: Maybe; + clientMutationId?: Maybe; /** Errors encountered during execution of the mutation. */ - errors: Array; + errors: Array; question?: Maybe; }; @@ -140,24 +163,25 @@ export type MutationUpdateQuestionArgs = { /** An object with an ID. */ export type Node = { /** ID of the object. */ - id: Scalars['ID']; + id: Scalars['ID']['output']; }; /** Information about pagination in a connection. */ export type PageInfo = { __typename?: 'PageInfo'; /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; + endCursor?: Maybe; /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']; + hasNextPage: Scalars['Boolean']['output']; /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']; + hasPreviousPage: Scalars['Boolean']['output']; /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; + startCursor?: Maybe; }; export type Query = { __typename?: 'Query'; + categories: CategoryConnection; currentUser?: Maybe; /** Fetches an object given its ID. */ node?: Maybe; @@ -170,81 +194,89 @@ export type Query = { }; +export type QueryCategoriesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + + export type QueryNodeArgs = { - id: Scalars['ID']; + id: Scalars['ID']['input']; }; export type QueryNodesArgs = { - ids: Array; + ids: Array; }; export type QueryQuestionsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; where?: InputMaybe; }; export type QueryReviewersArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; }; export type QuerySubjectsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; }; export type Question = Node & { __typename?: 'Question'; alternatives: Array; - authorship?: Maybe; - authorshipYear?: Maybe; + authorship?: Maybe; + authorshipYear?: Maybe; bloomTaxonomy?: Maybe; - body?: Maybe; + body?: Maybe; checkType?: Maybe; - createdAt: Scalars['ISO8601DateTime']; + createdAt: Scalars['ISO8601DateTime']['output']; difficulty?: Maybe; - explanation?: Maybe; - id: Scalars['ID']; - instruction?: Maybe; - intention?: Maybe; - references?: Maybe; + explanation?: Maybe; + id: Scalars['ID']['output']; + instruction?: Maybe; + intention?: Maybe; + references?: Maybe; reviewMessages: ReviewMessageConnection; reviewer?: Maybe; status: QuestionStatus; subject?: Maybe; - support?: Maybe; - updatedAt: Scalars['ISO8601DateTime']; + support?: Maybe; + updatedAt: Scalars['ISO8601DateTime']['output']; user: User; }; export type QuestionReviewMessagesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; }; export type QuestionAlternative = { __typename?: 'QuestionAlternative'; - correct: Scalars['Boolean']; - text?: Maybe; + correct: Scalars['Boolean']['output']; + text?: Maybe; }; export type QuestionAlternativeInput = { - correct?: InputMaybe; - text?: InputMaybe; + correct?: InputMaybe; + text?: InputMaybe; }; export enum QuestionBloomTaxonomy { @@ -278,25 +310,25 @@ export type QuestionConnection = { nodes: Array; /** Information to aid in pagination. */ pageInfo: PageInfo; - totalCount: Scalars['Int']; + totalCount: Scalars['Int']['output']; }; export type QuestionCreateInput = { alternatives: Array; - authorship: Scalars['String']; - authorshipYear: Scalars['String']; + authorship: Scalars['String']['input']; + authorshipYear: Scalars['String']['input']; bloomTaxonomy?: InputMaybe; - body: Scalars['String']; + body: Scalars['String']['input']; checkType?: InputMaybe; difficulty?: InputMaybe; - explanation: Scalars['String']; - instruction: Scalars['String']; - intention?: InputMaybe; - references: Scalars['String']; - reviewerUserId?: InputMaybe; + explanation: Scalars['String']['input']; + instruction: Scalars['String']['input']; + intention?: InputMaybe; + references: Scalars['String']['input']; + reviewerUserId?: InputMaybe; status: QuestionStatus; - subjectId?: InputMaybe; - support: Scalars['String']; + subjectId?: InputMaybe; + support: Scalars['String']['input']; }; export enum QuestionDifficulty { @@ -309,14 +341,14 @@ export enum QuestionDifficulty { export type QuestionEdge = { __typename?: 'QuestionEdge'; /** A cursor for use in pagination. */ - cursor: Scalars['String']; + cursor: Scalars['String']['output']; /** The item at the end of the edge. */ node?: Maybe; }; export type QuestionFilterOptions = { __typename?: 'QuestionFilterOptions'; - years: Array; + years: Array; }; export enum QuestionStatus { @@ -329,43 +361,43 @@ export enum QuestionStatus { export type QuestionUpdateInput = { alternatives: Array; - authorship: Scalars['String']; - authorshipYear: Scalars['String']; + authorship: Scalars['String']['input']; + authorshipYear: Scalars['String']['input']; bloomTaxonomy?: InputMaybe; - body: Scalars['String']; + body: Scalars['String']['input']; checkType?: InputMaybe; difficulty?: InputMaybe; - explanation: Scalars['String']; - id: Scalars['ID']; - instruction: Scalars['String']; - intention?: InputMaybe; - references: Scalars['String']; - reviewerUserId?: InputMaybe; + explanation: Scalars['String']['input']; + id: Scalars['ID']['input']; + instruction: Scalars['String']['input']; + intention?: InputMaybe; + references: Scalars['String']['input']; + reviewerUserId?: InputMaybe; status: QuestionStatus; - subjectId?: InputMaybe; - support: Scalars['String']; + subjectId?: InputMaybe; + support: Scalars['String']['input']; }; export type QuestionWhereInput = { - authorshipYear?: InputMaybe>; + authorshipYear?: InputMaybe>; bloomTaxonomy?: InputMaybe>; checkType?: InputMaybe>; createDate?: InputMaybe; difficulty?: InputMaybe>; status?: InputMaybe>; - subjectId?: InputMaybe; - unifesoAuthorship?: InputMaybe; - userId?: InputMaybe; + subjectId?: InputMaybe; + unifesoAuthorship?: InputMaybe; + userId?: InputMaybe; }; export type ReviewMessage = { __typename?: 'ReviewMessage'; - createdAt: Scalars['ISO8601DateTime']; + createdAt: Scalars['ISO8601DateTime']['output']; feedbackType: ReviewMessageFeedbackType; - id: Scalars['ID']; + id: Scalars['ID']['output']; question: Question; - text: Scalars['String']; - updatedAt: Scalars['ISO8601DateTime']; + text: Scalars['String']['output']; + updatedAt: Scalars['ISO8601DateTime']['output']; user: User; }; @@ -378,14 +410,14 @@ export type ReviewMessageConnection = { nodes: Array; /** Information to aid in pagination. */ pageInfo: PageInfo; - totalCount: Scalars['Int']; + totalCount: Scalars['Int']['output']; }; /** An edge in a connection. */ export type ReviewMessageEdge = { __typename?: 'ReviewMessageEdge'; /** A cursor for use in pagination. */ - cursor: Scalars['String']; + cursor: Scalars['String']['output']; /** The item at the end of the edge. */ node?: Maybe; }; @@ -398,14 +430,14 @@ export enum ReviewMessageFeedbackType { export type ReviewMessageInput = { feedbackType: ReviewMessageFeedbackType; - questionId: Scalars['ID']; - text: Scalars['String']; + questionId: Scalars['ID']['input']; + text: Scalars['String']['input']; }; export type ReviewRequest = { __typename?: 'ReviewRequest'; - answered: Scalars['Boolean']; - id: Scalars['ID']; + answered: Scalars['Boolean']['output']; + id: Scalars['ID']['output']; question: Question; user: User; }; @@ -419,14 +451,14 @@ export type ReviewRequestConnection = { nodes: Array; /** Information to aid in pagination. */ pageInfo: PageInfo; - totalCount: Scalars['Int']; + totalCount: Scalars['Int']['output']; }; /** An edge in a connection. */ export type ReviewRequestEdge = { __typename?: 'ReviewRequestEdge'; /** A cursor for use in pagination. */ - cursor: Scalars['String']; + cursor: Scalars['String']['output']; /** The item at the end of the edge. */ node?: Maybe; }; @@ -435,17 +467,17 @@ export type Subject = { __typename?: 'Subject'; axis: Axis; category: Category; - id: Scalars['ID']; - name: Scalars['String']; + id: Scalars['ID']['output']; + name: Scalars['String']['output']; questions: QuestionConnection; }; export type SubjectQuestionsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; where?: InputMaybe; }; @@ -458,14 +490,14 @@ export type SubjectConnection = { nodes: Array; /** Information to aid in pagination. */ pageInfo: PageInfo; - totalCount: Scalars['Int']; + totalCount: Scalars['Int']['output']; }; /** An edge in a connection. */ export type SubjectEdge = { __typename?: 'SubjectEdge'; /** A cursor for use in pagination. */ - cursor: Scalars['String']; + cursor: Scalars['String']['output']; /** The item at the end of the edge. */ node?: Maybe; }; @@ -473,7 +505,7 @@ export type SubjectEdge = { /** Autogenerated input type of UpdateQuestion */ export type UpdateQuestionInput = { /** A unique identifier for the client performing the mutation. */ - clientMutationId?: InputMaybe; + clientMutationId?: InputMaybe; question: QuestionUpdateInput; }; @@ -481,37 +513,37 @@ export type UpdateQuestionInput = { export type UpdateQuestionPayload = { __typename?: 'UpdateQuestionPayload'; /** A unique identifier for the client performing the mutation. */ - clientMutationId?: Maybe; + clientMutationId?: Maybe; /** Errors encountered during execution of the mutation. */ - errors: Array; + errors: Array; question?: Maybe; }; export type User = { __typename?: 'User'; activeReviewRequests: ReviewRequestConnection; - avatarUrl?: Maybe; - email: Scalars['String']; - id: Scalars['ID']; + avatarUrl?: Maybe; + email: Scalars['String']['output']; + id: Scalars['ID']['output']; inactiveReviewRequests: ReviewRequestConnection; - name: Scalars['String']; + name: Scalars['String']['output']; roles: Array; }; export type UserActiveReviewRequestsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; }; export type UserInactiveReviewRequestsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; }; /** The connection type for User. */ @@ -523,14 +555,14 @@ export type UserConnection = { nodes: Array; /** Information to aid in pagination. */ pageInfo: PageInfo; - totalCount: Scalars['Int']; + totalCount: Scalars['Int']['output']; }; /** An edge in a connection. */ export type UserEdge = { __typename?: 'UserEdge'; /** A cursor for use in pagination. */ - cursor: Scalars['String']; + cursor: Scalars['String']['output']; /** The item at the end of the edge. */ node?: Maybe; }; diff --git a/app/javascript/__generated__/schema.graphql b/app/javascript/__generated__/schema.graphql index 5b0266a..508296e 100644 --- a/app/javascript/__generated__/schema.graphql +++ b/app/javascript/__generated__/schema.graphql @@ -10,6 +10,42 @@ type Category { subjects: [Subject!]! } +""" +The connection type for Category. +""" +type CategoryConnection { + """ + A list of edges. + """ + edges: [CategoryEdge!]! + + """ + A list of nodes. + """ + nodes: [Category!]! + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} + +""" +An edge in a connection. +""" +type CategoryEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: Category +} + """ Autogenerated input type of CreateQuestion """ @@ -202,6 +238,27 @@ type PageInfo { } type Query { + categories( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CategoryConnection! currentUser: User """ diff --git a/app/javascript/pages/assessment/NewAssessement.tsx b/app/javascript/pages/assessment/NewAssessement.tsx index 4d78d1b..1ecbaaa 100644 --- a/app/javascript/pages/assessment/NewAssessement.tsx +++ b/app/javascript/pages/assessment/NewAssessement.tsx @@ -1,93 +1,180 @@ -import React from "react"; -import { Button, Navigator } from '../../components' +import { gql, useQuery } from "@apollo/client"; +import React, { useState } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { Query } from "../../__generated__/graphql-schema"; +import { Button, Card, Input, Navigator } from '../../components'; + +type NewAssessementForm = { + subjectWeights: Record +} + +const NEW_ASSESSEMENT_DATA_QUERY = gql` + query NewAssessementDataQuery { + categories { + nodes { + id + name + subjects { + id + name + } + } + } + } +` export const NewAssessement = () => { + const { data } = useQuery(NEW_ASSESSEMENT_DATA_QUERY) + + const [subjectsIds, setSubjectsIds] = useState([]) + const subjectForm = useForm<{ subjectId: string }>() + const { register, control, watch } = useForm({ + mode: 'onBlur' + }) + + const handleSubjectFormSubmit = (data: { + subjectId: string + }) => { + setSubjectsIds(prev => [...prev, data.subjectId]) + subjectForm.reset(); + } + + if (!data?.categories) { + return null; + } + return ( <>
-
-
-

- Ano de Criação -

- -
-

Apenas inéditas?

- - - - + +
+

Titulo:

+
+
- -
-
-
-

- Habilidade Cognitiva -

- -
- +
+
+ + +
+
+ -
+ +
-
-
-
-

- Habilidade Cognitiva -

+
+ {data.categories.nodes.map(category => ( + category.subjects.find(subject => subjectsIds.includes(subject.id)) ? +
+
{category.name}
+ {category.subjects.map(subject => + subjectsIds.includes(subject.id) + ?
+
{subject.name}
+
+ Fácil + + {watch(`subjectWeights.easy.${subject.id}`) ?? 5} + +
+ ( + + )} + /> -
- -
+
+ +
+
+ Médio + + {watch(`subjectWeights.medium.${subject.id}`) ?? 5} + +
+ ( + + )} + /> + +
+ +
+
+ Difícil + + {watch(`subjectWeights.hard.${subject.id}`) ?? 5} + +
+ ( + + )} + /> + +
+ +
+
+ : null + )} +
+ : null + ))}
- -
+