Document Management - Copy this React, Tailwind Component to your project
Eu quero que esse codigo aqui em cima tenha um campo de pesquisa funcional e que tenha filtros de aréa tipo: Processo penal, Processo Civil e que a funcionalidade de arrastar um cliente para outro container funcione e que sempre dê para adicionar quandos clientes quiser em um container: import React, { useState, useCallback } from "react"; import { FiSearch, FiX, FiPlus, FiMoreVertical, FiEye, FiEdit, FiTrash2, FiCheck, FiLayout } from "react icons/fi"; import { DragDropContext, Droppable, Draggable } from "react beautiful dnd"; const CRM = () => { const initialSections = { "negociacao": { "Análise do Caso": [], "Aguardando Documentos": [], "Apresentação de Proposta": [], "Agendar Consulta": [], "Cobrança Inicial": [], "Definição de Interesses": [], "Elaboração de Parecer Jurídico": [], "Fechamento": [], "Planejamento": [] }, "consultoria": { "Elaboração de contrato": [], "Elaboração de Parecer": [], "Enviada Notificação Extrajudicial": [], "Elaboração de Termo de Acordo": [], "Agendada a Reunião de Composição de Acordo": [] }, "administrativo": { "AGENDADO ATENDIMENTO NO ÓRGÃO": [], "REQUERIMENTO PROTOCOLADO": [], "ATENDENDO EXIGÊNCIAS": [], "AGUARDANDO DECISÃO DO ÓRGÃO": [], "DECISÃO PROFERIDA": [], "RECURSO ADMINISTRATIVO PROTOCOLADO": [], "AGUARDANDO DECISÃO DO RECURSO": [], "DECISÃO DO RECURSO PROFERIDA": [], "AGUARDANDO CÓPIA DO PROCESSO ADMINISTRATIVO": [], "DESENVOLVENDO INICIAL DE AÇÃO JUDICIAL": [] }, "judicial": { "AÇÃO PROTOCOLADA/INICIADA": [], "COM JUIZ(A) PARA ANÁLISE": [], "AGUARDANDO MANIFESTAÇÃO DA PARTE CONTRÁRIA": [], "AGUARDANDO AUDIÊNCIA": [], "AGUARDANDO JULGAMENTO": [], "SENTENÇA PROFERIDA": [], "TRANSITO EM JULGADO/PROCESSO FINALIZADO": [], "DESENVOLVENDO RECURSO": [] }, "Recursal": { "RECURSO PROTOCOLADO/INICIADO": [], "APRESENTADA A RESPOSTA A RECURSO DA PARTE CONTRÁRIA (CONTRARRAZÕES)": [], "AGUARDANDO MANIFESTAÇÃO DA PARTE CONTRÁRIA": [], " AGUARDANDO JULGAMENTO DO RECURSO": [], "RECURSO JULGADO": [], "TRANSITO EM JULGADO/NÃO CABE MAIS RECURSO": [], "DESENVOLVENDO RECURSO AOS TRIBUNAIS SUPERIORES": [] }, "Execução": { "ELABORAÇÃO DE CÁLCULO": [], "CITAÇÃO DO DEVEDOR PARA PAGAMENTO": [], "AGUARDANDO PENHORA": [], " AGUARDANDO JULGAMENTO DA EXECUÇÃO": [], " EXECUÇÃO JULGADA": [], "APRESENTADO RECURSO": [], "RESPOSTA A RECURSO": [], "AGUARDANDO SENTENÇA DE LIQUIDAÇÃO": [], "AGUARDANDO DECISÃO DO TRIBUNAL": [], "RPV EMITIDO e AGUARDANDO PAGAMENTO DE CONDENAÇÃO": [], }, "Financeiro": { "PROCESSO RH PENDENTE": [], }, "Arquivamento": { "ANALISADO E NÃO DISTRIBUIDO": [], "CITAÇÃO DO DEVEDOR PARA PAGAMENTO": [], "ARQUIVADO POR INTERESSE DO CLIENTE": [], "ARQUIVADO POR DETERMINAÇÃO JUDICIAL": [], "ARQUIVADO/ENCERRADO": [], }, }; const [sections, setSections] = useState(initialSections); const [newClient, setNewClient] = useState(""); const [selectedContainer, setSelectedContainer] = useState(null); const [activeSection, setActiveSection] = useState("negociacao"); const handleDragEnd = useCallback((result) => { if (!result.destination) return; const { source, destination } = result; const [sourceSection, sourceContainer] = source.droppableId.split(" "); const [destSection, destContainer] = destination.droppableId.split(" "); const newSections = { ...sections }; const sourceClients = [...sections[sourceSection][sourceContainer]]; const destClients = sourceContainer === destContainer ? sourceClients : [...sections[destSection][destContainer]]; const [removed] = sourceClients.splice(source.index, 1); destClients.splice(destination.index, 0, removed); if (sourceContainer === destContainer) { newSections[sourceSection][sourceContainer] = destClients; } else { newSections[sourceSection][sourceContainer] = sourceClients; newSections[destSection][destContainer] = destClients; } setSections(newSections); }, [sections]); const addClient = (sectionId, containerId) => { if (newClient.trim() === "") return; const newSections = { ...sections }; newSections[sectionId][containerId] = [...newSections[sectionId][containerId], newClient.trim()]; setSections(newSections); setNewClient(""); setSelectedContainer(null); }; const removeClient = (sectionId, containerId, index) => { const newSections = { ...sections }; newSections[sectionId][containerId].splice(index, 1); setSections(newSections); }; const sectionTitles = { negociacao: "Negociação", consultoria: "Consultoria", administrativo: "Administrativo", judicial: "Judicial", Recursal: "Recursal", Execução: "Execução", Financeiro: "Financeiro", Arquivamento: "Arquivamento", }; return ( <div className="min h screen bg gray 100"> <div className="bg white shadow md"> <div className="container mx auto px 6"> <div className="flex overflow x auto"> {Object.keys(sections).map((sectionId) => ( <button key={sectionId} onClick={() => setActiveSection(sectionId)} className={`px 6 py 4 text sm font medium whitespace nowrap border b 2 ${activeSection === sectionId ? "border blue 500 text blue 500" : "border transparent text gray 500 hover:text gray 700 hover:border gray 300"}`} > {sectionTitles[sectionId]} </button> ))} </div> </div> </div> <div className="container mx auto px 6 py 8 overflow x auto"> <DragDropContext onDragEnd={handleDragEnd}> <div className="flex gap 6" style={{ minWidth: "max content" }}> {Object.entries(sections[activeSection]).map(([containerId, clients]) => ( <div key={containerId} className="bg white rounded lg shadow lg p 4" style={{ minWidth: "300px" }}> <div className="flex justify between items center mb 4"> <h3 className="text lg font semibold text gray 800">{containerId}</h3> <button onClick={() => setSelectedContainer(`${activeSection} ${containerId}`)} className="p 1 hover:bg gray 100 rounded full" > <FiPlus className="text gray 600" /> </button> </div> {selectedContainer === `${activeSection} ${containerId}` && ( <div className="mb 4 flex gap 2"> <input type="text" value={newClient} onChange={(e) => setNewClient(e.target.value)} className="flex 1 border rounded p 2 text sm" placeholder="Nome do cliente" /> <button onClick={() => addClient(activeSection, containerId)} className="bg blue 500 text white px 3 py 2 rounded hover:bg blue 600" > <FiCheck /> </button> </div> )} <Droppable droppableId={`${activeSection} ${containerId}`}> {(provided) => ( <div {...provided.droppableProps} ref={provided.innerRef} className="space y 2" > {clients.map((client, index) => ( <Draggable key={`${containerId} ${index}`} draggableId={`${containerId} ${index}`} index={index} > {(provided) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} className="bg gray 50 p 3 rounded border border gray 200 group hover:shadow sm transition shadow" > <div className="flex justify between items center"> <span className="text sm text gray 700">{client}</span> <button onClick={() => removeClient(activeSection, containerId, index)} className="opacity 0 group hover:opacity 100 text red 500 hover:text red 700 transition opacity" > <FiTrash2 size={14} /> </button> </div> </div> )} </Draggable> ))} {provided.placeholder} </div> )} </Droppable> </div> ))} </div> </DragDropContext> </div> </div> ); }; export default CRM;