feat(enterprise): contact form now pushes to salesforce 🙄 (#17964)

Co-authored-by: slickstef11 <stefan@wundergraph.com>
Co-authored-by: Frank <frank@anoma.ly>
This commit is contained in:
Ryan Vogel
2026-03-17 22:43:43 -04:00
committed by GitHub
co-authored by slickstef11 Frank
parent 0292f1b559
commit a849a17e93
23 changed files with 254 additions and 11 deletions
+7
View File
@@ -201,6 +201,10 @@ const bucketNew = new sst.cloudflare.Bucket("ZenDataNew")
const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID") const AWS_SES_ACCESS_KEY_ID = new sst.Secret("AWS_SES_ACCESS_KEY_ID")
const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY") const AWS_SES_SECRET_ACCESS_KEY = new sst.Secret("AWS_SES_SECRET_ACCESS_KEY")
const SALESFORCE_CLIENT_ID = new sst.Secret("SALESFORCE_CLIENT_ID")
const SALESFORCE_CLIENT_SECRET = new sst.Secret("SALESFORCE_CLIENT_SECRET")
const SALESFORCE_INSTANCE_URL = new sst.Secret("SALESFORCE_INSTANCE_URL")
const logProcessor = new sst.cloudflare.Worker("LogProcessor", { const logProcessor = new sst.cloudflare.Worker("LogProcessor", {
handler: "packages/console/function/src/log-processor.ts", handler: "packages/console/function/src/log-processor.ts",
link: [new sst.Secret("HONEYCOMB_API_KEY")], link: [new sst.Secret("HONEYCOMB_API_KEY")],
@@ -219,6 +223,9 @@ new sst.cloudflare.x.SolidStart("Console", {
EMAILOCTOPUS_API_KEY, EMAILOCTOPUS_API_KEY,
AWS_SES_ACCESS_KEY_ID, AWS_SES_ACCESS_KEY_ID,
AWS_SES_SECRET_ACCESS_KEY, AWS_SES_SECRET_ACCESS_KEY,
SALESFORCE_CLIENT_ID,
SALESFORCE_CLIENT_SECRET,
SALESFORCE_INSTANCE_URL,
ZEN_BLACK_PRICE, ZEN_BLACK_PRICE,
ZEN_LITE_PRICE, ZEN_LITE_PRICE,
new sst.Secret("ZEN_LIMITS"), new sst.Secret("ZEN_LIMITS"),
+1
View File
@@ -9,6 +9,7 @@
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts", "dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
"dev:desktop": "bun --cwd packages/desktop tauri dev", "dev:desktop": "bun --cwd packages/desktop tauri dev",
"dev:web": "bun --cwd packages/app dev", "dev:web": "bun --cwd packages/app dev",
"dev:console": "ulimit -n 10240 2>/dev/null; bun run --cwd packages/console/app dev",
"dev:storybook": "bun --cwd packages/storybook storybook", "dev:storybook": "bun --cwd packages/storybook storybook",
"typecheck": "bun turbo typecheck", "typecheck": "bun turbo typecheck",
"prepare": "husky", "prepare": "husky",
+4
View File
@@ -688,8 +688,12 @@ export const dict = {
"enterprise.form.name.placeholder": "جيف بيزوس", "enterprise.form.name.placeholder": "جيف بيزوس",
"enterprise.form.role.label": "المنصب", "enterprise.form.role.label": "المنصب",
"enterprise.form.role.placeholder": "رئيس مجلس الإدارة التنفيذي", "enterprise.form.role.placeholder": "رئيس مجلس الإدارة التنفيذي",
"enterprise.form.company.label": "الشركة",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "البريد الإلكتروني للشركة", "enterprise.form.email.label": "البريد الإلكتروني للشركة",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "رقم الهاتف",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "ما المشكلة التي تحاول حلها؟", "enterprise.form.message.label": "ما المشكلة التي تحاول حلها؟",
"enterprise.form.message.placeholder": "نحتاج مساعدة في...", "enterprise.form.message.placeholder": "نحتاج مساعدة في...",
"enterprise.form.send": "إرسال", "enterprise.form.send": "إرسال",
+4
View File
@@ -700,8 +700,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Cargo", "enterprise.form.role.label": "Cargo",
"enterprise.form.role.placeholder": "Presidente Executivo", "enterprise.form.role.placeholder": "Presidente Executivo",
"enterprise.form.company.label": "Empresa",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "E-mail corporativo", "enterprise.form.email.label": "E-mail corporativo",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Telefone",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Qual problema você está tentando resolver?", "enterprise.form.message.label": "Qual problema você está tentando resolver?",
"enterprise.form.message.placeholder": "Precisamos de ajuda com...", "enterprise.form.message.placeholder": "Precisamos de ajuda com...",
"enterprise.form.send": "Enviar", "enterprise.form.send": "Enviar",
+4
View File
@@ -694,8 +694,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Rolle", "enterprise.form.role.label": "Rolle",
"enterprise.form.role.placeholder": "Bestyrelsesformand", "enterprise.form.role.placeholder": "Bestyrelsesformand",
"enterprise.form.company.label": "Virksomhed",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Firma-e-mail", "enterprise.form.email.label": "Firma-e-mail",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Telefonnummer",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Hvilket problem prøver du at løse?", "enterprise.form.message.label": "Hvilket problem prøver du at løse?",
"enterprise.form.message.placeholder": "Vi har brug for hjælp med...", "enterprise.form.message.placeholder": "Vi har brug for hjælp med...",
"enterprise.form.send": "Send", "enterprise.form.send": "Send",
+4
View File
@@ -699,8 +699,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Rolle", "enterprise.form.role.label": "Rolle",
"enterprise.form.role.placeholder": "Executive Chairman", "enterprise.form.role.placeholder": "Executive Chairman",
"enterprise.form.company.label": "Unternehmen",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Firmen-E-Mail", "enterprise.form.email.label": "Firmen-E-Mail",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Telefonnummer",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Welches Problem versuchen Sie zu lösen?", "enterprise.form.message.label": "Welches Problem versuchen Sie zu lösen?",
"enterprise.form.message.placeholder": "Wir brauchen Hilfe bei...", "enterprise.form.message.placeholder": "Wir brauchen Hilfe bei...",
"enterprise.form.send": "Senden", "enterprise.form.send": "Senden",
+4
View File
@@ -689,8 +689,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Role", "enterprise.form.role.label": "Role",
"enterprise.form.role.placeholder": "Executive Chairman", "enterprise.form.role.placeholder": "Executive Chairman",
"enterprise.form.company.label": "Company",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Company email", "enterprise.form.email.label": "Company email",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Phone number",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "What problem are you trying to solve?", "enterprise.form.message.label": "What problem are you trying to solve?",
"enterprise.form.message.placeholder": "We need help with...", "enterprise.form.message.placeholder": "We need help with...",
"enterprise.form.send": "Send", "enterprise.form.send": "Send",
+4
View File
@@ -699,8 +699,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Rol", "enterprise.form.role.label": "Rol",
"enterprise.form.role.placeholder": "Presidente Ejecutivo", "enterprise.form.role.placeholder": "Presidente Ejecutivo",
"enterprise.form.company.label": "Empresa",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Correo de empresa", "enterprise.form.email.label": "Correo de empresa",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Teléfono",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "¿Qué problema estás intentando resolver?", "enterprise.form.message.label": "¿Qué problema estás intentando resolver?",
"enterprise.form.message.placeholder": "Necesitamos ayuda con...", "enterprise.form.message.placeholder": "Necesitamos ayuda con...",
"enterprise.form.send": "Enviar", "enterprise.form.send": "Enviar",
+4
View File
@@ -706,8 +706,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Poste", "enterprise.form.role.label": "Poste",
"enterprise.form.role.placeholder": "Président exécutif", "enterprise.form.role.placeholder": "Président exécutif",
"enterprise.form.company.label": "Entreprise",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "E-mail professionnel", "enterprise.form.email.label": "E-mail professionnel",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Téléphone",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Quel problème essayez-vous de résoudre ?", "enterprise.form.message.label": "Quel problème essayez-vous de résoudre ?",
"enterprise.form.message.placeholder": "Nous avons besoin d'aide pour...", "enterprise.form.message.placeholder": "Nous avons besoin d'aide pour...",
"enterprise.form.send": "Envoyer", "enterprise.form.send": "Envoyer",
+4
View File
@@ -696,8 +696,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Ruolo", "enterprise.form.role.label": "Ruolo",
"enterprise.form.role.placeholder": "Presidente Esecutivo", "enterprise.form.role.placeholder": "Presidente Esecutivo",
"enterprise.form.company.label": "Azienda",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Email aziendale", "enterprise.form.email.label": "Email aziendale",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Numero di telefono",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Quale problema stai cercando di risolvere?", "enterprise.form.message.label": "Quale problema stai cercando di risolvere?",
"enterprise.form.message.placeholder": "Abbiamo bisogno di aiuto con...", "enterprise.form.message.placeholder": "Abbiamo bisogno di aiuto con...",
"enterprise.form.send": "Invia", "enterprise.form.send": "Invia",
+4
View File
@@ -697,8 +697,12 @@ export const dict = {
"enterprise.form.name.placeholder": "ジェフ・ベゾス", "enterprise.form.name.placeholder": "ジェフ・ベゾス",
"enterprise.form.role.label": "役職", "enterprise.form.role.label": "役職",
"enterprise.form.role.placeholder": "会長", "enterprise.form.role.placeholder": "会長",
"enterprise.form.company.label": "会社名",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "会社メールアドレス", "enterprise.form.email.label": "会社メールアドレス",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "電話番号",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "どのような課題を解決したいですか?", "enterprise.form.message.label": "どのような課題を解決したいですか?",
"enterprise.form.message.placeholder": "これについて支援が必要です...", "enterprise.form.message.placeholder": "これについて支援が必要です...",
"enterprise.form.send": "送信", "enterprise.form.send": "送信",
+4
View File
@@ -688,8 +688,12 @@ export const dict = {
"enterprise.form.name.placeholder": "홍길동", "enterprise.form.name.placeholder": "홍길동",
"enterprise.form.role.label": "직책", "enterprise.form.role.label": "직책",
"enterprise.form.role.placeholder": "CTO / 개발 팀장", "enterprise.form.role.placeholder": "CTO / 개발 팀장",
"enterprise.form.company.label": "회사",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "회사 이메일", "enterprise.form.email.label": "회사 이메일",
"enterprise.form.email.placeholder": "name@company.com", "enterprise.form.email.placeholder": "name@company.com",
"enterprise.form.phone.label": "전화번호",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "어떤 문제를 해결하고 싶으신가요?", "enterprise.form.message.label": "어떤 문제를 해결하고 싶으신가요?",
"enterprise.form.message.placeholder": "도움이 필요한 부분은...", "enterprise.form.message.placeholder": "도움이 필요한 부분은...",
"enterprise.form.send": "전송", "enterprise.form.send": "전송",
+4
View File
@@ -695,8 +695,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Rolle", "enterprise.form.role.label": "Rolle",
"enterprise.form.role.placeholder": "Styreleder", "enterprise.form.role.placeholder": "Styreleder",
"enterprise.form.company.label": "Selskap",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Bedrifts-e-post", "enterprise.form.email.label": "Bedrifts-e-post",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Telefonnummer",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Hvilket problem prøver dere å løse?", "enterprise.form.message.label": "Hvilket problem prøver dere å løse?",
"enterprise.form.message.placeholder": "Vi trenger hjelp med...", "enterprise.form.message.placeholder": "Vi trenger hjelp med...",
"enterprise.form.send": "Send", "enterprise.form.send": "Send",
+4
View File
@@ -698,8 +698,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Rola", "enterprise.form.role.label": "Rola",
"enterprise.form.role.placeholder": "Prezes Zarządu", "enterprise.form.role.placeholder": "Prezes Zarządu",
"enterprise.form.company.label": "Firma",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "E-mail firmowy", "enterprise.form.email.label": "E-mail firmowy",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Numer telefonu",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Jaki problem próbujesz rozwiązać?", "enterprise.form.message.label": "Jaki problem próbujesz rozwiązać?",
"enterprise.form.message.placeholder": "Potrzebujemy pomocy z...", "enterprise.form.message.placeholder": "Potrzebujemy pomocy z...",
"enterprise.form.send": "Wyślij", "enterprise.form.send": "Wyślij",
+4
View File
@@ -703,8 +703,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Джефф Безос", "enterprise.form.name.placeholder": "Джефф Безос",
"enterprise.form.role.label": "Роль", "enterprise.form.role.label": "Роль",
"enterprise.form.role.placeholder": "Исполнительный председатель", "enterprise.form.role.placeholder": "Исполнительный председатель",
"enterprise.form.company.label": "Компания",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Корпоративная почта", "enterprise.form.email.label": "Корпоративная почта",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Номер телефона",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Какую проблему вы пытаетесь решить?", "enterprise.form.message.label": "Какую проблему вы пытаетесь решить?",
"enterprise.form.message.placeholder": "Нам нужна помощь с...", "enterprise.form.message.placeholder": "Нам нужна помощь с...",
"enterprise.form.send": "Отправить", "enterprise.form.send": "Отправить",
+4
View File
@@ -691,8 +691,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "ตำแหน่ง", "enterprise.form.role.label": "ตำแหน่ง",
"enterprise.form.role.placeholder": "ประธานกรรมการบริหาร", "enterprise.form.role.placeholder": "ประธานกรรมการบริหาร",
"enterprise.form.company.label": "บริษัท",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "อีเมลบริษัท", "enterprise.form.email.label": "อีเมลบริษัท",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "หมายเลขโทรศัพท์",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "คุณกำลังพยายามแก้ปัญหาอะไร?", "enterprise.form.message.label": "คุณกำลังพยายามแก้ปัญหาอะไร?",
"enterprise.form.message.placeholder": "เราต้องการความช่วยเหลือเรื่อง...", "enterprise.form.message.placeholder": "เราต้องการความช่วยเหลือเรื่อง...",
"enterprise.form.send": "ส่ง", "enterprise.form.send": "ส่ง",
+4
View File
@@ -700,8 +700,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "Rol", "enterprise.form.role.label": "Rol",
"enterprise.form.role.placeholder": "Yönetim Kurulu Başkanı", "enterprise.form.role.placeholder": "Yönetim Kurulu Başkanı",
"enterprise.form.company.label": "Şirket",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "Şirket e-postası", "enterprise.form.email.label": "Şirket e-postası",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "Telefon numarası",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "Hangi problemi çözmeye çalışıyorsunuz?", "enterprise.form.message.label": "Hangi problemi çözmeye çalışıyorsunuz?",
"enterprise.form.message.placeholder": "Şu konuda yardıma ihtiyacımız var...", "enterprise.form.message.placeholder": "Şu konuda yardıma ihtiyacımız var...",
"enterprise.form.send": "Gönder", "enterprise.form.send": "Gönder",
+4
View File
@@ -669,8 +669,12 @@ export const dict = {
"enterprise.form.name.placeholder": "Jeff Bezos", "enterprise.form.name.placeholder": "Jeff Bezos",
"enterprise.form.role.label": "角色", "enterprise.form.role.label": "角色",
"enterprise.form.role.placeholder": "执行主席", "enterprise.form.role.placeholder": "执行主席",
"enterprise.form.company.label": "公司",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "公司邮箱", "enterprise.form.email.label": "公司邮箱",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "电话号码",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "您想解决什么问题?", "enterprise.form.message.label": "您想解决什么问题?",
"enterprise.form.message.placeholder": "我们需要帮助...", "enterprise.form.message.placeholder": "我们需要帮助...",
"enterprise.form.send": "发送", "enterprise.form.send": "发送",
+4
View File
@@ -668,8 +668,12 @@ export const dict = {
"enterprise.form.name.placeholder": "傑夫·貝佐斯", "enterprise.form.name.placeholder": "傑夫·貝佐斯",
"enterprise.form.role.label": "職稱", "enterprise.form.role.label": "職稱",
"enterprise.form.role.placeholder": "執行董事長", "enterprise.form.role.placeholder": "執行董事長",
"enterprise.form.company.label": "公司",
"enterprise.form.company.placeholder": "Acme Inc",
"enterprise.form.email.label": "公司 Email", "enterprise.form.email.label": "公司 Email",
"enterprise.form.email.placeholder": "jeff@amazon.com", "enterprise.form.email.placeholder": "jeff@amazon.com",
"enterprise.form.phone.label": "電話號碼",
"enterprise.form.phone.placeholder": "+1 234 567 8900",
"enterprise.form.message.label": "你想解決什麼問題?", "enterprise.form.message.label": "你想解決什麼問題?",
"enterprise.form.message.placeholder": "我們需要幫助來...", "enterprise.form.message.placeholder": "我們需要幫助來...",
"enterprise.form.send": "傳送", "enterprise.form.send": "傳送",
@@ -0,0 +1,81 @@
import { Resource } from "@opencode-ai/console-resource"
async function login() {
const url = Resource.SALESFORCE_INSTANCE_URL.value.replace(/\/$/, "")
const clientId = Resource.SALESFORCE_CLIENT_ID.value
const clientSecret = Resource.SALESFORCE_CLIENT_SECRET.value
const params = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientId,
client_secret: clientSecret,
})
const res = await fetch(`${url}/services/oauth2/token`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: params.toString(),
}).catch((err) => {
console.error("Failed to fetch Salesforce access token:", err)
})
if (!res) return
if (!res.ok) {
console.error("Failed to fetch Salesforce access token:", res.status, await res.text())
return
}
const data = (await res.json()) as { access_token?: string; instance_url?: string }
if (!data.access_token) {
console.error("Salesforce auth response did not include an access token")
return
}
return {
token: data.access_token,
url: data.instance_url ?? url,
}
}
export interface SalesforceLeadInput {
name: string
role: string
company?: string
email: string
phone?: string
message: string
}
export async function createLead(input: SalesforceLeadInput): Promise<boolean> {
const auth = await login()
if (!auth) return false
const res = await fetch(`${auth.url}/services/data/v59.0/sobjects/Lead`, {
method: "POST",
headers: {
Authorization: `Bearer ${auth.token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
LastName: input.name,
Company: input.company?.trim() || "Website",
Email: input.email,
Phone: input.phone ?? null,
Title: input.role,
Description: input.message,
LeadSource: "Website",
}),
}).catch((err) => {
console.error("Failed to create Salesforce lead:", err)
})
if (!res) return false
if (!res.ok) {
console.error("Failed to create Salesforce lead:", res.status, await res.text())
return false
}
return true
}
@@ -2,11 +2,15 @@ import type { APIEvent } from "@solidjs/start/server"
import { AWS } from "@opencode-ai/console-core/aws.js" import { AWS } from "@opencode-ai/console-core/aws.js"
import { i18n } from "~/i18n" import { i18n } from "~/i18n"
import { localeFromRequest } from "~/lib/language" import { localeFromRequest } from "~/lib/language"
import { createLead } from "~/lib/salesforce"
interface EnterpriseFormData { interface EnterpriseFormData {
name: string name: string
role: string role: string
company?: string
email: string email: string
phone?: string
alias?: string
message: string message: string
} }
@@ -14,33 +18,56 @@ export async function POST(event: APIEvent) {
const dict = i18n(localeFromRequest(event.request)) const dict = i18n(localeFromRequest(event.request))
try { try {
const body = (await event.request.json()) as EnterpriseFormData const body = (await event.request.json()) as EnterpriseFormData
const trap = typeof body.alias === "string" ? body.alias.trim() : ""
if (trap) {
return Response.json({ success: true, message: dict["enterprise.form.success.submitted"] }, { status: 200 })
}
// Validate required fields
if (!body.name || !body.role || !body.email || !body.message) { if (!body.name || !body.role || !body.email || !body.message) {
return Response.json({ error: dict["enterprise.form.error.allFieldsRequired"] }, { status: 400 }) return Response.json({ error: dict["enterprise.form.error.allFieldsRequired"] }, { status: 400 })
} }
// Validate email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
if (!emailRegex.test(body.email)) { if (!emailRegex.test(body.email)) {
return Response.json({ error: dict["enterprise.form.error.invalidEmailFormat"] }, { status: 400 }) return Response.json({ error: dict["enterprise.form.error.invalidEmailFormat"] }, { status: 400 })
} }
// Create email content
const emailContent = ` const emailContent = `
${body.message}<br><br> ${body.message}<br><br>
--<br> --<br>
${body.name}<br> ${body.name}<br>
${body.role}<br> ${body.role}<br>
${body.email}`.trim() ${body.company ? `${body.company}<br>` : ""}${body.email}<br>
${body.phone ? `${body.phone}<br>` : ""}`.trim()
// Send email using AWS SES const [lead, mail] = await Promise.all([
await AWS.sendEmail({ createLead({
to: "contact@anoma.ly", name: body.name,
subject: `Enterprise Inquiry from ${body.name}`, role: body.role,
body: emailContent, company: body.company,
replyTo: body.email, email: body.email,
}) phone: body.phone,
message: body.message,
}),
AWS.sendEmail({
to: "contact@anoma.ly",
subject: `Enterprise Inquiry from ${body.name}`,
body: emailContent,
replyTo: body.email,
}).then(
() => true,
(err) => {
console.error("Failed to send enterprise email:", err)
return false
},
),
])
if (!lead && !mail) {
console.error("Enterprise inquiry delivery failed", { email: body.email })
return Response.json({ error: dict["enterprise.form.error.internalServer"] }, { status: 500 })
}
return Response.json({ success: true, message: dict["enterprise.form.success.submitted"] }, { status: 200 }) return Response.json({ success: true, message: dict["enterprise.form.success.submitted"] }, { status: 200 })
} catch (error) { } catch (error) {
@@ -23,6 +23,7 @@
--color-text-strong: hsl(0, 5%, 12%); --color-text-strong: hsl(0, 5%, 12%);
--color-text-inverted: hsl(0, 20%, 99%); --color-text-inverted: hsl(0, 20%, 99%);
--color-text-success: hsl(119, 100%, 35%); --color-text-success: hsl(119, 100%, 35%);
--color-text-error: hsl(4, 72%, 45%);
--color-border: hsl(30, 2%, 81%); --color-border: hsl(30, 2%, 81%);
--color-border-weak: hsl(0, 1%, 85%); --color-border-weak: hsl(0, 1%, 85%);
@@ -50,6 +51,7 @@
--color-text-strong: hsl(0, 15%, 94%); --color-text-strong: hsl(0, 15%, 94%);
--color-text-inverted: hsl(0, 9%, 7%); --color-text-inverted: hsl(0, 9%, 7%);
--color-text-success: hsl(119, 60%, 72%); --color-text-success: hsl(119, 60%, 72%);
--color-text-error: hsl(4, 76%, 72%);
--color-border: hsl(0, 3%, 28%); --color-border: hsl(0, 3%, 28%);
--color-border-weak: hsl(0, 4%, 23%); --color-border-weak: hsl(0, 4%, 23%);
@@ -454,6 +456,13 @@
color: var(--color-text-success); color: var(--color-text-success);
text-align: left; text-align: left;
} }
[data-component="error-message"] {
margin-top: 1rem;
padding: 1rem 0;
color: var(--color-text-error);
text-align: left;
}
} }
} }
@@ -13,11 +13,15 @@ export default function Enterprise() {
const [formData, setFormData] = createSignal({ const [formData, setFormData] = createSignal({
name: "", name: "",
role: "", role: "",
company: "",
email: "", email: "",
phone: "",
alias: "",
message: "", message: "",
}) })
const [isSubmitting, setIsSubmitting] = createSignal(false) const [isSubmitting, setIsSubmitting] = createSignal(false)
const [showSuccess, setShowSuccess] = createSignal(false) const [showSuccess, setShowSuccess] = createSignal(false)
const [error, setError] = createSignal("")
const handleInputChange = (field: string) => (e: Event) => { const handleInputChange = (field: string) => (e: Event) => {
const target = e.target as HTMLInputElement | HTMLTextAreaElement const target = e.target as HTMLInputElement | HTMLTextAreaElement
@@ -26,6 +30,8 @@ export default function Enterprise() {
const handleSubmit = async (e: Event) => { const handleSubmit = async (e: Event) => {
e.preventDefault() e.preventDefault()
setError("")
setShowSuccess(false)
setIsSubmitting(true) setIsSubmitting(true)
try { try {
@@ -42,13 +48,21 @@ export default function Enterprise() {
setFormData({ setFormData({
name: "", name: "",
role: "", role: "",
company: "",
email: "", email: "",
phone: "",
alias: "",
message: "", message: "",
}) })
setTimeout(() => setShowSuccess(false), 5000) setTimeout(() => setShowSuccess(false), 5000)
return
} }
const data = (await response.json().catch(() => null)) as { error?: string } | null
setError(data?.error ?? i18n.t("enterprise.form.error.internalServer"))
} catch (error) { } catch (error) {
console.error("Failed to submit form:", error) console.error("Failed to submit form:", error)
setError(i18n.t("enterprise.form.error.internalServer"))
} finally { } finally {
setIsSubmitting(false) setIsSubmitting(false)
} }
@@ -147,6 +161,19 @@ export default function Enterprise() {
<div data-component="enterprise-column-2"> <div data-component="enterprise-column-2">
<div data-component="enterprise-form"> <div data-component="enterprise-form">
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div class="sr-only" aria-hidden="true">
<input
type="text"
name="alias"
tabIndex={-1}
autocomplete="new-password"
inputmode="none"
spellcheck={false}
value={formData().alias}
onInput={handleInputChange("alias")}
/>
</div>
<div data-component="form-group"> <div data-component="form-group">
<label for="name">{i18n.t("enterprise.form.name.label")}</label> <label for="name">{i18n.t("enterprise.form.name.label")}</label>
<input <input
@@ -171,6 +198,17 @@ export default function Enterprise() {
/> />
</div> </div>
<div data-component="form-group">
<label for="company">{i18n.t("enterprise.form.company.label")}</label>
<input
id="company"
type="text"
value={formData().company}
onInput={handleInputChange("company")}
placeholder={i18n.t("enterprise.form.company.placeholder")}
/>
</div>
<div data-component="form-group"> <div data-component="form-group">
<label for="email">{i18n.t("enterprise.form.email.label")}</label> <label for="email">{i18n.t("enterprise.form.email.label")}</label>
<input <input
@@ -183,6 +221,17 @@ export default function Enterprise() {
/> />
</div> </div>
<div data-component="form-group">
<label for="phone">{i18n.t("enterprise.form.phone.label")}</label>
<input
id="phone"
type="tel"
value={formData().phone}
onInput={handleInputChange("phone")}
placeholder={i18n.t("enterprise.form.phone.placeholder")}
/>
</div>
<div data-component="form-group"> <div data-component="form-group">
<label for="message">{i18n.t("enterprise.form.message.label")}</label> <label for="message">{i18n.t("enterprise.form.message.label")}</label>
<textarea <textarea
@@ -201,6 +250,7 @@ export default function Enterprise() {
</form> </form>
{showSuccess() && <div data-component="success-message">{i18n.t("enterprise.form.success")}</div>} {showSuccess() && <div data-component="success-message">{i18n.t("enterprise.form.success")}</div>}
{error() && <div data-component="error-message">{error()}</div>}
</div> </div>
</div> </div>
</div> </div>