From 47ae36e3530f8ce1d9c56c81709efbb1f1573334 Mon Sep 17 00:00:00 2001 From: Mariana Lins Date: Sun, 23 Nov 2025 20:17:27 -0300 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20implementa=C3=A7=C3=A3o=20tema=20?= =?UTF-8?q?escuro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.css | 3 +- src/main.jsx | 1 + src/scripts/darkModeToggle.js | 146 ++++++++++++++++++++++++++ src/styles/dark-mode.css | 186 ++++++++++++++++++++++++++++++++++ 4 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 src/scripts/darkModeToggle.js create mode 100644 src/styles/dark-mode.css diff --git a/src/index.css b/src/index.css index e340f75..d3c4dce 100644 --- a/src/index.css +++ b/src/index.css @@ -2,4 +2,5 @@ @import './styles/global.css'; @import './styles/reset.css'; @import './styles/typography.css'; -@import './styles/tableCommons.css' \ No newline at end of file +@import './styles/tableCommons.css'; +@import './styles/dark-mode.css'; \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx index 16ac828..eb536fb 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -6,6 +6,7 @@ import 'bootstrap/dist/css/bootstrap.min.css'; import 'bootstrap/dist/js/bootstrap.bundle.min.js'; import 'bootstrap-icons/font/bootstrap-icons.css'; import App from './App.jsx' +import './scripts/darkModeToggle.js' createRoot(document.getElementById('root')).render( diff --git a/src/scripts/darkModeToggle.js b/src/scripts/darkModeToggle.js new file mode 100644 index 0000000..d525609 --- /dev/null +++ b/src/scripts/darkModeToggle.js @@ -0,0 +1,146 @@ +/** + * Dark Mode Toggle - Sistema Independente + * + * Script vanilla JavaScript que: + * - Cria um botão no navbar com ícone Bootstrap Icons + * - Gerencia o estado do tema (light/dark) + * - Persiste a escolha no localStorage + * - Detecta preferência do sistema + * - Não interfere com código React existente + */ + +(function() { + 'use strict'; + + // Chave para localStorage + const STORAGE_KEY = 'theme-preference'; + + // Função para obter o tema inicial + function getInitialTheme() { + // Primeiro, verifica localStorage + const saved = localStorage.getItem(STORAGE_KEY); + if (saved) { + return saved; + } + + // Depois, verifica preferência do sistema + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + return 'dark'; + } + + // Padrão: light + return 'light'; + } + + // Função para aplicar o tema + function applyTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + localStorage.setItem(STORAGE_KEY, theme); + updateToggleButton(theme); + } + + // Função para alternar tema + function toggleTheme() { + const current = document.documentElement.getAttribute('data-theme') || 'light'; + const next = current === 'light' ? 'dark' : 'light'; + applyTheme(next); + } + + // Função para criar o botão de toggle + function createToggleButton() { + // Verifica se já existe + if (document.getElementById('dark-mode-toggle')) { + return; + } + + // Encontra o navbar + const navbar = document.querySelector('.navbar-nav:last-child'); + if (!navbar) { + console.warn('Navbar não encontrado, botão não foi criado'); + return; + } + + // Cria o item de lista + const li = document.createElement('li'); + li.className = 'nav-item'; + + // Cria o botão + const button = document.createElement('button'); + button.id = 'dark-mode-toggle'; + button.setAttribute('aria-label', 'Alternar modo escuro'); + button.innerHTML = ''; + + // Event listener + button.addEventListener('click', toggleTheme); + + // Adiciona ao navbar + li.appendChild(button); + navbar.appendChild(li); + } + + // Função para atualizar o ícone do botão + function updateToggleButton(theme) { + const button = document.getElementById('dark-mode-toggle'); + if (button) { + const icon = theme === 'light' + ? '' + : ''; + const title = theme === 'light' ? 'Ativar modo escuro' : 'Ativar modo claro'; + button.innerHTML = icon; + button.setAttribute('title', title); + } + } + + // Listener para mudanças na preferência do sistema + function watchSystemTheme() { + if (window.matchMedia) { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + mediaQuery.addEventListener('change', (e) => { + // Só aplica se não houver preferência salva + if (!localStorage.getItem(STORAGE_KEY)) { + applyTheme(e.matches ? 'dark' : 'light'); + } + }); + } + } + + // Inicialização + function init() { + // Aplica tema inicial imediatamente (antes do DOM carregar) + const initialTheme = getInitialTheme(); + document.documentElement.setAttribute('data-theme', initialTheme); + + // Função para tentar criar o botão (com retry) + function tryCreateButton(attempts = 0) { + const navbar = document.querySelector('.navbar-nav:last-child'); + if (navbar) { + createToggleButton(); + updateToggleButton(initialTheme); + } else if (attempts < 20) { + // Tenta novamente após 100ms + setTimeout(() => tryCreateButton(attempts + 1), 100); + } + } + + // Quando o DOM estiver pronto, tenta criar o botão + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + tryCreateButton(); + watchSystemTheme(); + }); + } else { + tryCreateButton(); + watchSystemTheme(); + } + } + + // Executa inicialização + init(); + + // Expõe funções globalmente (opcional, para debug) + window.darkMode = { + toggle: toggleTheme, + set: applyTheme, + get: () => document.documentElement.getAttribute('data-theme') + }; +})(); diff --git a/src/styles/dark-mode.css b/src/styles/dark-mode.css new file mode 100644 index 0000000..dd3d4f4 --- /dev/null +++ b/src/styles/dark-mode.css @@ -0,0 +1,186 @@ +/* + * Dark Mode - Implementação Independente + * Não modifica os estilos existentes. Apenas adiciona regras quando [data-theme="dark"] está ativo. + * Usa apenas as cores da paleta oficial do sistema. + */ + +/* Variáveis auxiliares (não utilizadas atualmente, podem ser removidas) */ +[data-theme="dark"] { + --bg-main: var(--base-black); + --bg-card: var(--black-700); + --bg-hover: var(--black-500); + --txt-primary: var(--base-white); + --txt-secondary: var(--white-500); + --txt-tertiary: var(--white-700); +} + +/* Background principal */ +[data-theme="dark"] body, +[data-theme="dark"] div#root { + background-color: var(--base-black) !important; + color: var(--base-white) !important; +} + +/* Navbar */ +[data-theme="dark"] nav.navbar { + background-color: var(--black-700) !important; + color: var(--base-white) !important; +} + +[data-theme="dark"] .nav-link { + color: var(--white-500) !important; +} + +[data-theme="dark"] .nav-link:hover { + color: var(--base-white) !important; +} + +[data-theme="dark"] .navbar-toggler-icon { + filter: invert(1); +} + +/* Footer */ +[data-theme="dark"] footer#footer { + background-color: var(--base-navy) !important; +} + +/* Tabelas */ +[data-theme="dark"] table.table > thead * { + background-color: var(--black-700) !important; + color: var(--white-500) !important; +} + +[data-theme="dark"] table.table > tbody tr, +[data-theme="dark"] table.table > tbody tr th, +[data-theme="dark"] table.table > tbody tr td { + background-color: var(--base-black) !important; + color: var(--white-700) !important; +} + +[data-theme="dark"] table.table > tbody tr:hover th, +[data-theme="dark"] table.table > tbody tr:hover td { + background-color: var(--black-700) !important; +} + +/* Inputs e Formulários */ +[data-theme="dark"] input, +[data-theme="dark"] textarea, +[data-theme="dark"] select { + background-color: var(--black-700) !important; + color: var(--base-white) !important; + border-color: var(--black-500) !important; +} + +[data-theme="dark"] input::placeholder, +[data-theme="dark"] textarea::placeholder { + color: var(--white-700) !important; +} + +/* Labels */ +[data-theme="dark"] label { + color: var(--base-white) !important; +} + +/* Cards e Containers */ +[data-theme="dark"] .card, +[data-theme="dark"] [class*="container"] > div { + background-color: var(--black-700) !important; + color: var(--base-white) !important; +} + +/* Títulos */ +[data-theme="dark"] h1, +[data-theme="dark"] h2, +[data-theme="dark"] h3, +[data-theme="dark"] h4, +[data-theme="dark"] h5, +[data-theme="dark"] h6 { + color: var(--base-white) !important; +} + +/* Parágrafos */ +[data-theme="dark"] p { + color: var(--white-500) !important; +} + +/* Links */ +[data-theme="dark"] a { + color: var(--royal-300) !important; +} + +[data-theme="dark"] a:hover { + color: var(--royal-500) !important; +} + +/* Dropzone (DragDrop) */ +[data-theme="dark"] [class*="dropzone"], +[data-theme="dark"] [class*="drop-zone"] { + background-color: var(--black-700) !important; + color: var(--base-white) !important; +} + +/* Step Map */ +[data-theme="dark"] [class*="step-map-circle"] { + background-color: var(--black-700) !important; + color: var(--base-white) !important; +} + +[data-theme="dark"] [class*="step-map-count"], +[data-theme="dark"] [class*="step-map-label"] { + color: var(--base-white) !important; +} + +/* Dropdown Options */ +[data-theme="dark"] [class*="option"] { + background-color: var(--black-700) !important; + color: var(--base-white) !important; +} + +[data-theme="dark"] [class*="option"]:hover { + background-color: var(--black-500) !important; +} + +/* Modals e Overlays */ +[data-theme="dark"] .modal-content { + background-color: var(--black-700) !important; + color: var(--base-white) !important; +} + +/* Borders gerais */ +[data-theme="dark"] [class*="border"], +[data-theme="dark"] .border { + border-color: var(--black-500) !important; +} + +/* Botão de Toggle - Minimalista com Bootstrap Icons */ +#dark-mode-toggle { + background: transparent; + border: none; + cursor: pointer; + font-size: 1.1rem; + padding: 8px 10px; + margin-left: 0.5rem; + display: inline-flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + color: var(--base-navy) !important; +} + +#dark-mode-toggle:hover { + color: var(--royal-700) !important; + transform: scale(1.15); +} + +[data-theme="dark"] #dark-mode-toggle { + color: var(--base-white) !important; +} + +[data-theme="dark"] #dark-mode-toggle:hover { + color: var(--white-300) !important; +} + +/* Transições suaves */ +[data-theme="dark"] * { + transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; +} From c60b031b9d25162fa4872b262b73026196472795 Mon Sep 17 00:00:00 2001 From: Mariana Lins Date: Sun, 23 Nov 2025 20:33:33 -0300 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20corre=C3=A7=C3=A3o=20dark=20mode?= =?UTF-8?q?=20styles=20para=20navbar,=20cards,=20e=20buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/dark-mode.css | 97 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/src/styles/dark-mode.css b/src/styles/dark-mode.css index dd3d4f4..7ccba1c 100644 --- a/src/styles/dark-mode.css +++ b/src/styles/dark-mode.css @@ -27,6 +27,11 @@ color: var(--base-white) !important; } +[data-theme="dark"] nav.navbar img, +[data-theme="dark"] .navbar-brand img { + filter: brightness(0) invert(1); +} + [data-theme="dark"] .nav-link { color: var(--white-500) !important; } @@ -83,8 +88,65 @@ /* Cards e Containers */ [data-theme="dark"] .card, -[data-theme="dark"] [class*="container"] > div { +[data-theme="dark"] div[class*="card"] { background-color: var(--black-700) !important; + border-color: var(--black-500) !important; +} + +[data-theme="dark"] .card:hover, +[data-theme="dark"] div[class*="card"]:hover { + background-color: var(--black-700) !important; + border-color: var(--royal-500) !important; + box-shadow: 0 4px 12px rgba(35, 111, 189, 0.3) !important; +} + +[data-theme="dark"] .card-body, +[data-theme="dark"] div[class*="card-content"] { + background-color: transparent !important; +} + +[data-theme="dark"] .card-title, +[data-theme="dark"] .card h1, +[data-theme="dark"] .card h2, +[data-theme="dark"] .card h3, +[data-theme="dark"] .card h4, +[data-theme="dark"] .card h5, +[data-theme="dark"] .card h6, +[data-theme="dark"] div[class*="card"] h1, +[data-theme="dark"] div[class*="card"] h2, +[data-theme="dark"] div[class*="card"] h3 { + color: var(--base-white) !important; +} + +[data-theme="dark"] .card-text, +[data-theme="dark"] .card p, +[data-theme="dark"] div[class*="card"] p { + color: var(--white-500) !important; +} + +/* Ícone dentro dos cards */ +[data-theme="dark"] .card-icon, +[data-theme="dark"] div[class*="card-icon"] { + background-color: var(--black-500) !important; +} + +[data-theme="dark"] .card:hover .card-icon, +[data-theme="dark"] div[class*="card"]:hover div[class*="card-icon"] { + background-color: var(--black-500) !important; +} + +[data-theme="dark"] .card svg, +[data-theme="dark"] .card i, +[data-theme="dark"] div[class*="card"] svg, +[data-theme="dark"] div[class*="card"] i { + filter: brightness(1) !important; +} + +[data-theme="dark"] .container, +[data-theme="dark"] .container-sm, +[data-theme="dark"] .container-fluid, +[data-theme="dark"] [class*="container"] > div { + background-color: transparent !important; color: var(--base-white) !important; } @@ -130,6 +192,14 @@ color: var(--base-white) !important; } +[data-theme="dark"] [class*="step-map-load"], +[data-theme="dark"] [class*="loading"], +[data-theme="dark"] .fa-spinner, +[data-theme="dark"] .fa-circle-notch, +[data-theme="dark"] .fa-arrow-rotate-right { + color: var(--base-white) !important; +} + /* Dropdown Options */ [data-theme="dark"] [class*="option"] { background-color: var(--black-700) !important; @@ -180,6 +250,31 @@ color: var(--white-300) !important; } +/* Homepage - Elementos destacados (Descriptum e PDF) */ +[data-theme="dark"] b { + background: var(--black-500) !important; + color: var(--base-white) !important; +} + +[data-theme="dark"] abbr { + background: var(--black-500) !important; + color: var(--base-white) !important; +} + +/* Botões outlined no modo escuro */ +[data-theme="dark"] button[class*="outlined"], +[data-theme="dark"] a[class*="outlined"] { + border-color: var(--white-500) !important; + color: var(--base-white) !important; +} + +[data-theme="dark"] button[class*="outlined"]:hover, +[data-theme="dark"] a[class*="outlined"]:hover { + background-color: var(--black-500) !important; + border-color: var(--base-white) !important; + color: var(--base-white) !important; +} + /* Transições suaves */ [data-theme="dark"] * { transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; From 3c7a9618c4eea15327f41160f77e3fbfdbb97369 Mon Sep 17 00:00:00 2001 From: Mariana Lins Date: Sun, 23 Nov 2025 21:01:09 -0300 Subject: [PATCH 03/11] =?UTF-8?q?feat=20CBD-108:=20p=C3=A1gina=20guia=20do?= =?UTF-8?q?=20usu=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Navbar/Navbar.jsx | 2 +- src/pages/Homepage/Homepage.jsx | 3 + src/pages/UserGuide/UserGuide.jsx | 387 +++++++++++++++++ src/pages/UserGuide/UserGuide.module.css | 506 +++++++++++++++++++++++ src/routes.jsx | 2 + 5 files changed, 899 insertions(+), 1 deletion(-) create mode 100644 src/pages/UserGuide/UserGuide.jsx create mode 100644 src/pages/UserGuide/UserGuide.module.css diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index 2506c54..4bbc978 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -29,7 +29,7 @@ const Navbar = () => {
  • - Guia de Uso + Guia de Uso
diff --git a/src/pages/Homepage/Homepage.jsx b/src/pages/Homepage/Homepage.jsx index 5f2eac0..e98e585 100644 --- a/src/pages/Homepage/Homepage.jsx +++ b/src/pages/Homepage/Homepage.jsx @@ -45,6 +45,9 @@ function Homepage () { icon={faArrowUpRightFromSquare} iconPosition="right" className={styles.userGuideBtn} + onClick={() => { + navigate('/user-guide') + }} > Ver Guia de Uso diff --git a/src/pages/UserGuide/UserGuide.jsx b/src/pages/UserGuide/UserGuide.jsx new file mode 100644 index 0000000..9e790a9 --- /dev/null +++ b/src/pages/UserGuide/UserGuide.jsx @@ -0,0 +1,387 @@ +import { useState } from 'react' +import styles from './UserGuide.module.css' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { + faFileUpload, + faGears, + faEdit, + faDatabase, + faChevronRight, + faCircle, + faCheckCircle, + faFileArrowDown, + faLightbulb +} from '@fortawesome/free-solid-svg-icons' +import Button from '../../components/Button' +import { useNavigate } from 'react-router-dom' + +function UserGuide() { + const navigate = useNavigate() + const [activeSection, setActiveSection] = useState('overview') + + const sections = [ + { id: 'overview', label: 'Visão Geral', icon: faLightbulb }, + { id: 'upload', label: 'Carregar Pedido', icon: faFileUpload }, + { id: 'process', label: 'Processar Pedido', icon: faGears }, + { id: 'edit', label: 'Editar Resultados', icon: faEdit }, + { id: 'database', label: 'Banco de Dados', icon: faDatabase }, + ] + + const scrollToSection = (sectionId) => { + setActiveSection(sectionId) + const element = document.getElementById(sectionId) + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }) + } + } + + return ( +
+ {/* Sidebar de Navegação */} + + + {/* Conteúdo Principal */} +
+ {/* Visão Geral */} +
+
+ +

Bem-vindo ao Descriptum

+
+ +

+ O Descriptum é uma solução completa para automatizar o processo de registro aduaneiro, + transformando pedidos de compra em informações organizadas e prontas para análise. +

+ +
+
+ +

Envio Rápido

+

Carregue seus pedidos em PDF de forma simples e rápida

+
+
+ +

Processamento Automático

+

O sistema identifica automaticamente produtos, fabricantes e fornecedores

+
+
+ +

Associação de NCM

+

Produtos são associados aos principais NCM's correspondentes

+
+
+ +

Revisão Facilitada

+

Revise e ajuste detalhes conforme necessário antes de finalizar

+
+
+ +
+

Fluxo de Trabalho

+
+
+
1
+
+

Carregar Pedido

+

Faça upload do PDF do pedido de compra

+
+
+ +
+
2
+
+

Processar Pedido

+

Acompanhe a extração automática dos dados

+
+
+ +
+
3
+
+

Editar Resultados

+

Revise e ajuste as informações geradas

+
+
+
+
+
+ + {/* Carregar Pedido */} +
+
+ +

Passo 1: Carregar Pedido

+
+ +

+ Nesta etapa, você fará o upload do arquivo PDF contendo o pedido de compra que deseja processar. +

+ +
+

Como fazer:

+
    +
  1. + + Clique no botão "Começar a Extrair" na página inicial ou acesse diretamente a página de upload +
  2. +
  3. + + Arraste e solte o arquivo PDF do pedido na área indicada ou clique para selecionar +
  4. +
  5. + + Aguarde o upload ser concluído - você verá uma confirmação visual +
  6. +
+
+ +
+ +
+

Dicas importantes:

+
    +
  • Certifique-se de que o arquivo está em formato PDF
  • +
  • O arquivo deve conter informações legíveis do pedido de compra
  • +
  • Verifique se o PDF não está protegido por senha
  • +
+
+
+
+ + {/* Processar Pedido */} +
+
+ +

Passo 2: Processar Pedido

+
+ +

+ Após o upload, o sistema iniciará automaticamente o processamento do pedido. + Nesta fase, o Descriptum extrai e organiza todas as informações relevantes. +

+ +
+

O que acontece nesta etapa:

+
    +
  1. + + Extração de Dados: O sistema lê o PDF e identifica produtos, códigos e quantidades +
  2. +
  3. + + Identificação Automática: Cada produto é analisado e associado a informações de fabricante e fornecedor +
  4. +
  5. + + Associação de NCM: O sistema sugere os códigos NCM mais adequados para cada produto +
  6. +
  7. + + Geração de Descrições: Descrições completas são criadas automaticamente para declaração aduaneira +
  8. +
+
+ +
+

Acompanhamento em Tempo Real

+

+ Durante o processamento, você verá uma lista de verificação (checklist) indicando + o progresso de cada etapa. Aguarde até que todas as etapas sejam concluídas antes de prosseguir. +

+
+ +
+ +
+

Importante:

+
    +
  • Não feche a página durante o processamento
  • +
  • O tempo de processamento varia de acordo com o tamanho do pedido
  • +
  • Você será automaticamente direcionado para a próxima etapa quando concluído
  • +
+
+
+
+ + {/* Editar Resultados */} +
+
+ +

Passo 3: Editar Resultados

+
+ +

+ Após o processamento, você terá acesso à tabela com todos os dados extraídos e poderá + revisar e editar qualquer informação antes de finalizar. +

+ +
+

Como revisar e editar:

+
    +
  1. + + Visualizar a Tabela: Todos os produtos extraídos serão exibidos em formato de tabela +
  2. +
  3. + + Editar um Item: Clique na linha do produto que deseja editar +
  4. +
  5. + + Modificar Campos: Um formulário será aberto com todos os campos editáveis: +
      +
    • Part Number (PN)
    • +
    • Código ERP
    • +
    • Descrição ERP
    • +
    • Descrição para DI (Declaração de Importação)
    • +
    • NCM (Nomenclatura Comum do Mercosul)
    • +
    • Dados do Fabricante (Nome, Endereço, País)
    • +
    +
    +
  6. +
  7. + + Salvar Alterações: Clique em "Salvar" para confirmar as modificações +
  8. +
  9. + + Finalizar: Quando estiver satisfeito com todas as informações, clique em "Finalizar" para gerar o Excel +
  10. +
+
+ +
+ +
+

Exportação de Dados

+

+ Ao finalizar, o sistema gera automaticamente um arquivo Excel contendo todos os dados + organizados e prontos para uso no processo de registro aduaneiro. +

+
+
+ +
+ +
+

Dicas para edição:

+
    +
  • Revise especialmente as descrições para DI, garantindo que estejam completas e corretas
  • +
  • Verifique se os códigos NCM sugeridos estão adequados ao produto
  • +
  • Confirme os dados de fabricante e fornecedor para evitar problemas na documentação
  • +
  • Você pode editar quantas linhas forem necessárias antes de finalizar
  • +
+
+
+
+ + {/* Banco de Dados */} +
+
+ +

Banco de Dados

+
+ +

+ O Descriptum mantém um banco de dados completo com informações de produtos, fornecedores e + fabricantes, além do histórico de todas as extrações realizadas. +

+ +
+
+ +

Histórico de Extrações

+

Acesse o registro completo de todos os pedidos processados, com data, status e informações detalhadas de cada extração realizada.

+
+ +
+ +

Produtos

+

Explore o catálogo completo de produtos já processados. Visualize e atualize informações como códigos, descrições e especificações técnicas.

+
+ +
+ +

Fornecedores

+

Gerencie o cadastro de fornecedores, incluindo razão social, endereço, país de origem e outras informações relevantes para o processo aduaneiro.

+
+ +
+ +

Fabricantes

+

Mantenha atualizado o cadastro de fabricantes com nome, endereço completo, país de fabricação e demais dados necessários para documentação.

+
+
+ +
+

Como utilizar o Banco de Dados:

+
    +
  1. + + Acesse o menu "Banco de Dados" na navegação principal +
  2. +
  3. + + Selecione a categoria que deseja consultar ou editar +
  4. +
  5. + + Use os filtros e busca para encontrar registros específicos +
  6. +
  7. + + Clique em qualquer registro para visualizar detalhes ou editar informações +
  8. +
+
+ +
+ +
+

Benefícios do Banco de Dados:

+
    +
  • Reutilização de informações em futuras extrações
  • +
  • Melhoria contínua da precisão dos dados
  • +
  • Histórico completo para auditoria e rastreabilidade
  • +
  • Facilita a padronização de descrições e classificações
  • +
+
+
+
+ + {/* Call to Action */} +
+

Pronto para começar?

+

Inicie agora o processo de extração e aproveite todos os recursos do Descriptum!

+ +
+
+
+ ) +} + +export default UserGuide diff --git a/src/pages/UserGuide/UserGuide.module.css b/src/pages/UserGuide/UserGuide.module.css new file mode 100644 index 0000000..da1f9a5 --- /dev/null +++ b/src/pages/UserGuide/UserGuide.module.css @@ -0,0 +1,506 @@ +.container { + display: flex; + min-height: 100vh; + background: var(--background-primary); +} + +/* Sidebar */ +.sidebar { + position: fixed; + left: 0; + top: 0; + width: 280px; + height: 100vh; + background: var(--background-secondary); + border-right: 1px solid var(--border-color); + padding: 2rem 1rem; + overflow-y: auto; + z-index: 100; +} + +.sidebarTitle { + font-size: 1.5rem; + font-weight: 700; + color: var(--text-primary); + margin-bottom: 2rem; + padding: 0 1rem; +} + +.nav { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.navItem { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.875rem 1rem; + background: transparent; + border: none; + border-radius: 8px; + color: var(--text-secondary); + font-size: 0.95rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + text-align: left; +} + +.navItem:hover { + background: var(--background-tertiary); + color: var(--text-primary); +} + +.navItemActive { + background: var(--royal-blue-100); + color: var(--royal-blue-700); +} + +.navItemActive:hover { + background: var(--royal-blue-100); + color: var(--royal-blue-700); +} + +.navIcon { + width: 18px; + font-size: 1rem; +} + +/* Content */ +.content { + margin-left: 280px; + flex: 1; + padding: 3rem; + max-width: 1200px; +} + +.section { + margin-bottom: 4rem; + scroll-margin-top: 2rem; +} + +.sectionHeader { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid var(--border-color); +} + +.sectionIcon { + font-size: 2rem; + color: var(--royal-blue-500); +} + +.sectionTitle { + font-size: 2rem; + font-weight: 700; + color: var(--text-primary); + margin: 0; +} + +.description { + font-size: 1.125rem; + line-height: 1.7; + color: var(--text-secondary); + margin-bottom: 2rem; +} + +/* Features Grid */ +.featuresGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1.5rem; + margin: 2rem 0; +} + +.featureCard { + padding: 1.5rem; + background: var(--background-secondary); + border: 1px solid var(--border-color); + border-radius: 12px; + transition: all 0.3s ease; +} + +.featureCard:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + border-color: var(--royal-blue-300); +} + +.featureIcon { + font-size: 2rem; + color: var(--royal-blue-500); + margin-bottom: 1rem; +} + +.featureCard h3 { + font-size: 1.125rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.featureCard p { + font-size: 0.95rem; + color: var(--text-secondary); + line-height: 1.6; +} + +/* Workflow */ +.workflow { + margin: 3rem 0; + padding: 2rem; + background: var(--background-secondary); + border-radius: 12px; +} + +.workflow h2 { + font-size: 1.5rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 2rem; +} + +.workflowSteps { + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; +} + +.workflowStep { + flex: 1; + display: flex; + align-items: center; + gap: 1rem; + padding: 1.5rem; + background: var(--background-primary); + border: 1px solid var(--border-color); + border-radius: 10px; +} + +.stepNumber { + display: flex; + align-items: center; + justify-content: center; + width: 48px; + height: 48px; + min-width: 48px; + background: var(--royal-blue-500); + color: white; + font-size: 1.5rem; + font-weight: 700; + border-radius: 50%; +} + +.stepContent h4 { + font-size: 1rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.25rem; +} + +.stepContent p { + font-size: 0.875rem; + color: var(--text-secondary); +} + +.stepArrow { + font-size: 1.5rem; + color: var(--text-tertiary); + min-width: 24px; +} + +/* Instruction Box */ +.instructionBox { + background: var(--background-secondary); + border-left: 4px solid var(--royal-blue-500); + border-radius: 8px; + padding: 1.5rem; + margin: 2rem 0; +} + +.instructionBox h3 { + font-size: 1.25rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 1rem; +} + +.instructionList { + list-style: none; + counter-reset: item; + padding: 0; + margin: 0; +} + +.instructionList > li { + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 0.75rem 0; + color: var(--text-secondary); + line-height: 1.6; + counter-increment: item; +} + +.instructionList > li::before { + content: counter(item) "."; + font-weight: 700; + color: var(--royal-blue-500); + min-width: 24px; +} + +.bulletIcon { + color: var(--royal-blue-500); + font-size: 0.5rem; + margin-top: 0.5rem; + min-width: 12px; +} + +.subList { + margin-top: 0.5rem; + margin-left: 1rem; +} + +.subList li { + padding: 0.25rem 0; +} + +/* Tip Box */ +.tipBox { + display: flex; + gap: 1rem; + background: var(--warning-bg, #fffbeb); + border: 1px solid var(--warning-border, #fbbf24); + border-radius: 8px; + padding: 1.5rem; + margin: 2rem 0; +} + +.tipIcon { + color: var(--warning-text, #f59e0b); + font-size: 1.5rem; + min-width: 24px; + margin-top: 0.25rem; +} + +.tipBox h4 { + font-size: 1rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.tipBox ul { + margin: 0.5rem 0 0 1.25rem; + color: var(--text-secondary); +} + +.tipBox li { + padding: 0.25rem 0; + line-height: 1.6; +} + +/* Dark mode for Tip Box */ +[data-theme="dark"] .tipBox { + background: rgba(245, 158, 11, 0.1); + border-color: rgba(245, 158, 11, 0.3); +} + +[data-theme="dark"] .tipBox h4, +[data-theme="dark"] .tipBox ul, +[data-theme="dark"] .tipBox li { + color: var(--base-white) !important; +} + +/* Progress Info */ +.progressInfo { + background: var(--info-bg, #eff6ff); + border: 1px solid var(--info-border, #60a5fa); + border-radius: 8px; + padding: 1.5rem; + margin: 2rem 0; +} + +.progressInfo h3 { + font-size: 1.125rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.75rem; +} + +.progressInfo p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* Dark mode for Progress Info */ +[data-theme="dark"] .progressInfo { + background: rgba(59, 130, 246, 0.1); + border-color: rgba(59, 130, 246, 0.3); +} + +[data-theme="dark"] .progressInfo h3, +[data-theme="dark"] .progressInfo p { + color: var(--base-white) !important; +} + +/* Feature Highlight */ +.featureHighlight { + display: flex; + gap: 1.5rem; + align-items: center; + background: linear-gradient(135deg, var(--royal-blue-50) 0%, var(--royal-blue-100) 100%); + border-radius: 12px; + padding: 2rem; + margin: 2rem 0; +} + +.highlightIcon { + font-size: 3rem; + color: var(--royal-blue-500); + min-width: 48px; +} + +.featureHighlight h3 { + font-size: 1.25rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.featureHighlight p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* Database Grid */ +.databaseGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; + margin: 2rem 0; +} + +.databaseCard { + padding: 2rem; + background: var(--background-secondary); + border: 1px solid var(--border-color); + border-radius: 12px; + transition: all 0.3s ease; +} + +.databaseCard:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + border-color: var(--royal-blue-300); +} + +.databaseIcon { + font-size: 2.5rem; + color: var(--royal-blue-500); + margin-bottom: 1rem; +} + +.databaseCard h3 { + font-size: 1.25rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.75rem; +} + +.databaseCard p { + font-size: 0.95rem; + color: var(--text-secondary); + line-height: 1.6; +} + +/* CTA Section */ +.ctaSection { + text-align: center; + padding: 3rem; + background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%); + border-radius: 16px; + margin-top: 4rem; +} + +.ctaSection h2 { + font-size: 2rem; + font-weight: 700; + color: var(--text-primary) !important; + margin-bottom: 1rem; +} + +.ctaSection p { + font-size: 1.125rem; + color: var(--text-secondary) !important; + margin-bottom: 2rem; +} + +/* Dark mode for CTA Section */ +[data-theme="dark"] .ctaSection { + background: linear-gradient(135deg, var(--royal-blue-700) 0%, var(--royal-blue-900) 100%); +} + +[data-theme="dark"] .ctaSection h2, +[data-theme="dark"] .ctaSection p { + color: var(--base-white) !important; +} + +/* Responsive */ +@media (max-width: 1024px) { + .sidebar { + width: 240px; + } + + .content { + margin-left: 240px; + padding: 2rem; + } + + .workflowSteps { + flex-direction: column; + } + + .stepArrow { + transform: rotate(90deg); + } +} + +@media (max-width: 768px) { + .container { + flex-direction: column; + } + + .sidebar { + position: relative; + width: 100%; + height: auto; + border-right: none; + border-bottom: 1px solid var(--border-color); + } + + .content { + margin-left: 0; + padding: 1.5rem; + } + + .sectionTitle { + font-size: 1.5rem; + } + + .featuresGrid, + .databaseGrid { + grid-template-columns: 1fr; + } + + .featureHighlight { + flex-direction: column; + text-align: center; + } +} diff --git a/src/routes.jsx b/src/routes.jsx index 27259c1..325d5d2 100644 --- a/src/routes.jsx +++ b/src/routes.jsx @@ -3,6 +3,7 @@ import { Routes , Route } from "react-router-dom"; import Homepage from "./pages/Homepage/Homepage"; import TableEdit from "./pages/TableEdit/TableEdit"; import InputFiles from "./pages/InputFiles/InputFiles"; +import UserGuide from "./pages/UserGuide/UserGuide"; import DataBase from "./pages/DataBase/DataBase"; @@ -18,6 +19,7 @@ const RoutesApp = () => { } /> } /> } /> + } /> } /> } /> } /> From 4367c65de75cf5c46a53c3c5382bda2bae8ae6e7 Mon Sep 17 00:00:00 2001 From: Mariana Lins Date: Sun, 23 Nov 2025 21:07:24 -0300 Subject: [PATCH 04/11] =?UTF-8?q?CBD-108=20refactor:=20centraliza=20regras?= =?UTF-8?q?=20de=20dark=20mode=20da=20p=C3=A1gina=20UserGuide=20no=20arqui?= =?UTF-8?q?vo=20dark-mode.css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/UserGuide/UserGuide.module.css | 33 ---------------------- src/styles/dark-mode.css | 35 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/pages/UserGuide/UserGuide.module.css b/src/pages/UserGuide/UserGuide.module.css index da1f9a5..9f348ba 100644 --- a/src/pages/UserGuide/UserGuide.module.css +++ b/src/pages/UserGuide/UserGuide.module.css @@ -306,18 +306,6 @@ line-height: 1.6; } -/* Dark mode for Tip Box */ -[data-theme="dark"] .tipBox { - background: rgba(245, 158, 11, 0.1); - border-color: rgba(245, 158, 11, 0.3); -} - -[data-theme="dark"] .tipBox h4, -[data-theme="dark"] .tipBox ul, -[data-theme="dark"] .tipBox li { - color: var(--base-white) !important; -} - /* Progress Info */ .progressInfo { background: var(--info-bg, #eff6ff); @@ -339,17 +327,6 @@ line-height: 1.6; } -/* Dark mode for Progress Info */ -[data-theme="dark"] .progressInfo { - background: rgba(59, 130, 246, 0.1); - border-color: rgba(59, 130, 246, 0.3); -} - -[data-theme="dark"] .progressInfo h3, -[data-theme="dark"] .progressInfo p { - color: var(--base-white) !important; -} - /* Feature Highlight */ .featureHighlight { display: flex; @@ -442,16 +419,6 @@ margin-bottom: 2rem; } -/* Dark mode for CTA Section */ -[data-theme="dark"] .ctaSection { - background: linear-gradient(135deg, var(--royal-blue-700) 0%, var(--royal-blue-900) 100%); -} - -[data-theme="dark"] .ctaSection h2, -[data-theme="dark"] .ctaSection p { - color: var(--base-white) !important; -} - /* Responsive */ @media (max-width: 1024px) { .sidebar { diff --git a/src/styles/dark-mode.css b/src/styles/dark-mode.css index 7ccba1c..c9800da 100644 --- a/src/styles/dark-mode.css +++ b/src/styles/dark-mode.css @@ -279,3 +279,38 @@ [data-theme="dark"] * { transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; } + +/* ===== USER GUIDE PAGE ===== */ + +/* Progress Info Box (azul) */ +[data-theme="dark"] [class*="progressInfo"] { + background: rgba(59, 130, 246, 0.1) !important; + border-color: rgba(59, 130, 246, 0.3) !important; +} + +[data-theme="dark"] [class*="progressInfo"] h3, +[data-theme="dark"] [class*="progressInfo"] p { + color: var(--base-white) !important; +} + +/* Tip Box (amarelo/laranja) */ +[data-theme="dark"] [class*="tipBox"] { + background: rgba(245, 158, 11, 0.1) !important; + border-color: rgba(245, 158, 11, 0.3) !important; +} + +[data-theme="dark"] [class*="tipBox"] h4, +[data-theme="dark"] [class*="tipBox"] ul, +[data-theme="dark"] [class*="tipBox"] li { + color: var(--base-white) !important; +} + +/* CTA Section */ +[data-theme="dark"] [class*="ctaSection"] { + background: linear-gradient(135deg, var(--royal-blue-700) 0%, var(--royal-blue-900) 100%) !important; +} + +[data-theme="dark"] [class*="ctaSection"] h2, +[data-theme="dark"] [class*="ctaSection"] p { + color: var(--base-white) !important; +} From 114561c730e006a0fa80d20686c207f8265c6574 Mon Sep 17 00:00:00 2001 From: Mariana Lins Date: Sun, 23 Nov 2025 21:21:56 -0300 Subject: [PATCH 05/11] =?UTF-8?q?CDB-108=20fix:=20corrige=20problemas=20id?= =?UTF-8?q?entificados=20no=20code=20review=20da=20p=C3=A1gina=20UserGuide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/UserGuide/UserGuide.jsx | 55 ++++++----- src/pages/UserGuide/UserGuide.module.css | 114 ++++++++++----------- src/styles/dark-mode.css | 121 ++++++++++++++++++++--- 3 files changed, 195 insertions(+), 95 deletions(-) diff --git a/src/pages/UserGuide/UserGuide.jsx b/src/pages/UserGuide/UserGuide.jsx index 9e790a9..39442d6 100644 --- a/src/pages/UserGuide/UserGuide.jsx +++ b/src/pages/UserGuide/UserGuide.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useState, useEffect } from 'react' import styles from './UserGuide.module.css' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { @@ -7,8 +7,6 @@ import { faEdit, faDatabase, faChevronRight, - faCircle, - faCheckCircle, faFileArrowDown, faLightbulb } from '@fortawesome/free-solid-svg-icons' @@ -19,6 +17,29 @@ function UserGuide() { const navigate = useNavigate() const [activeSection, setActiveSection] = useState('overview') + useEffect(() => { + const handleScroll = () => { + const sections = ['overview', 'upload', 'process', 'edit', 'database'] + const scrollPosition = window.scrollY + 150 + + for (const sectionId of sections) { + const element = document.getElementById(sectionId) + if (element) { + const offsetTop = element.offsetTop + const offsetBottom = offsetTop + element.offsetHeight + + if (scrollPosition >= offsetTop && scrollPosition < offsetBottom) { + setActiveSection(sectionId) + break + } + } + } + } + + window.addEventListener('scroll', handleScroll) + return () => window.removeEventListener('scroll', handleScroll) + }, []) + const sections = [ { id: 'overview', label: 'Visão Geral', icon: faLightbulb }, { id: 'upload', label: 'Carregar Pedido', icon: faFileUpload }, @@ -46,8 +67,10 @@ function UserGuide() { key={section.id} className={`${styles.navItem} ${activeSection === section.id ? styles.navItemActive : ''}`} onClick={() => scrollToSection(section.id)} + aria-label={`Navegar para ${section.label}`} + aria-current={activeSection === section.id ? 'true' : 'false'} > - +