Desenvolvedores
src_
app_
(app)
cursos
slugs
page.js

📚 Documentação do Arquivo page.js - [slugs]

🚀 Funcionalidades

  • Carregamento Dinâmico: Carrega e exibe o curso com base no slug da URL.
  • Exibição Interativa: Apresenta informações como nome, descrição, níveis de habilidade, horas de duração, módulos e pré-requisitos.
  • Interação com Módulos: Permite expandir ou contrair módulos para ver suas respectivas aulas.

🧑‍💻 Explicação do Código

Abaixo estão as principais partes do código que implementam a funcionalidade descrita acima.

'use client'
import { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { useCourses } from '@/components/context/CoursesContext'
import RichTextContent from '@/components/RichTextContent'
import Link from 'next/link'
import {
  FaCode,
  FaProjectDiagram,
  FaInfoCircle,
  FaAward,
  FaFolder,
  FaClock,
  FaChartBar,
  FaExclamationCircle,
  FaChevronDown,
  FaChevronUp,
  FaBook,
} from 'react-icons/fa'

Aqui, importamos os hooks useState e useEffect, componentes e ícones necessários para o funcionamento da interface.


🔑 Estado e Efeitos

Definimos dois estados importantes para controlar os dados e o estado de visualização dos módulos.

export default function CoursePage({ params }) {
  const { slug } = params // Obtém o slug do curso da URL
  const { courses } = useCourses() // Acessa o contexto de cursos
  const [course, setCourse] = useState(null) // Estado para armazenar o curso encontrado
  const [openModuleIndex, setOpenModuleIndex] = useState(null) // Estado para controlar qual módulo está aberto
 
  useEffect(() => {
    if (slug) {
      const foundCourse = courses.find((course) => course.slug === slug) // Busca o curso pelo slug
      setCourse(foundCourse) // Atualiza o estado com o curso encontrado
    }
  }, [slug, courses]) // Re-executa quando o slug ou a lista de cursos muda

Usamos o useEffect para buscar o curso baseado no slug da URL. O estado course armazena o curso encontrado, enquanto openModuleIndex controla a expansão dos módulos.


📚 Exibição do Curso e Seus Detalhes

A seguir, temos o código que exibe as informações do curso.

  if (!course) {
    return <div>Curso não encontrado ou carregando...</div> // Mensagem de carregamento ou erro
  }
 
  const handleToggleModule = (index) => {
    // Função para alternar a visibilidade de um módulo
    setOpenModuleIndex(openModuleIndex === index ? null : index)
  }
 
  const totalModulos = Array.isArray(course.modulos) ? course.modulos.length : 0 // Total de módulos
  const totalAulas = Array.isArray(course.modulos)
    ? course.modulos.reduce(
        (acc, modulo) => acc + (Array.isArray(modulo.aulas) ? modulo.aulas.length : 0),
        0,
      )
    : 0 // Total de aulas

Aqui, verificamos se o curso foi encontrado e calculamos o total de módulos e aulas, além de permitir a alternância entre expandir ou contrair módulos.


🖥️ Renderização e Interface de Usuário

Agora, vamos para a renderização do conteúdo do curso, como nome, descrição, módulos e aulas.

  return (
    <div className="max-w-4xl mx-auto p-4 space-y-8">
      <section className="p-6 border rounded-md">
        <h2 className="text-sm font-semibold text-muted-foreground">Curso</h2>
        <h1 className="text-3xl font-bold">{course.nomeCurso}</h1>
        <p className="mt-2 text-muted-foreground">{course.descricao}</p>
        <Button className="mt-4 bg-primary text-primary-foreground">Iniciar</Button>
        <div className="mt-6 p-4 border rounded-md">
          <h3 className="text-lg font-semibold">Este curso inclui</h3>
          <ul className="mt-2 space-y-2">
            <li className="flex items-center">
              <FaCode className="mr-2 h-5 w-5" />
              Assistência de professores qualificados
            </li>
            <li className="flex items-center">
              <FaProjectDiagram className="mr-2 h-5 w-5" />
              Projetos para aplicar novas habilidades
            </li>
            <li className="flex items-center">
              <FaInfoCircle className="mr-2 h-5 w-5" />
              Questionários para testar seu conhecimento
            </li>
            <li className="flex items-center">
              <FaAward className="mr-2 h-5 w-5" />
              Um certificado de conclusão
            </li>
          </ul>
        </div>
      </section>

Esse trecho exibe as informações principais do curso, como nome, descrição, e botões de interação. Também destaca os recursos adicionais do curso, como assistência de professores e projetos.


🎓 Exibição de Módulos e Aulas

Agora, renderizamos a lista de módulos com a possibilidade de expandir suas aulas.

      <section className="p-4 border rounded-md flex flex-wrap justify-between items-center">
        <div className="flex items-center space-x-4 w-full sm:w-auto mb-4 sm:mb-0">
          <div className="flex items-center space-x-2">
            <FaChartBar className="w-6 h-6 text-muted-foreground mr-2" />
            <div>
              <p className="text-sm">Nível de habilidade</p>
              <p className="text-lg font-semibold">{course.nivel}</p>
            </div>
          </div>
        </div>
      </section>
 
      <section className="p-4 border rounded-md">
        <h2 className="text-xl font-bold">Conteúdo Completo</h2>
        <p>{`${totalModulos} módulos - ${totalAulas} aulas`}</p>
        <div className="mt-4 space-y-4">
          {course && course.modulos && course.modulos.length > 0 ? (
            course.modulos.map((modulo, index) => (
              <div key={index} className="p-4 border rounded-md">
                <div className="flex justify-between items-center">
                  <div className="flex items-center space-x-2">
                    <span className="text-lg font-bold">{index + 1}</span>
                    <h3 className="text-lg font-semibold">{modulo.modulo.nomeModulo}</h3>
                  </div>
                  <button onClick={() => handleToggleModule(index)}>
                    {openModuleIndex === index ? (
                      <FaChevronUp className="h-5 w-5" />
                    ) : (
                      <FaChevronDown className="h-5 w-5" />
                    )}
                  </button>
                </div>
                {openModuleIndex === index && (
                  <ul className="mt-4 space-y-2">
                    {modulo.modulo.aulas.map((aula, aulaIndex) => (
                      <li key={aulaIndex} className="flex items-center space-x-2 ml-3">
                        <FaBook className="h-5 w-5 text-muted-foreground" />
                        <Link
                          href={`/cursos/${course.slug}/${index}/${aula.aula.nomeAula}`}
                          className="text-primary hover:underline"
                        >
                          {aula.aula.nomeAula}
                        </Link>
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            ))
          ) : (
            <p>Nenhum módulo encontrado</p>
          )}
        </div>
      </section>
    </div>
  )
}

Aqui, o componente exibe todos os módulos e aulas do curso. A interação é feita com ícones de expandir e contrair, permitindo ao usuário visualizar as aulas conforme necessário.


📋 Código Completo

'use client'
import { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { useCourses } from '@/components/context/CoursesContext'
import RichTextContent from '@/components/RichTextContent'
import Link from 'next/link'
import {
  FaCode,
  FaProjectDiagram,
  FaInfoCircle,
  FaAward,
  FaFolder,
  FaClock,
  FaChartBar,
  FaExclamationCircle,
  FaChevronDown,
  FaChevronUp,
  FaBook,
} from 'react-icons/fa'
 
export default function CoursePage({ params }) {
  const { slug } = params // Obtém o slug do curso da URL
  const { courses } = useCourses() // Acessa o contexto de cursos
  const [course, setCourse] = useState(null) // Estado para armazenar o curso encontrado
  const [openModuleIndex, setOpenModuleIndex] = useState(null) // Estado para controlar qual módulo está aberto
 
  useEffect(() => {
    if (slug) {
      const foundCourse = courses.find((course) => course.slug === slug) // Busca o curso pelo slug
      setCourse(foundCourse) // Atualiza o estado com o curso encontrado
    }
  }, [slug, courses]) // Re-executa quando o slug ou a lista de cursos muda
 
  if (!course) {
    return <div>Curso não encontrado ou carregando...</div> // Mensagem de carregamento ou erro
  }
 
  const handleToggleModule = (index) => {
    // Função para alternar a visibilidade de um módulo
    setOpenModuleIndex(openModuleIndex === index ? null : index)
  }
 
  const totalModulos = Array.isArray(course.modulos) ? course.modulos.length : 0 // Total de módulos
  const totalAulas = Array.isArray(course.modulos)
    ? course.modulos.reduce(
        (acc, modulo) => acc + (Array.isArray(modulo.aulas) ? modulo.aulas.length : 0),
        0,
      )
    : 0 // Total de aulas
 
  return (
    <div className="max-w-4xl mx-auto p-4 space-y-8">
      <section className="p-6 border rounded-md">
        <h2 className="text-sm font-semibold text-muted-foreground">Curso</h2>
        <h1 className="text-3xl font-bold">{course.nomeCurso}</h1>
        <p className="mt-2 text-muted-foreground">{course.descricao}</p>
        <Button className="mt-4 bg-primary text-primary-foreground">Iniciar</Button>
        <div
 
 className="mt-6 p-4 border rounded-md">
          <h3 className="text-lg font-semibold">Este curso inclui</h3>
          <ul className="mt-2 space-y-2">
            <li className="flex items-center">
              <FaCode className="mr-2 h-5 w-5" />
              Assistência de professores qualificados
            </li>
            <li className="flex items-center">
              <FaProjectDiagram className="mr-2 h-5 w-5" />
              Projetos para aplicar novas habilidades
            </li>
            <li className="flex items-center">
              <FaInfoCircle className="mr-2 h-5 w-5" />
              Questionários para testar seu conhecimento
            </li>
            <li className="flex items-center">
              <FaAward className="mr-2 h-5 w-5" />
              Um certificado de conclusão
            </li>
          </ul>
        </div>
      </section>
 
      <section className="p-4 border rounded-md flex flex-wrap justify-between items-center">
        <div className="flex items-center space-x-4 w-full sm:w-auto mb-4 sm:mb-0">
          <div className="flex items-center space-x-2">
            <FaChartBar className="w-6 h-6 text-muted-foreground mr-2" />
            <div>
              <p className="text-sm">Nível de habilidade</p>
              <p className="text-lg font-semibold">{course.nivel}</p>
            </div>
          </div>
        </div>
      </section>
 
      <section className="p-4 border rounded-md">
        <h2 className="text-xl font-bold">Conteúdo Completo</h2>
        <p>{`${totalModulos} módulos - ${totalAulas} aulas`}</p>
        <div className="mt-4 space-y-4">
          {course && course.modulos && course.modulos.length > 0 ? (
            course.modulos.map((modulo, index) => (
              <div key={index} className="p-4 border rounded-md">
                <div className="flex justify-between items-center">
                  <div className="flex items-center space-x-2">
                    <span className="text-lg font-bold">{index + 1}</span>
                    <h3 className="text-lg font-semibold">{modulo.modulo.nomeModulo}</h3>
                  </div>
                  <button onClick={() => handleToggleModule(index)}>
                    {openModuleIndex === index ? (
                      <FaChevronUp className="h-5 w-5" />
                    ) : (
                      <FaChevronDown className="h-5 w-5" />
                    )}
                  </button>
                </div>
                {openModuleIndex === index && (
                  <ul className="mt-4 space-y-2">
                    {modulo.modulo.aulas.map((aula, aulaIndex) => (
                      <li key={aulaIndex} className="flex items-center space-x-2 ml-3">
                        <FaBook className="h-5 w-5 text-muted-foreground" />
                        <Link
                          href={`/cursos/${course.slug}/${index}/${aula.aula.nomeAula}`}
                          className="text-primary hover:underline"
                        >
                          {aula.aula.nomeAula}
                        </Link>
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            ))
          ) : (
            <p>Nenhum módulo encontrado</p>
          )}
        </div>
      </section>
    </div>
  )
}