mirror of
https://github.com/waynesutton/markdown-site.git
synced 2026-01-12 12:19:18 +00:00
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
85 lines
2.5 KiB
TypeScript
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;
|
|
},
|
|
});
|