In.Orbit-Web

Projeto para organizar suas metas - Realizei seguindo o evento da RocketSeat do dia 09/09/24 até 15/09/24

Stars
2

In.Orbit Front-End

Esse o lado do cliente do projeto in.orbit, ele uma aplicao web usando React que consulta dados do Back-End atravs de uma API utilizando o React Query

O projeto foi criado no evento NLW da RocketSeat com nvel intermedirio com tutoria do Diego Fernandes.

Abaixo vou dar destaque a alguns pontos que para mim foram destaque do projeto, ou por ser minha primeira experincia usando ou por ser chave no projeto.

@radix-ui

Sendo sincero, nem conhecia essa lib e tambm nunca fui um grande apoiador dessas libs que disponibilizam uma UI pr-pronta.

Isso porque acredito que seja importante conseguir criar do 0 sem ser dependende de uma lib assim, mas achei muito interessante trabalhar com uma lib dessa pela primeira vez, quem sabe um dia me aprofunde.

No caso nos foi disponibilizado uma pasta chamada "ui" com os componentes usando @radix-ui j criados

  src/components/ui

Instalao

  npm i @radix ui

Exemplo de componente

  src/components/ui/progress-bar.tsx
import * as ProgressPrimitive from '@radix-ui/react-progress'

export function Progress(props: ProgressPrimitive.ProgressProps) {
  return (
    <ProgressPrimitive.Progress
      {...props}
      className="bg-zinc-900 rounded-full h-2"
    />
  )
}

export function ProgressIndicator(
  props: ProgressPrimitive.ProgressIndicatorProps
) {
  return (
    <ProgressPrimitive.Indicator
      {...props}
      className="bg-gradient-to-r from-pink-500 to-violet-500 w-1/2 h-2 rounded-full"
    />
  )
}

Exemplo de aplicao

{/* Restante dos imports */}
import { Progress, ProgressIndicator } from './ui/progress-bar'

export default function Summary() {
  {/* Restante das operaes */}
  return (
    {/* Outros componentes acima */}
     <Progress value={8} max={15}>
      {/* completedPercentage => Varivel nmerica */}
       <ProgressIndicator style={{ width: `${completedPercentage}%` }} />
     </Progress>
    {/* Outros componentes abaixo */}
  )
}

React Query

Nunca havia usado antes, mas defitivamente mudou minhas perspectiva quanto a requisies http usando React, definitivamente no vou mais usar o bom e velho useEffect para isso...

Instalao

  npm i @tanstack/react-query

Definindo provider

Para podermos utilizar o React Query na nossa aplicao precisamos implementar nosso provider no arquivo raiz que engloba os demais, no caso main.tsx

  src/main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './app'
import './index.css'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient()

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </StrictMode>
)

Exemplo - Realizando requisio

O useQuery muito mais eficiente que o mtodo "nativo" por inumeros motivos, mas principalmente pois possivel cancelar requisies, requisitar novamente ou definir um tempo entre a requisio atual ou a prxima com muita facilidade, assim ganhando muito desempenho.

Abaixo deixo um exemplo da realizao de uma requisio http:

  src/components/summary.tsx
import { useQuery } from '@tanstack/react-query'

export default function Summary() {
  const { data: summary } = useQuery({
    queryKey: ['summary'],
    queryFn: getSummary,
    staleTime: 1000 * 60,
  })

  if (!summary?.at(0)) {
    return null
  }

  return (
    <h1>Todas as tarefas cadastradas: {summary[0].total}</h1>
  )
}

Exemplo - Renovando requisio

Para "cancelar" uma requisio antiga e renova-l muito tranquilo, basta declarar um "useQueryClient" e utilizar o mtodo ".invalidateQueries", deixo abaixo um exemplo de componente que usa o useQuery e o useQueryClient

  src/components/pending-goals.tsx
import { Plus } from 'lucide-react'
import { OutlineButton } from './ui/outline-button'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { getPendingGoals } from '../http/get-pending-goals'
import { createGoalCompletion } from '../http/create-goal-completion'
import { deleteGoal } from '../http/delete-goal'

export default function PendingGoals() {
  const queryClient = useQueryClient()

  const { data: pendingGoals } = useQuery({
    queryKey: ['pending-goals'],
    queryFn: getPendingGoals,
    staleTime: 1000 * 60,
  })

  if (!pendingGoals) {
    return null
  }

  async function handleCompleteGoal(goalId: string) {
    await createGoalCompletion(goalId)

    queryClient.invalidateQueries({ queryKey: ['summary'] })
    queryClient.invalidateQueries({ queryKey: ['pending-goals'] })
  }

  async function handleDeleteGoal(goalId: string) {
    await deleteGoal(goalId)

    queryClient.invalidateQueries({ queryKey: ['summary'] })
    queryClient.invalidateQueries({ queryKey: ['pending-goals'] })
  }

  return (
    <div className="flex flex-wrap gap-3">
      {pendingGoals.map(goal => {
        return (
          <OutlineButton
            onClick={() => handleCompleteGoal(goal.id)}
            onDoubleClick={() => handleDeleteGoal(goal.id)}
            key={goal.id}
            disabled={goal.completionCount >= goal.desiredWeeklyFrequency}
          >
            <Plus className="size-4 text-zinc-600" />
            {goal.title}
          </OutlineButton>
        )
      })}
    </div>
  )
}

Resultado Final do Projeto

https://github.com/user-attachments/assets/cb45546f-88de-4c97-a723-a62caa3a5aae

Autores