Skip to content

#5594 - New unified data path for appeals and forms + non punitive (Student UI)#5767

Merged
andrewsignori-aot merged 21 commits intomainfrom
feature/#5594-new-unified-data-path-for-appeals-and-forms-student-ui
Feb 13, 2026
Merged

#5594 - New unified data path for appeals and forms + non punitive (Student UI)#5767
andrewsignori-aot merged 21 commits intomainfrom
feature/#5594-new-unified-data-path-for-appeals-and-forms-student-ui

Conversation

@andrewsignori-aot
Copy link
Copy Markdown
Collaborator

@andrewsignori-aot andrewsignori-aot commented Feb 12, 2026

  • New Student UI for forms submissions, consolidating appeals and forms into a single path.

New Forms Menu

  • Renamed the top menu from "Appeals" to "Forms" 1️⃣.

Submission Tab

  • Created two different sections to display the different form categories introduced in the previous DB changes.
    • 2️⃣ Standard forms section to create a clear distinction from the "Appeals", as per business request.
    • 3️⃣ List of forms under the category Student form on sims.dynamic_form_configurations.form_category. Currently, has_application_scope and allow_bundled_submission are not being taken into consideration by the UI but the backend will use them in a generic way, allowing the functionality to be extended to these forms, following the same from the appeals.
    • 4️⃣ Appeals forms section to create a clear distinction from the "Forms", as per business request.
    • 5️⃣ Eligible applications following the same approach from the current appeals.
    • 6️⃣ List of forms under the category Student appeal on sims.dynamic_form_configurations.form_category, that has_application_scope as true and allow_bundled_submission also true.
    • 7️⃣ List of forms under the category Student appeal on sims.dynamic_form_configurations.form_category, that has_application_scope as false and allow_bundled_submission also false.
image
  • Regular Vuetify form validations were used for the selected forms.
  • Content is currently under business review and may be adjusted in upcoming PRs.

Navigation from the Student application

When navigating from the student application, the "Appeas" section will be moved to the top to allow for quick interaction from the user.

image

History Tab

The history tab was refactored based on user feedback about a not clear separation between the appeals.

  • 1️⃣ Filter to display only appeals or forms.
  • 2️⃣ indicates the status of the submission and should display green once is no longer pending, even if the DB status is set as "Declined".
  • 3️⃣ and 4️⃣ Form category type as on DB, dynamically displaying "Student appeal" or "Student form".
  • 5️⃣ Navigates to the submitted form in a read-only view that will also display the decision status for each item.
image

Forms/Appeals Submission View

  • 1️⃣ Allow navigation back to the forms selector page.
  • 2️⃣ Dynamic form category of the submission.
  • 3️⃣ Expand or collapse all panels to allow a quick overview of the decision approvals and navigation to a specific form (having multiple forms fully extended may be too much to follow in the UI).
  • 4️⃣ Form name (form type) from the sims.dynamic_form_configurations.form_type.
  • 5️⃣ Current decision status, if any. Note: the status may not be the most up-to-date since the business would like to have the final status displayed only once the parent submission is completed (to be implemented).
image

Technical Considerations

  • While running locally, use the bool variable under useFeatureToggles to switch between the new and current UI.
    • Please note the toggle is applied only to the top menu, not to the mobile view.
    • Please note the toggle is true for the review and will be false before merge.
  • New Vue views were created under views/student/form-submissions.
    • Current views under views/student/appela should be removed by the end of this effort. Note: appeal-legacy removal to be discussed, but possible.
    • The previous approach to have different views to deal with application vs top menu navigation was dropped, and a query string parameter for the applicationID was adopted instead, trying to simplify the views.

Form.io UI References

  • As much as possible, the idea is to rely on the dynamic configuration ID to render the form.io definitions and to submit the appeals/forms to the API. Going in this direction, the component responsible for rendering the list of form.io definitions (form-submission-items) is now keeping a dynamic ID (form-key) and using it to relate the form submission to its data.

<formio
:form-key="submissionItem.dynamicConfigurationId"
:form-name="submissionItem.formName"
:data="submissionItem.formData"
:read-only="readOnly"
@loaded="formLoaded"
></formio>

