Skip to content

Commit 978f800

Browse files
committed
feat: add Convex integration, new sections, and UI improvements
- Add Convex backend integration with contact form actions - Add new sections: Benefits, ContactFormHybrid, Derivative, Mission, NetworkRecoverySteps, Services, Supporters, UnicornStudioEffect - Refactor Slider component into separate index and script files - Update Icon component and remove old Testimonials section - Add 3D scene JSON files and background SVG - Update Tailwind config and styles - Add package.json and wrangler.toml for deployment
1 parent d36dfe1 commit 978f800

43 files changed

Lines changed: 7240 additions & 781 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,55 @@
11
{
2-
"name": "Home",
3-
"path": "/",
4-
"sections": [
5-
{
6-
"__resolveType": "Header"
7-
},
8-
{
9-
"__resolveType": "site/sections/Hero.tsx",
10-
"title": "<p>Click here to tweak this text however you want.</p>",
11-
"cta": [],
12-
"description": "This text is fully editable and ready for your personal touch. Just click here, head over to the section window, or dive straight into the code to make changes as you see fit. Whether it's about the content, formatting, font, or anything in between, editing is just a click away."
13-
},
14-
{
15-
"__resolveType": "site/sections/Logos.tsx"
16-
},
17-
{
18-
"__resolveType": "site/sections/ImageWithParagraph.tsx"
19-
},
20-
{
21-
"__resolveType": "site/sections/ImageWithParagraph.tsx",
22-
"placement": "right"
23-
},
24-
{
25-
"__resolveType": "site/sections/BlogPosts.tsx"
26-
},
27-
{
28-
"__resolveType": "site/sections/Testimonials.tsx",
29-
"arrows": true
30-
},
31-
{
2+
"name": "Home",
3+
"path": "/",
4+
"sections": [
5+
{
6+
"__resolveType": "Header"
7+
},
8+
{
9+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
10+
"section": {
11+
"__resolveType": "site/sections/Derivative.tsx"
12+
}
13+
},
14+
{
15+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
16+
"section": {
17+
"__resolveType": "site/sections/NetworkRecoverySteps.tsx"
18+
}
19+
},
20+
{
21+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
22+
"section": {
23+
"__resolveType": "site/sections/Services.tsx"
24+
}
25+
},
26+
{
27+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
28+
"section": {
29+
"__resolveType": "site/sections/Benefits.tsx"
30+
}
31+
},
32+
{
33+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
34+
"section": {
35+
"__resolveType": "site/sections/Mission.tsx"
36+
}
37+
},
38+
{
39+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
40+
"section": {
3241
"__resolveType": "site/sections/Faq.tsx"
33-
},
34-
{
35-
"__resolveType": "Footer"
3642
}
37-
],
38-
"__resolveType": "website/pages/Page.tsx",
39-
"seo": {
40-
"__resolveType": "website/sections/Seo/SeoV2.tsx"
43+
},
44+
{
45+
"__resolveType": "website/sections/Rendering/Lazy.tsx",
46+
"section": {
47+
"__resolveType": "site/sections/ContactFormHybrid.tsx"
48+
}
4149
}
42-
}
50+
],
51+
"__resolveType": "website/pages/Page.tsx",
52+
"seo": {
53+
"__resolveType": "website/sections/Seo/SeoV2.tsx"
54+
}
55+
}

.deco/metadata/blocks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"/.deco/blocks/Mobile.json":{"blockType":"matchers","__resolveType":"website/matchers/device.ts"},"/.deco/blocks/Preview%20%2Fsections%2FHero.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Hero.tsx"},"/.deco/blocks/Header.json":{"blockType":"sections","__resolveType":"site/sections/Header.tsx"},"/.deco/blocks/Faq%20-%20default.json":{"blockType":"sections","__resolveType":"site/sections/Faq.tsx"},"/.deco/blocks/pages-home-5afd25174424.json":{"name":"Home","path":"/","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Sunset%20Glow.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/pages-test-3c04f2690620.json":{"name":"Test","path":"/test","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Preview%20Sections%20MyHero.json":{"blockType":"sections","__resolveType":"site/sections/myHero.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FFaq.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Faq.tsx"},"/.deco/blocks/app-site%252Fapps%252Fsite.ts.json":{"blockType":"apps","__resolveType":"site/apps/site.ts"},"/.deco/blocks/deco-htmx.json":{"blockType":"apps","__resolveType":"site/apps/deco/htmx.ts"},"/.deco/blocks/Urban%20Chic.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/site.json":{"blockType":"apps","__resolveType":"site/apps/site.ts"},"/.deco/blocks/deco-blog.json":{"blockType":"apps","__resolveType":"site/apps/deco/blog.ts"},"/.deco/blocks/hero.json":{"blockType":"sections","__resolveType":"site/sections/Hero.tsx"},"/.deco/blocks/Preview Sections MyHero.json":{"blockType":"sections","__resolveType":"site/sections/myHero.tsx"},"/.deco/blocks/Serene%20Coastline.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Neutral.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Vanilla.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Preview%20%2Fsections%2Fhero-1.tsx.json":{"blockType":"sections","__resolveType":"site/sections/hero-1.tsx"},"/.deco/blocks/pages-Landing-945097.json":{"name":"Landing","path":"/landing","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Footer.json":{"blockType":"sections","__resolveType":"site/sections/Footer.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FPoweredByDeco.tsx.json":{"blockType":"sections","__resolveType":"site/sections/PoweredByDeco.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FImageWithParagraph.tsx.json":{"blockType":"sections","__resolveType":"site/sections/ImageWithParagraph.tsx"},"/.deco/blocks/Preview%20%2Fsections%2Fhero-2.tsx.json":{"blockType":"sections","__resolveType":"site/sections/hero-2.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FHeader.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Header.tsx"},"/.deco/blocks/pages-mynewpage-a771a8f0fda6.json":{"name":"My New Page","path":"/example-path","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Groovy%20Vibes.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Preview%20site%2Fsections%2FImageWithParagraph.tsx.json":{"blockType":"sections","__resolveType":"site/sections/ImageWithParagraph.tsx"},"/.deco/blocks/Desktop.json":{"blockType":"matchers","__resolveType":"website/matchers/device.ts"},"/.deco/blocks/Preview%20%2Fsections%2FFooter.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Footer.tsx"}}
1+
{"/.deco/blocks/Preview Sections MyHero.json":{"blockType":"sections","__resolveType":"site/sections/myHero.tsx"},"/.deco/blocks/pages-home-5afd25174424.json":{"name":"Home","path":"/","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/site.json":{"blockType":"apps","__resolveType":"site/apps/site.ts"},"/.deco/blocks/Header.json":{"blockType":"sections","__resolveType":"site/sections/Header.tsx"},"/.deco/blocks/app-site%252Fapps%252Fsite.ts.json":{"blockType":"apps","__resolveType":"site/apps/site.ts"},"/.deco/blocks/Serene%20Coastline.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Sunset%20Glow.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Footer.json":{"blockType":"sections","__resolveType":"site/sections/Footer.tsx"},"/.deco/blocks/pages-test-3c04f2690620.json":{"name":"Test","path":"/test","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FImageWithParagraph.tsx.json":{"blockType":"sections","__resolveType":"site/sections/ImageWithParagraph.tsx"},"/.deco/blocks/pages-mynewpage-a771a8f0fda6.json":{"name":"My New Page","path":"/example-path","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Groovy%20Vibes.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Preview%20%2Fsections%2Fhero-2.tsx.json":{"blockType":"sections","__resolveType":"site/sections/hero-2.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FHero.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Hero.tsx"},"/.deco/blocks/Mobile.json":{"blockType":"matchers","__resolveType":"website/matchers/device.ts"},"/.deco/blocks/Preview%20Sections%20MyHero.json":{"blockType":"sections","__resolveType":"site/sections/myHero.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FPoweredByDeco.tsx.json":{"blockType":"sections","__resolveType":"site/sections/PoweredByDeco.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FFaq.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Faq.tsx"},"/.deco/blocks/Urban%20Chic.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Faq%20-%20default.json":{"blockType":"sections","__resolveType":"site/sections/Faq.tsx"},"/.deco/blocks/pages-Landing-945097.json":{"name":"Landing","path":"/landing","blockType":"pages","__resolveType":"website/pages/Page.tsx"},"/.deco/blocks/Neutral.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/Preview%20site%2Fsections%2FImageWithParagraph.tsx.json":{"blockType":"sections","__resolveType":"site/sections/ImageWithParagraph.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FFooter.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Footer.tsx"},"/.deco/blocks/Preview%20%2Fsections%2FHeader.tsx.json":{"blockType":"sections","__resolveType":"site/sections/Header.tsx"},"/.deco/blocks/Vanilla.json":{"blockType":"sections","__resolveType":"site/sections/Theme/Theme.tsx"},"/.deco/blocks/deco-blog.json":{"blockType":"apps","__resolveType":"site/apps/deco/blog.ts"},"/.deco/blocks/Preview%20%2Fsections%2Fhero-1.tsx.json":{"blockType":"sections","__resolveType":"site/sections/hero-1.tsx"},"/.deco/blocks/deco-htmx.json":{"blockType":"apps","__resolveType":"site/apps/deco/htmx.ts"},"/.deco/blocks/hero.json":{"blockType":"sections","__resolveType":"site/sections/Hero.tsx"},"/.deco/blocks/Desktop.json":{"blockType":"matchers","__resolveType":"website/matchers/device.ts"}}

actions/contactFormConvex.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { AppContext } from "../apps/site.ts";
2+
3+
export interface Props {
4+
nome: string;
5+
email: string;
6+
mensagem: string;
7+
}
8+
9+
export default async function ContactFormConvexAction(
10+
props: Props,
11+
req: Request,
12+
ctx: AppContext,
13+
) {
14+
try {
15+
console.log("🚀 ContactFormConvexAction chamada com:", props);
16+
17+
// Validar dados de entrada
18+
if (!props.nome || !props.email || !props.mensagem) {
19+
return {
20+
success: false,
21+
message: "Todos os campos são obrigatórios.",
22+
};
23+
}
24+
25+
// Validar formato do email
26+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
27+
if (!emailRegex.test(props.email)) {
28+
return {
29+
success: false,
30+
message: "Por favor, insira um email válido.",
31+
};
32+
}
33+
34+
// URL correta do Convex HTTP Actions
35+
const CONVEX_HTTP_URL = "https://precise-cassowary-240.convex.site";
36+
37+
console.log("🔄 Chamando Convex HTTP API...");
38+
39+
// Chamar a função do Convex via HTTP Actions
40+
const response = await fetch(`${CONVEX_HTTP_URL}/api/mutations/contatos/submitContactForm`, {
41+
method: "POST",
42+
headers: {
43+
"Content-Type": "application/json",
44+
},
45+
body: JSON.stringify({
46+
nome: props.nome.trim(),
47+
email: props.email.trim().toLowerCase(),
48+
mensagem: props.mensagem.trim(),
49+
}),
50+
});
51+
52+
console.log("📡 Resposta do Convex:", response.status, response.statusText);
53+
54+
if (!response.ok) {
55+
const errorText = await response.text();
56+
console.error("❌ Erro da API Convex:", errorText);
57+
throw new Error(`Convex API error: ${response.status} - ${errorText}`);
58+
}
59+
60+
const result = await response.json();
61+
console.log("✅ Dados salvos no Convex:", result);
62+
63+
return {
64+
success: true,
65+
message: "Mensagem enviada com sucesso! Entraremos em contato em breve.",
66+
id: result.id,
67+
};
68+
} catch (error) {
69+
console.error("❌ Erro ao salvar no Convex:", error);
70+
return {
71+
success: false,
72+
message: "Erro ao enviar mensagem. Tente novamente em alguns instantes.",
73+
};
74+
}
75+
}

actions/contactFormConvexFixed.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { AppContext } from "../apps/site.ts";
2+
3+
export interface Props {
4+
nome: string;
5+
email: string;
6+
mensagem: string;
7+
}
8+
9+
export default async function ContactFormConvexFixedAction(
10+
props: Props,
11+
req: Request,
12+
ctx: AppContext,
13+
) {
14+
try {
15+
console.log("🚀 ContactFormConvexFixedAction chamada com:", props);
16+
17+
// Validar dados de entrada
18+
if (!props.nome || !props.email || !props.mensagem) {
19+
return {
20+
success: false,
21+
message: "Todos os campos são obrigatórios.",
22+
};
23+
}
24+
25+
// Validar formato do email
26+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
27+
if (!emailRegex.test(props.email)) {
28+
return {
29+
success: false,
30+
message: "Por favor, insira um email válido.",
31+
};
32+
}
33+
34+
// URL correta do Convex HTTP Actions
35+
const CONVEX_HTTP_URL = "https://precise-cassowary-240.convex.site";
36+
37+
console.log("🔄 Chamando Convex HTTP API...");
38+
console.log("📡 URL:", `${CONVEX_HTTP_URL}/api/mutations/contatos/submitContactForm`);
39+
40+
// Chamar a função do Convex via HTTP Actions
41+
const response = await fetch(`${CONVEX_HTTP_URL}/api/mutations/contatos/submitContactForm`, {
42+
method: "POST",
43+
headers: {
44+
"Content-Type": "application/json",
45+
},
46+
body: JSON.stringify({
47+
nome: props.nome.trim(),
48+
email: props.email.trim().toLowerCase(),
49+
mensagem: props.mensagem.trim(),
50+
}),
51+
});
52+
53+
console.log("📡 Resposta do Convex:", response.status, response.statusText);
54+
55+
if (!response.ok) {
56+
const errorText = await response.text();
57+
console.error("❌ Erro da API Convex:", errorText);
58+
throw new Error(`Convex API error: ${response.status} - ${errorText}`);
59+
}
60+
61+
const result = await response.json();
62+
console.log("✅ Dados salvos no Convex:", result);
63+
64+
return {
65+
success: true,
66+
message: "Mensagem enviada com sucesso! Entraremos em contato em breve.",
67+
id: result.id,
68+
};
69+
} catch (error) {
70+
console.error("❌ Erro ao salvar no Convex:", error);
71+
return {
72+
success: false,
73+
message: "Erro ao enviar mensagem. Tente novamente em alguns instantes.",
74+
};
75+
}
76+
}

actions/submitToConvex.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { AppContext } from "../apps/site.ts";
2+
import { ConvexHttpClient } from "convex/browser";
3+
4+
export interface Props {
5+
nome: string;
6+
email: string;
7+
mensagem: string;
8+
}
9+
10+
export default async function SubmitToConvexAction(
11+
props: Props,
12+
req: Request,
13+
ctx: AppContext,
14+
) {
15+
try {
16+
console.log("🚀 SubmitToConvexAction chamada com:", props);
17+
18+
// Validar dados de entrada
19+
if (!props.nome || !props.email || !props.mensagem) {
20+
return {
21+
success: false,
22+
message: "Todos os campos são obrigatórios.",
23+
};
24+
}
25+
26+
// Validar formato do email
27+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
28+
if (!emailRegex.test(props.email)) {
29+
return {
30+
success: false,
31+
message: "Por favor, insira um email válido.",
32+
};
33+
}
34+
35+
// URL do Convex (production)
36+
const convexUrl = "https://watchful-capybara-907.convex.cloud";
37+
38+
console.log("🔄 Chamando Convex via HTTP Client...");
39+
40+
// Usar ConvexHttpClient para chamar a mutation
41+
const client = new ConvexHttpClient(convexUrl);
42+
43+
const result = await client.mutation("contatos:submitContactForm", {
44+
nome: props.nome.trim(),
45+
email: props.email.trim().toLowerCase(),
46+
mensagem: props.mensagem.trim()
47+
});
48+
49+
console.log("✅ Dados salvos no Convex:", result);
50+
51+
return {
52+
success: true,
53+
message: "Mensagem enviada com sucesso! Entraremos em contato em breve.",
54+
id: result.id,
55+
};
56+
57+
} catch (error) {
58+
console.error("❌ Erro ao salvar no Convex:", error);
59+
return {
60+
success: false,
61+
message: "Erro ao enviar mensagem. Tente novamente em alguns instantes.",
62+
};
63+
}
64+
}

components/ui/Icon.tsx

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,45 @@ import { asset } from "$fresh/runtime.ts";
22
import type { JSX } from "preact";
33

44
export type AvailableIcons =
5-
| "ArrowLeft"
6-
| "ArrowRight"
7-
| "ArrowsPointingOut"
8-
| "Bars3"
95
| "ChevronLeft"
106
| "ChevronRight"
117
| "ChevronUp"
128
| "ChevronDown"
13-
| "CreditCard"
14-
| "Deco"
15-
| "Diners"
16-
| "Discord"
17-
| "Discount"
18-
| "Elo"
19-
| "Facebook"
20-
| "FilterList"
9+
| "QuestionMarkCircle"
10+
| "User"
11+
| "ShoppingCart"
12+
| "Bars3"
2113
| "Heart"
22-
| "Instagram"
23-
| "Linkedin"
14+
| "MagnifyingGlass"
15+
| "XMark"
16+
| "Plus"
2417
| "Minus"
2518
| "MapPin"
26-
| "MagnifyingGlass"
27-
| "Mastercard"
28-
| "Message"
2919
| "Phone"
20+
| "Elo"
21+
| "Mastercard"
22+
| "Visa"
3023
| "Pix"
31-
| "Plus"
32-
| "QuestionMarkCircle"
33-
| "Return"
34-
| "Ruler"
35-
| "ShoppingCart"
36-
| "Star"
24+
| "Logo"
25+
| "Facebook"
26+
| "Instagram"
3727
| "Tiktok"
38-
| "Trash"
3928
| "Truck"
40-
| "Twitter"
41-
| "User"
42-
| "Visa"
29+
| "Discount"
30+
| "Return"
31+
| "CreditCard"
32+
| "Deco"
33+
| "Discord"
34+
| "Trash"
35+
| "FilterList"
4336
| "WhatsApp"
44-
| "XMark"
45-
| "Zoom";
37+
| "ArrowsPointingOut"
38+
| "Linkedin"
39+
| "XTwitter"
40+
| "Link"
41+
| "LinkedinOutline"
42+
| "FacebookOutline"
43+
| "TwitterOutline";
4644

4745
interface Props extends JSX.SVGAttributes<SVGSVGElement> {
4846
/**

0 commit comments

Comments
 (0)