Skip to content

Conversation

@yash-learner
Copy link
Member

@yash-learner yash-learner commented Jan 18, 2026

Proposed Changes

Fixes #15216

Screen.Recording.2026-01-19.014323.mp4

Tagging: @ohcnetwork/care-fe-code-reviewers

Merge Checklist

  • Add specs that demonstrate the bug or test the new feature.
  • Update product documentation.
  • Ensure that UI text is placed in I18n files.
  • Prepare a screenshot or demo video for the changelog entry and attach it to the issue.
  • Request peer reviews.
  • Complete QA on mobile devices.
  • Complete QA on desktop devices.
  • Add or update Playwright tests for related changes

Summary by CodeRabbit

  • New Features

    • Added an activity-definition picker to select service request types inline.
  • Improvements

    • Redesigned service request UI with compact badges, separators, and a left accent preview for clarity.
    • Replaced select controls with radio choices for priority and auto-expanding textareas for notes/instructions.
    • Improved add/remove and preview behaviors and responsive single/multi-column layouts.
  • Documentation

    • Added three new English localization strings for service request selection.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings January 18, 2026 19:01
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 18, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds three English localization keys for service-request selection and refactors the ServiceRequestQuestion UI: swaps several UI primitives, replaces the priority select with radio inputs, introduces a pickerSlot for activity definition selection, restructures badges/layout, and updates state and event wiring.

Changes

Cohort / File(s) Change Summary
Localization Keys
public/locale/en.json
Added three new keys: select_another_service_request, select_service_request, selected_service_request ( +3 lines ).
Service Request Question Component
src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx
Major UI refactor: removed ChevronDown, Info, Textarea; added AutoExpandingTextarea, RadioInput, CareIcon, Separator; replaced priority Select with RadioInput; added pickerSlot?: React.ReactNode to ServiceRequestFormProps and threaded activity definition picker into preview and form; introduced badge row rendering, visual separators, containerized multi-item layout, updated event handlers and state reset logic for activity definition selection. (+254/-238 lines).
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: updating the Service Request question component to a new design, which is confirmed by the substantial UI/layout refactoring in the ServiceRequestQuestion.tsx file.
Description check ✅ Passed The description includes the fixed issue reference (#15216), a design asset link, and proper tagging, but lacks specific details about the changes made (missing bullet points describing what was updated).
Linked Issues check ✅ Passed The PR implements the new Service Request Question design as specified in issue #15216, with substantial component refactoring, new UI elements, updated layouts, and localization strings.
Out of Scope Changes check ✅ Passed All changes are scope-aligned: localization strings and component refactoring directly support the new design implementation referenced in issue #15216, with no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch implement-new-sr-design

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Service Request question component to align with a new design system. The changes modernize the UI with improved visual hierarchy, better component organization, and enhanced user experience through clearer information presentation and improved interaction patterns.

Changes:

  • Replaced Select component with RadioInput for priority selection, improving accessibility and clarity
  • Replaced standard Textarea with AutoExpandingTextarea for better text input experience
  • Updated visual design with new badge variants, separators, and consistent spacing
  • Reorganized layout from grid-based to stacked vertical layout for better responsiveness

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx Refactored component to use new design system with updated components, improved layout structure, and enhanced visual hierarchy
public/locale/en.json Added new translation keys for the updated service request selection UI

<div className="w-px h-10 bg-gray-300 self-center" />
<div className="flex flex-col gap-1">
<span className="text-xs font-normal leading-none text-gray-700">
&nbsp;
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a non-breaking space character as placeholder text is unclear and makes the code harder to maintain. Consider either removing this span element entirely if the vertical alignment works without it, or use an explicit empty string with a comment explaining why the spacing is needed for visual alignment with other badges.

Suggested change
&nbsp;
{/* Intentionally left empty to align this badge with other labeled badges */}
{""}

Copilot uses AI. Check for mistakes.
{t("cancel")}
</Button>
)}
<Button variant="outline_primary" onClick={onAdd} className="">
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty className prop serves no purpose and should be removed for cleaner code.

Suggested change
<Button variant="outline_primary" onClick={onAdd} className="">
<Button variant="outline_primary" onClick={onAdd}>

Copilot uses AI. Check for mistakes.
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Jan 18, 2026

Deploying care-preview with  Cloudflare Pages  Cloudflare Pages

Latest commit: c50fb13
Status: ✅  Deploy successful!
Preview URL: https://b5b42c82.care-preview-a7w.pages.dev
Branch Preview URL: https://implement-new-sr-design.care-preview-a7w.pages.dev

View logs

@github-actions
Copy link

github-actions bot commented Jan 18, 2026

