Skip to content

feat: integrate patch API to allow edit application#1147

Merged
iamitprakash merged 7 commits intodevelopfrom
feat/edit-application
Feb 19, 2026
Merged

feat: integrate patch API to allow edit application#1147
iamitprakash merged 7 commits intodevelopfrom
feat/edit-application

Conversation

@MayankBansal12
Copy link
Member

@MayankBansal12 MayankBansal12 commented Feb 13, 2026

Date: 17-02-25

Developer Name: @MayankBansal12


Issue Ticket Number:-

Description:

  • Integrate PATCH /application to allow edit application
  • Updated naming for institution from college for new applicatoin

Is Under Feature Flag

  • Yes
  • No

Database changes

  • Yes
  • No

Breaking changes (If your feature is breaking/missing something please mention pending tickets)

  • Yes
  • No

Is Development Tested?

  • Yes
  • No

Tested in staging?

  • Yes
  • No

Add relevant Screenshot below ( e.g test coverage etc. )

demo
demo.mp4

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Feb 13, 2026

Deploying www-rds with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7e1e72e
Status:⚡️  Build in progress...

View logs

@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR adds edit mode functionality to the application form, allowing users to modify existing pending applications. It renames the phone number field for consistency, converts static storage key properties to getters across form steps, and integrates API-driven data loading and submission for the edit workflow.

Changes

Cohort / File(s) Summary
Edit Mode in Detail Header
app/components/application/detail-header.hbs, app/components/application/detail-header.js
Added isEditAllowed computed property that blocks editing when status is 'accepted' or 'rejected'; made Edit button conditional on this flag; enhanced editApplication() to show error toast when disallowed or navigate to join route with edit and dev params.
Storage Key Property Refactoring
app/components/new-join-steps/new-step-two.js, new-step-three.js, new-step-four.js, new-step-five.js
Converted storageKey field initialization to getter methods across all form step components, returning the same step-specific constant values.
Phone Number Field Rename
app/components/new-join-steps/new-step-four.hbs, new-step-four.js, app/constants/new-join-form.js
Renamed phone field key from phoneNo to phoneNumber in template binding, validation rules, and error messages for naming consistency.
Edit Mode Feature in Stepper
app/components/new-stepper.js
Added editMode and applicationId getters; introduced loadExistingData() to fetch and populate existing application data into localStorage; enhanced handleSubmit() to use PATCH for updates (edit mode) with filtered payload, defaulting to POST for creation; added edit mode initialization in constructor.
Application API and Constants
app/constants/apis.js
Added UPDATE_APPLICATION_URL(applicationId) export for constructing dynamic update endpoints.
Controller and Service Edit Support
app/controllers/join.js, app/services/onboarding.js
Extended join controller with edit tracked property, updated query params, added isEditMode getter, and default step logic for edit flows; enhanced onboarding service with editDataLoaded flag and populateLocalStorageFromApplication() method to map server data into step-specific storage structures.
Template and Route Integration
app/templates/join.hbs
Updated StatusCard rendering to exclude display when in edit mode; passed new @edit argument to NewStepper component.
Test Updates
tests/integration/components/application/detail-header-test.js, tests/integration/components/new-stepper-test.js, tests/unit/controllers/join-test.js
Added service stubs (OnboardingStub, LoginStub, JoinApplicationTermsStub) for test harness; updated test fixtures to use phoneNumber key; added integration tests validating edit data loading, PATCH submission in edit mode, and navigation behavior; expanded join controller queryParams test expectations.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DetailHeader as Detail Header<br/>(Component)
    participant JoinController as Join<br/>(Controller)
    participant NewStepper as New Stepper<br/>(Component)
    participant OnboardingService as Onboarding<br/>(Service)
    participant API as Backend API

    User->>DetailHeader: Click Edit Button
    alt isEditAllowed == false
        DetailHeader->>User: Show error toast
    else isEditAllowed == true
        DetailHeader->>JoinController: Navigate to join route<br/>with edit=true, dev=true
        JoinController->>JoinController: Set edit flag<br/>isEditMode = true
        JoinController->>NewStepper: Pass `@edit`=true
        NewStepper->>NewStepper: Detect editMode
        NewStepper->>OnboardingService: Call loadExistingData()
        OnboardingService->>API: Fetch application details
        API-->>OnboardingService: Return application data
        OnboardingService->>OnboardingService: Map data to step storage<br/>populateLocalStorageFromApplication()
        OnboardingService->>OnboardingService: Set editDataLoaded=true
        User->>NewStepper: Edit form fields & Submit
        NewStepper->>OnboardingService: Collect application data<br/>filtered by EDIT_MODE_ALLOWED_FIELDS
        NewStepper->>API: Send PATCH request<br/>UPDATE_APPLICATION_URL
        API-->>NewStepper: Return 200 success
        NewStepper->>JoinController: Navigate to<br/>applications.detail
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • iamitprakash
  • Suvidh-kaushik
  • AnujChhikara

Poem

