Initial working state: CL3.5 complete (Plesk sync + suspend/unsuspend)
This commit is contained in:
163
app/dashboard/page.tsx
Normal file
163
app/dashboard/page.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import { SignOutButton } from "@/components/auth/sign-out-button";
|
||||
import { DashboardControls } from "@/components/dashboard/dashboard-controls";
|
||||
import { getServerAgencyContextOrRedirect } from "@/lib/agency";
|
||||
import type { Database } from "@/lib/types";
|
||||
import { createSupabaseServerClient } from "@/lib/supabase/server";
|
||||
|
||||
type AgencySummary = Pick<Database["public"]["Tables"]["agencies"]["Row"], "id" | "name">;
|
||||
type BillingSummary = Pick<
|
||||
Database["public"]["Tables"]["billing_accounts"]["Row"],
|
||||
"subscription_status" | "plan_id" | "current_period_end"
|
||||
>;
|
||||
type ActionLogSummary = Pick<
|
||||
Database["public"]["Tables"]["actions_log"]["Row"],
|
||||
"target_id" | "status" | "action" | "created_at" | "error_message"
|
||||
>;
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const context = await getServerAgencyContextOrRedirect();
|
||||
const supabase = createSupabaseServerClient() as any;
|
||||
|
||||
const [
|
||||
{ data: agency },
|
||||
{ data: instances },
|
||||
{ data: subscriptions },
|
||||
{ data: domains },
|
||||
{ data: billing },
|
||||
{ data: autoSyncLogs },
|
||||
] =
|
||||
(await Promise.all([
|
||||
supabase.from("agencies").select("id, name").eq("id", context.agencyId).maybeSingle(),
|
||||
supabase
|
||||
.from("plesk_instances")
|
||||
.select(
|
||||
"id, name, base_url, auth_type, status, error_message, last_connected_at, last_sync_at, last_sync_status, last_sync_error, last_sync_subscriptions, last_sync_domains",
|
||||
)
|
||||
.eq("agency_id", context.agencyId)
|
||||
.order("created_at", { ascending: false }),
|
||||
supabase
|
||||
.from("plesk_subscriptions")
|
||||
.select("id, name, status, plesk_subscription_id, plesk_instance_id")
|
||||
.eq("agency_id", context.agencyId)
|
||||
.order("updated_at", { ascending: false })
|
||||
.limit(10),
|
||||
supabase
|
||||
.from("plesk_domains")
|
||||
.select(
|
||||
"id, plesk_instance_id, domain_name, status, hosting_type, source_created_at, aliases_count, updated_at",
|
||||
)
|
||||
.eq("agency_id", context.agencyId)
|
||||
.order("updated_at", { ascending: false })
|
||||
.limit(500),
|
||||
supabase
|
||||
.from("billing_accounts")
|
||||
.select("subscription_status, plan_id, current_period_end")
|
||||
.eq("agency_id", context.agencyId)
|
||||
.maybeSingle(),
|
||||
supabase
|
||||
.from("actions_log")
|
||||
.select("target_id, status, action, created_at, error_message")
|
||||
.eq("agency_id", context.agencyId)
|
||||
.eq("target_type", "plesk_instance")
|
||||
.eq("action", "plesk_sync_auto")
|
||||
.order("created_at", { ascending: false })
|
||||
.limit(200),
|
||||
])) as [
|
||||
{ data: AgencySummary | null },
|
||||
{
|
||||
data:
|
||||
| Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
base_url: string;
|
||||
auth_type: "api_key" | "basic";
|
||||
status: string;
|
||||
error_message: string | null;
|
||||
last_connected_at: string | null;
|
||||
last_sync_at: string | null;
|
||||
last_sync_status: string | null;
|
||||
last_sync_error: string | null;
|
||||
last_sync_subscriptions: number;
|
||||
last_sync_domains: number;
|
||||
}>
|
||||
| null;
|
||||
},
|
||||
{
|
||||
data:
|
||||
| Array<{
|
||||
id: string;
|
||||
name: string | null;
|
||||
status: string | null;
|
||||
plesk_subscription_id: string;
|
||||
plesk_instance_id: string;
|
||||
}>
|
||||
| null;
|
||||
},
|
||||
{
|
||||
data:
|
||||
| Array<{
|
||||
id: string;
|
||||
plesk_instance_id: string;
|
||||
domain_name: string;
|
||||
status: string | null;
|
||||
hosting_type: string | null;
|
||||
source_created_at: string | null;
|
||||
aliases_count: number | null;
|
||||
updated_at: string;
|
||||
}>
|
||||
| null;
|
||||
},
|
||||
{ data: BillingSummary | null },
|
||||
{ data: ActionLogSummary[] | null },
|
||||
];
|
||||
|
||||
const autoSyncByInstance = new Map<
|
||||
string,
|
||||
{ status: string; created_at: string; error_message: string | null }
|
||||
>();
|
||||
|
||||
for (const log of autoSyncLogs ?? []) {
|
||||
if (!log.target_id || autoSyncByInstance.has(log.target_id)) continue;
|
||||
autoSyncByInstance.set(log.target_id, {
|
||||
status: log.status,
|
||||
created_at: log.created_at,
|
||||
error_message: log.error_message,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="mx-auto flex w-full max-w-6xl flex-col gap-6 px-6 py-8">
|
||||
<header className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-slate-900">{agency?.name ?? "Agency"} Dashboard</h1>
|
||||
<p className="text-sm text-slate-600">Role: {context.role}</p>
|
||||
</div>
|
||||
<SignOutButton />
|
||||
</header>
|
||||
|
||||
<section className="grid gap-4 md:grid-cols-3">
|
||||
<div className="rounded-xl border border-slate-200 bg-white p-4">
|
||||
<p className="text-sm text-slate-500">Plesk Instances</p>
|
||||
<p className="text-2xl font-semibold text-slate-900">{instances?.length ?? 0}</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-slate-200 bg-white p-4">
|
||||
<p className="text-sm text-slate-500">Tracked Subscriptions</p>
|
||||
<p className="text-2xl font-semibold text-slate-900">{subscriptions?.length ?? 0}</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-slate-200 bg-white p-4">
|
||||
<p className="text-sm text-slate-500">Billing Status</p>
|
||||
<p className="text-2xl font-semibold text-slate-900">{billing?.subscription_status ?? "none"}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<DashboardControls
|
||||
instances={instances ?? []}
|
||||
subscriptions={subscriptions ?? []}
|
||||
domains={domains ?? []}
|
||||
autoSyncByInstance={Object.fromEntries(autoSyncByInstance.entries())}
|
||||
/>
|
||||
|
||||
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user