| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
68879c33c3 | Estabilizando função de filtro na pagina de encomendas | 3 years ago |
|
|
6da99423b6 | implendata pagina de listagem de encomendas | 3 years ago |
| @ -1,3 +1,3 @@ | |||
| export const Environments = { | |||
| URLApi: "http://jailton.bootcamp.dev.netuno.org:20190/services/netunovendas" | |||
| URLApi: "https://jailton.bootcamp.dev.netuno.org:20193/services/netunovendas" | |||
| } | |||
| @ -0,0 +1,5 @@ | |||
| export interface Encomenda { | |||
| cliente:string, | |||
| itens:[], | |||
| valor:number | |||
| } | |||
| @ -0,0 +1,312 @@ | |||
| import styles from './encomenda.module.css'; | |||
| import { Button, Input, InputRef, Select, Space, Table } from 'antd'; | |||
| import Column from 'antd/es/table/Column'; | |||
| import { SearchOutlined } from '@ant-design/icons'; | |||
| import { useEffect, useRef, useState } from 'react'; | |||
| import { ColumnType } from 'antd/es/table'; | |||
| import Highlighter from 'react-highlight-words'; | |||
| import { useDispatch, useSelector } from 'react-redux'; | |||
| import { | |||
| getAllEncomenda | |||
| } from '../../slices/EncomendaSlice'; | |||
| import { ParamsType } from '../../interfaces/ParamsType'; | |||
| function Encomendas() { | |||
| const dispatch = useDispatch<any>(); | |||
| const { encomendas, loading } = useSelector((state: any) => state.encomenda); | |||
| const [searchText, setSearchText] = useState(''); | |||
| const [statusFilter, setStatusFilter] = useState(''); | |||
| const [clienteFilter, setClienteFilter] = useState(''); | |||
| const [dataCriacaoFilter, setDataCriacaoFilter] = useState(''); | |||
| const [dataEnvioFilter, setDataEnvioFilter] = useState(''); | |||
| const [searchedColumn, setSearchedColumn] = useState(''); | |||
| const searchInput = useRef<InputRef>(null); | |||
| const parans:ParamsType = { | |||
| pagination:{ | |||
| current:1, | |||
| pageSize:5 | |||
| }, | |||
| filter:{ | |||
| data_criacao:dataCriacaoFilter, | |||
| data_envio:dataEnvioFilter, | |||
| status:statusFilter, | |||
| cliente:clienteFilter | |||
| } | |||
| } | |||
| const handleSearch = ( | |||
| selectedKeys: string[], | |||
| dataIndex: any, | |||
| ) => { | |||
| setSearchText(selectedKeys[0]); | |||
| setSearchedColumn(dataIndex); | |||
| if (dataIndex == 'data_envio') { | |||
| setDataEnvioFilter(selectedKeys[0]); | |||
| dispatch(getAllEncomenda( | |||
| { | |||
| pagination: { | |||
| current: 1, | |||
| pageSize: 5 | |||
| }, | |||
| filter:parans.filter | |||
| } | |||
| )); | |||
| } else if (dataIndex == 'data_criacao') { | |||
| setDataCriacaoFilter(selectedKeys[0]); | |||
| dispatch(getAllEncomenda( | |||
| { | |||
| pagination: { | |||
| current: 1, | |||
| pageSize: 5 | |||
| }, | |||
| filter:{...parans.filter,data_criacao:selectedKeys[0]} | |||
| } | |||
| )); | |||
| console.log(parans) | |||
| } else if (dataIndex == 'status') { | |||
| setStatusFilter(selectedKeys[0]) | |||
| dispatch(getAllEncomenda( | |||
| { | |||
| pagination: { | |||
| current: 1, | |||
| pageSize: 5 | |||
| }, | |||
| filter:{...parans.filter,status:selectedKeys[0]} | |||
| } | |||
| )); | |||
| console.log(parans) | |||
| } else if (dataIndex == 'cliente') { | |||
| parans.filter.cliente = selectedKeys[0]; | |||
| dispatch(getAllEncomenda( | |||
| { | |||
| pagination: { | |||
| current: 1, | |||
| pageSize: 5 | |||
| }, | |||
| filter:parans.filter | |||
| } | |||
| )); | |||
| } | |||
| }; | |||
| const handleReset = (clearFilters: () => void) => { | |||
| clearFilters(); | |||
| setSearchText(''); | |||
| setClienteFilter(''); | |||
| setDataCriacaoFilter(''); | |||
| setDataEnvioFilter(''); | |||
| setStatusFilter(''); | |||
| }; | |||
| useEffect(() => { | |||
| dispatch(getAllEncomenda( | |||
| { | |||
| pagination: { | |||
| current: 1, | |||
| pageSize: 5 | |||
| } | |||
| } | |||
| )) | |||
| }, []); | |||
| // **Columns Filter** | |||
| const getColumnSearchProps = (dataIndex: any): ColumnType<any> => ({ | |||
| filterDropdown: ({ setSelectedKeys, selectedKeys, clearFilters, close }) => ( | |||
| <div style={{ padding: 8 }} onKeyDown={(e) => e.stopPropagation()}> | |||
| {dataIndex == 'status' ? ( | |||
| <Select | |||
| options={[ | |||
| { value: '1', label: 'CREATED' }, | |||
| { value: '2', label: 'CANCELED' }, | |||
| { value: '3', label: 'FINISHED' } | |||
| ]} | |||
| style={{ marginBottom: 8, display: 'block' }} | |||
| onChange={(e) => setSelectedKeys(e ? [e] : [])} | |||
| value={selectedKeys[0]} | |||
| /> | |||
| ) : | |||
| ( | |||
| <Input | |||
| ref={searchInput} | |||
| placeholder={`Search ${dataIndex}`} | |||
| type={(dataIndex == 'data_criacao' || dataIndex == 'data_envio') ? 'date' : 'text'} | |||
| value={selectedKeys[0]} | |||
| onChange={(e) => setSelectedKeys(e.target.value ? [e.target.value] : [])} | |||
| onPressEnter={() => handleSearch(selectedKeys as string[], dataIndex)} | |||
| style={{ marginBottom: 8, display: 'block' }} | |||
| /> | |||
| )} | |||
| <Space> | |||
| <Button | |||
| type="primary" | |||
| onClick={() => handleSearch(selectedKeys as string[], dataIndex)} | |||
| icon={<SearchOutlined />} | |||
| size="small" | |||
| style={{ width: 90 }} | |||
| > | |||
| Search | |||
| </Button> | |||
| <Button | |||
| onClick={() => clearFilters && handleReset(clearFilters)} | |||
| size="small" | |||
| style={{ width: 90 }} | |||
| > | |||
| Reset | |||
| </Button> | |||
| <Button | |||
| type="link" | |||
| size="small" | |||
| onClick={() => { | |||
| close(); | |||
| }} | |||
| > | |||
| close | |||
| </Button> | |||
| </Space> | |||
| </div> | |||
| ), | |||
| filterIcon: (filtered: boolean) => ( | |||
| <SearchOutlined style={{ color: filtered ? '#1677ff' : undefined,fontSize:15 }} /> | |||
| ), | |||
| onFilter: (value, record) => | |||
| record[dataIndex] | |||
| .toString() | |||
| .toLowerCase() | |||
| .includes((value as string).toLowerCase()), | |||
| onFilterDropdownOpenChange: (visible) => { | |||
| if (visible) { | |||
| setTimeout(() => searchInput.current?.select(), 100); | |||
| } | |||
| }, | |||
| render: (text) => | |||
| searchedColumn === dataIndex ? ( | |||
| <Highlighter | |||
| highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }} | |||
| searchWords={[searchText]} | |||
| autoEscape | |||
| textToHighlight={text ? text.toString() : ''} | |||
| /> | |||
| ) : ( | |||
| text | |||
| ), | |||
| }); | |||
| // **Columns Filter** | |||
| return ( | |||
| <div className={styles.container_table}> | |||
| <Table | |||
| dataSource={ | |||
| encomendas.map((encomenda: any) => ( | |||
| { | |||
| key: encomenda.uid, | |||
| data_criacao: encomenda.data_criacao, | |||
| data_envio: encomenda.data_envio, | |||
| status: encomenda.status.nome, | |||
| valor: `R$ ${encomenda.valor}` | |||
| } | |||
| )) | |||
| } | |||
| // pagination={{ | |||
| // position: ["bottomCenter"], | |||
| // total: total, | |||
| // defaultPageSize: 5, | |||
| // onChange(page, pageSize) { | |||
| // onChangePage(page, pageSize) | |||
| // }, | |||
| // pageSizeOptions: [5, 10, 15], | |||
| // showSizeChanger: true, | |||
| // onShowSizeChange(current, size) { | |||
| // onChangePage(current, size) | |||
| // }, | |||
| // }} | |||
| loading={loading} | |||
| bordered={true} | |||
| > | |||
| <Column | |||
| title="Data Criação" | |||
| dataIndex="data_criacao" | |||
| key="data_criacao" | |||
| {...getColumnSearchProps('data_criacao')} | |||
| /> | |||
| <Column | |||
| title="Data Envio" | |||
| dataIndex="data_envio" | |||
| key="data_envio" | |||
| {...getColumnSearchProps('data_envio')} | |||
| /> | |||
| <Column | |||
| title="Cliente" | |||
| dataIndex="cliente" | |||
| key="cliente" | |||
| {...getColumnSearchProps('cliente')} | |||
| /> | |||
| <Column | |||
| title="Status" | |||
| dataIndex="status" | |||
| key="status" | |||
| {...getColumnSearchProps('status')} | |||
| /> | |||
| <Column | |||
| title="Valor" | |||
| dataIndex="valor" | |||
| key="valor" | |||
| /> | |||
| <Column | |||
| title="Actions" | |||
| key="action" | |||
| render={(_: any, record: any) => ( | |||
| <Space size="middle"> | |||
| {/* <Popconfirm | |||
| title="Atenção:" | |||
| description="Confirme a ação de delete!" | |||
| // onConfirm={() => { handleDelete(record.key) }} | |||
| okText="Sim" | |||
| cancelText="Não" | |||
| > | |||
| <Button value="small" | |||
| type="primary" | |||
| danger icon={<DeleteOutlined />} | |||
| size="large" | |||
| title="Deletar" | |||
| /> | |||
| </Popconfirm> | |||
| <Button | |||
| value="small" | |||
| type="primary" | |||
| icon={<EditOutlined />} size="large" | |||
| title="Atualizar" | |||
| // onClick={() => { navigate(`/cliente/new`) }} | |||
| /> */} | |||
| </Space> | |||
| )} | |||
| /> | |||
| </Table> | |||
| </div> | |||
| ) | |||
| } | |||
| export default Encomendas; | |||
| @ -1,73 +1,139 @@ | |||
| import { Button, Collapse, Popconfirm, Space, Table } from 'antd'; | |||
| import { Button, Divider, Select, Space, Table } from 'antd'; | |||
| import styles from './encomenda.module.css'; | |||
| import Column from 'antd/es/table/Column'; | |||
| import { useSelector } from 'react-redux'; | |||
| import { useDispatch, useSelector } from 'react-redux'; | |||
| import { ItemCart } from '../../interfaces/ItemCart'; | |||
| import { | |||
| DeleteOutlined | |||
| } from '@ant-design/icons'; | |||
| import { removeItem } from '../../slices/CarrinhoSlice'; | |||
| import { getAllClientes } from '../../slices/ClienteSlice'; | |||
| import { useState } from 'react'; | |||
| import { ParamsType } from '../../interfaces/ParamsType'; | |||
| import { Cliente } from '../../interfaces/Cliente'; | |||
| import { newEncomenda } from '../../slices/EncomendaSlice'; | |||
| import { notify } from '../../hooks/useToastfy'; | |||
| import Search from 'antd/es/input/Search'; | |||
| import { Encomenda } from '../../interfaces/Encomenda'; | |||
| function NewEncomenda() { | |||
| const { itens } = useSelector((state: any) => state.cart); | |||
| const dispatch = useDispatch<any>(); | |||
| const { itens, valorTotal } = useSelector((state: any) => state.cart); | |||
| const { clientes, loading:loadingCliente } = useSelector((state:any) => state.cliente); | |||
| const { loading:loadingEncomenda } = useSelector((state:any) => state.encomenda); | |||
| const handleDelete = () => { | |||
| const [clienteUid, setCliente] = useState(''); | |||
| const handleDelete = (uid: string) => { | |||
| dispatch(removeItem(uid)); | |||
| } | |||
| const searchCliente = (nome:string) => { | |||
| const params: ParamsType = { | |||
| pagination: { | |||
| current: 1, | |||
| pageSize: 5 | |||
| }, | |||
| filter: { | |||
| nome: nome | |||
| } | |||
| } | |||
| dispatch(getAllClientes(params)) | |||
| } | |||
| const handleFinalize = () => { | |||
| if (clienteUid == '' || clienteUid == null) { | |||
| notify('Selecione o cliente!','error') | |||
| return; | |||
| } else if (itens.length == 0) { | |||
| notify('A lista está vazia!','error') | |||
| return; | |||
| } | |||
| const encomenda:Encomenda = { | |||
| itens:itens, | |||
| cliente:clienteUid, | |||
| valor:valorTotal | |||
| } | |||
| dispatch(newEncomenda(encomenda)); | |||
| } | |||
| return ( | |||
| <div className={styles.container_table}> | |||
| <Collapse | |||
| size="large" | |||
| items={[{ | |||
| key: '1', label: 'Itens da encomenda.', children: ( | |||
| <Table | |||
| dataSource={ | |||
| itens.map((item: ItemCart) => ( | |||
| { key: item.produto.uid, name: item.produto.nome, quantidade: item.quantidade, preco: item.produto.preco } | |||
| )) | |||
| } | |||
| pagination={false} | |||
| bordered={true} | |||
| scroll={{ x: 300, y: 300 }} | |||
| > | |||
| <Column title="Nome" dataIndex="name" key="name" /> | |||
| <Column title="Quantidade" dataIndex="quantidade" key="quantidade" /> | |||
| <Column title="Preço" dataIndex="preco" key="preco" /> | |||
| <Column | |||
| title="Actions" | |||
| key="action" | |||
| render={(_: any) => ( | |||
| <Space size="middle"> | |||
| <Popconfirm | |||
| title="Atenção:" | |||
| description="Confirme a ação de delete!" | |||
| onConfirm={() => { handleDelete() }} | |||
| okText="Sim" | |||
| cancelText="Não" | |||
| > | |||
| <Button value="small" | |||
| type="primary" | |||
| danger icon={<DeleteOutlined />} | |||
| size="large" | |||
| title="Deletar" | |||
| /> | |||
| </Popconfirm> | |||
| </Space> | |||
| )} | |||
| <div className={styles.container_encomenda}> | |||
| <Table | |||
| dataSource={ | |||
| itens.map((item: ItemCart) => ( | |||
| { key: item.produto.uid, name: item.produto.nome, quantidade: item.quantidade, preco: item.produto.preco } | |||
| )) | |||
| } | |||
| pagination={false} | |||
| bordered={true} | |||
| scroll={{ x: 300, y: 300 }} | |||
| style={{minHeight:300}} | |||
| > | |||
| <Column title="Nome" dataIndex="name" key="name" /> | |||
| <Column title="Quantidade" dataIndex="quantidade" key="quantidade" /> | |||
| <Column title="Preço" dataIndex="preco" key="preco" /> | |||
| <Column | |||
| title="Actions" | |||
| key="action" | |||
| render={(_: any, record: any) => ( | |||
| <Space size="middle"> | |||
| <Button value="small" | |||
| type="primary" | |||
| danger icon={<DeleteOutlined />} | |||
| size="large" | |||
| title="Deletar" | |||
| onClick={() => { handleDelete(record.key) }} | |||
| /> | |||
| </Space> | |||
| )} | |||
| /> | |||
| </Table> | |||
| <Divider style={{ backgroundColor: '#000' }} /> | |||
| <div className={styles.container_cliente}> | |||
| <Select | |||
| style={{ width: 300 }} | |||
| placeholder="Selecione o cliente" | |||
| optionFilterProp="children" | |||
| onChange={setCliente} | |||
| loading={loadingCliente} | |||
| options={ | |||
| clientes.map((cliente:Cliente) => ( | |||
| {value:cliente.uid, label:cliente.nome} | |||
| )) | |||
| } | |||
| /> | |||
| <Search | |||
| placeholder="Buscar cliente por nome" | |||
| enterButton | |||
| style={{ width: 300 }} | |||
| onSearch={searchCliente} | |||
| loading={loadingCliente} | |||
| /> | |||
| </div> | |||
| </Table> | |||
| <Divider style={{ backgroundColor: '#000' }} /> | |||
| ) | |||
| }]} | |||
| <div className={styles.container_finalize}> | |||
| <div className={styles.container_finalize__total}> | |||
| <span>Total: </span> <span>{`R$ ${valorTotal.toFixed(2)}`}</span> | |||
| </div> | |||
| <Button type="primary" | |||
| onClick={handleFinalize} | |||
| disabled={itens.length == 0} | |||
| loading={loadingEncomenda} | |||
| >Finalizar Encomenda | |||
| </Button> | |||
| </div> | |||
| /> | |||
| </div> | |||
| ) | |||
| } | |||
| @ -1,18 +1,33 @@ | |||
| .container_table { | |||
| .container_encomenda { | |||
| width: 800px; | |||
| height: 100%; | |||
| margin-top: 3em; | |||
| gap: 1em; | |||
| display: flex; | |||
| flex-direction: column; | |||
| } | |||
| .container_table__filter{ | |||
| width: 100%; | |||
| .container_cliente { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: baseline; | |||
| gap: 0.5em; | |||
| } | |||
| .container_finalize{ | |||
| display: flex; | |||
| justify-content: end; | |||
| margin-bottom: 1em; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| width: 100%; | |||
| } | |||
| .container_table__search{ | |||
| width: 300px; | |||
| .container_finalize__total{ | |||
| font-size: 1.3em; | |||
| } | |||
| .container_table { | |||
| width: 800px; | |||
| display: flex; | |||
| flex-direction: column; | |||
| } | |||
| @ -0,0 +1,47 @@ | |||
| import { Environments} from "../environments"; | |||
| import { Encomenda } from "../interfaces/Encomenda"; | |||
| import { ParamsType } from "../interfaces/ParamsType"; | |||
| const { URLApi } = Environments; | |||
| const newEncomenda = async (encomenda:Encomenda) => { | |||
| const config = { | |||
| method:"POST", | |||
| body:JSON.stringify(encomenda), | |||
| headers: { | |||
| "Content-type":"application/json", | |||
| } | |||
| } | |||
| try { | |||
| const data = await fetch(`${URLApi}/encomenda`,config) | |||
| .then((res)=>res.json()) | |||
| .catch((err)=>err); | |||
| return data; | |||
| } catch (error) { | |||
| console.log(error) | |||
| } | |||
| } | |||
| const getAllEncomenda = async (parans:ParamsType) => { | |||
| const config = { | |||
| method:"POST", | |||
| body:JSON.stringify(parans), | |||
| headers: { | |||
| "Content-type":"application/json", | |||
| } | |||
| } | |||
| const data = await fetch(`${URLApi}/encomenda/list`,config) | |||
| .then((res)=>res.json()) | |||
| .catch((err)=>err); | |||
| return data; | |||
| } | |||
| export const encomendaService = { | |||
| newEncomenda, | |||
| getAllEncomenda | |||
| } | |||
| @ -0,0 +1,72 @@ | |||
| import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; | |||
| import { notify } from "../hooks/useToastfy"; | |||
| import { Encomenda } from "../interfaces/Encomenda"; | |||
| import { encomendaService } from "../services/EncomendaService"; | |||
| import { ParamsType } from "../interfaces/ParamsType"; | |||
| const initialState = { | |||
| encomendas:[] as any, | |||
| loading:false, | |||
| error:false, | |||
| message:'' | |||
| } | |||
| export const newEncomenda = createAsyncThunk( | |||
| "encomenda/new", | |||
| async (encomenda:Encomenda, ThunkApi) => { | |||
| const data = await encomendaService.newEncomenda(encomenda); | |||
| if (data.error) { | |||
| return ThunkApi.rejectWithValue(data); | |||
| } | |||
| return data; | |||
| } | |||
| ) | |||
| export const getAllEncomenda = createAsyncThunk( | |||
| "encomenda/getAll", | |||
| async (parans:ParamsType) => { | |||
| const data = await encomendaService.getAllEncomenda(parans); | |||
| return data; | |||
| } | |||
| ) | |||
| export const encomendaSlice = createSlice({ | |||
| name:"cliente", | |||
| initialState, | |||
| reducers:{ | |||
| resetState:(state)=>{ | |||
| state.loading = false, | |||
| state.error = false; | |||
| state.message = '' | |||
| }, | |||
| }, | |||
| extraReducers(builder) { | |||
| builder | |||
| .addCase(newEncomenda.pending,(state)=>{ | |||
| state.loading = true; | |||
| }).addCase(newEncomenda.fulfilled,(state)=>{ | |||
| state.loading = false; | |||
| state.error = false; | |||
| notify('Encomenda feita com sucesso!','success') | |||
| }).addCase(newEncomenda.rejected,(state,action:any)=>{ | |||
| state.loading = false, | |||
| state.error = true; | |||
| state.message = action.payload.messege ? action.payload.messege : ''; | |||
| notify(state.message,'error'); | |||
| }) | |||
| .addCase(getAllEncomenda.pending,(state)=>{ | |||
| state.loading = true; | |||
| }).addCase(getAllEncomenda.fulfilled,(state, action:any)=>{ | |||
| state.loading = false; | |||
| state.error = false; | |||
| state.encomendas = action.payload.results; | |||
| }) | |||
| }, | |||
| }); | |||
| export const { resetState } = encomendaSlice.actions; | |||
| export default encomendaSlice.reducer; | |||