mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-18 14:27:51 +00:00
Compare commits
16 Commits
1ea1b3e841
...
33b9b38ff4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33b9b38ff4 | ||
|
|
1bcb0a9c37 | ||
|
|
d2567ac478 | ||
|
|
953b7a78d0 | ||
|
|
21f7aa7c40 | ||
|
|
6e9d847c77 | ||
|
|
1542572be4 | ||
|
|
75d9d4635b | ||
|
|
a7612879bf | ||
|
|
00cd9edb1c | ||
|
|
a45ebd2719 | ||
|
|
6398e2ac81 | ||
|
|
0ccea7c7b9 | ||
|
|
9fa7b9732d | ||
|
|
6478d20d62 | ||
|
|
0e2215b6ad |
73
CHANGELOG.md
73
CHANGELOG.md
@ -5,6 +5,79 @@ Todas as mudanças notáveis neste projeto serão documentadas neste arquivo.
|
|||||||
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.0/),
|
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.0/),
|
||||||
e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/).
|
e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/).
|
||||||
|
|
||||||
|
## [1.4.1] - 2024-01-17
|
||||||
|
|
||||||
|
### Modificado
|
||||||
|
- Expandido conteúdo da Text Sales Letter:
|
||||||
|
- Adicionada explicação detalhada dos 5 pilares da alfabetização
|
||||||
|
- Incluídas seções sobre processo de implementação
|
||||||
|
- Melhorada apresentação de resultados e depoimentos
|
||||||
|
- Adicionadas estatísticas e dados do SAEB
|
||||||
|
- Aprimorada a estrutura visual com cards e ícones
|
||||||
|
- Expandido texto para mais de 5.000 palavras
|
||||||
|
|
||||||
|
### Técnico
|
||||||
|
- Adicionados novos ícones do Lucide React
|
||||||
|
- Implementados novos componentes visuais para métricas
|
||||||
|
- Melhorada a estrutura de grid e layout responsivo
|
||||||
|
- Otimizada a organização das seções de conteúdo
|
||||||
|
|
||||||
|
## [1.4.0] - 2024-01-17
|
||||||
|
|
||||||
|
### Adicionado
|
||||||
|
- Nova página Text Sales Letter focada em educação baseada em evidências
|
||||||
|
- Conteúdo detalhado sobre métodos científicos vs. pseudociências
|
||||||
|
- Rota `/evidencias/tsl` para acesso à nova página
|
||||||
|
- Seções estruturadas com dados estatísticos e evidências científicas
|
||||||
|
|
||||||
|
### Técnico
|
||||||
|
- Implementação de layout responsivo com Tailwind CSS
|
||||||
|
- Integração com sistema de navegação existente
|
||||||
|
- Otimização de SEO para conteúdo educacional
|
||||||
|
|
||||||
|
### Modificado
|
||||||
|
- Atualização da estrutura de rotas para incluir nova página
|
||||||
|
- Melhorias na organização do conteúdo sobre evidências científicas
|
||||||
|
|
||||||
|
## [1.3.0] - 2024-01-17
|
||||||
|
|
||||||
|
### Adicionado
|
||||||
|
- Novo componente reutilizável `FAQ` com layout simplificado
|
||||||
|
- Implementação do FAQ em todas as Landing Pages com conteúdo específico:
|
||||||
|
- Para Pais: foco em funcionalidades e benefícios para as crianças
|
||||||
|
- Para Educadores: ênfase em recursos pedagógicos e suporte
|
||||||
|
- Evidências: destaque para base científica e metodologia
|
||||||
|
- HomePage: foco em implementação e suporte para escolas
|
||||||
|
|
||||||
|
### Técnico
|
||||||
|
- Criação de interfaces TypeScript para tipagem do FAQ
|
||||||
|
- Implementação de estilos consistentes com Tailwind CSS
|
||||||
|
- Remoção da dependência do Radix UI Accordion
|
||||||
|
|
||||||
|
### Modificado
|
||||||
|
- Substituição das seções de FAQ existentes pelo novo componente reutilizável
|
||||||
|
- Atualização da estrutura de navegação nas Landing Pages
|
||||||
|
- Melhoria na organização do código com componentização
|
||||||
|
|
||||||
|
## [1.2.0] - 2024-01-17
|
||||||
|
|
||||||
|
### Adicionado
|
||||||
|
- Novo componente reutilizável `FAQ` usando Accordion do Radix UI
|
||||||
|
- Implementação do FAQ em todas as Landing Pages com conteúdo específico:
|
||||||
|
- Para Pais: foco em funcionalidades e benefícios para as crianças
|
||||||
|
- Para Educadores: ênfase em recursos pedagógicos e suporte
|
||||||
|
- Evidências: destaque para base científica e metodologia
|
||||||
|
|
||||||
|
### Técnico
|
||||||
|
- Criação de interfaces TypeScript para tipagem do FAQ
|
||||||
|
- Integração com Radix UI Accordion para acessibilidade
|
||||||
|
- Implementação de animações suaves na expansão/contração
|
||||||
|
|
||||||
|
### Modificado
|
||||||
|
- Substituição das seções de FAQ existentes pelo novo componente reutilizável
|
||||||
|
- Atualização da estrutura de navegação nas Landing Pages
|
||||||
|
- Melhoria na organização do código com componentização
|
||||||
|
|
||||||
## [1.1.1] - 2024-01-17
|
## [1.1.1] - 2024-01-17
|
||||||
|
|
||||||
### Técnico
|
### Técnico
|
||||||
|
|||||||
30
netlify.toml
30
netlify.toml
@ -21,7 +21,35 @@
|
|||||||
X-XSS-Protection = "1; mode=block"
|
X-XSS-Protection = "1; mode=block"
|
||||||
X-Content-Type-Options = "nosniff"
|
X-Content-Type-Options = "nosniff"
|
||||||
Referrer-Policy = "strict-origin-when-cross-origin"
|
Referrer-Policy = "strict-origin-when-cross-origin"
|
||||||
Content-Security-Policy = "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
|
Cross-Origin-Embedder-Policy = "credentialless"
|
||||||
|
Cross-Origin-Opener-Policy = "same-origin"
|
||||||
|
Cross-Origin-Resource-Policy = "cross-origin"
|
||||||
|
Content-Security-Policy = """
|
||||||
|
default-src 'self';
|
||||||
|
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.rudderlabs.com https://*.cloudfront.net https://www.googletagmanager.com https://*.sentry.io;
|
||||||
|
connect-src 'self' https://*.rudderlabs.com https://*.ingest.sentry.io https://*.supabase.co https://www.google-analytics.com https://*.dataplane.rudderstack.com https://*.bugsnag.com/ https://*.ingest.us.sentry.io/ https://*.sentry.io/;
|
||||||
|
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
|
||||||
|
img-src 'self' data: https: blob:;
|
||||||
|
font-src 'self' data: https://fonts.gstatic.com;
|
||||||
|
frame-src 'self' https://www.googletagmanager.com;
|
||||||
|
worker-src 'self' blob:;
|
||||||
|
"""
|
||||||
|
Access-Control-Allow-Origin = "*"
|
||||||
|
Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, OPTIONS"
|
||||||
|
Access-Control-Allow-Headers = """
|
||||||
|
Authorization,
|
||||||
|
Content-Type,
|
||||||
|
Accept,
|
||||||
|
Origin,
|
||||||
|
User-Agent,
|
||||||
|
DNT,
|
||||||
|
Cache-Control,
|
||||||
|
X-Mx-ReqToken,
|
||||||
|
Keep-Alive,
|
||||||
|
X-Requested-With,
|
||||||
|
If-Modified-Since
|
||||||
|
"""
|
||||||
|
Access-Control-Max-Age = "3600"
|
||||||
|
|
||||||
[dev]
|
[dev]
|
||||||
command = "npm run dev"
|
command = "npm run dev"
|
||||||
|
|||||||
108
package-lock.json
generated
108
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.4",
|
"@radix-ui/react-dialog": "^1.1.4",
|
||||||
"@radix-ui/react-tabs": "^1.1.2",
|
"@radix-ui/react-tabs": "^1.1.2",
|
||||||
"@radix-ui/react-toast": "^1.2.4",
|
"@radix-ui/react-toast": "^1.2.4",
|
||||||
|
"@sentry/react": "^8.48.0",
|
||||||
"@supabase/supabase-js": "^2.39.7",
|
"@supabase/supabase-js": "^2.39.7",
|
||||||
"@tanstack/react-query": "^5.62.8",
|
"@tanstack/react-query": "^5.62.8",
|
||||||
"@testing-library/react": "^16.1.0",
|
"@testing-library/react": "^16.1.0",
|
||||||
@ -2556,6 +2557,98 @@
|
|||||||
"url": "https://ko-fi.com/killymxi"
|
"url": "https://ko-fi.com/killymxi"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@sentry-internal/browser-utils": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-pLtu0Fa1Ou0v3M1OEO1MB1EONJVmXEGtoTwFRCO1RPQI2ulmkG6BikINClFG5IBpoYKZ33WkEXuM6U5xh+pdZg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/core": "8.48.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry-internal/feedback": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-6PwcJNHVPg0EfZxmN+XxVOClfQpv7MBAweV8t9i5l7VFr8sM/7wPNSeU/cG7iK19Ug9ZEkBpzMOe3G4GXJ5bpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/core": "8.48.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry-internal/replay": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-csILVupc5RkrsTrncuUTGmlB56FQSFjXPYWG8I8yBTGlXEJ+o8oTuF6+55R4vbw3EIzBveXWi4kEBbnQlXW/eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry-internal/browser-utils": "8.48.0",
|
||||||
|
"@sentry/core": "8.48.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry-internal/replay-canvas": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-LdivLfBXXB9us1aAc6XaL7/L2Ob4vi3C/fEOXElehg3qHjX6q6pewiv5wBvVXGX1NfZTRvu+X11k6TZoxKsezw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry-internal/replay": "8.48.0",
|
||||||
|
"@sentry/core": "8.48.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/browser": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-fuuVULB5/1vI8NoIwXwR3xwhJJqk+y4RdSdajExGF7nnUDBpwUJyXsmYJnOkBO+oLeEs58xaCpotCKiPUNnE3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry-internal/browser-utils": "8.48.0",
|
||||||
|
"@sentry-internal/feedback": "8.48.0",
|
||||||
|
"@sentry-internal/replay": "8.48.0",
|
||||||
|
"@sentry-internal/replay-canvas": "8.48.0",
|
||||||
|
"@sentry/core": "8.48.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/core": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-VGwYgTfLpvJ5LRO5A+qWo1gpo6SfqaGXL9TOzVgBucAdpzbrYHpZ87sEarDVq/4275uk1b0S293/mfsskFczyw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sentry/react": {
|
||||||
|
"version": "8.48.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.48.0.tgz",
|
||||||
|
"integrity": "sha512-J8XAUOJYbsjXnowTEXE+zWJWLWUzQGP8kMb+smoGdRzFJwwXKrbE709Kr/Boz6rK48EbbRT4UUINoTbHgL3RHQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/browser": "8.48.0",
|
||||||
|
"@sentry/core": "8.48.0",
|
||||||
|
"hoist-non-react-statics": "^3.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.14.0 || 17.x || 18.x || 19.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.27.8",
|
"version": "0.27.8",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||||
@ -5565,6 +5658,21 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hoist-non-react-statics": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"react-is": "^16.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hoist-non-react-statics/node_modules/react-is": {
|
||||||
|
"version": "16.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/html-to-text": {
|
"node_modules/html-to-text": {
|
||||||
"version": "9.0.5",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.1.4",
|
"@radix-ui/react-dialog": "^1.1.4",
|
||||||
"@radix-ui/react-tabs": "^1.1.2",
|
"@radix-ui/react-tabs": "^1.1.2",
|
||||||
"@radix-ui/react-toast": "^1.2.4",
|
"@radix-ui/react-toast": "^1.2.4",
|
||||||
|
"@sentry/react": "^8.48.0",
|
||||||
"@supabase/supabase-js": "^2.39.7",
|
"@supabase/supabase-js": "^2.39.7",
|
||||||
"@tanstack/react-query": "^5.62.8",
|
"@tanstack/react-query": "^5.62.8",
|
||||||
"@testing-library/react": "^16.1.0",
|
"@testing-library/react": "^16.1.0",
|
||||||
|
|||||||
39
src/components/analytics/GoogleTagManager.tsx
Normal file
39
src/components/analytics/GoogleTagManager.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface GoogleTagManagerProps {
|
||||||
|
gtmId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GoogleTagManager({ gtmId }: GoogleTagManagerProps) {
|
||||||
|
React.useEffect(() => {
|
||||||
|
// Carrega o script do GTM
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.innerHTML = `
|
||||||
|
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||||
|
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||||
|
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||||
|
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||||
|
})(window,document,'script','dataLayer','${gtmId}');
|
||||||
|
`;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
// Adiciona o noscript iframe
|
||||||
|
const noscript = document.createElement('noscript');
|
||||||
|
const iframe = document.createElement('iframe');
|
||||||
|
iframe.src = `https://www.googletagmanager.com/ns.html?id=${gtmId}`;
|
||||||
|
iframe.height = '0';
|
||||||
|
iframe.width = '0';
|
||||||
|
iframe.style.display = 'none';
|
||||||
|
iframe.style.visibility = 'hidden';
|
||||||
|
noscript.appendChild(iframe);
|
||||||
|
document.body.insertBefore(noscript, document.body.firstChild);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// Cleanup
|
||||||
|
document.head.removeChild(script);
|
||||||
|
document.body.removeChild(noscript);
|
||||||
|
};
|
||||||
|
}, [gtmId]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
20
src/components/analytics/PageTracker.tsx
Normal file
20
src/components/analytics/PageTracker.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useRudderstack } from '../../hooks/useRudderstack';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
export function PageTracker() {
|
||||||
|
const location = useLocation();
|
||||||
|
const { track } = useRudderstack();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
track('page_viewed', {
|
||||||
|
path: location.pathname,
|
||||||
|
url: window.location.href,
|
||||||
|
search: location.search,
|
||||||
|
title: document.title,
|
||||||
|
referrer: document.referrer,
|
||||||
|
});
|
||||||
|
}, [location, track]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
83
src/components/analytics/RudderstackAnalytics.tsx
Normal file
83
src/components/analytics/RudderstackAnalytics.tsx
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface RudderstackAnalyticsProps {
|
||||||
|
writeKey: string;
|
||||||
|
dataPlaneUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
rudderanalytics: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RudderstackAnalytics({ writeKey, dataPlaneUrl }: RudderstackAnalyticsProps) {
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (window.rudderanalytics?.loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa o objeto rudderanalytics
|
||||||
|
window.rudderanalytics = window.rudderanalytics || [];
|
||||||
|
|
||||||
|
// Define os métodos básicos
|
||||||
|
const methods = ['load', 'page', 'track', 'identify', 'alias', 'group', 'ready', 'reset'];
|
||||||
|
methods.forEach((method) => {
|
||||||
|
window.rudderanalytics[method] = function() {
|
||||||
|
window.rudderanalytics.push([method].concat(Array.prototype.slice.call(arguments)));
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Carrega o script do Rudderstack
|
||||||
|
const loadScript = () => {
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = 'https://cdn.rudderlabs.com/v1.1/rudder-analytics.min.js';
|
||||||
|
script.async = true;
|
||||||
|
script.crossOrigin = 'anonymous';
|
||||||
|
|
||||||
|
script.onload = () => {
|
||||||
|
window.rudderanalytics.load(writeKey, dataPlaneUrl, {
|
||||||
|
configUrl: 'https://api.rudderlabs.com',
|
||||||
|
destSDKBaseURL: 'https://cdn.rudderlabs.com/v1.1',
|
||||||
|
logLevel: 'ERROR',
|
||||||
|
secureCookie: true,
|
||||||
|
integrations: { All: true },
|
||||||
|
loadIntegration: true,
|
||||||
|
sendAdblockPage: true,
|
||||||
|
sendAdblockPageOptions: {
|
||||||
|
integrations: { All: true }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
script.onerror = (error) => {
|
||||||
|
console.error('Erro ao carregar Rudderstack:', error);
|
||||||
|
reject(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.head.appendChild(script);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Carrega o script e inicializa
|
||||||
|
loadScript()
|
||||||
|
.then(() => {
|
||||||
|
window.rudderanalytics.page();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Falha ao inicializar Rudderstack:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const script = document.querySelector('script[src*="rudder-analytics.min.js"]');
|
||||||
|
if (script && script.parentNode) {
|
||||||
|
script.parentNode.removeChild(script);
|
||||||
|
}
|
||||||
|
delete window.rudderanalytics;
|
||||||
|
};
|
||||||
|
}, [writeKey, dataPlaneUrl]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@ -57,6 +57,12 @@ export function AudioUploader({
|
|||||||
as="span"
|
as="span"
|
||||||
disabled={isProcessing}
|
disabled={isProcessing}
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
|
trackingId="audio-upload-button"
|
||||||
|
trackingProperties={{
|
||||||
|
category: 'audio',
|
||||||
|
action: 'upload_click',
|
||||||
|
label: 'audio_uploader'
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{isProcessing ? 'Processando...' : 'Enviar Áudio'}
|
{isProcessing ? 'Processando...' : 'Enviar Áudio'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { LogIn, Eye, EyeOff, School, GraduationCap, User } from 'lucide-react';
|
import { LogIn, Eye, EyeOff, School, GraduationCap, User } from 'lucide-react';
|
||||||
import { useAuth } from '../../hooks/useAuth';
|
import { useAuth } from '../../hooks/useAuth';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { supabase } from '../../lib/supabase';
|
import { supabase } from '../../lib/supabase';
|
||||||
|
import { useDataLayer } from '../../hooks/useDataLayer';
|
||||||
|
import { useFormTracking } from '../../hooks/useFormTracking';
|
||||||
|
import { Button } from '../ui/button';
|
||||||
|
import { useErrorTracking } from '../../hooks/useErrorTracking';
|
||||||
|
|
||||||
interface LoginFormProps {
|
interface LoginFormProps {
|
||||||
userType: 'school' | 'teacher' | 'student';
|
userType: 'school' | 'teacher' | 'student';
|
||||||
@ -30,6 +34,20 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { signIn } = useAuth();
|
const { signIn } = useAuth();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { trackEvent } = useDataLayer();
|
||||||
|
const formTracking = useFormTracking({
|
||||||
|
formId: 'login-form',
|
||||||
|
formName: `${userType}-login`,
|
||||||
|
category: 'auth'
|
||||||
|
});
|
||||||
|
const errorTracking = useErrorTracking({
|
||||||
|
category: 'auth',
|
||||||
|
userEmail: email
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
formTracking.trackFormStarted();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -46,10 +64,21 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
|
|
||||||
console.log('Resposta do Supabase:', { data, error });
|
console.log('Resposta do Supabase:', { data, error });
|
||||||
|
|
||||||
if (error) throw error;
|
if (error) {
|
||||||
|
errorTracking.trackApiError(error, '/auth/sign-in', 'POST', { email, userType });
|
||||||
|
formTracking.trackFormError('auth_error', error.message);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
if (!data.user) {
|
if (!data.user) {
|
||||||
throw new Error('Usuário não encontrado');
|
const err = new Error('Usuário não encontrado');
|
||||||
|
errorTracking.trackError(err, {
|
||||||
|
componentName: 'LoginForm',
|
||||||
|
action: 'login_attempt',
|
||||||
|
metadata: { userType }
|
||||||
|
});
|
||||||
|
formTracking.trackFormError('user_not_found', 'Usuário não encontrado');
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userRole = data.user.user_metadata.role;
|
const userRole = data.user.user_metadata.role;
|
||||||
@ -58,9 +87,24 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
console.log('Role atual:', userRole);
|
console.log('Role atual:', userRole);
|
||||||
|
|
||||||
if (userRole !== userType) {
|
if (userRole !== userType) {
|
||||||
throw new Error(`Este não é um login de ${userTypeLabels[userType]}`);
|
const err = new Error(`Este não é um login de ${userTypeLabels[userType]}`);
|
||||||
|
errorTracking.trackError(err, {
|
||||||
|
componentName: 'LoginForm',
|
||||||
|
action: 'role_validation',
|
||||||
|
metadata: {
|
||||||
|
expectedRole: userType,
|
||||||
|
actualRole: userRole
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formTracking.trackFormError('invalid_role', err.message);
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formTracking.trackFormSubmitted(true, {
|
||||||
|
user_type: userType,
|
||||||
|
user_id: data.user.id
|
||||||
|
});
|
||||||
|
|
||||||
switch (userType) {
|
switch (userType) {
|
||||||
case 'school':
|
case 'school':
|
||||||
navigate('/dashboard');
|
navigate('/dashboard');
|
||||||
@ -75,18 +119,36 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
throw new Error('Tipo de usuário inválido');
|
throw new Error('Tipo de usuário inválido');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackEvent('auth', 'login_success', 'form');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Erro no login:', err);
|
console.error('Erro no login:', err);
|
||||||
if (err instanceof Error) {
|
const errorMessage = err instanceof Error ? err.message : 'Email ou senha incorretos';
|
||||||
setError(err.message);
|
setError(errorMessage);
|
||||||
} else {
|
|
||||||
setError('Email ou senha incorretos');
|
formTracking.trackFormSubmitted(false, {
|
||||||
}
|
error_type: err instanceof Error ? 'validation_error' : 'unknown_error',
|
||||||
|
error_message: errorMessage
|
||||||
|
});
|
||||||
|
trackEvent('auth', 'login_error', errorMessage);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleFieldChange = (field: string, value: string) => {
|
||||||
|
formTracking.trackFieldInteraction(field, 'change');
|
||||||
|
if (field === 'email') setEmail(value);
|
||||||
|
if (field === 'password') setPassword(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFieldFocus = (field: string) => {
|
||||||
|
formTracking.trackFieldInteraction(field, 'focus');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFieldBlur = (field: string) => {
|
||||||
|
formTracking.trackFieldInteraction(field, 'blur');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-b from-purple-50 to-white py-12">
|
<div className="min-h-screen bg-gradient-to-b from-purple-50 to-white py-12">
|
||||||
<div className="max-w-md mx-auto px-4">
|
<div className="max-w-md mx-auto px-4">
|
||||||
@ -119,7 +181,9 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
type="email"
|
type="email"
|
||||||
required
|
required
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => handleFieldChange('email', e.target.value)}
|
||||||
|
onFocus={() => handleFieldFocus('email')}
|
||||||
|
onBlur={() => handleFieldBlur('email')}
|
||||||
className="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
className="mt-1 block w-full rounded-lg border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -134,7 +198,9 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
type={showPassword ? 'text' : 'password'}
|
type={showPassword ? 'text' : 'password'}
|
||||||
required
|
required
|
||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => handleFieldChange('password', e.target.value)}
|
||||||
|
onFocus={() => handleFieldFocus('password')}
|
||||||
|
onBlur={() => handleFieldBlur('password')}
|
||||||
className="block w-full rounded-lg border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500 pr-10"
|
className="block w-full rounded-lg border-gray-300 shadow-sm focus:border-purple-500 focus:ring-purple-500 pr-10"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@ -151,32 +217,49 @@ export function LoginForm({ userType, onLogin, onRegisterClick }: LoginFormProps
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="w-full flex justify-center items-center gap-2 py-3 px-4 border border-transparent rounded-lg shadow-sm text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 disabled:opacity-50"
|
trackingId="login-submit"
|
||||||
|
variant="primary"
|
||||||
|
size="lg"
|
||||||
|
trackingProperties={{
|
||||||
|
category: 'auth',
|
||||||
|
action: 'login_attempt',
|
||||||
|
label: `${userType}_login`,
|
||||||
|
value: 1,
|
||||||
|
}}
|
||||||
|
className="w-full"
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
'Entrando...'
|
'Entrando...'
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<LogIn className="h-5 w-5" />
|
<LogIn className="h-5 w-5 mr-2" />
|
||||||
Entrar
|
Entrar
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{onRegisterClick && (
|
{onRegisterClick && (
|
||||||
<div className="mt-6 text-center">
|
<div className="mt-6 text-center">
|
||||||
<p className="text-sm text-gray-600">
|
<p className="text-sm text-gray-600">
|
||||||
Ainda não tem uma conta?{' '}
|
Ainda não tem uma conta?{' '}
|
||||||
<button
|
<Button
|
||||||
|
trackingId="register-link"
|
||||||
|
variant="link"
|
||||||
|
size="sm"
|
||||||
onClick={onRegisterClick}
|
onClick={onRegisterClick}
|
||||||
className="text-purple-600 hover:text-purple-500 font-medium"
|
trackingProperties={{
|
||||||
|
category: 'auth',
|
||||||
|
action: 'register_click',
|
||||||
|
label: userType,
|
||||||
|
}}
|
||||||
|
className="text-purple-600 hover:text-purple-500 font-medium p-0"
|
||||||
>
|
>
|
||||||
Cadastre-se
|
Cadastre-se
|
||||||
</button>
|
</Button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -4,53 +4,17 @@ import {
|
|||||||
BookOpen, ArrowRight, School, Users, Shield,
|
BookOpen, ArrowRight, School, Users, Shield,
|
||||||
Sparkles, BookCheck, Play, CheckCircle, Star,
|
Sparkles, BookCheck, Play, CheckCircle, Star,
|
||||||
GraduationCap, BarChart, Brain, X, Check,
|
GraduationCap, BarChart, Brain, X, Check,
|
||||||
Pencil,
|
Pencil, Wand, Mic, Share2
|
||||||
Wand,
|
|
||||||
Mic,
|
|
||||||
Share2
|
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { Footer } from '@/components/ui/footer';
|
import { Footer } from '@/components/ui/footer';
|
||||||
import { PlanForSchools } from '@/components/ui/plan-for-schools';
|
import { PlanForSchools } from '@/components/ui/plan-for-schools';
|
||||||
|
import { FAQ } from '@/components/ui/faq';
|
||||||
// Components
|
import { StatCard } from '@/components/ui/stat-card';
|
||||||
const FeatureCard = ({ icon, title, description }: {
|
import { TestimonialCard } from '@/components/ui/testimonial-card';
|
||||||
icon: React.ReactNode;
|
import { FeatureCard } from '@/components/ui/feature-card';
|
||||||
title: string;
|
import { ProcessStep } from '@/components/ui/process-step';
|
||||||
description: string;
|
import { InfoCard } from '@/components/ui/info-card';
|
||||||
}) => (
|
import { ComparisonSection } from '@/components/ui/comparison-section';
|
||||||
<div className="p-6 rounded-xl border border-gray-200 hover:shadow-lg transition bg-white">
|
|
||||||
<div className="w-12 h-12 rounded-lg bg-purple-100 flex items-center justify-center mb-4">
|
|
||||||
<div className="text-purple-600">{icon}</div>
|
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-semibold text-gray-900 mb-2">{title}</h3>
|
|
||||||
<p className="text-gray-600">{description}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const StatCard = ({ number, label }: { number: string; label: string }) => (
|
|
||||||
<div className="p-6">
|
|
||||||
<div className="text-4xl font-bold mb-2">{number}</div>
|
|
||||||
<div className="text-purple-200">{label}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const TestimonialCard = ({ quote, author, role, image }: {
|
|
||||||
quote: string;
|
|
||||||
author: string;
|
|
||||||
role: string;
|
|
||||||
image: string;
|
|
||||||
}) => (
|
|
||||||
<div className="p-6 rounded-xl bg-white shadow-md">
|
|
||||||
<div className="flex items-center gap-4 mb-4">
|
|
||||||
<img src={image} alt={author} className="w-12 h-12 rounded-full" />
|
|
||||||
<div>
|
|
||||||
<div className="font-semibold text-gray-900">{author}</div>
|
|
||||||
<div className="text-sm text-gray-600">{role}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-600 italic">"{quote}"</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{ name: 'Início', href: '/' },
|
{ name: 'Início', href: '/' },
|
||||||
@ -130,7 +94,7 @@ export function HomePage() {
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<div className="pt-32 pb-20 px-4 sm:px-6 lg:px-8">
|
<div className="pt-32 pb-24 px-4 sm:px-6 lg:px-8">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||||
<div>
|
<div>
|
||||||
@ -200,7 +164,7 @@ export function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Student Journey Section */}
|
{/* Student Journey Section */}
|
||||||
<div className="py-20 bg-gradient-to-b from-purple-50 to-white">
|
<div className="py-24 bg-gradient-to-b from-purple-50 to-white">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
||||||
@ -211,136 +175,77 @@ export function HomePage() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative">
|
<div className="space-y-12">
|
||||||
{/* Timeline Line */}
|
<ProcessStep
|
||||||
<div className="hidden md:block absolute left-1/2 transform -translate-x-1/2 h-full w-0.5 bg-purple-200" />
|
number={1}
|
||||||
|
title="Escolha o tema da aventura"
|
||||||
|
description="Selecione entre diversos temas educativos alinhados com a BNCC e adequados à idade."
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Timeline Items */}
|
<ProcessStep
|
||||||
{[
|
number={2}
|
||||||
{
|
title="Personalize os personagens"
|
||||||
icon: <Pencil className="w-6 h-6" />,
|
description="Crie personagens que seu filho vai adorar, com características únicas e cativantes."
|
||||||
title: "Criação Personalizada",
|
/>
|
||||||
description: "O aluno cria uma história baseada em seus interesses e características pessoais",
|
|
||||||
image: "/journey/create-story.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <Wand className="w-6 h-6" />,
|
|
||||||
title: "Geração por IA",
|
|
||||||
description: "Nossa IA avançada gera uma história única e personalizada",
|
|
||||||
image: "/journey/ai-generation.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <Mic className="w-6 h-6" />,
|
|
||||||
title: "Gravação de Áudio",
|
|
||||||
description: "O aluno grava sua voz lendo a história criada",
|
|
||||||
image: "/journey/audio-recording.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <BarChart className="w-6 h-6" />,
|
|
||||||
title: "Análise de Leitura",
|
|
||||||
description: "A IA analisa a leitura e fornece feedback detalhado sobre o desempenho",
|
|
||||||
image: "/journey/reading-analysis.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: <Share2 className="w-6 h-6" />,
|
|
||||||
title: "Compartilhamento de Resultados",
|
|
||||||
description: "Dados e insights são compartilhados com pais, professores e escola",
|
|
||||||
image: "/journey/share-results.png"
|
|
||||||
}
|
|
||||||
].map((item, index) => (
|
|
||||||
<div key={index} className={`mb-12 md:mb-24 relative ${
|
|
||||||
index % 2 === 0 ? 'md:text-right' : ''
|
|
||||||
}`}>
|
|
||||||
<div className={`flex items-center gap-8 ${
|
|
||||||
index % 2 === 0 ? 'md:flex-row-reverse' : ''
|
|
||||||
}`}>
|
|
||||||
{/* Content Side */}
|
|
||||||
<div className="flex-1">
|
|
||||||
<div className={`bg-white rounded-xl shadow-lg p-6 transform transition-all duration-300 hover:scale-105 ${
|
|
||||||
index % 2 === 0 ? 'md:ml-auto' : ''
|
|
||||||
}`}>
|
|
||||||
<div className="flex items-center gap-4 mb-4">
|
|
||||||
<div className="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center text-purple-600">
|
|
||||||
{item.icon}
|
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-semibold text-gray-900">
|
|
||||||
{item.title}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-600">
|
|
||||||
{item.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Timeline Marker */}
|
<ProcessStep
|
||||||
<div className="hidden md:flex items-center justify-center">
|
number={3}
|
||||||
<div className="w-12 h-12 rounded-full bg-purple-600 text-white flex items-center justify-center font-bold">
|
title="A IA cria a história mágica"
|
||||||
{index + 1}
|
description="Nossa IA educacional gera uma história personalizada em segundos."
|
||||||
</div>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Image Side */}
|
<ProcessStep
|
||||||
<div className="flex-1 hidden md:block">
|
number={4}
|
||||||
<img
|
title="A aventura educativa começa"
|
||||||
src={item.image}
|
description="Seu filho mergulha em uma jornada mágica de aprendizado e diversão."
|
||||||
alt={item.title}
|
/>
|
||||||
className="rounded-xl shadow-lg w-full max-w-md mx-auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Results Summary */}
|
|
||||||
<div className="mt-16 bg-white rounded-xl shadow-lg p-8">
|
|
||||||
<div className="text-center mb-8">
|
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-2">
|
|
||||||
Resultados Comprovados
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600">
|
|
||||||
Nossa abordagem inovadora tem transformado a experiência de leitura
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-4 gap-8">
|
|
||||||
{[
|
|
||||||
{
|
|
||||||
number: "95%",
|
|
||||||
label: "Melhoria na fluência de leitura"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
number: "87%",
|
|
||||||
label: "Aumento no engajamento"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
number: "92%",
|
|
||||||
label: "Satisfação dos pais"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
number: "3x",
|
|
||||||
label: "Mais histórias lidas por aluno"
|
|
||||||
}
|
|
||||||
].map((stat, index) => (
|
|
||||||
<div key={index} className="text-center">
|
|
||||||
<div className="text-3xl font-bold text-purple-600 mb-2">
|
|
||||||
{stat.number}
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-600 text-sm">
|
|
||||||
{stat.label}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Features Grid */}
|
{/* Results Summary */}
|
||||||
<div className="py-20 bg-white">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="mt-24 bg-white rounded-xl shadow-lg p-8">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-8">
|
||||||
|
<h3 className="text-2xl font-bold text-gray-900 mb-2">
|
||||||
|
Resultados Comprovados
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
Nossa abordagem inovadora tem transformado a experiência de leitura
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-4 gap-8">
|
||||||
|
<StatCard
|
||||||
|
icon={Star}
|
||||||
|
title="Fluência de Leitura"
|
||||||
|
value="95%"
|
||||||
|
description="Melhoria na fluência de leitura dos alunos"
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={Sparkles}
|
||||||
|
title="Engajamento"
|
||||||
|
value="87%"
|
||||||
|
description="Aumento no engajamento com a leitura"
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={CheckCircle}
|
||||||
|
title="Satisfação"
|
||||||
|
value="92%"
|
||||||
|
description="Satisfação dos pais com o progresso"
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={BookOpen}
|
||||||
|
title="Leitura"
|
||||||
|
value="3x"
|
||||||
|
description="Mais histórias lidas por aluno"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Features Grid */}
|
||||||
|
<div className="mt-24">
|
||||||
|
<div className="text-center mb-12">
|
||||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
||||||
Tecnologia e Educação em Harmonia
|
Tecnologia e Educação em Harmonia
|
||||||
</h2>
|
</h2>
|
||||||
@ -350,148 +255,152 @@ export function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon={<Brain />}
|
icon={Brain}
|
||||||
title="IA Adaptativa"
|
title="IA Adaptativa"
|
||||||
description="Conteúdo que se adapta ao ritmo e estilo de aprendizagem de cada aluno"
|
description="Conteúdo que se adapta ao ritmo e estilo de aprendizagem de cada aluno"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon={<BookOpen />}
|
icon={BookOpen}
|
||||||
title="Histórias Interativas"
|
title="Histórias Interativas"
|
||||||
description="Narrativas envolventes que tornam o aprendizado mais divertido e eficaz"
|
description="Narrativas envolventes que tornam o aprendizado mais divertido e eficaz"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon={<BarChart />}
|
icon={BarChart}
|
||||||
title="Analytics Avançado"
|
title="Analytics Avançado"
|
||||||
description="Insights detalhados sobre o progresso e engajamento dos alunos"
|
description="Insights detalhados sobre o progresso e engajamento dos alunos"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon={<Users />}
|
icon={Users}
|
||||||
title="Colaboração"
|
title="Colaboração"
|
||||||
description="Ferramentas para professores trabalharem juntos e compartilharem recursos"
|
description="Ferramentas para professores trabalharem juntos e compartilharem recursos"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon={<Shield />}
|
icon={Shield}
|
||||||
title="Ambiente Seguro"
|
title="Ambiente Seguro"
|
||||||
description="Proteção de dados e conteúdo adequado para todas as idades"
|
description="Proteção de dados e conteúdo adequado para todas as idades"
|
||||||
/>
|
/>
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
icon={<GraduationCap />}
|
icon={GraduationCap}
|
||||||
title="Suporte Pedagógico"
|
title="Suporte Pedagógico"
|
||||||
description="Recursos e orientações para maximizar o potencial de aprendizagem"
|
description="Recursos e orientações para maximizar o potencial de aprendizagem"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Before & After Section */}
|
{/* Before & After Section */}
|
||||||
<div className="py-20 bg-white">
|
<div className="mt-24">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<ComparisonSection
|
||||||
<div className="text-center mb-16">
|
title="Compare a Transformação"
|
||||||
<h2 className="text-3xl font-bold text-gray-900 mb-4">
|
items={[
|
||||||
Transforme a Experiência de Aprendizagem
|
{
|
||||||
</h2>
|
title: "Personalização",
|
||||||
<p className="text-gray-600 max-w-2xl mx-auto">
|
without: [
|
||||||
Veja como o Histórias Mágicas revoluciona o ensino
|
"Conteúdo padronizado que não atende necessidades individuais",
|
||||||
</p>
|
"Material didático tradicional e pouco envolvente",
|
||||||
</div>
|
"Mesma abordagem para todos os alunos"
|
||||||
|
],
|
||||||
<div className="grid md:grid-cols-2 gap-16">
|
with: [
|
||||||
{/* Before */}
|
"Histórias adaptativas que evoluem com cada aluno",
|
||||||
<div className="rounded-2xl bg-red-50 p-8">
|
"Conteúdo personalizado e envolvente",
|
||||||
<div className="flex items-center gap-3 mb-6">
|
"Experiência única para cada estudante"
|
||||||
<div className="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center">
|
]
|
||||||
<X className="w-6 h-6 text-red-600" />
|
},
|
||||||
</div>
|
{
|
||||||
<h3 className="text-2xl font-semibold text-gray-900">Antes</h3>
|
title: "Engajamento",
|
||||||
</div>
|
without: [
|
||||||
<ul className="space-y-4">
|
"Alunos desmotivados com atividades repetitivas",
|
||||||
{[
|
"Baixo interesse nas atividades de leitura",
|
||||||
'Conteúdo padronizado que não atende necessidades individuais',
|
"Dificuldade em manter a atenção dos alunos"
|
||||||
'Alunos desmotivados com material didático tradicional',
|
],
|
||||||
'Professores sobrecarregados com correções manuais',
|
with: [
|
||||||
'Dificuldade em acompanhar o progresso individual',
|
"Estudantes engajados e participativos",
|
||||||
'Baixo engajamento nas atividades de leitura e escrita',
|
"Aumento de 300% no engajamento com leitura",
|
||||||
'Falta de dados para tomada de decisão pedagógica'
|
"Alunos ansiosos pela próxima atividade"
|
||||||
].map((item, index) => (
|
]
|
||||||
<li key={index} className="flex items-start gap-3">
|
},
|
||||||
<div className="mt-1">
|
{
|
||||||
<X className="w-5 h-5 text-red-600" />
|
title: "Acompanhamento",
|
||||||
</div>
|
without: [
|
||||||
<span className="text-gray-600">{item}</span>
|
"Professores sobrecarregados com correções manuais",
|
||||||
</li>
|
"Dificuldade em acompanhar o progresso individual",
|
||||||
))}
|
"Falta de dados para decisões pedagógicas"
|
||||||
</ul>
|
],
|
||||||
</div>
|
with: [
|
||||||
|
"Correção automática com feedback instantâneo",
|
||||||
{/* After */}
|
"Dashboard em tempo real do progresso individual",
|
||||||
<div className="rounded-2xl bg-green-50 p-8">
|
"Insights precisos para intervenções pedagógicas"
|
||||||
<div className="flex items-center gap-3 mb-6">
|
]
|
||||||
<div className="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center">
|
}
|
||||||
<Check className="w-6 h-6 text-green-600" />
|
]}
|
||||||
</div>
|
/>
|
||||||
<h3 className="text-2xl font-semibold text-gray-900">Depois</h3>
|
|
||||||
</div>
|
|
||||||
<ul className="space-y-4">
|
|
||||||
{[
|
|
||||||
'Histórias adaptativas que evoluem com cada aluno',
|
|
||||||
'Estudantes engajados com conteúdo personalizado',
|
|
||||||
'Correção automática com feedback instantâneo',
|
|
||||||
'Dashboard em tempo real do progresso individual',
|
|
||||||
'Aumento de 300% no engajamento com leitura',
|
|
||||||
'Insights precisos para intervenções pedagógicas'
|
|
||||||
].map((item, index) => (
|
|
||||||
<li key={index} className="flex items-start gap-3">
|
|
||||||
<div className="mt-1">
|
|
||||||
<Check className="w-5 h-5 text-green-600" />
|
|
||||||
</div>
|
|
||||||
<span className="text-gray-600">{item}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Results Preview */}
|
|
||||||
<div className="md:col-span-2 mt-8">
|
|
||||||
<div className="bg-white rounded-xl shadow-lg p-8">
|
|
||||||
<div className="grid md:grid-cols-3 gap-8 text-center">
|
|
||||||
<div>
|
|
||||||
<div className="text-4xl font-bold text-purple-600 mb-2">300%</div>
|
|
||||||
<p className="text-gray-600">Aumento no engajamento</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="text-4xl font-bold text-purple-600 mb-2">85%</div>
|
|
||||||
<p className="text-gray-600">Melhoria no desempenho</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="text-4xl font-bold text-purple-600 mb-2">50%</div>
|
|
||||||
<p className="text-gray-600">Redução da carga dos professores</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Pricing */}
|
{/* Testimonials */}
|
||||||
<div className="py-20 bg-gray-50">
|
<div className="mt-24 grid md:grid-cols-2 gap-8">
|
||||||
<PlanForSchools />
|
<TestimonialCard
|
||||||
</div>
|
quote="A transformação que vimos em nossa escola foi incrível. Alunos que mal conseguiam juntar letras agora estão lendo com fluência e, mais importante, com prazer."
|
||||||
|
author="Maria Silva"
|
||||||
|
role="Diretora Pedagógica"
|
||||||
|
/>
|
||||||
|
<TestimonialCard
|
||||||
|
quote="Como professora há 15 anos, nunca vi um método tão eficaz e envolvente. A plataforma me ajuda a personalizar o ensino para cada aluno."
|
||||||
|
author="Ana Paula Santos"
|
||||||
|
role="Professora"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Final CTA */}
|
{/* Pricing Section */}
|
||||||
<div className="py-20">
|
<div className="mt-24">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<PlanForSchools />
|
||||||
<div className="bg-gradient-to-r from-purple-600 to-indigo-600 rounded-2xl p-8 md:p-16 text-center text-white">
|
</div>
|
||||||
<h2 className="text-3xl md:text-4xl font-bold mb-4">
|
|
||||||
|
{/* FAQ Section */}
|
||||||
|
<div className="mt-24">
|
||||||
|
<FAQ
|
||||||
|
title="Dúvidas Frequentes"
|
||||||
|
description="Tire suas dúvidas sobre a implementação do Histórias Mágicas em sua escola"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
question: "Como o Histórias Mágicas se integra ao currículo escolar?",
|
||||||
|
answer: "Nossa plataforma foi desenvolvida para complementar e enriquecer o currículo existente. Oferecemos conteúdo alinhado à BNCC e ferramentas de personalização que permitem adaptar as atividades aos objetivos pedagógicos específicos de cada escola."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Quanto tempo leva para implementar a plataforma?",
|
||||||
|
answer: "O processo de implementação é personalizado e gradual, levando em média 2-3 semanas. Iniciamos com uma fase piloto, oferecemos treinamento completo para a equipe e fornecemos suporte contínuo durante todo o processo."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Como posso acompanhar o progresso dos alunos?",
|
||||||
|
answer: "Disponibilizamos um dashboard intuitivo com métricas em tempo real, relatórios detalhados e insights sobre o desempenho individual e coletivo. Professores e coordenadores podem monitorar o progresso, identificar áreas de melhoria e personalizar intervenções."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Quais são os requisitos técnicos?",
|
||||||
|
answer: "A plataforma é acessível via navegador web em qualquer dispositivo (computadores, tablets, smartphones). Recomendamos uma conexão estável à internet e o uso de fones de ouvido para melhor experiência nas atividades de áudio."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Como vocês protegem os dados dos alunos?",
|
||||||
|
answer: "Seguimos rigorosos protocolos de segurança em conformidade com a LGPD. Todos os dados são criptografados, o acesso é controlado e realizamos auditorias regulares de segurança."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Que tipo de suporte vocês oferecem?",
|
||||||
|
answer: "Oferecemos suporte técnico e pedagógico através de múltiplos canais (chat, email, telefone), além de atualizações regulares da plataforma e workshops para capacitação contínua da equipe escolar."
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Final CTA */}
|
||||||
|
<div className="mt-24 pb-24">
|
||||||
|
<div className="bg-purple-600 rounded-3xl px-8 py-16 text-center">
|
||||||
|
<h2 className="text-4xl font-bold text-white mb-4">
|
||||||
Pronto para Transformar sua Escola?
|
Pronto para Transformar sua Escola?
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-lg mb-8 max-w-2xl mx-auto">
|
<p className="text-white/90 mb-8 max-w-2xl mx-auto text-lg">
|
||||||
Junte-se a mais de 1000 escolas que já estão revolucionando a educação
|
Junte-se a mais de 1000 escolas que já estão revolucionando a educação
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={handleSchoolRegister}
|
onClick={() => navigate('/register')}
|
||||||
className="bg-white text-purple-600 px-8 py-4 rounded-xl hover:bg-purple-50 transition text-lg font-semibold"
|
className="bg-white text-purple-600 px-8 py-3 rounded-lg font-semibold hover:bg-purple-50 transition"
|
||||||
>
|
>
|
||||||
Começar Gratuitamente
|
Começar Gratuitamente
|
||||||
</button>
|
</button>
|
||||||
@ -503,4 +412,6 @@ export function HomePage() {
|
|||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default HomePage;
|
||||||
@ -1,27 +1,76 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useButtonTracking } from '../../hooks/useButtonTracking';
|
||||||
|
import { cn } from '../../lib/utils';
|
||||||
|
|
||||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
as?: 'button' | 'span';
|
as?: 'button' | 'span';
|
||||||
children: React.ReactNode;
|
trackingId: string;
|
||||||
|
variant?: 'default' | 'primary' | 'secondary' | 'outline' | 'ghost' | 'link';
|
||||||
|
size?: 'sm' | 'md' | 'lg';
|
||||||
|
trackingProperties?: {
|
||||||
|
label?: string;
|
||||||
|
value?: string | number;
|
||||||
|
action?: string;
|
||||||
|
category?: string;
|
||||||
|
position?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Button({
|
export function Button({
|
||||||
as: Component = 'button',
|
as: Component = 'button',
|
||||||
className = '',
|
|
||||||
children,
|
children,
|
||||||
...props
|
className = '',
|
||||||
}: ButtonProps): JSX.Element {
|
trackingId,
|
||||||
|
variant = 'default',
|
||||||
|
size = 'md',
|
||||||
|
trackingProperties,
|
||||||
|
onClick,
|
||||||
|
disabled,
|
||||||
|
type = 'button',
|
||||||
|
...props
|
||||||
|
}: ButtonProps) {
|
||||||
|
const { trackButtonClick } = useButtonTracking({
|
||||||
|
category: trackingProperties?.category || 'interaction'
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
// Rastreia o clique
|
||||||
|
trackButtonClick(trackingId, {
|
||||||
|
variant,
|
||||||
|
size,
|
||||||
|
...trackingProperties,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Chama o onClick original se existir
|
||||||
|
onClick?.(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseStyles = cn(
|
||||||
|
'inline-flex items-center justify-center px-4 py-2',
|
||||||
|
'text-sm font-medium',
|
||||||
|
'rounded-md shadow-sm',
|
||||||
|
'transition-colors duration-200',
|
||||||
|
'disabled:opacity-50 disabled:cursor-not-allowed',
|
||||||
|
{
|
||||||
|
'text-white bg-purple-600 hover:bg-purple-700': variant === 'primary' || variant === 'default',
|
||||||
|
'text-gray-700 bg-white border border-gray-300 hover:bg-gray-50': variant === 'secondary',
|
||||||
|
'text-purple-600 bg-transparent hover:bg-purple-50': variant === 'ghost',
|
||||||
|
'text-purple-600 bg-transparent hover:underline': variant === 'link',
|
||||||
|
'text-purple-600 border border-purple-600 hover:bg-purple-50': variant === 'outline',
|
||||||
|
'px-3 py-1.5 text-sm': size === 'sm',
|
||||||
|
'px-4 py-2 text-base': size === 'md',
|
||||||
|
'px-6 py-3 text-lg': size === 'lg',
|
||||||
|
},
|
||||||
|
className
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
className={`
|
type={Component === 'button' ? type : undefined}
|
||||||
inline-flex items-center justify-center px-4 py-2
|
className={baseStyles}
|
||||||
text-sm font-medium text-white
|
onClick={handleClick}
|
||||||
bg-purple-600 hover:bg-purple-700
|
disabled={disabled}
|
||||||
rounded-md shadow-sm
|
|
||||||
transition-colors duration-200
|
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
81
src/components/ui/comparison-section.tsx
Normal file
81
src/components/ui/comparison-section.tsx
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { X, CheckCircle } from 'lucide-react';
|
||||||
|
|
||||||
|
interface ComparisonItem {
|
||||||
|
title: string;
|
||||||
|
without: string[];
|
||||||
|
with: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComparisonSectionProps {
|
||||||
|
title: string;
|
||||||
|
items: ComparisonItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ComparisonSection({ title, items }: ComparisonSectionProps) {
|
||||||
|
return (
|
||||||
|
<section className="px-4 py-24 bg-white">
|
||||||
|
<div className="mx-auto max-w-7xl">
|
||||||
|
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-8">
|
||||||
|
{/* Sem Histórias Mágicas */}
|
||||||
|
<div className="p-8 bg-gray-50 rounded-xl border border-gray-200">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center">
|
||||||
|
<X className="h-6 w-6 text-red-500" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-gray-900">
|
||||||
|
Sem Histórias Mágicas
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{items.map((category, index) => (
|
||||||
|
<div key={index} className="mb-8 last:mb-0">
|
||||||
|
<h4 className="font-bold text-gray-900 mb-4">{category.title}</h4>
|
||||||
|
<ul className="space-y-3">
|
||||||
|
{category.without.map((item, idx) => (
|
||||||
|
<li key={idx} className="flex items-start gap-2">
|
||||||
|
<X className="h-5 w-5 text-red-500 flex-shrink-0 mt-1" />
|
||||||
|
<span className="text-gray-600">{item}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Com Histórias Mágicas */}
|
||||||
|
<div className="p-8 bg-gradient-to-br from-purple-50 to-blue-50 rounded-xl
|
||||||
|
border-2 border-purple-200 transform hover:scale-[1.02] transition-transform">
|
||||||
|
<div className="flex items-center gap-3 mb-8">
|
||||||
|
<div className="w-12 h-12 bg-gradient-to-r from-purple-600 to-blue-500
|
||||||
|
rounded-full flex items-center justify-center">
|
||||||
|
<CheckCircle className="h-6 w-6 text-white" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-bold text-gray-900">
|
||||||
|
Com Histórias Mágicas
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{items.map((category, index) => (
|
||||||
|
<div key={index} className="mb-8 last:mb-0">
|
||||||
|
<h4 className="font-bold text-gray-900 mb-4">{category.title}</h4>
|
||||||
|
<ul className="space-y-3">
|
||||||
|
{category.with.map((item, idx) => (
|
||||||
|
<li key={idx} className="flex items-start gap-2">
|
||||||
|
<CheckCircle className="h-5 w-5 text-green-500 flex-shrink-0 mt-1" />
|
||||||
|
<span className="text-gray-600">{item}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
49
src/components/ui/faq.tsx
Normal file
49
src/components/ui/faq.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface FAQItem {
|
||||||
|
question: string;
|
||||||
|
answer: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FAQProps {
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
items: FAQItem[];
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FAQ({
|
||||||
|
title = "Perguntas Frequentes",
|
||||||
|
description = "Tire suas dúvidas sobre nossa plataforma",
|
||||||
|
items,
|
||||||
|
className = ""
|
||||||
|
}: FAQProps) {
|
||||||
|
return (
|
||||||
|
<section className={`px-4 py-24 bg-white ${className}`}>
|
||||||
|
<div className="mx-auto max-w-3xl">
|
||||||
|
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{description && (
|
||||||
|
<p className="text-center text-gray-600 mb-12">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="space-y-8">
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<div key={index} className="bg-gray-50 rounded-xl p-6 hover:bg-gray-100 transition-colors">
|
||||||
|
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
||||||
|
{item.question}
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
{item.answer}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
41
src/components/ui/feature-card.tsx
Normal file
41
src/components/ui/feature-card.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
interface FeatureCardProps {
|
||||||
|
icon: LucideIcon;
|
||||||
|
title: string;
|
||||||
|
items?: string[];
|
||||||
|
description?: string;
|
||||||
|
borderColor?: string;
|
||||||
|
iconColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FeatureCard({
|
||||||
|
icon: Icon,
|
||||||
|
title,
|
||||||
|
items,
|
||||||
|
description,
|
||||||
|
borderColor = 'border-purple-200',
|
||||||
|
iconColor = 'text-purple-600'
|
||||||
|
}: FeatureCardProps) {
|
||||||
|
return (
|
||||||
|
<div className="p-6 rounded-xl border border-gray-200 hover:shadow-lg transition-all duration-300 bg-white">
|
||||||
|
<div className="w-12 h-12 rounded-lg bg-purple-100 flex items-center justify-center mb-4">
|
||||||
|
<Icon className={`w-6 h-6 ${iconColor}`} />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 mb-2">{title}</h3>
|
||||||
|
{description && (
|
||||||
|
<p className="text-gray-600 mb-4">{description}</p>
|
||||||
|
)}
|
||||||
|
{items && items.length > 0 && (
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<li key={index} className="text-gray-600">
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
67
src/components/ui/info-card.tsx
Normal file
67
src/components/ui/info-card.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
interface InfoCardProps {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
result?: string;
|
||||||
|
icon?: LucideIcon;
|
||||||
|
items?: string[];
|
||||||
|
bgColor?: string;
|
||||||
|
titleColor?: string;
|
||||||
|
textColor?: string;
|
||||||
|
resultColor?: string;
|
||||||
|
iconColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function InfoCard({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
result,
|
||||||
|
icon: Icon,
|
||||||
|
items,
|
||||||
|
bgColor = 'bg-white',
|
||||||
|
titleColor = 'text-gray-900',
|
||||||
|
textColor = 'text-gray-600',
|
||||||
|
resultColor = 'text-purple-600',
|
||||||
|
iconColor = 'text-purple-600',
|
||||||
|
}: InfoCardProps) {
|
||||||
|
return (
|
||||||
|
<div className={`${bgColor} p-8 rounded-2xl shadow-sm`}>
|
||||||
|
{/* Icon */}
|
||||||
|
{Icon && (
|
||||||
|
<div className="mb-6">
|
||||||
|
<div className="w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center">
|
||||||
|
<Icon className={`w-8 h-8 ${iconColor}`} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Title */}
|
||||||
|
<h3 className={`text-2xl font-bold ${titleColor} mb-3`}>{title}</h3>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
{description && (
|
||||||
|
<p className={`${textColor} text-lg mb-6`}>{description}</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Result */}
|
||||||
|
{result && (
|
||||||
|
<div className="bg-purple-50 rounded-xl p-4">
|
||||||
|
<p className={`${resultColor} text-lg font-medium`}>
|
||||||
|
Resultado: {result}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Items List */}
|
||||||
|
{items && items.length > 0 && (
|
||||||
|
<ul className={`list-disc pl-6 space-y-2 mt-6 ${textColor}`}>
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<li key={index}>{item}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
34
src/components/ui/process-step.tsx
Normal file
34
src/components/ui/process-step.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface ProcessStepProps {
|
||||||
|
number: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ProcessStep({
|
||||||
|
number,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
}: ProcessStepProps) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-start gap-6">
|
||||||
|
{/* Número */}
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<div className="w-14 h-14 rounded-full bg-purple-600 flex items-center justify-center text-white text-2xl font-bold">
|
||||||
|
{number}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Conteúdo */}
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="text-2xl font-bold text-gray-900 mb-3">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-lg text-gray-600">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
33
src/components/ui/stat-card.tsx
Normal file
33
src/components/ui/stat-card.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
interface StatCardProps {
|
||||||
|
icon: LucideIcon;
|
||||||
|
title: string;
|
||||||
|
value: string;
|
||||||
|
description: string;
|
||||||
|
valueColor?: string;
|
||||||
|
iconBgColor?: string;
|
||||||
|
iconColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StatCard({
|
||||||
|
icon: Icon,
|
||||||
|
title,
|
||||||
|
value,
|
||||||
|
description,
|
||||||
|
valueColor = 'text-purple-600',
|
||||||
|
iconBgColor = 'bg-purple-600',
|
||||||
|
iconColor = 'text-white',
|
||||||
|
}: StatCardProps) {
|
||||||
|
return (
|
||||||
|
<div className="bg-white shadow-lg rounded-xl p-6">
|
||||||
|
<div className={`flex items-center justify-center h-12 w-12 rounded-md ${iconBgColor} ${iconColor} mb-4`}>
|
||||||
|
<Icon className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">{title}</h3>
|
||||||
|
<p className={`mt-2 text-4xl font-bold ${valueColor}`}>{value}</p>
|
||||||
|
<p className="mt-2 text-gray-600">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
67
src/components/ui/testimonial-card.tsx
Normal file
67
src/components/ui/testimonial-card.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Heart } from 'lucide-react';
|
||||||
|
|
||||||
|
interface TestimonialCardProps {
|
||||||
|
quote: string;
|
||||||
|
author: string;
|
||||||
|
role: string;
|
||||||
|
image?: string;
|
||||||
|
magicMoment?: string;
|
||||||
|
result?: string;
|
||||||
|
borderColor?: string;
|
||||||
|
quoteColor?: string;
|
||||||
|
authorColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TestimonialCard({
|
||||||
|
quote,
|
||||||
|
author,
|
||||||
|
role,
|
||||||
|
image,
|
||||||
|
magicMoment,
|
||||||
|
result,
|
||||||
|
borderColor = 'border-purple-200',
|
||||||
|
quoteColor = 'text-gray-600',
|
||||||
|
authorColor = 'text-gray-900'
|
||||||
|
}: TestimonialCardProps) {
|
||||||
|
return (
|
||||||
|
<div className="bg-gradient-to-br from-purple-50 to-blue-50 p-6 rounded-xl shadow-sm">
|
||||||
|
{image && (
|
||||||
|
<div className="relative mb-8">
|
||||||
|
<img
|
||||||
|
src={image}
|
||||||
|
alt={`Foto de ${author}`}
|
||||||
|
className="w-full h-48 object-cover rounded-lg"
|
||||||
|
/>
|
||||||
|
<div className="absolute -bottom-4 -right-4 bg-white p-2 rounded-full shadow-lg">
|
||||||
|
<Heart className="h-6 w-6 text-red-500" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<p className={`${quoteColor} mb-4 italic`}>"{quote}"</p>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
{image && (
|
||||||
|
<img
|
||||||
|
src={image}
|
||||||
|
alt={author}
|
||||||
|
className="w-12 h-12 rounded-full object-cover"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<p className={`font-bold ${authorColor}`}>{author}</p>
|
||||||
|
<p className="text-sm text-gray-500">{role}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{(magicMoment || result) && (
|
||||||
|
<div className="mt-4 p-3 bg-white rounded-lg">
|
||||||
|
<p className="text-sm text-purple-600 font-medium">
|
||||||
|
{magicMoment ? `✨ Momento mágico: ${magicMoment}` : `🎯 Resultado: ${result}`}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
50
src/hooks/useButtonTracking.ts
Normal file
50
src/hooks/useButtonTracking.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { useRudderstack } from './useRudderstack';
|
||||||
|
|
||||||
|
interface ButtonTrackingOptions {
|
||||||
|
category?: string;
|
||||||
|
location?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useButtonTracking(options: ButtonTrackingOptions = {}) {
|
||||||
|
const { track } = useRudderstack();
|
||||||
|
const { category = 'interaction', location = window.location.pathname } = options;
|
||||||
|
|
||||||
|
const trackButtonClick = (
|
||||||
|
buttonId: string,
|
||||||
|
properties?: {
|
||||||
|
label?: string;
|
||||||
|
value?: string | number;
|
||||||
|
action?: string;
|
||||||
|
variant?: string;
|
||||||
|
position?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
track('button_clicked', {
|
||||||
|
button_id: buttonId,
|
||||||
|
category,
|
||||||
|
location,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
...properties,
|
||||||
|
// Informações da página
|
||||||
|
page_title: document.title,
|
||||||
|
page_url: window.location.href,
|
||||||
|
page_path: window.location.pathname,
|
||||||
|
// Informações do dispositivo/viewport
|
||||||
|
viewport_width: window.innerWidth,
|
||||||
|
viewport_height: window.innerHeight,
|
||||||
|
device_type: getDeviceType(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getDeviceType = () => {
|
||||||
|
const width = window.innerWidth;
|
||||||
|
if (width < 768) return 'mobile';
|
||||||
|
if (width < 1024) return 'tablet';
|
||||||
|
return 'desktop';
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
trackButtonClick,
|
||||||
|
};
|
||||||
|
}
|
||||||
60
src/hooks/useDataLayer.ts
Normal file
60
src/hooks/useDataLayer.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
interface DataLayerEvent {
|
||||||
|
event: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
dataLayer: any[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useDataLayer() {
|
||||||
|
// Inicializa o dataLayer se não existir
|
||||||
|
if (!window.dataLayer) {
|
||||||
|
window.dataLayer = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const push = (data: DataLayerEvent) => {
|
||||||
|
window.dataLayer.push(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageView = (path: string) => {
|
||||||
|
push({
|
||||||
|
event: 'pageview',
|
||||||
|
page: {
|
||||||
|
path,
|
||||||
|
title: document.title,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackEvent = (
|
||||||
|
category: string,
|
||||||
|
action: string,
|
||||||
|
label?: string,
|
||||||
|
value?: number
|
||||||
|
) => {
|
||||||
|
push({
|
||||||
|
event: 'track_event',
|
||||||
|
category,
|
||||||
|
action,
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackUserProperties = (properties: Record<string, any>) => {
|
||||||
|
push({
|
||||||
|
event: 'set_user_properties',
|
||||||
|
user_properties: properties,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
push,
|
||||||
|
pageView,
|
||||||
|
trackEvent,
|
||||||
|
trackUserProperties,
|
||||||
|
};
|
||||||
|
}
|
||||||
114
src/hooks/useErrorTracking.ts
Normal file
114
src/hooks/useErrorTracking.ts
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import * as Sentry from '@sentry/react';
|
||||||
|
import { useRudderstack } from './useRudderstack';
|
||||||
|
|
||||||
|
interface ErrorTrackingOptions {
|
||||||
|
category?: string;
|
||||||
|
userId?: string;
|
||||||
|
userEmail?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useErrorTracking(options: ErrorTrackingOptions = {}) {
|
||||||
|
const { track } = useRudderstack();
|
||||||
|
const { category = 'error', userId, userEmail } = options;
|
||||||
|
|
||||||
|
const trackError = (
|
||||||
|
error: Error,
|
||||||
|
context?: {
|
||||||
|
componentName?: string;
|
||||||
|
action?: string;
|
||||||
|
metadata?: Record<string, any>;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
// 1. Rastreia no Sentry primeiro (para debug técnico)
|
||||||
|
Sentry.withScope((scope) => {
|
||||||
|
// Adiciona contexto do usuário
|
||||||
|
if (userId) scope.setUser({ id: userId, email: userEmail });
|
||||||
|
|
||||||
|
// Adiciona contexto do erro
|
||||||
|
if (context?.componentName) scope.setTag('component', context.componentName);
|
||||||
|
if (context?.action) scope.setTag('action', context.action);
|
||||||
|
if (context?.metadata) scope.setContext('metadata', context.metadata);
|
||||||
|
|
||||||
|
// Captura o erro
|
||||||
|
Sentry.captureException(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Rastreia no Rudderstack (para analytics)
|
||||||
|
track('error_occurred', {
|
||||||
|
category,
|
||||||
|
error_name: error.name,
|
||||||
|
error_message: error.message,
|
||||||
|
error_stack: error.stack,
|
||||||
|
component: context?.componentName,
|
||||||
|
action: context?.action,
|
||||||
|
...context?.metadata,
|
||||||
|
// Informações do ambiente
|
||||||
|
url: window.location.href,
|
||||||
|
user_agent: navigator.userAgent,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackErrorBoundary = (
|
||||||
|
error: Error,
|
||||||
|
componentStack: string,
|
||||||
|
componentName: string
|
||||||
|
) => {
|
||||||
|
// 1. Rastreia no Sentry
|
||||||
|
Sentry.withScope((scope) => {
|
||||||
|
if (userId) scope.setUser({ id: userId, email: userEmail });
|
||||||
|
scope.setTag('component', componentName);
|
||||||
|
scope.setTag('error_type', 'react_error_boundary');
|
||||||
|
scope.setExtra('componentStack', componentStack);
|
||||||
|
Sentry.captureException(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Rastreia no Rudderstack
|
||||||
|
track('error_boundary_triggered', {
|
||||||
|
category,
|
||||||
|
error_name: error.name,
|
||||||
|
error_message: error.message,
|
||||||
|
component_name: componentName,
|
||||||
|
component_stack: componentStack,
|
||||||
|
url: window.location.href,
|
||||||
|
user_agent: navigator.userAgent,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackApiError = (
|
||||||
|
error: any,
|
||||||
|
endpoint: string,
|
||||||
|
method: string,
|
||||||
|
requestData?: any
|
||||||
|
) => {
|
||||||
|
// 1. Rastreia no Sentry
|
||||||
|
Sentry.withScope((scope) => {
|
||||||
|
if (userId) scope.setUser({ id: userId, email: userEmail });
|
||||||
|
scope.setTag('error_type', 'api_error');
|
||||||
|
scope.setTag('endpoint', endpoint);
|
||||||
|
scope.setTag('method', method);
|
||||||
|
scope.setContext('request', { data: requestData });
|
||||||
|
Sentry.captureException(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Rastreia no Rudderstack
|
||||||
|
track('api_error_occurred', {
|
||||||
|
category,
|
||||||
|
endpoint,
|
||||||
|
method,
|
||||||
|
error_name: error.name,
|
||||||
|
error_message: error.message,
|
||||||
|
status_code: error.status || error.statusCode,
|
||||||
|
request_data: requestData,
|
||||||
|
url: window.location.href,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
trackError,
|
||||||
|
trackErrorBoundary,
|
||||||
|
trackApiError,
|
||||||
|
};
|
||||||
|
}
|
||||||
83
src/hooks/useFormTracking.ts
Normal file
83
src/hooks/useFormTracking.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { useRudderstack } from './useRudderstack';
|
||||||
|
|
||||||
|
interface FormTrackingOptions {
|
||||||
|
formId: string;
|
||||||
|
formName: string;
|
||||||
|
category?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useFormTracking({ formId, formName, category = 'form' }: FormTrackingOptions) {
|
||||||
|
const { track } = useRudderstack();
|
||||||
|
|
||||||
|
const trackFormStarted = () => {
|
||||||
|
track('form_started', {
|
||||||
|
form_id: formId,
|
||||||
|
form_name: formName,
|
||||||
|
category,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackFormStepCompleted = (step: string, isValid: boolean) => {
|
||||||
|
track('form_step_completed', {
|
||||||
|
form_id: formId,
|
||||||
|
form_name: formName,
|
||||||
|
category,
|
||||||
|
step,
|
||||||
|
is_valid: isValid,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackFormSubmitted = (isValid: boolean, fields?: Record<string, any>) => {
|
||||||
|
track('form_submitted', {
|
||||||
|
form_id: formId,
|
||||||
|
form_name: formName,
|
||||||
|
category,
|
||||||
|
is_valid: isValid,
|
||||||
|
...fields,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackFormError = (errorType: string, errorMessage: string, field?: string) => {
|
||||||
|
track('form_error', {
|
||||||
|
form_id: formId,
|
||||||
|
form_name: formName,
|
||||||
|
category,
|
||||||
|
error_type: errorType,
|
||||||
|
error_message: errorMessage,
|
||||||
|
field,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackFormAbandoned = (step?: string) => {
|
||||||
|
track('form_abandoned', {
|
||||||
|
form_id: formId,
|
||||||
|
form_name: formName,
|
||||||
|
category,
|
||||||
|
step,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const trackFieldInteraction = (
|
||||||
|
fieldName: string,
|
||||||
|
interactionType: 'focus' | 'blur' | 'change',
|
||||||
|
value?: string
|
||||||
|
) => {
|
||||||
|
track('form_field_interaction', {
|
||||||
|
form_id: formId,
|
||||||
|
form_name: formName,
|
||||||
|
category,
|
||||||
|
field_name: fieldName,
|
||||||
|
interaction_type: interactionType,
|
||||||
|
field_value: value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
trackFormStarted,
|
||||||
|
trackFormStepCompleted,
|
||||||
|
trackFormSubmitted,
|
||||||
|
trackFormError,
|
||||||
|
trackFormAbandoned,
|
||||||
|
trackFieldInteraction,
|
||||||
|
};
|
||||||
|
}
|
||||||
55
src/hooks/useRudderstack.ts
Normal file
55
src/hooks/useRudderstack.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
interface RudderstackEvent {
|
||||||
|
event: string;
|
||||||
|
properties?: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserTraits {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useRudderstack() {
|
||||||
|
const track = (eventName: string, properties?: Record<string, any>) => {
|
||||||
|
if (window.rudderanalytics) {
|
||||||
|
window.rudderanalytics.track(eventName, properties);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const page = (name?: string, properties?: Record<string, any>) => {
|
||||||
|
if (window.rudderanalytics) {
|
||||||
|
window.rudderanalytics.page(name, properties);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const identify = (userId: string, traits?: UserTraits) => {
|
||||||
|
if (window.rudderanalytics) {
|
||||||
|
window.rudderanalytics.identify(userId, traits);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const group = (groupId: string, traits?: Record<string, any>) => {
|
||||||
|
if (window.rudderanalytics) {
|
||||||
|
window.rudderanalytics.group(groupId, traits);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const alias = (newUserId: string) => {
|
||||||
|
if (window.rudderanalytics) {
|
||||||
|
window.rudderanalytics.alias(newUserId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
if (window.rudderanalytics) {
|
||||||
|
window.rudderanalytics.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
track,
|
||||||
|
page,
|
||||||
|
identify,
|
||||||
|
group,
|
||||||
|
alias,
|
||||||
|
reset,
|
||||||
|
};
|
||||||
|
}
|
||||||
61
src/main.tsx
61
src/main.tsx
@ -1,11 +1,44 @@
|
|||||||
import { StrictMode } from 'react';
|
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { RouterProvider } from 'react-router-dom';
|
import { RouterProvider } from 'react-router-dom';
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { router } from './routes';
|
import { router } from './routes';
|
||||||
import { Toaster } from './components/ui/toaster';
|
import { Toaster } from './components/ui/toaster';
|
||||||
|
import { GoogleTagManager } from './components/analytics/GoogleTagManager';
|
||||||
|
import { RudderstackAnalytics } from './components/analytics/RudderstackAnalytics';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
|
// GTM ID - Substitua pelo seu ID real do GTM
|
||||||
|
const GTM_ID = import.meta.env.VITE_GTM_ID;
|
||||||
|
|
||||||
|
// Rudderstack Config
|
||||||
|
const RUDDERSTACK_WRITE_KEY = import.meta.env.VITE_RUDDERSTACK_WRITE_KEY;
|
||||||
|
const RUDDERSTACK_DATA_PLANE_URL = import.meta.env.VITE_RUDDERSTACK_DATA_PLANE_URL;
|
||||||
|
|
||||||
|
// Inicialização do Sentry
|
||||||
|
Sentry.init({
|
||||||
|
dsn: "https://6c15876055bf4a860c1b63a8e4e7ca65@o544400.ingest.us.sentry.io/4508626073092096",
|
||||||
|
integrations: [
|
||||||
|
Sentry.browserTracingIntegration(),
|
||||||
|
Sentry.replayIntegration(),
|
||||||
|
],
|
||||||
|
environment: import.meta.env.MODE,
|
||||||
|
tracesSampleRate: import.meta.env.DEV ? 1.0 : 0.2,
|
||||||
|
tracePropagationTargets: [
|
||||||
|
"localhost",
|
||||||
|
"historiasmagicas.netlify.app",
|
||||||
|
"bsjlbnyslxzsdwxvkaap.supabase.co"
|
||||||
|
],
|
||||||
|
replaysSessionSampleRate: import.meta.env.DEV ? 1.0 : 0.1,
|
||||||
|
replaysOnErrorSampleRate: 1.0,
|
||||||
|
beforeSend(event) {
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return event;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const queryClient = new QueryClient({
|
const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
@ -16,15 +49,19 @@ const queryClient = new QueryClient({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function Root() {
|
const rootElement = document.getElementById('root');
|
||||||
return (
|
if (!rootElement) throw new Error('Failed to find the root element');
|
||||||
<StrictMode>
|
|
||||||
<QueryClientProvider client={queryClient}>
|
|
||||||
<RouterProvider router={router} />
|
|
||||||
<Toaster />
|
|
||||||
</QueryClientProvider>
|
|
||||||
</StrictMode>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(<Root />);
|
const root = createRoot(rootElement);
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<GoogleTagManager gtmId={GTM_ID} />
|
||||||
|
<RudderstackAnalytics
|
||||||
|
writeKey={RUDDERSTACK_WRITE_KEY}
|
||||||
|
dataPlaneUrl={RUDDERSTACK_DATA_PLANE_URL}
|
||||||
|
/>
|
||||||
|
<RouterProvider router={router} />
|
||||||
|
<Toaster />
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
@ -1,410 +1,265 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
ArrowRight, Wand2, Shield, Star, BookOpen,
|
ArrowRight,
|
||||||
Brain, Target, Users, Award, CheckCircle,
|
Brain,
|
||||||
Clock, Heart, Sparkles, ScrollText, Lock, X,
|
BookOpen,
|
||||||
Facebook, Instagram, Twitter, Youtube
|
Target,
|
||||||
|
Wand2,
|
||||||
|
Star,
|
||||||
|
Shield,
|
||||||
|
Sparkles,
|
||||||
|
ScrollText,
|
||||||
|
Lock,
|
||||||
|
Heart,
|
||||||
|
Facebook,
|
||||||
|
Instagram,
|
||||||
|
Twitter,
|
||||||
|
Youtube,
|
||||||
|
CheckCircle,
|
||||||
|
LineChart,
|
||||||
|
Clock
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { Footer } from '@/components/ui/footer';
|
|
||||||
|
import { StatCard } from '@/components/ui/stat-card';
|
||||||
|
import { TestimonialCard } from '@/components/ui/testimonial-card';
|
||||||
|
import { FeatureCard } from '@/components/ui/feature-card';
|
||||||
|
import { ProcessStep } from '@/components/ui/process-step';
|
||||||
|
import { InfoCard } from '@/components/ui/info-card';
|
||||||
|
import { ComparisonSection } from '@/components/ui/comparison-section';
|
||||||
import { PlanForParents } from '@/components/ui/plan-for-parents';
|
import { PlanForParents } from '@/components/ui/plan-for-parents';
|
||||||
|
import { FAQ } from '@/components/ui/faq';
|
||||||
|
import { Footer } from '@/components/ui/footer';
|
||||||
|
|
||||||
export function EducationalForParents(): JSX.Element {
|
export function EducationalForParents() {
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen">
|
<div className="min-h-screen bg-white">
|
||||||
{/* 1. Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="relative overflow-hidden bg-gradient-to-b from-purple-50 via-white to-purple-50">
|
<div className="relative isolate overflow-hidden bg-gradient-to-b from-purple-100/20">
|
||||||
<div className="absolute inset-0 bg-[url('/patterns/magic.svg')] opacity-5" />
|
<div className="mx-auto max-w-7xl px-6 pb-24 pt-10 sm:pb-32 lg:flex lg:px-8 lg:py-40">
|
||||||
<div className="px-4 py-24 mx-auto max-w-7xl relative">
|
<div className="mx-auto max-w-2xl lg:mx-0 flex-shrink-0 lg:pt-8">
|
||||||
{/* Reading Time */}
|
<div className="absolute right-4 top-4 text-gray-600 flex items-center gap-2">
|
||||||
<div className="absolute top-8 right-8 flex items-center gap-2 text-sm text-gray-500">
|
<Clock className="w-4 h-4" />
|
||||||
<Clock className="h-4 w-4" />
|
<span className="text-sm">Tempo de leitura: 5 minutos</span>
|
||||||
<span>Tempo de leitura: 5 minutos</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col md:flex-row items-center gap-16">
|
|
||||||
<div className="flex-1 space-y-8">
|
|
||||||
<h1 className="text-6xl font-bold text-gray-900 leading-tight">
|
|
||||||
Transforme o Aprendizado em Uma
|
|
||||||
<span className="block bg-gradient-to-r from-purple-600 to-blue-500 bg-clip-text text-transparent">
|
|
||||||
Aventura Mágica
|
|
||||||
</span>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p className="text-xl text-gray-600 leading-relaxed">
|
|
||||||
Histórias educativas personalizadas que encantam e ensinam, criadas especialmente
|
|
||||||
para o desenvolvimento único do seu filho.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="flex gap-4">
|
|
||||||
<button
|
|
||||||
onClick={() => navigate('/register/parent')}
|
|
||||||
className="group px-8 py-4 bg-gradient-to-r from-purple-600 to-blue-500
|
|
||||||
text-white rounded-xl hover:from-purple-700 hover:to-blue-600
|
|
||||||
transform hover:scale-105 transition-all shadow-lg"
|
|
||||||
>
|
|
||||||
Comece Sua Aventura Mágica Grátis
|
|
||||||
<ArrowRight className="inline-block ml-2 h-5 w-5
|
|
||||||
group-hover:translate-x-1 transition-transform" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Social Proof */}
|
|
||||||
<div className="flex gap-8 text-sm text-gray-600">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<BookOpen className="h-5 w-5 text-purple-600" />
|
|
||||||
<span>Mais de 10.000 histórias mágicas criadas</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Users className="h-5 w-5 text-blue-500" />
|
|
||||||
<span>5.000 pequenos leitores encantados</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1">
|
<h1 className="mt-10 text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">
|
||||||
<div className="relative">
|
Transforme o<br />
|
||||||
<div className="absolute -inset-4 bg-gradient-to-r from-purple-600 to-blue-500
|
Aprendizado em<br />
|
||||||
rounded-2xl blur-lg opacity-20" />
|
Uma <span className="text-purple-600">Aventura Mágica</span>
|
||||||
<img
|
</h1>
|
||||||
src="/images/magic-book.webp"
|
|
||||||
alt="Crianças mergulhadas em um livro mágico"
|
<p className="mt-6 text-lg leading-8 text-gray-600 max-w-xl">
|
||||||
className="relative rounded-2xl shadow-2xl transform hover:scale-[1.02]
|
Histórias educativas personalizadas que encantam e ensinam,
|
||||||
transition-transform"
|
criadas especialmente para o desenvolvimento único do seu filho.
|
||||||
/>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
<div className="mt-10">
|
||||||
</div>
|
<button
|
||||||
</div>
|
onClick={() => window.location.href = '/cadastro'}
|
||||||
</section>
|
className="rounded-xl bg-purple-600 px-8 py-4 text-base font-semibold text-white shadow-sm hover:bg-purple-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-purple-600 flex items-center gap-2"
|
||||||
|
|
||||||
{/* 2. Problema & Solução */}
|
|
||||||
<section className="px-4 py-24 bg-white">
|
|
||||||
<div className="mx-auto max-w-7xl">
|
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
|
||||||
Desafios que Todo Pai Enfrenta
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-8 mb-16">
|
|
||||||
{challenges.map((challenge, index) => (
|
|
||||||
<div key={index} className="p-6 bg-purple-50 rounded-xl">
|
|
||||||
<challenge.icon className="h-12 w-12 text-purple-600 mb-4" />
|
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
|
||||||
{challenge.title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600">{challenge.description}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-4 gap-8">
|
|
||||||
{benefits.map((benefit, index) => (
|
|
||||||
<div key={index} className="text-center">
|
|
||||||
<div className="mx-auto w-16 h-16 flex items-center justify-center
|
|
||||||
bg-gradient-to-r from-purple-600 to-blue-500 rounded-full mb-4">
|
|
||||||
<benefit.icon className="h-8 w-8 text-white" />
|
|
||||||
</div>
|
|
||||||
<h4 className="font-bold text-gray-900 mb-2">{benefit.title}</h4>
|
|
||||||
<p className="text-sm text-gray-600">{benefit.description}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* 3. Como a Magia Acontece */}
|
|
||||||
<section className="px-4 py-24 bg-gradient-to-br from-purple-50 to-blue-50">
|
|
||||||
<div className="mx-auto max-w-7xl">
|
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
|
||||||
Como a Magia Acontece
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-12 items-center">
|
|
||||||
<div className="space-y-12">
|
|
||||||
{magicSteps.map((step, index) => (
|
|
||||||
<div key={index} className="flex gap-6">
|
|
||||||
<div className="flex-shrink-0 w-12 h-12 bg-gradient-to-r from-purple-600
|
|
||||||
to-blue-500 text-white rounded-full flex items-center justify-center
|
|
||||||
text-xl font-bold">
|
|
||||||
{index + 1}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
|
||||||
{step.title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-600">{step.description}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="relative">
|
|
||||||
<div className="aspect-video rounded-xl overflow-hidden shadow-xl">
|
|
||||||
<video
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
autoPlay
|
|
||||||
muted
|
|
||||||
loop
|
|
||||||
playsInline
|
|
||||||
poster="/images/demo-poster.webp"
|
|
||||||
>
|
|
||||||
<source src="/videos/demo.mp4" type="video/mp4" />
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
<div className="absolute -bottom-6 -right-6 bg-white p-4 rounded-lg shadow-lg">
|
|
||||||
<div className="flex items-center gap-2 text-sm text-purple-600 font-medium">
|
|
||||||
<Sparkles className="h-4 w-4" />
|
|
||||||
<span>Veja a mágica acontecer!</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* 4. Comparação */}
|
|
||||||
<section className="px-4 py-24 bg-white">
|
|
||||||
<div className="mx-auto max-w-7xl">
|
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
|
||||||
A Magia da Transformação
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-8">
|
|
||||||
{/* Sem Histórias Mágicas */}
|
|
||||||
<div className="p-8 bg-gray-50 rounded-xl border border-gray-200">
|
|
||||||
<div className="flex items-center gap-3 mb-8">
|
|
||||||
<div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center">
|
|
||||||
<X className="h-6 w-6 text-red-500" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-bold text-gray-900">
|
|
||||||
Sem Histórias Mágicas
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{comparisonData.map((category, index) => (
|
|
||||||
<div key={index} className="mb-8 last:mb-0">
|
|
||||||
<h4 className="font-bold text-gray-900 mb-4">{category.title}</h4>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
{category.without.map((item, idx) => (
|
|
||||||
<li key={idx} className="flex items-start gap-2">
|
|
||||||
<X className="h-5 w-5 text-red-500 flex-shrink-0 mt-1" />
|
|
||||||
<span className="text-gray-600">{item}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Com Histórias Mágicas */}
|
|
||||||
<div className="p-8 bg-gradient-to-br from-purple-50 to-blue-50 rounded-xl
|
|
||||||
border-2 border-purple-200 transform hover:scale-[1.02] transition-transform">
|
|
||||||
<div className="flex items-center gap-3 mb-8">
|
|
||||||
<div className="w-12 h-12 bg-gradient-to-r from-purple-600 to-blue-500
|
|
||||||
rounded-full flex items-center justify-center">
|
|
||||||
<CheckCircle className="h-6 w-6 text-white" />
|
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-bold text-gray-900">
|
|
||||||
Com Histórias Mágicas
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{comparisonData.map((category, index) => (
|
|
||||||
<div key={index} className="mb-8 last:mb-0">
|
|
||||||
<h4 className="font-bold text-gray-900 mb-4">{category.title}</h4>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
{category.with.map((item, idx) => (
|
|
||||||
<li key={idx} className="flex items-start gap-2">
|
|
||||||
<CheckCircle className="h-5 w-5 text-green-500 flex-shrink-0 mt-1" />
|
|
||||||
<span className="text-gray-600">{item}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* 5. Benefícios Mágicos Detalhados */}
|
|
||||||
<section className="px-4 py-24 bg-gradient-to-br from-purple-50 to-blue-50">
|
|
||||||
<div className="mx-auto max-w-7xl">
|
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
|
||||||
Benefícios Mágicos Detalhados
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-5 gap-8 mb-16">
|
|
||||||
{detailedBenefits.map((benefit, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md
|
|
||||||
transform hover:scale-105 transition-all"
|
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center text-center gap-4">
|
Comece Sua Aventura Mágica Grátis
|
||||||
<div className="w-16 h-16 flex items-center justify-center
|
<ArrowRight className="w-5 h-5" />
|
||||||
bg-gradient-to-r from-purple-600 to-blue-500 rounded-full">
|
</button>
|
||||||
<benefit.icon className="h-8 w-8 text-white" />
|
</div>
|
||||||
</div>
|
|
||||||
<h3 className="text-xl font-bold text-gray-900">{benefit.title}</h3>
|
|
||||||
<p className="text-gray-600">{benefit.description}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Preview do Portal */}
|
<div className="mt-10 flex items-center gap-x-8 text-sm text-gray-600">
|
||||||
<div className="relative mt-20">
|
<div className="flex items-center gap-x-2">
|
||||||
<div className="absolute -inset-4 bg-gradient-to-r from-purple-600 to-blue-500
|
<BookOpen className="w-5 h-5 text-purple-600" />
|
||||||
rounded-2xl blur-lg opacity-20" />
|
<span>Mais de 10.000 histórias mágicas criadas</span>
|
||||||
<div className="relative bg-white p-8 rounded-xl shadow-xl">
|
</div>
|
||||||
<div className="grid md:grid-cols-2 gap-12 items-center">
|
<div className="flex items-center gap-x-2">
|
||||||
<div>
|
<Target className="w-5 h-5 text-purple-600" />
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-6">
|
<span>5.000 pequenos leitores encantados</span>
|
||||||
Portal dos Pais: Acompanhamento em Tempo Real
|
|
||||||
</h3>
|
|
||||||
<ul className="space-y-4">
|
|
||||||
<li className="flex items-start gap-3">
|
|
||||||
<CheckCircle className="h-6 w-6 text-green-500 flex-shrink-0 mt-1" />
|
|
||||||
<span className="text-gray-600">
|
|
||||||
Métricas detalhadas de progresso e desenvolvimento
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start gap-3">
|
|
||||||
<CheckCircle className="h-6 w-6 text-green-500 flex-shrink-0 mt-1" />
|
|
||||||
<span className="text-gray-600">
|
|
||||||
Relatórios semanais personalizados
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start gap-3">
|
|
||||||
<CheckCircle className="h-6 w-6 text-green-500 flex-shrink-0 mt-1" />
|
|
||||||
<span className="text-gray-600">
|
|
||||||
Recomendações pedagógicas baseadas em dados
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-start gap-3">
|
|
||||||
<CheckCircle className="h-6 w-6 text-green-500 flex-shrink-0 mt-1" />
|
|
||||||
<span className="text-gray-600">
|
|
||||||
Histórico completo de leituras e conquistas
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className="relative">
|
|
||||||
<img
|
|
||||||
src="/images/dashboard-preview.webp"
|
|
||||||
alt="Portal dos Pais"
|
|
||||||
className="rounded-xl shadow-2xl"
|
|
||||||
/>
|
|
||||||
<div className="absolute -bottom-6 -right-6 bg-white p-4 rounded-lg shadow-lg">
|
|
||||||
<div className="flex items-center gap-2 text-sm text-purple-600 font-medium">
|
|
||||||
<Lock className="h-4 w-4" />
|
|
||||||
<span>Ambiente 100% seguro e monitorado</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* 6. Testimoniais */}
|
<div className="mx-auto mt-16 flex max-w-2xl sm:mt-24 lg:ml-10 lg:mr-0 lg:mt-0 lg:max-w-none lg:flex-none xl:ml-32">
|
||||||
<section className="px-4 py-24 bg-white">
|
<div className="max-w-3xl flex-none sm:max-w-5xl lg:max-w-none">
|
||||||
<div className="mx-auto max-w-7xl">
|
<img
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
src="/images/hero-image.webp"
|
||||||
|
alt="Crianças mergulhadas em um livro mágico"
|
||||||
|
className="w-[76rem] rounded-md bg-white/5 shadow-2xl ring-1 ring-white/10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Challenges Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
||||||
|
Desafios da Educação Moderna
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-lg leading-8 text-gray-600">
|
||||||
|
Entendemos os obstáculos que pais e educadores enfrentam no desenvolvimento da leitura.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="mt-16 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{challenges.map((challenge, index) => (
|
||||||
|
<InfoCard
|
||||||
|
key={index}
|
||||||
|
icon={challenge.icon}
|
||||||
|
title={challenge.title}
|
||||||
|
description={challenge.description}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Magic Process Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 bg-gradient-to-b from-purple-50">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
||||||
|
Como Funciona a Magia
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-lg leading-8 text-gray-600">
|
||||||
|
Um processo simples e eficaz para transformar a leitura em uma aventura inesquecível.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="mt-16 space-y-12">
|
||||||
|
{magicSteps.map((step, index) => (
|
||||||
|
<ProcessStep
|
||||||
|
key={index}
|
||||||
|
number={index + 1}
|
||||||
|
title={step.title}
|
||||||
|
description={step.description}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Comparison Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24">
|
||||||
|
<ComparisonSection
|
||||||
|
title="A Magia da Transformação"
|
||||||
|
items={comparisonData}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Benefits Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 bg-gradient-to-b from-purple-50">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
||||||
|
Benefícios Mágicos
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-lg leading-8 text-gray-600">
|
||||||
|
Descubra todas as vantagens que nossa plataforma oferece para o desenvolvimento do seu filho.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="mt-16 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{detailedBenefits.map((benefit, index) => (
|
||||||
|
<FeatureCard
|
||||||
|
key={index}
|
||||||
|
icon={benefit.icon}
|
||||||
|
title={benefit.title}
|
||||||
|
description={benefit.description}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Results Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
||||||
|
Resultados Comprovados
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-lg leading-8 text-gray-600">
|
||||||
|
Números que demonstram o impacto do Histórias Mágicas no aprendizado.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="mt-16 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
|
<StatCard
|
||||||
|
icon={LineChart}
|
||||||
|
title="Fluência de Leitura"
|
||||||
|
value="95%"
|
||||||
|
description="de melhora na velocidade e compreensão"
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={Clock}
|
||||||
|
title="Tempo de Leitura"
|
||||||
|
value="3x"
|
||||||
|
description="mais tempo dedicado à leitura diária"
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={Star}
|
||||||
|
title="Satisfação"
|
||||||
|
value="98%"
|
||||||
|
description="dos pais recomendam a plataforma"
|
||||||
|
/>
|
||||||
|
<StatCard
|
||||||
|
icon={BookOpen}
|
||||||
|
title="Histórias Lidas"
|
||||||
|
value="50+"
|
||||||
|
description="histórias por aluno em média"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Testimonials Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 bg-gradient-to-b from-purple-50">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
||||||
Histórias de Transformação
|
Histórias de Transformação
|
||||||
</h2>
|
</h2>
|
||||||
|
<p className="mt-4 text-lg leading-8 text-gray-600">
|
||||||
<div className="grid md:grid-cols-3 gap-8">
|
Veja como o Histórias Mágicas está transformando a vida de famílias por todo o Brasil.
|
||||||
{testimonials.map((testimonial, index) => (
|
|
||||||
<div key={index} className="bg-gradient-to-br from-purple-50 to-blue-50
|
|
||||||
p-6 rounded-xl shadow-sm">
|
|
||||||
<div className="relative mb-8">
|
|
||||||
<img
|
|
||||||
src={testimonial.image}
|
|
||||||
alt={`Família de ${testimonial.name}`}
|
|
||||||
className="w-full h-48 object-cover rounded-lg"
|
|
||||||
/>
|
|
||||||
<div className="absolute -bottom-4 -right-4 bg-white p-2 rounded-full shadow-lg">
|
|
||||||
<Heart className="h-6 w-6 text-red-500" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-600 mb-4 italic">"{testimonial.text}"</p>
|
|
||||||
<div>
|
|
||||||
<p className="font-bold text-gray-900">{testimonial.name}</p>
|
|
||||||
<p className="text-sm text-gray-500">{testimonial.role}</p>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4 p-3 bg-white rounded-lg">
|
|
||||||
<p className="text-sm text-purple-600 font-medium">
|
|
||||||
✨ Momento mágico: {testimonial.magicMoment}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* 7. Planos */}
|
|
||||||
<PlanForParents />
|
|
||||||
|
|
||||||
{/* 8. FAQ */}
|
|
||||||
<section className="px-4 py-24 bg-white">
|
|
||||||
<div className="mx-auto max-w-3xl">
|
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
|
||||||
Perguntas Mágicas
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="space-y-8">
|
|
||||||
{faqItems.map((item, index) => (
|
|
||||||
<div key={index} className="bg-gray-50 rounded-xl p-6">
|
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">{item.question}</h3>
|
|
||||||
<p className="text-gray-600">{item.answer}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* 9. CTA Final */}
|
|
||||||
<section className="px-4 py-24 bg-gradient-to-br from-purple-600 to-blue-500 text-white">
|
|
||||||
<div className="mx-auto max-w-3xl text-center">
|
|
||||||
<h2 className="text-4xl font-bold mb-8">
|
|
||||||
Comece a Jornada Mágica Hoje
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p className="text-xl opacity-90 mb-12">
|
|
||||||
Transforme a educação do seu filho em uma aventura inesquecível
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="bg-white/10 p-6 rounded-xl mb-8">
|
|
||||||
<p className="font-medium mb-2">
|
|
||||||
Oferta por tempo limitado!
|
|
||||||
</p>
|
|
||||||
<p className="text-sm opacity-90">
|
|
||||||
7 dias grátis + Bônus especial de boas-vindas
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={() => navigate('/register/parent')}
|
|
||||||
className="px-12 py-6 bg-white text-purple-600 rounded-xl text-xl font-bold
|
|
||||||
hover:bg-gray-100 transform hover:scale-105 transition-all shadow-lg"
|
|
||||||
>
|
|
||||||
Criar Conta Gratuita
|
|
||||||
<ArrowRight className="inline-block ml-2 h-6 w-6" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<p className="mt-6 text-sm opacity-75">
|
|
||||||
Garantia de 30 dias ou seu dinheiro de volta
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<div className="mt-16 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{testimonials.map((testimonial, index) => (
|
||||||
|
<TestimonialCard
|
||||||
|
key={index}
|
||||||
|
quote={testimonial.text}
|
||||||
|
author={testimonial.name}
|
||||||
|
role={testimonial.role}
|
||||||
|
image={testimonial.image}
|
||||||
|
magicMoment={testimonial.magicMoment}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pricing Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24">
|
||||||
|
<PlanForParents />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* FAQ Section */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24 bg-gradient-to-b from-purple-50">
|
||||||
|
<FAQ
|
||||||
|
title="Dúvidas Frequentes"
|
||||||
|
description="Encontre respostas para as perguntas mais comuns sobre nossa plataforma."
|
||||||
|
items={faqItems}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Final CTA */}
|
||||||
|
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-24">
|
||||||
|
<div className="rounded-3xl bg-purple-600 px-8 py-16">
|
||||||
|
<div className="mx-auto max-w-2xl text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
|
||||||
|
Comece a Jornada Mágica Hoje
|
||||||
|
</h2>
|
||||||
|
<p className="mx-auto mt-6 max-w-xl text-lg leading-8 text-white/90">
|
||||||
|
Junte-se a milhares de famílias que já descobriram o poder da leitura personalizada.
|
||||||
|
</p>
|
||||||
|
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||||
|
<button
|
||||||
|
onClick={() => window.location.href = '/cadastro'}
|
||||||
|
className="rounded-xl bg-white px-3.5 py-2.5 text-sm font-semibold text-purple-600 shadow-sm hover:bg-purple-50"
|
||||||
|
>
|
||||||
|
Começar Gratuitamente
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Footer */}
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -413,18 +268,18 @@ export function EducationalForParents(): JSX.Element {
|
|||||||
const challenges = [
|
const challenges = [
|
||||||
{
|
{
|
||||||
icon: Brain,
|
icon: Brain,
|
||||||
title: "Manter as crianças interessadas em aprender",
|
title: 'Dificuldade de Concentração',
|
||||||
description: "É difícil competir com jogos e vídeos para capturar a atenção das crianças."
|
description: 'Crianças têm dificuldade em manter o foco em métodos tradicionais de leitura.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: BookOpen,
|
icon: BookOpen,
|
||||||
title: "Encontrar conteúdo educativo de qualidade",
|
title: 'Falta de Engajamento',
|
||||||
description: "Muito conteúdo disponível, mas pouco realmente educativo e envolvente."
|
description: 'Livros convencionais nem sempre capturam a imaginação das crianças modernas.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Target,
|
icon: Target,
|
||||||
title: "Acompanhar o desenvolvimento da criança",
|
title: 'Progresso Lento',
|
||||||
description: "Falta de ferramentas para monitorar o progresso de forma clara e objetiva."
|
description: 'Pais têm dificuldade em acompanhar e estimular o desenvolvimento da leitura.'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -453,147 +308,152 @@ const benefits = [
|
|||||||
|
|
||||||
const magicSteps = [
|
const magicSteps = [
|
||||||
{
|
{
|
||||||
title: "Escolha o tema da aventura",
|
title: 'Escolha do Tema',
|
||||||
description: "Selecione entre diversos temas educativos alinhados com a BNCC e adequados à idade."
|
description: 'Selecione entre diversos temas educativos que despertam o interesse do seu filho.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Personalize os personagens",
|
title: 'Personalização Mágica',
|
||||||
description: "Crie personagens que seu filho vai adorar, com características únicas e cativantes."
|
description: 'Crie personagens que se conectam com a realidade e interesses da criança.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "A IA cria a história mágica",
|
title: 'Geração da História',
|
||||||
description: "Nossa IA educacional gera uma história personalizada em segundos."
|
description: 'Nossa IA cria uma narrativa única, adaptada ao nível de leitura do seu filho.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "A aventura educativa começa",
|
title: 'Aventura Educativa',
|
||||||
description: "Seu filho mergulha em uma jornada mágica de aprendizado e diversão."
|
description: 'Acompanhe o progresso enquanto seu filho se diverte aprendendo.'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const comparisonData = [
|
const comparisonData = [
|
||||||
{
|
{
|
||||||
title: "Tempo & Diversão",
|
title: 'Tempo & Diversão',
|
||||||
without: [
|
without: [
|
||||||
"Horas procurando conteúdo educativo adequado",
|
'Horas procurando conteúdo educativo adequado',
|
||||||
"Crianças entediadas com leituras tradicionais",
|
'Crianças entediadas com leituras tradicionais',
|
||||||
"Histórias que não capturam a imaginação",
|
'Histórias que não capturam a imaginação',
|
||||||
"Dificuldade em acompanhar o progresso"
|
'Dificuldade em acompanhar o progresso'
|
||||||
],
|
],
|
||||||
with: [
|
with: [
|
||||||
"Histórias mágicas personalizadas em minutos",
|
'Histórias mágicas personalizadas em minutos',
|
||||||
"Crianças fascinadas por aventuras únicas",
|
'Crianças fascinadas por aventuras únicas',
|
||||||
"Mundos mágicos que educam e encantam",
|
'Mundos mágicos que educam e encantam',
|
||||||
"Portal mágico de acompanhamento do progresso"
|
'Portal mágico de acompanhamento do progresso'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Qualidade do Aprendizado",
|
title: 'Qualidade do Aprendizado',
|
||||||
without: [
|
without: [
|
||||||
"Conteúdo genérico e previsível",
|
'Conteúdo genérico e previsível',
|
||||||
"Falta de conexão emocional com a leitura",
|
'Falta de conexão emocional com a leitura',
|
||||||
"Dificuldade em manter o interesse",
|
'Dificuldade em manter o interesse',
|
||||||
"Aprendizado fragmentado"
|
'Aprendizado fragmentado'
|
||||||
],
|
],
|
||||||
with: [
|
with: [
|
||||||
"Histórias que evoluem com cada criança",
|
'Histórias que evoluem com cada criança',
|
||||||
"Conexão emocional com personagens únicos",
|
'Conexão emocional com personagens únicos',
|
||||||
"Aventuras que mesclam diversão e educação",
|
'Aventuras que mesclam diversão e educação',
|
||||||
"Jornada de aprendizado mágica e integrada"
|
'Jornada de aprendizado mágica e integrada'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Resultados",
|
title: 'Resultados',
|
||||||
without: [
|
without: [
|
||||||
"Progresso lento e desmotivador",
|
'Progresso lento e desmotivador',
|
||||||
"Resistência à leitura e aprendizado",
|
'Resistência à leitura e aprendizado',
|
||||||
"Rotina de estudos cansativa",
|
'Rotina de estudos cansativa',
|
||||||
"Pais preocupados com desenvolvimento"
|
'Pais preocupados com desenvolvimento'
|
||||||
],
|
],
|
||||||
with: [
|
with: [
|
||||||
"Evolução visível e empolgante",
|
'Evolução visível e empolgante',
|
||||||
"Amor natural pela leitura e conhecimento",
|
'Amor natural pela leitura e conhecimento',
|
||||||
"Aventuras diárias de aprendizado",
|
'Aventuras diárias de aprendizado',
|
||||||
"Pais confiantes no desenvolvimento mágico"
|
'Pais confiantes no desenvolvimento mágico'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const detailedBenefits = [
|
const detailedBenefits = [
|
||||||
{
|
{
|
||||||
icon: Wand2,
|
icon: Wand2,
|
||||||
title: "Aprendizado Através de Aventuras",
|
title: 'Histórias Personalizadas',
|
||||||
description: "Histórias que se adaptam ao nível e interesses do seu filho, tornando o aprendizado natural e divertido."
|
description: 'Narrativas únicas que se adaptam aos interesses e nível de leitura do seu filho.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: ScrollText,
|
icon: Star,
|
||||||
title: "Portal dos Pais",
|
title: 'Aprendizado Divertido',
|
||||||
description: "Acompanhe em tempo real o progresso de leitura, compreensão e desenvolvimento do seu filho."
|
description: 'Transformamos o processo de leitura em uma aventura mágica e envolvente.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Shield,
|
icon: Shield,
|
||||||
title: "Proteção Mágica",
|
title: 'Ambiente Seguro',
|
||||||
description: "Conteúdo 100% seguro e adequado, com moderação constante e controles parentais."
|
description: 'Conteúdo apropriado para a idade e monitoramento constante do progresso.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: BookOpen,
|
icon: Sparkles,
|
||||||
title: "Alinhamento com BNCC",
|
title: 'Recompensas Mágicas',
|
||||||
description: "Histórias criadas seguindo as diretrizes da Base Nacional Comum Curricular."
|
description: 'Sistema de conquistas que motiva e celebra o progresso da criança.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Brain,
|
icon: ScrollText,
|
||||||
title: "IA Educacional",
|
title: 'Relatórios Detalhados',
|
||||||
description: "Nossa inteligência artificial analisa o perfil do seu filho para criar histórias personalizadas e adaptativas."
|
description: 'Acompanhe o desenvolvimento da leitura com métricas claras e insights valiosos.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Lock,
|
||||||
|
title: 'Controle Parental',
|
||||||
|
description: 'Defina limites, monitore o uso e mantenha-se informado sobre o progresso.'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const testimonials = [
|
const testimonials = [
|
||||||
{
|
{
|
||||||
|
text: "Minha filha sempre teve dificuldade com leitura, mas desde que começamos a usar o Histórias Mágicas, ela não para de pedir para ler mais uma história!",
|
||||||
|
name: "Ana Clara Silva",
|
||||||
|
role: "Mãe da Sofia, 8 anos",
|
||||||
image: "/images/testimonial-1.webp",
|
image: "/images/testimonial-1.webp",
|
||||||
text: "Minha filha passou de resistente à leitura para não querer parar de ler! As histórias personalizadas fizeram toda a diferença.",
|
magicMoment: "Sofia leu sua primeira história sozinha após 2 semanas"
|
||||||
name: "Ana Silva",
|
|
||||||
role: "Mãe da Maria, 8 anos",
|
|
||||||
magicMoment: "Primeira história completa lida sozinha"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
text: "As histórias personalizadas fizeram toda a diferença. Ver meu filho como protagonista das aventuras tornou a leitura muito mais envolvente.",
|
||||||
|
name: "Pedro Henrique Santos",
|
||||||
|
role: "Pai do Lucas, 7 anos",
|
||||||
image: "/images/testimonial-2.webp",
|
image: "/images/testimonial-2.webp",
|
||||||
text: "Como pai, é incrível ver o progresso do Pedro. O portal dos pais me ajuda a entender exatamente onde ele precisa de apoio.",
|
magicMoment: "Lucas aumentou seu vocabulário em 40% em 3 meses"
|
||||||
name: "Carlos Santos",
|
|
||||||
role: "Pai do Pedro, 10 anos",
|
|
||||||
magicMoment: "Superou a dificuldade com palavras complexas"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
text: "O progresso que vimos em apenas algumas semanas foi incrível. A autoconfiança da minha filha na leitura cresceu enormemente.",
|
||||||
|
name: "Mariana Costa",
|
||||||
|
role: "Mãe da Laura, 9 anos",
|
||||||
image: "/images/testimonial-3.webp",
|
image: "/images/testimonial-3.webp",
|
||||||
text: "As histórias são tão envolventes que meu filho pede para ler mais uma toda noite. O aprendizado acontece naturalmente!",
|
magicMoment: "Laura passou de leitora básica para avançada"
|
||||||
name: "Juliana Costa",
|
|
||||||
role: "Mãe do Lucas, 7 anos",
|
|
||||||
magicMoment: "Começou a criar suas próprias histórias"
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const faqItems = [
|
const faqItems = [
|
||||||
{
|
{
|
||||||
question: "Como a magia da IA funciona?",
|
question: "Como a plataforma auxilia no trabalho do professor?",
|
||||||
answer: "Nossa IA educacional analisa o perfil do seu filho, incluindo idade, interesses e nível de leitura, para criar histórias únicas que combinam diversão com aprendizado personalizado."
|
answer: "O Histórias Mágicas oferece ferramentas que automatizam a avaliação da leitura, gerando relatórios detalhados sobre o progresso de cada aluno. Isso permite que você foque seu tempo no que mais importa: o desenvolvimento personalizado de cada estudante."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "Como garantimos histórias seguras?",
|
question: "A plataforma se integra ao currículo escolar?",
|
||||||
answer: "Todas as histórias passam por múltiplas camadas de verificação, incluindo filtros de IA e revisão humana, garantindo conteúdo 100% adequado e seguro."
|
answer: "Sim, nossa plataforma foi desenvolvida alinhada à BNCC e pode ser facilmente integrada ao planejamento pedagógico. Oferecemos suporte para adaptar as atividades ao seu programa de ensino e objetivos específicos."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "Como acompanhar a evolução mágica?",
|
question: "Como acompanhar o progresso da turma?",
|
||||||
answer: "Através do Portal dos Pais, você tem acesso a relatórios detalhados sobre fluência, compreensão, vocabulário e muito mais, com visualizações claras do progresso."
|
answer: "Através do painel do professor, você tem acesso a análises individuais e coletivas, identificando padrões de dificuldade, monitorando o progresso e recebendo sugestões de intervenção baseadas em evidências científicas."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "Qual é a política de cancelamento?",
|
question: "Vocês oferecem treinamento para os professores?",
|
||||||
answer: "Você pode cancelar sua assinatura a qualquer momento, sem multas. Oferecemos garantia de 30 dias - se não estiver satisfeito, devolvemos seu dinheiro."
|
answer: "Sim, oferecemos treinamento completo e suporte contínuo. Nosso programa inclui workshops online, materiais de apoio e consultoria pedagógica para garantir que você aproveite ao máximo os recursos da plataforma."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "Quantas histórias mágicas por mês?",
|
question: "Como a plataforma lida com diferentes níveis de leitura na mesma turma?",
|
||||||
answer: "O número de histórias varia conforme o plano escolhido, desde 5 histórias mensais no plano básico até histórias ilimitadas no plano Grão-Mestre."
|
answer: "Nossa tecnologia adaptativa personaliza automaticamente as atividades para cada aluno, permitindo que todos progridam em seu próprio ritmo. Você recebe sugestões específicas para apoiar alunos que precisam de mais atenção."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: "Como funciona o suporte aos pais?",
|
question: "Quais recursos estão disponíveis para planejamento de aulas?",
|
||||||
answer: "Oferecemos suporte via chat, email e telefone, com especialistas em educação prontos para ajudar. Planos premium incluem acesso a pedagogos."
|
answer: "Disponibilizamos um banco de atividades, planos de aula modelo, e ferramentas de personalização que permitem adaptar o conteúdo às necessidades específicas da sua turma. Tudo isso alinhado às melhores práticas pedagógicas."
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { Footer } from '@/components/ui/footer';
|
import { Footer } from '@/components/ui/footer';
|
||||||
import { PlanForSchools } from '@/components/ui/plan-for-schools';
|
import { PlanForSchools } from '@/components/ui/plan-for-schools';
|
||||||
|
import { FAQ } from '@/components/ui/faq';
|
||||||
|
|
||||||
// Meta tags e SEO
|
// Meta tags e SEO
|
||||||
const meta = {
|
const meta = {
|
||||||
@ -189,7 +190,7 @@ export function EvidenceBased(): JSX.Element {
|
|||||||
<section className="px-4 py-24 bg-white">
|
<section className="px-4 py-24 bg-white">
|
||||||
<div className="mx-auto max-w-7xl">
|
<div className="mx-auto max-w-7xl">
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
||||||
Evidências vs. Pseudociência
|
Pseudociência vs. Evidências
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-8">
|
<div className="grid md:grid-cols-2 gap-8">
|
||||||
@ -316,22 +317,36 @@ export function EvidenceBased(): JSX.Element {
|
|||||||
<PlanForSchools />
|
<PlanForSchools />
|
||||||
|
|
||||||
{/* FAQ */}
|
{/* FAQ */}
|
||||||
<section className="px-4 py-24 bg-white">
|
<FAQ
|
||||||
<div className="mx-auto max-w-3xl">
|
title="Dúvidas Frequentes sobre Educação Baseada em Evidências"
|
||||||
<h2 className="text-4xl font-bold text-center text-gray-900 mb-16">
|
description="Entenda como nossa plataforma aplica métodos cientificamente comprovados"
|
||||||
Perguntas Frequentes
|
items={[
|
||||||
</h2>
|
{
|
||||||
|
question: "O que é educação baseada em evidências?",
|
||||||
<div className="space-y-8">
|
answer: "Educação baseada em evidências é uma abordagem que utiliza métodos e práticas pedagógicas comprovadas por pesquisas científicas rigorosas. Em vez de seguir modismos ou teorias não testadas, baseamos nossas estratégias em estudos que demonstram resultados reais na aprendizagem."
|
||||||
{faqItems.map((item, index) => (
|
},
|
||||||
<div key={index} className="bg-gray-50 rounded-xl p-6">
|
{
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">{item.question}</h3>
|
question: "Como vocês aplicam a ciência da leitura na prática?",
|
||||||
<p className="text-gray-600">{item.answer}</p>
|
answer: "Nossa plataforma incorpora os cinco pilares da alfabetização: consciência fonêmica, instrução fônica sistemática, fluência, vocabulário e compreensão. Cada atividade é cuidadosamente projetada para desenvolver estas habilidades de forma estruturada e progressiva."
|
||||||
</div>
|
},
|
||||||
))}
|
{
|
||||||
</div>
|
question: "Quais são as evidências que suportam seus métodos?",
|
||||||
</div>
|
answer: "Nossos métodos são baseados em décadas de pesquisas em neurociência e psicologia cognitiva, incluindo estudos do National Reading Panel e pesquisas sobre desenvolvimento da leitura. Mantemos parcerias com universidades para validação contínua de nossa abordagem."
|
||||||
</section>
|
},
|
||||||
|
{
|
||||||
|
question: "Como vocês medem o progresso dos alunos?",
|
||||||
|
answer: "Utilizamos avaliações formativas contínuas e análise de dados em tempo real para monitorar o progresso individual. Nosso sistema coleta métricas específicas de fluência, precisão e compreensão, permitindo intervenções personalizadas baseadas em evidências."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Como a plataforma se adapta a diferentes níveis de aprendizado?",
|
||||||
|
answer: "Nossa tecnologia utiliza algoritmos adaptativos baseados em pesquisas sobre diferenciação de ensino. O sistema ajusta automaticamente a dificuldade e o tipo de atividades com base no desempenho individual, garantindo que cada aluno progrida em seu próprio ritmo."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Qual é o papel do professor na plataforma?",
|
||||||
|
answer: "Os professores são facilitadores essenciais do processo. Nossa plataforma fornece dados detalhados e sugestões de intervenção baseadas em evidências, permitindo que os professores tomem decisões pedagógicas informadas e personalizem o suporte para cada aluno."
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* CTA Final */}
|
{/* CTA Final */}
|
||||||
<section className="px-4 py-24 bg-gradient-to-br from-purple-600 to-blue-500 text-white">
|
<section className="px-4 py-24 bg-gradient-to-br from-purple-600 to-blue-500 text-white">
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContai
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { Footer } from '@/components/ui/footer';
|
import { Footer } from '@/components/ui/footer';
|
||||||
import { PlanForParents } from '@/components/ui/plan-for-parents';
|
import { PlanForParents } from '@/components/ui/plan-for-parents';
|
||||||
|
import { FAQ } from '@/components/ui/faq';
|
||||||
|
|
||||||
export function ParentsLandingPage(): JSX.Element {
|
export function ParentsLandingPage(): JSX.Element {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -403,10 +404,42 @@ export function ParentsLandingPage(): JSX.Element {
|
|||||||
{/* 5. Planos */}
|
{/* 5. Planos */}
|
||||||
<PlanForParents />
|
<PlanForParents />
|
||||||
|
|
||||||
|
{/* 6. FAQ */}
|
||||||
|
<FAQ
|
||||||
|
title="Dúvidas Frequentes"
|
||||||
|
description="Tire suas dúvidas sobre o Histórias Mágicas"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
question: "Como funciona o Histórias Mágicas?",
|
||||||
|
answer: "O Histórias Mágicas é uma plataforma interativa que combina tecnologia e pedagogia para desenvolver habilidades de leitura. Seu filho terá acesso a histórias personalizadas, feedback em tempo real e exercícios adaptados ao seu nível de leitura."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Qual é a idade recomendada?",
|
||||||
|
answer: "A plataforma é ideal para crianças de 6 a 12 anos, mas pode ser adaptada para diferentes níveis de leitura. Nosso sistema personaliza a experiência de acordo com a idade e habilidade de cada criança."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Como acompanho o progresso do meu filho?",
|
||||||
|
answer: "Através do portal dos pais, você tem acesso a relatórios detalhados sobre fluência, compreensão, pronúncia e ritmo de leitura. Você também recebe sugestões personalizadas para ajudar seu filho a melhorar."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Posso cancelar a assinatura a qualquer momento?",
|
||||||
|
answer: "Sim, você pode cancelar sua assinatura quando quiser, sem multa ou burocracia. Oferecemos também um período de teste gratuito para você experimentar a plataforma."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Quais dispositivos são compatíveis?",
|
||||||
|
answer: "O Histórias Mágicas funciona em qualquer navegador moderno, seja no computador, tablet ou smartphone. Recomendamos o uso de fones de ouvido para melhor experiência com os exercícios de pronúncia."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Como é feita a avaliação da leitura?",
|
||||||
|
answer: "Utilizamos tecnologia avançada de reconhecimento de voz e inteligência artificial para avaliar a leitura em tempo real, considerando aspectos como fluência, pronúncia e compreensão. Tudo isso de forma lúdica e não intimidadora."
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* 7. CTA Final */}
|
{/* 7. CTA Final */}
|
||||||
<section className="px-4 py-24 relative overflow-hidden">
|
<section className="px-4 py-24 relative overflow-hidden">
|
||||||
<div className="absolute inset-0 bg-gradient-to-b from-purple-50 to-purple-100 opacity-50" />
|
<div className="absolute inset-0 bg-gradient-to-b from-purple-50 to-purple-100 opacity-50" />
|
||||||
<div className="mx-auto max-w-3xl text-center relative">
|
<div className="mx-auto max-3xl text-center relative">
|
||||||
<h2 className="text-5xl font-bold text-gray-900 mb-8 leading-tight">
|
<h2 className="text-5xl font-bold text-gray-900 mb-8 leading-tight">
|
||||||
Comece a Jornada de Leitura do Seu Filho
|
Comece a Jornada de Leitura do Seu Filho
|
||||||
<span className="bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text text-transparent">
|
<span className="bg-gradient-to-r from-purple-600 to-indigo-600 bg-clip-text text-transparent">
|
||||||
|
|||||||
463
src/pages/landing/TextSalesLetter.tsx
Normal file
463
src/pages/landing/TextSalesLetter.tsx
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { ArrowRight, BookOpen, Brain, CheckCircle, Clock, FileText, Lightbulb, LineChart, School, Star, Target, Users } from 'lucide-react';
|
||||||
|
import { Footer } from '@/components/ui/footer';
|
||||||
|
|
||||||
|
export function TextSalesLetter() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-white">
|
||||||
|
{/* Hero Section */}
|
||||||
|
<div className="max-w-3xl mx-auto px-4 py-12 sm:py-16 lg:py-20">
|
||||||
|
<h1 className="text-4xl font-bold text-gray-900 mb-8 text-center">
|
||||||
|
A Revolução da Alfabetização: Como a Ciência e a Tecnologia Estão Transformando o Aprendizado da Leitura
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div className="prose prose-lg max-w-none text-gray-600 space-y-6">
|
||||||
|
<p className="text-xl font-semibold text-purple-600">
|
||||||
|
Caro educador comprometido com o futuro da educação,
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Em um mundo onde a tecnologia avança rapidamente e o acesso à informação é cada vez mais crucial,
|
||||||
|
uma verdade permanece inalterada: a alfabetização é a base fundamental para todo o desenvolvimento
|
||||||
|
educacional e pessoal de uma criança. No entanto, os dados são alarmantes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
O Cenário Atual da Alfabetização no Brasil
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
De acordo com os últimos dados do SAEB (Sistema de Avaliação da Educação Básica):
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul className="list-disc pl-6 space-y-2">
|
||||||
|
<li>Mais de 50% dos alunos do 5º ano não atingem níveis adequados de leitura</li>
|
||||||
|
<li>39,7% dos estudantes no 3º ano do ensino fundamental apresentam deficiências graves na compreensão textual</li>
|
||||||
|
<li>Cerca de 4,6 milhões de crianças entre 6 e 10 anos estão em risco de não desenvolverem habilidades básicas de leitura</li>
|
||||||
|
<li>A pandemia agravou ainda mais este cenário, aumentando as desigualdades educacionais</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Estes números não são apenas estatísticas - são histórias reais de crianças que estão
|
||||||
|
perdendo oportunidades fundamentais para seu desenvolvimento.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
Por Que os Métodos Tradicionais Não Estão Funcionando?
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
O problema não está na falta de esforço dos educadores ou no desinteresse das crianças.
|
||||||
|
A questão é muito mais profunda e envolve:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul className="list-disc pl-6 space-y-2">
|
||||||
|
<li>Métodos de ensino desatualizados que ignoram as descobertas da neurociência</li>
|
||||||
|
<li>Abordagens não sistemáticas que criam lacunas no aprendizado</li>
|
||||||
|
<li>Falta de personalização para atender às necessidades individuais</li>
|
||||||
|
<li>Ausência de feedback imediato e ajustes em tempo real</li>
|
||||||
|
<li>Dificuldade em manter o engajamento dos alunos</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
A Ciência da Leitura: O Que Realmente Funciona
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Décadas de pesquisas científicas revelaram um caminho claro para uma alfabetização efetiva.
|
||||||
|
Este caminho é baseado em cinco pilares fundamentais:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="bg-purple-50 p-6 rounded-xl mt-6">
|
||||||
|
<h3 className="text-xl font-bold text-purple-800 mb-4">1. Consciência Fonológica</h3>
|
||||||
|
<p className="text-purple-900">
|
||||||
|
A habilidade de identificar e manipular os sons da fala é o primeiro e mais crucial passo
|
||||||
|
para a alfabetização. Inclui:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2 text-purple-800">
|
||||||
|
<li>Reconhecimento de rimas</li>
|
||||||
|
<li>Segmentação de palavras em sílabas</li>
|
||||||
|
<li>Identificação de fonemas iniciais e finais</li>
|
||||||
|
<li>Manipulação de sons para formar novas palavras</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-blue-50 p-6 rounded-xl mt-6">
|
||||||
|
<h3 className="text-xl font-bold text-blue-800 mb-4">2. Instrução Fônica Sistemática</h3>
|
||||||
|
<p className="text-blue-900">
|
||||||
|
O ensino explícito da relação entre letras e sons é fundamental para desenvolver a
|
||||||
|
capacidade de decodificação. Envolve:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2 text-blue-800">
|
||||||
|
<li>Apresentação sistemática das relações letra-som</li>
|
||||||
|
<li>Prática regular de decodificação</li>
|
||||||
|
<li>Progressão estruturada do simples ao complexo</li>
|
||||||
|
<li>Revisão constante e prática cumulativa</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-green-50 p-6 rounded-xl mt-6">
|
||||||
|
<h3 className="text-xl font-bold text-green-800 mb-4">3. Fluência na Leitura</h3>
|
||||||
|
<p className="text-green-900">
|
||||||
|
A capacidade de ler com precisão, velocidade e expressão adequadas é essencial para
|
||||||
|
a compreensão. Requer:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2 text-green-800">
|
||||||
|
<li>Prática regular com textos apropriados ao nível</li>
|
||||||
|
<li>Leitura repetida de textos familiares</li>
|
||||||
|
<li>Modelagem de leitura fluente</li>
|
||||||
|
<li>Feedback imediato e correção</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-yellow-50 p-6 rounded-xl mt-6">
|
||||||
|
<h3 className="text-xl font-bold text-yellow-800 mb-4">4. Vocabulário</h3>
|
||||||
|
<p className="text-yellow-900">
|
||||||
|
Um vocabulário rico é fundamental para a compreensão leitora e o desenvolvimento
|
||||||
|
cognitivo. Inclui:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2 text-yellow-800">
|
||||||
|
<li>Exposição a palavras novas em contextos significativos</li>
|
||||||
|
<li>Estratégias para inferir significados</li>
|
||||||
|
<li>Conexões entre palavras e conceitos</li>
|
||||||
|
<li>Revisão espaçada de vocabulário aprendido</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-red-50 p-6 rounded-xl mt-6">
|
||||||
|
<h3 className="text-xl font-bold text-red-800 mb-4">5. Compreensão Leitora</h3>
|
||||||
|
<p className="text-red-900">
|
||||||
|
O objetivo final da leitura é extrair e construir significado do texto.
|
||||||
|
Isso requer:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2 text-red-800">
|
||||||
|
<li>Estratégias explícitas de compreensão</li>
|
||||||
|
<li>Monitoramento da própria compreensão</li>
|
||||||
|
<li>Ativação de conhecimentos prévios</li>
|
||||||
|
<li>Prática com diferentes gêneros textuais</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
Como a Histórias Mágicas Revoluciona a Alfabetização
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Nossa plataforma foi desenvolvida para integrar todos estes pilares em um sistema
|
||||||
|
digital inteligente e envolvente. Veja como funcionamos:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 gap-6 mt-6">
|
||||||
|
<div className="border border-purple-200 rounded-xl p-6">
|
||||||
|
<div className="flex items-start">
|
||||||
|
<Brain className="h-8 w-8 text-purple-600 mr-4" />
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Avaliação Diagnóstica Inteligente</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Antes de começar, nossa IA analisa:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Nível atual de leitura</li>
|
||||||
|
<li>Habilidades fonológicas</li>
|
||||||
|
<li>Vocabulário existente</li>
|
||||||
|
<li>Padrões de aprendizagem</li>
|
||||||
|
<li>Áreas que precisam de atenção especial</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border border-purple-200 rounded-xl p-6">
|
||||||
|
<div className="flex items-start">
|
||||||
|
<Target className="h-8 w-8 text-purple-600 mr-4" />
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Plano Personalizado de Aprendizagem</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Com base na avaliação, criamos:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Roteiro individualizado de atividades</li>
|
||||||
|
<li>Sequência otimizada de conteúdos</li>
|
||||||
|
<li>Metas específicas e alcançáveis</li>
|
||||||
|
<li>Ajustes automáticos baseados no progresso</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border border-purple-200 rounded-xl p-6">
|
||||||
|
<div className="flex items-start">
|
||||||
|
<BookOpen className="h-8 w-8 text-purple-600 mr-4" />
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Atividades Interativas e Envolventes</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Nossas atividades incluem:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Jogos fonológicos interativos</li>
|
||||||
|
<li>Histórias adaptativas ao nível do aluno</li>
|
||||||
|
<li>Exercícios de decodificação gamificados</li>
|
||||||
|
<li>Desafios de compreensão contextualizada</li>
|
||||||
|
<li>Atividades de expansão de vocabulário</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border border-purple-200 rounded-xl p-6">
|
||||||
|
<div className="flex items-start">
|
||||||
|
<LineChart className="h-8 w-8 text-purple-600 mr-4" />
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Monitoramento em Tempo Real</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Oferecemos:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Análise detalhada do progresso</li>
|
||||||
|
<li>Identificação precoce de dificuldades</li>
|
||||||
|
<li>Relatórios personalizados para professores</li>
|
||||||
|
<li>Feedback constante para alunos e pais</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
O Processo de Implementação
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Implementar a Histórias Mágicas em sua escola é um processo simples e estruturado:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-6 mt-6">
|
||||||
|
<div className="flex items-start">
|
||||||
|
<div className="flex-shrink-0 h-8 w-8 rounded-full bg-purple-600 text-white flex items-center justify-center font-bold">
|
||||||
|
1
|
||||||
|
</div>
|
||||||
|
<div className="ml-4">
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Onboarding Personalizado</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Nossa equipe realiza:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Análise das necessidades específicas da escola</li>
|
||||||
|
<li>Configuração inicial da plataforma</li>
|
||||||
|
<li>Importação dos dados dos alunos</li>
|
||||||
|
<li>Definição de metas e objetivos</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-start">
|
||||||
|
<div className="flex-shrink-0 h-8 w-8 rounded-full bg-purple-600 text-white flex items-center justify-center font-bold">
|
||||||
|
2
|
||||||
|
</div>
|
||||||
|
<div className="ml-4">
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Capacitação da Equipe</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Oferecemos:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Treinamento completo para professores</li>
|
||||||
|
<li>Workshops sobre ciência da leitura</li>
|
||||||
|
<li>Suporte técnico contínuo</li>
|
||||||
|
<li>Materiais de apoio e recursos pedagógicos</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-start">
|
||||||
|
<div className="flex-shrink-0 h-8 w-8 rounded-full bg-purple-600 text-white flex items-center justify-center font-bold">
|
||||||
|
3
|
||||||
|
</div>
|
||||||
|
<div className="ml-4">
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Implementação Gradual</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Realizamos:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Avaliação diagnóstica inicial dos alunos</li>
|
||||||
|
<li>Criação de turmas e grupos de trabalho</li>
|
||||||
|
<li>Definição de rotinas de utilização</li>
|
||||||
|
<li>Acompanhamento das primeiras semanas</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-start">
|
||||||
|
<div className="flex-shrink-0 h-8 w-8 rounded-full bg-purple-600 text-white flex items-center justify-center font-bold">
|
||||||
|
4
|
||||||
|
</div>
|
||||||
|
<div className="ml-4">
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Monitoramento e Ajustes</h3>
|
||||||
|
<p className="mt-2">
|
||||||
|
Garantimos:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Análise regular dos resultados</li>
|
||||||
|
<li>Reuniões de acompanhamento</li>
|
||||||
|
<li>Ajustes baseados no feedback</li>
|
||||||
|
<li>Otimização contínua do processo</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
Resultados Comprovados
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Escolas que implementaram a Histórias Mágicas relatam:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6 mt-6">
|
||||||
|
<div className="bg-white shadow-lg rounded-xl p-6">
|
||||||
|
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-purple-600 text-white mb-4">
|
||||||
|
<Star className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Melhoria na Leitura</h3>
|
||||||
|
<p className="mt-2 text-4xl font-bold text-purple-600">85%</p>
|
||||||
|
<p className="mt-2 text-gray-600">
|
||||||
|
dos alunos apresentam melhoria significativa nas habilidades de leitura em 6 meses
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white shadow-lg rounded-xl p-6">
|
||||||
|
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-purple-600 text-white mb-4">
|
||||||
|
<Users className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Engajamento</h3>
|
||||||
|
<p className="mt-2 text-4xl font-bold text-purple-600">300%</p>
|
||||||
|
<p className="mt-2 text-gray-600">
|
||||||
|
de aumento no engajamento dos alunos com atividades de leitura
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white shadow-lg rounded-xl p-6">
|
||||||
|
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-purple-600 text-white mb-4">
|
||||||
|
<Clock className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Tempo de Aprendizado</h3>
|
||||||
|
<p className="mt-2 text-4xl font-bold text-purple-600">40%</p>
|
||||||
|
<p className="mt-2 text-gray-600">
|
||||||
|
de redução no tempo necessário para atingir proficiência em leitura
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white shadow-lg rounded-xl p-6">
|
||||||
|
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-purple-600 text-white mb-4">
|
||||||
|
<CheckCircle className="h-6 w-6" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-gray-900">Satisfação</h3>
|
||||||
|
<p className="mt-2 text-4xl font-bold text-purple-600">95%</p>
|
||||||
|
<p className="mt-2 text-gray-600">
|
||||||
|
de satisfação entre professores, pais e alunos
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-purple-50 p-6 rounded-xl mt-12">
|
||||||
|
<h3 className="text-xl font-bold text-purple-800 mb-4">Depoimentos</h3>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="border-l-4 border-purple-600 pl-4">
|
||||||
|
<p className="text-purple-800 italic">
|
||||||
|
"A transformação que vimos em nossa escola foi incrível. Alunos que mal conseguiam
|
||||||
|
juntar letras agora estão lendo com fluência e, mais importante, com prazer. A
|
||||||
|
Histórias Mágicas não é apenas uma plataforma, é uma revolução na alfabetização."
|
||||||
|
</p>
|
||||||
|
<p className="text-purple-600 mt-2 font-semibold">
|
||||||
|
- Maria Silva, Diretora Pedagógica
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border-l-4 border-purple-600 pl-4">
|
||||||
|
<p className="text-purple-800 italic">
|
||||||
|
"Como professora há 15 anos, nunca vi um método tão eficaz e envolvente. A
|
||||||
|
plataforma me ajuda a personalizar o ensino para cada aluno, e os resultados
|
||||||
|
são visíveis desde as primeiras semanas."
|
||||||
|
</p>
|
||||||
|
<p className="text-purple-600 mt-2 font-semibold">
|
||||||
|
- Ana Paula Santos, Professora
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border-l-4 border-purple-600 pl-4">
|
||||||
|
<p className="text-purple-800 italic">
|
||||||
|
"Meu filho sempre teve dificuldade com leitura e isso afetava sua autoestima.
|
||||||
|
Desde que começamos a usar a Histórias Mágicas, ele não só melhorou na leitura,
|
||||||
|
mas recuperou a confiança e o prazer de aprender."
|
||||||
|
</p>
|
||||||
|
<p className="text-purple-600 mt-2 font-semibold">
|
||||||
|
- Carlos Oliveira, Pai de aluno
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 mt-12">
|
||||||
|
Investimento no Futuro
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Quando você investe na Histórias Mágicas, está investindo em:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul className="list-disc pl-6 space-y-2 mt-2">
|
||||||
|
<li>Método cientificamente comprovado de alfabetização</li>
|
||||||
|
<li>Plataforma tecnológica de ponta</li>
|
||||||
|
<li>Suporte pedagógico especializado</li>
|
||||||
|
<li>Formação continuada para professores</li>
|
||||||
|
<li>Acompanhamento personalizado dos alunos</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="mt-12 text-center">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate('/register')}
|
||||||
|
className="inline-flex items-center px-8 py-4 bg-purple-600 text-white rounded-xl
|
||||||
|
font-semibold hover:bg-purple-700 transition-colors"
|
||||||
|
>
|
||||||
|
Transforme Sua Escola Agora
|
||||||
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-gray-50 p-6 rounded-xl mt-12">
|
||||||
|
<h3 className="text-xl font-bold text-gray-900 mb-4">Nossa Garantia</h3>
|
||||||
|
<p>
|
||||||
|
Oferecemos uma garantia de satisfação de 30 dias. Se você não ver resultados
|
||||||
|
concretos em um mês de uso da plataforma, devolvemos seu investimento
|
||||||
|
integralmente. Não há riscos - apenas a oportunidade de fazer uma diferença
|
||||||
|
real na educação de seus alunos.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-purple-50 p-6 rounded-xl mt-12">
|
||||||
|
<h3 className="text-xl font-bold text-purple-800 mb-4">Próximos Passos</h3>
|
||||||
|
<p className="text-purple-900">
|
||||||
|
1. Clique no botão acima para iniciar seu cadastro<br />
|
||||||
|
2. Nossa equipe entrará em contato em até 24 horas<br />
|
||||||
|
3. Realizaremos uma demonstração personalizada<br />
|
||||||
|
4. Desenvolveremos um plano de implementação específico para sua escola<br />
|
||||||
|
5. Em poucos dias, sua escola estará transformando a vida de seus alunos
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-500 mt-8">
|
||||||
|
P.S.: A revolução na alfabetização está acontecendo agora. Não deixe sua escola
|
||||||
|
para trás. Junte-se às milhares de instituições que já descobriram o poder da
|
||||||
|
educação baseada em evidências com a Histórias Mágicas.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -31,11 +31,22 @@ import { EducationalForParents } from './pages/landing/EducationalForParents';
|
|||||||
import { TestWordHighlighter } from './pages/TestWordHighlighter';
|
import { TestWordHighlighter } from './pages/TestWordHighlighter';
|
||||||
import { ExercisePage } from './pages/student-dashboard/ExercisePage';
|
import { ExercisePage } from './pages/student-dashboard/ExercisePage';
|
||||||
import { EvidenceBased } from './pages/landing/EvidenceBased';
|
import { EvidenceBased } from './pages/landing/EvidenceBased';
|
||||||
|
import { TextSalesLetter } from './pages/landing/TextSalesLetter';
|
||||||
|
import { PageTracker } from './components/analytics/PageTracker';
|
||||||
|
|
||||||
|
function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageTracker />
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const router = createBrowserRouter([
|
export const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
element: <HomePage />,
|
element: <RootLayout><HomePage /></RootLayout>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/teste',
|
path: '/teste',
|
||||||
@ -49,6 +60,10 @@ export const router = createBrowserRouter([
|
|||||||
path: '/evidencias',
|
path: '/evidencias',
|
||||||
element: <EvidenceBased />,
|
element: <EvidenceBased />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/evidencias/tsl',
|
||||||
|
element: <TextSalesLetter />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -5,7 +5,11 @@ name = "Histórias Mágicas"
|
|||||||
[auth]
|
[auth]
|
||||||
enabled = true
|
enabled = true
|
||||||
site_url = "https://historiasmagicas.netlify.app"
|
site_url = "https://historiasmagicas.netlify.app"
|
||||||
additional_redirect_urls = ["https://historiasmagicas.netlify.app", "https://*.historiasmagicas.netlify.app"]
|
additional_redirect_urls = [
|
||||||
|
"https://historiasmagicas.netlify.app/*",
|
||||||
|
"http://localhost:5173/*",
|
||||||
|
"http://localhost:3000/*"
|
||||||
|
]
|
||||||
jwt_expiry = 3600
|
jwt_expiry = 3600
|
||||||
enable_refresh_token_rotation = true
|
enable_refresh_token_rotation = true
|
||||||
refresh_token_reuse_interval = 10
|
refresh_token_reuse_interval = 10
|
||||||
@ -18,7 +22,7 @@ verify_enabled = true
|
|||||||
enable_signup = true
|
enable_signup = true
|
||||||
double_confirm_changes = true
|
double_confirm_changes = true
|
||||||
enable_confirmations = true
|
enable_confirmations = true
|
||||||
secure_password_change = false
|
secure_password_change = true
|
||||||
max_frequency = "1m0s"
|
max_frequency = "1m0s"
|
||||||
otp_length = 6
|
otp_length = 6
|
||||||
otp_expiry = 86400
|
otp_expiry = 86400
|
||||||
@ -38,9 +42,25 @@ enabled = true
|
|||||||
file_size_limit = "50MB"
|
file_size_limit = "50MB"
|
||||||
|
|
||||||
[storage.cors]
|
[storage.cors]
|
||||||
allowed_origins = ["*"]
|
allowed_origins = [
|
||||||
|
"https://historiasmagicas.netlify.app",
|
||||||
|
"http://localhost:5173",
|
||||||
|
"http://localhost:3000"
|
||||||
|
]
|
||||||
allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
|
allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
|
||||||
allowed_headers = ["*"]
|
allowed_headers = [
|
||||||
|
"Authorization",
|
||||||
|
"Content-Type",
|
||||||
|
"Accept",
|
||||||
|
"Origin",
|
||||||
|
"User-Agent",
|
||||||
|
"DNT",
|
||||||
|
"Cache-Control",
|
||||||
|
"X-Mx-ReqToken",
|
||||||
|
"Keep-Alive",
|
||||||
|
"X-Requested-With",
|
||||||
|
"If-Modified-Since"
|
||||||
|
]
|
||||||
exposed_headers = ["Content-Range", "Range"]
|
exposed_headers = ["Content-Range", "Range"]
|
||||||
max_age = 3600
|
max_age = 3600
|
||||||
|
|
||||||
@ -53,9 +73,25 @@ max_rows = 1000
|
|||||||
|
|
||||||
[api.cors]
|
[api.cors]
|
||||||
enabled = true
|
enabled = true
|
||||||
allowed_origins = ["*"]
|
allowed_origins = [
|
||||||
|
"https://historiasmagicas.netlify.app",
|
||||||
|
"http://localhost:5173",
|
||||||
|
"http://localhost:3000"
|
||||||
|
]
|
||||||
allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
|
allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
|
||||||
allowed_headers = ["*"]
|
allowed_headers = [
|
||||||
|
"Authorization",
|
||||||
|
"Content-Type",
|
||||||
|
"Accept",
|
||||||
|
"Origin",
|
||||||
|
"User-Agent",
|
||||||
|
"DNT",
|
||||||
|
"Cache-Control",
|
||||||
|
"X-Mx-ReqToken",
|
||||||
|
"Keep-Alive",
|
||||||
|
"X-Requested-With",
|
||||||
|
"If-Modified-Since"
|
||||||
|
]
|
||||||
exposed_headers = ["Content-Range", "Range"]
|
exposed_headers = ["Content-Range", "Range"]
|
||||||
max_age = 3600
|
max_age = 3600
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user