Raí Santos
commited on
Commit
·
dd60672
1
Parent(s):
c94ea82
oi
Browse files- Dockerfile +91 -15
- src/components/GameByGameResults.tsx +7 -1
Dockerfile
CHANGED
@@ -1,26 +1,102 @@
|
|
1 |
-
#
|
2 |
-
|
|
|
3 |
|
4 |
-
#
|
5 |
WORKDIR /app
|
6 |
|
7 |
-
# Copiar dependências primeiro (cache
|
8 |
COPY package*.json ./
|
9 |
-
RUN npm install --silent
|
10 |
|
11 |
-
#
|
|
|
|
|
|
|
12 |
COPY . .
|
13 |
|
14 |
-
#
|
15 |
-
ENV NODE_ENV=
|
16 |
-
ENV
|
17 |
-
ENV
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
-
#
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
EXPOSE 7860
|
24 |
|
25 |
-
#
|
26 |
-
CMD ["
|
|
|
|
|
|
|
|
|
|
|
|
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>
|