MED-88: add doctor email notifications (#65)
* MED-88: add doctor email notifications * add logging, send open jobs notification on partial analysis response * update permissions * fix import, permissions * casing, let email be null * unused import
This commit is contained in:
@@ -1,7 +1,20 @@
|
||||
import { SupabaseClient } from '@supabase/supabase-js';
|
||||
|
||||
import {
|
||||
renderAllResultsReceivedEmail,
|
||||
renderFirstResultsReceivedEmail,
|
||||
} from '@kit/email-templates';
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
import {
|
||||
getAssignedDoctorAccount,
|
||||
getDoctorAccounts,
|
||||
} from '../../../../../lib/services/account.service';
|
||||
import {
|
||||
NotificationAction,
|
||||
createNotificationLog,
|
||||
} from '../../../../../lib/services/audit/notificationEntries.service';
|
||||
import { sendEmailFromTemplate } from '../../../../../lib/services/mailer.service';
|
||||
import { RecordChange, Tables } from '../record-change.type';
|
||||
|
||||
export function createDatabaseWebhookRouterService(
|
||||
@@ -42,6 +55,12 @@ class DatabaseWebhookRouterService {
|
||||
return this.handleAccountsWebhook(payload);
|
||||
}
|
||||
|
||||
case 'analysis_orders': {
|
||||
const payload = body as RecordChange<typeof body.table>;
|
||||
|
||||
return this.handleAnalysisOrdersWebhook(payload);
|
||||
}
|
||||
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
@@ -83,4 +102,69 @@ class DatabaseWebhookRouterService {
|
||||
return service.handleAccountDeletedWebhook(body.old_record);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleAnalysisOrdersWebhook(
|
||||
body: RecordChange<'analysis_orders'>,
|
||||
) {
|
||||
if (body.type === 'UPDATE' && body.record && body.old_record) {
|
||||
const { record, old_record } = body;
|
||||
|
||||
if (record.status === old_record.status) {
|
||||
return;
|
||||
}
|
||||
|
||||
let action;
|
||||
try {
|
||||
const data = {
|
||||
analysisOrderId: record.id,
|
||||
language: 'et',
|
||||
};
|
||||
|
||||
if (record.status === 'PARTIAL_ANALYSIS_RESPONSE') {
|
||||
action = NotificationAction.NEW_JOBS_ALERT;
|
||||
|
||||
const doctorAccounts = await getDoctorAccounts();
|
||||
const doctorEmails: string[] = doctorAccounts
|
||||
.map(({ email }) => email)
|
||||
.filter((email): email is string => !!email);
|
||||
|
||||
await sendEmailFromTemplate(
|
||||
renderFirstResultsReceivedEmail,
|
||||
data,
|
||||
doctorEmails,
|
||||
);
|
||||
} else if (record.status === 'FULL_ANALYSIS_RESPONSE') {
|
||||
action = NotificationAction.PATIENT_RESULTS_RECEIVED_ALERT;
|
||||
const doctorAccount = await getAssignedDoctorAccount(record.id);
|
||||
const assignedDoctorEmail = doctorAccount?.email;
|
||||
|
||||
if (!assignedDoctorEmail) {
|
||||
return;
|
||||
}
|
||||
|
||||
await sendEmailFromTemplate(
|
||||
renderAllResultsReceivedEmail,
|
||||
data,
|
||||
assignedDoctorEmail,
|
||||
);
|
||||
}
|
||||
|
||||
if (action) {
|
||||
await createNotificationLog({
|
||||
action,
|
||||
status: 'SUCCESS',
|
||||
relatedRecordId: record.id,
|
||||
});
|
||||
}
|
||||
} catch (e: any) {
|
||||
if (action)
|
||||
await createNotificationLog({
|
||||
action,
|
||||
status: 'FAIL',
|
||||
comment: e?.message,
|
||||
relatedRecordId: record.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import {
|
||||
Body,
|
||||
Head,
|
||||
Html,
|
||||
Preview,
|
||||
Tailwind,
|
||||
Text,
|
||||
render
|
||||
} from '@react-email/components';
|
||||
|
||||
import { BodyStyle } from '../components/body-style';
|
||||
import CommonFooter from '../components/common-footer';
|
||||
import { EmailContent } from '../components/content';
|
||||
import { EmailButton } from '../components/email-button';
|
||||
import { EmailHeader } from '../components/header';
|
||||
import { EmailHeading } from '../components/heading';
|
||||
import { EmailWrapper } from '../components/wrapper';
|
||||
import { initializeEmailI18n } from '../lib/i18n';
|
||||
|
||||
export async function renderAllResultsReceivedEmail({
|
||||
language,
|
||||
analysisOrderId,
|
||||
}: {
|
||||
language: string;
|
||||
analysisOrderId: number;
|
||||
}) {
|
||||
const namespace = 'all-results-received-email';
|
||||
|
||||
const { t } = await initializeEmailI18n({
|
||||
language,
|
||||
namespace: [namespace, 'common'],
|
||||
});
|
||||
|
||||
const previewText = t(`${namespace}:previewText`);
|
||||
|
||||
const subject = t(`${namespace}:subject`);
|
||||
|
||||
const html = await render(
|
||||
<Html>
|
||||
<Head>
|
||||
<BodyStyle />
|
||||
</Head>
|
||||
|
||||
<Preview>{previewText}</Preview>
|
||||
|
||||
<Tailwind>
|
||||
<Body>
|
||||
<EmailWrapper>
|
||||
<EmailHeader>
|
||||
<EmailHeading>{previewText}</EmailHeading>
|
||||
</EmailHeader>
|
||||
|
||||
<EmailContent>
|
||||
<Text className="text-[16px] leading-[24px] text-[#242424]">
|
||||
{t(`${namespace}:hello`)}
|
||||
</Text>
|
||||
<Text className="text-[16px] leading-[24px] font-semibold text-[#242424]">
|
||||
{t(`${namespace}:openOrdersHeading`)}
|
||||
</Text>
|
||||
<EmailButton
|
||||
href={`${process.env.NEXT_PUBLIC_SITE_URL}/doctor/analysis/${analysisOrderId}`}
|
||||
>
|
||||
{t(`${namespace}:linkText`)}
|
||||
</EmailButton>
|
||||
|
||||
<Text>
|
||||
{t(`${namespace}:ifLinksDisabled`)}{' '}
|
||||
{`${process.env.NEXT_PUBLIC_SITE_URL}/doctor/analysis/${analysisOrderId}`}
|
||||
</Text>
|
||||
<CommonFooter t={t} />
|
||||
</EmailContent>
|
||||
</EmailWrapper>
|
||||
</Body>
|
||||
</Tailwind>
|
||||
</Html>,
|
||||
);
|
||||
|
||||
return {
|
||||
html,
|
||||
subject,
|
||||
};
|
||||
}
|
||||
@@ -19,14 +19,12 @@ import { initializeEmailI18n } from '../lib/i18n';
|
||||
|
||||
export async function renderDoctorSummaryReceivedEmail({
|
||||
language,
|
||||
recipientEmail,
|
||||
recipientName,
|
||||
orderNr,
|
||||
orderId,
|
||||
}: {
|
||||
language?: string;
|
||||
recipientName: string;
|
||||
recipientEmail: string;
|
||||
orderNr: string;
|
||||
orderId: number;
|
||||
}) {
|
||||
@@ -37,8 +35,6 @@ export async function renderDoctorSummaryReceivedEmail({
|
||||
namespace: [namespace, 'common'],
|
||||
});
|
||||
|
||||
const to = recipientEmail;
|
||||
|
||||
const previewText = t(`${namespace}:previewText`, {
|
||||
orderNr,
|
||||
});
|
||||
@@ -92,6 +88,5 @@ export async function renderDoctorSummaryReceivedEmail({
|
||||
return {
|
||||
html,
|
||||
subject,
|
||||
to,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import {
|
||||
Body,
|
||||
Head,
|
||||
Html,
|
||||
Preview,
|
||||
Tailwind,
|
||||
Text,
|
||||
render,
|
||||
} from '@react-email/components';
|
||||
|
||||
import { BodyStyle } from '../components/body-style';
|
||||
import CommonFooter from '../components/common-footer';
|
||||
import { EmailContent } from '../components/content';
|
||||
import { EmailButton } from '../components/email-button';
|
||||
import { EmailHeader } from '../components/header';
|
||||
import { EmailHeading } from '../components/heading';
|
||||
import { EmailWrapper } from '../components/wrapper';
|
||||
import { initializeEmailI18n } from '../lib/i18n';
|
||||
|
||||
export async function renderFirstResultsReceivedEmail({
|
||||
language,
|
||||
analysisOrderId,
|
||||
}: {
|
||||
language: string;
|
||||
analysisOrderId: number;
|
||||
}) {
|
||||
const namespace = 'first-results-received-email';
|
||||
|
||||
const { t } = await initializeEmailI18n({
|
||||
language,
|
||||
namespace: [namespace, 'common'],
|
||||
});
|
||||
|
||||
const previewText = t(`${namespace}:previewText`);
|
||||
|
||||
const subject = t(`${namespace}:subject`);
|
||||
|
||||
const html = await render(
|
||||
<Html>
|
||||
<Head>
|
||||
<BodyStyle />
|
||||
</Head>
|
||||
|
||||
<Preview>{previewText}</Preview>
|
||||
|
||||
<Tailwind>
|
||||
<Body>
|
||||
<EmailWrapper>
|
||||
<EmailHeader>
|
||||
<EmailHeading>{previewText}</EmailHeading>
|
||||
</EmailHeader>
|
||||
|
||||
<EmailContent>
|
||||
<Text className="text-[16px] leading-[24px] text-[#242424]">
|
||||
{t(`${namespace}:hello`)}
|
||||
</Text>
|
||||
<Text className="text-[16px] leading-[24px] text-[#242424]">
|
||||
{t(`${namespace}:resultsReceivedForOrders`)}
|
||||
</Text>
|
||||
<Text className="text-[16px] leading-[24px] font-semibold text-[#242424]">
|
||||
{t(`${namespace}:openOrdersHeading`)}
|
||||
</Text>
|
||||
|
||||
<EmailButton
|
||||
href={`${process.env.NEXT_PUBLIC_SITE_URL}/doctor/analysis/${analysisOrderId}`}
|
||||
>
|
||||
{t(`${namespace}:linkText`)}
|
||||
</EmailButton>
|
||||
|
||||
<Text>
|
||||
{t(`${namespace}:ifLinksDisabled`)}{' '}
|
||||
{`${process.env.NEXT_PUBLIC_SITE_URL}/doctor/analysis/${analysisOrderId}`}
|
||||
</Text>
|
||||
<CommonFooter t={t} />
|
||||
</EmailContent>
|
||||
</EmailWrapper>
|
||||
</Body>
|
||||
</Tailwind>
|
||||
</Html>,
|
||||
);
|
||||
|
||||
return {
|
||||
html,
|
||||
subject,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import {
|
||||
Body,
|
||||
Head,
|
||||
Html,
|
||||
Link,
|
||||
Preview,
|
||||
Tailwind,
|
||||
Text,
|
||||
render
|
||||
} from '@react-email/components';
|
||||
|
||||
import { BodyStyle } from '../components/body-style';
|
||||
import CommonFooter from '../components/common-footer';
|
||||
import { EmailContent } from '../components/content';
|
||||
import { EmailHeader } from '../components/header';
|
||||
import { EmailHeading } from '../components/heading';
|
||||
import { EmailWrapper } from '../components/wrapper';
|
||||
import { initializeEmailI18n } from '../lib/i18n';
|
||||
|
||||
export async function renderNewJobsAvailableEmail({
|
||||
language,
|
||||
analysisResponseIds,
|
||||
}: {
|
||||
language?: string;
|
||||
analysisResponseIds: number[];
|
||||
}) {
|
||||
const namespace = 'new-jobs-available-email';
|
||||
|
||||
const { t } = await initializeEmailI18n({
|
||||
language,
|
||||
namespace: [namespace, 'common'],
|
||||
});
|
||||
|
||||
const previewText = t(`${namespace}:previewText`, {
|
||||
nr: analysisResponseIds.length,
|
||||
});
|
||||
|
||||
const subject = t(`${namespace}:subject`, {
|
||||
nr: analysisResponseIds.length,
|
||||
});
|
||||
|
||||
const html = await render(
|
||||
<Html>
|
||||
<Head>
|
||||
<BodyStyle />
|
||||
</Head>
|
||||
|
||||
<Preview>{previewText}</Preview>
|
||||
|
||||
<Tailwind>
|
||||
<Body>
|
||||
<EmailWrapper>
|
||||
<EmailHeader>
|
||||
<EmailHeading>{previewText}</EmailHeading>
|
||||
</EmailHeader>
|
||||
|
||||
<EmailContent>
|
||||
<Text className="text-[16px] leading-[24px] text-[#242424]">
|
||||
{t(`${namespace}:hello`)}
|
||||
</Text>
|
||||
<Text className="text-[16px] leading-[24px] text-[#242424]">
|
||||
{t(`${namespace}:resultsReceivedForOrders`, {
|
||||
nr: analysisResponseIds.length,
|
||||
})}
|
||||
</Text>
|
||||
<Text className="text-[16px] leading-[24px] font-semibold text-[#242424]">
|
||||
{t(`${namespace}:openOrdersHeading`, {
|
||||
nr: analysisResponseIds.length,
|
||||
})}
|
||||
</Text>
|
||||
<ul className="list-none text-[16px] leading-[24px]">
|
||||
{analysisResponseIds.map((analysisResponseId, index) => (
|
||||
<li>
|
||||
<Link
|
||||
key={analysisResponseId}
|
||||
href={`${process.env.NEXT_PUBLIC_SITE_URL}/doctor/analysis/${analysisResponseId}`}
|
||||
>
|
||||
{t(`${namespace}:linkText`, { nr: index + 1 })}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Text>
|
||||
{t(`${namespace}:ifLinksDisabled`)}{' '}
|
||||
{`${process.env.NEXT_PUBLIC_SITE_URL}/doctor/open-jobs`}
|
||||
</Text>
|
||||
<CommonFooter t={t} />
|
||||
</EmailContent>
|
||||
</EmailWrapper>
|
||||
</Body>
|
||||
</Tailwind>
|
||||
</Html>,
|
||||
);
|
||||
|
||||
return {
|
||||
html,
|
||||
subject,
|
||||
};
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export async function renderOtpEmail(props: Props) {
|
||||
|
||||
<Section className="mb-[16px] mt-[16px] text-center">
|
||||
<Button className={'w-full rounded bg-neutral-950 text-center'}>
|
||||
<Text className="text-[16px] font-medium font-semibold leading-[16px] text-white">
|
||||
<Text className="text-[16px] font-semibold leading-[16px] text-white">
|
||||
{props.otp}
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
@@ -9,12 +9,12 @@ import {
|
||||
} from '@react-email/components';
|
||||
|
||||
import { BodyStyle } from '../components/body-style';
|
||||
import CommonFooter from '../components/common-footer';
|
||||
import { EmailContent } from '../components/content';
|
||||
import { EmailHeader } from '../components/header';
|
||||
import { EmailHeading } from '../components/heading';
|
||||
import { EmailWrapper } from '../components/wrapper';
|
||||
import { initializeEmailI18n } from '../lib/i18n';
|
||||
import CommonFooter from '../components/common-footer';
|
||||
|
||||
interface Props {
|
||||
analysisPackageName: string;
|
||||
@@ -31,7 +31,10 @@ export async function renderSynlabAnalysisPackageEmail(props: Props) {
|
||||
namespace: [namespace, 'common'],
|
||||
});
|
||||
|
||||
const previewText = t(`${namespace}:previewText`);
|
||||
const previewText = t(`${namespace}:previewText`, {
|
||||
analysisPackageName: props.analysisPackageName,
|
||||
});
|
||||
|
||||
const subject = t(`${namespace}:subject`, {
|
||||
analysisPackageName: props.analysisPackageName,
|
||||
});
|
||||
|
||||
@@ -4,3 +4,6 @@ export * from './emails/otp.email';
|
||||
export * from './emails/company-offer.email';
|
||||
export * from './emails/synlab.email';
|
||||
export * from './emails/doctor-summary-received.email';
|
||||
export * from './emails/new-jobs-available.email';
|
||||
export * from './emails/first-results-received.email';
|
||||
export * from './emails/all-results-received.email';
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"previewText": "All analysis results have been received",
|
||||
"subject": "All patient analysis results have been received",
|
||||
"openOrdersHeading": "Review the results and prepare a summary:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"previewText": "First analysis responses received",
|
||||
"subject": "New job - first analysis responses received",
|
||||
"resultsReceivedForOrders": "New job available to claim",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"previewText": "New jobs available",
|
||||
"subject": "Please write a summary",
|
||||
"resultsReceivedForOrders": "Please review the results and write a summary.",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "Open job {{nr}}",
|
||||
"ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"previewText": "Kõik analüüside vastused on saabunud",
|
||||
"subject": "Patsiendi kõikide analüüside vastused on saabunud",
|
||||
"openOrdersHeading": "Vaata tulemusi ja kirjuta kokkuvõte:",
|
||||
"linkText": "Vaata tulemusi",
|
||||
"ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"previewText": "Saabusid esimesed analüüside vastused",
|
||||
"subject": "Uus töö - saabusid esimesed analüüside vastused",
|
||||
"resultsReceivedForOrders": "Patsiendile saabusid esimesed analüüside vastused.",
|
||||
"openOrdersHeading": "Vaata siit:",
|
||||
"linkText": "Vaata tulemusi",
|
||||
"ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"previewText": "Palun koosta kokkuvõte",
|
||||
"subject": "Palun koosta kokkuvõte",
|
||||
"resultsReceivedForOrders": "Palun vaata tulemused üle ja kirjuta kokkuvõte.",
|
||||
"openOrdersHeading": "Vaata siit:",
|
||||
"linkText": "Töö {{nr}}",
|
||||
"ifLinksDisabled": "Kui lingid ei tööta, näed vabasid töid sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"previewText": "All analysis results have been received",
|
||||
"subject": "All patient analysis results have been received",
|
||||
"openOrdersHeading": "Review the results and prepare a summary:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"previewText": "First analysis responses received",
|
||||
"subject": "New job - first analysis responses received",
|
||||
"resultsReceivedForOrders": "New job available to claim",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"previewText": "New jobs available",
|
||||
"subject": "Please write a summary",
|
||||
"resultsReceivedForOrders": "Please review the results and write a summary.",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "Open job {{nr}}",
|
||||
"ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
@@ -41,6 +41,7 @@ export const PatientSchema = z.object({
|
||||
email: z.string().nullable(),
|
||||
height: z.number().optional().nullable(),
|
||||
weight: z.number().optional().nullable(),
|
||||
preferred_locale: z.string().nullable(),
|
||||
});
|
||||
export type Patient = z.infer<typeof PatientSchema>;
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ export const AccountSchema = z.object({
|
||||
last_name: z.string().nullable(),
|
||||
id: z.string(),
|
||||
primary_owner_user_id: z.string(),
|
||||
preferred_locale: z.string().nullable(),
|
||||
});
|
||||
export type Account = z.infer<typeof AccountSchema>;
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@ import 'server-only';
|
||||
|
||||
import { isBefore } from 'date-fns';
|
||||
|
||||
import { renderDoctorSummaryReceivedEmail } from '@kit/email-templates';
|
||||
import { getFullName } from '@kit/shared/utils';
|
||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
|
||||
import { sendDoctorSummaryCompletedEmail } from '../../../../../../../lib/services/mailer.service';
|
||||
import { sendEmailFromTemplate } from '../../../../../../../lib/services/mailer.service';
|
||||
import { AnalysisResultDetails } from '../schema/doctor-analysis-detail-view.schema';
|
||||
import {
|
||||
AnalysisResponseBase,
|
||||
@@ -54,7 +55,7 @@ async function enrichAnalysisData(analysisResponses?: AnalysisResponseBase[]) {
|
||||
supabase
|
||||
.schema('medreport')
|
||||
.from('accounts')
|
||||
.select('name, last_name, id, primary_owner_user_id')
|
||||
.select('name, last_name, id, primary_owner_user_id, preferred_locale')
|
||||
.in('primary_owner_user_id', userIds),
|
||||
]);
|
||||
|
||||
@@ -67,7 +68,7 @@ async function enrichAnalysisData(analysisResponses?: AnalysisResponseBase[]) {
|
||||
? await supabase
|
||||
.schema('medreport')
|
||||
.from('accounts')
|
||||
.select('name, last_name, id, primary_owner_user_id')
|
||||
.select('name, last_name, id, primary_owner_user_id, preferred_locale')
|
||||
.in('primary_owner_user_id', doctorUserIds)
|
||||
: { data: [] };
|
||||
|
||||
@@ -408,7 +409,7 @@ export async function getAnalysisResultsForDoctor(
|
||||
.schema('medreport')
|
||||
.from('accounts')
|
||||
.select(
|
||||
`primary_owner_user_id, id, name, last_name, personal_code, phone, email,
|
||||
`primary_owner_user_id, id, name, last_name, personal_code, phone, email, preferred_locale,
|
||||
account_params(height,weight)`,
|
||||
)
|
||||
.eq('is_personal_account', true)
|
||||
@@ -472,6 +473,7 @@ export async function getAnalysisResultsForDoctor(
|
||||
personal_code,
|
||||
phone,
|
||||
account_params,
|
||||
preferred_locale,
|
||||
} = accountWithParams[0];
|
||||
|
||||
const analysisResponseElementsWithPreviousData = [];
|
||||
@@ -503,6 +505,7 @@ export async function getAnalysisResultsForDoctor(
|
||||
},
|
||||
doctorFeedback: doctorFeedback?.[0],
|
||||
patient: {
|
||||
preferred_locale,
|
||||
userId: primary_owner_user_id,
|
||||
accountId,
|
||||
firstName: name,
|
||||
@@ -638,7 +641,7 @@ export async function submitFeedback(
|
||||
}
|
||||
|
||||
if (status === 'COMPLETED') {
|
||||
const [{ data: recipient }, { data: medusaOrderIds }] = await Promise.all([
|
||||
const [{ data: recipient }, { data: analysisOrder }] = await Promise.all([
|
||||
supabase
|
||||
.schema('medreport')
|
||||
.from('accounts')
|
||||
@@ -659,18 +662,21 @@ export async function submitFeedback(
|
||||
throw new Error('Could not find user email.');
|
||||
}
|
||||
|
||||
if (!medusaOrderIds?.[0]?.id) {
|
||||
if (!analysisOrder?.[0]?.id) {
|
||||
throw new Error('Could not retrieve order.');
|
||||
}
|
||||
|
||||
const { preferred_locale, name, last_name, email } = recipient[0];
|
||||
|
||||
await sendDoctorSummaryCompletedEmail(
|
||||
preferred_locale ?? 'et',
|
||||
getFullName(name, last_name),
|
||||
await sendEmailFromTemplate(
|
||||
renderDoctorSummaryReceivedEmail,
|
||||
{
|
||||
language: preferred_locale ?? 'et',
|
||||
recipientName: getFullName(name, last_name),
|
||||
orderNr: analysisOrder?.[0]?.medusa_order_id ?? '',
|
||||
orderId: analysisOrder[0].id,
|
||||
},
|
||||
email,
|
||||
medusaOrderIds?.[0]?.medusa_order_id ?? '',
|
||||
medusaOrderIds[0].id,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './use-csrf-token';
|
||||
export * from './use-current-locale-language-names';
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function useLanguageName(currentLanguage: string) {
|
||||
return useMemo(() => {
|
||||
return new Intl.DisplayNames([currentLanguage], {
|
||||
type: 'language',
|
||||
});
|
||||
}, [currentLanguage]);
|
||||
}
|
||||
|
||||
export function useCurrentLocaleLanguageNames() {
|
||||
const { i18n } = useTranslation();
|
||||
const { language: currentLanguage } = i18n;
|
||||
return useLanguageName(currentLanguage);
|
||||
}
|
||||
Reference in New Issue
Block a user