2026-02-14 02:20:19 +00:00

199 lines
7.2 KiB
TypeScript

// routes/tenant/documents/index.tsx
import { define } from "../../../utils.ts";
import { page } from "fresh";
import { getLeasesByTenant } from "../../../services/leaseService.ts";
import {
getDocumentsByLease,
signDocumentAsTenant,
} from "../../../services/leaseDocumentService.ts";
import { Lease, LeaseDocument } from "../../../db/interfaces.ts";
function formatDate(value?: number | null): string {
if (!value) return "-";
return new Date(value).toLocaleDateString();
}
export const handler = define.handlers({
async GET(ctx) {
const { user_id } = ctx.state.data;
try {
const leases = await getLeasesByTenant(user_id);
const documents: Record<string, LeaseDocument[]> = {};
for (const lease of leases || []) {
if (!lease.id) continue;
documents[lease.id] = await getDocumentsByLease(lease.id);
}
return page({
leases,
documents,
});
} catch (error) {
console.error("Error loading tenant documents:", error);
return page({
error: "Failed to load documents",
});
}
},
async POST(ctx) {
const formData = await ctx.req.formData();
const action = (formData.get("action") || "").toString();
const documentId = (formData.get("document_id") || "").toString();
if (action === "sign" && documentId) {
await signDocumentAsTenant(documentId);
}
return new Response("", {
status: 302,
headers: { Location: "/tenant/documents" },
});
},
});
export default define.page(function TenantDocuments({ data }) {
const { leases, documents, error } = data as {
leases: Lease[];
documents: Record<string, LeaseDocument[]>;
error?: string;
};
return (
<div class="min-h-screen bg-gray-50">
<div class="bg-white shadow">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center py-6">
<div>
<h1 class="text-3xl font-bold text-gray-900">Documents</h1>
<p class="mt-1 text-sm text-gray-500">
Access your lease agreements, receipts, and notices
</p>
</div>
<div class="flex space-x-3">
<a
href="/tenant/dashboard"
class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50"
>
Back to Dashboard
</a>
</div>
</div>
</div>
</div>
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{error && (
<div class="mb-6 bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded">
{error}
</div>
)}
{(leases || []).map((lease) => {
const leaseDocs = documents?.[lease.id] || [];
return (
<div key={lease.id} class="mb-8 bg-white shadow rounded-lg">
<div class="px-6 py-4 border-b border-gray-200">
<div class="flex items-center justify-between">
<div>
<h2 class="text-lg font-semibold text-gray-900">
{lease.property_address || "Lease Documents"}
</h2>
<p class="text-sm text-gray-500">
Lease ID: {lease.id}
</p>
</div>
</div>
</div>
<div class="p-6">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">
Type
</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">
File
</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">
Tenant Status
</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">
Landlord Status
</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">
Signed
</th>
<th class="px-4 py-2"></th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{leaseDocs.length > 0
? (
leaseDocs.map((doc) => (
<tr key={doc.id}>
<td class="px-4 py-2 text-sm text-gray-900 capitalize">
{doc.document_type || "document"}
</td>
<td class="px-4 py-2 text-sm text-blue-600">
<a href={doc.file_url || "#"}>
{doc.file_name || "View"}
</a>
</td>
<td class="px-4 py-2 text-sm text-gray-900">
{doc.signed_by_tenant ? "Signed" : "Pending"}
</td>
<td class="px-4 py-2 text-sm text-gray-900">
{doc.signed_by_landlord ? "Signed" : "Pending"}
</td>
<td class="px-4 py-2 text-sm text-gray-900">
{formatDate(doc.signature_date)}
</td>
<td class="px-4 py-2 text-sm">
{!doc.signed_by_tenant && (
<form method="POST">
<input
type="hidden"
name="action"
value="sign"
/>
<input
type="hidden"
name="document_id"
value={doc.id}
/>
<button
type="submit"
class="text-blue-600 hover:text-blue-500"
>
Sign as Tenant
</button>
</form>
)}
</td>
</tr>
))
)
: (
<tr>
<td
colspan={6}
class="px-4 py-4 text-center text-sm text-gray-500"
>
No documents available yet
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
})}
</div>
</div>
);
});