Prettier format pending files
This commit is contained in:
parent
47b9b4a0bd
commit
2d25128ee1
12 changed files with 190 additions and 42 deletions
|
|
@ -1,6 +1,12 @@
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
|
@ -36,11 +42,15 @@ export default function LeadForm() {
|
||||||
}));
|
}));
|
||||||
}, [inferred.full, inferred.email]);
|
}, [inferred.full, inferred.email]);
|
||||||
|
|
||||||
const update = (k: keyof typeof form) => (e: any) => setForm({ ...form, [k]: e.target.value });
|
const update = (k: keyof typeof form) => (e: any) =>
|
||||||
|
setForm({ ...form, [k]: e.target.value });
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if (!form.email) {
|
if (!form.email) {
|
||||||
toast({ title: "Email required", description: "Please provide a valid email." });
|
toast({
|
||||||
|
title: "Email required",
|
||||||
|
description: "Please provide a valid email.",
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
@ -53,10 +63,17 @@ export default function LeadForm() {
|
||||||
const ok = r.ok;
|
const ok = r.ok;
|
||||||
const data = await r.json().catch(() => ({}));
|
const data = await r.json().catch(() => ({}));
|
||||||
if (!ok) throw new Error(data?.error || `Request failed (${r.status})`);
|
if (!ok) throw new Error(data?.error || `Request failed (${r.status})`);
|
||||||
toast({ title: "Thanks!", description: "We’ll follow up shortly with next steps." });
|
toast({
|
||||||
|
title: "Thanks!",
|
||||||
|
description: "We’ll follow up shortly with next steps.",
|
||||||
|
});
|
||||||
setForm({ ...form, message: "" });
|
setForm({ ...form, message: "" });
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
toast({ title: "Submission failed", description: e?.message || "Try again later.", variant: "destructive" as any });
|
toast({
|
||||||
|
title: "Submission failed",
|
||||||
|
description: e?.message || "Try again later.",
|
||||||
|
variant: "destructive" as any,
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
@ -67,39 +84,81 @@ export default function LeadForm() {
|
||||||
<Card className="border-border/40 bg-card/60 backdrop-blur">
|
<Card className="border-border/40 bg-card/60 backdrop-blur">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Start a Wix project</CardTitle>
|
<CardTitle>Start a Wix project</CardTitle>
|
||||||
<CardDescription>Tell us a bit about your goals. We’ll get back within 1 business day.</CardDescription>
|
<CardDescription>
|
||||||
|
Tell us a bit about your goals. We’ll get back within 1 business
|
||||||
|
day.
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="grid gap-4 md:grid-cols-2">
|
<CardContent className="grid gap-4 md:grid-cols-2">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="name">Name</Label>
|
<Label htmlFor="name">Name</Label>
|
||||||
<Input id="name" value={form.name} onChange={update("name")} placeholder="Your name" />
|
<Input
|
||||||
|
id="name"
|
||||||
|
value={form.name}
|
||||||
|
onChange={update("name")}
|
||||||
|
placeholder="Your name"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="email">Email</Label>
|
<Label htmlFor="email">Email</Label>
|
||||||
<Input id="email" value={form.email} onChange={update("email")} placeholder="you@company.com" />
|
<Input
|
||||||
|
id="email"
|
||||||
|
value={form.email}
|
||||||
|
onChange={update("email")}
|
||||||
|
placeholder="you@company.com"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="company">Company</Label>
|
<Label htmlFor="company">Company</Label>
|
||||||
<Input id="company" value={form.company} onChange={update("company")} placeholder="Company Inc." />
|
<Input
|
||||||
|
id="company"
|
||||||
|
value={form.company}
|
||||||
|
onChange={update("company")}
|
||||||
|
placeholder="Company Inc."
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="website">Website</Label>
|
<Label htmlFor="website">Website</Label>
|
||||||
<Input id="website" value={form.website} onChange={update("website")} placeholder="https://example.com" />
|
<Input
|
||||||
|
id="website"
|
||||||
|
value={form.website}
|
||||||
|
onChange={update("website")}
|
||||||
|
placeholder="https://example.com"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="budget">Budget</Label>
|
<Label htmlFor="budget">Budget</Label>
|
||||||
<Input id="budget" value={form.budget} onChange={update("budget")} placeholder="e.g. $5k–$10k" />
|
<Input
|
||||||
|
id="budget"
|
||||||
|
value={form.budget}
|
||||||
|
onChange={update("budget")}
|
||||||
|
placeholder="e.g. $5k–$10k"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="timeline">Timeline</Label>
|
<Label htmlFor="timeline">Timeline</Label>
|
||||||
<Input id="timeline" value={form.timeline} onChange={update("timeline")} placeholder="e.g. 4–6 weeks" />
|
<Input
|
||||||
|
id="timeline"
|
||||||
|
value={form.timeline}
|
||||||
|
onChange={update("timeline")}
|
||||||
|
placeholder="e.g. 4–6 weeks"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2 md:col-span-2">
|
<div className="space-y-2 md:col-span-2">
|
||||||
<Label htmlFor="message">Project overview</Label>
|
<Label htmlFor="message">Project overview</Label>
|
||||||
<Textarea id="message" value={form.message} onChange={update("message")} placeholder="What are you building? Who is it for? What does success look like?" />
|
<Textarea
|
||||||
|
id="message"
|
||||||
|
value={form.message}
|
||||||
|
onChange={update("message")}
|
||||||
|
placeholder="What are you building? Who is it for? What does success look like?"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:col-span-2">
|
<div className="md:col-span-2">
|
||||||
<Button onClick={submit} disabled={loading} className="w-full md:w-auto">
|
<Button
|
||||||
|
onClick={submit}
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full md:w-auto"
|
||||||
|
>
|
||||||
{loading ? "Submitting…" : "Submit"}
|
{loading ? "Submitting…" : "Submit"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import type { PricingTier } from "@/data/wix/pricing";
|
import type { PricingTier } from "@/data/wix/pricing";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
|
||||||
export default function ServiceCard({
|
export default function ServiceCard({
|
||||||
name,
|
name,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@ export default function WixHero() {
|
||||||
<CardContent className="p-6 md:p-10">
|
<CardContent className="p-6 md:p-10">
|
||||||
<div className="flex flex-col gap-4 md:gap-6">
|
<div className="flex flex-col gap-4 md:gap-6">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Badge variant="outline" className="border-aethex-400/50 text-aethex-300">
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className="border-aethex-400/50 text-aethex-300"
|
||||||
|
>
|
||||||
Official Wix Agency Partner
|
Official Wix Agency Partner
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -18,8 +21,9 @@ export default function WixHero() {
|
||||||
Wix & Wix Studio Sites — designed, built, and scaled by AeThex
|
Wix & Wix Studio Sites — designed, built, and scaled by AeThex
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground text-base md:text-lg max-w-3xl">
|
<p className="text-muted-foreground text-base md:text-lg max-w-3xl">
|
||||||
We ship fast, accessible, and SEO-ready sites using Wix Studio. From launch
|
We ship fast, accessible, and SEO-ready sites using Wix Studio.
|
||||||
microsites to full eCommerce, your team gets a site you can actually edit.
|
From launch microsites to full eCommerce, your team gets a site
|
||||||
|
you can actually edit.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap gap-3">
|
<div className="flex flex-wrap gap-3">
|
||||||
<Button asChild>
|
<Button asChild>
|
||||||
|
|
@ -32,7 +36,13 @@ export default function WixHero() {
|
||||||
<Link to="/wix/faq">FAQ</Link>
|
<Link to="/wix/faq">FAQ</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button asChild variant="outline">
|
<Button asChild variant="outline">
|
||||||
<a href="https://www.wix.com/studio/community/partners/aethex" target="_blank" rel="noreferrer">Wix Partner Profile</a>
|
<a
|
||||||
|
href="https://www.wix.com/studio/community/partners/aethex"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Wix Partner Profile
|
||||||
|
</a>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -271,11 +271,17 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
// Auto-seed owner roles if logging in as site owner
|
// Auto-seed owner roles if logging in as site owner
|
||||||
const normalizedEmail = userProfile?.email?.toLowerCase();
|
const normalizedEmail = userProfile?.email?.toLowerCase();
|
||||||
if (normalizedEmail === "mrpiglr@gmail.com" && !r.includes("owner")) {
|
if (normalizedEmail === "mrpiglr@gmail.com" && !r.includes("owner")) {
|
||||||
const seeded = Array.from(new Set(["owner", "admin", "founder", ...r]));
|
const seeded = Array.from(
|
||||||
|
new Set(["owner", "admin", "founder", ...r]),
|
||||||
|
);
|
||||||
await aethexRoleService.setUserRoles(userId, seeded);
|
await aethexRoleService.setUserRoles(userId, seeded);
|
||||||
r = seeded;
|
r = seeded;
|
||||||
}
|
}
|
||||||
if (normalizedEmail && /@aethex\.dev$/i.test(normalizedEmail) && !r.includes("staff")) {
|
if (
|
||||||
|
normalizedEmail &&
|
||||||
|
/@aethex\.dev$/i.test(normalizedEmail) &&
|
||||||
|
!r.includes("staff")
|
||||||
|
) {
|
||||||
const seeded = Array.from(new Set(["staff", ...r]));
|
const seeded = Array.from(new Set(["staff", ...r]));
|
||||||
await aethexRoleService.setUserRoles(userId, seeded);
|
await aethexRoleService.setUserRoles(userId, seeded);
|
||||||
r = seeded;
|
r = seeded;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
export type Partner = { name: string; tier?: string | null; url?: string | null };
|
export type Partner = {
|
||||||
|
name: string;
|
||||||
|
tier?: string | null;
|
||||||
|
url?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
export const partners: Partner[] = [
|
export const partners: Partner[] = [
|
||||||
{ name: "Wix", tier: "Official Agency Partner", url: "https://www.wix.com/studio/community/partners/aethex" },
|
{
|
||||||
|
name: "Wix",
|
||||||
|
tier: "Official Agency Partner",
|
||||||
|
url: "https://www.wix.com/studio/community/partners/aethex",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default partners;
|
export default partners;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ export const pricing: PricingTier[] = [
|
||||||
id: "starter",
|
id: "starter",
|
||||||
name: "Starter",
|
name: "Starter",
|
||||||
price: "From $2,500",
|
price: "From $2,500",
|
||||||
description: "Single-page or small brochure site with strong SEO and fast turnaround.",
|
description:
|
||||||
|
"Single-page or small brochure site with strong SEO and fast turnaround.",
|
||||||
features: [
|
features: [
|
||||||
"1–3 pages",
|
"1–3 pages",
|
||||||
"Wix Studio setup and theme",
|
"Wix Studio setup and theme",
|
||||||
|
|
|
||||||
|
|
@ -49,16 +49,21 @@ function OrgLogin() {
|
||||||
<div className="space-y-3 p-3 rounded border border-border/40 bg-background/50">
|
<div className="space-y-3 p-3 rounded border border-border/40 bg-background/50">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="text-sm font-medium">Aethex Login (org)</div>
|
<div className="text-sm font-medium">Aethex Login (org)</div>
|
||||||
<Badge variant="outline" className="uppercase">@aethex.dev</Badge>
|
<Badge variant="outline" className="uppercase">
|
||||||
|
@aethex.dev
|
||||||
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
{sent ? (
|
{sent ? (
|
||||||
<Alert className="border-aethex-400/30 bg-aethex-500/10 text-foreground">
|
<Alert className="border-aethex-400/30 bg-aethex-500/10 text-foreground">
|
||||||
<AlertTitle>Check your inbox</AlertTitle>
|
<AlertTitle>Check your inbox</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
We sent a magic link to {email}. If email isn’t configured, a manual link is shown below.
|
We sent a magic link to {email}. If email isn’t configured, a manual
|
||||||
|
link is shown below.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
{sent.startsWith("http") && (
|
{sent.startsWith("http") && (
|
||||||
<p className="mt-2 break-all rounded bg-background/60 px-3 py-2 font-mono text-xs text-foreground/90">{sent}</p>
|
<p className="mt-2 break-all rounded bg-background/60 px-3 py-2 font-mono text-xs text-foreground/90">
|
||||||
|
{sent}
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
</Alert>
|
</Alert>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
@ -88,7 +93,10 @@ function OrgLogin() {
|
||||||
const r = await fetch("/api/auth/send-org-link", {
|
const r = await fetch("/api/auth/send-org-link", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "content-type": "application/json" },
|
headers: { "content-type": "application/json" },
|
||||||
body: JSON.stringify({ email, redirectTo: window.location.origin + "/dashboard" }),
|
body: JSON.stringify({
|
||||||
|
email,
|
||||||
|
redirectTo: window.location.origin + "/dashboard",
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
if (!r.ok) {
|
if (!r.ok) {
|
||||||
const msg = await r.text().catch(() => "");
|
const msg = await r.text().catch(() => "");
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,9 @@ export default function ProjectsAdmin() {
|
||||||
const isOwner = Boolean(
|
const isOwner = Boolean(
|
||||||
user?.email?.toLowerCase() === "mrpiglr@gmail.com" ||
|
user?.email?.toLowerCase() === "mrpiglr@gmail.com" ||
|
||||||
(roles || []).some((r) =>
|
(roles || []).some((r) =>
|
||||||
["owner", "admin", "founder", "staff"].includes(String(r).toLowerCase()),
|
["owner", "admin", "founder", "staff"].includes(
|
||||||
|
String(r).toLowerCase(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const [list, setList] = useState<any[]>([]);
|
const [list, setList] = useState<any[]>([]);
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,17 @@ export default function Wix() {
|
||||||
<WixHero />
|
<WixHero />
|
||||||
|
|
||||||
<section className="container mx-auto px-4 py-10">
|
<section className="container mx-auto px-4 py-10">
|
||||||
<h2 className="text-2xl md:text-3xl font-semibold mb-6">What we build</h2>
|
<h2 className="text-2xl md:text-3xl font-semibold mb-6">
|
||||||
|
What we build
|
||||||
|
</h2>
|
||||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
{services.map((s) => (
|
{services.map((s) => (
|
||||||
<ServiceCard key={s.id} name={s.name} summary={s.summary} highlights={s.highlights} />
|
<ServiceCard
|
||||||
|
key={s.id}
|
||||||
|
name={s.name}
|
||||||
|
summary={s.summary}
|
||||||
|
highlights={s.highlights}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
import Layout from "@/components/Layout";
|
import Layout from "@/components/Layout";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import studies from "@/data/wix/caseStudies";
|
import studies from "@/data/wix/caseStudies";
|
||||||
|
|
||||||
export default function WixCaseStudies() {
|
export default function WixCaseStudies() {
|
||||||
|
|
@ -7,10 +13,15 @@ export default function WixCaseStudies() {
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="min-h-screen bg-aethex-gradient py-10">
|
<div className="min-h-screen bg-aethex-gradient py-10">
|
||||||
<section className="container mx-auto px-4">
|
<section className="container mx-auto px-4">
|
||||||
<h1 className="text-3xl md:text-4xl font-bold mb-6">Wix Case Studies</h1>
|
<h1 className="text-3xl md:text-4xl font-bold mb-6">
|
||||||
|
Wix Case Studies
|
||||||
|
</h1>
|
||||||
<div className="grid gap-6 md:grid-cols-2">
|
<div className="grid gap-6 md:grid-cols-2">
|
||||||
{studies.map((c) => (
|
{studies.map((c) => (
|
||||||
<Card key={c.id} className="border-border/40 bg-card/60 backdrop-blur">
|
<Card
|
||||||
|
key={c.id}
|
||||||
|
className="border-border/40 bg-card/60 backdrop-blur"
|
||||||
|
>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>{c.title}</CardTitle>
|
<CardTitle>{c.title}</CardTitle>
|
||||||
<CardDescription>{c.summary}</CardDescription>
|
<CardDescription>{c.summary}</CardDescription>
|
||||||
|
|
@ -18,7 +29,10 @@ export default function WixCaseStudies() {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-3 gap-3 text-sm">
|
<div className="grid grid-cols-3 gap-3 text-sm">
|
||||||
{c.metrics.map((m, i) => (
|
{c.metrics.map((m, i) => (
|
||||||
<div key={i} className="rounded border border-border/40 p-3">
|
<div
|
||||||
|
key={i}
|
||||||
|
className="rounded border border-border/40 p-3"
|
||||||
|
>
|
||||||
<div className="text-muted-foreground">{m.label}</div>
|
<div className="text-muted-foreground">{m.label}</div>
|
||||||
<div className="font-semibold">{m.value}</div>
|
<div className="font-semibold">{m.value}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -147,11 +147,17 @@ export function createServer() {
|
||||||
// Org domain magic-link sender (Aethex)
|
// Org domain magic-link sender (Aethex)
|
||||||
app.post("/api/auth/send-org-link", async (req, res) => {
|
app.post("/api/auth/send-org-link", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { email, redirectTo } = (req.body || {}) as { email?: string; redirectTo?: string };
|
const { email, redirectTo } = (req.body || {}) as {
|
||||||
const target = String(email || "").trim().toLowerCase();
|
email?: string;
|
||||||
|
redirectTo?: string;
|
||||||
|
};
|
||||||
|
const target = String(email || "")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
if (!target) return res.status(400).json({ error: "email is required" });
|
if (!target) return res.status(400).json({ error: "email is required" });
|
||||||
const allowed = /@aethex\.dev$/i.test(target);
|
const allowed = /@aethex\.dev$/i.test(target);
|
||||||
if (!allowed) return res.status(403).json({ error: "domain not allowed" });
|
if (!allowed)
|
||||||
|
return res.status(403).json({ error: "domain not allowed" });
|
||||||
|
|
||||||
if (!adminSupabase?.auth?.admin) {
|
if (!adminSupabase?.auth?.admin) {
|
||||||
return res.status(500).json({ error: "Supabase admin unavailable" });
|
return res.status(500).json({ error: "Supabase admin unavailable" });
|
||||||
|
|
@ -163,7 +169,10 @@ export function createServer() {
|
||||||
process.env.SITE_URL ??
|
process.env.SITE_URL ??
|
||||||
"https://aethex.dev";
|
"https://aethex.dev";
|
||||||
|
|
||||||
const toUrl = typeof redirectTo === "string" && redirectTo.startsWith("http") ? redirectTo : fallbackRedirect;
|
const toUrl =
|
||||||
|
typeof redirectTo === "string" && redirectTo.startsWith("http")
|
||||||
|
? redirectTo
|
||||||
|
: fallbackRedirect;
|
||||||
|
|
||||||
const { data, error } = await adminSupabase.auth.admin.generateLink({
|
const { data, error } = await adminSupabase.auth.admin.generateLink({
|
||||||
type: "magiclink" as any,
|
type: "magiclink" as any,
|
||||||
|
|
@ -1310,7 +1319,16 @@ export function createServer() {
|
||||||
|
|
||||||
// Leads: capture website leads (Wix microsite and others)
|
// Leads: capture website leads (Wix microsite and others)
|
||||||
app.post("/api/leads", async (req, res) => {
|
app.post("/api/leads", async (req, res) => {
|
||||||
const { name, email, company, website, budget, timeline, message, source } = (req.body || {}) as {
|
const {
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
company,
|
||||||
|
website,
|
||||||
|
budget,
|
||||||
|
timeline,
|
||||||
|
message,
|
||||||
|
source,
|
||||||
|
} = (req.body || {}) as {
|
||||||
name?: string;
|
name?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
company?: string;
|
company?: string;
|
||||||
|
|
@ -1335,7 +1353,10 @@ export function createServer() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (emailService.isConfigured) {
|
if (emailService.isConfigured) {
|
||||||
const base = process.env.PUBLIC_BASE_URL || process.env.SITE_URL || "https://aethex.dev";
|
const base =
|
||||||
|
process.env.PUBLIC_BASE_URL ||
|
||||||
|
process.env.SITE_URL ||
|
||||||
|
"https://aethex.dev";
|
||||||
await (emailService as any).sendInviteEmail({
|
await (emailService as any).sendInviteEmail({
|
||||||
to: process.env.VERIFY_SUPPORT_EMAIL || "support@aethex.biz",
|
to: process.env.VERIFY_SUPPORT_EMAIL || "support@aethex.biz",
|
||||||
inviteUrl: `${base}/wix`,
|
inviteUrl: `${base}/wix`,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue