cre-sync/lib/ghl/webhook-handler.ts
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

91 lines
2.4 KiB
TypeScript

import { prisma } from '@/lib/db';
import { broadcaster } from '@/lib/realtime/broadcaster';
import { REALTIME_EVENTS } from '@/lib/realtime/events';
export interface GHLWebhookPayload {
type: string;
locationId: string;
data: any;
}
export async function handleGHLWebhook(payload: GHLWebhookPayload): Promise<{ success: boolean }> {
const { type, locationId, data } = payload;
console.log('[GHL Webhook] Received:', type, locationId);
// Find user by locationId
const user = await prisma.user.findFirst({
where: { ghlLocationId: locationId },
});
if (!user) {
console.log('[GHL Webhook] No user found for location:', locationId);
return { success: false };
}
// Process different webhook types
switch (type) {
case 'ContactCreate':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.CONTACT_CREATED, {
contact: data,
});
break;
case 'ContactUpdate':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.CONTACT_UPDATED, {
contact: data,
});
break;
case 'ContactDelete':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.CONTACT_DELETED, {
contactId: data.id,
});
break;
case 'InboundMessage':
case 'OutboundMessage':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.MESSAGE_RECEIVED, {
message: data,
direction: type === 'InboundMessage' ? 'inbound' : 'outbound',
});
break;
case 'OpportunityCreate':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.OPPORTUNITY_CREATED, {
opportunity: data,
});
break;
case 'OpportunityUpdate':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.OPPORTUNITY_UPDATED, {
opportunity: data,
});
break;
case 'OpportunityStageUpdate':
await broadcaster.broadcastToUser(user.id, REALTIME_EVENTS.OPPORTUNITY_STAGE_CHANGED, {
opportunity: data,
previousStage: data.previousStage,
newStage: data.newStage,
});
break;
default:
console.log('[GHL Webhook] Unhandled type:', type);
}
// Log webhook receipt
await prisma.auditLog.create({
data: {
userId: user.id,
action: 'WEBHOOK_RECEIVED',
resource: 'webhook',
resourceId: type,
details: { type, dataKeys: Object.keys(data) },
},
});
return { success: true };
}