Client - update input style on validation error

This commit is contained in:
Sam 2021-11-11 08:29:12 +01:00
parent c2b2bdcabd
commit 7a7cd509ed
35 changed files with 84 additions and 49 deletions

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"><link rel="stylesheet" href="/static/css/leaflet.css"><title>FitTrackee</title><link href="/static/css/admin.e96a4210.css" rel="prefetch"><link href="/static/css/main.ce026596.css" rel="prefetch"><link href="/static/css/main~workouts.ca97ac72.css" rel="prefetch"><link href="/static/css/profile.b792256b.css" rel="prefetch"><link href="/static/css/reset.dc50c1a7.css" rel="prefetch"><link href="/static/css/workouts.9c79c3ad.css" rel="prefetch"><link href="/static/js/admin.2f1d393d.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/main.c42d7740.js" rel="prefetch"><link href="/static/js/main~workouts.a74990d7.js" rel="prefetch"><link href="/static/js/profile.6a786c1d.js" rel="prefetch"><link href="/static/js/reset.6f6516bc.js" rel="prefetch"><link href="/static/js/workouts.ed2b92d6.js" rel="prefetch"><link href="/static/css/app.1b990916.css" rel="preload" as="style"><link href="/static/js/app.3ce561e1.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.71654064.js" rel="preload" as="script"><link href="/static/css/app.1b990916.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.71654064.js"></script><script src="/static/js/app.3ce561e1.js"></script></body></html> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><!--[if IE]><link rel="icon" href="/favicon.ico"><![endif]--><link rel="stylesheet" href="/static/css/fork-awesome.min.css"><link rel="stylesheet" href="/static/css/leaflet.css"><title>FitTrackee</title><link href="/static/css/admin.04e24276.css" rel="prefetch"><link href="/static/css/main.c790adb1.css" rel="prefetch"><link href="/static/css/main~workouts.66c5ef05.css" rel="prefetch"><link href="/static/css/profile.b52bc193.css" rel="prefetch"><link href="/static/css/reset.bd9657a8.css" rel="prefetch"><link href="/static/css/workouts.54006dff.css" rel="prefetch"><link href="/static/js/admin.2f1d393d.js" rel="prefetch"><link href="/static/js/chunk-2d0c9189.c81458cc.js" rel="prefetch"><link href="/static/js/chunk-2d0cf391.020c75ea.js" rel="prefetch"><link href="/static/js/chunk-2d0da8f3.c8c3e7e8.js" rel="prefetch"><link href="/static/js/chunk-2d2248b6.d84473c1.js" rel="prefetch"><link href="/static/js/chunk-2d22523a.4b710d99.js" rel="prefetch"><link href="/static/js/main.2d300ca4.js" rel="prefetch"><link href="/static/js/main~workouts.a74990d7.js" rel="prefetch"><link href="/static/js/profile.6a786c1d.js" rel="prefetch"><link href="/static/js/reset.518e646f.js" rel="prefetch"><link href="/static/js/workouts.f85cc044.js" rel="prefetch"><link href="/static/css/app.d06ac220.css" rel="preload" as="style"><link href="/static/js/app.0657b3d3.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.71654064.js" rel="preload" as="script"><link href="/static/css/app.d06ac220.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="no"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="fittrackee_client"><link rel="apple-touch-icon" href="/img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="/img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="/img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><noscript><strong>We're sorry but FitTrackee doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.71654064.js"></script><script src="/static/js/app.0657b3d3.js"></script></body></html>

View File

