Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion platform/app/src/routes/Register/Register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ const RegisterPage = () => {
/>
<Input
id="register-license"
placeholder={tMembers('License No.')}
placeholder={tMembers('License No. (optional)')}
aria-label={tMembers('License No. (optional)')}
className="mb-4 w-full"
type="text"
maxLength={100}
Expand Down
19 changes: 19 additions & 0 deletions platform/app/src/routes/Register/registrationRequest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,23 @@ describe('createRegistrationRequest', () => {
expect(request.tenantId).toBe('tenant-from-session');
expect(request).not.toHaveProperty('code');
});

it('normalizes a blank license number for the public registration API', () => {
const request = createRegistrationRequest({
tenantId: 'tenant-from-session',
firstName: 'Grace',
lastName: 'Hopper',
email: 'grace@example.com',
password: 'Strong!Password',
licenseNo: ' ',
specialty: 'radiology',
turnstileToken: 'turnstile-proof',
policyAcceptances: [
{ policyKey: 'TERMS_OF_SERVICE', version: 'terms-v1' },
{ policyKey: 'PRIVACY_POLICY', version: 'privacy-v1' },
],
});

expect(request.licenseNo).toBe('');
});
});
11 changes: 11 additions & 0 deletions platform/app/src/routes/Register/registrationValidation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ describe('getRegistrationValidationMessage', () => {
expect(getRegistrationValidationMessage(validRegistration)).toBeNull();
});

it('accepts an omitted public-registration license number', () => {
expect(getRegistrationValidationMessage({ ...validRegistration, licenseNo: '' })).toBeNull();
expect(getRegistrationValidationMessage({ ...validRegistration, licenseNo: ' ' })).toBeNull();
});

it('rejects invalid email and mismatched passwords clearly', () => {
expect(getRegistrationValidationMessage({ ...validRegistration, email: 'not-an-email' })).toBe(
'Please enter a valid email address.'
Expand Down Expand Up @@ -81,6 +86,12 @@ describe('getRegistrationValidationMessage', () => {
lastName: 'y',
})
).toBe('First and last name together must be 100 characters or fewer.');
expect(
getRegistrationValidationMessage({
...validRegistration,
licenseNo: 'x'.repeat(101),
})
).toBe('License number must be 100 characters or fewer.');
expect(
getRegistrationValidationMessage({
...validRegistration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export const getRegistrationValidationMessage = ({
!email.trim() ||
!firstName.trim() ||
!lastName.trim() ||
!licenseNo.trim() ||
!specialty.trim() ||
!password ||
!confirmPassword
Expand Down
18 changes: 13 additions & 5 deletions platform/app/src/routes/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import tenantRepository from '../../api/tenantRepository';
import { logoutUser } from '../../service/userService';
import { resetTutorialAndNotify } from '../../service/tutorialService';
import { FrontendVersionContext } from '../../App';
import { getProfileCredentialDetails } from './profileCredentialDetails';

const SettingsPage = () => {
const { t } = useTranslation('Settings');
Expand Down Expand Up @@ -214,6 +215,11 @@ const SettingsPage = () => {
};

const GeneralSettings = () => {
const profileCredentials = getProfileCredentialDetails(
currentUser.specialty,
currentUser.licenseNo
);

return (
<div className="rounded-xl border border-white border-opacity-10 bg-white bg-opacity-[5%] p-5">
<div className="">
Expand All @@ -230,11 +236,13 @@ const SettingsPage = () => {
<div className="ml-3">
<h1 className="text-lg font-normal text-white">{currentUser.name}</h1>
<div className="-mt-1 flex flex-col text-sm font-light text-white text-opacity-70 sm:flex-row sm:items-center">
<div className="text-left capitalize">{currentUser.specialty} •</div>
<div className="flex items-center sm:ml-1">
{currentUser.licenseNo}
<CopyToClipboardButton text={currentUser.licenseNo} />
</div>
<div className="text-left capitalize">{profileCredentials.specialtyLabel}</div>
{profileCredentials.licenseNo && (
<div className="flex items-center sm:ml-1">
{profileCredentials.licenseNo}
<CopyToClipboardButton text={profileCredentials.licenseNo} />
</div>
)}
</div>
</div>
) : (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getProfileCredentialDetails } from './profileCredentialDetails';

describe('getProfileCredentialDetails', () => {
it('shows a normalized license number after the specialty', () => {
expect(getProfileCredentialDetails('Cardiology', ' MD-123 ')).toEqual({
specialtyLabel: 'Cardiology •',
licenseNo: 'MD-123',
});
});

it.each([undefined, null, '', ' '])(
'omits an absent license number and its separator for %p',
licenseNo => {
expect(getProfileCredentialDetails('Cardiology', licenseNo)).toEqual({
specialtyLabel: 'Cardiology',
licenseNo: null,
});
}
);
});
16 changes: 16 additions & 0 deletions platform/app/src/routes/Settings/profileCredentialDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
interface ProfileCredentialDetails {
specialtyLabel: string;
licenseNo: string | null;
}

export const getProfileCredentialDetails = (
specialty?: string,
licenseNo?: string | null
): ProfileCredentialDetails => {
const normalizedLicenseNo = licenseNo?.trim() || null;

return {
specialtyLabel: `${specialty || ''}${normalizedLicenseNo ? ' •' : ''}`,
licenseNo: normalizedLicenseNo,
};
};
1 change: 1 addition & 0 deletions platform/i18n/src/locales/ar/Members.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Invite Sent": "تم إرسال الدعوة",
"Last Name": "الاسم الأخير",
"License No.": "رقم الترخيص",
"License No. (optional)": "رقم الترخيص (اختياري)",
"Name": "الاسم",
"Next": "التالي",
"No Data Found": "لم يتم العثور على بيانات",
Expand Down
1 change: 1 addition & 0 deletions platform/i18n/src/locales/de/Members.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Invite Sent": "Einladung gesendet",
"Last Name": "Nachname",
"License No.": "Lizenznummer",
"License No. (optional)": "Lizenznummer (optional)",
"Name": "Name",
"Next": "Weiter",
"No Data Found": "Keine Daten gefunden",
Expand Down
1 change: 1 addition & 0 deletions platform/i18n/src/locales/en-US/Members.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Invite Sent": "Invite Sent",
"Last Name": "Last Name",
"License No.": "License No.",
"License No. (optional)": "License No. (optional)",
"Name": "Name",
"Next": "Next",
"No Data Found": "No Data Found",
Expand Down
1 change: 1 addition & 0 deletions platform/i18n/src/locales/es/Members.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Invite Sent": "Invitación enviada",
"Last Name": "Apellido",
"License No.": "Número de Licencia",
"License No. (optional)": "Número de Licencia (opcional)",
"Name": "Nombre",
"Next": "Siguiente",
"No Data Found": "No se Encontraron Datos",
Expand Down
1 change: 1 addition & 0 deletions platform/i18n/src/locales/fr/Members.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"Invite Sent": "Invitation envoyée",
"Last Name": "Nom",
"License No.": "Numéro de licence",
"License No. (optional)": "Numéro de licence (facultatif)",
"Name": "Nom",
"No Data Found": "Aucune donnée trouvée",
"No invitations yet": "Aucune invitation pour le moment.",
Expand Down
Loading