DEV Community

Cover image for Componente genérico de Detalhes de Categoria usando Chakra UI no CrazyStack Next.js
Dev Doido
Dev Doido

Posted on • Edited on

Componente genérico de Detalhes de Categoria usando Chakra UI no CrazyStack Next.js

Bem-vindo à aula "Componente Genérico de Detalhes de Categoria usando Chakra UI e Atomic Design". Nesta aula, exploraremos como criar um componente genérico de detalhes de categoria, que pode ser facilmente reutilizado em diferentes projetos de interface do usuário. Usando o poder do Chakra UI, um conjunto de ferramentas de design de interface do usuário, e o Atomic Design, um método para criar hierarquias de componentes de interface do usuário, criaremos um componente versátil e flexível.

Image description
O vídeo dessa aula está publicada no bootcamp CrazyStack, se você ainda não garantiu sua vaga clique aqui

O Atomic Design permite que criemos componentes mais complexos a partir de componentes menores e mais simples, como átomos, moléculas e organismos. Ao utilizar essa abordagem, podemos criar componentes reutilizáveis e escaláveis ​​que podem ser facilmente modificados e adaptados a diferentes necessidades de design. Combinado com o Chakra UI, que fornece uma ampla variedade de componentes pré-projetados e personalizáveis, podemos criar rapidamente interfaces de usuário atraentes e funcionais.

Ao final desta aula, você terá uma compreensão clara de como criar um componente genérico de detalhes de categoria usando o Chakra UI e o Atomic Design. Você também poderá aplicar esse conhecimento para criar outros componentes reutilizáveis, escaláveis e personalizáveis para suas próprias interfaces de usuário. Vamos começar!

GenericDetailsItem (Molécula)

Este arquivo implementa uma molécula que pode ser usada em diferentes partes do projeto para exibir detalhes genéricos de um item. Ele usa o sistema de grid do Chakra UI para exibir cada detalhe do item. Os detalhes que são exibidos são determinados por meio de uma lista de campos que são passados como props para a molécula. A molécula é altamente reutilizável, uma vez que não é específica para nenhum item em particular, tornando-se uma boa implementação do conceito de Atomic Design.

import { Grid, GridItem, Text } from "@chakra-ui/react";
import React from "react";
interface GenericDetailsItemProps {
  item: any;
  fields: any[];
}

export const GenericDetailsItem: React.FC<GenericDetailsItemProps> = ({
  item,
  fields,
}) => {
  return (
    <Grid
      templateRows="repeat(2, 1fr)"
      templateColumns={["repeat(1,1fr)", "repeat(2,1f)", "repeat(3,1fr)"]}
      gap={2}
    >
      {!!item &&
        fields?.map?.((field, index) => (
          <React.Fragment key={`${Math.random() * 10}-${index}`}>
            {!!item?.[field?.id] && (
              <GridItem w="100%" p={["0", "0", "0", "4"]}>
                <Text>{field?.label}:&nbsp;</Text>
                <Text>{item?.[field?.id]}</Text>
              </GridItem>
            )}
          </React.Fragment>
        ))}
    </Grid>
  );
};
Enter fullscreen mode Exit fullscreen mode

O código acima é um componente React chamado GenericDetailsItem, que é uma molécula que pode ser reutilizada em diferentes partes de um projeto para exibir informações de um item em um formato de tabela. O componente usa o pacote @chakra-ui/react para estilização.

O componente recebe duas propriedades:

  • item: um objeto contendo as informações do item a ser exibido.
  • fields: uma matriz de objetos que descreve os campos do item que devem ser exibidos. Cada objeto contém uma propriedade id, que é a chave do campo no objeto item, e uma propriedade label, que é a etiqueta que deve ser exibida para o campo.

O componente é composto por um Grid, que é uma grade flexível usada para exibir as informações do item em colunas. O Grid tem três propriedades:

  • templateRows: define o número de linhas e sua altura na grade.
  • templateColumns: define o número de colunas e sua largura na grade. Para diferentes tamanhos de tela, o número de colunas é ajustado automaticamente usando a sintaxe de matriz responsiva do Chakra UI. Por exemplo, para telas pequenas, o templateColumns tem uma única coluna (repeat(1, 1fr)), enquanto para telas maiores, ele tem três colunas (repeat(3, 1fr)).
  • gap: define o espaçamento entre as células da grade.

O componente também usa a função .map para percorrer a matriz fields e gerar um conjunto de GridItem para cada campo. Cada GridItem contém um rótulo Text e o valor correspondente do item, que são exibidos em colunas adjacentes. O GridItem tem uma propriedade w que define a largura da célula. Para diferentes tamanhos de tela, essa largura é ajustada automaticamente usando a sintaxe responsiva do Chakra UI.

