Files
pleno-vue/src/views/auth/Login.vue
T
Jeppe BandPleno Bugfix Bot cafe671e85 feat(pleno-vue): add driver/subuser login button (mobile-visible) (TRU-61) (#321)
## Why

Drivers (sub-users) could not reliably reach the driver login from the
customer login page (/login) on mobile devices. The form contained an
internal driver button, but it sat below the QR code and passkey
buttons, making it easy to miss on small screens. The desktop sidebar
layout further reduced discoverability.

## What changed

- **src/views/auth/Login.vue** — Add a page-level .driver-entry block
below the customer login form, with a router-link to { name:
'subuserlogin' }. Distinct color (#1584BC) and a truck icon match the
existing LandingPage driver entry pattern. Full-width on mobile (<768px)
so it's impossible to miss.
- **i18n** — Add auth.driver_login_help to en, da, de, no, sv locale
files + global shared auth index. auth.driver_login_button already
existed in all locales.
- **tests/unit/login-driver-entry.spec.js** — 5 Vitest tests verifying
the driver entry block, router-link, button label, help text, and
placement (not in sidebar).

## CI

- Vitest unit tests pass (5/5 new tests, existing tests unaffected)
- ESLint clean
- Text encoding check clean
- i18n v2 source check + compile clean

Co-authored-by: Pleno Bugfix Bot <bugfix-bot@pleno.local>
2026-08-16 22:38:03 +02:00

273 lines
6.2 KiB
Vue

<script setup>
import LoginForm from "@/components/forms/auth/LoginForm.vue";
import logo from "@/assets/img/truckwash-banner.png";
import ConnectivityIssue from "@/views/errors/ConnectivityIssue.vue";
import BrandedLoadingScreen from "@/components/global/BrandedLoadingScreen.vue";
import { useStoredSessionGuestRedirect } from "@/composables/useStoredSessionGuestRedirect.js";
const { hasPendingStoredSession } = useStoredSessionGuestRedirect();
</script>
<template>
<BrandedLoadingScreen
v-if="hasPendingStoredSession"
title="Bekræfter bruger..."
subtitle="Vi indlæser din session"
test-id="guest-session-loading"
status-test-id="guest-session-loading-status"
aria-label="Bekræfter bruger"
/>
<section v-else class="login-section">
<div class="wrapper">
<div class="sidebar">
<h1>{{ $t('auth.customer_login_title') }}</h1>
</div>
<div class="main">
<router-link :to="{ name: 'landing' }" class="logo">
<img :src="logo" alt="Truck Wash">
</router-link>
<ConnectivityIssue>
<LoginForm />
</ConnectivityIssue>
<p>{{ $t('auth.terms_acceptance') }}</p>
<!-- Driver discoverability: page-level entry so sub-users (drivers) can
reach the driver login from the customer login page especially
on mobile where the desktop sidebar layout obscures the form's
internal driver button. -->
<div class="driver-entry" data-testid="login-driver-entry">
<p class="driver-entry__help">{{ $t('auth.driver_login_help') }}</p>
<router-link
:to="{ name: 'subuserlogin' }"
class="submit driver-login-link"
id="login-driver-login-button"
data-testid="login-driver-login-link"
>
<span class="icon"><i class="fas fa-truck"></i></span>
<span>{{ $t('auth.driver_login_button') }}</span>
</router-link>
</div>
</div>
</div>
</section>
</template>
<style scoped>
/*login-section*/
.login-section .wrapper{
display: flex;
align-items: stretch;
min-height: calc(100vh)
}
.login-section .wrapper .sidebar{
width: 33%;
background-color: #13324C;
display: flex;
flex-direction: column;
padding: 70px 20px;
position: sticky;
top: 0;
height: 100vh;
}
.login-section .wrapper .sidebar h1{
color: #fff;
margin-top: auto;
margin-bottom: auto;
font-size: 3.8em;
font-weight: 600;
text-align: center;
line-height: 1;
}
.login-section .wrapper .sidebar p{
color: #fff;
font-size: 2em;
font-weight: 600;
text-align: center;
line-height: 1;
}
.login-section .wrapper .main{
width: 67%;
padding: 70px 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.login-section .wrapper .main .logo{
display: flex;
max-width: 230px;
margin-bottom: 40px;
}
.login-section .wrapper .main .logo img{
width: 100%;
height: auto;
aspect-ratio: 183/32;
object-fit: contain;
}
.login-section .wrapper .main form{
display: flex;
flex-direction: column;
gap: 16px;
max-width: 400px;
margin-bottom: 40px;
width: 100%;
}
.login-section .wrapper .main form .form-field{
display: flex;
flex-direction: column;
gap: 4px;
}
.login-section .wrapper .main form .form-field label{
color: #13324C;
font-size: 16px;
line-height: 1;
display: flex;
gap: 16px;
}
.login-section .wrapper .main form input{
border: 1.5px solid #333;
border-radius: 8px;
margin-top: 4px;
font-size: 16px;
line-height: 1;
}
.login-section .wrapper .main form input:not([type="checkbox"]) {
min-height: 40px;
}
.login-section .wrapper .main p{
max-width: 400px;
text-align: center;
font-size: 16px;
color: #13324C;
}
.login-section .wrapper .main a{
text-decoration: underline;
color: inherit;
}
.login-section .wrapper .main .submit{
width: 100%;
border-radius: 30px;
background-color: #13324C;
border: 0;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
min-height: 43px;
margin: 20px 0;
text-decoration: none;
}
/* Driver entry block — page-level, always visible on every viewport.
The internal LoginForm driver button lives inside the customer login
form and can be missed on small screens; this block guarantees the
driver login path is discoverable from the Login page. */
.login-section .wrapper .main .driver-entry {
max-width: 400px;
width: 100%;
margin-top: 24px;
padding: 16px 20px;
background-color: #F2F8FC;
border: 1px solid #BFE0EF;
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.login-section .wrapper .main .driver-entry__help {
max-width: none;
margin: 0;
font-size: 14px;
color: #13324C;
text-align: center;
line-height: 1.4;
}
.login-section .wrapper .main .driver-entry .driver-login-link {
background-color: #1584BC;
color: #fff;
border: 0;
border-radius: 30px;
min-height: 43px;
font-size: 16px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
text-decoration: none;
margin: 0;
width: auto;
padding: 0 24px;
}
.login-section .wrapper .main .driver-entry .driver-login-link:hover {
background-color: #1a99d6;
color: #fff;
}
@media (max-width: 1250px) {
.login-section .wrapper .sidebar h1{
font-size: 2.3em;
}
.login-section .wrapper .sidebar p{
font-size: 1.5em;
}
}
@media (max-width: 991px) {
.login-section .wrapper{
flex-direction: column;
min-height: calc(100vh - 96px)
}
.login-section .wrapper .sidebar{
width: 100%;
padding: 70px 10px;
position: relative;
top: 0;
height: max-content;
}
.login-section .wrapper .main{
width: 100%;
padding: 70px 10px;
}
}
/* Mobile (<768px): ensure the driver entry block is always visible and
takes full width so it's impossible to miss on phones. */
@media (max-width: 767px) {
.login-section .wrapper .main .driver-entry {
margin-top: 20px;
padding: 14px 16px;
width: 100%;
}
.login-section .wrapper .main .driver-entry .driver-login-link {
width: 100%;
padding: 0 16px;
}
}
/*end login-section*/
</style>