Skip to content

Commit eac213c

Browse files
committed
Merge branch 'main' of github.com:efdevcon/monorepo
2 parents 7a75450 + 6de90c0 commit eac213c

17 files changed

Lines changed: 3384 additions & 1641 deletions

File tree

devcon-api/src/controllers/account.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { decryptFile } from '@/utils/encrypt'
1111
import { parseCSV } from '@/utils/files'
1212
import { ValidateTicketPod } from '@/utils/zupass'
1313
import { GenerateRandomUsername, GetEnsAddress, GetEnsAvatar, GetEnsName } from '@/utils/account'
14+
import { apikeyHandler } from '@/middleware/apikey'
1415
import dayjs from 'dayjs'
1516

1617
const client = new PrismaClient()
@@ -32,6 +33,7 @@ accountRouter.get(`/account/speakers`, FollowedSpeakers)
3233
accountRouter.get(`/account/speakers/recommended`, RecommendedSpeakers)
3334
accountRouter.get(`/account/sessions`, FollowedSessions)
3435
accountRouter.get(`/account/sessions/recommended`, RecommendedSessions)
36+
accountRouter.post(`/account/accreditation/email`, apikeyHandler, SendAccreditationEmail)
3537

3638
async function GetAccount(req: Request, res: Response) {
3739
// #swagger.tags = ['Account']
@@ -725,6 +727,48 @@ async function RecommendedSessions(req: Request, res: Response) {
725727
return res.status(200).send({ code: 200, message: '', data: sessions })
726728
}
727729

730+
async function SendAccreditationEmail(req: Request, res: Response) {
731+
// #swagger.tags = ['Account']
732+
// Private route: requires apiKey
733+
// #swagger.ignore = true
734+
735+
const { email, name, insuranceLink } = req.body
736+
737+
if (!email || !name || !insuranceLink) {
738+
return res.status(400).send({
739+
code: 400,
740+
message: 'Missing required fields: email, name, insuranceLink'
741+
})
742+
}
743+
744+
try {
745+
// Import the email service
746+
const { sendAccreditationConfirmationEmail } = await import('@/services/email')
747+
748+
// Send the accreditation confirmation email
749+
const success = await sendAccreditationConfirmationEmail(email, name, insuranceLink)
750+
751+
if (success) {
752+
return res.status(200).send({
753+
code: 200,
754+
message: 'Accreditation confirmation email sent successfully',
755+
data: { email, name, insuranceLink }
756+
})
757+
} else {
758+
return res.status(500).send({
759+
code: 500,
760+
message: 'Failed to send accreditation email'
761+
})
762+
}
763+
} catch (error) {
764+
console.error('Error in SendAccreditationEmail:', error)
765+
return res.status(500).send({
766+
code: 500,
767+
message: 'Internal server error'
768+
})
769+
}
770+
}
771+
728772
async function parseProfileData(attendeeEmail: string) {
729773
const normalizedEmail = attendeeEmail.toLowerCase()
730774

devcon-api/src/services/email-templates.json

Lines changed: 28 additions & 5 deletions
Large diffs are not rendered by default.

devcon-api/src/services/email.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import nodemailer from 'nodemailer'
22
import { SERVER_CONFIG } from '@/utils/config'
33
import emailTemplates from './email-templates.json'
44

5-
type EmailTemplates = 'default-email' | 'email-cta'
5+
type EmailTemplates = 'default-email' | 'email-cta' | 'accreditation-confirmation'
66

77
const transporter = nodemailer.createTransport({
88
host: SERVER_CONFIG.SMTP_SERVICE,
@@ -22,6 +22,9 @@ export async function sendMail(to: string, template: EmailTemplates, subject: st
2222
if (template === 'email-cta') {
2323
text = replace(emailTemplates.ctaEmail.text.join('\n'), properties)
2424
html = replace(emailTemplates.ctaEmail.html, properties).replace(/(?:\r\n|\r|\n)/g, '<br>')
25+
} else if (template === 'accreditation-confirmation') {
26+
text = replace(emailTemplates.accreditationConfirmation.text.join('\n'), properties)
27+
html = replace(emailTemplates.accreditationConfirmation.html, properties).replace(/(?:\r\n|\r|\n)/g, '<br>')
2528
}
2629

2730
const response = await transporter.sendMail({
@@ -35,6 +38,25 @@ export async function sendMail(to: string, template: EmailTemplates, subject: st
3538
return response.accepted.length > 0
3639
}
3740

41+
// Example usage for accreditation confirmation
42+
export async function sendAccreditationConfirmationEmail(
43+
to: string,
44+
name: string,
45+
insuranceLink: string
46+
) {
47+
const properties = {
48+
Name: name,
49+
InsuranceLink: insuranceLink
50+
}
51+
52+
return sendMail(
53+
to,
54+
'accreditation-confirmation',
55+
'🎉 Your Accreditation Has Been Confirmed!',
56+
properties
57+
)
58+
}
59+
3860
function replace(template: string, data: any) {
3961
const pattern = /{%\s*(\w+?)\s*%}/g // {%property%}
4062
return template.replace(pattern, (_, token) => data[token] || '')

devconnect-app/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
"@pcd/pod": "^0.5.1",
3434
"@radix-ui/react-dialog": "^1.1.14",
3535
"@radix-ui/react-slot": "^1.2.3",
36-
"@reown/appkit": "^1.7.17",
37-
"@reown/appkit-adapter-wagmi": "^1.7.17",
36+
"@reown/appkit": "^1.8.1",
37+
"@reown/appkit-adapter-wagmi": "^1.8.1",
3838
"@solana-mobile/wallet-adapter-mobile": "^2.2.2",
3939
"@solana/wallet-adapter-base": "^0.9.27",
4040
"@solana/wallet-adapter-react": "^0.15.39",
@@ -65,7 +65,7 @@
6565
"tailwind-merge": "^3.3.1",
6666
"usehooks-ts": "^3.1.1",
6767
"viem": "^2.33.0",
68-
"wagmi": "^2.16.0",
68+
"wagmi": "^2.16.8",
6969
"zustand": "^5.0.7"
7070
},
7171
"devDependencies": {

devconnect-app/src/app/page.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,46 @@
11
'use client';
22

3+
import { useEffect, useRef } from 'react';
34
import Onboarding from '@/components/Onboarding';
45
import ConnectedWallet from '@/components/ConnectedWallet';
56
import { useUnifiedConnection } from '@/hooks/useUnifiedConnection';
67

78
export default function HomePage() {
8-
// Unified connection status
9+
// Unified connection status - trust the unified hook completely
910
const { isConnected, address, isPara } = useUnifiedConnection();
1011

11-
console.log('Is Para wallet:', isPara);
12-
console.log('Unified connection status:', {
13-
isConnected,
14-
address,
15-
isPara,
16-
});
12+
// Only log significant connection changes to avoid spam
13+
const lastLoggedState = useRef<string | null>(null);
14+
useEffect(() => {
15+
const stateKey = `${isConnected}-${address}-${isPara}`;
16+
if (stateKey !== lastLoggedState.current) {
17+
console.log('🔗 [PAGE] Connection state:', {
18+
isConnected,
19+
hasAddress: !!address,
20+
isPara,
21+
address: address ? `${address.slice(0, 6)}...${address.slice(-4)}` : undefined
22+
});
23+
lastLoggedState.current = stateKey;
24+
}
25+
}, [isConnected, address, isPara]);
1726

1827
return (
1928
<>
20-
{!isConnected ? (
21-
<div className="min-h-screen flex items-center justify-center">
29+
{!isConnected || !address ? (
30+
<div className="min-h-screen flex items-center justify-center p-4">
2231
<div className="max-w-md w-full">
23-
<div className="m-6">
24-
<Onboarding />
25-
</div>
32+
<Onboarding />
2633
</div>
2734
</div>
28-
) : (
29-
<div className="min-h-screen bg-white w-full absolute top-0 left-0">
30-
<div className="w-full flex flex-col items-center py-8 pb-20">
31-
<div className="max-w-md w-full">
32-
<ConnectedWallet address={address!} isPara={isPara} />
33-
</div>
35+
) : (
36+
<div className="min-h-screen bg-white">
37+
<div className="w-full flex flex-col items-center py-8 pb-20 px-4">
38+
<div className="max-w-md w-full">
39+
<ConnectedWallet address={address} />
3440
</div>
3541
</div>
36-
)}
42+
</div>
43+
)}
3744
</>
3845
);
3946
}
40-

0 commit comments

Comments
 (0)