styling, DateOfBirth corrected
This commit is contained in:
@@ -283,7 +283,6 @@
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
input,
|
||||
textarea,
|
||||
@@ -316,7 +315,6 @@
|
||||
}
|
||||
/* Add consistent spacing between input boxes */
|
||||
.input-box {
|
||||
margin: 1rem 0;
|
||||
padding: 0.5rem;
|
||||
background-color: var(--surface0);
|
||||
border-radius: 6px;
|
||||
|
||||
@@ -28,28 +28,6 @@
|
||||
|
||||
<div class="modal-background">
|
||||
<div transition:modal|global={{ duration: 1000 }} class="modal" role="dialog" aria-modal="true">
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<a
|
||||
title={$t('cancel')}
|
||||
class="modal-close"
|
||||
on:click={closeModal}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
on:keydown={(e) => e.key == 'Enter' && closeModal()}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 384 512"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">{$t('cancel')}</span>
|
||||
</a>
|
||||
<div class="container">
|
||||
<slot />
|
||||
</div>
|
||||
@@ -64,7 +42,7 @@
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(30, 30, 46, 0.65); /* var(--base) with 0.75 opacity */
|
||||
background: var(--modal-backdrop); /* var(--base) with 0.75 opacity */
|
||||
backdrop-filter: blur(4px); /* Optional: adds a slight blur effect */
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
@@ -149,7 +127,6 @@
|
||||
.modal .container {
|
||||
flex-direction: column;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
zip_code: '',
|
||||
city: '',
|
||||
company: '',
|
||||
date_of_birth: '',
|
||||
dateofbirth: '',
|
||||
notes: '',
|
||||
profile_picture: '',
|
||||
payment_status: 0,
|
||||
@@ -297,11 +297,11 @@
|
||||
placeholder={$t('placeholder.phone')}
|
||||
/>
|
||||
<InputField
|
||||
name="user[date_of_birth]"
|
||||
name="user[dateofbirth]"
|
||||
type="date"
|
||||
label={$t('date_of_birth')}
|
||||
bind:value={localUser.date_of_birth}
|
||||
placeholder={$t('placeholder.date_of_birth')}
|
||||
label={$t('dateofbirth')}
|
||||
bind:value={localUser.dateofbirth}
|
||||
placeholder={$t('placeholder.dateofbirth')}
|
||||
/>
|
||||
<InputField
|
||||
name="user[address]"
|
||||
@@ -529,7 +529,7 @@
|
||||
.category-break {
|
||||
grid-column: 1 / -1;
|
||||
height: 1px;
|
||||
background-color: var(--surface0);
|
||||
background-color: var(--overlay0);
|
||||
margin-top: 10px;
|
||||
margin-left: 20%;
|
||||
width: 60%;
|
||||
|
||||
3
frontend/src/lib/css/styles.min.css
vendored
3
frontend/src/lib/css/styles.min.css
vendored
@@ -25,6 +25,7 @@
|
||||
--base: #1e1e2e;
|
||||
--mantle: #181825;
|
||||
--crust: #11111b;
|
||||
--modal-backdrop: rgba(49, 50, 68, 0.45); /* For Mocha theme */
|
||||
}
|
||||
|
||||
@font-face {
|
||||
@@ -385,8 +386,6 @@ li strong {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -1,179 +1,176 @@
|
||||
export default {
|
||||
userStatus: {
|
||||
1: "Nicht verifiziert",
|
||||
2: "Verifiziert",
|
||||
3: "Aktiv",
|
||||
4: "Passiv",
|
||||
5: "Deaktiviert",
|
||||
},
|
||||
userRole: {
|
||||
0: "Mitglied",
|
||||
1: "Betrachter",
|
||||
4: "Bearbeiter",
|
||||
8: "Administrator",
|
||||
},
|
||||
placeholder: {
|
||||
password: "Passwort eingeben...",
|
||||
email: "Emailadresse eingeben...",
|
||||
company: "Firmennamen eingeben...",
|
||||
first_name: "Vornamen eingeben...",
|
||||
last_name: "Nachnamen eingeben...",
|
||||
phone: "Telefonnummer eingeben...",
|
||||
address: "Straße und Hausnummer eingeben...",
|
||||
zip_code: "Postleitzahl eingeben...",
|
||||
city: "Wohnort eingeben...",
|
||||
bank_name: "Namen der Bank eingeben...",
|
||||
parent_member_id: "Mitgliedsnr des Hauptmitglieds eingeben...",
|
||||
bank_account_holder: "Namen eingeben...",
|
||||
iban: "IBAN eingeben..",
|
||||
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",
|
||||
password: "Password zu kurz, mindestens 8 Zeichen",
|
||||
password_match: "Passwörter stimmen nicht überein!",
|
||||
phone: "Ungültiges Format(+491738762387 oder 0173850698)",
|
||||
zip_code: "Ungültige Postleitzahl(Nur deutsche Wohnorte sind zulässig)",
|
||||
bic: "Ungültige BIC",
|
||||
iban: "Ungültige IBAN",
|
||||
date: "Bitte geben Sie ein Datum ein",
|
||||
email: "Ungültige Emailadresse",
|
||||
licence: "Nummer zu kurz(11 Zeichen)",
|
||||
},
|
||||
server: {
|
||||
error: {
|
||||
invalid_json: "JSON Daten sind ungültig",
|
||||
no_auth_token: "Nicht authorisiert, fehlender oder ungültiger Auth-Token",
|
||||
jwt_parsing_error:
|
||||
"Nicht authorisiert, Auth-Token konnte nicht gelesen werden",
|
||||
unauthorized: "Sie sind nicht befugt diese Handlung durchzuführen",
|
||||
internal_server_error:
|
||||
"Verdammt, Fehler auf unserer Seite, probieren Sie es nochmal, danach rufen Sie jemanden vom Verein an.",
|
||||
},
|
||||
validation: {
|
||||
invalid_user_id: "Nutzer ID ungültig",
|
||||
invalid_subscription_model: "Model nicht gefunden",
|
||||
user_not_found: "{field} konnte nicht gefunden werden",
|
||||
invalid_user_data: "Nutzerdaten ungültig",
|
||||
user_not_found_or_wrong_password:
|
||||
"Existiert nicht oder falsches Passwort",
|
||||
email_already_registered:
|
||||
"Ein Mitglied wurde schon mit dieser Emailadresse erstellt.",
|
||||
alphanumunicode: "beinhaltet nicht erlaubte Zeichen",
|
||||
safe_content: "I see what you did there! Do not cross this line!",
|
||||
iban: "Ungültig. Format: DE07123412341234123412",
|
||||
bic: "Ungültig. Format: BELADEBEXXX",
|
||||
email: "Format ungültig",
|
||||
number: "Ist keine Nummer",
|
||||
euDriversLicence: "Ist kein europäischer Führerschein",
|
||||
lte: "Ist zu groß/neu",
|
||||
gt: "Ist zu klein/alt",
|
||||
required: "Feld wird benötigt",
|
||||
image: "Dies ist kein Bild",
|
||||
alphanum: "beinhaltet ungültige Zeichen",
|
||||
alphaunicode: "darf nur aus Buchstaben bestehen",
|
||||
},
|
||||
},
|
||||
licenceCategory: {
|
||||
AM: "Mopeds und leichte vierrädrige Kraftfahrzeuge (50ccm, max 45km/h)",
|
||||
A1: "Leichte Motorräder (125ccm)",
|
||||
A2: "Motorräder mit mittlerer Leistung (max 35kW)",
|
||||
A: "Motorräder",
|
||||
B: "Kraftfahrzeuge ≤ 3500 kg, ≤ 8 Sitzplätze",
|
||||
C1: "Mittelschwere Fahrzeuge -7500 kg",
|
||||
C: "Schwere Nutzfahrzeuge > 3500 kg",
|
||||
D1: "Kleinbusse 9-16 Sitzplätze",
|
||||
D: "Busse > 8 Sitzplätze",
|
||||
BE: "Fahrzeugklasse B mit Anhänger",
|
||||
C1E: "Fahrzeugklasse C1 mit Anhänger",
|
||||
CE: "Fahrzeugklasse C mit Anhänger",
|
||||
D1E: "Fahrzeugklasse D1 mit Anhänger",
|
||||
DE: "Fahrzeugklasse D mit Anhänger",
|
||||
L: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 40km/h",
|
||||
T: "Land-, Forstwirtschaftsfahrzeuge, Stapler max 60km/h",
|
||||
},
|
||||
users: "Mitglieder",
|
||||
user: {
|
||||
login: "Nutzer Anmeldung",
|
||||
edit: "Nutzer bearbeiten",
|
||||
user: "Nutzer",
|
||||
management: "Mitgliederverwaltung",
|
||||
id: "Mitgliedsnr",
|
||||
name: "Name",
|
||||
email: "Email",
|
||||
status: "Status",
|
||||
role: "Nutzerrolle",
|
||||
},
|
||||
cancel: "Abbrechen",
|
||||
confirm: "Bestätigen",
|
||||
actions: "Aktionen",
|
||||
edit: "Bearbeiten",
|
||||
delete: "Löschen",
|
||||
mandate_date_signed: "Mandatserteilungsdatum",
|
||||
licence_categories: "Führerscheinklassen",
|
||||
subscription_model: "Mitgliedschatfsmodell",
|
||||
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",
|
||||
conditions: "Bedingungen",
|
||||
unknown: "Unbekannt",
|
||||
notes: "Notizen",
|
||||
address: "Straße & Hausnummer",
|
||||
city: "Wohnort",
|
||||
zip_code: "PLZ",
|
||||
forgot_password: "Passwort vergessen?",
|
||||
password: "Passwort",
|
||||
password_repeat: "Passwort wiederholen",
|
||||
email: "Email",
|
||||
company: "Firma",
|
||||
login: "Anmeldung",
|
||||
profile: "Profil",
|
||||
membership: "Mitgliedschaft",
|
||||
bankaccount: "Kontodaten",
|
||||
first_name: "Vorname",
|
||||
last_name: "Nachname",
|
||||
name: "Name",
|
||||
phone: "Telefonnummer",
|
||||
date_of_birth: "Geburtstag",
|
||||
status: "Status",
|
||||
start: "Beginn",
|
||||
end: "Ende",
|
||||
parent_member_id: "Hauptmitgliedsnr.",
|
||||
bank_account_holder: "Kontoinhaber",
|
||||
bank_name: "Bank",
|
||||
iban: "IBAN",
|
||||
bic: "BIC",
|
||||
mandate_reference: "SEPA Mandat",
|
||||
subscriptions: "Tarifmodelle",
|
||||
payments: "Zahlungen",
|
||||
add_new: "Neu",
|
||||
included_hours_per_year: "Inkludierte Stunden pro Jahr",
|
||||
included_hours_per_month: "Inkludierte Stunden pro Monat",
|
||||
userStatus: {
|
||||
1: 'Nicht verifiziert',
|
||||
2: 'Verifiziert',
|
||||
3: 'Aktiv',
|
||||
4: 'Passiv',
|
||||
5: 'Deaktiviert'
|
||||
},
|
||||
userRole: {
|
||||
0: 'Mitglied',
|
||||
1: 'Betrachter',
|
||||
4: 'Bearbeiter',
|
||||
8: 'Administrator'
|
||||
},
|
||||
placeholder: {
|
||||
password: 'Passwort eingeben...',
|
||||
email: 'Emailadresse eingeben...',
|
||||
company: 'Firmennamen eingeben...',
|
||||
first_name: 'Vornamen eingeben...',
|
||||
last_name: 'Nachnamen eingeben...',
|
||||
phone: 'Telefonnummer eingeben...',
|
||||
address: 'Straße und Hausnummer eingeben...',
|
||||
zip_code: 'Postleitzahl eingeben...',
|
||||
city: 'Wohnort eingeben...',
|
||||
bank_name: 'Namen der Bank eingeben...',
|
||||
parent_member_id: 'Mitgliedsnr des Hauptmitglieds eingeben...',
|
||||
bank_account_holder: 'Namen eingeben...',
|
||||
iban: 'IBAN eingeben..',
|
||||
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',
|
||||
password: 'Password zu kurz, mindestens 8 Zeichen',
|
||||
password_match: 'Passwörter stimmen nicht überein!',
|
||||
phone: 'Ungültiges Format(+491738762387 oder 0173850698)',
|
||||
zip_code: 'Ungültige Postleitzahl(Nur deutsche Wohnorte sind zulässig)',
|
||||
bic: 'Ungültige BIC',
|
||||
iban: 'Ungültige IBAN',
|
||||
date: 'Bitte geben Sie ein Datum ein',
|
||||
email: 'Ungültige Emailadresse',
|
||||
licence: 'Nummer zu kurz(11 Zeichen)'
|
||||
},
|
||||
server: {
|
||||
error: {
|
||||
invalid_json: 'JSON Daten sind ungültig',
|
||||
no_auth_token: 'Nicht authorisiert, fehlender oder ungültiger Auth-Token',
|
||||
jwt_parsing_error: 'Nicht authorisiert, Auth-Token konnte nicht gelesen werden',
|
||||
unauthorized: 'Sie sind nicht befugt diese Handlung durchzuführen',
|
||||
internal_server_error:
|
||||
'Verdammt, Fehler auf unserer Seite, probieren Sie es nochmal, danach rufen Sie jemanden vom Verein an.'
|
||||
},
|
||||
validation: {
|
||||
invalid_user_id: 'Nutzer ID ungültig',
|
||||
invalid_subscription_model: 'Model nicht gefunden',
|
||||
user_not_found: '{field} konnte nicht gefunden werden',
|
||||
invalid_user_data: 'Nutzerdaten ungültig',
|
||||
user_not_found_or_wrong_password: 'Existiert nicht oder falsches Passwort',
|
||||
email_already_registered: 'Ein Mitglied wurde schon mit dieser Emailadresse erstellt.',
|
||||
alphanumunicode: 'beinhaltet nicht erlaubte Zeichen',
|
||||
safe_content: 'I see what you did there! Do not cross this line!',
|
||||
iban: 'Ungültig. Format: DE07123412341234123412',
|
||||
bic: 'Ungültig. Format: BELADEBEXXX',
|
||||
email: 'Format ungültig',
|
||||
number: 'Ist keine Nummer',
|
||||
euDriversLicence: 'Ist kein europäischer Führerschein',
|
||||
lte: 'Ist zu groß/neu',
|
||||
gt: 'Ist zu klein/alt',
|
||||
required: 'Feld wird benötigt',
|
||||
image: 'Dies ist kein Bild',
|
||||
alphanum: 'beinhaltet ungültige Zeichen',
|
||||
alphaunicode: 'darf nur aus Buchstaben bestehen'
|
||||
}
|
||||
},
|
||||
licenceCategory: {
|
||||
AM: 'Mopeds und leichte vierrädrige Kraftfahrzeuge (50ccm, max 45km/h)',
|
||||
A1: 'Leichte Motorräder (125ccm)',
|
||||
A2: 'Motorräder mit mittlerer Leistung (max 35kW)',
|
||||
A: 'Motorräder',
|
||||
B: 'Kraftfahrzeuge ≤ 3500 kg, ≤ 8 Sitzplätze',
|
||||
C1: 'Mittelschwere Fahrzeuge -7500 kg',
|
||||
C: 'Schwere Nutzfahrzeuge > 3500 kg',
|
||||
D1: 'Kleinbusse 9-16 Sitzplätze',
|
||||
D: 'Busse > 8 Sitzplätze',
|
||||
BE: 'Fahrzeugklasse B mit Anhänger',
|
||||
C1E: 'Fahrzeugklasse C1 mit Anhänger',
|
||||
CE: 'Fahrzeugklasse C mit Anhänger',
|
||||
D1E: 'Fahrzeugklasse D1 mit Anhänger',
|
||||
DE: 'Fahrzeugklasse D mit Anhänger',
|
||||
L: 'Land-, Forstwirtschaftsfahrzeuge, Stapler max 40km/h',
|
||||
T: 'Land-, Forstwirtschaftsfahrzeuge, Stapler max 60km/h'
|
||||
},
|
||||
users: 'Mitglieder',
|
||||
user: {
|
||||
login: 'Nutzer Anmeldung',
|
||||
edit: 'Nutzer bearbeiten',
|
||||
user: 'Nutzer',
|
||||
management: 'Mitgliederverwaltung',
|
||||
id: 'Mitgliedsnr',
|
||||
name: 'Name',
|
||||
email: 'Email',
|
||||
status: 'Status',
|
||||
role: 'Nutzerrolle'
|
||||
},
|
||||
cancel: 'Abbrechen',
|
||||
confirm: 'Bestätigen',
|
||||
actions: 'Aktionen',
|
||||
edit: 'Bearbeiten',
|
||||
delete: 'Löschen',
|
||||
mandate_date_signed: 'Mandatserteilungsdatum',
|
||||
licence_categories: 'Führerscheinklassen',
|
||||
subscription_model: 'Mitgliedschatfsmodell',
|
||||
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',
|
||||
conditions: 'Bedingungen',
|
||||
unknown: 'Unbekannt',
|
||||
notes: 'Notizen',
|
||||
address: 'Straße & Hausnummer',
|
||||
city: 'Wohnort',
|
||||
zip_code: 'PLZ',
|
||||
forgot_password: 'Passwort vergessen?',
|
||||
password: 'Passwort',
|
||||
password_repeat: 'Passwort wiederholen',
|
||||
email: 'Email',
|
||||
company: 'Firma',
|
||||
login: 'Anmeldung',
|
||||
profile: 'Profil',
|
||||
membership: 'Mitgliedschaft',
|
||||
bankaccount: 'Kontodaten',
|
||||
first_name: 'Vorname',
|
||||
last_name: 'Nachname',
|
||||
name: 'Name',
|
||||
phone: 'Telefonnummer',
|
||||
dateofbirth: 'Geburtstag',
|
||||
status: 'Status',
|
||||
start: 'Beginn',
|
||||
end: 'Ende',
|
||||
parent_member_id: 'Hauptmitgliedsnr.',
|
||||
bank_account_holder: 'Kontoinhaber',
|
||||
bank_name: 'Bank',
|
||||
iban: 'IBAN',
|
||||
bic: 'BIC',
|
||||
mandate_reference: 'SEPA Mandat',
|
||||
subscriptions: 'Tarifmodelle',
|
||||
payments: 'Zahlungen',
|
||||
add_new: 'Neu',
|
||||
included_hours_per_year: 'Inkludierte Stunden pro Jahr',
|
||||
included_hours_per_month: 'Inkludierte Stunden pro Monat',
|
||||
|
||||
// For payments section
|
||||
payment: {
|
||||
id: "Zahlungs-Nr",
|
||||
amount: "Betrag",
|
||||
date: "Datum",
|
||||
status: "Status",
|
||||
},
|
||||
// For payments section
|
||||
payment: {
|
||||
id: 'Zahlungs-Nr',
|
||||
amount: 'Betrag',
|
||||
date: 'Datum',
|
||||
status: 'Status'
|
||||
},
|
||||
|
||||
// For subscription statuses
|
||||
subscriptionStatus: {
|
||||
pending: "Ausstehend",
|
||||
completed: "Abgeschlossen",
|
||||
failed: "Fehlgeschlagen",
|
||||
cancelled: "Storniert",
|
||||
},
|
||||
// For subscription statuses
|
||||
subscriptionStatus: {
|
||||
pending: 'Ausstehend',
|
||||
completed: 'Abgeschlossen',
|
||||
failed: 'Fehlgeschlagen',
|
||||
cancelled: 'Storniert'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
// @ts-nocheck
|
||||
import { quintOut } from "svelte/easing";
|
||||
import { crossfade } from "svelte/transition";
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { crossfade } from 'svelte/transition';
|
||||
|
||||
export const [send, receive] = crossfade({
|
||||
duration: (d) => Math.sqrt(d * 200),
|
||||
duration: (d) => Math.sqrt(d * 200),
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fallback(node, params) {
|
||||
const style = getComputedStyle(node);
|
||||
const transform = style.transform === "none" ? "" : style.transform;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fallback(node, params) {
|
||||
const style = getComputedStyle(node);
|
||||
const transform = style.transform === 'none' ? '' : style.transform;
|
||||
|
||||
return {
|
||||
duration: 600,
|
||||
easing: quintOut,
|
||||
css: (t) => `
|
||||
return {
|
||||
duration: 600,
|
||||
easing: quintOut,
|
||||
css: (t) => `
|
||||
transform: ${transform} scale(${t});
|
||||
opacity: ${t}
|
||||
`,
|
||||
};
|
||||
},
|
||||
`
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -27,9 +27,9 @@ export const [send, receive] = crossfade({
|
||||
* @param {string} email - The email to validate
|
||||
*/
|
||||
export const isValidEmail = (email) => {
|
||||
const EMAIL_REGEX =
|
||||
/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
|
||||
return EMAIL_REGEX.test(email.trim());
|
||||
const EMAIL_REGEX =
|
||||
/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
|
||||
return EMAIL_REGEX.test(email.trim());
|
||||
};
|
||||
/**
|
||||
* Validates a strong password field
|
||||
@@ -37,11 +37,9 @@ export const isValidEmail = (email) => {
|
||||
* @param {string} password - The password to validate
|
||||
*/
|
||||
export const isValidPasswordStrong = (password) => {
|
||||
const strongRegex = new RegExp(
|
||||
"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})"
|
||||
);
|
||||
const strongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})');
|
||||
|
||||
return strongRegex.test(password.trim());
|
||||
return strongRegex.test(password.trim());
|
||||
};
|
||||
/**
|
||||
* Validates a medium password field
|
||||
@@ -49,11 +47,11 @@ export const isValidPasswordStrong = (password) => {
|
||||
* @param {string} password - The password to validate
|
||||
*/
|
||||
export const isValidPasswordMedium = (password) => {
|
||||
const mediumRegex = new RegExp(
|
||||
"^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})"
|
||||
);
|
||||
const mediumRegex = new RegExp(
|
||||
'^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})'
|
||||
);
|
||||
|
||||
return mediumRegex.test(password.trim());
|
||||
return mediumRegex.test(password.trim());
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -63,22 +61,22 @@ export const isValidPasswordMedium = (password) => {
|
||||
*/
|
||||
|
||||
export function isEmpty(obj) {
|
||||
for (const _i in obj) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
for (const _i in obj) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function toRFC3339(dateString) {
|
||||
if (!dateString) dateString = "0001-01-01T00:00:00.000Z";
|
||||
const date = new Date(dateString);
|
||||
return date.toISOString();
|
||||
if (!dateString) dateString = '0001-01-01T00:00:00.000Z';
|
||||
const date = new Date(dateString);
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
export function fromRFC3339(dateString) {
|
||||
if (!dateString) dateString = "0001-01-01T00:00:00.000Z";
|
||||
const date = new Date(dateString);
|
||||
return date.toISOString().split("T")[0];
|
||||
if (!dateString) dateString = '0001-01-01T00:00:00.000Z';
|
||||
const date = new Date(dateString);
|
||||
return date.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,28 +84,26 @@ export function fromRFC3339(dateString) {
|
||||
* @param {App.Locals.User} user - The user object to format
|
||||
*/
|
||||
export function userDatesFromRFC3339(user) {
|
||||
if (user.date_of_birth) {
|
||||
user.date_of_birth = fromRFC3339(user.date_of_birth);
|
||||
}
|
||||
if (user.membership) {
|
||||
if (user.membership.start_date) {
|
||||
user.membership.start_date = fromRFC3339(user.membership.start_date);
|
||||
}
|
||||
if (user.membership.end_date) {
|
||||
user.membership.end_date = fromRFC3339(user.membership.end_date);
|
||||
}
|
||||
}
|
||||
if (user.licence?.issued_date) {
|
||||
user.licence.issued_date = fromRFC3339(user.licence.issued_date);
|
||||
}
|
||||
if (user.licence?.expiration_date) {
|
||||
user.licence.expiration_date = fromRFC3339(user.licence.expiration_date);
|
||||
}
|
||||
if (user.bank_account && user.bank_account.mandate_date_signed) {
|
||||
user.bank_account.mandate_date_signed = fromRFC3339(
|
||||
user.bank_account.mandate_date_signed
|
||||
);
|
||||
}
|
||||
if (user.dateofbirth) {
|
||||
user.dateofbirth = fromRFC3339(user.dateofbirth);
|
||||
}
|
||||
if (user.membership) {
|
||||
if (user.membership.start_date) {
|
||||
user.membership.start_date = fromRFC3339(user.membership.start_date);
|
||||
}
|
||||
if (user.membership.end_date) {
|
||||
user.membership.end_date = fromRFC3339(user.membership.end_date);
|
||||
}
|
||||
}
|
||||
if (user.licence?.issued_date) {
|
||||
user.licence.issued_date = fromRFC3339(user.licence.issued_date);
|
||||
}
|
||||
if (user.licence?.expiration_date) {
|
||||
user.licence.expiration_date = fromRFC3339(user.licence.expiration_date);
|
||||
}
|
||||
if (user.bank_account && user.bank_account.mandate_date_signed) {
|
||||
user.bank_account.mandate_date_signed = fromRFC3339(user.bank_account.mandate_date_signed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,28 +111,26 @@ export function userDatesFromRFC3339(user) {
|
||||
* @param {App.Locals.User} user - The user object to format
|
||||
*/
|
||||
export function userDatesToRFC3339(user) {
|
||||
if (user.date_of_birth) {
|
||||
user.date_of_birth = toRFC3339(user.date_of_birth);
|
||||
}
|
||||
if (user.membership) {
|
||||
if (user.membership.start_date) {
|
||||
user.membership.start_date = toRFC3339(user.membership.start_date);
|
||||
}
|
||||
if (user.membership.end_date) {
|
||||
user.membership.end_date = toRFC3339(user.membership.end_date);
|
||||
}
|
||||
}
|
||||
if (user.licence?.issued_date) {
|
||||
user.licence.issued_date = toRFC3339(user.licence.issued_date);
|
||||
}
|
||||
if (user.licence?.expiration_date) {
|
||||
user.licence.expiration_date = toRFC3339(user.licence.expiration_date);
|
||||
}
|
||||
if (user.bank_account && user.bank_account.mandate_date_signed) {
|
||||
user.bank_account.mandate_date_signed = toRFC3339(
|
||||
user.bank_account.mandate_date_signed
|
||||
);
|
||||
}
|
||||
if (user.dateofbirth) {
|
||||
user.dateofbirth = toRFC3339(user.dateofbirth);
|
||||
}
|
||||
if (user.membership) {
|
||||
if (user.membership.start_date) {
|
||||
user.membership.start_date = toRFC3339(user.membership.start_date);
|
||||
}
|
||||
if (user.membership.end_date) {
|
||||
user.membership.end_date = toRFC3339(user.membership.end_date);
|
||||
}
|
||||
}
|
||||
if (user.licence?.issued_date) {
|
||||
user.licence.issued_date = toRFC3339(user.licence.issued_date);
|
||||
}
|
||||
if (user.licence?.expiration_date) {
|
||||
user.licence.expiration_date = toRFC3339(user.licence.expiration_date);
|
||||
}
|
||||
if (user.bank_account && user.bank_account.mandate_date_signed) {
|
||||
user.bank_account.mandate_date_signed = toRFC3339(user.bank_account.mandate_date_signed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,33 +139,33 @@ export function userDatesToRFC3339(user) {
|
||||
* @returns {array} The formatted error object
|
||||
*/
|
||||
export function formatError(obj) {
|
||||
const errors = [];
|
||||
if (typeof obj === "object" && obj !== null) {
|
||||
if (Array.isArray(obj)) {
|
||||
obj.forEach((error) => {
|
||||
errors.push({
|
||||
field: error.field,
|
||||
key: error.key,
|
||||
id: Math.random() * 1000,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Object.keys(obj).forEach((field) => {
|
||||
errors.push({
|
||||
field: field,
|
||||
key: obj[field].key,
|
||||
id: Math.random() * 1000,
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
errors.push({
|
||||
field: "general",
|
||||
key: obj,
|
||||
id: 0,
|
||||
});
|
||||
}
|
||||
return errors;
|
||||
const errors = [];
|
||||
if (typeof obj === 'object' && obj !== null) {
|
||||
if (Array.isArray(obj)) {
|
||||
obj.forEach((error) => {
|
||||
errors.push({
|
||||
field: error.field,
|
||||
key: error.key,
|
||||
id: Math.random() * 1000
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Object.keys(obj).forEach((field) => {
|
||||
errors.push({
|
||||
field: field,
|
||||
key: obj[field].key,
|
||||
id: Math.random() * 1000
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
errors.push({
|
||||
field: 'general',
|
||||
key: obj,
|
||||
id: 0
|
||||
});
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,26 +174,26 @@ export function formatError(obj) {
|
||||
* @param {import('RequestEvent<Partial<Record<string, string>>, string | null>')} event - The event object
|
||||
*/
|
||||
export function refreshCookie(newToken, event) {
|
||||
if (newToken) {
|
||||
const match = newToken.match(/jwt=([^;]+)/);
|
||||
if (match) {
|
||||
if (event) {
|
||||
event.cookies.set("jwt", match[1], {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production", // Secure in production
|
||||
sameSite: "lax",
|
||||
maxAge: 5 * 24 * 60 * 60, // 5 days in seconds
|
||||
});
|
||||
} else {
|
||||
cookies.set("jwt", match[1], {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production", // Secure in production
|
||||
sameSite: "lax",
|
||||
maxAge: 5 * 24 * 60 * 60, // 5 days in seconds
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newToken) {
|
||||
const match = newToken.match(/jwt=([^;]+)/);
|
||||
if (match) {
|
||||
if (event) {
|
||||
event.cookies.set('jwt', match[1], {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production', // Secure in production
|
||||
sameSite: 'lax',
|
||||
maxAge: 5 * 24 * 60 * 60 // 5 days in seconds
|
||||
});
|
||||
} else {
|
||||
cookies.set('jwt', match[1], {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production', // Secure in production
|
||||
sameSite: 'lax',
|
||||
maxAge: 5 * 24 * 60 * 60 // 5 days in seconds
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
121
frontend/src/lib/utils/processing.js
Normal file
121
frontend/src/lib/utils/processing.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import { toRFC3339 } from './helpers';
|
||||
|
||||
/**
|
||||
* Converts FormData to a nested object structure
|
||||
* @param {FormData} formData - The FormData object to convert
|
||||
* @returns {{ user: Partial<App.Locals['user']> }} Nested object representation of the form data
|
||||
*/
|
||||
export function formDataToObject(formData) {
|
||||
/** @type { Partial<App.Locals['user']> } */
|
||||
const object = {};
|
||||
|
||||
console.log('Form data entries:');
|
||||
for (const [key, value] of formData.entries()) {
|
||||
console.log('Key:', key, 'Value:', value);
|
||||
}
|
||||
for (const [key, value] of formData.entries()) {
|
||||
/** @type {string[]} */
|
||||
const keys = key.match(/\[([^\]]+)\]/g)?.map((k) => k.slice(1, -1)) || [key];
|
||||
console.log('Processed keys:', keys);
|
||||
/** @type {Record<string, any>} */
|
||||
let current = object;
|
||||
|
||||
console.log('Current object state:', JSON.stringify(current));
|
||||
for (let i = 0; i < keys.length - 1; i++) {
|
||||
/**
|
||||
* Create nested object if it doesn't exist
|
||||
* @type {Record<string, any>}
|
||||
* @description Ensures proper nesting structure for user data fields
|
||||
* @example
|
||||
* // For input name="user[membership][status]"
|
||||
* // Creates: { user: { membership: { status: value } } }
|
||||
*/
|
||||
current[keys[i]] = current[keys[i]] || {};
|
||||
/**
|
||||
* Move to the next level of the object
|
||||
* @type {Record<string, any>}
|
||||
*/
|
||||
current = current[keys[i]];
|
||||
}
|
||||
|
||||
const lastKey = keys[keys.length - 1];
|
||||
if (lastKey.endsWith('[]')) {
|
||||
/**
|
||||
* Handle array fields (licence categories)
|
||||
*/
|
||||
const arrayKey = lastKey.slice(0, -2);
|
||||
current[arrayKey] = current[arrayKey] || [];
|
||||
current[arrayKey].push(value);
|
||||
} else {
|
||||
current[lastKey] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return { user: object };
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the raw form data into the expected user data structure
|
||||
* @param {{ user: Partial<App.Locals['user']> } } rawData - The raw form data object
|
||||
* @returns {{ user: Partial<App.Locals['user']> }} Processed user data
|
||||
*/
|
||||
export function processFormData(rawData) {
|
||||
/** @type {{ user: Partial<App.Locals['user']> }} */
|
||||
const processedData = {
|
||||
user: {
|
||||
id: Number(rawData.user.id) || 0,
|
||||
status: Number(rawData.user.status),
|
||||
role_id: Number(rawData.user.role_id),
|
||||
first_name: String(rawData.user.first_name),
|
||||
last_name: String(rawData.user.last_name),
|
||||
email: String(rawData.user.email),
|
||||
phone: String(rawData.user.phone || ''),
|
||||
company: String(rawData.user.company || ''),
|
||||
dateofbirth: toRFC3339(rawData.user.dateofbirth),
|
||||
address: String(rawData.user.address || ''),
|
||||
zip_code: String(rawData.user.zip_code || ''),
|
||||
city: String(rawData.user.city || ''),
|
||||
notes: String(rawData.user.notes || ''),
|
||||
profile_picture: String(rawData.user.profile_picture || ''),
|
||||
|
||||
membership: {
|
||||
id: Number(rawData.user.membership?.id) || 0,
|
||||
status: Number(rawData.user.membership?.status),
|
||||
start_date: toRFC3339(rawData.user.membership?.start_date),
|
||||
end_date: toRFC3339(rawData.user.membership?.end_date),
|
||||
parent_member_id: Number(rawData.user.membership?.parent_member_id) || 0,
|
||||
subscription_model: {
|
||||
id: Number(rawData.user.membership?.subscription_model?.id) || 0,
|
||||
name: String(rawData.user.membership?.subscription_model?.name) || ''
|
||||
}
|
||||
},
|
||||
|
||||
licence: {
|
||||
id: Number(rawData.user.licence?.id) || 0,
|
||||
status: Number(rawData.user.licence?.status),
|
||||
licence_number: String(rawData.user.licence?.licence_number || ''),
|
||||
issued_date: toRFC3339(rawData.user.licence?.issued_date),
|
||||
expiration_date: toRFC3339(rawData.user.licence?.expiration_date),
|
||||
country: String(rawData.user.licence?.country || ''),
|
||||
licence_categories: rawData.user.licence?.licence_categories || []
|
||||
},
|
||||
|
||||
bank_account: {
|
||||
id: Number(rawData.user.bank_account?.id) || 0,
|
||||
account_holder_name: String(rawData.user.bank_account?.account_holder_name || ''),
|
||||
bank: String(rawData.user.bank_account?.bank || ''),
|
||||
iban: String(rawData.user.bank_account?.iban || ''),
|
||||
bic: String(rawData.user.bank_account?.bic || ''),
|
||||
mandate_reference: String(rawData.user.bank_account?.mandate_reference || ''),
|
||||
mandate_date_signed: toRFC3339(rawData.user.bank_account?.mandate_date_signed)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Remove undefined or null properties
|
||||
const cleanUpdateData = JSON.parse(JSON.stringify(processedData), (key, value) =>
|
||||
value !== null && value !== '' ? value : undefined
|
||||
);
|
||||
console.dir(cleanUpdateData);
|
||||
return cleanUpdateData;
|
||||
}
|
||||
Reference in New Issue
Block a user