Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions public/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,37 @@
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://monynha.com/</loc>
<lastmod>2026-03-07</lastmod>
<lastmod>2026-03-22</lastmod>
<changefreq>weekly</changefreq>
<priority>1</priority>
</url>
<url>
<loc>https://monynha.com/about</loc>
<lastmod>2026-03-07</lastmod>
<lastmod>2026-03-22</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://monynha.com/projects</loc>
<lastmod>2026-03-07</lastmod>
<lastmod>2026-03-22</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc>https://monynha.com/privacy</loc>
<lastmod>2026-03-07</lastmod>
<lastmod>2026-03-22</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://monynha.com/terms</loc>
<lastmod>2026-03-07</lastmod>
<lastmod>2026-03-22</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://monynha.com/cookies</loc>
<lastmod>2026-03-07</lastmod>
<lastmod>2026-03-22</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
Expand Down
2 changes: 1 addition & 1 deletion src/components/LoadingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ const LoadingScreen: React.FC<LoadingScreenProps> = ({ isDone }) => {
<>
<p className="text-green-400 font-bold uppercase">&gt; [SUCCESS] Diagnosis generated successfully!</p>
<p className="text-green-400 font-bold uppercase">&gt; [SUCCESS] Lead stored in Database...</p>
<p className="text-green-400 font-bold uppercase">&gt; [SUCCESS] Strategies polished with Gemini AI...</p>
<p className="text-green-400 font-bold uppercase">&gt; [SUCCESS] Strategies polished with OpenAI...</p>
<p className="text-white">&gt; [SYSTEM] Redirecting to report module in 3, 2, 1...</p>
</>
) : (
Expand Down
9 changes: 9 additions & 0 deletions src/components/Wizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,15 @@ const Wizard: React.FC<WizardProps> = ({ onComplete, onCancel, error }) => {

<main className="flex-grow flex items-center justify-center w-full max-w-7xl mx-auto py-1 sm:py-2 relative z-10 overflow-hidden min-h-[250px] sm:min-h-[350px]">
<form onSubmit={handleSubmit} className="w-full h-full relative">
{error && (
<div
role="alert"
className="mb-4 sm:mb-6 mx-auto max-w-3xl px-4 py-3 sm:px-6 sm:py-4 bg-red-50 border-2 border-red-500 rounded-xl text-red-800 font-bold text-sm sm:text-base"
>
{error}
</div>
)}

{renderStep()}

<div className="flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4 mt-4 sm:mt-6 pt-4 sm:pt-6 border-t-2 border-near-black/5 px-4">
Expand Down
2 changes: 1 addition & 1 deletion src/services/geminiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const generateDiagnosis = async (data: LeadData): Promise<DiagnosisResult

return result;
} catch (error) {
console.error("Gemini Error:", error);
console.error('AI Diagnosis Error:', error);
return {
title: "Mona, o sistema deu uma piscada!",
description: "Teu negócio tem potencial, mas a tecnologia aqui deu um close errado agora. Pelo que sinto na minha intuição de CEO, você precisa de estrutura e menos achismo.",
Expand Down
17 changes: 14 additions & 3 deletions src/services/supabaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ import { LeadData, DiagnosisResult } from '../types';
*/

// Initialize Supabase client
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL || 'https://your-project.supabase.co';
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY || 'your-anon-key';
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

if (!supabaseUrl || !supabaseKey) {
throw new Error(
'Supabase configuration is missing. Please set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.'
);
}

export const supabase = createClient<Database>(supabaseUrl, supabaseKey);

Expand Down Expand Up @@ -43,7 +49,12 @@ export const saveLead = async (data: LeadData, diagnosis: DiagnosisResult) => {
);

if (error) {
console.error("❌ Error saving lead to Supabase:", error.message);
console.error('❌ Error saving lead to Supabase:', {
message: error.message,
code: error.code,
details: error.details,
hint: error.hint,
});
throw error;
}

Expand Down
128 changes: 123 additions & 5 deletions supabase/functions/company-search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ const logEdgeCall = async (input: {
metadata?: Record<string, unknown>;
}) => {
const supabaseUrl = Deno.env.get("SUPABASE_URL");
const supabaseAnonKey = Deno.env.get("SUPABASE_ANON_KEY");
if (!supabaseUrl || !supabaseAnonKey) return;
const supabaseServiceRoleKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? Deno.env.get("SUPABASE_ANON_KEY");
if (!supabaseUrl || !supabaseServiceRoleKey) return;

try {
const supabase = createClient(supabaseUrl, supabaseAnonKey, { auth: { persistSession: false } });
const supabase = createClient(supabaseUrl, supabaseServiceRoleKey, { auth: { persistSession: false } });
await supabase.rpc("log_edge_function_call", {
p_function_name: input.functionName,
p_lead_email: input.leadEmail ?? null,
Expand Down Expand Up @@ -94,6 +94,96 @@ const extractMeta = (html: string) => {
};
};

const analyzeWithOpenAI = async (input: {
query: string;
website?: string;
instagram?: string;
linkedin?: string;
websiteTitle?: string;
websiteDescription?: string;
}) => {
const apiKey = Deno.env.get("OPENAI_API_KEY");
if (!apiKey) {
throw new Error("OPENAI_API_KEY not configured");
}

const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
},
body: JSON.stringify({
model: "gpt-4o-mini",
temperature: 0.2,
response_format: {
type: "json_schema",
json_schema: {
name: "company_search_result",
strict: true,
schema: {
type: "object",
additionalProperties: false,
properties: {
name: { type: "string" },
summary: { type: "string" },
signals: {
type: "object",
additionalProperties: false,
properties: {
marketPosition: { type: "string" },
digitalMaturity: { type: "string" },
confidence: { type: "string" },
},
required: ["marketPosition", "digitalMaturity", "confidence"],
},
},
required: ["name", "summary", "signals"],
},
},
},
messages: [
{
role: "system",
content: "Analise sinais digitais de empresas e retorne resumo objetivo em português.",
},
{
role: "user",
content:
`Empresa: ${input.query || "não informado"}\n` +
`Website: ${input.website || "não informado"}\n` +
`Instagram: ${input.instagram || "não informado"}\n` +
`LinkedIn: ${input.linkedin || "não informado"}\n` +
`Título do site: ${input.websiteTitle || "não informado"}\n` +
`Descrição do site: ${input.websiteDescription || "não informado"}\n` +
"Gere um resumo breve da proposta de valor e maturidade digital com indicação de confiança.",
},
],
}),
});

if (!response.ok) {
const bodyText = await response.text();
throw new Error(`OpenAI error ${response.status}: ${bodyText.slice(0, 300)}`);
}

const payload = await response.json();
const content = payload?.choices?.[0]?.message?.content;
if (typeof content !== "string") {
throw new Error("OpenAI returned empty content");
}

return JSON.parse(content) as {
name: string;
summary: string;
signals: {
marketPosition: string;
digitalMaturity: string;
confidence: string;
};
};
};

serve(async (req) => {
if (req.method === "OPTIONS") {
return new Response("ok", { headers: corsHeaders });
Expand Down Expand Up @@ -147,15 +237,43 @@ serve(async (req) => {
}
}

let aiAnalysis:
| {
name: string;
summary: string;
signals: {
marketPosition: string;
digitalMaturity: string;
confidence: string;
};
}
| null = null;

try {
aiAnalysis = await analyzeWithOpenAI({
query,
website: website || undefined,
instagram,
linkedin,
websiteTitle,
websiteDescription,
});
} catch (error) {
warnings.push(error instanceof Error ? `AI analysis unavailable: ${error.message}` : "AI analysis unavailable.");
}

const result = {
name: query || undefined,
name: aiAnalysis?.name || query || undefined,
website: website || undefined,
instagram: normalizeHandle(instagram),
linkedin: linkedin || undefined,
summary: websiteDescription || undefined,
summary: aiAnalysis?.summary || websiteDescription || undefined,
signals: {
websiteTitle: websiteTitle || "",
websiteDescription: websiteDescription || "",
marketPosition: aiAnalysis?.signals.marketPosition || "",
digitalMaturity: aiAnalysis?.signals.digitalMaturity || "",
confidence: aiAnalysis?.signals.confidence || "",
},
warnings,
};
Expand Down
Loading
Loading