|
1 | 1 | import * as Popover from '@radix-ui/react-popover'; |
2 | | -import { useId, useRef, useState } from 'react'; |
| 2 | +import { useId, useState } from 'react'; |
3 | 3 | import { toast } from 'sonner'; |
| 4 | +import { sendTestEmail } from '../actions/send-test-email'; |
4 | 5 | import { Button } from './button'; |
5 | 6 | import { Text } from './text'; |
6 | 7 |
|
7 | | -const useTimer = (startingSeconds: number, onStop?: () => void) => { |
8 | | - const [isActive, setIsActive] = useState(false); |
9 | | - const [secondsRemaining, setSecondsRemaining] = useState(startingSeconds); |
10 | | - |
11 | | - const interval = useRef<NodeJS.Timeout | undefined>(undefined); |
12 | | - |
13 | | - return { |
14 | | - isActive, |
15 | | - secondsRemaining, |
16 | | - start: () => { |
17 | | - setIsActive(true); |
18 | | - setSecondsRemaining(startingSeconds); |
19 | | - clearInterval(interval.current); |
20 | | - |
21 | | - let secondsRemainingTemp = startingSeconds; |
22 | | - interval.current = setInterval(() => { |
23 | | - setSecondsRemaining((v) => v - 1); |
24 | | - secondsRemainingTemp -= 1; |
25 | | - |
26 | | - if (secondsRemainingTemp <= 0) { |
27 | | - clearInterval(interval.current); |
28 | | - setIsActive(false); |
29 | | - setSecondsRemaining(startingSeconds); |
30 | | - onStop?.(); |
31 | | - } |
32 | | - }, 1_000); |
33 | | - }, |
34 | | - }; |
35 | | -}; |
36 | | - |
37 | 8 | export const Send = ({ markup }: { markup: string }) => { |
38 | 9 | const [to, setTo] = useState(''); |
39 | 10 | const [subject, setSubject] = useState('Testing React Email'); |
40 | 11 | const [isSending, setIsSending] = useState(false); |
41 | 12 | const [isPopOverOpen, setIsPopOverOpen] = useState(false); |
42 | 13 |
|
43 | | - const [isRateLimited, setIsRateLimited] = useState(false); |
44 | | - const rateLimiter = useTimer(60, () => { |
45 | | - setIsRateLimited(false); |
46 | | - }); |
47 | | - |
48 | 14 | const onFormSubmit = async (e: React.FormEvent) => { |
49 | 15 | e.preventDefault(); |
50 | 16 | setIsSending(true); |
51 | 17 |
|
52 | | - try { |
53 | | - const response = await fetch('https://react.email/api/send/test', { |
54 | | - method: 'POST', |
55 | | - headers: { 'Content-Type': 'application/json' }, |
56 | | - body: JSON.stringify({ |
57 | | - to, |
58 | | - subject, |
59 | | - html: markup, |
60 | | - }), |
61 | | - }); |
| 18 | + const response = await sendTestEmail(to, subject, markup); |
62 | 19 |
|
63 | | - if (!rateLimiter.isActive) { |
64 | | - rateLimiter.start(); |
65 | | - } |
66 | | - |
67 | | - if (response.ok) { |
68 | | - toast.success('Email sent! Check your inbox.'); |
69 | | - } else if (response.status === 429) { |
70 | | - toast.error('Too many requests.'); |
71 | | - rateLimiter.start(); |
72 | | - setIsRateLimited(true); |
73 | | - } else { |
74 | | - toast.error('Something went wrong. Please try again.'); |
75 | | - } |
76 | | - } catch { |
| 20 | + if (response.ok) { |
| 21 | + toast.success('Email sent! Check your inbox.'); |
| 22 | + } else if (response.status === 429) { |
| 23 | + toast.error('Too many requests. Try again in around 1 minute'); |
| 24 | + } else { |
77 | 25 | toast.error('Something went wrong. Please try again.'); |
78 | 26 | } |
| 27 | + |
79 | 28 | setIsSending(false); |
80 | 29 | }; |
81 | 30 |
|
@@ -151,29 +100,29 @@ export const Send = ({ markup }: { markup: string }) => { |
151 | 100 | type="checkbox" |
152 | 101 | /> |
153 | 102 | <div className="mt-3 flex items-center justify-between"> |
154 | | - <Text className="inline-block" size="1"> |
155 | | - Powered by{' '} |
156 | | - <a |
157 | | - className="text-white/85 transition duration-300 ease-in-out hover:text-slate-12" |
158 | | - href="https://go.resend.com/react-email" |
159 | | - rel="noreferrer" |
160 | | - target="_blank" |
161 | | - > |
162 | | - Resend |
163 | | - </a> |
164 | | - </Text> |
| 103 | + <div className="flex flex-col inline-block"> |
| 104 | + <Text size="1"> |
| 105 | + Powered by{' '} |
| 106 | + <a |
| 107 | + className="text-white/85 transition duration-300 ease-in-out hover:text-slate-12" |
| 108 | + href="https://go.resend.com/react-email" |
| 109 | + rel="noreferrer" |
| 110 | + target="_blank" |
| 111 | + > |
| 112 | + Resend |
| 113 | + </a> |
| 114 | + </Text> |
| 115 | + </div> |
165 | 116 | <Button |
166 | 117 | className="disabled:border-transparent disabled:bg-slate-11" |
167 | 118 | disabled={ |
168 | 119 | subject.length === 0 || |
169 | 120 | to.length === 0 || |
170 | | - isSending || |
171 | | - isRateLimited |
| 121 | + isSending |
172 | 122 | } |
173 | 123 | type="submit" |
174 | 124 | > |
175 | 125 | Send |
176 | | - {isRateLimited ? ` ${rateLimiter.secondsRemaining}s` : null} |
177 | 126 | </Button> |
178 | 127 | </div> |
179 | 128 | </form> |
|
0 commit comments