1
0
mirror of https://github.com/XFox111/my-website.git synced 2026-04-22 07:28:01 +03:00

init: First version

This commit is contained in:
2024-08-19 23:08:50 +00:00
commit 3ec7d9a722
134 changed files with 17088 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
"use client";
import React, { useEffect } from "react";
import { useFormStatus } from "react-dom";
// Since useFormStatus requires to be inside of the form, I moved it to a separate helper component.
// Could it be done better? Probably.
// Did I do it? No.
/** Renders a React component that tracks the form status and calls the provided callback function when the form status changes. */
const FormStatusTracker: React.FC<FormStatusTrackerProps> = ({ onPendingChanged }) =>
{
const { pending } = useFormStatus();
useEffect(() =>
{
onPendingChanged(pending);
}, [pending, onPendingChanged]);
return null;
};
export default FormStatusTracker;
/** Props for the `FormStatusTracker` component. */
export type FormStatusTrackerProps =
{
/** The callback function that is called when the form status changes. */
// For some reason ESLint shows a warning for "unused" "pending" parameter.
// eslint-disable-next-line no-unused-vars
onPendingChanged: (pending: boolean) => void;
};
+74
View File
@@ -0,0 +1,74 @@
"use server";
import { canonicalName } from "@/_data/metadata";
import nodemailer from "nodemailer";
import { z } from "zod";
const schema = z.object({
email: z.string().email().max(60),
subject: z.string().max(120),
message: z.string().min(100).max(2000),
timezone: z.string().optional()
});
const mailClient = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: parseInt(process.env.SMTP_PORT!),
priority: "high",
auth:
{
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD
}
});
export default async function sendInquiry(_: FormStatus, formData: FormData): Promise<FormStatus>
{
const { success, data } = schema.safeParse({
email: formData.get("email"),
subject: formData.get("subject"),
message: formData.get("message"),
timezone: formData.get("timezone")
});
if (!success)
return {
status: "error",
message: "Invalid request"
};
await mailClient.sendMail({
from: process.env.SMTP_FROM_EMAIL,
to: process.env.SMTP_TO_EMAIL,
subject: `${canonicalName.hostname}: Contact Inquiry`,
text: getTemplate(data)
});
return {
status: "success"
};
}
const getTemplate = (data: InquiryData): string => (
`From: ${data.email}
Received on: ${new Date()}
Sender timezone: ${data.timezone ?? "Unknown"}
Subject: ${data.subject}
${data.message}`
);
export type FormStatus =
{
status: "idle" | "success" | "error";
message?: string;
};
type InquiryData =
{
email: string;
subject: string;
message: string;
timezone?: string;
};