@salla.sa/twilight-components
Version:
Salla Web Component
179 lines (174 loc) • 7.74 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
import { C as CameraIcon } from './camera.js';
import { F as FormFieldTypes } from './interfaces.js';
import { d as defineCustomElement$3 } from './salla-button2.js';
import { d as defineCustomElement$2 } from './salla-file-upload2.js';
const sallaCustomFieldsCss = ":host{display:block}";
const SallaCustomFields$1 = /*@__PURE__*/ proxyCustomElement(class SallaCustomFields extends HTMLElement {
constructor() {
super();
this.__registerHost();
this.fieldChanged = createEvent(this, "fieldChanged", 7);
this.fileUploaded = createEvent(this, "fileUploaded", 7);
/** Whether the fields can be edited by the user. */
this.isEditable = true;
this.fieldErrors = {};
this.isSubmitting = false;
}
get dragAndDropText() {
return salla.lang.get("common.uploader.drag_and_drop");
}
get browseText() {
return salla.lang.get("common.uploader.browse");
}
get saveButtonText() {
return salla.lang.get("common.elements.save");
}
/** Update the displayed fields programmatically. */
async setFields(fields) {
this.parsedFields = fields;
}
/** Gets the current values of all fields, formatted for submission. */
async getFieldValues() {
return this.parsedFields?.reduce((values, field) => {
values[`custom_fields[${field.id}]`] = field.value;
return values;
}, {}) || {};
}
/** Validates all required fields and updates the error state. Returns true if valid. */
async validateFields() {
if (!this.parsedFields)
return true;
const errors = this.parsedFields.reduce((acc, field) => {
if (field.required && (!field.value || field.value === "")) {
acc[field.id.toString()] = `${field.label} is required`;
}
return acc;
}, {});
this.fieldErrors = errors;
return Object.keys(errors).length === 0;
}
handleFieldChange(field, event) {
const value = event.target.value;
field.value = value;
this.clearFieldError(field.id);
const isValid = !(field.required && !value);
if (!isValid) {
this.setFieldError(field.id, `${field.label} is required`);
}
this.fieldChanged.emit({ fieldId: field.id, value, isValid });
}
handleFileUpload(field, event) {
const { error, file } = event.detail;
const isValid = !error;
this.clearFieldError(field.id);
if (isValid) {
field.value = file;
}
else {
this.setFieldError(field.id, "File upload failed");
}
this.fileUploaded.emit({ fieldId: field.id, file, isValid });
}
clearFieldError(fieldId) {
this.fieldErrors = { ...this.fieldErrors };
delete this.fieldErrors[fieldId];
}
setFieldError(fieldId, message) {
this.fieldErrors = { ...this.fieldErrors, [fieldId]: message };
}
renderTextField(field) {
return (h("input", { disabled: !this.isEditable, type: field.type, id: `custom-field-${field.id}`, value: field.value?.toString() || "", onChange: (e) => this.handleFieldChange(field, e), name: `${field.id}`, class: "form-input", required: field.required }));
}
renderFileField(field) {
return (h("salla-file-upload", { url: salla.url.api('upload'), id: `custom-field-${field.id}`, name: `${field.id}`, type: "registration", value: field.value, height: "120px", onAdded: (e) => this.handleFileUpload(field, e), required: field.required, disabled: !this.isEditable, onUploaded: e => { e.target.value = e.target.value?.url; }, allowRemove: true, onRemoved: (e) => {
e.preventDefault();
e.stopPropagation();
field.value = "";
e.target.value = "";
}, payloadName: "files[]", payloadParams: { type: 'registration' }, "instant-upload": true }, h("div", { class: "s-custom-fields-filepond-placeholder" }, h("span", { class: "s-custom-fields-filepond-placeholder-icon" }, h("i", { innerHTML: CameraIcon })), h("p", { class: "s-custom-fields-filepond-placeholder-text" }, this.dragAndDropText), h("span", { class: "filepond--label-action" }, this.browseText))));
}
renderField(field) {
return (h("div", { class: "s-custom-fields-field", key: field.id }, h("label", { class: "s-custom-fields-field-label", htmlFor: `custom-field-${field.id}` }, field.label, field.required && h("span", { class: "s-custom-fields-required" }, "*")), h("div", null, field.type === FormFieldTypes.Photo
? this.renderFileField(field)
: this.renderTextField(field), this.fieldErrors[field.id] && (h("p", { class: "s-custom-fields-error" }, this.fieldErrors[field.id])))));
}
componentWillLoad() {
this.parsedFields = this.parseFields(this.fields);
}
parseFields(fields) {
if (!fields)
return [];
return typeof fields === "string"
? JSON.parse(fields)
: Array.isArray(fields) ? fields : [];
}
async handleSubmit(e) {
e.preventDefault();
this.isSubmitting = true;
try {
const payload = {};
const form = e.target;
const elements = form.elements;
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
if (element.name && !element.name.startsWith("hidden") && element.value) {
payload[element.name] = element.value;
}
}
await salla.api.profile.updateCustomFields({
id: salla.config.get("store.id"),
fields: payload,
});
}
finally {
this.isSubmitting = false;
}
}
render() {
if (!this.parsedFields?.length)
return null;
return (h("form", { class: "s-custom-fields-wrapper", onSubmit: this.handleSubmit }, this.parsedFields.map(field => this.renderField(field)), h("salla-button", { type: "submit", loading: this.isSubmitting, disabled: this.isSubmitting || !this.isEditable, "loader-position": "end", class: "s-custom-fields-submit-btn" }, this.saveButtonText)));
}
static get style() { return sallaCustomFieldsCss; }
}, [0, "salla-custom-fields", {
"fields": [1],
"isEditable": [4, "is-editable"],
"fileUploadUrl": [1, "file-upload-url"],
"parsedFields": [32],
"fieldErrors": [32],
"isSubmitting": [32],
"setFields": [64],
"getFieldValues": [64],
"validateFields": [64]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["salla-custom-fields", "salla-button", "salla-file-upload"];
components.forEach(tagName => { switch (tagName) {
case "salla-custom-fields":
if (!customElements.get(tagName)) {
customElements.define(tagName, SallaCustomFields$1);
}
break;
case "salla-button":
if (!customElements.get(tagName)) {
defineCustomElement$3();
}
break;
case "salla-file-upload":
if (!customElements.get(tagName)) {
defineCustomElement$2();
}
break;
} });
}
defineCustomElement$1();
const SallaCustomFields = SallaCustomFields$1;
const defineCustomElement = defineCustomElement$1;
export { SallaCustomFields, defineCustomElement };