feat: implement 100% dynamic pre-enrollment routing based on database slug, allowing fully customizable clean URL paths
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 2m2s
Details
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 2m2s
Details
This commit is contained in:
parent
26796290a2
commit
9c1e604cb9
|
|
@ -229,14 +229,10 @@ const PreMatricula: React.FC<Props> = ({ data, onConvert }) => {
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-[10px] font-bold text-slate-500 uppercase mb-1">Slug do Link Personalizado</label>
|
<label className="block text-[10px] font-bold text-slate-500 uppercase mb-1">Slug do Link Personalizado</label>
|
||||||
<div className="flex items-center bg-slate-50 border border-slate-200 rounded-lg overflow-hidden">
|
<div className="flex items-center bg-slate-50 border border-slate-200 rounded-lg overflow-hidden">
|
||||||
<span className="px-3 text-xs text-slate-400 font-mono whitespace-nowrap">/pre-matricula-</span>
|
<span className="px-3 text-xs text-slate-400 font-mono whitespace-nowrap">/</span>
|
||||||
<input className="flex-1 px-2 py-3 bg-transparent focus:outline-none text-sm font-mono font-bold text-indigo-700"
|
<input className="flex-1 px-2 py-3 bg-transparent focus:outline-none text-sm font-mono font-bold text-indigo-700"
|
||||||
value={config?.slug ? config.slug.replace(/^pre-matricula-?/, '') : ''}
|
value={config?.slug || ''}
|
||||||
onChange={e => {
|
onChange={e => setConfig(prev => prev ? { ...prev, slug: e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, '') } : prev)}
|
||||||
const val = e.target.value.replace(/[^a-z0-9-]/g, '');
|
|
||||||
const newSlug = val ? `pre-matricula-${val}` : 'pre-matricula';
|
|
||||||
setConfig(prev => prev ? { ...prev, slug: newSlug } : prev);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3031,20 +3031,29 @@ async function startServer() {
|
||||||
// Rota com slug explícito
|
// Rota com slug explícito
|
||||||
app.get('/api/prematricula/public/:slug', (req, res) => handlePublicPreMatricula(req, res, req.params.slug));
|
app.get('/api/prematricula/public/:slug', (req, res) => handlePublicPreMatricula(req, res, req.params.slug));
|
||||||
|
|
||||||
// Rota que serve a página HTML pública do formulário de pré-matrícula
|
// Middleware para servir a página HTML pública de forma 100% dinâmica baseada na slug do banco
|
||||||
app.get('/pre-matricula', async (req, res) => {
|
app.use(async (req, res, next) => {
|
||||||
try {
|
// Ignorar APIs, Storage ou arquivos de assets estáticos (com extensão)
|
||||||
const { rows } = await pool.query('SELECT slug FROM prematricula_config WHERE id = 1');
|
if (req.path.startsWith('/api') || req.path.startsWith('/storage') || req.path.includes('.')) {
|
||||||
const slug = rows[0]?.slug || 'pre-matricula';
|
return next();
|
||||||
res.send(getPreMatriculaHTML(slug));
|
|
||||||
} catch (e) {
|
|
||||||
res.send(getPreMatriculaHTML('pre-matricula'));
|
|
||||||
}
|
}
|
||||||
});
|
const slug = req.path.substring(1); // Remove a primeira barra
|
||||||
|
if (!slug) return next();
|
||||||
|
|
||||||
app.get('/pre-matricula-:slug', (req, res) => {
|
try {
|
||||||
const { slug } = req.params;
|
// Verifica se a slug atual corresponde a alguma configuração de pré-matrícula publicada
|
||||||
res.send(getPreMatriculaHTML('pre-matricula-' + slug));
|
const { rows } = await pool.query(
|
||||||
|
'SELECT slug FROM prematricula_config WHERE slug = $1 AND status = $2 LIMIT 1',
|
||||||
|
[slug, 'published']
|
||||||
|
);
|
||||||
|
if (rows.length > 0) {
|
||||||
|
// Se bater, serve a página pública renderizando a slug dinâmica!
|
||||||
|
return res.send(getPreMatriculaHTML(slug));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[PreMatricula:Router] Erro de roteamento dinâmico:', e);
|
||||||
|
}
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ===================================================
|
// ===================================================
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue