- 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>
132 lines
3.7 KiB
TypeScript
132 lines
3.7 KiB
TypeScript
import { GHLAgencyClient } from '../agency-client';
|
|
import { GHLLocation } from '@/types/ghl';
|
|
|
|
export interface CreateLocationDTO {
|
|
name: string;
|
|
email: string;
|
|
phone?: string;
|
|
address?: string;
|
|
city?: string;
|
|
state?: string;
|
|
country?: string;
|
|
postalCode?: string;
|
|
timezone?: string;
|
|
website?: string;
|
|
}
|
|
|
|
export interface UpdateLocationDTO {
|
|
name?: string;
|
|
email?: string;
|
|
phone?: string;
|
|
address?: string;
|
|
city?: string;
|
|
state?: string;
|
|
country?: string;
|
|
postalCode?: string;
|
|
timezone?: string;
|
|
website?: string;
|
|
}
|
|
|
|
export interface LocationSettings {
|
|
allowDuplicateContact?: boolean;
|
|
allowDuplicateOpportunity?: boolean;
|
|
allowFacebookNameMerge?: boolean;
|
|
disableContactTimezone?: boolean;
|
|
}
|
|
|
|
export class LocationsService {
|
|
constructor(private agencyClient: GHLAgencyClient) {}
|
|
|
|
// Create a new location (sub-account) for a user
|
|
async create(data: CreateLocationDTO): Promise<GHLLocation> {
|
|
const response = await this.agencyClient.createLocation({
|
|
name: data.name,
|
|
email: data.email,
|
|
phone: data.phone,
|
|
address: data.address,
|
|
city: data.city,
|
|
state: data.state,
|
|
country: data.country || 'US',
|
|
postalCode: data.postalCode,
|
|
timezone: data.timezone || 'America/New_York',
|
|
});
|
|
|
|
return response as GHLLocation;
|
|
}
|
|
|
|
// Get a location by ID
|
|
async getById(locationId: string): Promise<GHLLocation> {
|
|
const response = await this.agencyClient.getLocation(locationId);
|
|
return response as GHLLocation;
|
|
}
|
|
|
|
// List all locations for the agency
|
|
async getAll(): Promise<GHLLocation[]> {
|
|
const response = await this.agencyClient.listLocations();
|
|
return (response as any).locations || [];
|
|
}
|
|
|
|
// Update a location
|
|
async update(locationId: string, data: UpdateLocationDTO): Promise<GHLLocation> {
|
|
return this.agencyClient.request(`/locations/${locationId}`, {
|
|
method: 'PUT',
|
|
body: JSON.stringify(data),
|
|
}) as Promise<GHLLocation>;
|
|
}
|
|
|
|
// Delete a location (use with caution!)
|
|
async delete(locationId: string): Promise<void> {
|
|
await this.agencyClient.request(`/locations/${locationId}`, {
|
|
method: 'DELETE',
|
|
});
|
|
}
|
|
|
|
// Get location settings
|
|
async getSettings(locationId: string): Promise<LocationSettings> {
|
|
const response = await this.agencyClient.request(`/locations/${locationId}/settings`);
|
|
return response as LocationSettings;
|
|
}
|
|
|
|
// Update location settings
|
|
async updateSettings(locationId: string, settings: LocationSettings): Promise<LocationSettings> {
|
|
return this.agencyClient.request(`/locations/${locationId}/settings`, {
|
|
method: 'PUT',
|
|
body: JSON.stringify(settings),
|
|
}) as Promise<LocationSettings>;
|
|
}
|
|
|
|
// Search locations by name or email
|
|
async search(query: string): Promise<GHLLocation[]> {
|
|
const all = await this.getAll();
|
|
const lowerQuery = query.toLowerCase();
|
|
return all.filter(loc =>
|
|
loc.name?.toLowerCase().includes(lowerQuery) ||
|
|
loc.email?.toLowerCase().includes(lowerQuery)
|
|
);
|
|
}
|
|
|
|
// Check if a location exists by email
|
|
async existsByEmail(email: string): Promise<boolean> {
|
|
const all = await this.getAll();
|
|
return all.some(loc => loc.email?.toLowerCase() === email.toLowerCase());
|
|
}
|
|
|
|
// Create location for a new user signup
|
|
async createForUser(user: {
|
|
email: string;
|
|
firstName: string;
|
|
lastName: string;
|
|
brokerage?: string;
|
|
}): Promise<GHLLocation> {
|
|
const locationName = user.brokerage
|
|
? `${user.firstName} ${user.lastName} - ${user.brokerage}`
|
|
: `${user.firstName} ${user.lastName}`;
|
|
|
|
return this.create({
|
|
name: locationName,
|
|
email: user.email,
|
|
timezone: 'America/New_York', // Default, can be updated later
|
|
});
|
|
}
|
|
}
|