diff --git a/app/components/badge_component.rb b/app/components/badge_component.rb index 6f5f8a75c2c..17480c836c9 100644 --- a/app/components/badge_component.rb +++ b/app/components/badge_component.rb @@ -4,6 +4,8 @@ class BadgeComponent < BaseComponent ICONS = %i[ lock check_circle + warning + info ].to_set.freeze attr_reader :icon, :tag_options diff --git a/app/components/badge_component.scss b/app/components/badge_component.scss index 2dbbf933fc0..68ad4c8af97 100644 --- a/app/components/badge_component.scss +++ b/app/components/badge_component.scss @@ -5,3 +5,17 @@ .lg-verification-badge .usa-icon { margin-right: units(1); } + +.border-warning { + border-color: color('warning'); + .usa-icon { + color: color('warning'); + } +} + +.border-info { + border-color: color('info'); + .usa-icon { + color: color('info'); + } +} diff --git a/app/components/badge_tooltip_component.rb b/app/components/badge_tooltip_component.rb new file mode 100644 index 00000000000..d2ee2dc638c --- /dev/null +++ b/app/components/badge_tooltip_component.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class BadgeTooltipComponent < BaseComponent + attr_reader :tag_options, :tooltip_text + + def initialize(tooltip_text:, **tag_options) + @tag_options = tag_options + @tooltip_text = tooltip_text + end + + def call + content_tag( + :'lg-badge-tooltip', + badge_content, + 'tooltip-text': tooltip_text, + ) + end + + def badge_content + render BadgeComponent.new( + **tag_options, + type: :badge, + ).with_content(content) + end +end diff --git a/app/components/badge_tooltip_component.scss b/app/components/badge_tooltip_component.scss new file mode 100644 index 00000000000..d48ee770740 --- /dev/null +++ b/app/components/badge_tooltip_component.scss @@ -0,0 +1,10 @@ +@use 'uswds-core' as *; +@forward 'usa-tooltip'; + +// Workaround for tooltip issue preventing buttons from showing as full width at small screen sizes. +// See: https://github.com/uswds/uswds/issues/5273 +.usa-tooltip { + @include at-media-max('mobile-lg') { + display: block; + } +} diff --git a/app/components/badge_tooltip_component.ts b/app/components/badge_tooltip_component.ts new file mode 100644 index 00000000000..b9d5d01b521 --- /dev/null +++ b/app/components/badge_tooltip_component.ts @@ -0,0 +1 @@ +import '@18f/identity-badge-tooltip/badge-tooltip-element'; diff --git a/app/javascript/packages/badge-tooltip/README.md b/app/javascript/packages/badge-tooltip/README.md new file mode 100644 index 00000000000..7091ca06961 --- /dev/null +++ b/app/javascript/packages/badge-tooltip/README.md @@ -0,0 +1,23 @@ +# `@18f/identity-badge-tooltip` + +Custom element for a badge component. + +## Usage + +### Custom Element + +Importing the element will register the `` custom element: + +```ts +import '@18f/identity-badge-tooltip/badge-tooltip-element'; +``` + +```html + + +
+ +
+
+
+``` \ No newline at end of file diff --git a/app/javascript/packages/badge-tooltip/badge-tooltip-element.spec.ts b/app/javascript/packages/badge-tooltip/badge-tooltip-element.spec.ts new file mode 100644 index 00000000000..62f0976fad7 --- /dev/null +++ b/app/javascript/packages/badge-tooltip/badge-tooltip-element.spec.ts @@ -0,0 +1,27 @@ +import { getByText } from '@testing-library/dom'; +import userEvent from '@testing-library/user-event'; +import { computeAccessibleDescription } from 'dom-accessibility-api'; +import './badge-tooltip-element'; + +describe('BadgeTooltipElement', () => { + function createAndConnectElement({ tooltipText = '' } = {}) { + const element = document.createElement('lg-badge-tooltip'); + element.setAttribute('tooltip-text', tooltipText); + element.setAttribute('tooltip-text', 'Your identity has been verified'); + element.innerHTML = '
Verified
'; + document.body.appendChild(element); + return element; + } + + it('shows a tooltip when mouseover, until mouseout', async () => { + const element = createAndConnectElement(); + + const badge = getByText(element, 'Verified'); + + await userEvent.hover(badge); + expect(computeAccessibleDescription(badge)).to.be.equal('Your identity has been verified'); + + await userEvent.unhover(badge); + expect(computeAccessibleDescription(badge)).to.be.equal(''); + }); +}); diff --git a/app/javascript/packages/badge-tooltip/badge-tooltip-element.ts b/app/javascript/packages/badge-tooltip/badge-tooltip-element.ts new file mode 100644 index 00000000000..c00e8aa9be8 --- /dev/null +++ b/app/javascript/packages/badge-tooltip/badge-tooltip-element.ts @@ -0,0 +1,65 @@ +import { tooltip } from '@18f/identity-design-system'; + +class BadgeTooltipElement extends HTMLElement { + badge: HTMLElement; + + connectedCallback() { + this.badge = this.querySelector('.usa-tooltip')!; + + this.setUpTooltip(); + this.badge.addEventListener('mouseover', () => this.handleHover()); + } + + /** + * Retrieves the text to be shown in the tooltip. + */ + get tooltipText(): string { + return this.getAttribute('tooltip-text')!; + } + + /** + * Initializes the tooltip element. + */ + setUpTooltip() { + const { tooltipBody } = tooltip.setup(this.badge); + + // A default USWDS tooltip will always be visible when the badge is hovered over. + // To ensure the tooltip content is read when made visible, + // change its contents to a live region. + tooltipBody.setAttribute('aria-live', 'polite'); + } + + /** + * Handles the badge mouseover. + */ + handleHover() { + this.showTooltip(); + } + + /** + * Displays confirmation tooltip and binds event to dismiss tooltip on mouseout. + */ + showTooltip() { + const { trigger, body } = tooltip.getTooltipElements(this.badge); + body.textContent = this.tooltipText; + tooltip.show(body, trigger, 'top'); + + function hideTooltip() { + body.textContent = ''; + tooltip.hide(body); + } + this.badge.addEventListener('mouseout', hideTooltip, { once: true }); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'lg-badge-tooltip': BadgeTooltipElement; + } +} + +if (!customElements.get('lg-badge-tooltip')) { + customElements.define('lg-badge-tooltip', BadgeTooltipElement); +} + +export default BadgeTooltipElement; diff --git a/app/javascript/packages/badge-tooltip/package.json b/app/javascript/packages/badge-tooltip/package.json new file mode 100644 index 00000000000..c543386110f --- /dev/null +++ b/app/javascript/packages/badge-tooltip/package.json @@ -0,0 +1,11 @@ +{ + "name": "@18f/identity-badge-tooltip", + "version": "1.0.0", + "private": true, + "dependencies": { + "@18f/identity-design-system": "^9.2.0" + }, + "sideEffects": [ + "./badge-tooltip-element.ts" + ] +} diff --git a/app/presenters/account_show_presenter.rb b/app/presenters/account_show_presenter.rb index 109bc1286c5..db8e24459c2 100644 --- a/app/presenters/account_show_presenter.rb +++ b/app/presenters/account_show_presenter.rb @@ -18,7 +18,9 @@ def show_password_reset_partial? end def show_pii_partial? - decrypted_pii.present? || user.identity_verified? + decrypted_pii.present? || user.identity_verified? unless + user.pending_in_person_enrollment.present? || user. + gpo_verification_pending_profile.present? end def show_manage_personal_key_partial? @@ -34,10 +36,36 @@ def show_gpo_partial? user.gpo_verification_pending_profile? end + def show_ipp_partial? + user.pending_in_person_enrollment.present? + end + def showing_any_partials? + show_password_reset_partial? || + show_gpo_partial? || show_ipp_partial? || show_pii_partial? + end + + def showing_alerts? show_service_provider_continue_partial? || - show_password_reset_partial? || - show_gpo_partial? + show_password_reset_partial? + end + + def show_unverified? + show_password_reset_partial? && + (!show_ipp_partial? || !show_gpo_partial?) + end + + def service_provider_or_app_name + if user.identities.count == 0 + APP_NAME + else + user.identities.last.friendly_name + end + end + + def formatted_due_date + user.pending_in_person_enrollment.due_date. + strftime(I18n.t('time.formats.event_date')) end def show_unphishable_badge? @@ -60,6 +88,10 @@ def personal_key_generated_at user.personal_key_generated_at end + def biometric_identity_verification? + user.identity_verified_with_biometric_comparison? + end + def header_personalization return decrypted_pii.first_name if decrypted_pii.present? diff --git a/app/views/accounts/_badges.html.erb b/app/views/accounts/_badges.html.erb index 1dfdaf4f1c0..0b12c8fbc93 100644 --- a/app/views/accounts/_badges.html.erb +++ b/app/views/accounts/_badges.html.erb @@ -1,7 +1,3 @@ <% if @presenter.show_unphishable_badge? %> <%= render BadgeComponent.new(icon: :lock).with_content(t('headings.account.unphishable')) %> <% end %> - -<% if @presenter.show_verified_badge? %> - <%= render BadgeComponent.new(icon: :check_circle).with_content(t('headings.account.verified_account')) %> -<% end %> diff --git a/app/views/accounts/_pending_profile_gpo.html.erb b/app/views/accounts/_pending_profile_gpo.html.erb index 5ca40bc2edc..bd737d7d6cb 100644 --- a/app/views/accounts/_pending_profile_gpo.html.erb +++ b/app/views/accounts/_pending_profile_gpo.html.erb @@ -1,4 +1,4 @@ -<%= render AlertComponent.new(type: :warning, text_tag: 'div') do %> +<%= render AlertComponent.new(type: :info, text_tag: 'div') do %>

<%= t('account.index.verification.instructions') %>

diff --git a/app/views/accounts/_pending_profile_ipp.html.erb b/app/views/accounts/_pending_profile_ipp.html.erb new file mode 100644 index 00000000000..f8680d57d4a --- /dev/null +++ b/app/views/accounts/_pending_profile_ipp.html.erb @@ -0,0 +1,8 @@ +<%= render AlertComponent.new(type: :info, text_tag: 'div') do %> +

+ <%= t('account.index.verification.in_person_instructions', deadline: @presenter.formatted_due_date) %> +

+

+ <%= link_to t('account.index.verification.show_bar_code'), idv_in_person_ready_to_verify_url %> +

+<% end %> diff --git a/app/views/accounts/_pii.html.erb b/app/views/accounts/_pii.html.erb index 8decfe81eb5..766202eb544 100644 --- a/app/views/accounts/_pii.html.erb +++ b/app/views/accounts/_pii.html.erb @@ -14,15 +14,8 @@ <% end %> -
-
-
-

- <%= t('headings.account.verified_information') %> - <%= image_tag asset_url('lock.svg'), width: 8, height: 10 %> -

-
-
+ +
@@ -74,4 +67,3 @@ <%= link_to t('account.security.link'), MarketingSite.help_url %>
<% end %> -
diff --git a/app/views/accounts/_unverified_profile.html.erb b/app/views/accounts/_unverified_profile.html.erb new file mode 100644 index 00000000000..3662524290a --- /dev/null +++ b/app/views/accounts/_unverified_profile.html.erb @@ -0,0 +1,6 @@ +<%= render AlertComponent.new(type: :warning, text_tag: 'div') do %> +

+ <%= t('account.index.verification.finish_verifying', partner_agency: @presenter.service_provider_or_app_name) %> +
<%= link_to t('account.index.verification.learn_more_link'), MarketingSite.help_url %> +

+<% end %> diff --git a/app/views/accounts/_validated_badge.html.erb b/app/views/accounts/_validated_badge.html.erb new file mode 100644 index 00000000000..18d73c9d888 --- /dev/null +++ b/app/views/accounts/_validated_badge.html.erb @@ -0,0 +1,9 @@ +<% if @presenter.show_verified_badge? %> + <%= render BadgeTooltipComponent.new(icon: :check_circle, tooltip_text: @presenter.biometric_identity_verification? ? t('components.badge_tooltip_component.verified_biometric') : t('components.badge_tooltip_component.verified'), class: 'usa-tooltip', data_position: 'top').with_content(t('headings.account.verified_account')) %> +<% end %> +<% if @presenter.show_unverified? %> + <%= render BadgeTooltipComponent.new(icon: :check_circle, tooltip_text: t('components.badge_tooltip_component.unverified'), class: 'usa-tooltip border-warning', data_position: 'top').with_content(t('headings.account.unverified')) %> +<% end %> +<% if @presenter.show_ipp_partial? || @presenter.show_gpo_partial? %> + <%= render BadgeTooltipComponent.new(icon: :check_circle, tooltip_text: t('components.badge_tooltip_component.pending'), class: 'usa-tooltip border-info', data_position: 'top').with_content(t('headings.account.pending')) %> +<% end %> \ No newline at end of file diff --git a/app/views/accounts/show.html.erb b/app/views/accounts/show.html.erb index 23d491c2340..eda3356d577 100644 --- a/app/views/accounts/show.html.erb +++ b/app/views/accounts/show.html.erb @@ -1,22 +1,67 @@ <% self.title = t('titles.account') %> -<% if @presenter.showing_any_partials? %> +<%= render 'accounts/header', presenter: @presenter %> +<% if @presenter.showing_alerts? %>
<% if @presenter.show_password_reset_partial? %> <%= render 'accounts/password_reset', presenter: @presenter %> <% end %> - - <% if @presenter.show_gpo_partial? %> - <%= render 'accounts/pending_profile_gpo' %> - <% end %> - <% if @presenter.show_service_provider_continue_partial? %> <%= render 'accounts/service_provider_continue', presenter: @presenter %> <% end %>
<% end %> -<%= render 'accounts/header', presenter: @presenter %> +<% if @presenter.showing_any_partials? %> +
+
+
+
+
+
+

+
+ <%= t('account.index.verification.identity_verification') %> +
+

+
+ +
+ <% unless @presenter.show_pii_partial? %> + <% if @presenter.show_verified_badge? %> + <%= render 'accounts/unverified_profile' %> + <% else %> +

+ <%= t('account.index.verification.finish_verifying', partner_agency: @presenter.service_provider_or_app_name) %> +
<%= link_to t('account.index.verification.learn_more_link'), MarketingSite.help_url %> +

+ <% end %> + <% end %> + <% if @presenter.show_gpo_partial? %> + <%= render 'accounts/pending_profile_gpo' %> + <% end %> + <% if @presenter.show_ipp_partial? %> + <%= render 'accounts/pending_profile_ipp' %> + <% end %> +
+
+ + <% if @presenter.show_pii_partial? %> + + <% if @presenter.biometric_identity_verification? %> +

<%= t('account.index.verification.you_verified_your_biometric_identity', app_name: APP_NAME) %> + <%= link_to t('account.index.verification.learn_more_link'), MarketingSite.help_url %>

+ <% else %> +

<%= t('account.index.verification.you_verified_your_identity', partner_agency: @presenter.service_provider_or_app_name) %> +
<%= link_to t('account.index.verification.learn_more_link'), MarketingSite.help_url %>

+ <% end %> + <%= render 'accounts/pii', pii: @presenter.pii, locked_for_session: @presenter.locked_for_session %> + <% end %> +
+
+<% end %>

<%= t('account.index.email_preferences') %>

@@ -89,8 +134,3 @@ <%= render 'accounts/backup_codes' %>
<% end %> - -<% if @presenter.show_pii_partial? %> - <%= render 'accounts/pii', pii: @presenter.pii, - locked_for_session: @presenter.locked_for_session %> -<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 3c931ad39a4..2cef89d45ca 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -72,9 +72,16 @@ account.index.reactivation.instructions: Your profile was recently deactivated d account.index.reactivation.link: Reactivate your profile now. account.index.sign_in_location_and_ip: From %{ip} (IP address potentially located in %{location}) account.index.unknown_location: unknown location -account.index.verification.instructions: Your account requires a verification code to be verified. -account.index.verification.reactivate_button: Enter the code you received via US mail +account.index.verification.finish_verifying: Finish verifying your identity to access %{partner_agency}. +account.index.verification.identity_verification: Identity verification +account.index.verification.in_person_instructions: You must visit any participating Post Office by %{deadline} to verify your identity. +account.index.verification.instructions: Enter your verification code to finish verifying your identity. +account.index.verification.learn_more_link: Learn more about verifying your identity +account.index.verification.reactivate_button: Enter the verification code you received via US mail +account.index.verification.show_bar_code: Show me my %{app_name} barcode account.index.verification.success: We verified your information +account.index.verification.you_verified_your_biometric_identity: You have verified your identity with the information below and verified a photo of yourself which gives you access to all %{app_name} partners. +account.index.verification.you_verified_your_identity: You verified your identity for %{partner_agency} with the information below. account.index.webauthn: Security key account.index.webauthn_add: Add security key account.index.webauthn_platform: Face or touch unlock @@ -132,6 +139,10 @@ anonymous_mailer.password_reset_missing_user.try_different_email: Try a differen anonymous_mailer.password_reset_missing_user.use_this_email_html: Or use this email address and %{create_account_link_html}. banned_user.details: We are unable to authenticate you at this time. banned_user.title: Access is restricted +components.badge_tooltip_component.pending: Your identity is pending verification. +components.badge_tooltip_component.unverified: Finish verifying your identity. +components.badge_tooltip_component.verified: Your identity has been verified. +components.badge_tooltip_component.verified_biometric: Your identity and photo have both been verified. components.barcode.image_alt: Barcode components.captcha_submit_button.action_message: Verifying… components.captcha_submit_button.mock_score_disclaimer: Internal Only @@ -884,11 +895,12 @@ headings.account.devices: Devices headings.account.events: Events headings.account.federal_employee_id: Federal employee ID headings.account.login_info: Your account +headings.account.pending: Pending headings.account.reactivate: Reactivate your account headings.account.two_factor: Your authentication methods headings.account.unphishable: Unphishable -headings.account.verified_account: Verified Account -headings.account.verified_information: Verified information +headings.account.unverified: Unverified +headings.account.verified_account: Verified headings.add_email: Add a new email address headings.add_info.phone: Add a phone number headings.cancellations.login_cancel_prompt: Are you sure you want to cancel and exit %{app_name}? diff --git a/config/locales/es.yml b/config/locales/es.yml index e32ab74ce44..d1607688584 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -72,9 +72,16 @@ account.index.reactivation.instructions: Su perfil fue desactivado recientemente account.index.reactivation.link: Reactive su perfil ahora. account.index.sign_in_location_and_ip: Desde %{ip} (la dirección IP se encuentra posiblemente en %{location}) account.index.unknown_location: ubicación desconocida -account.index.verification.instructions: Su cuenta requiere un código de verificación para poderla verificar. -account.index.verification.reactivate_button: Ingrese el código que recibió por correo de los EE. UU. +account.index.verification.finish_verifying: Termine de verificar su identidad para acceder a la %{partner_agency}. +account.index.verification.identity_verification: Verificación de identidad +account.index.verification.in_person_instructions: Para terminar de verificar su identidad, debe acudir a una oficina de correos participante antes del %{deadline}. +account.index.verification.instructions: Ingrese su código de verificación para terminar de verificar su identidad. +account.index.verification.learn_more_link: Obtenga más información sobre la verificación de su identidad +account.index.verification.reactivate_button: Ingrese el código de verificación que recibió por correo de los EE. UU. +account.index.verification.show_bar_code: Mostrar mi código de barras de %{app_name} account.index.verification.success: Verificamos su información +account.index.verification.you_verified_your_biometric_identity: Usted verificó su identidad con la información siguiente y verificó una fotografía suya, lo cual le da acceso a todos los asociados de %{app_name}. +account.index.verification.you_verified_your_identity: Usted verificó su identidad para %{partner_agency} con la información siguiente. account.index.webauthn: Clave de seguridad account.index.webauthn_add: Agregar clave de seguridad account.index.webauthn_platform: Desbloqueo facial o táctil @@ -132,6 +139,10 @@ anonymous_mailer.password_reset_missing_user.try_different_email: Pruebe con una anonymous_mailer.password_reset_missing_user.use_this_email_html: O use este correo electrónico y %{create_account_link_html}. banned_user.details: No podemos autenticarle en este momento. banned_user.title: Acceso restringido +components.badge_tooltip_component.pending: La verificación de su identidad está pendiente +components.badge_tooltip_component.unverified: Termine de verificar su identidad. +components.badge_tooltip_component.verified: Se verificó su identidad. +components.badge_tooltip_component.verified_biometric: Se verificó tanto su identidad como su fotografía. components.barcode.image_alt: Código de barras components.captcha_submit_button.action_message: Verificando… components.captcha_submit_button.mock_score_disclaimer: Uso interno @@ -895,11 +906,12 @@ headings.account.devices: Dispositivos headings.account.events: Eventos headings.account.federal_employee_id: Identificación de empleado federal headings.account.login_info: Su cuenta +headings.account.pending: Pendiente headings.account.reactivate: Reactive su cuenta headings.account.two_factor: Sus métodos de autenticación headings.account.unphishable: No vulnerable al phishing -headings.account.verified_account: Cuenta verificada -headings.account.verified_information: Información verificada +headings.account.unverified: No verificada +headings.account.verified_account: Verificada headings.add_email: Agregar una nueva dirección de correo electrónico headings.add_info.phone: Agregar un número de teléfono headings.cancellations.login_cancel_prompt: '¿Está seguro de que desea cancelar y salir de %{app_name}?' diff --git a/config/locales/fr.yml b/config/locales/fr.yml index a70d855ed5f..3c24e8059fb 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -72,9 +72,16 @@ account.index.reactivation.instructions: Votre profil a été récemment désact account.index.reactivation.link: Réactiver votre profil maintenant. account.index.sign_in_location_and_ip: De %{ip} (adresse IP éventuellement située dans %{location}) account.index.unknown_location: lieu inconnu -account.index.verification.instructions: Votre compte nécessite un code de vérification pour être vérifié. -account.index.verification.reactivate_button: Saisissez le code que vous avez reçu par la poste +account.index.verification.finish_verifying: Terminez la procédure de vérification d’identité pour pouvoir accéder à %{partner_agency}. +account.index.verification.identity_verification: Vérification de l’identité +account.index.verification.in_person_instructions: Vous devez vous rendre à un bureau de poste participant d’ici le %{deadline} pour terminer la procédure de vérification de votre identité. +account.index.verification.instructions: Saisissez votre code de vérification pour terminer la procédure de vérification d’identité. +account.index.verification.learn_more_link: En savoir plus sur la vérification de votre identité +account.index.verification.reactivate_button: Saisissez le code de vérification que vous avez reçu par la poste. +account.index.verification.show_bar_code: Me montrer mon code-barre %{app_name} account.index.verification.success: Nous avons vérifié vos informations +account.index.verification.you_verified_your_biometric_identity: Vous avez confirmé votre identité à l’aide des informations ci-dessous et d’une photo de vous-même, ce qui vous permet d’accéder à tous les organismes partenaires de %{app_name}. +account.index.verification.you_verified_your_identity: Vous avez confirmé votre identité auprès de %{partner_agency} à l’aide des informations ci-dessous. account.index.webauthn: Clé de sécurité account.index.webauthn_add: Ajouter une clé de sécurité account.index.webauthn_platform: Déverrouillage facial ou tactile @@ -132,6 +139,10 @@ anonymous_mailer.password_reset_missing_user.try_different_email: Essayez une au anonymous_mailer.password_reset_missing_user.use_this_email_html: Ou utilisez cet e-mail et %{create_account_link_html}. banned_user.details: Nous ne sommes pas en mesure de vous authentifier pour le moment. banned_user.title: L’accès est restreint +components.badge_tooltip_component.pending: Votre identité est en cours de vérification. +components.badge_tooltip_component.unverified: Terminer la vérification de votre identité. +components.badge_tooltip_component.verified: Votre identité a été vérifiée. +components.badge_tooltip_component.verified_biometric: Votre identité et votre photo ont été vérifiées. components.barcode.image_alt: Code-barres components.captcha_submit_button.action_message: Vérification en cours… components.captcha_submit_button.mock_score_disclaimer: Usage interne uniquement @@ -884,11 +895,12 @@ headings.account.devices: Appareils headings.account.events: Événements headings.account.federal_employee_id: Carte d’employé fédéral headings.account.login_info: Votre compte +headings.account.pending: En cours headings.account.reactivate: Réactiver votre compte headings.account.two_factor: Vos méthodes d’authentification headings.account.unphishable: Non hameçonnable -headings.account.verified_account: Compte vérifié -headings.account.verified_information: Informations vérifiées +headings.account.unverified: Non vérifiée +headings.account.verified_account: Vérifiée headings.add_email: Ajouter une nouvelle adresse e-mail headings.add_info.phone: Ajouter un numéro de téléphone headings.cancellations.login_cancel_prompt: Êtes-vous sûr de vouloir annuler et quitter %{app_name}? diff --git a/config/locales/zh.yml b/config/locales/zh.yml index 2e4f95e01fa..9d278e25714 100644 --- a/config/locales/zh.yml +++ b/config/locales/zh.yml @@ -72,9 +72,16 @@ account.index.reactivation.instructions: 你的用户资料因为重设密码最 account.index.reactivation.link: 现在重新激活你的用户资料。 account.index.sign_in_location_and_ip: 从 %{ip}(IP 地址可能位于 %{location})。 account.index.unknown_location: 未知地点 -account.index.verification.instructions: 你账户的验证需要一个验证码。 -account.index.verification.reactivate_button: 输入你通过邮局邮件收到的代码。 +account.index.verification.finish_verifying: 完成身份验证流程来获得访问 %{partner_agency} 的权限。 +account.index.verification.identity_verification: 身份验证 +account.index.verification.in_person_instructions: 你必须在 %{deadline} 之前去邮局完成验证你的身份。 +account.index.verification.instructions: 输入你的验证码来完成身份验证。 +account.index.verification.learn_more_link: 了解更多有关验证你身份的信息。 +account.index.verification.reactivate_button: 输入你通过邮局收到的验证码。 +account.index.verification.show_bar_code: 显示我的%{app_name} 条形码 account.index.verification.success: 我们验证了你的信息 +account.index.verification.you_verified_your_biometric_identity: 你使用以下信息验证了身份并验证了一张你本人的照片,从而获得了访问%{app_name}所有合作伙伴机构的权限。 +account.index.verification.you_verified_your_identity: 你使用以下信息向 %{partner_agency} 验证了身份。 account.index.webauthn: 安全密钥 account.index.webauthn_add: 添加安全密钥 account.index.webauthn_platform: 人脸或触摸解锁 @@ -132,6 +139,10 @@ anonymous_mailer.password_reset_missing_user.try_different_email: 尝试用一 anonymous_mailer.password_reset_missing_user.use_this_email_html: 或者使用此电子邮件地址和 %{create_account_link_html}。 banned_user.details: 我们目前无法验证你的身份。 banned_user.title: 访问受限。 +components.badge_tooltip_component.pending: 你的身份有待验证。 +components.badge_tooltip_component.unverified: 完成验证你的身份。 +components.badge_tooltip_component.verified: 你的身份已经验证。 +components.badge_tooltip_component.verified_biometric: 你的身份和照片都已验证。 components.barcode.image_alt: 条形码 components.captcha_submit_button.action_message: 验证中 components.captcha_submit_button.mock_score_disclaimer: 只针对内部 @@ -899,11 +910,12 @@ headings.account.devices: 设备 headings.account.events: 事件 headings.account.federal_employee_id: 政府雇员身份证件 headings.account.login_info: 你的账户 +headings.account.pending: 待验证 headings.account.reactivate: 重新激活你的账户 headings.account.two_factor: 你的身份证实方法。 headings.account.unphishable: 无法网络钓鱼 -headings.account.verified_account: 验证过的账户 -headings.account.verified_information: 验证过的信息 +headings.account.unverified: 未验证 +headings.account.verified_account: 已验证 headings.add_email: 添加一个新电邮地址 headings.add_info.phone: 添加一个电话号码 headings.cancellations.login_cancel_prompt: 你确定要取消并退出 %{app_name} 吗? diff --git a/spec/components/badge_tooltip_component_spec.rb b/spec/components/badge_tooltip_component_spec.rb new file mode 100644 index 00000000000..586ed1d410a --- /dev/null +++ b/spec/components/badge_tooltip_component_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +RSpec.describe BadgeTooltipComponent, type: :component do + let(:tooltip_text) { 'Your identity has been verified.' } + let(:tag_options) { { icon: :check_circle } } + + subject(:rendered) do + render_inline BadgeTooltipComponent.new(tooltip_text:, **tag_options).with_content(tooltip_text) + end + + it 'renders with tooltip text as an attribute' do + expect(rendered).to have_css("lg-badge-tooltip[tooltip-text='#{tooltip_text}']") + end +end diff --git a/spec/support/idv_examples/clearing_and_restarting.rb b/spec/support/idv_examples/clearing_and_restarting.rb index 3379fab7257..861b25afd9a 100644 --- a/spec/support/idv_examples/clearing_and_restarting.rb +++ b/spec/support/idv_examples/clearing_and_restarting.rb @@ -48,7 +48,7 @@ visit account_path - expect(page).to_not have_content(t('headings.account.verified_information')) + expect(page).to_not have_content(t('headings.account.verified_account')) expect(page).to_not have_content(t('account.verified_information.address')) expect(page).to_not have_content(t('account.verified_information.dob')) expect(page).to_not have_content(t('account.verified_information.full_name')) diff --git a/spec/views/accounts/show.html.erb_spec.rb b/spec/views/accounts/show.html.erb_spec.rb index 1923dfb8e7e..87f6a8aaa14 100644 --- a/spec/views/accounts/show.html.erb_spec.rb +++ b/spec/views/accounts/show.html.erb_spec.rb @@ -23,11 +23,29 @@ render end + context 'when current user has a verified account' do + before do + allow(user).to receive(:identity_verified?).and_return(true) + end + + it 'displays a Verified badge' do + render + + expect(rendered).to have_content(t('headings.account.verified_account')) + end + end + context 'when current user has password_reset_profile' do before do allow(user).to receive(:password_reset_profile).and_return(true) end + it 'displays an Unverified badge' do + render + + expect(rendered).to have_content(t('headings.account.unverified')) + end + it 'displays an alert with instructions to reactivate their profile' do render @@ -69,6 +87,12 @@ allow(user).to receive(:pending_profile).and_return(pending) end + it 'displays a Pending badge' do + render + + expect(rendered).to have_content(t('headings.account.pending')) + end + it 'contains a link to activate profile' do render