Filtros

Formulário

O padrão de listagem do Brain: Toolbar com busca, troca de visão e FilterButton; os filtros aplicados logo abaixo, cada um removível; depois as abas com contador, que contam a lista já filtrada. O FilterDrawer guarda um rascunho: Aplicar entrega, fechar sem aplicar descarta.

Substitui no Brain:ui filter-buttonui active-filtersGavetaDeFiltrospartners FilterButton / ActiveFilters

Listagem com filtros, como no Brain

Filtros ativos:Financeiro
Conciliação automática
"use client";

import {
  ActiveFilters,
  Badge,
  FilterButton,
  FilterDrawer,
  FormField,
  MultiCombobox,
  SearchInput,
  SegmentedControl,
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
  Toolbar,
} from "@paytime/ui";
import { useState } from "react";

const AREAS = [
  { value: "comercial", label: "Comercial" },
  { value: "financeiro", label: "Financeiro" },
  { value: "operacoes", label: "Operações" },
];

const PROJECTS = [
  { name: "Novo checkout", area: "comercial", archived: false },
  { name: "Conciliação automática", area: "financeiro", archived: false },
  { name: "Onboarding de parceiros", area: "operacoes", archived: false },
  { name: "Migração do ERP", area: "financeiro", archived: true },
];

export default function Example() {
  const [search, setSearch] = useState("");
  const [view, setView] = useState("tabela");
  const [isDrawerOpen, setDrawerOpen] = useState(false);
  const [draft, setDraft] = useState<string[]>([]);
  const [areas, setAreas] = useState<string[]>(["financeiro"]);

  const labelOf = (value: string) => AREAS.find((area) => area.value === value)?.label ?? value;
  const filtered = PROJECTS.filter(
    (project) =>
      (areas.length === 0 || areas.includes(project.area)) &&
      project.name.toLowerCase().includes(search.trim().toLowerCase()),
  );
  // Counts use the filtered list, so a badge never disagrees with the rows shown.
  const active = filtered.filter((project) => !project.archived);
  const archived = filtered.filter((project) => project.archived);

  return (
    <div>
      <Toolbar
        className="mb-4"
        search={
          <SearchInput
            placeholder="Buscar projeto"
            aria-label="Buscar projeto"
            value={search}
            onChange={(event) => setSearch(event.target.value)}
          />
        }
      >
        <SegmentedControl
          appearance="tabs"
          aria-label="Visão da listagem"
          value={view}
          onValueChange={setView}
          options={[
            { value: "tabela", label: "Tabela" },
            { value: "cartoes", label: "Cartões" },
          ]}
        />
        <FilterButton
          count={areas.length}
          onClick={() => {
            setDraft(areas);
            setDrawerOpen(true);
          }}
        />
      </Toolbar>

      <ActiveFilters
        filters={areas.map((value) => ({ key: value, label: labelOf(value) }))}
        onRemove={(key) => setAreas((current) => current.filter((value) => value !== key))}
        onClear={() => setAreas([])}
      />

      <Tabs defaultValue="operacao">
        <TabsList className="mb-4">
          <TabsTrigger value="operacao">
            Em operação
            <Badge size="sm">{active.length}</Badge>
          </TabsTrigger>
          <TabsTrigger value="arquivados">
            Arquivados
            <Badge size="sm">{archived.length}</Badge>
          </TabsTrigger>
        </TabsList>
        <TabsContent value="operacao" className="mt-0 text-[13px]">
          {active.map((project) => project.name).join(" · ") || "Nenhum projeto com esses filtros."}
        </TabsContent>
        <TabsContent value="arquivados" className="mt-0 text-[13px]">
          {archived.map((project) => project.name).join(" · ") || "Nenhum projeto com esses filtros."}
        </TabsContent>
      </Tabs>

      <FilterDrawer open={isDrawerOpen} onOpenChange={setDrawerOpen} onApply={() => setAreas(draft)} onClear={() => setDraft([])}>
        <FormField label="Área">
          <MultiCombobox values={draft} onValuesChange={setDraft} options={AREAS} />
        </FormField>
      </FilterDrawer>
    </div>
  );
}