diff --git a/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.html b/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.html index aed5701f6..6f0e42cf2 100644 --- a/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.html +++ b/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.html @@ -88,7 +88,9 @@
- + + @if (form().get('organization')?.errors?.['required'] && form().get('organization')?.touched) { +

Organization name is required

+ } + @if (form().get('organization_url')?.errors?.['required'] && form().get('organization_url')?.touched) { +

Organization website is required

+ } + @if (form().get('organization_url')?.errors?.['pattern'] && form().get('organization_url')?.touched) { +

Please enter a valid URL

+ }
diff --git a/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts b/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts index 3688156b2..3deb7b992 100644 --- a/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts +++ b/apps/lfx-one/src/app/modules/committees/components/member-form/member-form.component.ts @@ -9,7 +9,7 @@ import { CalendarComponent } from '@components/calendar/calendar.component'; import { InputTextComponent } from '@components/input-text/input-text.component'; import { OrganizationSearchComponent } from '@components/organization-search/organization-search.component'; import { SelectComponent } from '@components/select/select.component'; -import { APPOINTED_BY_OPTIONS, LINKEDIN_PROFILE_PATTERN, MEMBER_ROLES, VOTING_STATUSES } from '@lfx-one/shared/constants'; +import { APPOINTED_BY_OPTIONS, LINKEDIN_PROFILE_PATTERN, MEMBER_ROLES, VOTING_STATUSES, WEBSITE_URL_PATTERN } from '@lfx-one/shared/constants'; import { Committee, CommitteeMember, CreateCommitteeMemberRequest, MemberFormValue } from '@lfx-one/shared/interfaces'; import { formatDateToISOString, parseISODateString } from '@lfx-one/shared/utils'; import { CommitteeService } from '@services/committee.service'; @@ -43,6 +43,11 @@ export class MemberFormComponent { // Wizard mode: returns data instead of calling API (used when committee doesn't exist yet) public readonly wizardMode: boolean; + // Organization fields are required when voting is enabled OR business email is required + public get orgRequired(): boolean { + return !!(this.committee?.enable_voting || this.committee?.business_email_required); + } + // Member options public roleOptions = MEMBER_ROLES; public votingStatusOptions = VOTING_STATUSES; @@ -205,8 +210,8 @@ export class MemberFormComponent { email: new FormControl('', [Validators.required, Validators.email]), job_title: new FormControl(''), linkedin_profile: new FormControl('', [Validators.pattern(LINKEDIN_PROFILE_PATTERN)]), - organization: new FormControl(''), - organization_url: new FormControl(''), + organization: new FormControl('', this.orgRequired ? [Validators.required] : []), + organization_url: new FormControl('', this.orgRequired ? [Validators.required, Validators.pattern(WEBSITE_URL_PATTERN)] : [Validators.pattern(WEBSITE_URL_PATTERN)]), role: new FormControl('', this.committee?.enable_voting ? [Validators.required] : []), voting_status: new FormControl('', this.committee?.enable_voting ? [Validators.required] : []), appointed_by: new FormControl(''), diff --git a/packages/shared/src/constants/validation.constants.ts b/packages/shared/src/constants/validation.constants.ts index fd1743ec5..8da96649c 100644 --- a/packages/shared/src/constants/validation.constants.ts +++ b/packages/shared/src/constants/validation.constants.ts @@ -27,3 +27,6 @@ * - linkedin.com (missing path) */ export const LINKEDIN_PROFILE_PATTERN = /^(https?:\/\/)?([a-z]{2,3}\.)?linkedin\.com\/.*$/; + +/** Website URL pattern matching the upstream backend validation */ +export const WEBSITE_URL_PATTERN = /^(https?:\/\/)?[^\s/$.?#].[^\s]*$/;