Skip to content

Commit 44d901b

Browse files
committed
update: added brand autofill on onboarding step
1 parent 943d70a commit 44d901b

File tree

3 files changed

+276
-6
lines changed

3 files changed

+276
-6
lines changed

next.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ const nextConfig: NextConfig = {
1111
protocol: 'https',
1212
hostname: 'cdn.brandfetch.io',
1313
pathname: '/**',
14+
},
15+
{
16+
protocol: 'https',
17+
hostname: 'image-save-1029-final.s3.amazonaws.com',
18+
pathname: '/**',
1419
}
1520
],
1621
},
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
3+
export async function POST(request: NextRequest) {
4+
try {
5+
const { website } = await request.json();
6+
7+
if (!website) {
8+
return NextResponse.json(
9+
{ error: "Website URL is required" },
10+
{ status: 400 }
11+
);
12+
}
13+
14+
// Call the external autofill endpoint
15+
const response = await fetch(
16+
"https://automations.ideacharge.com/webhook/onboardingautofill",
17+
{
18+
method: "POST",
19+
headers: {
20+
"Content-Type": "application/json",
21+
},
22+
body: JSON.stringify({
23+
chatInput: website,
24+
}),
25+
}
26+
);
27+
28+
if (!response.ok) {
29+
console.error("External API error:", response.status, response.statusText);
30+
return NextResponse.json(
31+
{ error: `External API error: ${response.status}` },
32+
{ status: response.status }
33+
);
34+
}
35+
36+
const data = await response.json();
37+
38+
// Return the autofill data
39+
return NextResponse.json({
40+
success: true,
41+
data: data.output,
42+
});
43+
} catch (error) {
44+
console.error("Onboarding autofill error:", error);
45+
return NextResponse.json(
46+
{ error: "Failed to fetch autofill data" },
47+
{ status: 500 }
48+
);
49+
}
50+
}

src/app/onboarding/page.tsx

Lines changed: 221 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { supabase } from "@/lib/supabase";
55
import { v4 as uuidv4 } from "uuid";
66
import { useEffect, useRef, useState } from "react";
77

8-
import { Check, Clock } from "lucide-react";
8+
import { Check, Clock, Loader2 } from "lucide-react";
99
import { Button } from "@/components/ui/button";
1010
import { useRouter, useSearchParams } from "next/navigation";
1111
import { UserSubscription } from "@/hooks/useAuth";
@@ -39,7 +39,7 @@ import {
3939
Kimi,
4040
} from "@lobehub/icons";
4141
import { countries } from "@/lib/countries";
42-
import { plans } from "@/lib/utils";
42+
import { cn, plans } from "@/lib/utils";
4343
import { INDUSTRIES } from "@/lib/utils";
4444
import ShinyText from "@/components/ui/shiny-text";
4545
import { KeywordAnalysisResults } from "@/components/keywords/keyword-analysis-results";
@@ -71,12 +71,40 @@ type KeywordAnalysisResultsProps = {
7171
metadata: Array<{ language: string; country: string }>;
7272
};
7373

