@progressive-development/pd-contact
Version:
Progressive Development Contact component
547 lines (533 loc) • 19.3 kB
JavaScript
import { LitElement, css, html } from 'lit';
import { property, state, query } from 'lit/decorators.js';
import { msg, str } from '@lit/localize';
import '@progressive-development/pd-icon/pd-icon';
import '@progressive-development/pd-forms/pd-checkbox';
import '@progressive-development/pd-forms/pd-form-container';
import '@progressive-development/pd-forms/pd-form-row';
import '@progressive-development/pd-forms/pd-input';
import '@progressive-development/pd-forms/pd-select';
import '@progressive-development/pd-forms/pd-radio-group';
import { C_TYPE, C_COMPANY, C_BTWNR, C_FIRSTNAME, C_LASTNAME, C_STREET, C_CITY, C_ZIP, C_ADDITIONAL, C_PROPERTY_DATE, C_PHONE1, C_EMAIL } from '../types.js';
var __defProp = Object.defineProperty;
var __decorateClass = (decorators, target, key, kind) => {
var result = void 0 ;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (decorator(target, key, result) ) || result;
if (result) __defProp(target, key, result);
return result;
};
const countryPrefixes = {
de: "+49",
// Deutschland
be: "+32",
// Belgien
nl: "+31",
// Niederland
fr: "+33",
// Frankreich
es: "+34"
// Spanien
};
function transformPhone(phone, country) {
if (!phone || typeof phone !== "string") return "";
const countryPrefix = countryPrefixes[country];
if (!countryPrefix) throw new Error(`Unbekanntes Land: ${country}`);
const cleanedPhone = phone.replace(/\s+/g, "").replace(/[^0-9+]/g, "");
if (cleanedPhone.startsWith("+")) return cleanedPhone;
if (cleanedPhone.startsWith("0"))
return countryPrefix + cleanedPhone.slice(1);
return "";
}
const yearSelection = [
{
value: "UNDEF",
name: msg("Baujahr auswählen", {
id: "pd.contact.property.year.selection"
})
},
...Array.from({ length: 2025 - 2014 + 1 }, (_, i) => {
const year = (2014 + i).toString();
return { value: year, name: year };
})
];
const _PdContact = class _PdContact extends LitElement {
constructor() {
super(...arguments);
this.addressTitle = msg("Adresse", { id: "pd.contact.address.title" });
this.phoneMailLink = false;
this.summary = false;
this.withPropertyDate = false;
this.requiredFields = [];
this.inputFields = [];
this._business = false;
}
static {
this.styles = [
css`
:host {
display: block;
}
.contact {
display: flex;
flex-direction: column;
}
address {
color: var(
--pd-contact-address-col,
var(--pd-default-font-content-col)
);
line-height: 1.8;
font-style: normal;
}
dl {
margin: 0;
padding: 0;
}
dt {
font-weight: bold;
padding-top: 10px;
color: var(
--pd-contact-address-title-col,
var(--pd-default-font-title-col)
);
}
dd {
font-weight: 400;
font-size: 1em;
margin: 0;
padding: 0;
}
dd.larger {
padding-top: 3px;
padding-bottom: 5px;
}
.contact-form {
--row-padding-top: 10px;
}
.link-icon {
--pd-icon-bg-col-active: #859900;
--pd-icon-bg-col-hover: #859900;
--pd-icon-size: 14px;
--pd-icon-col-active: white;
}
.link-item {
display: flex;
align-items: center;
text-decoration: none;
color: var(--pd-default-font-link-col, inherit);
}
.link-item:hover {
color: var(--pd-default-font-link-col-hover, #451a46);
}
`
];
}
willUpdate(changedProps) {
if (changedProps.has("contact") && this.contact) {
this._business = this.contact.business ?? false;
}
}
render() {
return html`
<div class="contact">
${this.summary ? this._renderViewContact() : this._renderEditContact()}
</div>
`;
}
_renderEditContact() {
return html`
<pd-form-container id="contactContainerId" requiredFieldInfo autoTrimm>
${this.inputFields.length === 0 || this._showInput(C_TYPE) ? html`
<pd-form-row>
<pd-radio-group
id="contactTypeRadioId"
class="quarter3"
label="${msg("Typ", { id: "pd.contact.label.type" })}"
required
initValue="${this._getRadioValue()}"
@pd-form-element-change="${this._switchAddressType}"
style="--group-gap: 20px;"
>
<pd-checkbox
checkType="RADIO"
initValue="${this.contact ? !this.contact.business : true}"
valueName="private"
>${msg("Privatperson", {
id: "pd.contact.check.private"
})}</pd-checkbox
>
<pd-checkbox
checkType="RADIO"
valueName="business"
initValue="${this.contact ? this.contact.business || false : false}"
>${msg("Unternehmen", {
id: "pd.contact.check.company"
})}</pd-checkbox
>
</pd-radio-group>
</pd-form-row>
` : ""}
${this._business ? html`
${this.inputFields.length === 0 || this._showInput(C_COMPANY) ? html`
<pd-form-row class="contact-form">
<pd-input
id="compNameId"
class="quarter3"
label="${msg("Name des Unternehmen", {
id: "pd.contact.label.company"
})}"
?required="${this._isRequired(C_COMPANY)}"
initValue="${this.contact?.companyName || ""}"
valueName="companyName"
autoCompleteName="organization"
></pd-input>
</pd-form-row>
` : ""}
${this.inputFields.length === 0 || this._showInput(C_BTWNR) ? html`
<pd-form-row class="contact-form">
<pd-input
id="vatId"
class="quarter3"
label="${msg("USt-IdNr.", {
id: "pd.contact.label.btw"
})}"
?required="${this._isRequired(C_BTWNR)}"
fieldType="vat"
valueName="vatNr"
initValue="${this.contact?.vatNr || ""}"
autoCompleteName="vat"
></pd-input>
</pd-form-row>
` : ""}
` : html`
${this.inputFields.length === 0 || this._showInput(C_FIRSTNAME) ? html`
<pd-form-row class="contact-form">
<pd-input
id="firstNameId"
class="quarter3"
label="${msg("Vorname", {
id: "pd.contact.label.firstName"
})}"
valueName="firstName"
initValue="${this.contact?.firstName || ""}"
autoCompleteName="given-name"
?required="${this._isRequired(C_FIRSTNAME)}"
></pd-input>
</pd-form-row>
` : ""}
${this.inputFields.length === 0 || this._showInput(C_LASTNAME) ? html`
<pd-form-row class="contact-form">
<pd-input
id="lastNameId"
class="quarter3"
label="${msg("Nachname", {
id: "pd.contact.label.lastName"
})}"
valueName="lastName"
initValue="${this.contact?.lastName || ""}"
autoCompleteName="family-name"
?required="${this._isRequired(C_LASTNAME)}"
></pd-input>
</pd-form-row>
` : ""}
`}
${this.inputFields.length === 0 || this._showInput(C_STREET) ? html`
<pd-form-row class="contact-form">
<pd-input
id="streetId"
class="quarter2"
label="${msg("Strasse", { id: "pd.contact.label.street" })}"
valueName="street"
initValue="${this.contact?.street || ""}"
autoCompleteName="street-address"
?required="${this._isRequired(C_STREET)}"
></pd-input>
<pd-input
id="streetNrId"
class="quarter1"
label="${msg("Nr.", { id: "pd.contact.label.streetNr" })}"
valueName="streetNr"
initValue="${this.contact?.streetNr || ""}"
?required="${this._isRequired(C_STREET)}"
></pd-input>
</pd-form-row>
` : ""}
${this.inputFields.length === 0 || this._showInput(C_CITY) ? html`
<pd-form-row class="contact-form">
${this.match && this.match.zip ? html`
<pd-input
readonly
id="zipId"
class="quarter1"
label="${msg("PLZ", { id: "pd.contact.label.zip" })}"
valueName="zip"
initValue="${this.match.zip}"
></pd-input>
` : html`
<pd-input
id="zipId"
class="quarter1"
label="${msg("PLZ", { id: "pd.contact.label.zip" })}"
fieldType="number"
valueName="zip"
initValue="${this.contact?.zip || ""}"
autoCompleteName="postal-code"
?required="${this._isRequired(C_ZIP)}"
></pd-input>
`}
<pd-input
id="cityId"
class="quarter2"
label="${msg("Ort", { id: "pd.contact.label.city" })}"
valueName="city"
initValue="${this.contact?.city || ""}"
autoCompleteName="locality"
?required="${this._isRequired(C_CITY)}"
></pd-input>
</pd-form-row>
` : ""}
${this.inputFields.length === 0 || this._showInput(C_ADDITIONAL) ? html`
<pd-form-row class="contact-form">
<pd-input
class="quarter3"
id="additionalHintId"
label="${msg("Addresszusatz", {
id: "pd.contact.label.additional"
})}"
initValue="${this.contact?.additionalHint || ""}"
valueName="additionalHint"
?required="${this._isRequired(C_ADDITIONAL)}"
></pd-input>
</pd-form-row>
` : ""}
${this.withPropertyDate ? html`
<pd-form-row class="contact-form">
<pd-select
class="quarter3"
id="propertyDateId"
label="${msg("Datum der Immobilie", {
id: "pd.contact.label.propertyDate"
})}"
initValue="${this.contact?.propertyDate || ""}"
.values="${yearSelection}"
?required="${this._isRequired(C_PROPERTY_DATE)}"
></pd-select>
</pd-form-row>
` : ""}
${this.inputFields.length === 0 || this._showInput(C_PHONE1) ? html`
<pd-form-row class="contact-form">
<pd-input
id="phoneId"
class="quarter3"
label="${msg("Telefon", { id: "pd.contact.label.phone" })}"
name="phone"
valueName="phone1"
initValue="${this.contact?.phone1 || ""}"
fieldType="phone"
autoCompleteName="tel"
?required="${this._isRequired(C_PHONE1)}"
></pd-input>
</pd-form-row>
` : ""}
${this.inputFields.length === 0 || this._showInput(C_EMAIL) ? html`
<pd-form-row class="contact-form">
<pd-input
id="mailId"
class="quarter3"
label="${msg("E-mail", { id: "pd.contact.label.email" })}"
fieldType="mail"
valueName="email"
initValue="${this.contact?.email || ""}"
autoCompleteName="email"
?required="${this._isRequired(C_EMAIL)}"
></pd-input>
</pd-form-row>
` : ""}
</pd-form-container>
`;
}
_getRadioValue() {
if (this.contact) {
return this.contact.business ? "business" : "private";
}
return "private";
}
_renderViewContact() {
if (!this.contact) return html`<p>Contact undefined</p>`;
const trPhoneNr = transformPhone(
this.contact.phone1 || "",
this.contact.country || "be"
);
return html`
<address>
<dl>
<dt>${this.addressTitle}</dt>
<dd>${this.contact.companyName}</dd>
<dd>${this.contact.vatNr}</dd>
<dd>${this._getFullName()}</dd>
<dd>${this._getFullStreet()}</dd>
<dd>${this._getFullLocation()}</dd>
${this.contact.additionalHint ? html`<dd>${this.contact.additionalHint}</dd>` : ""}
${this.contact.propertyDate ? html`<dd>
${msg(str`Baujahr: ${this.contact.propertyDate}`, {
id: "pd.contact.label.summary.propertyDate"
})}
</dd>` : ""}
<dd>${this.contact.country}</dd>
${this.contact.phone1 ? html` <dd class="larger">
${this.phoneMailLink && trPhoneNr ? html` <a
href="tel:${trPhoneNr}"
aria-label="Phone call: ${this.contact.phone1}"
class="link-item"
>
<span style="margin-right: 8px;"
>${this.contact.phone1}</span
>
<pd-icon
activeIcon
icon="phoneIcon"
class="round link-icon"
></pd-icon>
</a>` : this.contact.phone1}
</dd>` : ""}
${this.contact.email ? html` <dd class="larger">
${this.phoneMailLink ? html` <a
href="mailto:${this.contact.email}"
aria-label="Send mail: ${this.contact.email}"
class="link-item"
>
<span style="margin-right: 8px;"
>${this.contact.email}</span
>
<pd-icon
activeIcon
icon="mailIcon"
class="round link-icon"
></pd-icon>
</a>` : this.contact.email}
</dd>` : ""}
${this.contact.btw ? html` <dt>BTW</dt>
<dd>${this.contact.btw}</dd>` : ""}
${this.contact.kbc ? html` <dt>Bankgegevens</dt>
<dd>${this.contact.kbc}</dd>
<dd>${this.contact.bank}</dd>` : ""}
</dl>
</address>
`;
}
get valid() {
return this._contactForm?.valid === true;
}
async triggerValidate() {
return this._contactForm?.triggerValidate();
}
getValues() {
const contactFormValues = this._contactForm?.getValues().origin;
console.log("VAlues:", contactFormValues);
const commonValues = {
business: this._business,
street: contactFormValues.street,
streetNr: contactFormValues.streetNr,
zip: contactFormValues.zip,
city: contactFormValues.city,
additionalHint: contactFormValues.additionalHint,
propertyDate: contactFormValues.propertyDate,
phone1: contactFormValues.phone1,
email: contactFormValues.email
// No input fields for following values
//country?: string;
//btw?: string;
//kbc?: string;
//bank?: string;
};
return this._business ? {
...commonValues,
companyName: contactFormValues.companyName,
vatNr: contactFormValues.vatNr
} : {
...commonValues,
firstName: contactFormValues.firstName,
lastName: contactFormValues.lastName
};
}
_switchAddressType(e) {
console.log("Do switch", e);
if (e.detail.name === "contactTypeRadioId") {
this._business = e.detail.value === "business";
}
e.stopPropagation();
}
_isRequired(field) {
return this.requiredFields.length > 0 ? this.requiredFields.includes(field) : false;
}
_showInput(field) {
return this.inputFields.length > 0 ? this.inputFields.includes(field) : true;
}
_setFormData() {
const getInput = (id) => this.shadowRoot?.getElementById(id)?.value;
return {
business: this._business,
companyName: this._business ? getInput("compNameId") : void 0,
vatNr: this._business ? getInput("vatId") : void 0,
firstName: !this._business ? getInput("firstNameId") : void 0,
lastName: !this._business ? getInput("lastNameId") : void 0,
street: getInput("streetId"),
streetNr: getInput("streetNrId"),
additionalHint: getInput("additionalHintId"),
propertyDate: this.withPropertyDate ? getInput("propertyDateId") : void 0,
zip: getInput("zipId"),
city: getInput("cityId"),
phone1: getInput("phoneId"),
email: getInput("mailId")
};
}
_getFullName() {
return _PdContact._getFullVal(
this.contact?.firstName,
this.contact?.lastName
);
}
_getFullStreet() {
return _PdContact._getFullVal(this.contact?.street, this.contact?.streetNr);
}
_getFullLocation() {
return _PdContact._getFullVal(this.contact?.zip, this.contact?.city);
}
static _getFullVal(val1, val2, fallback = "") {
return [val1, val2].filter(Boolean).join(" ") || fallback;
}
};
__decorateClass([
property()
], _PdContact.prototype, "addressTitle");
__decorateClass([
property({ type: Boolean })
], _PdContact.prototype, "phoneMailLink");
__decorateClass([
property({ type: Boolean })
], _PdContact.prototype, "summary");
__decorateClass([
property({ type: Boolean })
], _PdContact.prototype, "withPropertyDate");
__decorateClass([
property({ type: Array })
], _PdContact.prototype, "requiredFields");
__decorateClass([
property({ type: Array })
], _PdContact.prototype, "inputFields");
__decorateClass([
property({ type: Object })
], _PdContact.prototype, "contact");
__decorateClass([
property({ type: Object })
], _PdContact.prototype, "match");
__decorateClass([
state()
], _PdContact.prototype, "_business");
__decorateClass([
query("#contactContainerId")
], _PdContact.prototype, "_contactForm");
let PdContact = _PdContact;
export { PdContact };