This commit is contained in:
Ravi Gulhane 2026-07-22 09:39:07 +05:30
commit 569ba6e97c
3 changed files with 60 additions and 28 deletions

View File

@ -183,11 +183,18 @@ export function FormSubmissionsPanel({ formId, formName, onClose }: Props) {
setReplying(true);
setReplyMessage(null);
try {
await formsApi.replyToSubmission(formId, { to, subject: replySubject, body: replyBody });
// Extend payload with submissionId; backend uses it to persist replied status.
await (formsApi as any).replyToSubmission(formId, {
submissionId: replyTarget._id,
to,
subject: replySubject,
body: replyBody,
});
setReplyMessage("Email sent successfully.");
setReplyTarget(null);
setReplySubject("");
setReplyBody("");
await fetchPage();
} catch (e) {
setReplyMessage(e instanceof Error ? e.message : "Failed to send reply.");
} finally {
@ -488,31 +495,40 @@ export function FormSubmissionsPanel({ formId, formName, onClose }: Props) {
<tbody>
{rows.map((s) => {
const o = dataToObj(s.data);
const hasEmail = participantEmail(s.participant) !== "—";
const isReplied = !!s.replied;
return (
<tr key={s._id} style={{ borderBottom: "1px solid var(--border)", verticalAlign: "top" }}>
<tr
key={s._id}
style={{
borderBottom: "1px solid var(--border)",
verticalAlign: "top",
background: isReplied ? "rgba(16, 185, 129, 0.08)" : undefined,
}}
>
<td style={{ padding: "10px 12px" }}>
<button
type="button"
onClick={() => openReply(s)}
style={{
display: "inline-flex",
alignItems: "center",
gap: 6,
padding: "6px 10px",
borderRadius: "var(--radius-button)",
onClick={() => hasEmail && !isReplied && openReply(s)}
disabled={!hasEmail || isReplied}
title={isReplied ? "Already replied" : !hasEmail ? "No email available" : "Reply"}
style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "6px 10px", borderRadius: "var(--radius-button)",
border: "1px solid var(--border)",
background: "var(--secondary)",
color: "var(--foreground)",
cursor: "pointer",
background: isReplied ? "rgba(16, 185, 129, 0.15)" : hasEmail ? "var(--secondary)" : "var(--background)",
color: isReplied ? "var(--foreground)" : hasEmail ? "var(--foreground)" : "var(--muted)",
cursor: !hasEmail || isReplied ? "not-allowed" : "pointer",
opacity: !hasEmail ? 0.5 : 1,
fontSize: "var(--text-xs)",
fontFamily: "var(--font-noto-sans)",
fontWeight: 600,
}}
>
<MailPlus size={14} />
Reply
{isReplied ? "Replied" : "Reply"}
</button>
</td>
<td style={{ padding: "10px 12px", whiteSpace: "nowrap", color: "var(--foreground)" }}>
{formatWhen(s.submittedAt)}
</td>

View File

@ -217,7 +217,7 @@ export function ParticipantBulkDialogs({
}}
style={{ padding: "7px 14px", borderRadius: "var(--radius-button)", border: "none", background: "var(--primary)", color: "var(--primary-foreground)", cursor: "pointer", fontSize: "var(--text-sm)" }}
>
Apply
{bulkDialog === "removeTags" ? "Remove" : "Apply"}
</button>
)}
</>

View File

@ -668,8 +668,24 @@ export interface FormSubmissionRecord {
form?: string;
submittedAt: string;
data?: Record<string, unknown>;
participant?: { _id?: string; firstName?: string; lastName?: string; email?: string } | string;
participant?: {
_id?: string;
firstName?: string;
lastName?: string;
email?: string;
} | string;
status?: string;
replied?: boolean;
repliedAt?: string;
repliedBy?:
| string
| {
_id?: string;
firstName?: string;
lastName?: string;
email?: string;
};
}
export interface SpeakerLogistics {