74+
type AutofillData = {
75+
logoUrl: string;
76+
industry: string;
77+
businessSubcategory: string;
78+
brandVoice: string;
79+
businessEntity: {
80+
type: string;
81+
description: string;
82+
offering: string;
83+
};
84+
mainLanguage: string;
85+
mainCountry: string;
86+
otherCountries: string[];
87+
competitors: string[];
88+
brandName: string;
89+
brandNameVariations: string[];
90+
brandWebsiteUrl: string;
91+
brandCallToAction: string;
92+
brandSocialMediaUrl: {
93+
linkedin: string;
94+
youtube: string;
95+
meta: string;
96+
instagram: string;
97+
x: string;
98+
tiktok: string;
99+
};
100+
};
101+
74102
export default function OnboardingPage() {
75103
const router = useRouter();
76104
const searchParams = useSearchParams();
77105
const email = searchParams.get("email");
78106
const domain = searchParams.get("domain");
79-
const step = searchParams.get("step");
107+
const step = searchParams.get("step") || "0";
80108
const [onboardingStep, setOnboardingStep] = useState(parseInt(step!));
81109
const [selectedPlan, setSelectedPlan] = useState("");
82110
const [password, setPassword] = useState("");
@@ -105,6 +133,8 @@ export default function OnboardingPage() {
105133
const [manualLanguage, setManualLanguage] = useState("");
106134
const [manualLocation, setManualLocation] = useState("");
107135
const [isManualAnalyzing, setIsManualAnalyzing] = useState(false);
136+
const [autofillData, setAutofillData] = useState<AutofillData | null>(null);
137+
const [isLoadingAutofill, setIsLoadingAutofill] = useState(false);
108138

109139

110140
// Update time every second
@@ -250,6 +280,11 @@ export default function OnboardingPage() {
250280
setSessionKey(authData.session?.access_token || "");
251281
setOnboardingStep(1); // Move to brand creation
252282
toast.success("Account created! Now let's set up your brand.");
283+
284+
// Fetch autofill data using domain from email
285+
if (domain) {
286+
await fetchAutofillData(`${domain}`);
287+
}
253288
}
254289
} catch (error: unknown) {
255290
const errorMessage =
@@ -266,6 +301,59 @@ export default function OnboardingPage() {
266301
setOnboardingStep((prev) => prev + 1);
267302
};
268303

304+
// Function to fetch autofill data from our API
305+
const fetchAutofillData = async (websiteUrl: string) => {
306+
if (!websiteUrl) return;
307+
308+
setIsLoadingAutofill(true);
309+
try {
310+
const response = await fetch("/api/onboarding-autofill", {
311+
method: "POST",
312+
headers: {
313+
"Content-Type": "application/json",
314+
},
315+
body: JSON.stringify({
316+
website: websiteUrl,
317+
}),
318+
});
319+
320+
const result = await response.json();
321+
322+
if (response.ok && result.success) {
323+
setAutofillData(result.data);
324+
// Auto-fill form fields
325+
if (result.data.brandName) setBrandName(result.data.brandName);
326+
if (result.data.brandWebsiteUrl) setBrandWebsite(result.data.brandWebsiteUrl);
327+
if (result.data.industry) setBrandIndustry(result.data.industry);
328+
if (result.data.mainCountry) setBrandLocation(result.data.mainCountry);
329+
if (result.data.mainLanguage) {
330+
// Map full language names to language codes
331+
const languageMap: { [key: string]: string } = {
332+
"English": "en",
333+
"Spanish": "es",
334+
"French": "fr",
335+
"German": "de",
336+
"Italian": "it",
337+
"Portuguese": "pt",
338+
"Russian": "ru"
339+
};
340+
setBrandLanguage(languageMap[result.data.mainLanguage] || "en");
341+
}
342+
if (result.data.logoUrl) setBrandLogoPreview(result.data.logoUrl);
343+
344+
toast.success("Brand information auto-filled!");
345+
} else {
346+
console.error("Failed to fetch autofill data:", result.error);
347+
toast.error("Failed to auto-fill brand information");
348+
}
349+
} catch (error) {
350+
console.error("Error fetching autofill data:", error);
351+
toast.error("Failed to auto-fill brand information");
352+
} finally {
353+
setIsLoadingAutofill(false);
354+
}
355+
};
356+
269357
const handleSkip = () => {
270358
if (onboardingStep === 0) {
271359
setSelectedPlan("free");
@@ -667,8 +755,8 @@ export default function OnboardingPage() {
667755
</div>
668756
</div>
669757
) : (
670-
<div className="max-w-md mx-auto mb-8 flex items-center justify-center">
671-
<div className="sm:max-w-[500px] border-accent">
758+
<div className="max-w-xl mx-auto mb-8 flex flex-col items-center justify-center">
759+
<div className={cn("sm:max-w-[500px] border-accent transition-all duration-400", isLoadingAutofill && "opacity-30 cursor-not-allowed pointer-events-none hidden")}>
672760
<div className="space-y-4 w-full">
673761
<div className="grid gap-6">
674762
<div className="grid gap-2">
@@ -840,13 +928,140 @@ export default function OnboardingPage() {
840928
{submitting ? "Creating..." : "Create Brand"}
841929
</Button>
842930
</div>
931+
932+
{/* Additional Information from Autofill */}
933+
{(isLoadingAutofill || autofillData) && (
934+
<div className="max-w-5xl w-full mx-auto mt-8 px-6 flex flex-col items-center justify-center">
935+
{isLoadingAutofill ? (
936+
<div className="text-center items-center gap-4 flex flex-col">
937+
<Loader2 className="animate-spin w-6 h-6 text-blue-500" />
938+
<p className="text-gray-400 shiny-text">Fetching brand information...</p>
939+
</div>
940+
) : autofillData && (
941+
<div className="space-y-6">
942+
<h3 className="text-xl font-semibold text-gray-200 mb-4">Additional Brand Information</h3>
943+
944+
{/* Company Description */}
945+
{autofillData.businessEntity?.description && (
946+
<div>
947+
<h4 className="text-sm font-medium text-gray-300 mb-2">Company Description</h4>
948+
<p className="text-gray-400 text-sm leading-relaxed">
949+
{autofillData.businessEntity.description}
950+
</p>
951+
</div>
952+
)}
953+
954+
{/* Social Media Links */}
955+
{autofillData.brandSocialMediaUrl && Object.values(autofillData.brandSocialMediaUrl).some(url => url) && (
956+
<div>
957+
<h4 className="text-sm font-medium text-gray-300 mb-2">Social Media</h4>
958+
<div className="flex items-center justify-center flex-wrap gap-2">
959+
{autofillData.brandSocialMediaUrl.linkedin && (
960+
<a
961+
href={autofillData.brandSocialMediaUrl.linkedin}
962+
target="_blank"
963+
rel="noopener noreferrer"
964+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-blue-400 hover:bg-zinc-600 transition-colors"
965+
>
966+
LinkedIn
967+
</a>
968+
)}
969+
{autofillData.brandSocialMediaUrl.x && (
970+
<a
971+
href={autofillData.brandSocialMediaUrl.x}
972+
target="_blank"
973+
rel="noopener noreferrer"
974+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-blue-400 hover:bg-zinc-600 transition-colors"
975+
>
976+
X (Twitter)
977+
</a>
978+
)}
979+
{autofillData.brandSocialMediaUrl.youtube && (
980+
<a
981+
href={autofillData.brandSocialMediaUrl.youtube}
982+
target="_blank"
983+
rel="noopener noreferrer"
984+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-blue-400 hover:bg-zinc-600 transition-colors"
985+
>
986+
YouTube
987+
</a>
988+
)}
989+
{autofillData.brandSocialMediaUrl.meta && (
990+
<a
991+
href={autofillData.brandSocialMediaUrl.meta}
992+
target="_blank"
993+
rel="noopener noreferrer"
994+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-blue-400 hover:bg-zinc-600 transition-colors"
995+
>
996+
Facebook
997+
</a>
998+
)}
999+
{autofillData.brandSocialMediaUrl.instagram && (
1000+
<a
1001+
href={autofillData.brandSocialMediaUrl.instagram}
1002+
target="_blank"
1003+
rel="noopener noreferrer"
1004+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-blue-400 hover:bg-zinc-600 transition-colors"
1005+
>
1006+
Instagram
1007+
</a>
1008+
)}
1009+
{autofillData.brandSocialMediaUrl.tiktok && (
1010+
<a
1011+
href={autofillData.brandSocialMediaUrl.tiktok}
1012+
target="_blank"
1013+
rel="noopener noreferrer"
1014+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-blue-400 hover:bg-zinc-600 transition-colors"
1015+
>
1016+
TikTok
1017+
</a>
1018+
)}
1019+
</div>
1020+
</div>
1021+
)}
1022+
1023+
{/* Competitors */}
1024+
{autofillData.competitors && autofillData.competitors.length > 0 && (
1025+
<div>
1026+
<h4 className="text-sm font-medium text-gray-300 mb-2">Competitors</h4>
1027+
<div className="flex items-center justify-center flex-wrap gap-2">
1028+
{autofillData.competitors.slice(0, 8).map((competitor, index) => (
1029+
<span
1030+
key={index}
1031+
className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-gray-300"
1032+
>
1033+
{competitor}
1034+
</span>
1035+
))}
1036+
{autofillData.competitors.length > 8 && (
1037+
<span className="bg-zinc-700 px-3 py-1 rounded-full text-xs text-gray-400">
1038+
+{autofillData.competitors.length - 8} more
1039+
</span>
1040+
)}
1041+
</div>
1042+
</div>
1043+
)}
1044+
1045+
{/* Brand Voice */}
1046+
{autofillData.brandVoice && (
1047+
<div>
1048+
<h4 className="text-sm font-medium text-gray-300 mb-2">Brand Voice</h4>
1049+
<p className="text-gray-400 text-sm leading-relaxed">
1050+
{autofillData.brandVoice}
1051+
</p>
1052+
</div>
1053+
)}
1054+
</div>
1055+
)}
1056+
</div>
1057+
)}
8431058
</div>
8441059
)}
8451060

8461061
<div className="flex justify-between mt-8">
8471062
<Button
8481063
variant="ghost"
849-
onClick={() => setOnboardingStep(1)}
1064+
onClick={() => setOnboardingStep(0)}
8501065
disabled={isAnalyzing}
8511066
>
8521067
← Back

0 commit comments

Comments
 (0)