172 lines
6.2 KiB
TypeScript
172 lines
6.2 KiB
TypeScript
// routes/tenant/applications/index.tsx
|
|
import { define } from "../../../utils.ts";
|
|
import { page } from "fresh";
|
|
import { getApplicationsByApplicant } from "../../../services/tenantApplicationService.ts";
|
|
import { TenantApplication } from "../../../db/interfaces.ts";
|
|
import { AlertMessage } from "../maintenance/new/components/AlertMessage.tsx";
|
|
|
|
interface ApplicationsPageData {
|
|
applications: TenantApplication[];
|
|
error?: string;
|
|
}
|
|
|
|
export const handler = define.handlers({
|
|
async GET(ctx) {
|
|
const { user_id } = ctx.state.data;
|
|
|
|
if (!user_id) {
|
|
return new Response("", {
|
|
status: 302,
|
|
headers: { Location: "/auth/login" },
|
|
});
|
|
}
|
|
|
|
try {
|
|
const applications = await getApplicationsByApplicant(user_id);
|
|
|
|
return page<ApplicationsPageData>({
|
|
applications: applications || [],
|
|
});
|
|
} catch (error) {
|
|
console.error("Error loading tenant applications:", error);
|
|
return page<ApplicationsPageData>({
|
|
applications: [],
|
|
error: "Failed to load applications.",
|
|
});
|
|
}
|
|
},
|
|
});
|
|
|
|
function ApplicationStatusPill({ status }: { status: string }) {
|
|
let colorClass = "bg-gray-100 text-gray-800";
|
|
switch (status.toLowerCase()) {
|
|
case "submitted":
|
|
case "pending":
|
|
colorClass = "bg-yellow-100 text-yellow-800";
|
|
break;
|
|
case "approved":
|
|
colorClass = "bg-green-100 text-green-800";
|
|
break;
|
|
case "rejected":
|
|
colorClass = "bg-red-100 text-red-800";
|
|
break;
|
|
}
|
|
return (
|
|
<span
|
|
class={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${colorClass} capitalize`}
|
|
>
|
|
{status}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export default define.page(function TenantApplicationsPage({ data }) {
|
|
const { applications, error } = data as ApplicationsPageData;
|
|
|
|
return (
|
|
<div class="min-h-screen bg-gray-50">
|
|
{/* Header */}
|
|
<div class="bg-white shadow">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="py-6 flex justify-between items-center">
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-gray-900">My Applications</h1>
|
|
<p class="mt-1 text-sm text-gray-500">
|
|
View the status of your submitted rental applications.
|
|
</p>
|
|
</div>
|
|
<a
|
|
href="/tenant/applications/new"
|
|
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
New Application
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Main Content */}
|
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 py-8">
|
|
{error && <AlertMessage type="error" message={error} />}
|
|
|
|
<div class="flex flex-col">
|
|
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
|
<div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
|
|
<div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th
|
|
scope="col"
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
>
|
|
Application ID
|
|
</th>
|
|
<th
|
|
scope="col"
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
>
|
|
Submitted On
|
|
</th>
|
|
<th
|
|
scope="col"
|
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
>
|
|
Status
|
|
</th>
|
|
<th scope="col" class="relative px-6 py-3">
|
|
<span class="sr-only">View</span>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="bg-white divide-y divide-gray-200">
|
|
{applications.length === 0
|
|
? (
|
|
<tr>
|
|
<td
|
|
colspan={4}
|
|
class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center"
|
|
>
|
|
No applications submitted yet.
|
|
</td>
|
|
</tr>
|
|
)
|
|
: (
|
|
applications.map((app) => (
|
|
<tr key={app.id}>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
|
|
{app.id.substring(0, 8)}...
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
|
{app.submitted_on
|
|
? new Date(app.submitted_on)
|
|
.toLocaleDateString()
|
|
: "N/A"}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm">
|
|
<ApplicationStatusPill
|
|
status={app.application_status || "Unknown"}
|
|
/>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
<a
|
|
href={`/tenant/applications/${app.id}`}
|
|
class="text-blue-600 hover:text-blue-900"
|
|
>
|
|
View Details
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
))
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|