🎭 Playwright Test Results

Status: ❌ Failed
Test Shards: 3

Metric Count
Total Tests 171
✅ Passed 164
❌ Failed 7
⏭️ Skipped 0

📊 Detailed results are available in the playwright-final-report artifact.

Run: #4909

Copilot AI review requested due to automatic review settings January 18, 2026 20:23
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

"select_section_to_add": "Select Section to Add",
"select_service_account_type": "Select service account type",
"select_service_point": "Select Service Point",
"select_service_request": "Select the service request",
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The translation key contains an unnecessary article 'the'. It should be "Select service request" to match the pattern of similar keys like "select_another_service_request" and maintain consistency with other selection prompts in the file.

Suggested change
"select_service_request": "Select the service request",
"select_service_request": "Select service request",

Copilot uses AI. Check for mistakes.
Comment on lines +205 to +206
<span className="text-xs font-normal leading-none text-gray-700">
&nbsp;
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a non-breaking space as placeholder content is a code smell. Consider using an empty string or CSS styling (min-height) to maintain spacing instead of relying on invisible content.

Suggested change
<span className="text-xs font-normal leading-none text-gray-700">
&nbsp;
<span className="text-xs font-normal leading-none text-gray-700 min-h-[1rem]">
{""}

Copilot uses AI. Check for mistakes.
Comment on lines +611 to +613
} else {
setSelectedActivityDefinition(def.slug);
}
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early return pattern would be cleaner here. Consider restructuring to handle the null case first and return early, then handle the success case without the else block.

Suggested change
} else {
setSelectedActivityDefinition(def.slug);
}
return;
}
setSelectedActivityDefinition(def.slug);

Copilot uses AI. Check for mistakes.
@yash-learner yash-learner marked this pull request as ready for review January 18, 2026 20:23
@yash-learner yash-learner requested review from a team and Copilot January 18, 2026 20:24
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

"select_section_to_add": "Select Section to Add",
"select_service_account_type": "Select service account type",
"select_service_point": "Select Service Point",
"select_service_request": "Select the service request",
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected article usage from 'the' to 'a' for more natural phrasing in selection prompts.

Suggested change
"select_service_request": "Select the service request",
"select_service_request": "Select a service request",

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx (1)

356-429: Significant code duplication between preview and collapsed form views.

The form fields (priority, body_site, patient_instruction, requester, note) are nearly identical between the preview (lines 229-300) and collapsed (lines 356-428) layouts. Consider extracting these into a shared helper component or function to reduce duplication and ensure consistency.

Additionally, there's a minor styling inconsistency: the preview AutoExpandingTextarea includes text-sm class (lines 286, 297) while the collapsed view does not (lines 405, 426).

♻️ Suggested approach

Extract the form fields into a reusable component:

function ServiceRequestFormFields({
  serviceRequest,
  onUpdate,
  disabled,
  errors,
  questionId,
  index,
  facilityId,
}: {
  serviceRequest: ServiceRequestApplyActivityDefinitionSpec;
  onUpdate?: (updates: Partial<ServiceRequestReadSpec>) => void;
  disabled?: boolean;
  errors?: QuestionValidationError[];
  questionId?: string;
  index?: number;
  facilityId?: string;
}) {
  const { t } = useTranslation();
  
  return (
    <div className="space-y-4">
      {/* Priority, body_site, requester, patient_instruction, note fields */}
    </div>
  );
}

Then use it in both preview and collapsed views.

