integratedhub/islands/MemberHome.tsx

232 lines
7.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect } from "preact/hooks";
import FloatingTileButtons from "./tiles/FloatingTileButtons.tsx";
import type { OnboardingStatus } from "../services/onboardingService.ts";
interface MemberHomeProps {
onboardingStatus?: OnboardingStatus | null;
/** Server-provided calendar year for hydration-safe initial link (avoids server/client date mismatch). */
serverCalendarYear?: number;
/** Server-provided calendar month (1–12) for hydration-safe initial link. */
serverCalendarMonth?: number;
}
export default function MemberHome(
{ onboardingStatus, serverCalendarYear, serverCalendarMonth }:
MemberHomeProps,
) {
useEffect(() => {
const lockRoute = localStorage.getItem("lock-route");
if (lockRoute) {
localStorage.removeItem("lock-route");
globalThis.location.href = lockRoute;
return;
}
const loginPurpose = localStorage.getItem("login-purpose");
if (loginPurpose) {
localStorage.removeItem("login-purpose");
const tenantDone = Boolean(onboardingStatus?.onboarded_tenant);
const destination = loginPurpose === "landlord"
? "/landlord/dashboard"
: loginPurpose === "tenant"
? (tenantDone ? "/tenant/dashboard" : "/tenant/onboarding")
: "";
if (destination) {
globalThis.location.href = destination;
}
}
}, [onboardingStatus]);
const tileIds = [
{ id: "landlord-hub", label: "Landlord" },
{ id: "tenant-hub", label: "Tenant" },
{ id: "admin-center", label: "Admin" },
{ id: "user-profile", label: "Profile" },
{ id: "dashboard", label: "Dashboard" },
{ id: "financial-calendar", label: "Calendar" },
];
const tenantOnboarded = Boolean(onboardingStatus?.onboarded_tenant);
const landlordStep = onboardingStatus?.onboarding_step ?? 0;
const landlordStarted = Boolean(onboardingStatus?.onboarded_landlord) ||
landlordStep > 0;
const landlordReady = landlordStarted && landlordStep === 0;
const landlordInProgress = landlordStep > 0;
const landlordPrimary = landlordReady
? { label: "Open Landlord Dashboard", href: "/landlord/dashboard" }
: landlordInProgress
? { label: "Continue Landlord Setup", href: "/landlord/onboarding/profile" }
: { label: "Start Landlord Setup", href: "/landlord/onboarding/profile" };
const tenantPrimary = tenantOnboarded
? { label: "Open Tenant Dashboard", href: "/tenant/dashboard" }
: { label: "Continue Tenant Setup", href: "/tenant/onboarding" };
const year = serverCalendarYear ?? new Date().getFullYear();
const month = serverCalendarMonth ?? new Date().getMonth() + 1;
const calendarHref = `/calendar/financial-calendar/${year}/${
month.toString().padStart(2, "0")
}?`;
return (
<>
<div class="landing-home landing-home--member">
<div class="landing-grid-overlay" aria-hidden="true"></div>
<div class="landing-orb landing-orb--north" aria-hidden="true"></div>
<div class="landing-orb landing-orb--east" aria-hidden="true"></div>
<div class="landing-orb landing-orb--south" aria-hidden="true"></div>
<section class="member-hero-panel">
<div class="member-hero-main">
<img
src="/logo.svg"
alt="Cyber Hybrid Hub Logo"
width="72"
height="72"
class="member-logo"
/>
<div>
<p class="landing-eyebrow">Member Workspace</p>
<h1 class="member-heading">Go straight to what matters</h1>
<p class="member-copy">
Open landlord or tenant dashboards quickly, or jump into the
financial calendar to plan your monthly budget.
</p>
</div>
</div>
<div class="member-status-row">
<div class="status-chip">
<span>Landlord</span>
<strong>
{landlordReady
? "Ready"
: landlordInProgress
? "Setup in Progress"
: "Not Started"}
</strong>
</div>
<div class="status-chip">
<span>Tenant</span>
<strong>{tenantOnboarded ? "Ready" : "Setup Needed"}</strong>
</div>
<div class="status-chip">
<span>Finance</span>
<strong>Calendar Ready</strong>
</div>
</div>
</section>
<section class="member-hub-grid">
<article id="landlord-hub" class="hub-card">
<div class="hub-card-header">
<h2>Landlord Operations</h2>
<span
class={`hub-badge ${
landlordReady
? "hub-badge--ready"
: landlordInProgress
? "hub-badge--progress"
: "hub-badge--pending"
}`}
>
{landlordReady
? "Onboarded"
: landlordInProgress
? "In Progress"
: "Not Set Up"}
</span>
</div>
<p>
Manage listings, tenants, lease activity, and incoming payments
from a single workflow.
</p>
<div class="hub-actions">
<a href={landlordPrimary.href} class="primary-action">
{landlordPrimary.label}
</a>
<a
href={landlordReady
? "/landlord/properties/add"
: "/landlord/onboarding/profile"}
class="secondary-action"
>
{landlordReady ? "Add Property" : "Complete Profile"}
</a>
</div>
</article>
<article id="tenant-hub" class="hub-card">
<div class="hub-card-header">
<h2>Tenant Workspace</h2>
<span
class={`hub-badge ${
tenantOnboarded ? "hub-badge--ready" : "hub-badge--pending"
}`}
>
{tenantOnboarded ? "Active" : "Needs Setup"}
</span>
</div>
<p>
Stay on top of rent, maintenance requests, and documents with
clear tenant-first workflows.
</p>
<div class="hub-actions">
<a href={tenantPrimary.href} class="primary-action">
{tenantPrimary.label}
</a>
<a href="/tenant/property" class="secondary-action">
View Property Details
</a>
</div>
</article>
</section>
<section class="member-quick-grid">
<article id="admin-center" class="quick-card">
<h3>Admin Center</h3>
<p>
Administrative controls are available based on your account
permissions.
</p>
</article>
<a
id="user-profile"
href="/user-profile"
class="quick-card quick-card-link"
>
<h3>Profile</h3>
<p>Review account and security preferences.</p>
</a>
<button
onClick={() => {
localStorage.setItem("lock-route", "/language/dashboard");
globalThis.location.href = "/language/dashboard";
}}
type="button"
id="dashboard"
class="quick-card quick-card-link text-left"
>
<h3>Dashboard</h3>
<p>Open your language and learning dashboard.</p>
</button>
<a
href={calendarHref}
id="financial-calendar"
class="quick-card quick-card-link"
>
<h3>Financial Calendar</h3>
<p>Track income and obligations by day.</p>
</a>
</section>
</div>
<FloatingTileButtons ids={[...tileIds]} />
</>
);
}