From 28b1ff542b2a42930b956389edf9e7aac5ec2d4e Mon Sep 17 00:00:00 2001 From: talksik Date: Thu, 16 Apr 2026 09:15:31 -0700 Subject: [PATCH] feat: add support email This will help humans whether they have billing questions or otherwise. --- js/src/components/copyable-email.tsx | 49 ++++++++++++++++++++++++++++ js/src/features/network-billing.tsx | 14 ++++++++ js/src/features/settings-page.tsx | 21 +++++++++++- js/src/lib/constants.ts | 2 ++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 js/src/components/copyable-email.tsx diff --git a/js/src/components/copyable-email.tsx b/js/src/components/copyable-email.tsx new file mode 100644 index 0000000..6c396fc --- /dev/null +++ b/js/src/components/copyable-email.tsx @@ -0,0 +1,49 @@ +import { useEffect, useState } from "react"; +import { Check, Copy } from "lucide-react"; +import { toast } from "sonner"; +import { cn } from "@/lib/utils"; + +interface CopyableEmailProps { + email: string; + className?: string; +} + +export function CopyableEmail({ email, className }: CopyableEmailProps) { + const [copied, setCopied] = useState(false); + + useEffect(() => { + if (!copied) return; + const id = setTimeout(() => setCopied(false), 1500); + return () => clearTimeout(id); + }, [copied]); + + const handleCopy = async (e: React.MouseEvent) => { + e.stopPropagation(); + try { + await navigator.clipboard.writeText(email); + setCopied(true); + toast.success("Email copied"); + } catch { + toast.error("Failed to copy email"); + } + }; + + return ( + + ); +} diff --git a/js/src/features/network-billing.tsx b/js/src/features/network-billing.tsx index aa64153..79056ec 100644 --- a/js/src/features/network-billing.tsx +++ b/js/src/features/network-billing.tsx @@ -7,7 +7,9 @@ import { Label } from "@/components/ui/label"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Separator } from "@/components/ui/separator"; import { Muted } from "@/components/ui/typography"; +import { CopyableEmail } from "@/components/copyable-email"; import { cn } from "@/lib/utils"; +import { SUPPORT_EMAIL } from "@/lib/constants"; import { useCreateCheckoutSession, useCreatePortalSession, @@ -309,6 +311,18 @@ export function BillingSection({ networkId }: { networkId: string }) { <> + + + Billing support + + Invoices, receipts, or plan changes + + + } + value={} + /> )} diff --git a/js/src/features/settings-page.tsx b/js/src/features/settings-page.tsx index 6cc6203..8a0b988 100644 --- a/js/src/features/settings-page.tsx +++ b/js/src/features/settings-page.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; -import { ChevronRight, LogOut, User, Info, Shield, Mail, Mic } from "lucide-react"; +import { ChevronRight, LogOut, User, Info, Shield, Mail, Mic, LifeBuoy } from "lucide-react"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { Separator } from "@/components/ui/separator"; import { Switch } from "@/components/ui/switch"; @@ -8,8 +8,10 @@ import { WindowControls } from "@/components/window-controls"; import { Button } from "@/components/ui/button"; import { Muted } from "@/components/ui/typography"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { CopyableEmail } from "@/components/copyable-email"; import { useAuthStore } from "@/stores/auth-store"; import { apiClient } from "@/api/client"; +import { SUPPORT_EMAIL } from "@/lib/constants"; import { ArrowLeft } from "lucide-react"; interface SettingsRowProps { @@ -165,6 +167,23 @@ export default function SettingsPage() { + +
+ + + +
+

Email support

+ + Questions, feedback, or bug reports + +
+ +
+
+ + +
} diff --git a/js/src/lib/constants.ts b/js/src/lib/constants.ts index 6a50eee..3d8a529 100644 --- a/js/src/lib/constants.ts +++ b/js/src/lib/constants.ts @@ -3,3 +3,5 @@ export const MAX_ATTACHMENT_SIZE_BYTES = 25 * 1024 * 1024; /** Maximum number of file attachments per particle. */ export const MAX_ATTACHMENTS = 10; + +export const SUPPORT_EMAIL = "team@flowylabs.ai";