feat: update doc

This commit is contained in:
2026-06-05 09:05:53 -03:00
parent fd8e9049bf
commit d09d695d29
11 changed files with 1091 additions and 15 deletions

23
app/.dockerignore Normal file
View File

@@ -0,0 +1,23 @@
node_modules
npm-debug.log
dist
.git
.gitignore
.github
.vscode
.env
.env.local
.env.production
.env.offline
*.md
docs
jupyter
SDD
.specify
.specs
.cache
.pnpmfile.cjs
.npmrc
coverage
.nyc_output
.vercel

View File

@@ -1,3 +1,45 @@
# ============================================================================
# ANALYTICS CONFIGURATION
# ============================================================================
# Provider: 'ga4' para Google Analytics 4, ou 'noop' para desabilitar
# Padrão: 'ga4' em produção, 'noop' em desenvolvimento
VITE_ANALYTICS_PROVIDER=ga4
VITE_GA4_ID=
# Google Analytics 4 - ID de Medição (ID do fluxo de dados)
# Obtenha em: https://analytics.google.com → Administração → Data Streams
# Formato: G-XXXXXXXXXX
# Deixe em branco para desabilitar GA4 (mesmo que VITE_ANALYTICS_PROVIDER=ga4)
VITE_GA4_ID=G-57HGKF773M
# Debug mode: 'true' para ativar logs de eventos no console do browser
# Útil para testing e desenvolvimento
VITE_GA4_DEBUG=false
# Banner de consentimento de cookies (LGPD/GDPR)
# 'true' para mostrar, 'false' para desabilitar
VITE_ENABLE_CONSENT_BANNER=true
# ============================================================================
# BUILD CONFIGURATION
# ============================================================================
# Git commit hash - usado para versionamento e detecção de atualizações
# Deixe em branco para usar 'unknown' durante o build
# Será preenchido automaticamente em CI/CD
GIT_COMMIT_HASH=
# ============================================================================
# NOTAS
# ============================================================================
#
# Para desenvolvimento (sem analytics):
# VITE_ANALYTICS_PROVIDER=noop
#
# Para produção (com GA4):
# VITE_ANALYTICS_PROVIDER=ga4
# VITE_GA4_ID=G-SEU_ID_AQUI
# VITE_GA4_DEBUG=false
#
# Veja ANALYTICS.md e DOCKER_BUILD_EXAMPLES.md para mais detalhes
#

View File

@@ -15,19 +15,16 @@ ENV VITE_ANALYTICS_PROVIDER=$VITE_ANALYTICS_PROVIDER
ENV VITE_GA4_ID=$VITE_GA4_ID
ENV VITE_GA4_DEBUG=$VITE_GA4_DEBUG
RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN echo "{\"version\": \"$APP_VERSION\", \"commit\": \"$GIT_COMMIT_HASH\", \"buildDate\": \"$(date)\"}" > public/version.json
RUN pnpm run build
RUN echo "{\"version\": \"$APP_VERSION\", \"commit\": \"$GIT_COMMIT_HASH\", \"buildDate\": \"$(date)\"}" > public/version.json && \
pnpm run build && \
rm -rf node_modules .pnpm-store
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx-spa.conf /etc/nginx/conf.d/default.conf

View File

@@ -6,6 +6,26 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="manifest" href="/manifest.json" />
<title>Decoda</title>
<script>
(async function checkForUpdates() {
try {
const response = await fetch('/version.json?t=' + Date.now());
const newVersion = await response.json();
const lastVersion = sessionStorage.getItem('app_version');
if (lastVersion && lastVersion !== newVersion.commit) {
console.log('🔄 Novo deploy detectado. Recarregando...');
sessionStorage.setItem('app_version', newVersion.commit);
window.location.reload(true);
return;
}
sessionStorage.setItem('app_version', newVersion.commit);
} catch (e) {
console.warn('Falha ao verificar atualizações:', e);
}
})();
</script>
</head>
<body>
<div id="root"></div>

View File

@@ -12,13 +12,15 @@ import LabPython from "./pages/LabPython/LabPython";
import ScrollToTop from "./components/ScrollToTop";
import { getAnalytics, usePageTracking } from "./services/analytics";
import { initializeAnalytics, analyticsConfig } from "./services/analytics";
import { ConsentManager } from "./services/consent";
// Inline CookieBanner para evitar bloqueio do Brave
function CookieBanner() {
const [visible, setVisible] = useState(false);
const enableBanner = import.meta.env.VITE_ENABLE_CONSENT_BANNER === 'true';
useEffect(() => {
if (!enableBanner) return;
try {
const stored = localStorage.getItem('decoda_consent');
if (!stored) {
@@ -27,7 +29,7 @@ function CookieBanner() {
} catch (e) {
console.error('Consent check failed:', e);
}
}, []);
}, [enableBanner]);
const handleAccept = () => {
try {
@@ -57,7 +59,7 @@ function CookieBanner() {
}
};
if (!visible) return null;
if (!visible || !enableBanner) return null;
return (
<div className="fixed bottom-0 left-0 right-0 z-50 p-4 md:p-6" role="dialog" aria-label="Consentimento de cookies">
@@ -212,11 +214,10 @@ export default function App() {
const [analyticsReady, setAnalyticsReady] = useState(false);
useEffect(() => {
const hasConsent = ConsentManager.hasConsent();
initializeAnalytics({
providerType: analyticsConfig.providerType,
measurementId: analyticsConfig.measurementId,
hasConsent,
hasConsent: true,
debugMode: analyticsConfig.debugMode,
});