Skip to content

Commit f832a10

Browse files
committed
feat: update project context and enhance lead conversion process with logging and error handling
1 parent 30fc027 commit f832a10

File tree

4 files changed

+71
-27
lines changed

4 files changed

+71
-27
lines changed

.github/copilot-instructions.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ user types we have
1414
## Project Context
1515

1616
BottleCRM is a modern CRM application built with:
17-
- **Framework**: SvelteKit 2.21.x, Svelte 5.x, Prisma
17+
- **Framework**: SvelteKit 2.21.x, Svelte 5.1, Prisma
1818
- **Styling**: tailwind 4.1.x css
1919
- **Database**: postgresql
2020
- **Icons**: lucide icons
21+
- **Form Validation**: zod
2122

2223
## Important Notes
2324
- We need to ensure access control is strictly enforced based on user roles.

src/routes/(app)/app/leads/[lead_id]/+page.server.js

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export const actions = {
4949
const org = locals.org;
5050

5151
try {
52+
console.log('Starting lead conversion for lead:', lead_id);
53+
5254
const lead = await prisma.lead.findUnique({
5355
where: { id: lead_id, organizationId: org.id },
5456
include: {
@@ -65,6 +67,7 @@ export const actions = {
6567
return { status: 'success', message: 'Lead already converted' };
6668
}
6769

70+
console.log('Creating contact...');
6871
const contact = await prisma.contact.create({
6972
data: {
7073
firstName: lead.firstName,
@@ -77,10 +80,12 @@ export const actions = {
7780
organization: { connect: { id: lead.organizationId } }
7881
}
7982
});
83+
console.log('Contact created with ID:', contact.id);
8084

8185
let accountId = null;
8286
let account = null;
8387
if (lead.company) {
88+
console.log('Creating account for company:', lead.company);
8489
account = await prisma.account.create({
8590
data: {
8691
name: lead.company,
@@ -90,7 +95,9 @@ export const actions = {
9095
}
9196
});
9297
accountId = account.id;
98+
console.log('Account created with ID:', accountId);
9399

100+
console.log('Creating account-contact relationship...');
94101
await prisma.accountContactRelationship.create({
95102
data: {
96103
account: { connect: { id: account.id } },
@@ -99,46 +106,48 @@ export const actions = {
99106
role: 'Primary Contact'
100107
}
101108
});
102-
}
103-
104-
const opportunityData = {
105-
name: `${lead.company || lead.firstName + ' ' + lead.lastName} Opportunity`,
106-
stage: 'PROSPECTING',
107-
amount: 0,
108-
closeDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
109-
contacts: { connect: { id: contact.id } },
110-
owner: { connect: { id: lead.ownerId } },
111-
organization: { connect: { id: lead.organizationId } }
112-
};
113-
114-
if (!accountId) {
115-
const placeholderAccount = await prisma.account.create({
109+
console.log('Account-contact relationship created');
110+
} else {
111+
console.log('Creating placeholder account...');
112+
// Create a placeholder account if no company
113+
account = await prisma.account.create({
116114
data: {
117115
name: `${lead.firstName} ${lead.lastName} Account`,
118116
owner: { connect: { id: lead.ownerId } },
119117
organization: { connect: { id: lead.organizationId } }
120118
}
121119
});
120+
accountId = account.id;
121+
console.log('Placeholder account created with ID:', accountId);
122122

123-
accountId = placeholderAccount.id;
124-
account = placeholderAccount;
125-
123+
console.log('Creating account-contact relationship...');
126124
await prisma.accountContactRelationship.create({
127125
data: {
128-
account: { connect: { id: placeholderAccount.id } },
126+
account: { connect: { id: account.id } },
129127
contact: { connect: { id: contact.id } },
130128
isPrimary: true,
131129
role: 'Primary Contact'
132130
}
133131
});
132+
console.log('Account-contact relationship created');
134133
}
135134

136-
opportunityData.account = { connect: { id: accountId } };
137-
135+
console.log('Creating opportunity...');
138136
const opportunity = await prisma.opportunity.create({
139-
data: opportunityData
137+
data: {
138+
name: `${lead.company || lead.firstName + ' ' + lead.lastName} Opportunity`,
139+
stage: 'PROSPECTING',
140+
amount: 0,
141+
closeDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
142+
contacts: { connect: { id: contact.id } },
143+
owner: { connect: { id: lead.ownerId } },
144+
organization: { connect: { id: lead.organizationId } },
145+
account: { connect: { id: accountId } }
146+
}
140147
});
148+
console.log('Opportunity created with ID:', opportunity.id);
141149

150+
console.log('Updating lead status...');
142151
await prisma.lead.update({
143152
where: { id: lead_id },
144153
data: {
@@ -151,17 +160,35 @@ export const actions = {
151160
contact: { connect: { id: contact.id } }
152161
}
153162
});
163+
console.log('Lead status updated successfully');
154164

165+
console.log('Lead conversion completed, account created:', accountId);
166+
155167
return {
156168
status: 'success',
157169
message: 'Lead successfully converted',
170+
redirectTo: `/app/accounts/${accountId}`,
158171
contact,
159172
account,
160173
opportunity
161174
};
162175
} catch (err) {
163-
console.error('Error converting lead:', err.message);
164-
return fail(500, { status: 'error', message: 'Failed to convert lead' });
176+
console.error('Error converting lead:', err);
177+
178+
// Extract meaningful error message
179+
let errorMessage = 'Failed to convert lead';
180+
if (err instanceof Error) {
181+
errorMessage = err.message;
182+
} else if (typeof err === 'string') {
183+
errorMessage = err;
184+
} else if (err && typeof err === 'object' && 'message' in err && typeof err.message === 'string') {
185+
errorMessage = err.message;
186+
}
187+
188+
return fail(500, {
189+
status: 'error',
190+
message: `Error converting lead: ${errorMessage}`
191+
});
165192
}
166193
},
167194

@@ -206,10 +233,11 @@ export const actions = {
206233
return {
207234
status: 'success',
208235
message: 'Comment added successfully',
236+
commentAdded: true,
209237
comments: updatedLead?.comments || []
210238
};
211239
} catch (err) {
212-
console.error('Error adding comment:', err.message);
240+
console.error('Error adding comment:', err instanceof Error ? err.message : String(err));
213241
if (err instanceof z.ZodError) {
214242
return fail(400, { status: 'error', message: err.errors[0].message });
215243
}

src/routes/(app)/app/leads/[lead_id]/+page.svelte

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script>
22
import { fly } from 'svelte/transition';
33
import { enhance } from '$app/forms';
4-
import { invalidateAll } from '$app/navigation';
4+
import { invalidateAll, goto } from '$app/navigation';
55
import {
66
UserCircle,
77
Edit3,
@@ -131,13 +131,18 @@
131131
isConverting = true;
132132
return async ({ update }) => {
133133
await update({ reset: false });
134+
// Note: If conversion is successful, the server will redirect automatically
135+
// This will only execute if there's an error
136+
isConverting = false;
134137
};
135138
};
136139
137140
const enhanceCommentForm = () => {
138141
isSubmittingComment = true;
139142
return async ({ update }) => {
140143
await update({ reset: false });
144+
// Reset the loading state after update
145+
isSubmittingComment = false;
141146
};
142147
};
143148
@@ -155,12 +160,22 @@
155160
if (form.commentAdded) {
156161
newComment = '';
157162
}
163+
// Handle redirect for lead conversion
164+
if (form.redirectTo) {
165+
setTimeout(() => {
166+
goto(form.redirectTo);
167+
}, 1500); // Wait 1.5 seconds to show the success message before redirecting
168+
}
158169
} else if (form?.status === 'error') {
159170
toastMessage = form.message || 'An error occurred.';
160171
toastType = 'error';
161172
showToast = true;
162173
isConverting = false;
163174
isSubmittingComment = false;
175+
} else {
176+
// Reset loading states if no form response
177+
isConverting = false;
178+
isSubmittingComment = false;
164179
}
165180
</script>
166181

src/routes/(app)/app/leads/new/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@
581581
type="tel"
582582
bind:value={formData.phone}
583583
oninput={handleChange}
584-
on:blur={validatePhone}
584+
onblur={validatePhone}
585585
placeholder="+1 (555) 123-4567"
586586
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 rounded-lg focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors {errors.phone || phoneError ? 'border-red-500 dark:border-red-400 ring-1 ring-red-500 dark:ring-red-400' : ''}" />
587587
{#if errors.phone}

0 commit comments

Comments
 (0)