🤖 Fix all issues with AI agents
In `@src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx`:
- Around line 673-716: The ResourceDefinitionCategoryPicker props are
duplicated; extract the shared config into a single const (e.g.,
activityDefinitionPickerProps) containing facilityId, value
(selectedActivityDefinitionData || undefined), onValueChange
(handleActivityDefinitionSelect), disabled, className, resourceType
(ResourceCategoryResourceType.activity_definition), listDefinitions (queryFn:
activityDefinitionApi.listActivityDefinition, pathParams: { facilityId }), and
translationBaseKey, then spread that object into both
<ResourceDefinitionCategoryPicker<ActivityDefinitionReadSpec>> usages and only
override the differing placeholder strings via a placeholder prop.
- Around line 696-702: The i18n key is being passed via a ternary inside the t()
call in the JSX span in ServiceRequestQuestion (the expression using
t(serviceRequests.length > 0 ? "select_another_service_request" :
"select_service_request")), which prevents static key detection; fix it by
removing the ternary and calling t() separately for each branch (e.g., compute
label = serviceRequests.length > 0 ? t("select_another_service_request") :
t("select_service_request") or render {serviceRequests.length > 0 ?
t("select_another_service_request") : t("select_service_request")}) so both keys
are statically visible to the i18n cleanup script, referencing the span element,
t(), and serviceRequests.length in ServiceRequestQuestion.
- Around line 333-336: The CareIcon usage inside ServiceRequestQuestion (the
CareIcon component instance with icon="l-edit" and className="size-5
text-gray-950 font-normal") should be made accessible: if the icon is purely
decorative add aria-hidden="true" and role="presentation" to the CareIcon props;
if it conveys meaning for screen readers provide a concise aria-label (e.g.,
aria-label="Edit" or aria-label="Expand section") instead and do not mark it
hidden. Update the CareIcon props accordingly in the ServiceRequestQuestion
component.
♻️ Duplicate comments (3)
public/locale/en.json (1)

4928-4928: Align wording with other selection prompts.

Consider removing the article to match similar keys like "select_another_service_request".

💬 Suggested tweak
-  "select_service_request": "Select the service request",
+  "select_service_request": "Select service request",
src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx (2)

204-209: Non-breaking space used for visual alignment is a code smell.

Using &nbsp; as placeholder content for alignment is fragile and unclear. Consider using CSS min-height or removing the span if the layout works without it.


607-614: Early return pattern would be cleaner.

Consider restructuring to handle the null case first with an early return, then handle the success case without the else block.

Comment on lines +333 to +336
<CareIcon
icon="l-edit"
className="size-5 text-gray-950 font-normal"
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding aria-label for the edit icon.

The edit icon appears to convey that the collapsible section is expandable/editable. Adding an aria-hidden="true" attribute would explicitly mark it as decorative, or add an aria-label if it should convey meaning to screen readers.

             <CareIcon
               icon="l-edit"
               className="size-5 text-gray-950 font-normal"
+              aria-hidden="true"
             />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<CareIcon
icon="l-edit"
className="size-5 text-gray-950 font-normal"
/>
<CareIcon
icon="l-edit"
className="size-5 text-gray-950 font-normal"
aria-hidden="true"
/>
🤖 Prompt for AI Agents
In `@src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx` around
lines 333 - 336, The CareIcon usage inside ServiceRequestQuestion (the CareIcon
component instance with icon="l-edit" and className="size-5 text-gray-950
font-normal") should be made accessible: if the icon is purely decorative add
aria-hidden="true" and role="presentation" to the CareIcon props; if it conveys
meaning for screen readers provide a concise aria-label (e.g., aria-label="Edit"
or aria-label="Expand section") instead and do not mark it hidden. Update the
CareIcon props accordingly in the ServiceRequestQuestion component.

Comment on lines +673 to +716
pickerSlot={
<ResourceDefinitionCategoryPicker<ActivityDefinitionReadSpec>
facilityId={facilityId}
value={selectedActivityDefinitionData || undefined}
onValueChange={handleActivityDefinitionSelect}
placeholder={t("select_activity_definition")}
disabled={disabled}
className="w-full"
resourceType={ResourceCategoryResourceType.activity_definition}
listDefinitions={{
queryFn: activityDefinitionApi.listActivityDefinition,
pathParams: { facilityId },
}}
translationBaseKey="activity_definition"
/>
}
/>
)}

