[Employer Sync 6.5] Employer login page UI/UX redesign (Bootstrap only)
TL;DR: One-card, Bootstrap-only redesign of the employer login page from the Senior UI/UX review — layout table, ASCII wireframe, three login states, final copy strings, and a prioritised change list. No custom CSS, no new dependencies.
Context
The current employer login page is two stacked 400px cards — Employer Portal (JodGig) and Employer Login (JodBoard). Layout and copy together reinforce the wrong "you have two accounts" mental model. Four brand names appear and none are explained: JodBoard, JodGig, Gig, JodApp.
After the sync lands, employers have one account. The page must say that — visually as much as in words.
Problem
Concrete issues found during the Senior UI/UX review:
- The two-card layout says "pick one of your two accounts". Migrated employers have one.
- The heading says
Employer Login (JodBoard); the button saysLogin to JodBoard; the meta title saysSign In; brand names are inconsistent. - The footer pushes signup (
btn btn-link"Sign up here") as the most prominent secondary action. The right one for the migrated-employer majority is "Forgot password?". - Errors collapse to a single generic message — a user with the correct password is told their password is wrong.
Direction
One card, one clear primary action, all stock Bootstrap / react-bootstrap. No custom CSS, no new dependencies.
Layout
| Region | Component | Classes |
|---|---|---|
| Page frame | Container | d-flex flex-column justify-content-center align-items-center, style={{ minHeight: '100vh' }} |
| Card | Card | shadow-sm, style={{ width: '400px' }}, mb-3 |
| Card body | Card.Body | p-4 |
| Brand mark | <img src="/images/text-logo.png" /> | style={{ height: 32 }}, wrapper mb-3 |
| Heading | Card.Title as h1 | h4 fw-bold mb-1 |
| Sub-text | Card.Subtitle / <p> | small text-muted mb-4 |
| State banner | Alert (conditional) | variant per state — see 6.3 |
| Form | IdentitiesSessionForm | unchanged component |
| Gig pointer | Alert variant="light" border | small mb-0 d-flex align-items-start |
| Footer | Card.Footer | text-center small text-muted |
ASCII wireframe
┌──────────────────────────────────────────────┐
│ [ Jod logo ] │
│ Log in to JodApp │
│ Post and manage your job ads. │
│ │
│ ┌────────────────────────────────────────┐ │ (state banner, conditional)
│ │ (i) We are still setting up your │ │
│ │ account. Please try again shortly. │ │
│ └────────────────────────────────────────┘ │
│ │
│ Email address or phone number │
│ [ ________________________________ ] │
│ Password │
│ [ ____________________________ 👁 ] │
│ Forgot password? │
│ [ Log in (full width) ] │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ (i) Managing gig (short-term) jobs? │ │ (gig pointer, light)
│ │ Go to gig.jodapp.com │ │
│ └────────────────────────────────────────┘ │
├──────────────────────────────────────────────┤
│ New to JodApp? Create an employer account │ (Card.Footer, demoted)
└──────────────────────────────────────────────┘
Three login states
Driven by API error codes from 6.3 (not by guessing on the page) — see 6.3 for the typed errors:
- (a) Normal — no banner. Inline field error on credential failure.
- (b) Provisioning (
code: 'migration_in_progress', HTTP 409) —Alert variant="info", headingSetting up your account, bodyWe are getting your account ready. This takes a minute. Please wait, then log in again.Optional disabled-submit + spinner for ~60s. - (c) Needs attention (
code: 'account_not_verified', HTTP 403, only if exposed) —Alert variant="warning", headingOne more step to access your account, bodyFor your security, please set your password before you log in. It only takes a minute., buttonSet my passwordlinking to/forgot-password.
Final copy strings
- Meta title:
Employer Log In — JodApp - Heading:
Log in to JodApp - Description:
Post and manage your job ads. Use the same email and password as your existing account. - Submit:
Log in - Gig pointer:
Managing gig (short-term) jobs? Go to {gigPortalHostname} - Footer:
New to JodApp? Create an employer account - Inline error:
Invalid email, phone number, or password. - Connection error (existing toast path):
Cannot connect right now. Please check your internet and try again.
Prioritised change list
| # | Change | Effort |
|---|---|---|
| 1 | Fix setError('email', …) → setError('identifier', …) | Small |
| 2 | Rewrite the heading, description, submit, gig pointer, footer, and error strings | Small |
| 3 | Delete the standalone "Employer Portal (JodGig)" card; collapse to one card | Medium |
| 4 | Demote signup to Card.Footer; surface "Forgot password?" as the recovery path | Small |
| 5 | Add loginState + render banners (b) and (c) from typed error codes | Medium |
| 6 | Standardise heading markup and spacing per the layout table; add shadow-sm, brand logo | Small |
Items 1–4 and 6 are self-contained and can ship immediately. Item 5 needs the backend codes from 6.3 / 5.2; until those land, treat every failure as state (a).
Acceptance
- One-card layout shipped; the JodGig card is gone.
- All copy strings match the list above.
- Stock Bootstrap / react-bootstrap classes only — no custom CSS, no new dependencies.
- Three login states render per 6.3 once the backend codes are in place.
- The page passes manual review against the wireframe above.
Depends on
- 6.1 (the copy slice)
- 6.3 (the typed error codes)