🐰 A rabbit hops through forms with glee,
Edits pending apps so they're free,
Phone numbers renamed, storage getters neat,
PATCH requests make the flow complete—
Pending apps now dance in edit mode, la dee dee! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 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 (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: integrate patch API to allow edit application' is directly related to the main change in the changeset, which implements PATCH API integration for editing applications across multiple components and services.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into develop
Description check ✅ Passed The pull request description clearly addresses the main objective: integrating PATCH /application API for edit application functionality, and it references issue #1141.

✏️ 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 feat/edit-application

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

❤️ Share

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

@MayankBansal12 MayankBansal12 marked this pull request as ready for review February 16, 2026 23:23
Copy link

@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: 10

Caution

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

⚠️ Outside diff range comments (2)
app/components/new-join-steps/new-step-four.js (1)

22-24: 🧹 Nitpick | 🔵 Trivial

Pre-existing: hardcoded 'newStepOneData' should use STEP_DATA_STORAGE_KEY.stepOne.

Since this file already imports STEP_DATA_STORAGE_KEY, the hardcoded string on Line 23 should be replaced for consistency — especially given the PR-wide effort to standardize storage key access.

♻️ Proposed fix
   get userRole() {
     const stepOneData = JSON.parse(
-      localStorage.getItem('newStepOneData') || '{}',
+      localStorage.getItem(STEP_DATA_STORAGE_KEY.stepOne) || '{}',
     );
     return stepOneData.role || '';
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/new-join-steps/new-step-four.js` around lines 22 - 24, Replace
the hardcoded storage key string used when reading step one data with the
standardized constant: change the localStorage.getItem call that populates
stepOneData to use STEP_DATA_STORAGE_KEY.stepOne instead of 'newStepOneData'
(locate usage in new-step-four.js where stepOneData is defined and the call to
localStorage.getItem occurs).
tests/integration/components/application/detail-header-test.js (1)

67-80: 🧹 Nitpick | 🔵 Trivial

Consider asserting that the edit button is hidden when status is 'accepted'.

This test sets status: 'accepted' and verifies the nudge button is disabled, but doesn't assert that the edit button is absent. Since isEditAllowed returns false for 'accepted', adding assert.dom('[data-test-button="edit-button"]').doesNotExist() would strengthen coverage for the new conditional rendering.

💚 Proposed addition
     assert.dom('[data-test-button="nudge-button"]').hasAttribute('disabled');
+    assert.dom('[data-test-button="edit-button"]').doesNotExist();
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/components/application/detail-header-test.js` around lines
67 - 80, The test "it disables nudge button when status is not pending" should
also assert that the edit button is hidden for non-editable statuses; update the
test in tests/integration/components/application/detail-header-test.js (the test
block with the application having status: 'accepted') to add an assertion that
the edit button does not exist (e.g.,
assert.dom('[data-test-button="edit-button"]').doesNotExist()), referencing the
Application::DetailHeader component rendering and the fact that isEditAllowed
should be false for 'accepted' status.
🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@app/components/new-join-steps/new-step-four.js`:
- Around line 22-24: Replace the hardcoded storage key string used when reading
step one data with the standardized constant: change the localStorage.getItem
call that populates stepOneData to use STEP_DATA_STORAGE_KEY.stepOne instead of
'newStepOneData' (locate usage in new-step-four.js where stepOneData is defined
and the call to localStorage.getItem occurs).

In `@app/components/new-stepper.js`:
- Around line 74-200: The loadExistingData method in NewStepper must mark
onboarding.editDataLoaded=true to avoid the controller's loading getter (in
app/controllers/join.js) staying true and blocking rendering; update the end of
the try block in loadExistingData (after setting localStorage and
this.isValid/preValid) to set this.onboarding.editDataLoaded = true (or call a
small helper e.g., this.markEditDataLoaded()) so the controller's loading check
(isEditMode && !this.onboarding.editDataLoaded) can become false and the stepper
can mount.
- Around line 57-65: The constructor uses a truthy check (if (this.args.edit))
while the editMode getter uses strict equality (this.args.edit === true), which
can lead to inconsistent behavior if a non-boolean value like "true" is passed;
update the constructor to use the same strict boolean check (or call the
editMode getter) so both checks align—e.g., replace the truthy if in the
constructor with if (this.args.edit === true) or if (this.editMode) and keep the
editMode getter as the single source of truth; ensure the branch that calls
loadExistingData() references those symbols (this.args.edit / editMode /
loadExistingData) consistently.
- Around line 155-157: The forEach callback currently uses an expression-bodied
arrow that returns a value due to "!value && delete stepFourData[key]" which
static analysis warns about; change the callback in
Object.entries(stepFourData).forEach(...) to a block-bodied function and perform
the delete imperatively (e.g., if (!value) delete stepFourData[key]) so the
callback does not return a value; reference the existing call to
Object.entries(stepFourData).forEach and the stepFourData variable when making
the edit.
- Around line 19-29: The allow-list EDIT_MODE_ALLOWED_FIELDS currently contains
'professional' which never exists in the flattened object produced by
collectApplicationData (it spreads stepTwoData as top-level keys like skills and
college), so professional fields are excluded from edit payloads; fix this by
either adding 'skills' and 'college' to EDIT_MODE_ALLOWED_FIELDS or by modifying
collectApplicationData to assemble a professional object from stepTwoData (e.g.,
{ professional: { skills, college, ... } }) before the filtering step so the
existing 'professional' entry matches; update the code paths that rely on
EDIT_MODE_ALLOWED_FIELDS and collectApplicationData to remain consistent (refer
to EDIT_MODE_ALLOWED_FIELDS, collectApplicationData, and stepTwoData).
- Around line 305-318: The PATCH handler may receive a response without
application.id, causing newApplicationId to be undefined and breaking
router.replaceWith; update the logic around newApplicationId (the const
newApplicationId = data.application?.id) to fall back to
this.onboarding.applicationData?.id when isEditMode is true or when
data.application?.id is missing, then call
this.router.replaceWith('applications.detail', <the resolved id>); ensure you
still clearAllStepData() and set this.isSubmitting = false as before.

In `@app/services/onboarding.js`:
- Line 232: The hardcoded storage key 'isValid' in the call to
setLocalStorageItem should be replaced with a named constant to match the
existing pattern (like STEP_DATA_STORAGE_KEY); declare a descriptive constant
(e.g., IS_VALID_STORAGE_KEY) near the other storage keys and use that constant
in the setLocalStorageItem call inside the function where setLocalStorageItem is
used to persist step state so future refactors won't miss the key.
- Around line 13-17: Remove the duplicated APPLICATION_STATUS_TYPES object from
app/services/onboarding.js and import the shared constant from
app/constants/join.js instead; update the top of onboarding.js to add an import
for APPLICATION_STATUS_TYPES and replace any local references to the literal
object with the imported APPLICATION_STATUS_TYPES to ensure a single source of
truth.
- Around line 144-147: getApplicationDetails() currently calls
populateLocalStorageFromApplication() unconditionally for pending applications,
which overwrites user-entered form data; change the logic in the
constructor/getApplicationDetails() so populateLocalStorageFromApplication()
runs only when the service is in edit mode (detect ?edit=true or an explicit
this.editMode flag) or when localStorage has no existing application data (check
the specific keys your app uses before overwriting). Also ensure editDataLoaded
is set appropriately (set it before or only after a deliberate edit-mode
population) so it can guard against accidental population; references to update:
getApplicationDetails(), populateLocalStorageFromApplication(), editDataLoaded,
this.applicationData, and APPLICATION_STATUS_TYPES.pending.

In `@tests/integration/components/application/detail-header-test.js`:
- Around line 67-80: The test "it disables nudge button when status is not
pending" should also assert that the edit button is hidden for non-editable
statuses; update the test in
tests/integration/components/application/detail-header-test.js (the test block
with the application having status: 'accepted') to add an assertion that the
edit button does not exist (e.g.,
assert.dom('[data-test-button="edit-button"]').doesNotExist()), referencing the
Application::DetailHeader component rendering and the fact that isEditAllowed
should be false for 'accepted' status.

In `@tests/integration/components/new-stepper-test.js`:
- Around line 324-334: The test assumes this.fetchStub.lastCall is the
submission fetch but loadExistingData (called when NewStepper is rendered with
`@edit`={{true}}) also issues a fetch, so make the assertion explicit: verify
this.fetchStub.callCount (or use this.fetchStub.getCall(index)) to ensure you
inspect the fetch made by the submit action. Update the test around the submit
block to assert the stub call count after
click('[data-test-button="submit-review"]') and replace this.fetchStub.lastCall
with this.fetchStub.getCall(<submissionIndex>) (or assert callCount === expected
and then use lastCall) to target the PATCH request to /applications/app-123 from
the submit flow.
- Around line 312-322: Replace the fragile setTimeout-based wait in the test for
the NewStepper component with a deterministic wait using settled() from
`@ember/test-helpers`: remove the await new Promise(resolve => setTimeout(resolve,
100)) call and replace it with await settled() so the test waits for all async
behavior (including NewStepper's loadExistingData) to finish before reading
localStorage (STEP_DATA_STORAGE_KEY.stepOne) and asserting city/state/role;
settled is already imported at the top of the file.

Copy link
Member Author

Choose a reason for hiding this comment

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

updated this expectation since a new query param is added for edit

AnujChhikara
AnujChhikara previously approved these changes Feb 19, 2026
* test: add tests for base step

* test: add test for new stepper for edit mode

* fix: replace college with institution
@iamitprakash iamitprakash merged commit ec7fc39 into develop Feb 19, 2026
3 of 4 checks passed
@iamitprakash iamitprakash deleted the feat/edit-application branch February 19, 2026 18:47
@MayankBansal12 MayankBansal12 mentioned this pull request Feb 21, 2026
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants