add checkbox styling, driverslicence handling and validation

This commit is contained in:
Alex
2024-10-02 14:32:14 +02:00
parent 4ee18f21f2
commit cafe030e79
17 changed files with 303 additions and 44 deletions

View File

@@ -73,6 +73,7 @@ declare global {
interface Locals {
user: User;
subscriptions: Subscription[];
licence_categories: LicenceCategory[];
}
// interface PageData {}
// interface Platform {}

View File

@@ -46,6 +46,8 @@ export async function handle({ event, resolve }) {
event.locals.subscriptions = data.subscriptions;
event.locals.user = data.user;
event.locals.licence_categories = data.licence_categories;
console.dir(event.locals.licence_categories);
if (event.locals.user.date_of_birth) {
event.locals.user.date_of_birth =
event.locals.user.date_of_birth.split("T")[0];

View File

@@ -32,6 +32,9 @@
/** @type {boolean} */
export let toUpperCase = false;
/** @type {boolean} */
export let checked = false;
/**
* @param {Event} event - The input event
*/
@@ -97,6 +100,11 @@
/^[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3})?$/.test(value)
? null
: $t("validation.bic");
case "licence_number":
return typeof value === "string" && value.length == 11
? null
: $t("validation.drivers_licence");
default:
return typeof value === "string" && !value.trim() && required
? $t("validation.required")
@@ -109,8 +117,21 @@
$: selectedColor = selectedOption ? selectedOption.color : "";
</script>
<div class="input-box">
<span class="label">{label}</span>
<div class="input-box {type === 'checkbox' ? 'checkbox-container' : ''}">
{#if type === "checkbox"}
<label class="checkbox-label">
<input
type="checkbox"
{name}
{value}
{checked}
on:change={() => (checked = !checked)}
/>
<span class="checkbox-text"> {label} </span>
</label>
{:else}
<span class="label">{label}</span>
{/if}
<div class="input-error-container">
{#if error}
<span class="error-message">{error}</span>
@@ -137,7 +158,7 @@
class="input textarea"
style="height:{rows * 1.5}em;"
/>
{:else}
{:else if type != "checkbox"}
<input
{name}
{type}
@@ -153,6 +174,36 @@
</div>
<style>
.checkbox-container {
display: inline-flex;
align-items: center;
background-color: transparent;
}
.checkbox-label {
display: inline-flex;
align-items: center;
cursor: pointer;
user-select: none;
justify-content: center;
}
.checkbox-label input[type="checkbox"] {
margin-right: 5px;
flex-shrink: 0;
width: 40px;
}
.checkbox-text {
font-size: 16px;
}
@media (min-width: 768px) {
.checkbox-text {
flex-direction: row;
align-items: center;
}
}
.select {
padding-right: 1.5em;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

View File

@@ -29,6 +29,10 @@ export default {
bic: "BIC eingeben(Bei nicht deutschen Konten)...",
mandate_reference: "SEPA Mandatsreferenz eingeben..",
notes: "Deine Notizen zu {name}...",
licence_number: "Auf dem Führerschein unter Feld 5",
issued_date: "Ausgabedatum unter Feld 4a",
expiration_date: "Ablaufdatum unter Feld 4b",
issuing_country: "Ausstellendes Land",
},
validation: {
required: "Eingabe benötigt",
@@ -40,6 +44,7 @@ export default {
iban: "Ungültige IBAN",
date: "Bitte geben Sie ein Datum ein",
email: "Ungültige Emailadresse",
drivers_licence: "Nummer zu kurz(11 Zeichen)",
},
licenceCategory: {
AM: "Mopeds und leichte vierrädrige Kraftfahrzeuge(50ccm,max 45km/h)",
@@ -59,8 +64,13 @@ export default {
L: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 40km/h",
T: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 60km/h",
},
licence_categories: "Führerscheinklassen",
subscription_model: "Mitgliedschatfsmodell",
licence: "Lizenz",
licence: "Führerschein",
licence_number: "Führerscheinnummer",
issued_date: "Ausgabedatum",
expiration_date: "Ablaufdatum",
country: "Land",
monthly_fee: "Monatliche Gebühr",
hourly_rate: "Stundensatz",
details: "Details",

View File

@@ -1,5 +1,5 @@
/** @type {import('./$types').LayoutLoad} */
export async function load({ fetch, url, data }) {
const { user, subscriptions } = data;
return { fetch, url: url.pathname, user, subscriptions };
const { user, subscriptions, licence_categories } = data;
return { fetch, url: url.pathname, user, subscriptions, licence_categories };
}

View File

@@ -3,5 +3,6 @@ export async function load({ locals }) {
return {
user: locals.user,
subscriptions: locals.subscriptions,
licence_categories: locals.licence_categories,
};
}

View File

@@ -20,6 +20,9 @@
/** @type {App.Locals['user']}*/
$: user = $page.data.user;
/** @type {App.Locals['licence_categories']} */
$: licence_categories = $page.data.licence_categories;
/** @typedef {{name: string, src: string}} Avatar */
const avatarFiles = import.meta.glob("$lib/img/Avatar-*.jpeg", {
eager: true,
@@ -55,6 +58,7 @@
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
];
const licenceStatusOptions = [
{ value: 1, label: $t("userStatus.1"), color: "#b1b1b1" }, // Grey for "Nicht verifiziert"
{ value: 3, label: $t("userStatus.3"), color: "#00bc00" }, // Green for "Aktiv"
{ value: 4, label: $t("userStatus.4"), color: "#FFC0CB" }, // Pink for "Passiv"
{ value: 5, label: $t("userStatus.5"), color: "#FF4646" }, // Red for "Deaktiviert"
@@ -78,6 +82,7 @@
onMount(() => {
console.dir(user);
console.dir(licence_categories);
avatars = Object.entries(avatarFiles).map(([path, module]) => {
if (typeof path !== "string") {
throw new Error("Unexpected non-string path");
@@ -437,6 +442,58 @@
bind:value={user.drivers_licence.status}
options={licenceStatusOptions}
/>
<InputField
name="licence_number"
type="text"
label={$t("licencce_number")}
bind:value={user.drivers_licence.licence_number}
placeholder={$t("placeholder.licence_number")}
toUpperCase={true}
/>
<InputField
name="isued_date"
type="date"
label={$t("issued_date")}
bind:value={user.drivers_licence.issued_date}
placeholder={$t("placeholder.issued_date")}
/>
<InputField
name="expiration_date"
type="date"
label={$t("expiration_date")}
bind:value={user.drivers_licence.expiration_date}
placeholder={$t("placeholder.expiration_date")}
/>
<InputField
name="country"
label={$t("country")}
bind:value={user.drivers_licence.issuing_country}
placeholder={$t("placeholder.issuing_country")}
/>
<div class="licence-categories">
<h3>{$t("licence_categories")}</h3>
<div class="checkbox-grid">
{#each licence_categories as category}
<div class="checkbox-item">
<div class="checkbox-label-container">
<InputField
type="checkbox"
name="licence_categories[]"
value={category.category}
label={category.category}
checked={user.drivers_licence.licence_categories != null &&
user.drivers_licence.licence_categories.some(
(cat) => cat.category === category.category
)}
/>
</div>
<span class="checkbox-description">
{$t(`licenceCategory.${category.category}`)}
</span>
</div>
{/each}
</div>
</div>
</div>
<div
class="tab-content"
@@ -566,6 +623,54 @@
{/if}
<style>
.licence-categories {
margin-bottom: 20px;
}
.checkbox-grid {
display: grid;
grid-template-columns: 1fr;
gap: 5px;
}
.checkbox-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.checkbox-label-container {
flex: 0 0 auto;
margin-right: 10px;
}
.checkbox-description {
flex: 1;
font-size: 14px;
color: #9b9b9b;
text-align: right;
margin-left: 10px;
}
@media (min-width: 768px) {
.checkbox-grid {
grid-template-columns: 1fr 1fr;
gap: 20px;
}
}
@media (max-width: 480px) {
.checkbox-item {
flex-direction: column;
align-items: flex-start;
}
.checkbox-description {
margin-left: 24px;
margin-top: 5px;
text-align: left;
}
}
.subscription-info {
display: flex;
flex-wrap: wrap;