Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

[Sugestão] Compartilhando minha solução para o desafio

Pessoal, segue meu desenvolvimento para a solução do desafio. Espero que contribua.

Filtro/index.tsx

import React, { useState } from "react";
import { useSetRecoilState } from "recoil";
import {
  IFiltroDeEventos,
  IFiltroStatus,
} from "../../interfaces/IFiltroDeEventos";
import { filtroDeEventos } from "../../state/atom";
import style from "./Filtro.module.scss";

const Filtro: React.FC = () => {
  const [data, setData] = useState("");
  const [status, setStatus] = useState<IFiltroStatus>("Ambos");

  const setFiltroDeEvento = useSetRecoilState(filtroDeEventos);

  const submeterForm = (evento: React.FormEvent<HTMLFormElement>) => {
    evento.preventDefault();
    const filtro: IFiltroDeEventos = {
      status,
    };
    data ? (filtro.data = new Date(data)) : (filtro.data = null);

    setFiltroDeEvento(filtro);
  };

  const opcoesFiltro = ["Ambos", "Completos", "Incompletos"];

  return (
    <form className={style.Filtro} onSubmit={submeterForm}>
      <h3 className={style.titulo}>Filtros</h3>
      <label htmlFor="data">Por data</label>
      <input
        type="date"
        name="data"
        className={style.input}
        onChange={(evento) => setData(evento.target.value)}
        placeholder="Por data"
        value={data}
      />
      <label htmlFor="status">Por status</label>
      <select
        name="status"
        id="filtro-status"
        className={style.input}
        onChange={(event) => setStatus(event.target.value as IFiltroStatus)}
      >
        {opcoesFiltro.map((opcao, index) => (
          <option key={index} value={opcao}>
            {opcao}
          </option>
        ))}
      </select>

      <button className={style.botao}>Filtrar</button>
    </form>
  );
};

export default Filtro;

interfaces/IFiltroDeEventos.ts

export type IFiltroStatus = "Completos" | "Incompletos" | "Ambos";

export interface IFiltroDeEventos {
  data?: Date | null;
  status: IFiltroStatus;
}

seletores/index.ts

import { selector } from "recoil";
import { filtroDeEventos, listaDeEventosState } from "../atom";

export const eventosFiltradosState = selector({
  key: "eventosFiltradosState",
  get: ({ get }) => {
    const filtro = get(filtroDeEventos);
    const todosOsEventos = get(listaDeEventosState);
    const eventoComStatus = todosOsEventos.filter((evento) =>
      filtro.status === "Completos"
        ? evento.completo
        : filtro.status === "Incompletos"
        ? !evento.completo
        : true
    );
    const eventos = eventoComStatus.filter((evento) => {
      if (!filtro.data) {
        return true;
      } else {
        const eHOMesmoDia =
          evento.inicio.toISOString().slice(0, 10) ===
          filtro.data.toISOString().slice(0, 10);
        return eHOMesmoDia;
      }
    });
    return eventos;
  },
});

state/atom.ts

import { atom } from "recoil";
import { IEvento } from "../interfaces/IEvento";
import { IFiltroDeEventos } from "../interfaces/IFiltroDeEventos";

export const listaDeEventosState = atom<IEvento[]>({
  key: "listaDeEventosState",
  default: [
    {
      descricao: "Estudar React",
      inicio: new Date("2023-07-19T09:00"),
      fim: new Date("2023-07-19T13:00"),
      completo: false,
      id: 1642342747,
    },
    {
      descricao: "Estudar Recoil",
      inicio: new Date("2023-07-20T09:00"),
      fim: new Date("2023-07-20T11:00"),
      completo: false,
      id: 1642342959,
    },
  ],
});

export const filtroDeEventos = atom<IFiltroDeEventos>({
  key: "filtroDeEventos",
  default: {
    data: null,
    status: "Ambos",
  },
});
3 respostas

Olá Luiz! Tudo ok por aí?

Parabéns pela sua solução para o desafio! Você se saiu muito bem resolvendo o problema e sua contribuição certamente será útil para outras pessoas que enfrentam desafios semelhantes.

Além disso, gostaria de elogiar a organização do seu código. A estrutura do projeto parece bem pensada e sua utilização das interfaces é muito adequada para garantir a tipagem correta dos dados.

Uma dica que posso oferecer é sobre a otimização do seletor eventosFiltradosState em seletores/index.ts. Atualmente, você está filtrando os eventos duas vezes, primeiro com base no status e depois com base na data. Uma maneira de melhorar o desempenho seria aplicar ambos os filtros em uma única passagem, em vez de fazer duas filtragens separadas. Isso pode ser feito combinando as condições usando operadores lógicos dentro do .filter().

Por exemplo, em vez de:

const eventoComStatus = todosOsEventos.filter((evento) =>
  filtro.status === "Completos"
    ? evento.completo
    : filtro.status === "Incompletos"
    ? !evento.completo
    : true
);
const eventos = eventoComStatus.filter((evento) => {
  if (!filtro.data) {
    return true;
  } else {
    const eHOMesmoDia =
      evento.inicio.toISOString().slice(0, 10) ===
      filtro.data.toISOString().slice(0, 10);
    return eHOMesmoDia;
  }
});

Você pode fazer:

const eventos = todosOsEventos.filter((evento) => {
  const statusMatch =
    filtro.status === "Completos"
      ? evento.completo
      : filtro.status === "Incompletos"
      ? !evento.completo
      : true;

  const dataMatch = !filtro.data || evento.inicio.toISOString().slice(0, 10) === filtro.data.toISOString().slice(0, 10);

  return statusMatch && dataMatch;
});

Isso deve melhorar a eficiência do seletor, especialmente quando a lista de eventos for grande.

Continue assim, Luiz! Excelente trabalho e obrigado por compartilhar sua solução conosco.

E caso precise você pode contar com o Fórum!

Abraços e bons estudos.

solução!

Olá Renan! Tudo ótimo e você?

Muito obrigado por compartilhar essa melhoria. Irei implementar.

Gostaria de mencionar que também adicionei a biblioteca "concurrently" como dependência de desenvolvimento para poder executar o servidor "json-server" e o "react" no próprio script "npm start". Achei que ficou muito mais fácil para executar o projeto local.

Segue o que foi feito:

  1. instalar a lib concurrently:

    "npm i -D concurrently"

  2. adicionar a execução do "json-server" para script "start" no package.json:

    "start": "concurrently "json-server --watch db.json -p 8000" "react-scripts start""

  3. executar no terminal o comando "npm start".

log do terminal ao executar o comando npm start

Olá Luiz! Eaí tudo ok?

Fico muito feliz em saber que você gostou da ideia.

Parabéns pela iniciativa de utilizar da biblioteca "concurrently". Ela tornará o processo de desenvolvimento muito mais prático e eficiente.

Agradeço por compartilhar o passo a passo detalhado.

Compartilhar essas informações é muito útil para que outros colegas possam aprender e utilizar essa abordagem em seus projetos também.

Continue com esse ótimo trabalho, Luiz! Tenho certeza de que suas contribuições serão valiosas para aprimorar ainda mais o ambiente da comunidade do fórum e auxiliar outros alunos na sua jornada de aprendizado.

Se precisar de qualquer ajuda ou tiver mais ideias, estou aqui para apoiar.

Parabéns novamente pela dedicação e pelo excelente trabalho!

Abraços e sucesso em sua jornada da aprendizagem! ;)