fixed sync

This commit is contained in:
2026-03-05 09:35:04 +00:00
parent a36d55eae5
commit 4ff4f9572d
4 changed files with 457 additions and 330 deletions

View File

@@ -3,8 +3,12 @@ import { DashboardControls } from "@/components/dashboard/dashboard-controls";
import { getServerAgencyContextOrRedirect } from "@/lib/agency";
import type { Database } from "@/lib/types";
import { createSupabaseServerClient } from "@/lib/supabase/server";
import type { PostgrestError } from "@supabase/supabase-js";
type AgencySummary = Pick<Database["public"]["Tables"]["agencies"]["Row"], "id" | "name">;
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"
@@ -20,96 +24,94 @@ export default async function DashboardPage() {
const [
{ data: agency },
{ data: instances },
{ data: instances, error: instancesError },
{ 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 },
];
] = (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;
error: { message: string } | 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,
@@ -129,7 +131,9 @@ export default async function DashboardPage() {
<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>
<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 />
@@ -138,26 +142,34 @@ export default async function DashboardPage() {
<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>
<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>
<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>
<p className="text-2xl font-semibold text-slate-900">
{billing?.subscription_status ?? "none"}
</p>
</div>
</section>
{instancesError ? (
<div className="rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-700">
Instances query failed: {instancesError.message}
</div>
) : null}
<DashboardControls
instances={instances ?? []}
subscriptions={subscriptions ?? []}
domains={domains ?? []}
autoSyncByInstance={Object.fromEntries(autoSyncByInstance.entries())}
/>
</main>
);
}