@ -64,7 +64,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/img/workouts/mountains.svg" "url": "/img/workouts/mountains.svg"
}, },
{ {
"revision": "b5a511093d76c7022f9a5d3c96737780", "revision": "a6b9ff333c570a6df2fd94519c10538e",
"url": "/index.html" "url": "/index.html"
}, },
{ {
@ -76,12 +76,12 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/robots.txt" "url": "/robots.txt"
}, },
{ {
"revision": "a1d50ec70acd25b1b70a", "revision": "ca5244fc3bcfc65816b9",
"url": "/static/css/admin.e96a4210.css" "url": "/static/css/admin.04e24276.css"
}, },
{ {
"revision": "dd027e243e87a31ad23f", "revision": "f6baf208ef194278aa64",
"url": "/static/css/app.1b990916.css" "url": "/static/css/app.d06ac220.css"
}, },
{ {
"revision": "82c1118c918377daaa71a320ab8eea42", "revision": "82c1118c918377daaa71a320ab8eea42",
@ -92,24 +92,24 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/css/leaflet.css" "url": "/static/css/leaflet.css"
}, },
{ {
"revision": "02825f02e064c9f982a1", "revision": "6b6d16fcb3cf2d77115c",
"url": "/static/css/main.ce026596.css" "url": "/static/css/main.c790adb1.css"
}, },
{ {
"revision": "d37b7cc3f4be1d095e98", "revision": "68364924c988a1f11b42",
"url": "/static/css/main~workouts.ca97ac72.css" "url": "/static/css/main~workouts.66c5ef05.css"
}, },
{ {
"revision": "46a831b0d7a94cbae773", "revision": "3438ac3f32223591afd9",
"url": "/static/css/profile.b792256b.css" "url": "/static/css/profile.b52bc193.css"
}, },
{ {
"revision": "9ef2fa45c16d6788a6e2", "revision": "688d813785d3c55a7d33",
"url": "/static/css/reset.dc50c1a7.css" "url": "/static/css/reset.bd9657a8.css"
}, },
{ {
"revision": "8a364ff438b4214d5d65", "revision": "f95074a416d77cca21e7",
"url": "/static/css/workouts.9c79c3ad.css" "url": "/static/css/workouts.54006dff.css"
}, },
{ {
"revision": "e719f9244c69e28e7d00e725ca1e280e", "revision": "e719f9244c69e28e7d00e725ca1e280e",
@ -192,12 +192,12 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/img/pt-sans-v9-latin-regular.f1f73e45.svg" "url": "/static/img/pt-sans-v9-latin-regular.f1f73e45.svg"
}, },
{ {
"revision": "a1d50ec70acd25b1b70a", "revision": "ca5244fc3bcfc65816b9",
"url": "/static/js/admin.2f1d393d.js" "url": "/static/js/admin.2f1d393d.js"
}, },
{ {
"revision": "dd027e243e87a31ad23f", "revision": "f6baf208ef194278aa64",
"url": "/static/js/app.3ce561e1.js" "url": "/static/js/app.0657b3d3.js"
}, },
{ {
"revision": "bd7d183c9f68e5f4027d", "revision": "bd7d183c9f68e5f4027d",
@ -224,23 +224,23 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/chunk-vendors.71654064.js" "url": "/static/js/chunk-vendors.71654064.js"
}, },
{ {
"revision": "02825f02e064c9f982a1", "revision": "6b6d16fcb3cf2d77115c",
"url": "/static/js/main.c42d7740.js" "url": "/static/js/main.2d300ca4.js"
}, },
{ {
"revision": "d37b7cc3f4be1d095e98", "revision": "68364924c988a1f11b42",
"url": "/static/js/main~workouts.a74990d7.js" "url": "/static/js/main~workouts.a74990d7.js"
}, },
{ {
"revision": "46a831b0d7a94cbae773", "revision": "3438ac3f32223591afd9",
"url": "/static/js/profile.6a786c1d.js" "url": "/static/js/profile.6a786c1d.js"
}, },
{ {
"revision": "9ef2fa45c16d6788a6e2", "revision": "688d813785d3c55a7d33",
"url": "/static/js/reset.6f6516bc.js" "url": "/static/js/reset.518e646f.js"
}, },
{ {
"revision": "8a364ff438b4214d5d65", "revision": "f95074a416d77cca21e7",
"url": "/static/js/workouts.ed2b92d6.js" "url": "/static/js/workouts.f85cc044.js"
} }
]); ]);

