import { redirect } from "next/navigation" import { and, eq, gte, lte } from "drizzle-orm" import { db } from "@/lib/db" import { profiles, rent_payments, leases, inspections } from "@/lib/db/schema" import { getSessionUser } from "@/lib/session" import { getAccountContext } from "@/lib/account" import { CalendarClient, type CalEvent } from "./calendar-client" export const metadata = { title: "Calendar" } const RENT_COLOR = (s: string) => s === "paid" ? "#10b981" : s === "overdue" ? "#ef4444" : "#6366f1" const LEASE_COLOR = "#f59e0b" const INSPECTION_COLOR = "#14b8a6" export default async function CalendarPage() { const user = await getSessionUser() if (!user) redirect("/login") const ctx = await getAccountContext(user.id) const ownerId = ctx.ownerId const now = new Date() const rangeStart = new Date(now.getFullYear(), now.getMonth() - 3, 1) const rangeEnd = new Date(now.getFullYear(), now.getMonth() + 12, 0) const iso = (d: Date) => d.toISOString().slice(0, 10) const [payments, leaseList, inspectionList, profile] = await Promise.all([ db.query.rent_payments.findMany({ where: and( eq(rent_payments.user_id, ownerId), gte(rent_payments.due_date, iso(rangeStart)), lte(rent_payments.due_date, iso(rangeEnd)) ), columns: { id: true, due_date: true, amount: true, status: true }, with: { tenant: { columns: { first_name: true, last_name: true } }, property: { columns: { name: true } }, unit: { columns: { unit_number: true } } }, }), db.query.leases.findMany({ where: and(eq(leases.user_id, ownerId), eq(leases.status, "active")), columns: { id: true, lease_end: true }, with: { tenant: { columns: { first_name: true, last_name: true } }, property: { columns: { name: true } } }, }), db.query.inspections.findMany({ where: and(eq(inspections.user_id, ownerId), gte(inspections.date, iso(rangeStart)), lte(inspections.date, iso(rangeEnd))), columns: { id: true, date: true, type: true, status: true }, with: { property: { columns: { name: true } }, unit: { columns: { unit_number: true } } }, }), db.query.profiles.findFirst({ where: eq(profiles.id, ownerId), columns: { calendar_token: true } }), ]) const events: CalEvent[] = [ ...payments.map((p) => { const who = `${p.tenant?.first_name ?? ""} ${p.tenant?.last_name ?? ""}`.trim() || "Tenant" const color = RENT_COLOR(p.status) return { id: `rent-${p.id}`, title: `${who} · $${Number(p.amount).toLocaleString("en-US")}`, start: p.due_date!, allDay: true, backgroundColor: color, borderColor: color, editable: ctx.canWrite, extendedProps: { type: "rent" as const, entityId: p.id, status: p.status, subtitle: `${p.property?.name ?? ""}${p.unit ? ` · Unit ${p.unit.unit_number}` : ""}`, href: "/rent", }, } }), ...leaseList.map((l) => { const who = `${l.tenant?.first_name ?? ""} ${l.tenant?.last_name ?? ""}`.trim() || "Tenant" return { id: `lease-${l.id}`, title: `Lease ends: ${who}`, start: l.lease_end!, allDay: true, backgroundColor: LEASE_COLOR, borderColor: LEASE_COLOR, editable: false, extendedProps: { type: "lease" as const, entityId: l.id, subtitle: l.property?.name ?? "", href: `/leases/${l.id}`, }, } }), ...inspectionList.map((ins) => { const label = ins.type.replace("_", "-") return { id: `insp-${ins.id}`, title: `${label} inspection`, start: ins.date!, allDay: true, backgroundColor: INSPECTION_COLOR, borderColor: INSPECTION_COLOR, editable: ctx.canWrite, extendedProps: { type: "inspection" as const, entityId: ins.id, status: ins.status, subtitle: `${ins.property?.name ?? ""}${ins.unit ? ` · Unit ${ins.unit.unit_number}` : ""}`, href: "/inspections", }, } }), ] const base = process.env.NEXT_PUBLIC_APP_URL ?? "" const subscribeUrl = profile?.calendar_token ? `${base}/api/calendar/${profile.calendar_token}.ics` : "" return (
Rent due dates, lease expirations, and inspections — subscribe to sync with Google, Apple, or Outlook.