Raí Santos commited on
Commit
dd60672
·
1 Parent(s): c94ea82
Files changed (2) hide show
  1. Dockerfile +91 -15
  2. src/components/GameByGameResults.tsx +7 -1
Dockerfile CHANGED
@@ -1,26 +1,102 @@
1
- # Base leve
2
- FROM node:18-alpine
 
3
 
4
- # Diretório de trabalho
5
  WORKDIR /app
6
 
7
- # Copiar dependências primeiro (cache melhor)
8
  COPY package*.json ./
9
- RUN npm install --silent
10
 
11
- # Copiar código da aplicação
 
 
 
12
  COPY . .
13
 
14
- # Variáveis de ambiente
15
- ENV NODE_ENV=development
16
- ENV PORT=7860
17
- ENV HOST=0.0.0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- # Garantir permissões totais para evitar erro do eslint cache
20
- RUN chmod -R 777 /app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- # Expor porta padrão do Hugging Face
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  EXPOSE 7860
24
 
25
- # Rodar em modo dev (react-scripts start)
26
- CMD ["npm", "start"]
 
 
 
 
 
 
1
+ # Multi-stage build otimizado para Hugging Face Spaces
2
+ # Stage 1: Build da aplicação React
3
+ FROM node:18-alpine AS builder
4
 
5
+ # Definir diretório de trabalho
6
  WORKDIR /app
7
 
8
+ # Copiar arquivos de dependências primeiro (cache layer)
9
  COPY package*.json ./
 
10
 
11
+ # Instalar dependências com cache otimizado
12
+ RUN npm ci --only=production --silent
13
+
14
+ # Copiar código fonte
15
  COPY . .
16
 
