Skip to content

Commit 964ade3

Browse files
committed
feat: complete email service
1 parent 62e46b9 commit 964ade3

File tree

6 files changed

+63
-146
lines changed

6 files changed

+63
-146
lines changed

apps/api/src/routers/payment.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { router, protectedProcedure } from "../trpc.js";
22
import { z } from "zod";
33
import { TRPCError } from "@trpc/server";
44
import { paymentService } from "../services/payment.service.js";
5+
import { emailService } from "../services/email.service.js";
6+
import prismaModule from "../prisma.js";
7+
8+
const { prisma } = prismaModule;
59

610
const createOrderSchema = z.object({
711
planId: z.string().min(1, "Plan ID is required"),
@@ -162,6 +166,34 @@ export const paymentRouter = router({
162166
payment.id
163167
);
164168

169+
// Step 4: Fetch user details and send premium subscription email
170+
try {
171+
const user = await prisma.user.findUnique({
172+
where: { id: userId },
173+
select: { email: true, firstName: true },
174+
});
175+
176+
if (user && user.email && user.firstName) {
177+
// Send premium subscription confirmation email
178+
await emailService.sendPremiumSubscriptionEmail(
179+
user.email,
180+
user.firstName
181+
);
182+
} else {
183+
// Log warning but don't fail the payment verification
184+
console.warn(
185+
`Unable to send premium subscription email: User ${userId} not found or missing email/firstName`
186+
);
187+
}
188+
} catch (emailError) {
189+
// Log error but don't fail the payment verification
190+
// Payment and subscription are already successful
191+
console.error(
192+
"Error sending premium subscription email:",
193+
emailError
194+
);
195+
}
196+
165197
return {
166198
success: true,
167199
message: "Payment verified and subscription activated",

apps/api/src/services/email.service.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,6 @@ export const emailService = {
103103
Let's have a chat over a meeting so that I can understand where you are currently and how I can help you move ahead.
104104
</p>
105105
106-
<p style="color: #333; line-height: 1.8; font-size: 16px;">
107-
Soon, I'll add you to the private Slack so that we can talk regularly.
108-
</p>
109-
110106
<p style="color: #333; line-height: 1.8; font-size: 16px;">
111107
Again, thank you :)
112108
</p>
@@ -143,8 +139,6 @@ To get started, please book your slot in the cal meet.
143139
144140
Let's have a chat over a meeting so that I can understand where you are currently and how I can help you move ahead.
145141
146-
Soon, I'll add you to the private Slack so that we can talk regularly.
147-
148142
Again, thank you :)
149143
150144
Cal: https://cal.com/ajeetunc/secret

apps/api/types/zeptomail.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
declare module "zeptomail" {
2+
export class SendMailClient {
3+
constructor(config: { url: string; token: string });
4+
sendMail(options: {
5+
from: { address: string; name: string };
6+
to: Array<{ email_address: { address: string; name: string } }>;
7+
subject: string;
8+
htmlbody: string;
9+
textbody?: string;
10+
}): Promise<any>;
11+
}
12+
}
13+

apps/web/src/components/payment/PaymentFlow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ const PaymentFlow: React.FC<PaymentFlowProps> = ({
147147

148148
await initiatePayment(options);
149149
} catch (error) {
150-
console.error("Failed to create order:", error);
151-
alert("Failed to initiate payment. Please try again.");
150+
console.warn("Failed to create order:", error);
151+
router.push("/login?callbackUrl=/pricing");
152152
setIsProcessing(false);
153153
}
154154
};

apps/web/src/providers/trpc-provider.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
44
import { httpBatchLink } from "@trpc/client";
5-
import { useState } from "react";
5+
import { useState, useMemo } from "react";
66
import { useSession } from "next-auth/react";
77
import { trpc } from "@/lib/trpc";
88

99
export function TRPCProvider({ children }: { children: React.ReactNode }) {
10-
const session = useSession();
10+
const { data: session, status } = useSession();
1111
const [queryClient] = useState(
1212
() =>
1313
new QueryClient({
@@ -19,7 +19,8 @@ export function TRPCProvider({ children }: { children: React.ReactNode }) {
1919
})
2020
);
2121

22-
const [trpcClient] = useState(() => {
22+
// Recreate client when session status changes to ensure we get the latest token
23+
const trpcClient = useMemo(() => {
2324
const baseUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000";
2425
const trpcUrl = baseUrl.endsWith("/trpc") ? baseUrl : `${baseUrl}/trpc`;
2526

@@ -28,7 +29,7 @@ export function TRPCProvider({ children }: { children: React.ReactNode }) {
2829
httpBatchLink({
2930
url: trpcUrl,
3031
async headers() {
31-
const token = (session.data as any)?.accessToken;
32+
const token = (session as any)?.accessToken;
3233
if (token) {
3334
return {
3435
authorization: `Bearer ${token}`,
@@ -39,7 +40,7 @@ export function TRPCProvider({ children }: { children: React.ReactNode }) {
3940
}),
4041
],
4142
});
42-
});
43+
}, [status, session]);
4344

4445
return (
4546
<trpc.Provider client={trpcClient} queryClient={queryClient}>

0 commit comments

Comments
 (0)