use axis instead os subjects on new assessement page

This commit is contained in:
2023-07-05 11:51:01 -03:00
parent d56483e600
commit 0e21b13035
6 changed files with 221 additions and 106 deletions

View 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

View File

@@ -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

View File

@@ -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']>;

View File

@@ -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.

View File

@@ -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>

View File

@@ -0,0 +1,7 @@
class AxisPolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.all
end
end
end