View File

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts( importScripts(
"/precache-manifest.cc6cd612d3010f62e8a6b2d637ce02fb.js" "/precache-manifest.cf4ee6309ccad810ffa908b5895175ac.js"
); );
workbox.core.setCacheNameDetails({prefix: "fittrackee_client"}); workbox.core.setCacheNameDetails({prefix: "fittrackee_client"});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,13 +11,17 @@
message="user.REGISTER_DISABLED" message="user.REGISTER_DISABLED"
v-if="registration_disabled" v-if="registration_disabled"
/> />
<form @submit.prevent="onSubmit(action)"> <form
:class="{ errors: formErrors }"
@submit.prevent="onSubmit(action)"
>
<div class="form-items"> <div class="form-items">
<input <input
v-if="action === 'register'" v-if="action === 'register'"
id="username" id="username"
:disabled="registration_disabled" :disabled="registration_disabled"
required required
@invalid="invalidateForm"
v-model="formData.username" v-model="formData.username"
:placeholder="$t('user.USERNAME')" :placeholder="$t('user.USERNAME')"
/> />
@ -26,6 +30,7 @@
id="email" id="email"
:disabled="registration_disabled" :disabled="registration_disabled"
required required
@invalid="invalidateForm"
type="email" type="email"
v-model="formData.email" v-model="formData.email"
:placeholder=" :placeholder="
@ -39,6 +44,7 @@
id="password" id="password"
:disabled="registration_disabled" :disabled="registration_disabled"
required required
@invalid="invalidateForm"
type="password" type="password"
v-model="formData.password" v-model="formData.password"
:placeholder=" :placeholder="
@ -53,6 +59,7 @@
:disabled="registration_disabled" :disabled="registration_disabled"
type="password" type="password"
required required
@invalid="invalidateForm"
v-model="formData.password_conf" v-model="formData.password_conf"
:placeholder=" :placeholder="
action === 'reset' action === 'reset'
@ -91,6 +98,7 @@
ComputedRef, ComputedRef,
computed, computed,
reactive, reactive,
ref,
toRefs, toRefs,
watch, watch,
withDefaults, withDefaults,
@ -133,6 +141,7 @@
() => () =>
props.action === 'register' && !appConfig.value.is_registration_enabled props.action === 'register' && !appConfig.value.is_registration_enabled
) )
const formErrors = ref(false)
function getButtonText(action: string): string { function getButtonText(action: string): string {
switch (action) { switch (action) {
@ -143,6 +152,9 @@
return `buttons.${props.action.toUpperCase()}` return `buttons.${props.action.toUpperCase()}`
} }
} }
function invalidateForm() {
formErrors.value = true
}
function onSubmit(actionType: string) { function onSubmit(actionType: string) {
switch (actionType) { switch (actionType) {
case 'reset': case 'reset':
@ -183,6 +195,7 @@
() => route.path, () => route.path,
async () => { async () => {
store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES) store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
formErrors.value = false
resetFormData() resetFormData()
} }
) )

View File

@ -10,7 +10,7 @@
}}</template> }}</template>
<template #content> <template #content>
<div id="workout-form"> <div id="workout-form">
<form @submit.prevent="updateWorkout"> <form :class="{ errors: formErrors }" @submit.prevent="updateWorkout">
<div class="form-items"> <div class="form-items">
<div class="form-item-radio" v-if="isCreation"> <div class="form-item-radio" v-if="isCreation">
<div> <div>
@ -41,6 +41,7 @@
<select <select
id="sport" id="sport"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.sport_id" v-model="workoutForm.sport_id"
> >
@ -64,6 +65,8 @@
type="file" type="file"
accept=".gpx, .zip" accept=".gpx, .zip"
:disabled="loading" :disabled="loading"
required
@invalid="invalidateForm"
@input="updateFile" @input="updateFile"
/> />
<div class="files-help info-box"> <div class="files-help info-box">
@ -94,6 +97,7 @@
name="title" name="title"
type="text" type="text"
:required="!isCreation" :required="!isCreation"
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.title" v-model="workoutForm.title"
/> />
@ -108,6 +112,7 @@
name="workout-date" name="workout-date"
type="date" type="date"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.workoutDate" v-model="workoutForm.workoutDate"
/> />
@ -117,6 +122,7 @@
class="workout-time" class="workout-time"
type="time" type="time"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.workoutTime" v-model="workoutForm.workoutTime"
/> />
@ -133,6 +139,7 @@
placeholder="HH" placeholder="HH"
pattern="^([0-9]*[0-9])$" pattern="^([0-9]*[0-9])$"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.workoutDurationHour" v-model="workoutForm.workoutDurationHour"
/> />
@ -145,6 +152,7 @@
pattern="^([0-5][0-9])$" pattern="^([0-5][0-9])$"
placeholder="MM" placeholder="MM"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.workoutDurationMinutes" v-model="workoutForm.workoutDurationMinutes"
/> />
@ -157,6 +165,7 @@
pattern="^([0-5][0-9])$" pattern="^([0-5][0-9])$"
placeholder="SS" placeholder="SS"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.workoutDurationSeconds" v-model="workoutForm.workoutDurationSeconds"
/> />
@ -171,6 +180,7 @@
min="0" min="0"
step="0.1" step="0.1"
required required
@invalid="invalidateForm"
:disabled="loading" :disabled="loading"
v-model="workoutForm.workoutDistance" v-model="workoutForm.workoutDistance"
/> />
@ -279,6 +289,7 @@
props.workout.id ? props.workout.with_gpx : props.isCreation props.workout.id ? props.workout.with_gpx : props.isCreation
) )
let gpxFile: File | null = null let gpxFile: File | null = null
const formErrors = ref(false)
onMounted(() => { onMounted(() => {
if (props.workout.id) { if (props.workout.id) {
@ -291,6 +302,7 @@
} }
function updateWithGpx() { function updateWithGpx() {
withGpx.value = !withGpx.value withGpx.value = !withGpx.value
formErrors.value = false
} }
function updateFile(event: Event & { target: HTMLInputElement }) { function updateFile(event: Event & { target: HTMLInputElement }) {
if (event.target.files) { if (event.target.files) {
@ -364,6 +376,9 @@
router.go(-1) router.go(-1)
} }
} }
function invalidateForm() {
formErrors.value = true
}
onUnmounted(() => store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)) onUnmounted(() => store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES))

View File

@ -39,6 +39,12 @@ input, textarea, select {
} }
} }
form.errors {
:invalid {
outline: 2px solid var(--input-error-color);
}
}
label { label {
font-weight: bold; font-weight: bold;
} }

View File

@ -20,6 +20,7 @@
--card-border-color: #c4c7cf; --card-border-color: #c4c7cf;
--input-border-color: #9da3af; --input-border-color: #9da3af;
--input-bg-color: #FFFFFF; --input-bg-color: #FFFFFF;
--input-error-color: #dc3545;
--dropdown-hover-color: #eff0f5; --dropdown-hover-color: #eff0f5;
--custom-checkbox-border-color: #9da3af; --custom-checkbox-border-color: #9da3af;