feat(course): auto-enrol button for paid course join requests (#769)

* feat(course): add auto-enrol flow for paid course join requests

- Extend teacher buy-request email with manual access steps and an
  Auto Enrol this Student button
- Link teachers to the course People page with grantAccess query param
- Add grant-access modal that sends the same org audience invite used
  by the Invite new students flow

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(i18n): translate grant access modal strings

Replace English placeholders copied into non-en locale files with
proper translations for each supported language.

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(email): shorten auto-enrol button label per review

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(email): use American spelling Enroll in auto-enroll CTA

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

* fix(i18n): localize Danish grant-access send invite label

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>

---------

Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>
This commit is contained in:
Rotimi Best
2026-07-19 12:02:11 +01:00
committed by GitHub
co-authored by Rotimi Best
parent 634ffeab0f
commit 6c3a982daf
14 changed files with 180 additions and 0 deletions
@@ -5,6 +5,7 @@ import { getCourseWithOrgData } from '@cio/db/queries/course';
import { buildEmailFromName, buildEmailBranding } from '@cio/email';
import { enqueueTransactionalEmail } from '@api/services/jobs';
import { trackServerEvent, SERVER_EVENTS } from '@cio/analytics';
import { getDashboardBaseUrl } from '@cio/core/config/dashboard-url';
export interface PaymentRequestData {
courseId: string;
@@ -47,6 +48,15 @@ export async function createPaymentRequest(data: PaymentRequestData) {
const teacherEmail = teacherResult[0].email;
const dashboardOrg = {
siteName: course.orgSiteName,
customDomain: course.orgCustomDomain,
isCustomDomainVerified: course.orgIsCustomDomainVerified
};
const dashboardBaseUrl = getDashboardBaseUrl(dashboardOrg);
const courseUrl = `${dashboardBaseUrl}/courses/${data.courseId}`;
const autoEnrollUrl = `${dashboardBaseUrl}/courses/${data.courseId}/people?grantAccess=${encodeURIComponent(data.studentEmail)}`;
try {
await enqueueTransactionalEmail('teacherStudentBuyRequest', {
to: teacherEmail,
@@ -54,6 +64,8 @@ export async function createPaymentRequest(data: PaymentRequestData) {
courseName,
studentEmail: data.studentEmail,
studentFullname: data.studentFullname,
courseUrl,
autoEnrollUrl,
branding
},
from: buildEmailFromName('ClassroomIO'),