Repository: cal-itp/benefits

Issue:
New screen `Eligibility error` for Agency Card flow only
This screen replaces the "You may not be eligible" page, but  only for Agency Card flows.

The idea is that it is more likely for the user's input to have not matched the exact formatting in the system rather than they're not actually eligible.

If they are actually not eligible, they can contact the transit agency.

![image](https://github.com/cal-itp/benefits/assets/25497886/04f351da-885a-480d-a42d-fc5eb4afb635)


## Acceptance Criteria

- [x] Spacing is 24px for icon to headline to body to agency info
- [x] Spacing is 64px above call-to-action button
- [x] CTA reloads eligibility confirmation page with no limit on how many times the user inputs that information



Discussion:

Resolving patch:
diff --git a/benefits/core/migrations/0008_eligibilityverifier_unverified_template.py b/benefits/core/migrations/0008_eligibilityverifier_unverified_template.py
new file mode 100644
--- /dev/null
+++ b/benefits/core/migrations/0008_eligibilityverifier_unverified_template.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.3 on 2024-04-24 21:01
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("core", "0007_eligibilitytype_enrollment_index_template"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="eligibilityverifier",
+            name="unverified_template",
+            field=models.TextField(default="eligibility/unverified.html"),
+        ),
+    ]
diff --git a/benefits/core/models.py b/benefits/core/models.py
--- a/benefits/core/models.py
+++ b/benefits/core/models.py
@@ -178,6 +178,7 @@ class EligibilityVerifier(models.Model):
     start_template = models.TextField(null=True, blank=True)
     # reference to a form class used by this Verifier, e.g. benefits.app.forms.FormClass
     form_class = models.TextField(null=True, blank=True)
+    unverified_template = models.TextField(default="eligibility/unverified.html")
     help_template = models.TextField(null=True, blank=True)
 
     class Meta:
diff --git a/benefits/eligibility/views.py b/benefits/eligibility/views.py
--- a/benefits/eligibility/views.py
+++ b/benefits/eligibility/views.py
@@ -24,7 +24,6 @@
 
 TEMPLATE_START = "eligibility/start.html"
 TEMPLATE_CONFIRM = "eligibility/confirm.html"
-TEMPLATE_UNVERIFIED = "eligibility/unverified.html"
 
 
 @decorator_from_middleware(RecaptchaEnabled)
@@ -119,6 +118,7 @@ def confirm(request):
 
     # GET from an unverified user, present the form
     if request.method == "GET":
+        session.update(request, origin=reverse(ROUTE_CONFIRM))
         return TemplateResponse(request, TEMPLATE_CONFIRM, context)
     # POST form submission, process form data, make Eligibility Verification API call
     elif request.method == "POST":
@@ -171,4 +171,4 @@ def unverified(request):
 
     analytics.returned_fail(request, types_to_verify)
 
-    return TemplateResponse(request, TEMPLATE_UNVERIFIED)
+    return TemplateResponse(request, verifier.unverified_template)


Test patch:
diff --git a/tests/cypress/specs/courtesy-cards.cy.js b/tests/cypress/specs/courtesy-cards.cy.js
--- a/tests/cypress/specs/courtesy-cards.cy.js
+++ b/tests/cypress/specs/courtesy-cards.cy.js
@@ -26,7 +26,7 @@ describe("Courtesy Cards", () => {
     cy.get("#name").type(users.ineligible.name);
     cy.get("#form-eligibility-verification button[type='submit']").click();
 
-    cy.contains("could not be verified");
+    cy.contains("may not have been entered correctly");
   });
 
   it("Validates an empty name field", () => {
diff --git a/tests/pytest/eligibility/test_views.py b/tests/pytest/eligibility/test_views.py
--- a/tests/pytest/eligibility/test_views.py
+++ b/tests/pytest/eligibility/test_views.py
@@ -12,7 +12,6 @@
     ROUTE_ENROLLMENT,
     ROUTE_UNVERIFIED,
     TEMPLATE_CONFIRM,
-    TEMPLATE_UNVERIFIED,
 )
 
 import benefits.eligibility.views
@@ -343,4 +342,4 @@ def test_unverified(client, mocked_analytics_module):
 
     mocked_analytics_module.returned_fail.assert_called_once()
     assert response.status_code == 200
-    assert response.template_name == TEMPLATE_UNVERIFIED
+    assert response.template_name == "eligibility/unverified.html"