Allow skipping confirmation email when adding mailing list subscribers

When creating a new subscriber, operators can now check "Skip confirmation email" if they already have the recipient's consent. This creates the subscriber in confirmed status and skips sending the notification email.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2026-03-19 22:12:08 +01:00
parent bedfd61168
commit c5589793da
4 changed files with 32 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
import { useTranslate } from "@probo/i18n";
import { Button, Dialog, DialogContent, DialogFooter, type DialogRef, Field, Spinner } from "@probo/ui";
import { Button, Checkbox, Dialog, DialogContent, DialogFooter, type DialogRef, Field, Spinner } from "@probo/ui";
import { type DataID, graphql } from "relay-runtime";
import { z } from "zod";
@@ -42,10 +42,11 @@ export function NewCompliancePageSubscriberDialog(props: {
.min(1, __("Email is required"))
.trim()
.email(__("Please enter a valid email address")),
confirmed: z.boolean(),
});
const form = useFormWithSchema(schema, {
defaultValues: { fullName: "", email: "" },
defaultValues: { fullName: "", email: "", confirmed: false },
});
const [createSubscriber, isCreating] = useMutationWithToasts<NewCompliancePageSubscriberDialogMutation>(
@@ -63,6 +64,7 @@ export function NewCompliancePageSubscriberDialog(props: {
mailingListId,
fullName: data.fullName.trim(),
email: data.email.trim(),
confirmed: data.confirmed || undefined,
},
connections: connectionId ? [connectionId] : [],
},
@@ -102,6 +104,15 @@ export function NewCompliancePageSubscriberDialog(props: {
{...form.register("email")}
placeholder={__("john@example.com")}
/>
<label className="flex items-center gap-2 cursor-pointer">
<Checkbox
checked={form.watch("confirmed")}
onChange={checked => form.setValue("confirmed", checked)}
/>
<span className="text-sm">
{__("Skip confirmation email (I already have consent)")}
</span>
</label>
</DialogContent>
<DialogFooter>
<Button type="submit" disabled={isCreating}>

View File

@@ -75,6 +75,7 @@ type (
MailingListID gid.GID
Email mail.Addr
FullName string
Confirmed bool
}
)
@@ -182,11 +183,18 @@ func (s *Service) CreateSubscriber(
mailingListID := req.MailingListID
email := req.Email
fullName := req.FullName
scope := coredata.NewScopeFromObjectID(mailingListID)
emailRecord, err := s.buildConfirmationMail(ctx, mailingListID, email, fullName)
if err != nil {
return nil, fmt.Errorf("cannot build confirmation mail: %w", err)
status := coredata.MailingListSubscriberStatusPending
var emailRecord *coredata.Email
if req.Confirmed {
status = coredata.MailingListSubscriberStatusConfirmed
} else {
var err error
emailRecord, err = s.buildConfirmationMail(ctx, mailingListID, email, fullName)
if err != nil {
return nil, fmt.Errorf("cannot build confirmation mail: %w", err)
}
}
now := time.Now()
@@ -195,7 +203,7 @@ func (s *Service) CreateSubscriber(
MailingListID: mailingListID,
FullName: fullName,
Email: email,
Status: coredata.MailingListSubscriberStatusPending,
Status: status,
CreatedAt: now,
UpdatedAt: now,
}
@@ -216,8 +224,10 @@ func (s *Service) CreateSubscriber(
return fmt.Errorf("cannot insert mailing list subscriber: %w", err)
}
if err := emailRecord.Insert(ctx, tx); err != nil {
return fmt.Errorf("cannot insert subscription confirmation email: %w", err)
if emailRecord != nil {
if err := emailRecord.Insert(ctx, tx); err != nil {
return fmt.Errorf("cannot insert subscription confirmation email: %w", err)
}
}
return nil

View File

@@ -3925,6 +3925,7 @@ input CreateMailingListSubscriberInput {
mailingListId: ID!
fullName: String!
email: EmailAddr!
confirmed: Boolean
}
input DeleteMailingListSubscriberInput {

View File

@@ -2404,6 +2404,7 @@ func (r *mutationResolver) CreateMailingListSubscriber(ctx context.Context, inpu
MailingListID: input.MailingListID,
Email: input.Email,
FullName: input.FullName,
Confirmed: input.Confirmed != nil && *input.Confirmed,
},
)
if err != nil {