fix: resolve portal white screen via physical service isolation and fix financeiro UI bugs
This commit is contained in:
parent
c1c2c9d9b9
commit
5ee1524d8a
|
|
@ -48,6 +48,6 @@ jobs:
|
|||
docker run --rm \
|
||||
-e DOCKER_API_VERSION=1.44 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v ~/.docker/config.json:/config.json \
|
||||
-v $DOCKER_CONFIG/config.json:/config.json \
|
||||
containrrr/watchtower \
|
||||
--run-once --cleanup
|
||||
|
|
|
|||
|
|
@ -26,4 +26,4 @@
|
|||
4. **Upload de Arquivos:** Proibido o uso de Base64 para envio de novos arquivos ao servidor. Use obrigatoriamente `FormData` e envie o objeto `File/Blob` para as rotas de API que integram com o MinIO.
|
||||
5. **Build & Deploy Stability:** O pipeline de deploy deve obrigatoriamente utilizar `runs-on: self-hosted` e compilar apenas a plataforma `linux/arm64` (sem emulação QEMU). A atualização da stack em produção deve ser automatizada via container transiente do Watchtower.
|
||||
6. **Express Compatibility**: Avoid using raw `/*` wildcards in Express 5 routes; use Regex paths (`/^\/route\/(.+)$/`) for compatibility with `path-to-regexp` v8.
|
||||
7. **Frontend Independence**: NEVER import files from `services/` or `server.js` directly into React components to prevent Node.js/SDK leakage (causes White Screen). Use `helpers.ts` for UI logic.
|
||||
7. **Frontend Independence**: NEVER import files from `services/` or `server.js` directly into React components to prevent Node.js/SDK leakage (causes White Screen). Physical isolation is enforced: backend-only services (like MinIO/S3 storage) MUST stay outside the `src/` directory in Vite/React projects. Use `helpers.ts` for UI logic and standard `fetch` for API calls.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# MEMORY.md - Contexto de Desenvolvimento
|
||||
|
||||
## 📅 Estado Atual (21/04/2026)
|
||||
## 📅 Estado Atual (22/04/2026)
|
||||
|
||||
- [x] Correção do "Bug da Tela Preta" na câmera ao alternar para câmera traseira no celular.
|
||||
- [x] Unificação do servidor de produção: Dockerfile agora utiliza `server.selfhosted.js` (Manager e Portal).
|
||||
|
|
@ -11,7 +11,10 @@
|
|||
- [x] Correção do Crash 404 no Portal: Injeção da pasta `src/services` no container de produção para permitir o import do `storage.js`.
|
||||
- [x] Correção das Imagens de Prova: Normalização das URLs nas questões de avaliações (Portal e Manager).
|
||||
- [x] Estabilização de CI/CD: Transição para `runs-on: self-hosted` (ARM64 nativo) eliminando lentidão e crashes do QEMU.
|
||||
- [x] Fix Tela Branca (Portal): Refatoração de `normalizePhotoUrl` para `helpers.ts` isolado, evitando vazamento de SDK de Backend no Navegador.
|
||||
- [x] Fix Tela Branca (Portal): Isolamento Físico absoluto do `storage.js` (SDK Backend) para pasta fora do `src` (server-only). Isso impede vazamentos de Node.js no navegador.
|
||||
- [x] Correção Financeiro (Portal): Resolvido erros de renderização em `Financeiro.tsx` e inconsistência de tipos em `Notifications.ts`.
|
||||
- [x] Pipeline Deploy: Ajustado volume do Docker no GitHub Actions de `~/.docker` para `$DOCKER_CONFIG` para compatibilidade total com o Runner.
|
||||
- [x] Normalização de Imagens: Todas as fotos de alunos no Portal agora passam pela vacina `normalizePhotoUrl`.
|
||||
- [ ] Próximo Passo: Verificar se o Watchtower sincronizou as imagens corretamente na produção.
|
||||
|
||||
### 💳 Módulo Financeiro (Portal do Aluno)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import puppeteer from 'puppeteer';
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
page.on('console', msg => console.log('BROWSER CONSOLE:', msg.text()));
|
||||
page.on('pageerror', error => console.error('BROWSER ERROR:', error.message));
|
||||
page.on('requestfailed', request => console.error('REQUEST FAILED:', request.url(), request.failure().errorText));
|
||||
|
||||
await page.goto('http://localhost:5173/', { waitUntil: 'networkidle0' }).catch(e => console.log(e));
|
||||
|
||||
await page.screenshot({ path: 'screenshot.png' });
|
||||
await browser.close();
|
||||
})();
|
||||
|
|
@ -17,7 +17,7 @@ import pg from 'pg';
|
|||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import multer from 'multer';
|
||||
import { uploadAtestado, s3Client } from './src/services/storage.js';
|
||||
import { uploadAtestado, s3Client } from './server/services/storage.js';
|
||||
import { GetObjectCommand } from '@aws-sdk/client-s3';
|
||||
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export default function Header() {
|
|||
overflow: 'hidden', flexShrink: 0,
|
||||
}}>
|
||||
{student.photo ? (
|
||||
<img src={student.photo} alt={student.name}
|
||||
<img src={normalizePhotoUrl(student.photo)} alt={student.name}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
) : (
|
||||
student.name.charAt(0).toUpperCase()
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ export default function Sidebar() {
|
|||
overflow: 'hidden', transition: 'all 0.3s ease', color: 'white'
|
||||
}}>
|
||||
{student.photo ? (
|
||||
<img src={student.photo} alt={student.name}
|
||||
<img src={normalizePhotoUrl(student.photo)} alt={student.name}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||
) : (
|
||||
student.name.charAt(0).toUpperCase()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* Helpers compartihados de UI
|
||||
*/
|
||||
export function normalizePhotoUrl(url) {
|
||||
export function normalizePhotoUrl(url?: string | null): string {
|
||||
if (!url || typeof url !== 'string') return '';
|
||||
if (url.startsWith('data:image')) return url;
|
||||
if (url.startsWith('/storage/')) return url;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export default function Financeiro() {
|
|||
overdue: { className: 'badge badge-danger', label: 'Atrasado' },
|
||||
cancelled: { className: 'badge badge-info', label: 'Cancelado' },
|
||||
};
|
||||
const s = map[norm] || { className: 'badge badge-info', label: status };
|
||||
const s = map[norm] || { className: 'badge badge-info', label: norm };
|
||||
return <span className={s.className}>{s.label}</span>;
|
||||
};
|
||||
|
||||
|
|
@ -362,7 +362,7 @@ export default function Financeiro() {
|
|||
>
|
||||
<Printer size={14} /> Visualizar Recibo
|
||||
</button>
|
||||
) : isPending(payment.status) && link ? (
|
||||
) : isPending(payment) && link ? (
|
||||
<a
|
||||
href={link}
|
||||
target="_blank"
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ export interface Notification {
|
|||
message: string;
|
||||
read: boolean;
|
||||
createdAt: string; // ISO string
|
||||
type?: 'info' | 'alert' | 'success' | 'danger';
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue