feat: complete i18n support, telegram webhook, and security improvements
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import { useState, useRef, useCallback } from "react";
|
||||
import type { MailMessage } from "@/app/[lang]/dashboard/mail/page";
|
||||
import { formatBytes } from "@/lib/format";
|
||||
import { useDictionary } from "@/components/DictionaryContext";
|
||||
|
||||
interface AttachmentFile {
|
||||
file: File;
|
||||
@@ -14,6 +15,7 @@ export default function ComposeModal({ replyTo, onClose, onSent }: {
|
||||
onClose: () => void;
|
||||
onSent: () => void;
|
||||
}) {
|
||||
const dict = useDictionary();
|
||||
const [to, setTo] = useState(replyTo ? replyTo.from[0]?.address ?? "" : "");
|
||||
const [cc, setCc] = useState("");
|
||||
const [subject, setSubject] = useState(replyTo ? `Re: ${replyTo.subject.replace(/^Re:\s*/i, "")}` : "");
|
||||
@@ -60,7 +62,7 @@ export default function ComposeModal({ replyTo, onClose, onSent }: {
|
||||
|
||||
const res = await fetch("/api/mail/send", { method: "POST", body: formData });
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || "Gönderilemedi");
|
||||
if (!res.ok) throw new Error(data.error || dict.mailClient.sendError || "Gönderilemedi");
|
||||
} else {
|
||||
// JSON for simple messages
|
||||
const res = await fetch("/api/mail/send", {
|
||||
@@ -72,7 +74,7 @@ export default function ComposeModal({ replyTo, onClose, onSent }: {
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || "Gönderilemedi");
|
||||
if (!res.ok) throw new Error(data.error || dict.mailClient.sendError || "Gönderilemedi");
|
||||
}
|
||||
onSent();
|
||||
} catch (err: any) {
|
||||
@@ -87,24 +89,24 @@ export default function ComposeModal({ replyTo, onClose, onSent }: {
|
||||
<div className="modal-overlay" onClick={(e) => e.target === e.currentTarget && onClose()}>
|
||||
<div className="modal" style={{ maxWidth: 620 }}>
|
||||
<div className="modal-header">
|
||||
<h2 className="modal-title">{replyTo ? "Yanıtla" : "Yeni Mail"}</h2>
|
||||
<h2 className="modal-title">{replyTo ? (dict.mailClient.reply || "Yanıtla") : (dict.mailClient.composeTitle || "Yeni Mail")}</h2>
|
||||
<button className="modal-close" onClick={onClose}>✕</button>
|
||||
</div>
|
||||
<form onSubmit={handleSend}>
|
||||
<div className="modal-body form-group">
|
||||
{error && <div className="error-msg">{error}</div>}
|
||||
<div>
|
||||
<label className="label">Alıcı</label>
|
||||
<label className="label">{dict.mailClient.to || "Alıcı"}</label>
|
||||
<input type="email" className="input" placeholder="alici@domain.com" value={to}
|
||||
onChange={(e) => setTo(e.target.value)} required autoFocus />
|
||||
</div>
|
||||
<div>
|
||||
<label className="label">CC (isteğe bağlı)</label>
|
||||
<label className="label">{dict.mailClient.cc || "CC"}</label>
|
||||
<input type="text" className="input" placeholder="cc@domain.com" value={cc}
|
||||
onChange={(e) => setCc(e.target.value)} />
|
||||
</div>
|
||||
<div>
|
||||
<label className="label">Konu</label>
|
||||
<label className="label">{dict.mailClient.subject || "Konu"}</label>
|
||||
<input type="text" className="input" value={subject}
|
||||
onChange={(e) => setSubject(e.target.value)} required />
|
||||
</div>
|
||||
@@ -131,7 +133,7 @@ export default function ComposeModal({ replyTo, onClose, onSent }: {
|
||||
onChange={(e) => { addFiles(e.target.files); e.target.value = ""; }}
|
||||
/>
|
||||
<span style={{ fontSize: 20 }}>📎</span>
|
||||
<span>Dosya sürükleyin veya tıklayın</span>
|
||||
<span>{dict.mailClient.dropFiles || "Dosya sürükleyin veya tıklayın"}</span>
|
||||
</div>
|
||||
|
||||
{/* Attachment list */}
|
||||
@@ -145,15 +147,15 @@ export default function ComposeModal({ replyTo, onClose, onSent }: {
|
||||
</div>
|
||||
))}
|
||||
<div style={{ fontSize: 11, color: "var(--text-muted)", marginTop: 4 }}>
|
||||
Toplam: {formatBytes(totalSize)} — {attachments.length} dosya
|
||||
{formatBytes(totalSize)} — {attachments.length} {dict.mailClient.attachments || "dosya"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-ghost" onClick={onClose}>İptal</button>
|
||||
<button type="button" className="btn btn-ghost" onClick={onClose}>{dict.mailClient.cancel || "İptal"}</button>
|
||||
<button type="submit" className="btn btn-primary" disabled={sending}>
|
||||
{sending ? <span className="spinner" /> : <SendIcon />} Gönder
|
||||
{sending ? <span className="spinner" /> : <SendIcon />} {dict.mailClient.send || "Gönder"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user