RenanBorba / react-web-pipecardfy

🗒️ Aplicação Web em ReactJS para clone do Pipefy

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Projeto - Aplicação Pipecardfy Web ReactJS


Generic badge Build Status Build Status made-for-VSCode Open Source Love svg2


pipe


Aplicação Front-end desenvolvida em ReactJS para clone do app Pipefy web, que é voltado para organização de tarefas, permitindo interação de arraste (drag n'drop) entre os cards nas listas de tarefas.



pipe



🚀 Tecnologias

  • Components
  • Server API fake
  • react-dnd
  • useDrag
  • react-dnd-html5-backend
  • DndProvider
  • useDrop
  • useRef
  • createContext
  • useContext
  • useState
  • Immer
  • react-icons
  • styled-components
  • Multiple CSS properties



▶️ Start

  • npm install
  • npm run start / npm start



👊 Como contribuir

  • Dê um fork nesse repositório
  • Crie a sua branch com a feature
    • git checkout -b my-feature
  • Commit a sua contribuição
    • git commit -m 'feat: My feature'
  • Push a sua branch
    • git push origin my-feature



📣 ⬇ Abaixo, as principais estruturas e interface principal:




src/App.js

import React from 'react';
import { DndProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import GlobalStyle from './styles/global';
import Header from './components/Header';
import Board from './components/Board';

function App() {
  return (
    // API dnd do html5
    <DndProvider backend={ HTML5Backend }>
      <Header />
      <Board />

      <GlobalStyle />
    </DndProvider>
  )
};

export default App;



src/components/Board/index.js

import React, { useState } from 'react';
import produce from 'immer';

import { loadLists } from '../../services/api';
import BoardContext from './context';
import List from '../List';
import { Container } from './styles';

const data = loadLists();

export default function Board() {
  const [lists, setLists] = useState(data);

  function move(fromList, toList, from, to) {
    setLists(produce(lists, draft => {
      const dragged = draft[fromList].cards[from];

      draft[fromList].cards.splice(from, 1);
      draft[toList].cards.splice(to, 0, dragged);
    }));
  }

  return (
    <BoardContext.Provider value={{ lists, move }}>
      <Container>
        { lists.map((list, index) =>
          <List key={ list.title }
            index={ index }
            data={ list } />)
        }
      </Container>
    </BoardContext.Provider>
  );
};



src/components/List/index.js

import React from 'react';

import { MdAdd } from 'react-icons/md';
import { Container } from './styles';
import Card from '../Card';

export default function List({ data, index: listIndex }) {
  return (
    <Container done={ data.done }>
      <header>
        <h2>{ data.title }</h2>
          { data.creatable && (
            <button type='button'>
              <MdAdd size={24} color="#FFF" />
            </button>
          )}
      </header>

      <ul>
        { data.cards.map((card, index) => (
          <Card key={ card.id }
            listIndex={ listIndex }
            index={ index }
            data={ card }
          />
        ))}
      </ul>
    </Container>
  );
};



src/components/Card/index.js

import React, { useRef, useContext } from 'react';
import { useDrag, useDrop } from 'react-dnd';

import BoardContext from '../Board/context';
import { Container, Label } from './styles';

export default function Card({ data, index, listIndex }) {
  const ref = useRef();
  const { move } = useContext(BoardContext);

  // Drag
  const [{ isDragging }, dragRef] = useDrag({
    item: { type: 'CARD', index, listIndex },
    collect: monitor => ({
      isDragging: monitor.isDragging()
    })
  })

// Drop
const [, dropRef] = useDrop({
  accept: 'CARD',
    hover(item, monitor) {
    const draggedListIndex = item.listIndex;
    const targetListIndex = listIndex;
    // item selecionado
    const draggedIndex = item.index;
    // alvo destino
    const targetIndex = index;

    // Não modificar na mesma posição do card e lista
    if(draggedIndex === targetIndex && draggedListIndex === targetListIndex) {
      return;
    }

    // tamanho elemento
    const targetSize = ref.current.getBoundingClientRect();
    // calc ponto central
    const targetCenter = (targetSize.bottom - targetSize.top) / 2;
    // distância dos pontos (quanto do item foi arrastado encima)
    const draggedOffset = monitor.getClientOffset();
    // calc ((topo dos pontos) - (topo elemento))
    const draggedTop = draggedOffset.y - targetSize.top;

    // Não modificar posição de um item que já anteceda ao outro
    if (draggedIndex < targetIndex && draggedTop < targetCenter) {
      return;
    }
    // Não modificar posição de um item que já preceda ao outro
    if (draggedIndex > targetIndex && draggedTop > targetCenter) {
      return;
    }

      move(draggedListIndex, targetListIndex, draggedIndex, targetIndex);

      item.index = targetIndex;
      item.listIndex = targetListIndex;
    }
  })

  dragRef(dropRef(ref));

  return (
    <Container ref={ ref } isDragging={ isDragging }>
      <header>
        { data.labels.map(label =>  <Label key={ label } color={ label } />) }
      </header>
      <p>{ data.content }</p>
      { data.user && <img src={ data.user } alt='avatar' /> }
    </Container>
  );
};



Interface principal

3



3 5



5

About

🗒️ Aplicação Web em ReactJS para clone do Pipefy


Languages

Language:JavaScript 95.9%Language:HTML 4.1%