use axis instead os subjects on new assessement page
This commit is contained in:
13
app/graphql/resolvers/axes_query_resolver.rb
Normal file
13
app/graphql/resolvers/axes_query_resolver.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
module Resolvers
|
||||
class AxesQueryResolver
|
||||
def initialize(context)
|
||||
@context = context
|
||||
end
|
||||
|
||||
def resolve
|
||||
AxisPolicy::Scope.new(@context[:current_user], Axis).resolve
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,7 @@ module Types
|
||||
field :questions, QuestionType.connection_type, null: false do
|
||||
argument :where, Inputs::QuestionWhereInput, required: false
|
||||
end
|
||||
field :axes, AxisType.connection_type, null: false
|
||||
field :subjects, SubjectType.connection_type, null: false
|
||||
field :categories, CategoryType.connection_type, null: false
|
||||
field :reviewers, UserType.connection_type, null: false
|
||||
@@ -16,6 +17,10 @@ module Types
|
||||
Resolvers::QuestionsQueryResolver.new(Question, context: context, where: where).resolve
|
||||
end
|
||||
|
||||
def axes
|
||||
Resolvers::AxesQueryResolver.new(context).resolve
|
||||
end
|
||||
|
||||
def subjects
|
||||
Resolvers::SubjectsQueryResolver.new(context).resolve
|
||||
end
|
||||
|
||||
30
app/javascript/__generated__/graphql-schema.ts
generated
30
app/javascript/__generated__/graphql-schema.ts
generated
@@ -25,6 +25,27 @@ export type Axis = {
|
||||
subjects: Array<Subject>;
|
||||
};
|
||||
|
||||
/** The connection type for Axis. */
|
||||
export type AxisConnection = {
|
||||
__typename?: 'AxisConnection';
|
||||
/** A list of edges. */
|
||||
edges: Array<AxisEdge>;
|
||||
/** A list of nodes. */
|
||||
nodes: Array<Axis>;
|
||||
/** Information to aid in pagination. */
|
||||
pageInfo: PageInfo;
|
||||
totalCount: Scalars['Int']['output'];
|
||||
};
|
||||
|
||||
/** An edge in a connection. */
|
||||
export type AxisEdge = {
|
||||
__typename?: 'AxisEdge';
|
||||
/** A cursor for use in pagination. */
|
||||
cursor: Scalars['String']['output'];
|
||||
/** The item at the end of the edge. */
|
||||
node?: Maybe<Axis>;
|
||||
};
|
||||
|
||||
export type Category = {
|
||||
__typename?: 'Category';
|
||||
id: Scalars['ID']['output'];
|
||||
@@ -181,6 +202,7 @@ export type PageInfo = {
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
axes: AxisConnection;
|
||||
categories: CategoryConnection;
|
||||
currentUser?: Maybe<User>;
|
||||
/** Fetches an object given its ID. */
|
||||
@@ -194,6 +216,14 @@ export type Query = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryAxesArgs = {
|
||||
after?: InputMaybe<Scalars['String']['input']>;
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
};
|
||||
|
||||
|
||||
export type QueryCategoriesArgs = {
|
||||
after?: InputMaybe<Scalars['String']['input']>;
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
|
||||
57
app/javascript/__generated__/schema.graphql
generated
57
app/javascript/__generated__/schema.graphql
generated
@@ -4,6 +4,42 @@ type Axis {
|
||||
subjects: [Subject!]!
|
||||
}
|
||||
|
||||
"""
|
||||
The connection type for Axis.
|
||||
"""
|
||||
type AxisConnection {
|
||||
"""
|
||||
A list of edges.
|
||||
"""
|
||||
edges: [AxisEdge!]!
|
||||
|
||||
"""
|
||||
A list of nodes.
|
||||
"""
|
||||
nodes: [Axis!]!
|
||||
|
||||
"""
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
totalCount: Int!
|
||||
}
|
||||
|
||||
"""
|
||||
An edge in a connection.
|
||||
"""
|
||||
type AxisEdge {
|
||||
"""
|
||||
A cursor for use in pagination.
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
The item at the end of the edge.
|
||||
"""
|
||||
node: Axis
|
||||
}
|
||||
|
||||
type Category {
|
||||
id: ID!
|
||||
name: String!
|
||||
@@ -238,6 +274,27 @@ type PageInfo {
|
||||
}
|
||||
|
||||
type Query {
|
||||
axes(
|
||||
"""
|
||||
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
|
||||
): AxisConnection!
|
||||
categories(
|
||||
"""
|
||||
Returns the elements in the list that come after the specified cursor.
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
import { gql, useQuery } from "@apollo/client";
|
||||
import React, { useState } from "react";
|
||||
import { FaTrash } from "react-icons/fa";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Query } from "../../__generated__/graphql-schema";
|
||||
|
||||
import { Axis, Query } from "../../__generated__/graphql-schema";
|
||||
import { Button, Card, Input, Navigator } from '../../components';
|
||||
|
||||
type NewAssessementForm = {
|
||||
subjectWeights: Record<string, any>
|
||||
axisWeights: Record<string, any>
|
||||
}
|
||||
|
||||
const NEW_ASSESSEMENT_DATA_QUERY = gql`
|
||||
query NewAssessementDataQuery {
|
||||
categories {
|
||||
axes {
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
subjects {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,24 +23,30 @@ const NEW_ASSESSEMENT_DATA_QUERY = gql`
|
||||
|
||||
export const NewAssessement = () => {
|
||||
const { data } = useQuery<Query>(NEW_ASSESSEMENT_DATA_QUERY)
|
||||
const axes = data?.axes.nodes
|
||||
|
||||
const [subjectsIds, setSubjectsIds] = useState<string[]>([])
|
||||
const subjectForm = useForm<{ subjectId: string }>()
|
||||
const { register, control, watch } = useForm<NewAssessementForm>({
|
||||
mode: 'onBlur'
|
||||
})
|
||||
|
||||
const handleSubjectFormSubmit = (data: {
|
||||
subjectId: string
|
||||
}) => {
|
||||
setSubjectsIds(prev => [...prev, data.subjectId])
|
||||
subjectForm.reset();
|
||||
|
||||
const addAxisForm = useForm<{ axisId: string }>()
|
||||
|
||||
const handleAddAxis = (formData: { axisId: string }) => {
|
||||
setSubjectsIds(prev => [...prev, formData.axisId])
|
||||
addAxisForm.reset();
|
||||
}
|
||||
|
||||
if (!data?.categories) {
|
||||
return null;
|
||||
const handleRemoveAxis = (axisId: string) => {
|
||||
setSubjectsIds(prev => prev.filter((axis => axis !== axisId)))
|
||||
}
|
||||
|
||||
if (!axes?.length) return null
|
||||
|
||||
const notSelectedAxis: Axis[] = axes.filter((axis) => !subjectsIds.includes(axis.id))
|
||||
const selectedAxis: Axis[] = axes.filter((axis) => subjectsIds.includes(axis.id))
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navigator home />
|
||||
@@ -61,117 +65,116 @@ export const NewAssessement = () => {
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card title="Assuntos e Pesos">
|
||||
<Card title="Exios e Pesos">
|
||||
<div className="mb-6">
|
||||
<form
|
||||
className="flex flex-row"
|
||||
onSubmit={subjectForm.handleSubmit(handleSubjectFormSubmit)}
|
||||
onSubmit={addAxisForm.handleSubmit(handleAddAxis)}
|
||||
>
|
||||
<select
|
||||
className="w-full rounded p-1 border-gray-400 border shadow-sm"
|
||||
{...subjectForm.register('subjectId')}
|
||||
disabled={!notSelectedAxis.length}
|
||||
{...addAxisForm.register('axisId')}
|
||||
>
|
||||
{data.categories.nodes.map(category => (
|
||||
<optgroup label={category.name} key={`category-${category.id}`}>
|
||||
{category.subjects.map(subject =>
|
||||
subjectsIds.includes(subject.id) ? null : <option value={subject.id} key={`subject-${subject.id}`}>{subject.name}</option>
|
||||
)}
|
||||
</optgroup>
|
||||
{notSelectedAxis.map(axes => (
|
||||
<option value={axes.id} key={`axes-${axes.id}`}>{axes.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<Button className="ml-4" htmlType="submit">Adicionar</Button>
|
||||
<Button
|
||||
className="ml-4"
|
||||
htmlType="submit"
|
||||
disabled={!notSelectedAxis.length}
|
||||
>
|
||||
Adicionar
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{data.categories.nodes.map(category => (
|
||||
category.subjects.find(subject => subjectsIds.includes(subject.id)) ?
|
||||
<div
|
||||
key={`list-category-${category.id}`}
|
||||
className="flex flex-col w-full border border-gray-300 rounded p-4 mt-4 shadow-sm"
|
||||
>
|
||||
<h5 className="text-xl">{category.name}</h5>
|
||||
{category.subjects.map(subject =>
|
||||
subjectsIds.includes(subject.id)
|
||||
? <div key={`list-subject-${subject.id}`} className="ml-4">
|
||||
<div className="text-lg">{subject.name}</div>
|
||||
<div className="ml-4 grid grid-cols-3">
|
||||
Fácil
|
||||
<span>
|
||||
{watch(`subjectWeights.easy.${subject.id}`) ?? 5}
|
||||
</span>
|
||||
<div>
|
||||
<Controller
|
||||
name={`subjectWeights.easy.${subject.id}`}
|
||||
control={control}
|
||||
defaultValue={5}
|
||||
render={({ field }) => (
|
||||
<input
|
||||
className="w-full"
|
||||
type="range"
|
||||
min={0}
|
||||
max={10}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{selectedAxis.map(axis => (
|
||||
<div
|
||||
key={`list-axis-${axis.id}`}
|
||||
className="flex flex-col w-full border border-gray-300 rounded p-4 mt-4 shadow-sm"
|
||||
>
|
||||
<div key={`list-axis-${axis.id}`} className="ml-4 mb-2">
|
||||
<div className="flex justify-between">
|
||||
<div className="text-lg">{axis.name}</div>
|
||||
<div className="text-red-600 cursor-pointer" onClick={() => handleRemoveAxis(axis.id)}><FaTrash></FaTrash></div>
|
||||
</div>
|
||||
<div className="ml-4 grid grid-cols-3">
|
||||
Fácil
|
||||
<span>
|
||||
{watch(`axisWeights.easy.${axis.id}`) ?? 5}
|
||||
</span>
|
||||
<div>
|
||||
<Controller
|
||||
name={`axisWeights.easy.${axis.id}`}
|
||||
control={control}
|
||||
defaultValue={5}
|
||||
render={({ field }) => (
|
||||
<input
|
||||
className="w-full"
|
||||
type="range"
|
||||
min={0}
|
||||
max={10}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="ml-4 grid grid-cols-3">
|
||||
Médio
|
||||
<span>
|
||||
{watch(`subjectWeights.medium.${subject.id}`) ?? 5}
|
||||
</span>
|
||||
<div>
|
||||
<Controller
|
||||
name={`subjectWeights.medium.${subject.id}`}
|
||||
control={control}
|
||||
defaultValue={5}
|
||||
render={({ field }) => (
|
||||
<input
|
||||
className="w-full"
|
||||
type="range"
|
||||
min={0}
|
||||
max={10}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-4 grid grid-cols-3">
|
||||
Médio
|
||||
<span>
|
||||
{watch(`axisWeights.medium.${axis.id}`) ?? 5}
|
||||
</span>
|
||||
<div>
|
||||
<Controller
|
||||
name={`axisWeights.medium.${axis.id}`}
|
||||
control={control}
|
||||
defaultValue={5}
|
||||
render={({ field }) => (
|
||||
<input
|
||||
className="w-full"
|
||||
type="range"
|
||||
min={0}
|
||||
max={10}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="ml-4 grid grid-cols-3">
|
||||
Difícil
|
||||
<span>
|
||||
{watch(`subjectWeights.hard.${subject.id}`) ?? 5}
|
||||
</span>
|
||||
<div>
|
||||
<Controller
|
||||
name={`subjectWeights.hard.${subject.id}`}
|
||||
control={control}
|
||||
defaultValue={5}
|
||||
render={({ field }) => (
|
||||
<input
|
||||
className="w-full"
|
||||
type="range"
|
||||
min={0}
|
||||
max={10}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-4 grid grid-cols-3">
|
||||
Difícil
|
||||
<span>
|
||||
{watch(`axisWeights.hard.${axis.id}`) ?? 5}
|
||||
</span>
|
||||
<div>
|
||||
<Controller
|
||||
name={`axisWeights.hard.${axis.id}`}
|
||||
control={control}
|
||||
defaultValue={5}
|
||||
render={({ field }) => (
|
||||
<input
|
||||
className="w-full"
|
||||
type="range"
|
||||
min={0}
|
||||
max={10}
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
: null
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
: null
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
7
app/policies/axis_policy.rb
Normal file
7
app/policies/axis_policy.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
class AxisPolicy < ApplicationPolicy
|
||||
class Scope < Scope
|
||||
def resolve
|
||||
scope.all
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user