Creating New-ish Components

  • Some of the components were reused (duplicated for now), being just adapted and/or simplified as much as possible. For instance, the (form-submission-items kept the idea of being reused for any component that will require the form.io definitions to be rendered as a v-for.

Retrieving Dynamic Forms Configurations from the API

  • The dynamic form configurations to render the list of appeals/forms to the student are being returned from a student-specific endpoint from the new form-submissions controller, which will receive more API endpoints in upcoming PRs.
    • There was a consideration to create a similar endpoint under the dynamic configurations endpoint, but the approach in this PR seems better to support the "forms-submission" as a feature.

@andrewsignori-aot andrewsignori-aot self-assigned this Feb 12, 2026
},
},
setup(props) {
const label = computed(() =>
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Created the "maps" inside the components. The reason we have maps outside the component was to allow reuse, mainly between form.io definition and Vue UI, which is no longer the case in many cases.
If there is a strong feeling that this type of map must be done externally, please let me know, and I will move it.

Copy link
Copy Markdown
Collaborator

@dheepak-aot dheepak-aot Feb 12, 2026

Choose a reason for hiding this comment

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

I also feel that this map must be done outside and also status and label can be an object which is derived at once based on props.status so they can be derived at once.

},
},
setup(props) {
const chipStatus = computed(() => {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Declined = "Declined",
}

export interface FormSubmissionItemApproval {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The DTOs FormSubmissionItemApproval, FormSubmissionItem, FormSubmissionItemSubmitted were based on existing appeals submissions and may be adapted in upcoming PRs once the API is fully connected.

if (props.applicationId) {
try {
application =
await ApplicationService.shared.getApplicationForRequestChange(
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This code remains from the previous solution, but a new solution should be implemented in upcoming PRs.

Copy link
Copy Markdown
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 introduces a new unified Student UI flow for “Forms” that consolidates standard forms and appeals into a single submission/history experience, supported by a new student API endpoint that returns dynamic form configurations by category.

Changes:

  • Added new Student “Forms” pages (selector, submission, history, view) and navigation updates (menu + application summary deep link).
  • Added a new student API controller endpoint to fetch dynamic form configurations for student submissions (forms + appeals).
  • Introduced shared types/DTOs and a mocked web API client/service layer for form submissions.

Reviewed changes

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

Show a summary per file
File Description
sources/packages/web/src/views/student/form-submissions/StudentFormsSelectorFormsSection.vue New “Standard forms” selection section.
sources/packages/web/src/views/student/form-submissions/StudentFormsSelectorAppealsSection.vue New “Appeals” selection section with application-scoped and standalone appeal modes.
sources/packages/web/src/views/student/form-submissions/StudentFormsSelector.vue Orchestrates selector sections and loads available configurations.
sources/packages/web/src/views/student/form-submissions/StudentFormsHistory.vue New submission history UI with category filtering and navigation to read-only view.
sources/packages/web/src/views/student/form-submissions/StudentForms.vue New tabbed container page for Submissions/History.
sources/packages/web/src/views/student/form-submissions/FormSubmissionView.vue Read-only view for a submitted form submission and its items/decisions.
sources/packages/web/src/views/student/form-submissions/FormSubmission.vue New submission view to render one-or-many Form.io forms and submit them.
sources/packages/web/src/views/student/StudentApplicationSummary.vue Deep-link from application summary to new Forms selector when feature toggle is enabled.
sources/packages/web/src/views/student/AppStudent.vue Replaces “Appeals” menu with “Forms” menu under feature toggle.
sources/packages/web/src/types/index.ts Exposes new form submission contract types.
sources/packages/web/src/types/contracts/FormSubmissionContracts.ts Adds shared enums/interfaces for form submissions in the web app.
sources/packages/web/src/types/AppRoutes.ts Adds new student routes for Forms selector/history/submit/view.
sources/packages/web/src/services/http/dto/index.ts Exposes new FormSubmission DTOs via the DTO barrel export.
sources/packages/web/src/services/http/dto/FormSubmission.dto.ts Adds web DTOs for configurations + submission summary/details.
sources/packages/web/src/services/http/FormSubmissionsApi.ts Adds HTTP client for form submissions (mocked summary/details).
sources/packages/web/src/services/http/ApiClient.ts Registers FormSubmissionsApi in the shared API client.
sources/packages/web/src/services/FormSubmissionsService.ts Adds service wrapper for form submission API calls.
sources/packages/web/src/router/StudentRoutes.ts Wires new Forms routes into the student router.
sources/packages/web/src/constants/routes/RouteConstants.ts Adds route name constants for Forms flows.
sources/packages/web/src/composables/useFeatureToggles.ts Adds a local feature toggle for enabling the new Forms menu/flow.
sources/packages/web/src/composables/index.ts Exports the new feature toggles composable.
sources/packages/web/src/components/generic/formio.vue Extends the loaded event to include a formKey to correlate forms.
sources/packages/web/src/components/generic/StatusChipFormSubmissionDecision.vue New chip component for per-item decision status.
sources/packages/web/src/components/generic/StatusChipFormSubmission.vue New chip component for overall submission status (pending vs completed).
sources/packages/web/src/components/form-submissions/FormSubmissionItems.vue New reusable component to render multiple Form.io forms and validate/submit them together.
sources/packages/backend/apps/api/src/services/dynamic-form-configuration/dynamic-form-configuration.service.ts Adds ability to retrieve dynamic form configurations by form category and exposes extra fields.
sources/packages/backend/apps/api/src/route-controllers/index.ts Exports the new form-submission controller and DTOs.
sources/packages/backend/apps/api/src/route-controllers/form-submission/models/form-submission.dto.ts Adds API DTOs for returning student submission form configurations.
sources/packages/backend/apps/api/src/route-controllers/form-submission/form-submission.students.controller.ts New students controller endpoint to return configurations for student forms/appeals.
sources/packages/backend/apps/api/src/app.students.module.ts Registers the new students controller in the students module.

Comment thread sources/packages/web/src/services/http/FormSubmissionApi.ts
Comment thread sources/packages/web/src/views/student/form-submissions/StudentFormsSelector.vue Outdated
const programYearId = options?.programYearId ?? null;
const offeringIntensity = options?.offeringIntensity ?? null;
const dynamicForm = this.dynamicFormConfigurations.find(
return this.dynamicFormConfigurations.find(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As we are returning the complete object now, can we ensure to return a immutable copy?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

To ensure we are on the same page, by "immutable copy" you mean to return a copy of the object, similar to what is done for DTOs, but between services to prevent the consumer from updating the cache data?
Or, would it be something like Object.freeze that should have been done during the loadAllDynamicFormConfigurations?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

something like object.freeze to not allow the consumer to change the values, till now it is not required in loadAllDynamicFormConfigurations as only a string was exposed from the service but from the moment we return the object it has the potential to be modified at consumer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I can change it to be safe with the current implementation, but having this data in-memory was temporary. We must move this cached data to Redis, first ensuring Redis is stable and API will not crash if Redis is down.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ha ha yes. For APIs we can also use the nestJS cache if we have issues with redis.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Did the shallow freeze for the object and the array 😉

Comment on lines +93 to +95
return this.dynamicFormConfigurations.filter((dynamicFormConfiguration) =>
formCategories.includes(dynamicFormConfiguration.formCategory),
);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment thread sources/packages/web/src/components/generic/formio.vue Outdated
@@ -0,0 +1,164 @@
<!-- Allow the student to submit a new form. -->
<template>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wanted share a suggestion here to bring the submission and history to a sideNav and each side nav having form categories as tab to organize the form submission life-cycle. Outside this PR we can discuss to see if this approach can simplify the view and be feasible as well.

Image

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Please feel free to bring it to the biz and ask if they are willing to move forward with some UI reorganization.
The suggestion seems mostly about navigation, which would allow the current components being built to still be useful 😉

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not just the navigation was the intention. When I saw the form categories re-ordered based on where it came from and usage of filters to show form history vs appeals history, I started feeling like each form category can have it's own tab.

It can be either achieved by side nav or sub tabs, but then intention is to have a seperate area for a form category.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I am not feeling 100% about changing the order of those panels.
I am willing to get some biz feedback once presented to users.

@dheepak-aot
Copy link
Copy Markdown
Collaborator

Great start and thanks for the early PR to get feedback. Added some comments and suggestions.

(form) => !form.hasApplicationScope && !form.allowBundledSubmission,
);
},
{ deep: true },
Copy link
Copy Markdown
Collaborator

@sh16011993 sh16011993 Feb 13, 2026

Choose a reason for hiding this comment

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

Do we need { deep: true } here? The formsConfigurations in the current context is not having the properties modified individually. The object is assigned as a whole.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I will review along upcming PRs 😉
What you just said makes sense. Let me give it a try and put more tests into it.

Copy link
Copy Markdown
Collaborator

@sh16011993 sh16011993 left a comment

Choose a reason for hiding this comment

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

Superb work @andrewsignori-aot 👍

@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

Backend Unit Tests Coverage Report

Totals Coverage
Statements: 20.39% ( 4428 / 21717 )
Methods: 9.92% ( 262 / 2640 )
Lines: 24.51% ( 3780 / 15420 )
Branches: 10.56% ( 386 / 3657 )

@github-actions
Copy link
Copy Markdown

E2E Workflow Workers Coverage Report

Totals Coverage
Statements: 75.41% ( 1055 / 1399 )
Methods: 79.31% ( 115 / 145 )
Lines: 78.79% ( 769 / 976 )
Branches: 61.51% ( 171 / 278 )

@github-actions
Copy link
Copy Markdown

E2E Queue Consumers Coverage Report

Totals Coverage
Statements: 85.68% ( 1616 / 1886 )
Methods: 85% ( 187 / 220 )
Lines: 88.64% ( 1287 / 1452 )
Branches: 66.36% ( 142 / 214 )

Copy link
Copy Markdown
Collaborator

@dheepak-aot dheepak-aot left a comment

Choose a reason for hiding this comment

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

Thanks for making the changes. Looks good 👍

@github-actions
Copy link
Copy Markdown

E2E SIMS API Coverage Report

Totals Coverage
Statements: 78.15% ( 9115 / 11663 )
Methods: 77.38% ( 1064 / 1375 )
Lines: 82.4% ( 6612 / 8024 )
Branches: 63.56% ( 1439 / 2264 )

@andrewsignori-aot andrewsignori-aot added this pull request to the merge queue Feb 13, 2026
Merged via the queue into main with commit df084dd Feb 13, 2026
22 checks passed
@andrewsignori-aot andrewsignori-aot deleted the feature/#5594-new-unified-data-path-for-appeals-and-forms-student-ui branch February 13, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SIMS-Api SIMS-Api Student Student Features Web portal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants