// routes/landlord/tenants/invites.tsx import { define } from "../../../utils.ts"; import { page } from "fresh"; import type { SessionCookie } from "../../auth/callback.ts"; import type { Property, TenantInvite } from "../../../db/interfaces.ts"; import { getPropertiesByOwner } from "../../../services/propertyService.ts"; import { getTenantInvitesByLandlord } from "../../../services/tenantInviteService.ts"; import { getPropertyById } from "../../../services/propertyService.ts"; import DeleteTenantInviteButton from "../../../islands/DeleteTenantInviteButton.tsx"; interface InvitesPageData { stateData: SessionCookie; properties: Property[]; invites: (TenantInvite & { property?: Property })[]; error?: string; } function parseInvitedEmails(value?: string | null) { if (!value) return []; try { const parsed = JSON.parse(value); if (Array.isArray(parsed)) { return parsed.filter((item) => typeof item === "string"); } } catch (_error) { // Fall back to comma-separated parsing. } return value.split(",").map((item) => item.trim()).filter(Boolean); } export const handler = define.handlers({ async GET(ctx) { const stateData = ctx.state.data as SessionCookie; const { user_id } = stateData; if (!user_id) { return new Response("", { status: 302, headers: { Location: "/auth/login" }, }); } try { const properties = await getPropertiesByOwner(user_id); const invites = await getTenantInvitesByLandlord(user_id); // Enrich invites with property data const enrichedInvites = await Promise.all( invites.map(async (invite) => { const property = invite.property_id ? await getPropertyById(invite.property_id) : null; return { ...invite, property }; }) ); return page({ stateData, properties, invites: enrichedInvites, }); } catch (error) { console.error("Error loading tenant invites:", error); return page({ stateData, properties: [], invites: [], error: "Unable to load tenant invites. Please try again.", }); } }, }); export default define.page(function TenantInvitesPage({ data }) { const { stateData, properties, invites, error } = data as InvitesPageData; return (

Tenant Invites

Manage your tenant invitations and track their status

{error && (
{error}
)} {invites.length === 0 ? (

No tenant invites

Get started by creating your first tenant invite.

) : (
{invites.map((invite) => { const invitedEmails = parseInvitedEmails(invite.invited_emails); const propertyAddress = invite.property?.address_1 || invite.property?.title || 'Unknown Property'; return (

{propertyAddress}

Invited Emails:
{invitedEmails.length > 0 ? (
    {invitedEmails.map((email, index) => (
  • {email}
  • ))}
) : (

No emails added

)}
Available On:

{invite.available_on ? new Date(invite.available_on).toLocaleDateString() : "Immediately"}

Status:
{invite.lease_id ? ( Lease Created ) : ( Pending )}
Created:

{invite.created_on ? new Date(invite.created_on).toLocaleDateString() : "Unknown"}

); })}
)}
); });