Fix: Use correct API endpoint for test email

This commit is contained in:
Tola Leng
2025-06-17 21:39:00 +08:00
parent 08b00728c2
commit 575869c50a
@@ -1,4 +1,3 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -7,8 +6,9 @@ import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useLanguage } from "@/contexts/LanguageContext"; import { useLanguage } from "@/contexts/LanguageContext";
import { Mail, X } from "lucide-react"; import { Mail, X, AlertCircle, CheckCircle, Loader2 } from "lucide-react";
import { toast } from "@/hooks/use-toast"; import { toast } from "@/hooks/use-toast";
import { Alert, AlertDescription } from "@/components/ui/alert";
interface TestEmailDialogProps { interface TestEmailDialogProps {
open: boolean; open: boolean;
@@ -33,9 +33,16 @@ const TestEmailDialog: React.FC<TestEmailDialogProps> = ({
const [email, setEmail] = useState(''); const [email, setEmail] = useState('');
const [template, setTemplate] = useState('verification'); const [template, setTemplate] = useState('verification');
const [collection, setCollection] = useState('_superusers'); const [collection, setCollection] = useState('_superusers');
const [lastResult, setLastResult] = useState<{ success: boolean; message: string } | null>(null);
const [isInternalTesting, setIsInternalTesting] = useState(false);
const validateEmail = (email: string): boolean => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const handleSend = async () => { const handleSend = async () => {
if (!email) { if (!email.trim()) {
toast({ toast({
title: "Error", title: "Error",
description: "Please enter an email address", description: "Please enter an email address",
@@ -44,39 +51,73 @@ const TestEmailDialog: React.FC<TestEmailDialogProps> = ({
return; return;
} }
if (!validateEmail(email)) {
toast({
title: "Error",
description: "Please enter a valid email address",
variant: "destructive",
});
return;
}
try { try {
setLastResult(null);
setIsInternalTesting(true);
console.log('Sending test email with data:', {
email,
template,
collection: template === 'verification' || template === 'password-reset' ? collection : undefined
});
await onSendTest({ await onSendTest({
email, email,
template, template,
collection: template === 'verification' ? collection : undefined collection: template === 'verification' || template === 'password-reset' ? collection : undefined
});
setLastResult({
success: true,
message: `Test email sent successfully to ${email}`
}); });
toast({ toast({
title: "Success", title: "Success",
description: "Test email sent successfully", description: `Test email sent successfully to ${email}`,
variant: "default", variant: "default",
}); });
// Close dialog on success
handleClose();
} catch (error) { } catch (error) {
console.error('Error sending test email:', error); console.error('Error sending test email:', error);
const errorMessage = error instanceof Error ? error.message : "Failed to send test email";
setLastResult({
success: false,
message: errorMessage
});
toast({ toast({
title: "Error", title: "Error",
description: "Failed to send test email", description: errorMessage,
variant: "destructive", variant: "destructive",
}); });
} finally {
setIsInternalTesting(false);
} }
}; };
const handleClose = () => { const handleClose = () => {
onOpenChange(false); onOpenChange(false);
// Reset form // Reset form but keep last result for reference
setEmail(''); setEmail('');
setTemplate('verification'); setTemplate('verification');
setCollection('_superusers'); setCollection('_superusers');
// Don't reset lastResult immediately to allow user to see the result
setTimeout(() => setLastResult(null), 300);
}; };
const isLoading = isTesting || isInternalTesting;
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md"> <DialogContent className="sm:max-w-md">
@@ -90,16 +131,31 @@ const TestEmailDialog: React.FC<TestEmailDialogProps> = ({
size="icon" size="icon"
className="absolute right-4 top-4" className="absolute right-4 top-4"
onClick={handleClose} onClick={handleClose}
disabled={isLoading}
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</Button> </Button>
</DialogHeader> </DialogHeader>
<div className="space-y-4 py-4"> <div className="space-y-4 py-4">
{/* Show last result */}
{lastResult && (
<Alert variant={lastResult.success ? "default" : "destructive"}>
{lastResult.success ? (
<CheckCircle className="h-4 w-4" />
) : (
<AlertCircle className="h-4 w-4" />
)}
<AlertDescription>
{lastResult.message}
</AlertDescription>
</Alert>
)}
{/* Template Selection */} {/* Template Selection */}
<div className="space-y-3"> <div className="space-y-3">
<Label>{t("emailTemplate", "settings")}</Label> <Label>{t("emailTemplate", "settings")}</Label>
<RadioGroup value={template} onValueChange={setTemplate}> <RadioGroup value={template} onValueChange={setTemplate} disabled={isLoading}>
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
<RadioGroupItem value="verification" id="verification" /> <RadioGroupItem value="verification" id="verification" />
<Label htmlFor="verification">{t("verification", "settings")}</Label> <Label htmlFor="verification">{t("verification", "settings")}</Label>
@@ -112,22 +168,14 @@ const TestEmailDialog: React.FC<TestEmailDialogProps> = ({
<RadioGroupItem value="email-change" id="email-change" /> <RadioGroupItem value="email-change" id="email-change" />
<Label htmlFor="email-change">{t("confirmEmailChange", "settings")}</Label> <Label htmlFor="email-change">{t("confirmEmailChange", "settings")}</Label>
</div> </div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="otp" id="otp" />
<Label htmlFor="otp">{t("otp", "settings")}</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="login-alert" id="login-alert" />
<Label htmlFor="login-alert">{t("loginAlert", "settings")}</Label>
</div>
</RadioGroup> </RadioGroup>
</div> </div>
{/* Auth Collection - only show for verification template */} {/* Auth Collection - show for verification and password-reset templates */}
{template === 'verification' && ( {(template === 'verification' || template === 'password-reset') && (
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("authCollection", "settings")} *</Label> <Label>{t("authCollection", "settings")} *</Label>
<Select value={collection} onValueChange={setCollection}> <Select value={collection} onValueChange={setCollection} disabled={isLoading}>
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder={t("selectCollection", "settings")} /> <SelectValue placeholder={t("selectCollection", "settings")} />
</SelectTrigger> </SelectTrigger>
@@ -148,21 +196,34 @@ const TestEmailDialog: React.FC<TestEmailDialogProps> = ({
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
placeholder={t("enterEmailAddress", "settings")} placeholder={t("enterEmailAddress", "settings")}
required required
disabled={isLoading}
/> />
</div> </div>
{/* Info message */}
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription>
This will send a test email using your configured SMTP settings. Make sure SMTP is properly configured first.
</AlertDescription>
</Alert>
</div> </div>
<DialogFooter className="flex justify-between"> <DialogFooter className="flex justify-between">
<Button variant="outline" onClick={handleClose}> <Button variant="outline" onClick={handleClose} disabled={isLoading}>
{t("close", "common")} {t("close", "common")}
</Button> </Button>
<Button <Button
onClick={handleSend} onClick={handleSend}
disabled={!email || isTesting} disabled={!email || isLoading}
className="flex items-center gap-2" className="flex items-center gap-2"
> >
{isLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Mail className="h-4 w-4" /> <Mail className="h-4 w-4" />
{isTesting ? t("sending", "settings") : t("send", "common")} )}
{isLoading ? t("sending", "settings") : t("send", "common")}
</Button> </Button>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>