Files
wiki/convex/contact.ts
Wayne Sutton a87db9d171 docs: add changelog entries for v1.33.1 through v1.37.0
Add missing changelog entries to content/pages/changelog-page.md:

v1.34.0 (2025-12-26): Blog page featured layout with hero post
- blogFeatured frontmatter field for posts
- Hero card displays first featured post with landscape image
- 2-column featured row for remaining featured posts
- 3-column grid for regular posts

v1.35.0 (2025-12-26): Image support at top of posts and pages
- showImageAtTop frontmatter field
- Full-width image display above post header
- Works for both posts and pages

v1.36.0 (2025-12-27): Social footer component
- Customizable social links (8 platform types)
- Copyright with auto-updating year
- showSocialFooter frontmatter field for per-page control
- Configurable via siteConfig.socialFooter

v1.37.0 (2025-12-27): Newsletter Admin UI
- Three-column admin interface at /newsletter-admin
- Subscriber management with search and filters
- Send newsletter panel (post selection or custom email)
- Weekly digest automation (Sunday 9am UTC)
- Developer notifications (subscriber alerts, weekly stats)
- Markdown-to-HTML conversion for custom emails
2025-12-27 15:32:07 -08:00

85 lines
2.5 KiB
TypeScript

import { mutation, internalMutation } from "./_generated/server";
import { v } from "convex/values";
import { internal } from "./_generated/api";
// Environment variable error message for production
const ENV_VAR_ERROR_MESSAGE = "AgentMail Environment Variables are not configured in production. Please set AGENTMAIL_API_KEY, AGENTMAIL_INBOX, and AGENTMAIL_CONTACT_EMAIL.";
// Submit contact form message
// Stores the message and schedules email sending via AgentMail
export const submitContact = mutation({
args: {
name: v.string(),
email: v.string(),
message: v.string(),
source: v.string(), // "page:slug" or "post:slug"
},
returns: v.object({
success: v.boolean(),
message: v.string(),
}),
handler: async (ctx, args) => {
// Validate required fields
const name = args.name.trim();
const email = args.email.toLowerCase().trim();
const message = args.message.trim();
if (!name) {
return { success: false, message: "Please enter your name." };
}
if (!email || !email.includes("@") || !email.includes(".")) {
return { success: false, message: "Please enter a valid email address." };
}
if (!message) {
return { success: false, message: "Please enter a message." };
}
// Check environment variables before proceeding
// Note: We can't access process.env in mutations, so we check in the action
// But we can still store the message and let the action handle the error
// For now, we'll store the message and let the action fail silently
// The user will see a success message but email won't send if env vars are missing
// Store the message
const messageId = await ctx.db.insert("contactMessages", {
name,
email,
message,
source: args.source,
createdAt: Date.now(),
});
// Schedule email sending via Node.js action
// The action will check env vars and fail silently if not configured
await ctx.scheduler.runAfter(0, internal.contactActions.sendContactEmail, {
messageId,
name,
email,
message,
source: args.source,
});
return {
success: true,
message: "Thanks for your message! We'll get back to you soon.",
};
},
});
// Mark contact message as email sent
// Internal mutation to update emailSentAt timestamp
export const markEmailSent = internalMutation({
args: {
messageId: v.id("contactMessages"),
},
returns: v.null(),
handler: async (ctx, args) => {
await ctx.db.patch(args.messageId, {
emailSentAt: Date.now(),
});
return null;
},
});