Files
property-management-network/app/(dashboard)/ai-dashboard/page.tsx
T

108 lines
3.6 KiB
TypeScript
Raw Normal View History

import { redirect } from "next/navigation"
import { and, desc, eq, gte, inArray } from "drizzle-orm"
import { db } from "@/lib/db"
import {
ai_recommendations,
ai_predictions,
activity_log,
rent_payments,
units as unitsTable,
maintenance_requests,
} from "@/lib/db/schema"
import { getSessionUser } from "@/lib/session"
import { getEffectiveOwnerId } from "@/lib/account"
import { AiDashboardClient } from "./ai-dashboard-client"
export const metadata = { title: "AI Dashboard" }
export default async function AiDashboardPage() {
const user = await getSessionUser()
if (!user) redirect("/login")
const ownerId = await getEffectiveOwnerId(user.id)
const now = new Date()
const threeMonthsAgo = new Date(now)
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3)
const [recs, predictions, activityLog, payments, units, maintenance] = await Promise.all([
db
.select()
.from(ai_recommendations)
.where(eq(ai_recommendations.user_id, ownerId))
.orderBy(desc(ai_recommendations.created_at))
.limit(3),
db
.select()
.from(ai_predictions)
.where(eq(ai_predictions.user_id, ownerId))
.orderBy(desc(ai_predictions.created_at))
.limit(3),
db
.select()
.from(activity_log)
.where(and(eq(activity_log.user_id, ownerId), eq(activity_log.type, "ai_action")))
.orderBy(desc(activity_log.created_at))
.limit(5),
db
.select({ amount: rent_payments.amount, status: rent_payments.status })
.from(rent_payments)
.where(
and(
eq(rent_payments.user_id, ownerId),
gte(rent_payments.due_date, threeMonthsAgo.toISOString().slice(0, 10))
)
),
db
.select({ status: unitsTable.status })
.from(unitsTable)
.where(eq(unitsTable.user_id, ownerId)),
db
.select({ status: maintenance_requests.status, priority: maintenance_requests.priority })
.from(maintenance_requests)
.where(
and(
eq(maintenance_requests.user_id, ownerId),
inArray(maintenance_requests.status, ["open", "in_progress"])
)
),
])
const allRecsData = await db
.select({ status: ai_recommendations.status, action_data: ai_recommendations.action_data })
.from(ai_recommendations)
.where(eq(ai_recommendations.user_id, ownerId))
const approvedRecs = allRecsData.filter((r) => r.status === "approved")
let totalImpact = 0
for (const r of approvedRecs) {
totalImpact += Number(r.action_data?.estimated_value ?? 0)
}
const occupiedUnits = units?.filter((u: any) => u.status === "occupied").length ?? 0
const totalUnits = units?.length ?? 0
const occupancyRate = totalUnits > 0 ? Math.round((occupiedUnits / totalUnits) * 100) : 0
const totalRevenue = payments?.filter((p: any) => p.status === "paid").reduce((s: number, p: any) => s + Number(p.amount), 0) ?? 0
const overdueAmount = payments?.filter((p: any) => p.status === "overdue").reduce((s: number, p: any) => s + Number(p.amount), 0) ?? 0
const criticalMaintenance = maintenance?.filter((m: any) => m.priority === "emergency" || m.priority === "high").length ?? 0
const riskAlerts = predictions?.filter((p: any) => ["critical", "high"].includes(p.risk_level)).length ?? 0
return (
<AiDashboardClient
recentRecs={recs ?? []}
recentPredictions={predictions ?? []}
activityLog={activityLog ?? []}
stats={{
totalImpact,
approvedRecs: approvedRecs.length,
pendingRecs: allRecsData.filter((r) => r.status === "pending").length,
occupancyRate,
totalRevenue,
overdueAmount,
criticalMaintenance,
riskAlerts,
}}
/>
)
}