BusyBee3333 4e6467ffb0 Add CRESync CRM application with Setup page
- Build complete Next.js CRM for commercial real estate
- Add authentication with JWT sessions and role-based access
- Add GoHighLevel API integration for contacts, conversations, opportunities
- Add AI-powered Control Center with tool calling
- Add Setup page with onboarding checklist (/setup)
- Add sidebar navigation with Setup menu item
- Fix type errors in onboarding API, GHL services, and control center tools
- Add Prisma schema with SQLite for local development
- Add UI components with clay morphism design system

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 17:30:55 -05:00

71 lines
2.3 KiB
TypeScript

import { NextResponse } from 'next/server';
import { getSession } from '@/lib/auth/session';
import { getGHLClientForUser } from '@/lib/ghl/helpers';
export async function GET() {
try {
const session = await getSession();
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { user } = session;
// Try to get real stats from GHL if configured
const ghlClient = await getGHLClientForUser(user.id);
if (ghlClient) {
try {
// Fetch real data from GHL
const [contactsResponse, conversationsResponse, opportunitiesResponse] = await Promise.allSettled([
ghlClient.contacts.getAll({ limit: 1 }), // Just to get count from meta
ghlClient.conversations.getAll({ limit: 1 }),
ghlClient.opportunities.getAll({ limit: 100 }),
]);
let totalContacts = 0;
let activeConversations = 0;
let openOpportunities = 0;
let pipelineValue = 0;
if (contactsResponse.status === 'fulfilled') {
totalContacts = contactsResponse.value.meta?.total || 0;
}
if (conversationsResponse.status === 'fulfilled') {
activeConversations = conversationsResponse.value.data?.length || 0;
}
if (opportunitiesResponse.status === 'fulfilled') {
const opportunities = opportunitiesResponse.value.data || [];
openOpportunities = opportunities.filter((o: any) => o.status === 'open').length;
pipelineValue = opportunities.reduce((sum: number, o: any) => {
return sum + (parseFloat(o.monetaryValue) || 0);
}, 0);
}
return NextResponse.json({
totalContacts,
activeConversations,
openOpportunities,
pipelineValue,
});
} catch (ghlError) {
console.error('GHL fetch error:', ghlError);
// Fall through to return mock stats
}
}
// Return mock stats for users without GHL configured
return NextResponse.json({
totalContacts: 0,
activeConversations: 0,
openOpportunities: 0,
pipelineValue: 0,
});
} catch (error) {
console.error('Dashboard stats error:', error);
return NextResponse.json({ error: 'Failed to fetch stats' }, { status: 500 });
}
}