Merge pull request #54 from nathanAndrinoid/open-swe/c8b0eca2-cb28-4a8f-ba09-09a7b62df99e

[WIP]: Implement lease creation for landlord dashboard and verify payment service
This commit is contained in:
nathanAndrinoid 2026-01-22 15:52:23 -06:00 committed by GitHub
commit 4982ab1ed7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 146 additions and 1 deletions

View File

@ -388,3 +388,11 @@ export const brain_question_progress = pgTable("brain_question_progress", {
created_on: bigint("created_on", { mode: "number" }),
updated_on: bigint("updated_on", { mode: "number" }),
});

View File

@ -0,0 +1,74 @@
import { define } from "../../../utils.ts";
import LeasedHome from "../../../islands/LeasedHome.tsx";
import { page } from "fresh";
import { SessionCookie } from "../../auth/callback.ts";
import WelcomeBar from "../../../islands/WelcomeBar/WelcomeBar.tsx";
import { getAllProperties } from "../../../services/propertyService.ts";
import { getLeasesByOwner } from "../../../services/leaseService.ts";
import { createPublicId } from "../../../helpers.ts";
import type { Lease, Property } from "../../../db/interfaces.ts";
export const handler = define.handlers({
async GET(ctx) {
const stateData: SessionCookie = ctx.state.data;
if (!stateData?.user_id) {
return new Response("", {
status: 302,
headers: { Location: "/auth/login" },
});
}
const ownerId = stateData.user_id;
let leases: Lease[] = [];
let properties: Property[] = [];
leases = await getLeasesByOwner(ownerId);
properties = await getAllProperties();
const publicId = stateData.user_id
? await createPublicId(stateData.user_id)
: "";
return page({
stateData,
leases,
properties,
user_name: stateData.user_name,
isEncrypted: stateData.user_encrypted,
publicId,
stateId: ctx.state.stateId,
});
},
});
export default define.page(
(
{ data }: {
data: {
stateData: SessionCookie;
leases: Lease[];
properties: Property[];
user_name: string;
isEncrypted: boolean;
publicId: string;
stateId: string;
};
},
) => (
<main class="min-h-screen flex flex-col items-center justify-start pt-0">
<WelcomeBar
publicId={data.publicId}
user_name={data.user_name}
isEncrypted={data.isEncrypted}
currentRoute="/landlord/leases"
stateId={data.stateId}
/>
<div class="w-full max-w-4xl px-8 sm:px-12 lg:px-24 mt-8">
<LeasedHome
leases={data.leases || []}
properties={data.properties || []}
/>
</div>
</main>
),
);

View File

@ -3,7 +3,7 @@
import { and, eq } from "drizzle-orm";
import { db } from "../db/db.ts";
import { leases } from "../db/schema.ts";
import { leases, tenant_invites } from "../db/schema.ts";
import { Lease } from "../db/interfaces.ts";
import {
getE2ELeaseById,
@ -247,3 +247,66 @@ export async function getLeaseStatsByOwner(owner_id: string) {
without_tenant: allLeases.filter((l) => l.tenant_id === null).length,
};
}
/**
* Link a lease to a tenant invite. If an inviteId is provided, update that
* tenant_invites row to reference this lease. Otherwise attempt to find an
* existing invite by the lease's property and owner and attach the lease_id
* there; if none exists, create a new tenant_invites row linking to the lease.
*/
export async function inviteLease(lease_id: string, inviteId?: string) {
// If an explicit inviteId was provided, update that invite record
if (inviteId) {
const now = Date.now();
return await db.update(tenant_invites)
.set({ lease_id, updated_on: now })
.where(eq(tenant_invites.id, inviteId))
.returning();
}
// Otherwise derive the property and landlord from the lease
const lease = await getLeaseById(lease_id);
if (!lease) return null;
const existing = await db.select().from(tenant_invites).where(
and(
eq(tenant_invites.property_id, lease.property_id),
eq(tenant_invites.landlord_id, lease.owner_id),
),
);
const now = Date.now();
if (existing.length > 0) {
return await db.update(tenant_invites)
.set({ lease_id, updated_on: now })
.where(eq(tenant_invites.id, existing[0].id))
.returning();
}
// Create a new invite linking to this lease
return await db.insert(tenant_invites).values({
id: crypto.randomUUID(),
landlord_id: lease.owner_id,
property_id: lease.property_id,
lease_id,
available_on: null,
invited_emails: JSON.stringify([]),
created_on: now,
updated_on: now,
}).returning();
}