// routes/tenant/messages/new/index.tsx import { define } from "../../../../utils.ts"; import { page } from "fresh"; import { getLeasesByTenant } from "../../../../services/leaseService.ts"; import { createMessage, getMessageById, } from "../../../../services/messageService.ts"; import { uploadToLocalBlobStorage } from "../../../../utils/blobStorage.ts"; import { Lease, Message } from "../../../../db/interfaces.ts"; import { FormField } from "../../maintenance/new/components/FormField.tsx"; import { TextAreaField } from "../../maintenance/new/components/TextAreaField.tsx"; import { FileUpload } from "../../maintenance/new/components/FileUpload.tsx"; import { AlertMessage } from "../../maintenance/new/components/AlertMessage.tsx"; interface NewMessagePageData { currentLease?: Lease; landlordId?: string; replyToMessage?: Message | null; initialSubject: string; error?: string; } async function getLandlordId(user_id: string): Promise { try { const leases = await getLeasesByTenant(user_id); // Assuming the first lease is the current active one return leases?.[0]?.owner_id || undefined; } catch (e) { console.error("Failed to get landlord ID:", e); return undefined; } } export const handler = define.handlers({ async GET(ctx) { const { user_id } = ctx.state.data; if (!user_id) { return new Response("", { status: 302, headers: { Location: "/auth/login" }, }); } try { const url = new URL(ctx.req.url); const replyToId = url.searchParams.get("reply_to"); const leases = await getLeasesByTenant(user_id); const currentLease = leases?.[0]; const landlordId = currentLease?.owner_id; if (!landlordId) { return page({ error: "Could not find an active lease or landlord ID.", initialSubject: "", }); } let replyToMessage: Message | null = null; let initialSubject = ""; if (replyToId) { const fetchedMessage = await getMessageById(replyToId); if (fetchedMessage) { replyToMessage = fetchedMessage; // Use the root message ID for threading if it's a reply const rootId = replyToMessage.parent_message_id || replyToMessage.id; replyToMessage.id = rootId; // Overwrite ID to ensure reply goes to the root const originalSubject = replyToMessage.subject || "No Subject"; initialSubject = originalSubject.startsWith("Re:") ? originalSubject : `Re: ${originalSubject}`; } } return page({ currentLease, landlordId, replyToMessage, initialSubject, }); } catch (error) { console.error("Error loading new message form:", error); return page({ error: "Failed to load form", initialSubject: "", }); } }, async POST(ctx) { const { user_id } = ctx.state.data; if (!user_id) { return new Response("", { status: 302, headers: { Location: "/auth/login" }, }); } try { const formData = await ctx.req.formData(); const lease_id = formData.get("lease_id") as string; const recipient_id = formData.get("recipient_id") as string; const subject = formData.get("subject") as string; const content = formData.get("content") as string; const parent_message_id = formData.get("parent_message_id") as string || null; if (!lease_id || !recipient_id || !subject || !content) { return new Response("Missing required fields", { status: 400 }); } const attachments: { url: string; name: string; type: string }[] = []; const files = formData.getAll("attachments") as File[]; for (const file of files) { if (file.size > 0) { const blob = new Blob([await file.arrayBuffer()], { type: file.type, }); const uploadResult = await uploadToLocalBlobStorage( file.name, blob, "image", { useTimestamp: true }, ); if (uploadResult.success && uploadResult.url) { attachments.push({ url: uploadResult.url, name: file.name, type: file.type, }); } } } await createMessage( lease_id, user_id, recipient_id, "general", // Default message type for tenant-initiated messages subject, content, parent_message_id, attachments.length > 0 ? attachments : null, ); // Redirect to the thread if it was a reply, otherwise to the main list const redirectPath = parent_message_id ? `/tenant/messages/${parent_message_id}` : "/tenant/messages"; return new Response("", { status: 302, headers: { Location: redirectPath }, }); } catch (error) { console.error("Error submitting new message:", error); return page({ error: "Failed to send message. Please try again.", initialSubject: "", }); } }, }); export default define.page(function NewTenantMessage({ data }) { const { currentLease, landlordId, replyToMessage, initialSubject, error, } = data as NewMessagePageData; const isReply = !!replyToMessage; const title = isReply ? "Reply to Message" : "Compose New Message"; const subtitle = isReply ? `Replying to: ${replyToMessage.subject || "No Subject"}` : "Send a new message to your landlord."; if (error && error !== "Failed to load form") { // If there's an error after POST, we should show it // but we don't have the form data to re-render the form, so we show a generic error page return ( ); } if (!currentLease || !landlordId) { return ( ); } return (
{/* Header */}

{title}

{subtitle}

{/* Main Content */}
{/* Hidden Fields */} {isReply && ( )}
{error && {error}} {/* Submit Button */}
Cancel
); });