[OSDEV-2203] Implemented new multi-step claim flow for production locations with routing skeleton and shared layout. #775
Conversation
React App | Jest test suite - Code coverage reportTotal: 34.62%Your code coverage diff: -0.70% ▾ ✅ All code changes are covered |
Dedupe Hub App | Unittest test suite - Code coverage reportTotal: 55.73%Your code coverage diff: 0.00% ▴ ✅ All code changes are covered |
📝 WalkthroughWalkthroughAdds a new multi-step production-location claim flow: route and route-order changes, a ClaimForm React container with four step components and stepper, a new Redux slice (actions + reducer), prefetching/hooks/validation/utils, error UI, a scroll-reset HOC, styles, tests, and release notes; session-based intro gating and routing adjustments included. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Router
participant ClaimForm as ClaimForm Component
participant Hooks as ClaimForm Hooks
participant Redux as Redux Store
participant Step as Step Component
participant Validation as Yup
User->>Router: Navigate to /claim/:osID/details
Router->>ClaimForm: Mount ClaimForm
ClaimForm->>Hooks: useRequireIntroAccess(osID)
Hooks-->>ClaimForm: allow / redirect
alt allowed
ClaimForm->>Redux: dispatch prefetch actions
Redux-->>ClaimForm: prefetch results / errors
ClaimForm->>Hooks: useClaimForm(initialValues, activeStep,...)
ClaimForm->>Step: render current step component
User->>Step: enter data
Step->>ClaimForm: handleFieldChange -> update Formik -> dispatch updateClaimFormField
User->>ClaimForm: click Next
ClaimForm->>Validation: validate current step schema
alt valid
ClaimForm->>Redux: markStepComplete, setActiveClaimFormStep(next)
ClaimForm->>Step: render next step
else invalid
Validation-->>ClaimForm: errors -> display
end
alt final submit
ClaimForm->>Redux: markStepComplete(final)
ClaimForm->>Backend: submit aggregated formData
end
else redirect
ClaimForm->>Router: navigate to intro route
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~70 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (16)
src/react/developed_by_lovable/Stepper.tsx (2)
50-66: Improve button semantics and accessibilityAdd type to prevent implicit submit; expose current step to assistive tech; optional aria-label.
- <button + <button + type="button" onClick={() => onStepClick(step.id)} className={cn( @@ >Optionally:
- <button + <button + aria-current={isCurrent ? "step" : undefined} + aria-label={step.title}
41-42: Remove or use isPastisPast is computed but unused.
- const isPast = index < currentIndex; + // const isPast = index < currentIndex;Or use it to style past steps/labels.
src/react/developed_by_lovable/ClaimsForm.tsx (3)
483-491: Read-only email: remove onChange and magic fallbackInput is readOnly; onChange won’t fire. Avoid hard-coded fallback value; rely on placeholder or inject from auth.
- <Input - id="claimant-email" - type="email" - value={formData.claimantEmail || "opensupplyhubuser@company.com"} - onChange={(e) => updateFormData("claimantEmail", e.target.value)} - placeholder="opensupplyhubuser@company.com" + <Input + id="claimant-email" + type="email" + value={formData.claimantEmail} + placeholder="opensupplyhubuser@company.com" className="text-foreground bg-muted" required readOnly />
928-935: Hard-coded OS IDBuild the link from the route param.
- <a - href="https://opensupplyhub.org/facilities/CN2021250D1DTN7" + <a + href={`https://opensupplyhub.org/facilities/${osID}`} target="_blank" rel="noopener noreferrer"
852-879: Overlay blocks interaction with visibility controlsThe decorative X covers the whole section and intercepts clicks. If intentional, mark controls disabled; otherwise, make the overlay non-interactive.
- <X className="absolute inset-0 w-full h-full text-red-600 opacity-30 p-4" strokeWidth={3} /> + <X className="absolute inset-0 w-full h-full text-red-600 opacity-30 p-4 pointer-events-none" strokeWidth={3} />Confirm desired behavior: disabled section (then set disabled/aria-disabled on controls) vs informative overlay only.
src/react/src/Routes.jsx (1)
137-141: Centralize route path and consider gating behind feature flagUse a constant in util/constants (like other routes) and/or gate under CLAIM_A_FACILITY for consistency.
Example:
-import ClaimForm from './components/ClaimForm/ClaimForm'; +import ClaimForm from './components/ClaimForm/ClaimForm'; +// import { claimFormDetailsRoute } from './util/constants'; @@ - <Route - exact - path="/claim/:osID/details/" - component={ClaimForm} - /> + {/* Consider: + <FeatureFlag flag={CLAIM_A_FACILITY} alternative={<RouteNotFound />}> + <Route exact path={claimFormDetailsRoute} component={ClaimForm} /> + </FeatureFlag> */}src/react/src/components/ClaimForm/hooks.js (1)
33-40: Consider memoizing the returned validation function.The
useStepValidationhook returns a newvalidateCurrentStepfunction on every render, which could cause unnecessary re-renders in consumer components that use this function in dependency arrays.Apply this diff to memoize the returned function:
+import { useCallback } from 'react'; + /** * Hook to validate current step before allowing navigation * @param {Object} formValues - Current form values * @param {Function} validateForm - Formik's validateForm function * @returns {Function} - Validation function that returns a promise */ export const useStepValidation = (formValues, validateForm) => { - const validateCurrentStep = async () => { + const validateCurrentStep = useCallback(async () => { const errors = await validateForm(formValues); return Object.keys(errors).length === 0; - }; + }, [formValues, validateForm]); return validateCurrentStep; };src/react/src/components/ClaimForm/Steps/ContactStep.jsx (2)
54-58: Decorative icon should be hidden from screen readersMark the People icon as decorative to avoid redundant announcement.
- <People className={classes.headerIcon} /> + <People className={classes.headerIcon} aria-hidden="true" />
117-138: Improve email field UX with autocompleteAdd autocomplete hints for better autofill and mobile keyboards.
- <TextField + <TextField fullWidth label="Your Email" type="email" + autoComplete="email"src/react/src/components/ClaimForm/validationSchemas.js (1)
12-17: Trim string inputs to reduce validation false negativesWhitespace should not cause email/URL/name mismatches. Add .trim() to relevant string fields. Optional to add .nullable() where you want empty to be treated as null.
export const contactStepSchema = Yup.object().shape({ - claimantName: Yup.string(), - claimantTitle: Yup.string(), - claimantEmail: Yup.string().email('Invalid email address'), - verificationMethod: Yup.string(), + claimantName: Yup.string().trim(), + claimantTitle: Yup.string().trim(), + claimantEmail: Yup.string().trim().email('Invalid email address'), + verificationMethod: Yup.string().trim(), }); export const businessStepSchema = Yup.object().shape({ - businessWebsite: Yup.string().url('Invalid URL'), - companyAddressVerification: Yup.string(), + businessWebsite: Yup.string().trim().url('Invalid URL'), + companyAddressVerification: Yup.string().trim(), }); export const profileStepSchema = Yup.object().shape({ - facilityName: Yup.string(), + facilityName: Yup.string().trim(), sector: Yup.array(), - facilityPhone: Yup.string(), - facilityWebsite: Yup.string().url('Invalid URL'), - localLanguageName: Yup.string(), - numberOfWorkers: Yup.string(), - femaleWorkers: Yup.string(), - minimumOrderQuantity: Yup.string(), - averageLeadTime: Yup.string(), + facilityPhone: Yup.string().trim(), + facilityWebsite: Yup.string().trim().url('Invalid URL'), + localLanguageName: Yup.string().trim(), + numberOfWorkers: Yup.string().trim(), + femaleWorkers: Yup.string().trim(), + minimumOrderQuantity: Yup.string().trim(), + averageLeadTime: Yup.string().trim(), facilityTypes: Yup.array(), - productTypes: Yup.string(), - parentCompanyName: Yup.string(), - officeName: Yup.string(), - officeAddress: Yup.string(), - officeCountry: Yup.string(), + productTypes: Yup.string().trim(), + parentCompanyName: Yup.string().trim(), + officeName: Yup.string().trim(), + officeAddress: Yup.string().trim(), + officeCountry: Yup.string().trim(), affiliations: Yup.array(), certifications: Yup.array(), - description: Yup.string(), + description: Yup.string().trim(), });Also applies to: 20-23, 26-45
src/react/src/components/ClaimForm/Stepper/utils.js (2)
1-7: Remove redundant getStepIconThis returns the input string and isn’t used by Stepper.jsx, which renders icons directly. Keeping it invites confusion.
-/** - * Get the appropriate icon component for a step - * @param {string} iconName - Name of the icon - * @returns {string} - Icon name that maps to Material-UI icon - */ -export const getStepIcon = iconName => iconName;
31-45: Avoid passing undefined class keysBuild the classes map with truthy keys only to keep DOM/class merging clean.
export const getStepLabelClasses = ( stepIndex, activeStep, completedSteps, classes, ) => { const isActive = stepIndex === activeStep; const isCompleted = completedSteps.includes(stepIndex); - return { - root: classes.stepLabel, - active: isActive ? classes.stepLabelActive : undefined, - completed: isCompleted ? classes.stepLabelCompleted : undefined, - }; + return { + root: classes.stepLabel, + ...(isActive && { active: classes.stepLabelActive }), + ...(isCompleted && { completed: classes.stepLabelCompleted }), + }; };src/react/src/components/ClaimForm/ClaimForm.jsx (1)
185-186: Make progress total dynamicAvoid hard-coding 4; derive from STEP_NAMES length to keep in sync with config.
- {completedSteps.length} of 4 sections completed + {completedSteps.length} of {STEP_NAMES.length} sections completedsrc/react/src/components/ClaimForm/Steps/BusinessStep.jsx (2)
71-91: Use URL-optimized input for websiteAdd type and autocomplete to improve validation and mobile keyboard.
- <TextField + <TextField fullWidth label="Business Website" + type="url" + autoComplete="url" value={formData.businessWebsite || ''}
54-58: Hide decorative icon from assistive techMark Language icon as decorative.
- <Language className={classes.headerIcon} /> + <Language className={classes.headerIcon} aria-hidden="true" />src/react/src/components/ClaimForm/utils.js (1)
27-38: The current implementation is sequential, but the utility function's assumption should be made explicit.The flow IS sequential in practice:
activeStepadvances strictly viagetNextStep()(returningcurrentStep + 1), andmarkComplete()is only called withactiveStepfrom the component. This meanscompletedStepswill always be[0, 1, 2, ...]in order.However, the reducer doesn't enforce this—it accepts any
stepIndexformarkStepComplete(). If the logic changes ormarkComplete()is called from elsewhere with arbitrary indices, the utility function's assumption breaks:stepIndex === completedSteps.lengthwould fail silently.Consider the suggested refactor to make the sequential requirement explicit:
- // Step immediately after last completed step is accessible - if (stepIndex === completedSteps.length) return true; + // Step is accessible if all previous steps are completed + const allPreviousComplete = Array.from({ length: stepIndex }, (_, i) => i) + .every(i => completedSteps.includes(i)); + if (allPreviousComplete) return true;This guards against future changes to the completion flow and makes the sequential requirement explicit at the utility level.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (20)
src/react/developed_by_lovable/ClaimsForm.tsx(1 hunks)src/react/developed_by_lovable/Stepper.tsx(1 hunks)src/react/src/Routes.jsx(2 hunks)src/react/src/actions/claimForm.js(1 hunks)src/react/src/components/ClaimForm/ClaimForm.jsx(1 hunks)src/react/src/components/ClaimForm/Stepper/Stepper.jsx(1 hunks)src/react/src/components/ClaimForm/Stepper/hooks.js(1 hunks)src/react/src/components/ClaimForm/Stepper/styles.js(1 hunks)src/react/src/components/ClaimForm/Stepper/utils.js(1 hunks)src/react/src/components/ClaimForm/Steps/BusinessStep.jsx(1 hunks)src/react/src/components/ClaimForm/Steps/ContactStep.jsx(1 hunks)src/react/src/components/ClaimForm/Steps/EligibilityStep.jsx(1 hunks)src/react/src/components/ClaimForm/Steps/ProfileStep.jsx(1 hunks)src/react/src/components/ClaimForm/constants.js(1 hunks)src/react/src/components/ClaimForm/hooks.js(1 hunks)src/react/src/components/ClaimForm/styles.js(1 hunks)src/react/src/components/ClaimForm/utils.js(1 hunks)src/react/src/components/ClaimForm/validationSchemas.js(1 hunks)src/react/src/reducers/ClaimFormReducer.js(1 hunks)src/react/src/reducers/index.js(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (11)
src/react/developed_by_lovable/Stepper.tsx (3)
src/react/src/components/ClaimFacilityStepper.jsx (1)
steps(123-149)src/react/src/components/ClaimForm/Stepper/utils.js (1)
isCompleted(38-38)src/react/src/reducers/ClaimFormReducer.js (1)
completedSteps(92-94)
src/react/src/reducers/ClaimFormReducer.js (1)
src/react/src/actions/claimForm.js (16)
startPrefetchClaimFormData(4-6)startPrefetchClaimFormData(4-6)completePrefetchClaimFormData(7-9)completePrefetchClaimFormData(7-9)failPrefetchClaimFormData(10-12)failPrefetchClaimFormData(10-12)setActiveClaimFormStep(15-17)setActiveClaimFormStep(15-17)markStepComplete(18-18)markStepComplete(18-18)updateClaimFormField(21-21)updateClaimFormField(21-21)setClaimFormData(22-22)setClaimFormData(22-22)resetClaimForm(23-23)resetClaimForm(23-23)
src/react/src/components/ClaimForm/Stepper/hooks.js (2)
src/react/src/components/ClaimFacilityStepper.jsx (1)
activeStep(163-163)src/react/src/reducers/ClaimFormReducer.js (1)
completedSteps(92-94)
src/react/src/components/ClaimForm/Stepper/utils.js (2)
src/react/src/components/ClaimForm/Stepper/Stepper.jsx (1)
getStepIcon(43-58)src/react/src/reducers/ClaimFormReducer.js (1)
completedSteps(92-94)
src/react/src/actions/claimForm.js (1)
src/react/src/__tests__/components/FacilityDetailsGeneralFields.test.js (1)
mockData(7-177)
src/react/src/components/ClaimForm/utils.js (3)
src/react/src/reducers/ClaimFormReducer.js (1)
completedSteps(92-94)src/react/src/components/ClaimForm/constants.js (4)
TOTAL_STEPS(47-47)TOTAL_STEPS(47-47)CLAIM_FORM_STEPS(1-6)CLAIM_FORM_STEPS(1-6)src/react/src/components/ClaimFacilityStepper.jsx (1)
activeStep(163-163)
src/react/src/Routes.jsx (1)
src/react/src/components/ClaimForm/ClaimForm.jsx (1)
ClaimForm(53-295)
src/react/src/components/ClaimForm/validationSchemas.js (1)
src/react/src/components/ClaimForm/constants.js (2)
CLAIM_FORM_STEPS(1-6)CLAIM_FORM_STEPS(1-6)
src/react/developed_by_lovable/ClaimsForm.tsx (1)
src/react/developed_by_lovable/Stepper.tsx (1)
Stepper(19-100)
src/react/src/components/ClaimForm/ClaimForm.jsx (8)
src/react/src/components/ClaimForm/constants.js (8)
CLAIM_FORM_STEPS(1-6)CLAIM_FORM_STEPS(1-6)claimIntroRoute(37-37)claimIntroRoute(37-37)STEP_NAMES(8-13)STEP_NAMES(8-13)STEP_DESCRIPTIONS(29-34)STEP_DESCRIPTIONS(29-34)src/react/src/components/ClaimForm/Steps/EligibilityStep.jsx (1)
EligibilityStep(47-93)src/react/src/components/ClaimForm/hooks.js (4)
useStepResetOnMount(8-12)useStepResetOnMount(8-12)usePrefetchData(19-25)usePrefetchData(19-25)src/react/src/components/ClaimForm/utils.js (10)
calculateProgress(8-9)calculateProgress(8-9)getNextStep(45-46)getNextStep(45-46)isFirstStep(60-61)isFirstStep(60-61)getPreviousStep(53-53)getPreviousStep(53-53)isLastStep(68-68)isLastStep(68-68)src/react/src/components/ClaimForm/Stepper/Stepper.jsx (1)
ClaimFormStepper(31-126)src/react/src/components/ClaimForm/validationSchemas.js (2)
getValidationSchemaForStep(52-61)getValidationSchemaForStep(52-61)src/react/src/actions/claimForm.js (7)
fetchClaimFormData(27-85)setActiveClaimFormStep(15-17)setActiveClaimFormStep(15-17)markStepComplete(18-18)markStepComplete(18-18)updateClaimFormField(21-21)updateClaimFormField(21-21)src/react/src/components/ClaimForm/styles.js (1)
claimFormStyles(3-127)
src/react/src/components/ClaimForm/Stepper/Stepper.jsx (3)
src/react/src/components/ClaimForm/Stepper/hooks.js (1)
useStepNavigation(10-22)src/react/src/components/ClaimForm/constants.js (8)
STEP_ICONS(40-45)STEP_ICONS(40-45)STEP_NAMES(8-13)STEP_NAMES(8-13)STEP_SUBTITLES(15-20)STEP_SUBTITLES(15-20)STEP_TIME_ESTIMATES(22-27)STEP_TIME_ESTIMATES(22-27)src/react/src/components/ClaimForm/Stepper/styles.js (1)
stepperStyles(3-104)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: run-dd-code-quality
- GitHub Check: get-base-branch-countries-cov
- GitHub Check: run-countries-code-quality
- GitHub Check: run-integration-test-code-quality
- GitHub Check: get-base-branch-dd-cov
- GitHub Check: get-base-branch-fe-cov
- GitHub Check: run-fe-code-quality
- GitHub Check: get-base-branch-django-cov
🔇 Additional comments (24)
src/react/src/components/ClaimForm/styles.js (1)
3-127: LGTM (consistent with MUI v3 and existing patterns)Styles align with current theming and freeze pattern.
src/react/src/reducers/index.js (1)
40-40: Reducer wiring verified and correctClaimFormReducer.js exists and properly exports a reducer created with
createReducerfrom redux-act (line 65). The import in index.js is correctly wired.src/react/src/reducers/ClaimFormReducer.js (3)
15-63: LGTM! Well-structured initial state.The initialState definition is comprehensive and properly structured with
Object.freezefor immutability. The deeply frozen structure works correctly withimmutability-helpersinceupdate()creates new objects rather than mutating existing ones.
91-99: LGTM! Proper duplicate prevention.The
markStepCompletehandler correctly prevents duplicate step indices in thecompletedStepsarray while maintaining immutability.
101-106: LGTM! Clean field update pattern.The
updateClaimFormFieldhandler correctly uses immutability-helper's dynamic key syntax to update individual form fields.src/react/src/components/ClaimForm/Stepper/hooks.js (1)
10-22: LGTM! Well-implemented navigation hook.The
useStepNavigationhook correctly implements step navigation with proper memoization and appropriate guard conditions (only allowing navigation to completed steps).src/react/src/components/ClaimForm/Stepper/Stepper.jsx (2)
24-29: LGTM! Clean icon component mapping.The
iconComponentsmapping provides a clear way to resolve icon names to Material-UI icon components.
43-58: LGTM! Dynamic icon styling based on step state.The
getStepIconfunction correctly determines the appropriate icon component and applies conditional styling based on whether the step is active or completed.src/react/src/components/ClaimForm/Stepper/styles.js (1)
3-104: LGTM! Comprehensive stepper styling.The
stepperStylesfunction provides well-structured, themed styles with appropriate use ofObject.freezefor immutability. The styling patterns are consistent with Material-UI v3 conventions (usingtheme.spacing.unit, nested selectors, etc.).src/react/src/components/ClaimForm/hooks.js (2)
8-12: LGTM! Clean step reset on mount.The
useStepResetOnMounthook correctly ensures the form always starts at step 0 when the component mounts.
19-25: LGTM! Proper data prefetching.The
usePrefetchDatahook correctly handles conditional data fetching with appropriate dependencies.src/react/src/components/ClaimForm/Steps/ProfileStep.jsx (2)
20-65: LGTM! Well-structured inline styles.The
profileStepStylesfunction follows the same frozen-object pattern used in other style files and provides comprehensive styling for the profile step sections.
67-265: LGTM! Clear expansion panel structure with noted placeholders.The component provides a clear multi-section layout using Material-UI ExpansionPanels. The placeholder text for future sections (Compliance & Partnerships, Environmental Data) is appropriately documented and transparent to users.
src/react/src/components/ClaimForm/constants.js (1)
1-47: LGTM! Well-organized and consistent constants.The constants file provides a clear, frozen configuration for the claim form workflow. All arrays have consistent lengths (4 elements), and the STEP_ICONS mapping correctly uses computed property names from CLAIM_FORM_STEPS.
src/react/src/components/ClaimForm/Steps/EligibilityStep.jsx (2)
15-45: LGTM! Consistent inline styling pattern.The
eligibilityStepStylesfunction follows the same frozen-object pattern used consistently across the claim form components.
47-93: LGTM! Clear eligibility verification flow.The component provides clear messaging about eligibility requirements with appropriate warnings about false claims. The checkbox implementation correctly uses controlled component patterns.
src/react/src/components/ClaimForm/utils.js (7)
8-9: LGTM: Progress calculation is correct.The percentage calculation correctly handles the base case (empty array returns 0%).
17-18: LGTM: Step completion check is straightforward.
45-46: LGTM: Correctly bounds the next step.
53-53: LGTM: Correctly bounds the previous step.
60-61: LGTM: First step check is correct.
68-68: LGTM: Last step check is correct.
75-76: LGTM: All-steps-complete check is correct.This correctly verifies that all 4 steps have been completed.
src/react/src/actions/claimForm.js (1)
1-23: LGTM: Action creators follow redux-act patterns.The action creators are well-structured and follow consistent naming conventions.
src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx
Outdated
Show resolved
Hide resolved
src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx
Outdated
Show resolved
Hide resolved
Countries App | Unittest test suite - Code coverage reportTotal: 100%Your code coverage diff: 0.00% ▴ ✅ All code changes are covered |
Contricleaner App | Unittest test suite - Code coverage reportTotal: 98.75%Your code coverage diff: 0.00% ▴ ✅ All code changes are covered |
Django App | Unittest test suite - Code coverage reportTotal: 81.41%Your code coverage diff: 0.00% ▴ ✅ All code changes are covered |
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (2)
src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (1)
60-89: Reset form state whenosIDchanges to avoid stale progressUsers switching facilities can see stale
completedSteps/form data. DispatchresetClaimForm()on mount and whenosIDchanges. This was raised earlier and still applies.-import React from 'react'; +import React, { useEffect } from 'react'; ... import { setActiveClaimFormStep, markStepComplete, updateClaimFormField, + resetClaimForm, } from '../../../actions/claimForm'; ... const ClaimForm = ({ classes, match: { params: { osID }, }, history, activeStep, completedSteps, formData, + resetForm, countriesOptions, ... }) => { // Redirect to intro page if user accessed form directly via URL. useRequireIntroAccess(history, osID); // Prefetch required data on mount. usePrefetchClaimData( ... ); + // Clear form state when facility changes. + useEffect(() => { + resetForm(); + }, [osID, resetForm]);And wire the dispatcher:
const mapDispatchToProps = dispatch => ({ fetchCountries: () => dispatch(fetchCountryOptions()), fetchFacilityProcessingType: () => dispatch(fetchFacilityProcessingTypeOptions()), fetchParentCompanies: () => dispatch(fetchParentCompanyOptions()), fetchProductionLocation: osID => dispatch(fetchProductionLocationByOsId(osID)), setStep: stepIndex => dispatch(setActiveClaimFormStep(stepIndex)), markComplete: stepIndex => dispatch(markStepComplete(stepIndex)), updateField: payload => dispatch(updateClaimFormField(payload)), + resetForm: () => dispatch(resetClaimForm()), });And PropTypes:
updateField: func.isRequired, + resetForm: func.isRequired,src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/Stepper.jsx (1)
124-129: PropTypes for classes fixed — thanks.
🧹 Nitpick comments (24)
src/react/src/components/InitialClaimFlow/ClaimForm/styles.js (1)
7-7: Consider using COLOURS constants for hard-coded colors.Hard-coded hex values
'#F9F7F7'(line 7) and'#0D1128'(line 46) appear instead of COLOURS constants. For consistency with the rest of the codebase (e.g., line 16 usesCOLOURS.WHITE), consider adding these colors to the COLOURS module and referencing them here.If these colors are intended to be one-off values specific to this component, consider adding a comment explaining why they're not in COLOURS.
Also applies to: 46-46
src/react/src/components/InitialClaimFlow/ClaimIntro/styles.js (1)
66-66: Consider using a COLOURS constant for the hard-coded border color.The hard-coded value
'#0D1128'(line 66) appears in multiple files across this PR (also in ClaimForm/styles.js and ErrorState/styles.js). Consider adding it to the COLOURS module as a named constant (e.g.,COLOURS.DARK_BORDERorCOLOURS.JET_BLACK_BORDER) for consistency and easier maintenance.src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/styles.js (2)
5-15: Consider extracting shared styles to reduce duplication.The
container(lines 5-8) andpaper(lines 9-15) styles are identical to those inClaimForm/styles.js(lines 6-9 and 14-20). Consider extracting these to a shared styles module or a base style object that both files can import to maintain consistency and reduce duplication.
6-6: Use COLOURS constants instead of hard-coded hex values.Hard-coded colors appear at lines 6 (
'#F9F7F7'), 11 ('#FFFFFF'), and 61 ('#0D1128'). Line 11 should useCOLOURS.WHITEfor consistency. The other colors should either be added to the COLOURS module or documented as intentional one-off values.Apply this diff to use the existing constant:
- backgroundColor: '#FFFFFF', + backgroundColor: COLOURS.WHITE,Also applies to: 11-11, 61-61
src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/styles.js (3)
3-3: Freeze the root style objectMinor immutability nit: also freeze the returned object.
-const stepperStyles = () => ({ +const stepperStyles = () => Object.freeze({
25-28: Avoid disabling pointer events on labels (a11y risk)Pointer-events none prevents keyboard interaction. Prefer leaving labels interactive or ensure the actual interactive element has role="button", tabIndex=0, and keyboard handlers. Please confirm Stepper.jsx handles this.
3-8: Consider theme-driven spacing instead of hard-coded pxOptional: accept
themein the style factory and usetheme.spacing.unitandtheme.palettefor consistency with the rest of the codebase.Also applies to: 17-24, 75-82
src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimIntro.jsx (1)
113-116: TightenhistoryPropTypes
goBackisn’t used; onlypushis required.history: PropTypes.shape({ - goBack: PropTypes.func.isRequired, push: PropTypes.func.isRequired, }).isRequired,src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx (2)
98-116: WireonBlurfor phone field as wellKeeps touch/validation behavior consistent across fields.
<TextField fullWidth name="contactPhone" label="Contact Phone (Optional)" value={formData.contactPhone || ''} onChange={e => handleChange('contactPhone', e.target.value) } + onBlur={handleBlur} className={classes.field} placeholder="+1 (555) 123-4567"
137-139: Fix misplaced TODOThis TODO references the eligibility step but lives in ContactStep. Move/update to the correct file to avoid confusion.
src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (1)
225-229: Gate step clicks to completed/current stepsPrevent jumping to unvalidated future steps via the Stepper click.
- <ClaimFormStepper - currentStep={activeStep} - completedSteps={completedSteps} - onStepClick={setStep} - /> + <ClaimFormStepper + currentStep={activeStep} + completedSteps={completedSteps} + onStepClick={index => { + if (index <= activeStep || completedSteps.includes(index)) { + setStep(index); + } + }} + />Also applies to: 176-178, 205-213
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx (3)
62-66: Replace deprecated Typography variant "title".Use a current variant (e.g., "h6") to avoid deprecation warnings and theming inconsistencies.
- <Typography variant="title"> + <Typography variant="h6">
56-57: Grid spacing values may be invalid on MUI v4+.spacing={24} and spacing={16} are valid in v3, but v4 limits spacing to 0–10. Adjust if the project uses v4+.
- <Grid container spacing={24}> + <Grid container spacing={3}> ... - <Grid container spacing={16}> + <Grid container spacing={2}>Also applies to: 73-74
97-118: Improve website field semantics (type and autocomplete).Use type="url" and autoComplete for better validation and mobile keyboard; keep current handlers.
- <TextField + <TextField fullWidth name="businessWebsite" label="Business Website (Optional)" value={formData.businessWebsite || ''} onChange={e => handleChange( 'businessWebsite', e.target.value, ) } className={classes.field} placeholder="https://company.com" + type="url" + inputMode="url" + autoComplete="url"src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx (4)
58-62: Replace deprecated Typography variant "title".- <Typography variant="title"> + <Typography variant="h6">
88-110: Use numeric input for Years at Company.Use type="number" with sane min/step; keep current validation.
- <TextField + <TextField fullWidth name="yearsAtCompany" label="Years at Company (Optional)" value={formData.yearsAtCompany || ''} onChange={e => handleChange( 'yearsAtCompany', e.target.value, ) } className={classes.field} placeholder="e.g., 5" + type="number" + inputProps={{ min: 0, step: 1 }}
15-42: MUI spacing API modernization (if on v4+).Same as BusinessStep: prefer theme.spacing(n) over theme.spacing.unit.
- marginBottom: theme.spacing.unit * 2, + marginBottom: theme.spacing(2), - paddingTop: theme.spacing.unit * 2, - paddingBottom: theme.spacing.unit * 2, + paddingTop: theme.spacing(2), + paddingBottom: theme.spacing(2), - marginRight: theme.spacing.unit, + marginRight: theme.spacing(1), - padding: theme.spacing.unit * 3, + padding: theme.spacing(3), - marginBottom: theme.spacing.unit * 2, + marginBottom: theme.spacing(2),To confirm MUI version, reuse the script from BusinessStep.
52-53: Grid spacing values may be invalid on MUI v4+.spacing={24} and spacing={16} → consider 3 and 2 respectively if using v4+.
- <Grid container spacing={24}> + <Grid container spacing={3}> ... - <Grid container spacing={16}> + <Grid container spacing={2}>Also applies to: 69-70
src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (1)
16-64: Prefetch error config returns first error only — intentional?If multiple sources fail, only the first is surfaced. If you want to aggregate, return a list. Otherwise, this is fine.
src/react/src/components/InitialClaimFlow/ClaimForm/constants.js (3)
8-13: Align step 4 label with PR copy.PR describes “Production Location Details”; constants use “Open Supply Hub Profile”. Pick one for consistency across UI and docs.
export const STEP_NAMES = Object.freeze([ 'Eligibility Check', 'Contact', 'Business', - 'Open Supply Hub Profile', + 'Production Location Details', ]);
36-40: Add final step button label.NEXT_BUTTON_TEXT lacks an entry for PROFILE; add a finishing label.
export const NEXT_BUTTON_TEXT = Object.freeze({ [CLAIM_FORM_STEPS.ELIGIBILITY]: 'Continue to Contact Information', [CLAIM_FORM_STEPS.CONTACT]: 'Continue to Business Details', [CLAIM_FORM_STEPS.BUSINESS]: 'Continue to Production Location Details', + [CLAIM_FORM_STEPS.PROFILE]: 'Finish', });
22-27: Make time units consistent (min vs mins).Unify singular/plural for polish, optionally via i18n.
export const STEP_TIME_ESTIMATES = Object.freeze([ - '1 min', - '5 mins', - '3 mins', - '10 mins', + '1 min', + '5 min', + '3 min', + '10 min', ]);src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js (1)
47-61: Harden redirect when osID is missing.Avoid generating /claim/undefined on rare routing glitches.
export const useRequireIntroAccess = (history, osID) => { useEffect(() => { + if (!osID) return; const hasAccessedFromIntro = sessionStorage.getItem( `claim-form-access-${osID}`, );src/react/src/components/InitialClaimFlow/ClaimForm/validationSchemas.js (1)
26-33: Clarify the validation error message for integer requirement.The validation enforces that
numberOfWorkersmust be an integer, but the error message "Must be at least 1 worker" doesn't communicate this constraint. If a user enters "1.5", they'll receive an unclear error.Apply this diff to improve the error message:
numberOfWorkers: Yup.string() .nullable() - .test('is-valid-workers', 'Must be at least 1 worker', value => { + .test('is-valid-workers', 'Must be a whole number of at least 1', value => { if (!value || value.trim() === '') return true; // Optional. const num = Number(value); return !Number.isNaN(num) && num >= 1 && Number.isInteger(num); }),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
doc/release/RELEASE-NOTES.md(1 hunks)src/react/src/Routes.jsx(3 hunks)src/react/src/actions/claimForm.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/ErrorState.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/styles.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/Stepper.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/hooks.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/styles.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ProfileStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/constants.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/styles.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/utils.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/validationSchemas.js(1 hunks)src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimInfoSection.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimIntro.jsx(5 hunks)src/react/src/components/InitialClaimFlow/ClaimIntro/styles.js(2 hunks)src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx(1 hunks)src/react/src/reducers/ClaimFormReducer.js(1 hunks)src/react/src/util/constants.jsx(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/react/src/util/constants.jsx
🚧 Files skipped from review as they are similar to previous changes (2)
- src/react/src/reducers/ClaimFormReducer.js
- src/react/src/actions/claimForm.js
🧰 Additional context used
🧬 Code graph analysis (14)
src/react/src/Routes.jsx (3)
src/react/src/util/constants.jsx (4)
claimIntroRoute(342-342)claimIntroRoute(342-342)claimDetailsRoute(343-343)claimDetailsRoute(343-343)src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimIntro.jsx (1)
ClaimIntro(24-107)src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (1)
ClaimForm(60-288)
src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/hooks.js (3)
src/react/src/components/ClaimFacilityStepper.jsx (1)
activeStep(163-163)src/react/src/reducers/ClaimFormReducer.js (1)
completedSteps(41-43)src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (2)
isStepComplete(3-4)isStepComplete(3-4)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx (1)
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js (4)
src/react/src/util/constants.jsx (2)
claimIntroRoute(342-342)claimIntroRoute(342-342)src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (1)
useClaimForm(118-123)src/react/src/components/ClaimFacilityStepper.jsx (1)
activeStep(163-163)src/react/src/components/InitialClaimFlow/ClaimForm/validationSchemas.js (2)
getValidationSchemaForStep(37-46)getValidationSchemaForStep(37-46)
src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/Stepper.jsx (3)
src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/hooks.js (1)
useStepNavigation(4-16)src/react/src/components/InitialClaimFlow/ClaimForm/constants.js (6)
STEP_NAMES(8-13)STEP_NAMES(8-13)STEP_SUBTITLES(15-20)STEP_SUBTITLES(15-20)STEP_TIME_ESTIMATES(22-27)STEP_TIME_ESTIMATES(22-27)src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/styles.js (1)
stepperStyles(3-83)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ProfileStep.jsx (2)
src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (1)
errors(17-22)src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (2)
src/react/src/reducers/ClaimFormReducer.js (1)
completedSteps(41-43)src/react/src/components/InitialClaimFlow/ClaimForm/constants.js (4)
TOTAL_STEPS(42-42)TOTAL_STEPS(42-42)CLAIM_FORM_STEPS(1-6)CLAIM_FORM_STEPS(1-6)
src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/ErrorState.jsx (4)
src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimIntro.jsx (1)
mapDispatchToProps(138-142)src/react/src/actions/claimForm.js (2)
resetClaimForm(11-11)resetClaimForm(11-11)src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/styles.js (1)
errorStateStyles(3-63)src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimIntro.jsx (4)
src/react/src/util/constants.jsx (4)
facilityDetailsRoute(340-340)facilityDetailsRoute(340-340)claimDetailsRoute(343-343)claimDetailsRoute(343-343)src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/ErrorState.jsx (1)
mapDispatchToProps(84-88)src/react/src/actions/claimForm.js (2)
resetClaimForm(11-11)resetClaimForm(11-11)src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/validationSchemas.js (1)
src/react/src/components/InitialClaimFlow/ClaimForm/constants.js (2)
CLAIM_FORM_STEPS(1-6)CLAIM_FORM_STEPS(1-6)
src/react/src/components/InitialClaimFlow/ClaimForm/styles.js (1)
src/react/src/util/constants.jsx (2)
HEADER_HEIGHT(1597-1597)HEADER_HEIGHT(1597-1597)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx (1)
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx (1)
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (9)
src/react/src/components/InitialClaimFlow/ClaimForm/constants.js (8)
CLAIM_FORM_STEPS(1-6)CLAIM_FORM_STEPS(1-6)STEP_NAMES(8-13)STEP_NAMES(8-13)STEP_DESCRIPTIONS(29-34)STEP_DESCRIPTIONS(29-34)NEXT_BUTTON_TEXT(36-40)NEXT_BUTTON_TEXT(36-40)src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js (7)
useRequireIntroAccess(47-62)useRequireIntroAccess(47-62)usePrefetchClaimData(7-41)usePrefetchClaimData(7-41)useClaimForm(64-133)useClaimForm(64-133)handleFieldChange(103-107)src/react/src/components/RequireAuthNotice.jsx (1)
RequireAuthNotice(9-29)src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (10)
getPrefetchErrorConfig(16-64)getPrefetchErrorConfig(16-64)getNextStep(6-7)getNextStep(6-7)isFirstStep(11-12)isFirstStep(11-12)getPreviousStep(9-9)getPreviousStep(9-9)isLastStep(14-14)isLastStep(14-14)src/react/src/components/InitialClaimFlow/ClaimForm/validationSchemas.js (2)
getValidationSchemaForStep(37-46)getValidationSchemaForStep(37-46)src/react/src/util/constants.jsx (2)
claimIntroRoute(342-342)claimIntroRoute(342-342)src/react/src/actions/filterOptions.js (3)
fetchCountryOptions(194-212)fetchFacilityProcessingTypeOptions(284-303)fetchParentCompanyOptions(264-282)src/react/src/actions/contributeProductionLocation.js (1)
fetchProductionLocationByOsId(143-162)src/react/src/actions/claimForm.js (6)
setActiveClaimFormStep(4-6)setActiveClaimFormStep(4-6)markStepComplete(7-7)markStepComplete(7-7)updateClaimFormField(10-10)updateClaimFormField(10-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: run-flake8-linter
- GitHub Check: run-contricleaner-code-quality
- GitHub Check: get-base-branch-contricleaner-cov
- GitHub Check: run-integration-test-code-quality
- GitHub Check: run-dd-code-quality
- GitHub Check: get-base-branch-dd-cov
- GitHub Check: run-countries-code-quality
- GitHub Check: run-django-code-quality
- GitHub Check: get-base-branch-countries-cov
- GitHub Check: run-fe-code-quality
- GitHub Check: get-base-branch-django-cov
🔇 Additional comments (9)
src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimInfoSection.jsx (1)
210-212: LGTM!The label update improves clarity and aligns with the new claim flow terminology.
src/react/src/Routes.jsx (1)
28-28: LGTM!The routing changes properly integrate the new claim form flow. The feature flag removal indicates the claim intro is now production-ready, and the new
claimDetailsRoutefollows established routing patterns.Also applies to: 61-61, 140-149
src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/hooks.js (1)
1-18: LGTM!The custom hook properly implements step navigation with appropriate guards. The dependency array correctly includes all referenced values, and the logic prevents invalid navigation attempts.
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
1-21: LGTM!The HOC follows React best practices with proper prop forwarding and displayName setting for debugging. The scroll reset behavior on location changes will improve user experience during navigation.
src/react/src/components/InitialClaimFlow/ClaimIntro/ClaimIntro.jsx (1)
42-49: LGTM on reset-and-navigate behaviorResetting form, filters, and production location before navigating back is sound.
src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (1)
301-328: PropTypes error fields mismatch is valid, but suggested fix is overly broadThe review correctly identifies that error fields are typed as
arrayin PropTypes but default tonull. However, verification shows errors are dispatched exclusively as arrays (never as objects or strings) vialogErrorAndDispatchFailure()in util.js. The actual runtime values are onlynullorarray, making the suggestedoneOfType([array, object, string])unnecessarily broad. A more precise fix would beoneOfType([arrayOf(string)])or simply explicitoneOfType([array])to align with actual dispatch patterns.Likely an incorrect or invalid review comment.
src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (1)
3-15: Navigation helpers look correct.Bounds are clamped and step checks are clear.
src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js (1)
70-75: Formik integration looks good; revalidation on step change is solid.No blockers spotted. Keep an eye on validationSchema updates across steps; your revalidation effect mitigates schema switch edge cases.
If issues arise, consider passing a function schema (if you migrate to Yup v1) or reconstructing Formik when activeStep changes.
Also applies to: 82-101, 109-132
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx (1)
15-46: ****The codebase uses MUI v3.1.0, which employs the
theme.spacing.unitAPI. The current code is correct for this version. The review comment assumes MUI v4+ (wheretheme.spacing(n)is the pattern), but that version is not installed. No changes are needed.Likely an incorrect or invalid review comment.
src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/ErrorState.jsx
Show resolved
Hide resolved
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx
Show resolved
Hide resolved
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx
Show resolved
Hide resolved
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx
Show resolved
Hide resolved
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ProfileStep.jsx
Show resolved
Hide resolved
|
@vlad-shapik Overall, looks good, nice work 👍 Pls:
and ping me to approve. |
|
@vlad-shapik LGTM, great work! |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/react/src/__tests__/components/ClaimIntro.test.js (1)
110-113: Add cleanup for sessionStorage mock or verify its usage.The
sessionStoragemock is created but lacks both assertions and cleanup, which could cause test pollution.Consider one of these approaches:
Option 1: Verify the mock is used (if the component stores data)
const continueButton = getByText('Continue to Claim Form'); fireEvent.click(continueButton); +expect(sessionStorageMock.setItem).toHaveBeenCalled(); const expectedPath = claimDetailsRoute.replace(':osID', mockOsID); expect(history.location.pathname).toBe(expectedPath);Option 2: Move to beforeEach/afterEach with cleanup (if just preventing errors)
+beforeEach(() => { + jest.clearAllMocks(); + history.push('/'); + global.sessionStorage = { setItem: jest.fn() }; +}); + +afterEach(() => { + delete global.sessionStorage; +});
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/react/src/__tests__/components/ClaimInfoSection.test.js(1 hunks)src/react/src/__tests__/components/ClaimIntro.test.js(3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-01-17T16:12:18.285Z
Learnt from: Innavin369
PR: opensupplyhub/open-supply-hub#483
File: src/react/src/__tests__/components/SearchByNameAndAddressSuccessResult.test.js:0-0
Timestamp: 2025-01-17T16:12:18.285Z
Learning: In the SearchByNameAndAddressSuccessResult component's tests, attempting to test internal navigation logic through mocking useHistory is not feasible, and button presence/click events should be covered in the main rendering test case.
Applied to files:
src/react/src/__tests__/components/ClaimIntro.test.js
🧬 Code graph analysis (2)
src/react/src/__tests__/components/ClaimInfoSection.test.js (1)
src/react/src/__tests__/components/ClaimIntro.test.js (1)
renderComponent(23-40)
src/react/src/__tests__/components/ClaimIntro.test.js (1)
src/react/src/util/constants.jsx (4)
facilityDetailsRoute(340-340)facilityDetailsRoute(340-340)claimDetailsRoute(343-343)claimDetailsRoute(343-343)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: get-base-branch-countries-cov
- GitHub Check: run-contricleaner-code-quality
- GitHub Check: run-flake8-linter
- GitHub Check: get-base-branch-django-cov
- GitHub Check: run-countries-code-quality
- GitHub Check: run-integration-test-code-quality
- GitHub Check: get-base-branch-dd-cov
- GitHub Check: run-django-code-quality
- GitHub Check: run-fe-code-quality
- GitHub Check: get-base-branch-fe-cov
🔇 Additional comments (4)
src/react/src/__tests__/components/ClaimInfoSection.test.js (1)
120-123: LGTM! Test correctly updated to reflect UI text changes.The test name and assertion have been properly updated to align with the renamed Step 5 label from "Get Verified" to "Get a Credible and Confirmed Profile". Both changes are consistent and maintain the test's correctness.
src/react/src/__tests__/components/ClaimIntro.test.js (3)
7-8: LGTM! Clean refactor to centralized route constants.The switch from
makeClaimDetailsLinkto direct route constants improves maintainability and aligns with the PR's routing skeleton implementation.
9-11: LGTM! Standard test setup pattern.Stubbing
window.scrollToinbeforeAllis the correct approach to prevent errors when components trigger scroll behavior during tests.
87-106: LGTM! Navigation tests properly updated.The back navigation test correctly uses
facilityDetailsRoute.replace(':osID', mockOsID)pattern and text expectations align with component changes.
|
@vlad-shapik can you address issues about props validation? |
|
There was a problem hiding this comment.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ProfileStep.jsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx (1)
15-46: Consider extracting shared step styles to reduce duplication.The businessStepStyles object is nearly identical to the styles in ContactStep, EligibilityStep, and ProfileStep. Extracting these common styles into a shared module (e.g.,
stepStyles.js) would improve maintainability and ensure consistent styling across all form steps.Example refactor:
In a new file
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/sharedStepStyles.js:import COLOURS from '../../../../util/COLOURS'; export const createStepStyles = theme => Object.freeze({ card: Object.freeze({ marginBottom: theme.spacing.unit * 2, boxShadow: 'none', border: `1px solid ${COLOURS.GREY}`, }), cardHeader: Object.freeze({ backgroundColor: '#f9fafb', paddingTop: theme.spacing.unit * 2, paddingBottom: theme.spacing.unit * 2, }), // ... other shared styles });Then import and use in each step component.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/ErrorState.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ProfileStep.jsx(1 hunks)src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/react/src/components/InitialClaimFlow/ClaimForm/ErrorState/ErrorState.jsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: vlad-shapik
PR: opensupplyhub/open-supply-hub#775
File: src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/Stepper.jsx:43-45
Timestamp: 2025-10-24T12:42:48.886Z
Learning: In the InitialClaimFlow ClaimForm Stepper component (src/react/src/components/InitialClaimFlow/ClaimForm/Stepper/Stepper.jsx), the stepper intentionally uses `index < currentStep` for the `isClickable` check rather than `completedSteps.includes(index)` to prevent users from jumping forward to completed future steps when navigating back, enforcing a linear backward-only navigation pattern.
🧬 Code graph analysis (5)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx (1)
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js (3)
src/react/src/util/constants.jsx (2)
claimIntroRoute(342-342)claimIntroRoute(342-342)src/react/src/components/InitialClaimFlow/ClaimForm/ClaimForm.jsx (1)
useClaimForm(118-123)src/react/src/components/InitialClaimFlow/ClaimForm/validationSchemas.js (2)
getValidationSchemaForStep(37-46)getValidationSchemaForStep(37-46)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx (1)
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ProfileStep.jsx (2)
src/react/src/components/InitialClaimFlow/ClaimForm/utils.js (1)
errors(17-22)src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx (1)
src/react/src/components/InitialClaimFlow/HOCs/withScrollReset.jsx (1)
withScrollReset(5-19)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
- GitHub Check: Cursor Bugbot
- GitHub Check: run-flake8-linter
- GitHub Check: get-base-branch-contricleaner-cov
- GitHub Check: run-eslint-linter-and-prettier-formatter
- GitHub Check: run-contricleaner-code-quality
- GitHub Check: run-integration-test-code-quality
- GitHub Check: run-dd-code-quality
- GitHub Check: run-countries-code-quality
- GitHub Check: get-base-branch-dd-cov
- GitHub Check: get-base-branch-countries-cov
- GitHub Check: run-django-code-quality
- GitHub Check: get-base-branch-fe-cov
- GitHub Check: get-base-branch-django-cov
- GitHub Check: run-fe-code-quality
🔇 Additional comments (6)
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/ContactStep.jsx (1)
75-95: LGTM: Contact email field properly configured.The required email field correctly wires up onChange, onBlur, and validation feedback using touched/errors props.
src/react/src/components/InitialClaimFlow/ClaimForm/hooks.js (3)
7-44: LGTM: Prefetch logic handles edge cases appropriately.The hook correctly guards against redundant fetches using isEmpty checks for most options. The intentional omission of isEmpty for parentCompanyOptions (to avoid infinite loops with empty datasets) shows thoughtful consideration of the data model.
46-65: LGTM: Access control pattern correctly implemented.The session-based gating ensures users follow the intended intro → form flow, and the cleanup on unmount prevents sessionStorage pollution.
85-103: Verify useEffect dependencies for potential stale closures.The useEffect accesses
formik.values,formik.setTouched, andformik.validateFormbut only lists[activeStep]in its dependency array. While Formik's instance methods are typically stable, omittingformik.valuescould potentially lead to reading stale form state when the step changes.Consider verifying whether this causes issues in practice, or add the missing dependencies:
- }, [activeStep]); + }, [activeStep, formik]);Note: If adding
formikcauses re-render issues, you may need to destructure the specific methods and values you need from formik before the useEffect, or useformik.currentvia a ref pattern.src/react/src/components/InitialClaimFlow/ClaimForm/Steps/BusinessStep.jsx (1)
75-94: LGTM: Business name field properly configured.The required field correctly implements the validation pattern with onBlur handling.
src/react/src/components/InitialClaimFlow/ClaimForm/Steps/EligibilityStep.jsx (1)
71-85: LGTM: Position field correctly configured.The required position field properly implements validation feedback with onBlur handling.



OSDEV-2203
Implemented new multi-step claim flow for production locations with routing skeleton and shared layout. Introduced claim form page (
/claim/:osID/details/) featuring a four-step stepper (Eligibility Check, Contact Information, Business Details, Production Location Details). Added step-isolated form validation with optimistic button states that enable on initial render and disable after user interaction with errors. Integrated session-based URL access protection and data prefetching for countries, facility processing types, parent companies, and production location data using the existing Redux infrastructure for the claim form steps where this data should be prepopulated.