webmoney/APRENDIZADOS_TECNICOS.md

7.6 KiB

APRENDIZADOS TÉCNICOS - WEBMONEY

Este documento registra problemas encontrados e suas soluções para referência futura.


📋 Índice

  1. Bootstrap 5 + React: Componentes JS não funcionam
  2. Deploy: Arquivos no diretório errado

1. Bootstrap 5 + React: Componentes JS não funcionam

Data: 8 de Dezembro de 2025
Versões afetadas: v1.3.8 - v1.3.11
Componentes afetados: Dropdown, Modal

Problema

Componentes do Bootstrap 5 que dependem de JavaScript (Dropdown, Modal, Tooltip, Popover, etc.) não funcionam corretamente em aplicações React, mesmo importando o Bootstrap JS.

Sintomas:

  • Dropdown não abre ao clicar
  • Modal não aparece
  • data-bs-toggle="dropdown" não faz nada
  • window.bootstrap.Modal não inicializa corretamente

🔍 Causa Raiz

O Bootstrap 5 JavaScript foi projetado para manipular o DOM diretamente, o que conflita com o Virtual DOM do React:

  1. Ciclo de vida: Bootstrap inicializa componentes no DOMContentLoaded, mas React renderiza depois
  2. Re-renders: Quando React re-renderiza, os listeners do Bootstrap são perdidos
  3. Referências: new bootstrap.Modal(element) pode referenciar elementos que React já substituiu

Solução

Implementar os componentes usando 100% React puro, sem depender da API JavaScript do Bootstrap.

Dropdown Controlado (React)

// ❌ ERRADO - Não funciona
<div className="dropdown">
  <button data-bs-toggle="dropdown">Menu</button>
  <ul className="dropdown-menu">...</ul>
</div>

// ✅ CORRETO - React controlado
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef(null);

// Fechar ao clicar fora
useEffect(() => {
  const handleClickOutside = (e) => {
    if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
      setIsOpen(false);
    }
  };
  document.addEventListener('mousedown', handleClickOutside);
  return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);

<div className="dropdown" ref={dropdownRef} style={{ position: 'relative' }}>
  <button onClick={() => setIsOpen(!isOpen)}>Menu</button>
  <ul 
    className={`dropdown-menu ${isOpen ? 'show' : ''}`}
    style={{ 
      position: 'absolute', 
      right: 0, 
      top: '100%', 
      zIndex: 1000 
    }}
  >
    ...
  </ul>
</div>

Modal Controlado (React)

// ❌ ERRADO - Depende de window.bootstrap
useEffect(() => {
  if (window.bootstrap) {
    const modal = new window.bootstrap.Modal(modalRef.current);
    // Não funciona consistentemente
  }
}, []);

// ✅ CORRETO - React puro
const Modal = ({ show, onHide, title, children, footer }) => {
  // Fechar com ESC
  useEffect(() => {
    const handleKeyDown = (e) => {
      if (e.key === 'Escape' && show) onHide();
    };
    if (show) {
      document.addEventListener('keydown', handleKeyDown);
      document.body.style.overflow = 'hidden'; // Bloqueia scroll
    }
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      document.body.style.overflow = '';
    };
  }, [show, onHide]);

  if (!show) return null;

  return (
    <>
      <div className="modal-backdrop show" style={{ backgroundColor: 'rgba(0,0,0,0.7)' }} />
      <div className="modal show d-block" onClick={(e) => e.target === e.currentTarget && onHide()}>
        <div className="modal-dialog modal-dialog-centered">
          <div className="modal-content">
            <div className="modal-header">
              <h5>{title}</h5>
              <button className="btn-close" onClick={onHide} />
            </div>
            <div className="modal-body">{children}</div>
            {footer && <div className="modal-footer">{footer}</div>}
          </div>
        </div>
      </div>
    </>
  );
};

📝 Regra para o Futuro

NUNCA usar data-bs-toggle, data-bs-dismiss ou window.bootstrap em React.

Sempre implementar componentes interativos com useState, useRef e useEffect.

🔗 Alternativas

Se precisar de muitos componentes Bootstrap interativos, considere usar:

Estas bibliotecas reimplementam os componentes Bootstrap em React puro.


2. Deploy: Arquivos no diretório errado

Data: 8 de Dezembro de 2025
Versão afetada: v1.3.10

Problema

Após fazer deploy do frontend, o site retornava 404 ou 403 Forbidden.

Sintomas:

  • curl https://webmoney.cnxifly.com/ retorna 404/403
  • Arquivos existem no servidor mas não são servidos
  • JS/CSS não carregam

🔍 Causa Raiz

Os arquivos foram copiados para o diretório errado:

# Onde os arquivos foram copiados:
/var/www/webmoney/frontend/assets/

# Onde o Nginx esperava encontrar:
/var/www/webmoney/frontend/dist/assets/

O Nginx estava configurado com:

root /var/www/webmoney/frontend/dist;

Solução

  1. Verificar configuração do Nginx:
cat /etc/nginx/sites-available/webmoney-subdomain
# Procurar por: root /var/www/webmoney/frontend/dist;
  1. Deploy para o caminho correto:
# Build do frontend
cd frontend && npm run build

# Deploy para o caminho CORRETO (inclui /dist/)
scp -r dist/* root@213.165.93.60:/var/www/webmoney/frontend/dist/
  1. Ajustar permissões:
chown -R www-data:www-data /var/www/webmoney/frontend/dist

📝 Regra para o Futuro

Sempre verificar o root do Nginx antes de fazer deploy.

O caminho de deploy deve corresponder EXATAMENTE ao configurado no Nginx.

Comando de Deploy Correto

# Frontend - Build e Deploy
cd /workspaces/webmoney/frontend
npm run build
sshpass -p 'Master9354' scp -r dist/* root@213.165.93.60:/var/www/webmoney/frontend/dist/

# Backend - Deploy
sshpass -p 'Master9354' rsync -avz --exclude 'vendor' --exclude '.git' \
  /workspaces/webmoney/backend/ root@213.165.93.60:/var/www/webmoney/backend/

# Pós-deploy no servidor
ssh root@213.165.93.60 "
  cd /var/www/webmoney/backend
  COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --optimize-autoloader
  cp .env.production .env
  php artisan config:cache
  php artisan route:cache
  chown -R www-data:www-data /var/www/webmoney
  systemctl restart php8.4-fpm
"

📊 Resumo de Problemas Frequentes

Problema Sintoma Solução Rápida
Dropdown não abre Clique não faz nada Usar useState + onClick
Modal não aparece window.bootstrap undefined Implementar modal React puro
404 no frontend Site não carrega Verificar root do Nginx
403 Forbidden Permissão negada chown -R www-data:www-data
API retorna 404 Endpoint não encontrado Verificar se routes/api.php foi copiado
Cache desatualizado Mudanças não aparecem php artisan config:clear + hard refresh

🔧 Checklist de Debug

Quando algo não funciona:

  1. Frontend não carrega:

    • Verificar se npm run build foi executado
    • Verificar se arquivos estão em /frontend/dist/
    • Verificar root do Nginx
    • Fazer hard refresh (Ctrl+Shift+R)
  2. Componente React não funciona:

    • Verificar se não está usando data-bs-*
    • Verificar console do browser para erros
    • Implementar com useState/useEffect
  3. API retorna erro:

    • Verificar se routes/api.php existe no servidor
    • Verificar se .env está configurado
    • Executar php artisan config:cache
    • Verificar logs: tail -f /var/log/nginx/webmoney_*.log

Documento atualizado em: 8 de Dezembro de 2025 - v1.3.11