feat(dashboard): berth-heat widget + investor-default surfacing
Step 6 minimal-but-functional per PRE-DEPLOY-PLAN § 1.6. Berth Heat — new widget showing top 15 berths by active interest count via the interest_berths junction (non-primary links included so multi-berth deals warm every berth in their bundle). Investor-friendly demand-pressure view; the ranked-table shape exports cleanly to PDF/ CSV. Future heatmap viz reads the same shape via /api/v1/dashboard/ berth-heat. Defaults flipped for investor-friendliness: - kpi_pipeline_value → defaultVisible (currency-aware headline number). - source_conversion → defaultVisible (conversion funnel by source; reads the inquiry → client linkage from Step 3). - berth_heat → defaultVisible. Pipeline-velocity-over-time + true heatmap viz deferred. pipeline_funnel covers snapshot stage breakdowns; over-time velocity warrants its own design pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
25
src/app/api/v1/dashboard/berth-heat/route.ts
Normal file
25
src/app/api/v1/dashboard/berth-heat/route.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
import { withAuth, withPermission } from '@/lib/api/helpers';
|
||||
import { errorResponse } from '@/lib/errors';
|
||||
import { getBerthHeatRanking } from '@/lib/services/berth-heat.service';
|
||||
|
||||
/**
|
||||
* GET /api/v1/dashboard/berth-heat
|
||||
*
|
||||
* Returns the top-N berths by active interest count, sorted hottest-
|
||||
* first. Drives the BerthHeatWidget on the dashboard and the future
|
||||
* heatmap visualization.
|
||||
*/
|
||||
export const GET = withAuth(
|
||||
withPermission('reports', 'view_dashboard', async (req, ctx) => {
|
||||
try {
|
||||
const url = new URL(req.url);
|
||||
const limit = Math.max(1, Math.min(50, Number(url.searchParams.get('limit') ?? '20')));
|
||||
const rows = await getBerthHeatRanking(ctx.portId, limit);
|
||||
return NextResponse.json({ data: { rows } });
|
||||
} catch (error) {
|
||||
return errorResponse(error);
|
||||
}
|
||||
}),
|
||||
);
|
||||
Reference in New Issue
Block a user