<div className="space-y-2 w-full">
<ResourceDefinitionCategoryPicker<ActivityDefinitionReadSpec>
facilityId={facilityId}
value={selectedActivityDefinitionData || undefined}
onValueChange={handleActivityDefinitionSelect}
placeholder={t("select_activity_definition")}
disabled={disabled}
className="w-full"
resourceType={ResourceCategoryResourceType.activity_definition}
listDefinitions={{
queryFn: activityDefinitionApi.listActivityDefinition,
pathParams: { facilityId },
}}
translationBaseKey="activity_definition"
/>
</div>
{!previewServiceRequest && !isLoadingSelectedAD && (
<div className="rounded-lg border border-gray-200 bg-gray-200/20 shadow-sm overflow-hidden relative">
<div className="absolute left-0 top-4 w-1 h-6 bg-indigo-600 rounded-r-full" />
<div className="p-4">
<span className="text-lg font-semibold leading-6 text-gray-900">
{t(
serviceRequests.length > 0
? "select_another_service_request"
: "select_service_request",
)}
</span>
<ResourceDefinitionCategoryPicker<ActivityDefinitionReadSpec>
facilityId={facilityId}
value={selectedActivityDefinitionData || undefined}
onValueChange={handleActivityDefinitionSelect}
placeholder={t("select_from_list")}
disabled={disabled}
className="w-full"
resourceType={ResourceCategoryResourceType.activity_definition}
listDefinitions={{
queryFn: activityDefinitionApi.listActivityDefinition,
pathParams: { facilityId },
}}
translationBaseKey="activity_definition"
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider extracting shared picker props to reduce duplication.

The ResourceDefinitionCategoryPicker configuration is duplicated between the preview mode (lines 674-687) and the standalone picker (lines 703-716). While functional, extracting shared props would improve maintainability.

♻️ Optional refactor
const activityDefinitionPickerProps = {
  facilityId,
  value: selectedActivityDefinitionData || undefined,
  onValueChange: handleActivityDefinitionSelect,
  disabled,
  className: "w-full",
  resourceType: ResourceCategoryResourceType.activity_definition,
  listDefinitions: {
    queryFn: activityDefinitionApi.listActivityDefinition,
    pathParams: { facilityId },
  },
  translationBaseKey: "activity_definition" as const,
};

// Then use:
<ResourceDefinitionCategoryPicker<ActivityDefinitionReadSpec>
  {...activityDefinitionPickerProps}
  placeholder={t("select_activity_definition")}
/>
🤖 Prompt for AI Agents
In `@src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx` around
lines 673 - 716, The ResourceDefinitionCategoryPicker props are duplicated;
extract the shared config into a single const (e.g.,
activityDefinitionPickerProps) containing facilityId, value
(selectedActivityDefinitionData || undefined), onValueChange
(handleActivityDefinitionSelect), disabled, className, resourceType
(ResourceCategoryResourceType.activity_definition), listDefinitions (queryFn:
activityDefinitionApi.listActivityDefinition, pathParams: { facilityId }), and
translationBaseKey, then spread that object into both
<ResourceDefinitionCategoryPicker<ActivityDefinitionReadSpec>> usages and only
override the differing placeholder strings via a placeholder prop.

Comment on lines +696 to +702
<span className="text-lg font-semibold leading-6 text-gray-900">
{t(
serviceRequests.length > 0
? "select_another_service_request"
: "select_service_request",
)}
</span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Ternary inside t() may prevent i18n key detection by cleanup scripts.

Per project conventions, the i18n cleanup script cannot detect keys wrapped in ternary expressions passed directly to t(). Use separate t() calls for each branch to ensure all keys are statically detectable.

Based on learnings, this pattern should be avoided.

🔧 Proposed fix
-            <span className="text-lg font-semibold leading-6 text-gray-900">
-              {t(
-                serviceRequests.length > 0
-                  ? "select_another_service_request"
-                  : "select_service_request",
-              )}
-            </span>
+            <span className="text-lg font-semibold leading-6 text-gray-900">
+              {serviceRequests.length > 0
+                ? t("select_another_service_request")
+                : t("select_service_request")}
+            </span>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<span className="text-lg font-semibold leading-6 text-gray-900">
{t(
serviceRequests.length > 0
? "select_another_service_request"
: "select_service_request",
)}
</span>
<span className="text-lg font-semibold leading-6 text-gray-900">
{serviceRequests.length > 0
? t("select_another_service_request")
: t("select_service_request")}
</span>
🤖 Prompt for AI Agents
In `@src/components/Questionnaire/QuestionTypes/ServiceRequestQuestion.tsx` around
lines 696 - 702, The i18n key is being passed via a ternary inside the t() call
in the JSX span in ServiceRequestQuestion (the expression using
t(serviceRequests.length > 0 ? "select_another_service_request" :
"select_service_request")), which prevents static key detection; fix it by
removing the ternary and calling t() separately for each branch (e.g., compute
label = serviceRequests.length > 0 ? t("select_another_service_request") :
t("select_service_request") or render {serviceRequests.length > 0 ?
t("select_another_service_request") : t("select_service_request")}) so both keys
are statically visible to the i18n cleanup script, referencing the span element,
t(), and serviceRequests.length in ServiceRequestQuestion.

@vinutv vinutv linked an issue Jan 19, 2026 that may be closed by this pull request
@github-actions github-actions bot added the Merge Conflict pull requests with merge conflict label Jan 20, 2026
@github-actions
Copy link

Conflicts have been detected against the base branch. Please merge the base branch into your branch.
cc: @yash-learner

See: https://docs.ohc.network/docs/contributing#how-to-resolve-merge-conflicts

1 similar comment
@github-actions
Copy link

Conflicts have been detected against the base branch. Please merge the base branch into your branch.
cc: @yash-learner

See: https://docs.ohc.network/docs/contributing#how-to-resolve-merge-conflicts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merge Conflict pull requests with merge conflict needs review needs testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update the design of the Service Request Question Improve UI/UX for Service Request Form Flow

2 participants