npm package: @mw-kit/mw-manager
Description: Made with create-react-library
Author: author
Latest version: 1.7.4

# Manager

Responsável por....

[![NPM](https://img.shields.io/npm/v/@mw-kit/mw-manager.svg)](https://www.npmjs.com/package/@mw-kit/mw-manager) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)

## Instalando

```bash
yarn add @mw-kit/mw-manager
```

## Usando

```tsx
import React, { useEffect, useState, useCallback } from 'react'

import {
  MwManager,
  Toolbar,
  FiltersInterfaces,
  SortState,
  ColumnInterface,
  Dropdown,
  DropdownInterfaces,
} from 'mw-manager'

/**
 * Cabeçalho de exemplo
 */
const header: ColumnInterface[] = [
  {
    content: 'Nome',
    key: 'name',
    textAlign: 'left' as const,
    width: 4 as const,
    sortKey: 'name',
  },
  {
    content: 'Altura',
    key: 'height',
    textAlign: 'left' as const,
    width: 3 as const,
    sortKey: 'height',
    verticalAlign: 'end',
  },
  {
    content: 'Filmes',
    key: 'films',
    textAlign: 'center' as const,
    width: 3 as const,
    sortKey: 'films',
  },
  {
    content: 'Veiculos',
    key: 'vehicles',
    textAlign: 'center' as const,
    width: 3 as const,
    sortKey: 'vehicles',
  },
  {
    content: 'Naves',
    key: 'starships',
    textAlign: 'center' as const,
    width: 3 as const,
    sortKey: 'starships',
  },
]

interface DataInterface {
  name: string
  height: string
  mass: string
  hair_color: string
  skin_color: string
  eye_color: string
  birth_year: string
  gender: string
  homeworld: string
  films: string[]
  species: string[]
  vehicles: string[]
  starships: string[]
  created: string
  edited: string
  url: string
}

interface BodyInterface {
  nameStr: string
  name: JSX.Element
  height: string
  mass: string
  hair_color: string
  skin_color: string
  eye_color: string
  birth_year: string
  gender: string
  homeworld: string
  films: number
  species: number
  vehicles: number
  starships: number
  created: string
  edited: string
  url: string
}

const filters: FiltersInterfaces.Filter[] = [
  {
    label: 'Status',
    name: 'active',
    options: [
      { label: <b>Ativo</b>, value: 1 },
      { label: 'Inativo', value: 0 },
    ],
    delimiter: true,
  },
  {
    label: 'Personagem',
    name: 'people_id',
    options: async (value: string, page?: number) => {
      // inicializando a variavel que contera os parametros da query http
      let params: any = {}

      if (value.trim() !== '') params.search = value
      if (page) params.page = page

      // montando a http query string
      params = Object.keys(params)
        .map((key) => `${key}=${params[key]}`)
        .join('&')

      // concatenando a base url com a http query string e fazendo a requisicao
      const response = await fetch([baseURL, params].join('?'))
      // decodificando o conteudo json do body da requisicao
      const responseData: any = JSON.parse(await response.text())

      // retornando o conteudo do body da requisicao
      const options = responseData.results.map((e: any) => ({
        label: e.name,
        value: e.url.split('/').at(-2),
      }))

      return { options, lastPage: !responseData.next }
    },
    // disabled: true,
    allowEmptyString: true,
  },
]

const baseURL = 'https://swapi.dev/api/people/'

// essa funcao ira pegar os dados recebidos e fazer o parse para o formato que o manager precisa
const parseData = (data: DataInterface[]): BodyInterface[] => {
  return data.map((e) => {
    return {
      nameStr: e.name,
      name: <b>{e.name}</b>,
      height: e.height,
      mass: e.mass,
      hair_color: e.hair_color,
      skin_color: e.skin_color,
      eye_color: e.eye_color,
      birth_year: e.birth_year,
      gender: e.gender,
      homeworld: e.homeworld,
      films: e.films.length,
      species: e.species.length,
      vehicles: e.vehicles.length,
      starships: e.starships.length,
      created: e.created,
      edited: e.edited,
      url: e.url,
    }
  })
}

// essa funcao ira fazer a requisicao dos dados
const request = async (
  appliedFilters: FiltersInterfaces.AppliedFilter[],
  search: string,
  sort: SortState | null,
  page: number
): Promise<any> => {
  // inicializando a variavel que contera os parametros da query http
  let params: any = {
    page,
  }

  // se existir algo na busca, insere o valor nos parametros da requisicao
  if (search.length > 0) params.search = search

  // para cada filtro aplicado, adiciona o nome do filtro e o valor aos parametros da requisicao
  for (let i = 0; i < appliedFilters.length; i++) {
    const { name, value } = { ...appliedFilters[i] }
    params[name] = value
  }

  // se houver alguma ordenacao aplicada, adiciona o nome da ordenacao e a direcao aos parametros da requisicao
  if (sort) {
    params.sort = sort.sort
    params.direction = sort.direction
  }

  // montando a http query string
  params = Object.keys(params)
    .map((key) => `${key}=${params[key]}`)
    .join('&')

  // concatenando a base url com a http query string e fazendo a requisicao
  const response = await fetch([baseURL, params].join('?'))
  // decodificando o conteudo json do body da requisicao
  const responseData: any = JSON.parse(await response.text())

  // retornando o conteudo do body da requisicao
  return responseData
}

const App = () => {
  // estado controlador dos filtros aplicados
  const [appliedFilters, setAppliedFilters] = useState<
    FiltersInterfaces.AppliedFilter[]
  >([])

  // estado controlador do valor do input de pesquisa
  const [search, setSearch] = useState<string>('')
  // estado controlador dos dados recebidos
  const [data, setData] = useState<DataInterface[]>([])
  // estado controlador do conteudo do manager
  const [body, setBody] = useState<BodyInterface[]>([])
  // estado controlador da ordenacao
  const [sort, setSort] = useState<SortState | null>(null)
  // estado controlador do loading
  const [loading, setLoading] = useState<boolean>(false)
  // estado controlador da paginacao
  const [page, setPage] = useState<number>(1)
  // estado controlador do limite da paginacao
  const [isLastPage, setIsLastPage] = useState<boolean>(false)
  // estado controlador dos itens checados
  const [checkeds, setCheckeds] = useState<BodyInterface[]>([])
  // estado controlador do filtro de calendario
  const [date, setDate] = useState<Date>(new Date())

  // essa funcao tem os filtros aplicados, o valor do input de busca e o valor da ordenacao como dependencias
  const loadData = useCallback(async () => {
    setLoading(true)

    // fazendo requisicao dos dados
    const responseData = await request(appliedFilters, search, sort, page)
    // setando se a pagina atual e a ultima
    setIsLastPage(!responseData.next)
    // pegando os resultados da requisicao
    const results = responseData.results || []

    // se for a primeira pagina, seta os resultados, se nao, concatena os resultados
    setData(page === 1 ? results : (prev) => prev.concat(results))

    setLoading(false)
  }, [appliedFilters, search, sort, page])

  // essa funcao sera executada quando clicar no botao refresh da barra de ferramentas
  const reload = () => {
    page === 1 ? loadData() : setPage(1)
  }

  // sempre que alguma dependencia da funcao loadData for alterada, chama a funcao
  useEffect(() => {
    loadData()
  }, [loadData])

  // sempre que os dados sao alterados, faz o parse para o formato que o manager precisa
  useEffect(() => {
    setBody(parseData(data))
  }, [data])

  const getItemMenu = (item: BodyInterface): DropdownInterfaces.Item[] => {
    return [
      {
        content: 'Editar',
        onClick: () => {
          alert(`Editar ${item.nameStr}`)
        },
        rules: [],
      },
      {
        content: 'Excluir',
        onClick: () => {
          alert(`Excluir ${item.nameStr}`)
        },
        rules: [],
      },
    ]
  }

  const paginator = () => {
    if (!isLastPage) setPage((prev) => (prev += 1))
  }

  const getRowDisabled = (row: BodyInterface): boolean => {
    return (
      checkeds.length === 2 &&
      !checkeds.some((checked) => checked.nameStr === row.nameStr)
    )
  }

  return (
    <div style={{ padding: '14px', height: '100%' }}>
      <div
        style={{
          width: '100%',
          height: '100%',
          display: 'flex',
          flexDirection: 'column',
        }}
      >
        <Toolbar
          filters={{
            filters,
            setAppliedFilters,
            appliedFilters,
            bottomMargin: 14,
          }}
          search={{ setSearch }}
          loading={loading}
          reloader={reload}
          pagination={{ setPage, isLastPage, paginator }}
          calendar={{
            date,
            setDate,
          }}
          except={{}}
          before={<div>Elemento 4</div>}
          after={<div>Elemento 5</div>}
        >
          <div>Elemento 1</div>
          <div>Elemento 2</div>
          <div>Elemento 3</div>
          <Dropdown
            items={[
              {
                content: 'Ativar',
                onClick: () => alert('Ativar'),
                rules: [
                  {
                    rule: () => {
                      return checkeds.length > 0
                    },
                    message: (
                      <b style={{ color: 'red' }}>
                        Deve selecionar pelo menos um item
                      </b>
                    ),
                  },
                ],
              },
              {
                content: 'Inativar',
                onClick: () => alert('Inativar'),
                rules: [
                  {
                    rule: () => {
                      return checkeds.length > 0
                    },
                    message: 'Deve selecionar pelo menos um item',
                  },
                ],
              },
              {
                content: 'Deletar',
                onClick: () => alert('Deletar'),
                rules: [
                  {
                    rule: () => {
                      return checkeds.length > 0
                    },
                    message: 'Deve selecionar pelo menos um item',
                  },
                ],
              },
              {
                content: 'Extrair dados',
                onClick: () => alert('Extrair dados'),
                border: true,
                rules: [],
              },
            ]}
            loading={loading}
            axis='y'
          />

          <button style={{ padding: 0 }}>Botão 1</button>
          <button style={{ padding: 0 }}>Botão 2</button>
          <button style={{ padding: 0 }}>Botão 3</button>
        </Toolbar>

        <MwManager
          columns={header}
          rows={body}
          sort={{ sort, setSort }}
          hasFilters={appliedFilters.length > 0 || search.length > 0}
          messages={{
            empty: 'Nenhum personagem encontrado',
            emptyWithFilters:
              'Nenhum personagem encontrado para a busca realizada',
          }}
          loading={loading}
          paginator={paginator}
          page={page}
          setPage={setPage}
          checkeds={{ checkeds, setCheckeds, verticalAlign: 'start' }}
          getItemMenu={getItemMenu}
          itemMenuVerticalAlign='end'
          centerCoodinates={{ y: 50 }}
          getRowDisabled={getRowDisabled}
        />
      </div>
    </div>
  )
}

export default App
```

## License

MIT © MundoWap