175 lines
5.3 KiB
TypeScript
175 lines
5.3 KiB
TypeScript
// routes/tenant/onboarding/index.tsx
|
|
import { define } from "../../../utils.ts";
|
|
import { page } from "fresh";
|
|
import type { SessionCookie } from "../../auth/callback.ts";
|
|
import { getUserById, updateUser } from "../../../services/userService.ts";
|
|
import {
|
|
getOnboardingStatus,
|
|
markRoleOnboarded,
|
|
} from "../../../services/onboardingService.ts";
|
|
import { User } from "../../../db/interfaces.ts";
|
|
import { createPublicId } from "../../../helpers.ts";
|
|
|
|
export const handler = define.handlers({
|
|
async GET(ctx) {
|
|
const stateData = ctx.state.data as SessionCookie;
|
|
const { user_id } = stateData;
|
|
|
|
const publicId = stateData.user_id
|
|
? await createPublicId(stateData.user_id)
|
|
: "";
|
|
|
|
const status = await getOnboardingStatus(user_id);
|
|
if (status?.onboarded_tenant) {
|
|
return new Response("", {
|
|
status: 303,
|
|
headers: { Location: "/tenant/dashboard" },
|
|
});
|
|
}
|
|
|
|
const user = await getUserById(user_id);
|
|
|
|
return page({ stateData, user: user ? { ...user, id: publicId } : null });
|
|
},
|
|
|
|
async POST(ctx) {
|
|
const stateData = ctx.state.data as SessionCookie;
|
|
const { user_id } = stateData;
|
|
|
|
const publicId = stateData.user_id
|
|
? await createPublicId(stateData.user_id)
|
|
: "";
|
|
|
|
const status = await getOnboardingStatus(user_id);
|
|
if (status?.onboarded_tenant) {
|
|
return new Response("", {
|
|
status: 303,
|
|
headers: { Location: "/tenant/dashboard" },
|
|
});
|
|
}
|
|
|
|
const formData = await ctx.req.formData();
|
|
|
|
const name = (formData.get("name") || "").toString().trim();
|
|
const email = (formData.get("email") || "").toString().trim();
|
|
const phone = (formData.get("phone") || "").toString().trim();
|
|
|
|
if (!name || !email || !phone) {
|
|
const user = await getUserById(user_id);
|
|
return page({
|
|
stateData,
|
|
user: user ? { ...user, id: publicId } : null,
|
|
error: "Name, email, and phone are required.",
|
|
});
|
|
}
|
|
|
|
await updateUser(user_id, {
|
|
name,
|
|
email,
|
|
phone,
|
|
user_type: "tenant",
|
|
onboarded_tenant: true,
|
|
} as Partial<User>);
|
|
|
|
await markRoleOnboarded(user_id, "tenant");
|
|
|
|
return new Response(null, {
|
|
status: 303,
|
|
headers: { Location: "/tenant/dashboard" },
|
|
});
|
|
},
|
|
});
|
|
|
|
export default define.page(function TenantOnboarding({ data }) {
|
|
const { stateData: _stateData, user, error } = data as {
|
|
stateData: SessionCookie;
|
|
user: User | null;
|
|
error?: string;
|
|
};
|
|
|
|
return (
|
|
<div class="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8 tenant-route">
|
|
<div class="sm:mx-auto sm:w-full sm:max-w-md">
|
|
<h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
|
|
Complete Your Tenant Profile
|
|
</h2>
|
|
<p class="mt-2 text-center text-sm text-gray-600">
|
|
We just need a few details to get you started.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
|
|
{error && (
|
|
<div class="mb-4 bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded">
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
<form method="POST" class="space-y-6">
|
|
<div>
|
|
<label
|
|
for="name"
|
|
class="block text-sm font-medium text-gray-700"
|
|
>
|
|
Full Name *
|
|
</label>
|
|
<input
|
|
id="name"
|
|
name="name"
|
|
type="text"
|
|
required
|
|
value={user?.name || ""}
|
|
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label
|
|
for="email"
|
|
class="block text-sm font-medium text-gray-700"
|
|
>
|
|
Email Address *
|
|
</label>
|
|
<input
|
|
id="email"
|
|
name="email"
|
|
type="email"
|
|
required
|
|
value={user?.email || ""}
|
|
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label
|
|
for="phone"
|
|
class="block text-sm font-medium text-gray-700"
|
|
>
|
|
Phone Number *
|
|
</label>
|
|
<input
|
|
id="phone"
|
|
name="phone"
|
|
type="tel"
|
|
required
|
|
value={user?.phone || ""}
|
|
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
|
/>
|
|
</div>
|
|
|
|
<div class="flex justify-end pt-6">
|
|
<button
|
|
type="submit"
|
|
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
Continue to Dashboard
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|