diff --git a/src/routes/contact-us/+page.server.ts b/src/routes/contact-us/+page.server.ts
index 3788b552..f859f2db 100644
--- a/src/routes/contact-us/+page.server.ts
+++ b/src/routes/contact-us/+page.server.ts
@@ -19,6 +19,7 @@ async function sendContactEmail(data: {
message: string
type: 'Standard' | 'Media' | 'Partnerships' | 'Feedback'
organization?: string
+ city_country?: string
}) {
if (!env.MAILERSEND_API_KEY) {
console.error('MAILERSEND_API_KEY is not configured')
@@ -40,9 +41,13 @@ async function sendContactEmail(data: {
htmlContent += `
Organization: ${data.organization}
`
}
+ if (data.city_country) {
+ htmlContent += `City, Country: ${data.city_country}
`
+ }
+
htmlContent += `Message:
${data.message.replace(/\n/g, '
')}
`
- const textContent = `Name: ${data.name}\nEmail: ${data.email}\nSubject: ${data.subject}${data.organization ? `\nOrganization: ${data.organization}` : ''}\n\nMessage:\n${data.message}`
+ const textContent = `Name: ${data.name}\nEmail: ${data.email}\nSubject: ${data.subject}${data.organization ? `\nOrganization: ${data.organization}` : ''}${data.city_country ? `\nCity, Country: ${data.city_country}` : ''}\n\nMessage:\n${data.message}`
// Build the request body for MailerSend API
const emailBody: {
@@ -55,7 +60,7 @@ async function sendContactEmail(data: {
} = {
from: {
email: 'info@pauseai.info',
- name: 'PauseAI Contact Form'
+ name: `PauseAI ${data.type} Form`
},
to: [
{
@@ -63,7 +68,7 @@ async function sendContactEmail(data: {
name: 'PauseAI Team'
}
],
- subject: `[Contact Form] ${data.subject}`,
+ subject: `[${data.type} Form]: ${data.subject}`,
html: htmlContent,
text: textContent
}
@@ -225,10 +230,18 @@ export const actions: Actions = {
const name = data.get('name')?.toString()
const email = data.get('email')?.toString()
const organization = data.get('organization')?.toString()
- const subject = data.get('subject')?.toString()
+ const city_country = data.get('city_country')?.toString()
+
+ let subject = data.get('partnership_type')?.toString() || ''
+ const other_type = data.get('other_partnership_type')?.toString()
+
+ if (subject === 'Other' && other_type) {
+ subject = `Other: ${other_type}`
+ }
+
const message = data.get('message')?.toString()
- if (!name || !email || !organization || !subject || !message) {
+ if (!name || !email || !city_country || !subject || !message) {
return fail(400, { message: 'Missing required fields' })
}
@@ -236,6 +249,7 @@ export const actions: Actions = {
name,
email,
organization,
+ city_country,
subject,
message,
type: 'Partnerships'
diff --git a/src/routes/contact-us/+page.svelte b/src/routes/contact-us/+page.svelte
index df0f768c..ea34316e 100644
--- a/src/routes/contact-us/+page.svelte
+++ b/src/routes/contact-us/+page.svelte
@@ -15,10 +15,64 @@
let formData = {
media: { name: '', email: '', subject: '', organization: '', details: '' },
- partnerships: { name: '', email: '', organization: '', subject: '', message: '' },
+ partnerships: {
+ name: '',
+ email: '',
+ organization: '',
+ city_country: '',
+ partnership_type: '',
+ other_partnership_type: '',
+ message: ''
+ },
feedback: { name: '', email: '', subject: '', message: '' }
}
+ const partnershipOptions = [
+ 'Mobilize grassroots support for PauseAI’s mission',
+ 'Open a chapter in my city/country',
+ 'Organize a public demonstration or protest',
+ 'Support citizen lobbying efforts',
+ 'Invite Pause AI to participate/speak at your local event/meeting',
+ 'Test and refine policy proposals with policymakers',
+ 'Amplify Pause AI campaign and/or proposal',
+ 'Assist with surveys or qualitative data collection',
+ 'Help disseminate research findings to the public',
+ 'Connect Pause AI with experts',
+ 'Share grassroots public sentiment data',
+ 'Exchange volunteers for events or campaigns',
+ 'Pool resources for joint campaigns or event',
+ 'Collaborate on grant applications',
+ 'Co-create educational or advocacy content',
+ 'Mobilize volunteers for emergency response',
+ 'Adapt messaging for local/international contexts',
+ 'Connect with engaged volunteer base',
+ 'Explore general partnership opportunities',
+ 'Other'
+ ]
+
+ function countWords(str: string) {
+ return str.trim().split(/\s+/).length
+ }
+
+ function validatePartnershipForm() {
+ if (activeTab !== 'partnerships') return true
+
+ if (
+ formData.partnerships.partnership_type === 'Other' &&
+ countWords(formData.partnerships.other_partnership_type) > 10
+ ) {
+ toast.error('Other partnership type must be 10 words or less.')
+ return false
+ }
+
+ const messageWords = countWords(formData.partnerships.message)
+ if (messageWords > 200) {
+ toast.error(`Message must be 200 words or less. (Current: ${messageWords} words)`)
+ return false
+ }
+ return true
+ }
+
onMount(() => {
const tab = $page.url.searchParams.get('tab')
if (tab === 'media') {
@@ -45,7 +99,19 @@
localStorage.setItem('contactFormData', JSON.stringify(formData))
}
- function handleEnhance() {
+ function handleEnhance({ cancel }: { cancel: () => void }) {
+ if (activeTab === 'partnerships') {
+ // Manually validate because we can't easily use the form state inside the enhancer
+ // without potentially stale data if we just used `formData` variable.
+ // But `formData` variable IS bound to inputs, so it should be fine.
+ // However, `data` from the argument contains the actual FormData being submitted.
+
+ if (!validatePartnershipForm()) {
+ cancel()
+ return
+ }
+ }
+
loading = true
return async ({
result,
@@ -66,7 +132,9 @@
name: '',
email: '',
organization: '',
- subject: '',
+ city_country: '',
+ partnership_type: '',
+ other_partnership_type: '',
message: ''
}
} else if (activeTab === 'feedback') {
@@ -119,9 +187,8 @@
{#if activeTab === 'partnerships'}