From 70f55c98b5b3ddf1eee1dbc667a640821ee0ab3a Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 14 Mar 2026 16:50:03 -0500 Subject: [PATCH] crm2 --- client/src/index.css | 3 +- client/src/lib/api.ts | 22 +++ .../src/modules/crm/CrmContactEntryForm.tsx | 72 ++++++++++ .../src/modules/crm/CrmContactTypeBadge.tsx | 13 ++ client/src/modules/crm/CrmDetailPage.tsx | 105 ++++++++++++++- client/src/modules/crm/config.ts | 32 ++++- client/src/theme/ThemeProvider.tsx | 2 +- .../migration.sql | 19 +++ server/prisma/schema.prisma | 19 +++ server/src/modules/crm/router.ts | 50 ++++++- server/src/modules/crm/service.ts | 127 +++++++++++++++++- shared/src/crm/types.ts | 24 ++++ 12 files changed, 477 insertions(+), 11 deletions(-) create mode 100644 client/src/modules/crm/CrmContactEntryForm.tsx create mode 100644 client/src/modules/crm/CrmContactTypeBadge.tsx create mode 100644 server/prisma/migrations/20260314203000_crm_contact_history/migration.sql diff --git a/client/src/index.css b/client/src/index.css index 7219984..32759cd 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -9,7 +9,8 @@ --font-family: "Manrope"; --color-brand: 24 90 219; --color-accent: 0 166 166; - --color-surface: 244 247 251; + --color-surface-brand: 244 247 251; + --color-surface: var(--color-surface-brand); --color-page: 248 250 252; --color-text: 15 23 42; --color-muted: 90 106 133; diff --git a/client/src/lib/api.ts b/client/src/lib/api.ts index c07fccc..a8c5c15 100644 --- a/client/src/lib/api.ts +++ b/client/src/lib/api.ts @@ -9,6 +9,8 @@ import type { LoginResponse, } from "@mrp/shared"; import type { + CrmContactEntryDto, + CrmContactEntryInput, CrmRecordDetailDto, CrmRecordInput, CrmRecordStatus, @@ -140,6 +142,16 @@ export const api = { token ); }, + createCustomerContactEntry(token: string, customerId: string, payload: CrmContactEntryInput) { + return request( + `/api/v1/crm/customers/${customerId}/contact-history`, + { + method: "POST", + body: JSON.stringify(payload), + }, + token + ); + }, getVendors(token: string, filters?: { q?: string; status?: CrmRecordStatus; state?: string }) { return request( `/api/v1/crm/vendors${buildQueryString({ @@ -174,6 +186,16 @@ export const api = { token ); }, + createVendorContactEntry(token: string, vendorId: string, payload: CrmContactEntryInput) { + return request( + `/api/v1/crm/vendors/${vendorId}/contact-history`, + { + method: "POST", + body: JSON.stringify(payload), + }, + token + ); + }, getGanttDemo(token: string) { return request<{ tasks: GanttTaskDto[]; links: GanttLinkDto[] }>("/api/v1/gantt/demo", undefined, token); }, diff --git a/client/src/modules/crm/CrmContactEntryForm.tsx b/client/src/modules/crm/CrmContactEntryForm.tsx new file mode 100644 index 0000000..82c987f --- /dev/null +++ b/client/src/modules/crm/CrmContactEntryForm.tsx @@ -0,0 +1,72 @@ +import type { CrmContactEntryInput } from "@mrp/shared/dist/crm/types.js"; + +import { crmContactTypeOptions } from "./config"; + +interface CrmContactEntryFormProps { + form: CrmContactEntryInput; + isSaving: boolean; + status: string; + onChange: (key: Key, value: CrmContactEntryInput[Key]) => void; + onSubmit: (event: React.FormEvent) => void; +} + +export function CrmContactEntryForm({ form, isSaving, status, onChange, onSubmit }: CrmContactEntryFormProps) { + return ( +
+
+ + +
+ +