Desenvolvedores
src_
blocks
PerguntaObjetiva.ts

📝 Bloco de Pergunta Objetiva no PayloadCMS

O PerguntaObjetiva é um bloco criado para armazenar perguntas de múltipla escolha dentro do PayloadCMS. Ele permite a criação de alternativas, a definição de uma resposta correta e a inclusão de uma explicação opcional.

🚀 Estrutura do Bloco

Esse bloco é composto pelos seguintes elementos:

  • slug → Define um identificador único do bloco.
  • labels → Define os nomes no singular e plural para exibição no painel.
  • fields → Define os campos da pergunta, alternativas e explicação.
import { Block } from 'payload'  
import {  
  lexicalEditor,  
  FixedToolbarFeature,  
  InlineToolbarFeature,  
} from '@payloadcms/richtext-lexical'  
import { isAdminOrCreatedByField } from '@/access/isAdminOrCreatedBy'

🔹 Aqui importamos os módulos necessários:

  • Block: Representa a estrutura de um bloco no PayloadCMS.
  • lexicalEditor: Editor de texto baseado no Lexical.
  • FixedToolbarFeature: Adiciona uma barra de ferramentas fixa ao editor.
  • InlineToolbarFeature: Adiciona uma barra de ferramentas flutuante para edição inline.
  • isAdminOrCreatedByField: Função de controle de acesso para restringir visualização no frontend.

🏗️ Definição do Bloco

const PerguntaObjetiva: Block = {  
  slug: 'perguntaObjetiva', // 🏷️ Identificador do bloco  
  labels: {  
    singular: 'Pergunta objetiva',  
    plural: 'Perguntas objetivas',  
  },  

🔹 O slug define o identificador do bloco, que será usado internamente pelo PayloadCMS.
🔹 Os rótulos (labels) especificam os nomes para exibição no painel.


📌 Campo da Pergunta

  fields: [  
    {  
      name: 'pergunta',  
      label: 'Enunciado da Pergunta Objetiva', // 📝 Texto da pergunta  
      type: 'richText',  
      required: true,  
      editor: lexicalEditor({  
        features: ({ defaultFeatures }) => {  
          return [...defaultFeatures, FixedToolbarFeature(), InlineToolbarFeature()]  
        },  
      }),  
    },

🔹 name: 'pergunta' → Define o identificador do campo.
🔹 label: 'Enunciado da Pergunta Objetiva' → Nome que aparecerá no painel administrativo.
🔹 type: 'richText' → Permite o uso do editor de texto avançado.
🔹 required: true → Torna o campo obrigatório.


🔢 Campo das Alternativas

    {  
      name: 'alternativas',  
      label: 'Alternativas',  
      type: 'array',  
      required: true,  
      minRows: 2, // 🔢 Exige pelo menos duas opções  
      fields: [  
        {  
          type: 'row',  
          fields: [  
            {  
              name: 'isCorrect',  
              label: 'Resposta Correta ✅',  
              type: 'checkbox',  
              required: true,  
              defaultValue: false,  
              access: {  
                read: isAdminOrCreatedByField, // 🔒 Restrição de acesso  
              },  
              admin: {  
                width: '9%',  
              },  
            },  
            {  
              name: 'texto',  
              label: 'Texto da Alternativa 📝',  
              type: 'textarea',  
              required: true,  
              admin: {  
                width: '79%',  
              },  
            },  
          ],  
        },  
      ],  

🔹 Alternativas são armazenadas como um array, garantindo que a pergunta tenha mais de uma opção.
🔹 isCorrect → Checkbox que define se a alternativa está correta (acesso restrito para evitar trapaças).
🔹 texto → Campo de texto para o conteúdo da alternativa.


🔍 Validação da Resposta

      validate: (value) => {  
        const correctAnswers = value.filter((option: { isCorrect: any }) => option.isCorrect)  
        if (correctAnswers.length !== 1) {  
          return 'Você deve marcar exatamente uma alternativa como correta.'  
        }  
        return true  
      },  
    },

🔹 Essa função valida que apenas uma alternativa seja marcada como correta. Caso contrário, retorna um erro.


📝 Campo de Explicação (Opcional)

    {  
      name: 'explicacao',  
      label: 'Explicação (opcional) 🤔',  
      type: 'textarea',  
      required: false,  
    },  
  ],  
}

🔹 Esse campo permite adicionar uma explicação para justificar a resposta correta.


📜 Código Completo

import { Block } from 'payload'  
import {  
  lexicalEditor,  
  FixedToolbarFeature,  
  InlineToolbarFeature,  
} from '@payloadcms/richtext-lexical'  
import { isAdminOrCreatedByField } from '@/access/isAdminOrCreatedBy'  
 
const PerguntaObjetiva: Block = {  
  slug: 'perguntaObjetiva',  
  labels: {  
    singular: 'Pergunta objetiva',  
    plural: 'Perguntas objetivas',  
  },  
  fields: [  
    {  
      name: 'pergunta',  
      label: 'Enunciado da Pergunta Objetiva',  
      type: 'richText',  
      required: true,  
      editor: lexicalEditor({  
        features: ({ defaultFeatures }) => {  
          return [...defaultFeatures, FixedToolbarFeature(), InlineToolbarFeature()]  
        },  
      }),  
    },  
    {  
      name: 'alternativas',  
      label: 'Alternativas',  
      type: 'array',  
      required: true,  
      minRows: 2,  
      fields: [  
        {  
          type: 'row',  
          fields: [  
            {  
              name: 'isCorrect',  
              label: 'Resposta Correta ✅',  
              type: 'checkbox',  
              required: true,  
              defaultValue: false,  
              access: {  
                read: isAdminOrCreatedByField,  
              },  
              admin: {  
                width: '9%',  
              },  
            },  
            {  
              name: 'texto',  
              label: 'Texto da Alternativa 📝',  
              type: 'textarea',  
              required: true,  
              admin: {  
                width: '79%',  
              },  
            },  
          ],  
        },  
      ],  
      validate: (value) => {  
        const correctAnswers = value.filter((option: { isCorrect: any }) => option.isCorrect)  
        if (correctAnswers.length !== 1) {  
          return 'Você deve marcar exatamente uma alternativa como correta.'  
        }  
        return true  
      },  
    },  
    {  
      name: 'explicacao',  
      label: 'Explicação (opcional) 🤔',  
      type: 'textarea',  
      required: false,  
    },  
  ],  
}  
 
export default PerguntaObjetiva