Por fim, o componente usa a sintaxe condicional !! para garantir que o campo seja exibido apenas se o item tiver um valor para esse campo. Se o item não tiver um valor para o campo, o campo não será exibido.

CategoryDetails

Este arquivo implementa um organismo que exibe os detalhes de uma categoria específica. Ele usa a molécula GenericDetailsItem para exibir os detalhes da categoria e também tem um botão de edição que leva o usuário para a página de edição da categoria. O organismo é específico para a exibição de detalhes de uma categoria e usa a molécula como seu componente genérico de detalhes.

import { Flex, GenericDetailsItem, Text, Button } from "shared/ui";
import { Heading, Icon } from "@chakra-ui/react";
import NextLink from "next/link";
import { RiAddLine } from "react-icons/ri";
import { CategoryProps } from "../category.model";
type CategoryDetailsProps = {
  category: CategoryProps;
};

export const CategoryDetails = ({ category }: CategoryDetailsProps) => {
  return (
    <>
      <Flex mb="8" justify="space-between" align="center">
        <Heading size="lg" fontWeight={"normal"}>
          Categoria {category?.name}
        </Heading>
        <NextLink passHref href={`/categorys/edit/${category?._id}`}>
          <Button
            size="sm"
            fontSize={"sm"}
            colorScheme="green"
            leftIcon={<Icon fontSize="20" as={RiAddLine} />}
          >
            Editar
          </Button>
        </NextLink>
      </Flex>
      <GenericDetailsItem
        item={category}
        fields={[
          { id: "name", label: "Nome" },
          { id: "createdById", label: "Id do criador" },
          { id: "createdAt", label: "Data de criação" },
        ]}
      />
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

O código acima define um componente React chamado CategoryDetails, que é responsável por exibir os detalhes de uma categoria específica. Ele recebe uma propriedade chamada "category", que é um objeto que contém informações sobre a categoria a ser exibida. O componente é composto por dois elementos principais, um componente Flex e um componente GenericDetailsItem.

O componente Flex é responsável por exibir o título da página e um botão de edição. O título é definido como "Categoria" seguido pelo nome da categoria, que é extraído da propriedade "category" usando a notação de ponto. O botão de edição é um componente NextLink que leva o usuário para a página de edição da categoria.

O componente GenericDetailsItem é responsável por exibir os detalhes da categoria, como o nome, o ID do criador e a data de criação. Ele recebe duas propriedades, "item" e "fields". A propriedade "item" é definida como a propriedade "category" que foi passada para o componente CategoryDetails. A propriedade "fields" é um array de objetos que descreve os campos que devem ser exibidos na lista de detalhes da categoria.

O componente GenericDetailsItem usa o componente Grid do Chakra UI para exibir os campos de detalhes da categoria em uma grade. Ele mapeia os campos definidos na propriedade "fields" e usa a notação de ponto para obter os valores correspondentes do objeto "category". Se o valor do campo não for nulo, ele é exibido usando o componente GridItem, que contém um componente Text para o rótulo do campo e outro componente Text para o valor do campo. Se houver mais de um campo, eles serão exibidos em colunas adicionais na grade.

Em resumo, o componente CategoryDetails é responsável por exibir os detalhes de uma categoria, incluindo o título da página e um botão de edição, juntamente com os detalhes da categoria em si. O componente GenericDetailsItem é usado para exibir os campos de detalhes da categoria em uma grade. Juntos, esses componentes fornecem uma visualização clara e organizada dos detalhes da categoria.

CategoryDetailsPage

Este arquivo implementa uma página que exibe os detalhes de uma categoria. Ele usa o organismo CategoryDetails e envolve-o em um componente de caixa que fornece estilos e espaçamento para a página. A página também usa o componente Head para definir o título e a descrição da página. A página é um exemplo de como os componentes do Atomic Design podem ser usados para criar páginas completas.

import { Box, Head } from "shared/ui";
import { CategoryDetails } from "entidades/category/details";
import { CategoryProps } from "entidades/category";
type CategoryDetailsProps = {
  data: CategoryProps;
  id: string;
};
export const CategoryDetailsPage = ({ data, id }: CategoryDetailsProps) => {
  const props = { category: data };
  return (
    <>
      <Head
        title={"Belezix Admin | Categorias"}
        description="Página de detalhes de categorias do painel de Admin Belezix"
      />
      <Box flex="1" borderRadius={8} bg="purple.800" p="8">
        <CategoryDetails {...props} />
      </Box>
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

Esse é um código para a página de detalhes de uma categoria. A página recebe duas propriedades: data e id. A propriedade data contém todas as informações da categoria, enquanto a propriedade id é apenas o identificador da categoria.

Dentro da função CategoryDetailsPage, é definido um objeto props que contém a propriedade category, que é igual a data. Em seguida, é renderizada uma caixa (Box) que contém o componente CategoryDetails passando as propriedades category e props. O componente Head é usado para definir informações de SEO da página, como o título e a descrição.

Basicamente, a página de detalhes de categoria é exibida com a categoria passada como propriedade para o componente CategoryDetails, que, por sua vez, usa o componente GenericDetailsItem para exibir os detalhes da categoria de forma organizada em uma tabela.

Category API

Este arquivo contém um serviço que faz uma chamada à API para obter os detalhes de uma categoria específica. Ele usa o cliente HTTP setupAPIClient para fazer a chamada e retorna os detalhes da categoria como um objeto CategoryProps. Se houver um erro ao fazer a chamada à API, ele retorna null. O serviço é responsável por buscar os dados da API para fornecer aos componentes da interface do usuário.

export const getCategoryById = async (
  id: string,
  ctx: any
): Promise<CategoryProps | null> => {
  try {
    const { data } = await setupAPIClient(ctx).get("/category/load", {
      params: { _id: id },
    });
    if (!data) {
      return null;
    }
    return categoryModel(data).format();
  } catch (error) {
    return null;
  }
};
Enter fullscreen mode Exit fullscreen mode

Esse é um código que exporta uma função chamada getCategoryById. Essa função recebe dois argumentos: id e ctx. O primeiro é uma string que representa o id da categoria que se deseja buscar. O segundo é um objeto de contexto que é utilizado para realizar a requisição à API.

Dentro da função, há uma chamada à função setupAPIClient, que é responsável por configurar o cliente HTTP utilizado para realizar a requisição. Essa função utiliza o objeto de contexto para adicionar o token de autenticação à requisição.

Em seguida, é realizada uma requisição GET para o endpoint "/category/load", passando o id da categoria como parâmetro na URL. Caso a requisição seja bem sucedida, o objeto data retornado é utilizado para criar uma instância de categoryModel, que é responsável por formatar os dados recebidos para um formato mais adequado.

Se a requisição falhar ou não retornar nenhum dado, a função retorna null.

Em resumo, esse código é responsável por buscar uma categoria específica na API a partir do seu id, formatar os dados recebidos e retornar um objeto que representa a categoria buscada.

details/[id]

Este arquivo é uma página do Next.js que usa a função getServerSideProps para obter os detalhes de uma categoria a partir da API e passá-los para o componente CategoryDetailsPage. A função withSSRAuth é usada para garantir que o usuário esteja autenticado antes de acessar a página. Se o ID fornecido na URL não for uma string válida, a página retornará um erro 404. A página é um exemplo de como os componentes do Atomic Design podem ser usados em conjunto com o Next.js para criar páginas dinâmicas e autenticadas.

import { CategoryDetailsPage } from "screens/category/details/CategoryDetailsPage";
import { getCategoryById } from "entidades/category/category.api";
import { GetServerSideProps } from "next";
import { withSSRAuth } from "shared/libs/utils";
export const getServerSideProps: GetServerSideProps = withSSRAuth(async (context) => {
  const id = context?.query?.id;
  if (!id || typeof id !== "string") {
    return {
      notFound: true,
    };
  }
  const data = await getCategoryById(id, context);
  return {
    props: {
      data,
      id,
    },
  };
});
export default CategoryDetailsPage;
Enter fullscreen mode Exit fullscreen mode

Esse código faz parte da página de detalhes de categoria da aplicação. Quando o usuário acessa a página /details/[id], o servidor executa a função getServerSideProps, que busca os dados da categoria correspondente ao id passado na URL.

A função getServerSideProps usa o utilitário withSSRAuth para garantir que o usuário esteja autenticado antes de carregar a página. Caso contrário, ele é redirecionado para a página de login.

Se o id não for uma string ou não existir, a página retorna o status 404 (não encontrado).

Se tudo estiver correto, a função getCategoryById é chamada para buscar os dados da categoria correspondente ao id passado. Se a busca for bem-sucedida, os dados são retornados como propriedades da página CategoryDetailsPage. Caso contrário, a propriedade data é nula e a página é carregada sem as informações da categoria.

Conclusão

Nesta aula, aprendemos sobre a criação de componentes genéricos de detalhes de categoria usando Chakra UI e Atomic Design. Vimos como criar moléculas, que são componentes compostos de átomos, e como usar essas moléculas para construir componentes maiores, como a página de detalhes de categoria.

Além disso, aprendemos sobre a organização do código em módulos e como o Atomic Design pode ajudar a criar componentes mais reutilizáveis e escaláveis. Também vimos exemplos de como essa organização pode ser aplicada em um projeto real.

Por fim, vimos como usar a API do Next.js para buscar dados do servidor e como usar a autenticação de rota para controlar o acesso a esses dados. Esperamos que esses conceitos tenham sido úteis e ajudado a entender como criar componentes reutilizáveis, escaláveis e bem organizados em seus projetos.

Top comments (0)