diff --git a/example/src/ReviewContractorOnboardingStep.tsx b/example/src/ReviewContractorOnboardingStep.tsx index 73ed107e..e8d8390a 100644 --- a/example/src/ReviewContractorOnboardingStep.tsx +++ b/example/src/ReviewContractorOnboardingStep.tsx @@ -1,5 +1,6 @@ import { ContractorOnboardingRenderProps, + corProductIdentifier, NormalizedFieldError, useMagicLink, } from '@remoteoss/remote-flows'; @@ -80,6 +81,29 @@ export const ReviewContractorOnboardingStep = ({ > Edit Basic Information +

Pricing plan

+ + + {onboardingBag.stepState.values?.pricing_plan?.subscription === + corProductIdentifier && ( + <> +

Eligibility Questionnaire

+ + + + )}

Contract Details

-

Pricing plan

- - - - {invitedStatus === 'not_invited' && ( - - )} + {invitedStatus === 'not_invited' && + typeof onboardingBag.employment?.basic_information?.name === + 'string' && ( + + )} {invitedStatus === 'invited' && (
diff --git a/src/client/sdk.gen.ts b/src/client/sdk.gen.ts index 845aa1aa..0cdc8a94 100644 --- a/src/client/sdk.gen.ts +++ b/src/client/sdk.gen.ts @@ -2569,8 +2569,9 @@ export const postCancelEmployeeTimeoff = ( * * ``` * - * This endpoint requires a company access token, as forms are dependent on certain - * properties of companies and their current employments. + * Most forms require a company access token, as they are dependent on certain + * properties of companies and their current employments. However, the `address_details` + * form can be accessed using client_credentials authentication (without a company). * * */ @@ -2585,6 +2586,7 @@ export const getShowFormCountry = ( security: [ { scheme: 'bearer', type: 'http' }, { scheme: 'bearer', type: 'http' }, + { scheme: 'bearer', type: 'http' }, ], url: '/v1/countries/{country_code}/{form}', ...options, diff --git a/src/client/types.gen.ts b/src/client/types.gen.ts index e50da160..8ce73948 100644 --- a/src/client/types.gen.ts +++ b/src/client/types.gen.ts @@ -3820,6 +3820,7 @@ export type MinimalEmployment = { work_address_details: { [key: string]: unknown; }; + work_email: string | null; }; /** @@ -8914,6 +8915,10 @@ export type GetShowContractorContractDetailsCountryData = { country_code: string; }; query?: { + /** + * Employment ID + */ + employment_id?: string; /** * Version of the form schema */ diff --git a/src/common/api/fixtures/contractors-subscriptions.ts b/src/common/api/fixtures/contractors-subscriptions.ts index 1366eda5..41252638 100644 --- a/src/common/api/fixtures/contractors-subscriptions.ts +++ b/src/common/api/fixtures/contractors-subscriptions.ts @@ -57,7 +57,6 @@ export const mockContractorSubscriptionResponse = { ], }; -export const mockManageSubscriptionResponse = mockBaseResponse; export const mockContractorSubscriptionWithEligibilityResponse = { data: [ { @@ -123,3 +122,5 @@ export const mockContractorSubscriptionWithEligibilityResponse = { }, ], }; + +export const mockManageSubscriptionResponse = mockBaseResponse; diff --git a/src/flows/ContractorOnboarding/api.ts b/src/flows/ContractorOnboarding/api.ts index 31607ede..37f44157 100644 --- a/src/flows/ContractorOnboarding/api.ts +++ b/src/flows/ContractorOnboarding/api.ts @@ -231,17 +231,23 @@ export const useCreateContractorContractDocument = () => { */ export const useContractorOnboardingDetailsSchema = ({ countryCode, + employmentId, fieldValues, options, }: { countryCode: string; fieldValues: FieldValues; + employmentId: string; options?: FlowOptions & { queryOptions?: { enabled?: boolean } }; query?: Record; }): UseQueryResult => { const { client } = useClient(); return useQuery({ - queryKey: ['contractor-onboarding-details-schema', countryCode], + queryKey: [ + 'contractor-onboarding-details-schema', + countryCode, + employmentId, + ], retry: false, queryFn: async () => { return getShowContractorContractDetailsCountry({ @@ -249,6 +255,7 @@ export const useContractorOnboardingDetailsSchema = ({ path: { country_code: countryCode }, query: { json_schema_version: 1, + employment_id: employmentId, }, }); }, diff --git a/src/flows/ContractorOnboarding/hooks.tsx b/src/flows/ContractorOnboarding/hooks.tsx index fd6bd552..71ac096d 100644 --- a/src/flows/ContractorOnboarding/hooks.tsx +++ b/src/flows/ContractorOnboarding/hooks.tsx @@ -32,6 +32,8 @@ import { ContractorOnboardingFlowProps } from '@/src/flows/ContractorOnboarding/ import { buildSteps, calculateProvisionalStartDateDescription, + reviewStepAllowedEmploymentStatus, + disabledInviteButtonEmploymentStatus, StepKeys, } from '@/src/flows/ContractorOnboarding/utils'; import { @@ -40,10 +42,6 @@ import { useJSONSchemaForm, useUpdateEmployment, } from '@/src/flows/Onboarding/api'; -import { - disabledInviteButtonEmploymentStatus, - reviewStepAllowedEmploymentStatus, -} from '@/src/flows/Onboarding/utils'; import { FlowOptions, JSFModify, JSONSchemaFormType } from '@/src/flows/types'; import { useStepState } from '@/src/flows/useStepState'; import { mutationToPromise } from '@/src/lib/mutations'; @@ -445,17 +443,33 @@ export const useContractorOnboarding = ({ fieldValues, ]); - const { data: eligibilityQuestionnaireForm } = useGetEligibilityQuestionnaire( - { - options: { - queryOptions: { - enabled: selectedPricingPlan === corProductIdentifier, - }, - jsfModify: options?.jsfModify?.eligibility_questionnaire, + const isEligibilityQuestionnaireEnabled = useMemo(() => { + return ( + (selectedPricingPlan === corProductIdentifier && + stepState.currentStep.name === 'eligibility_questionnaire') || + (Boolean(employmentId) && + isEmploymentReadOnly && + selectedPricingPlan === corProductIdentifier) + ); + }, [ + selectedPricingPlan, + stepState.currentStep.name, + employmentId, + isEmploymentReadOnly, + ]); + + const { + data: eligibilityQuestionnaireForm, + isLoading: isLoadingEligibilityQuestionnaire, + } = useGetEligibilityQuestionnaire({ + options: { + queryOptions: { + enabled: isEligibilityQuestionnaireEnabled, }, - fieldValues: eligibilityFields, + jsfModify: options?.jsfModify?.eligibility_questionnaire, }, - ); + fieldValues: eligibilityFields, + }); const { data: contractorOnboardingDetailsForm, @@ -463,6 +477,7 @@ export const useContractorOnboarding = ({ } = useContractorOnboardingDetailsSchema({ countryCode: internalCountryCode as string, fieldValues: fieldValues, + employmentId: internalEmploymentId as string, options: { queryOptions: { enabled: isContractorOnboardingDetailsEnabled, @@ -677,7 +692,8 @@ export const useContractorOnboarding = ({ isLoadingContractorSubscriptions || isLoadingDocumentPreviewForm || isLoadingIR35File || - isLoadingContractDocuments; + isLoadingContractDocuments || + isLoadingEligibilityQuestionnaire; const isNavigatingToReview = useMemo(() => { return Boolean( @@ -720,7 +736,6 @@ export const useContractorOnboarding = ({ pricingPlanInitialValues, stepFields.pricing_plan, ), - // TODO: we have to check if this works well or not eligibility_questionnaire: prettifyFormValues( eligibilityQuestionnaireInitialValues, stepFields.eligibility_questionnaire, @@ -731,11 +746,9 @@ export const useContractorOnboarding = ({ select_country: selectCountryInitialValues, basic_information: basicInformationInitialValues, contract_details: contractDetailsInitialValues, - // TODO: we need to retrieve the contract preview data somehow from the BE, who signed the document - contract_preview: {}, + contract_preview: contractPreviewInitialValues, pricing_plan: pricingPlanInitialValues, - // TODO: we need to retrieve information somehow only for COR though - eligibility_questionnaire: {}, + eligibility_questionnaire: eligibilityQuestionnaireInitialValues, review: {}, }); goToStep('review'); diff --git a/src/flows/ContractorOnboarding/utils.ts b/src/flows/ContractorOnboarding/utils.ts index 13f41023..0d052b62 100644 --- a/src/flows/ContractorOnboarding/utils.ts +++ b/src/flows/ContractorOnboarding/utils.ts @@ -3,6 +3,7 @@ import { contractorStandardProductIdentifier, contractorPlusProductIdentifier, } from '@/src/flows/ContractorOnboarding/constants'; +import { Employment } from '@/src/flows/Onboarding/types'; export type StepKeys = | 'select_country' @@ -111,3 +112,17 @@ export const isCMOrCMPlus = (subscription: string | undefined): boolean => { subscription === contractorPlusProductIdentifier ); }; + +/** + * Array of employment statuses that are allowed to proceed to the review step. + * These statuses indicate that the employment is in a final state and the employment cannot be modified further. + * @type {Employment['status'][]} + * @constant + */ +export const reviewStepAllowedEmploymentStatus: Employment['status'][] = [ + 'invited', +]; + +export const disabledInviteButtonEmploymentStatus: Employment['status'][] = [ + 'invited', +];