17
+ # Build otimizado para produção
18
+ ENV NODE_ENV=production
19
+ ENV GENERATE_SOURCEMAP=false
20
+ ENV INLINE_RUNTIME_CHUNK=false
21
+
22
+ # Build da aplicação
23
+ RUN npm run build
24
+
25
+ # Stage 2: Servidor Nginx otimizado
26
+ FROM nginx:alpine
27
+
28
+ # Instalar Node.js para servir a aplicação (necessário para Hugging Face)
29
+ RUN apk add --no-cache nodejs npm
30
+
31
+ # Remover configuração padrão do Nginx
32
+ RUN rm -rf /usr/share/nginx/html/*
33
+
34
+ # Copiar build da aplicação
35
+ COPY --from=builder /app/build /usr/share/nginx/html
36
+
37
+ # Configuração customizada do Nginx para SPA
38
+ COPY <<EOF /etc/nginx/conf.d/default.conf
39
+ server {
40
+ listen 7860;
41
+ server_name localhost;
42
+ root /usr/share/nginx/html;
43
+ index index.html;
44
 
45
+ # Configuração para SPA (Single Page Application)
46
+ location / {
47
+ try_files \$uri \$uri/ /index.html;
48
+
49
+ # Headers de segurança
50
+ add_header X-Frame-Options "SAMEORIGIN" always;
51
+ add_header X-Content-Type-Options "nosniff" always;
52
+ add_header X-XSS-Protection "1; mode=block" always;
53
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
54
+
55
+ # Cache para assets estáticos
56
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
57
+ expires 1y;
58
+ add_header Cache-Control "public, immutable";
59
+ }
60
+ }
61
 
62
+ # Compressão gzip
63
+ gzip on;
64
+ gzip_vary on;
65
+ gzip_min_length 1024;
66
+ gzip_types
67
+ text/plain
68
+ text/css
69
+ text/xml
70
+ text/javascript
71
+ application/javascript
72
+ application/xml+rss
73
+ application/json;
74
+ }
75
+ EOF
76
+
77
+ # Configurar script de inicialização
78
+ COPY <<EOF /docker-entrypoint.sh
79
+ #!/bin/sh
80
+ set -e
81
+
82
+ # Iniciar Nginx
83
+ echo "🚀 Iniciando Lotomania Estratégia no Hugging Face Spaces..."
84
+ echo "📊 Plataforma de análise estratégica da Lotomania"
85
+ echo "🔗 Acesse: http://localhost:7860"
86
+
87
+ exec nginx -g 'daemon off;'
88
+ EOF
89
+
90
+ # Dar permissão de execução
91
+ RUN chmod +x /docker-entrypoint.sh
92
+
93
+ # Expor porta padrão do Hugging Face Spaces
94
  EXPOSE 7860
95
 
96
+ # Comando de inicialização
97
+ CMD ["/docker-entrypoint.sh"]
98
+
99
+ # Labels para metadados
100
+ LABEL maintainer="Lotomania Estratégia"
101
+ LABEL description="Plataforma avançada de análise estratégica da Lotomania"
102
+ LABEL version="1.0.0"
src/components/GameByGameResults.tsx CHANGED
@@ -27,7 +27,7 @@ export const GameByGameResults: React.FC<GameByGameResultsProps> = ({
27
  currentResult
28
  }) => {
29
  const [filterType, setFilterType] = useState<'all' | 'vertical' | 'horizontal'>('all');
30
- const [filterPoints, setFilterPoints] = useState<'all' | 'winning' | '15+' | '17+' | '19+' | '20' | '0'>('all');
31
  const [showGrid, setShowGrid] = useState(true);
32
  const [currentPage, setCurrentPage] = useState(1);
33
  const GAMES_PER_PAGE = 10;
@@ -84,6 +84,10 @@ export const GameByGameResults: React.FC<GameByGameResultsProps> = ({
84
  filtered = filtered.filter(r => r.isWinning);
85
  } else if (filterPoints === '20') {
86
  filtered = filtered.filter(r => r.points === 20);
 
 
 
 
87
  } else if (filterPoints === '0') {
88
  filtered = filtered.filter(r => r.points === 0);
89
  } else if (filterPoints !== 'all') {
@@ -261,7 +265,9 @@ export const GameByGameResults: React.FC<GameByGameResultsProps> = ({
261
  <option value="all">Todas Pontuações</option>
262
  <option value="winning">Apenas Premiados</option>
263
  <option value="15+">15+ Pontos</option>
 
264
  <option value="17+">17+ Pontos</option>
 
265
  <option value="19+">19+ Pontos</option>
266
  <option value="20">20 Pontos</option>
267
  </select>
 
27
  currentResult
28
  }) => {
29
  const [filterType, setFilterType] = useState<'all' | 'vertical' | 'horizontal'>('all');
30
+ const [filterPoints, setFilterPoints] = useState<'all' | 'winning' | '15+' | '16' | '17+' | '18' | '19+' | '20' | '0'>('all');
31
  const [showGrid, setShowGrid] = useState(true);
32
  const [currentPage, setCurrentPage] = useState(1);
33
  const GAMES_PER_PAGE = 10;
 
84
  filtered = filtered.filter(r => r.isWinning);
85
  } else if (filterPoints === '20') {
86
  filtered = filtered.filter(r => r.points === 20);
87
+ } else if (filterPoints === '18') {
88
+ filtered = filtered.filter(r => r.points === 18);
89
+ } else if (filterPoints === '16') {
90
+ filtered = filtered.filter(r => r.points === 16);
91
  } else if (filterPoints === '0') {
92
  filtered = filtered.filter(r => r.points === 0);
93
  } else if (filterPoints !== 'all') {
 
265
  <option value="all">Todas Pontuações</option>
266
  <option value="winning">Apenas Premiados</option>
267
  <option value="15+">15+ Pontos</option>
268
+ <option value="16">16 Pontos</option>
269
  <option value="17+">17+ Pontos</option>
270
+ <option value="18">18 Pontos</option>
271
  <option value="19+">19+ Pontos</option>
272
  <option value="20">20 Pontos</option>
273
  </select>