/* eslint-disable @eslint-community/eslint-comments/disable-enable-pair */ /* eslint-disable unicorn/prefer-module */ import type { BulmaJS } from '@cityssm/bulma-js/types.js' import type { cityssmGlobal } from '@cityssm/bulma-webapp-js/src/types.js' import type * as globalTypes from '../../types/globalTypes.js' import type * as recordTypes from '../../types/recordTypes.js' declare const cityssm: cityssmGlobal declare const bulmaJS: BulmaJS declare const exports: Record ;(() => { const los = (exports as Record).los as globalTypes.LOS const lotOccupancyId = ( document.querySelector('#lotOccupancy--lotOccupancyId') as HTMLInputElement ).value const isCreate = lotOccupancyId === '' /* * Main form */ let refreshAfterSave = isCreate function setUnsavedChanges(): void { los.setUnsavedChanges() document .querySelector("button[type='submit'][form='form--lotOccupancy']") ?.classList.remove('is-light') } function clearUnsavedChanges(): void { los.clearUnsavedChanges() document .querySelector("button[type='submit'][form='form--lotOccupancy']") ?.classList.add('is-light') } const formElement = document.querySelector( '#form--lotOccupancy' ) as HTMLFormElement formElement.addEventListener('submit', (formEvent) => { formEvent.preventDefault() cityssm.postJSON( `${los.urlPrefix}/lotOccupancies/${isCreate ? 'doCreateLotOccupancy' : 'doUpdateLotOccupancy'}`, formElement, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { success: boolean lotOccupancyId?: number errorMessage?: string } if (responseJSON.success) { clearUnsavedChanges() if (isCreate || refreshAfterSave) { window.location.href = los.getLotOccupancyURL( responseJSON.lotOccupancyId, true, true ) } else { bulmaJS.alert({ message: `${los.escapedAliases.Occupancy} Updated Successfully`, contextualColorName: 'success' }) } } else { bulmaJS.alert({ title: `Error Saving ${los.escapedAliases.Occupancy}`, message: responseJSON.errorMessage ?? '', contextualColorName: 'danger' }) } } ) }) const formInputElements = formElement.querySelectorAll('input, select') for (const formInputElement of formInputElements) { formInputElement.addEventListener('change', setUnsavedChanges) } function doCopy(): void { cityssm.postJSON( `${los.urlPrefix}/lotOccupancies/doCopyLotOccupancy`, { lotOccupancyId }, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { success: boolean errorMessage?: string lotOccupancyId?: number } if (responseJSON.success) { clearUnsavedChanges() window.location.href = los.getLotOccupancyURL( responseJSON.lotOccupancyId, true ) } else { bulmaJS.alert({ title: 'Error Copying Record', message: responseJSON.errorMessage ?? '', contextualColorName: 'danger' }) } } ) } document .querySelector('#button--copyLotOccupancy') ?.addEventListener('click', (clickEvent) => { clickEvent.preventDefault() if (los.hasUnsavedChanges()) { bulmaJS.alert({ title: 'Unsaved Changes', message: 'Please save all unsaved changes before continuing.', contextualColorName: 'warning' }) } else { bulmaJS.confirm({ title: `Copy ${los.escapedAliases.Occupancy} Record as New`, message: 'Are you sure you want to copy this record to a new record?', contextualColorName: 'info', okButton: { text: 'Yes, Copy', callbackFunction: doCopy } }) } }) document .querySelector('#button--deleteLotOccupancy') ?.addEventListener('click', (clickEvent) => { clickEvent.preventDefault() function doDelete(): void { cityssm.postJSON( `${los.urlPrefix}/lotOccupancies/doDeleteLotOccupancy`, { lotOccupancyId }, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { success: boolean errorMessage?: string } if (responseJSON.success) { clearUnsavedChanges() window.location.href = los.getLotOccupancyURL() } else { bulmaJS.alert({ title: 'Error Deleting Record', message: responseJSON.errorMessage ?? '', contextualColorName: 'danger' }) } } ) } bulmaJS.confirm({ title: `Delete ${los.escapedAliases.Occupancy} Record`, message: 'Are you sure you want to delete this record?', contextualColorName: 'warning', okButton: { text: 'Yes, Delete', callbackFunction: doDelete } }) }) document .querySelector('#button--createWorkOrder') ?.addEventListener('click', (clickEvent) => { clickEvent.preventDefault() let createCloseModalFunction: () => void function doCreate(formEvent: SubmitEvent): void { formEvent.preventDefault() cityssm.postJSON( `${los.urlPrefix}/workOrders/doCreateWorkOrder`, formEvent.currentTarget, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { success: boolean errorMessage?: string workOrderId?: number } if (responseJSON.success) { createCloseModalFunction() bulmaJS.confirm({ title: 'Work Order Created Successfully', message: 'Would you like to open the work order now?', contextualColorName: 'success', okButton: { text: 'Yes, Open the Work Order', callbackFunction: () => { window.location.href = los.getWorkOrderURL( responseJSON.workOrderId, true ) } } }) } else { bulmaJS.alert({ title: 'Error Creating Work Order', message: responseJSON.errorMessage as string, contextualColorName: 'danger' }) } } ) } cityssm.openHtmlModal('lotOccupancy-createWorkOrder', { onshow(modalElement) { ;( modalElement.querySelector( '#workOrderCreate--lotOccupancyId' ) as HTMLInputElement ).value = lotOccupancyId ;( modalElement.querySelector( '#workOrderCreate--workOrderOpenDateString' ) as HTMLInputElement ).value = cityssm.dateToString(new Date()) const workOrderTypeSelectElement = modalElement.querySelector( '#workOrderCreate--workOrderTypeId' ) as HTMLSelectElement const workOrderTypes = (exports as Record) .workOrderTypes as recordTypes.WorkOrderType[] if (workOrderTypes.length === 1) { workOrderTypeSelectElement.innerHTML = '' } for (const workOrderType of workOrderTypes) { const optionElement = document.createElement('option') optionElement.value = workOrderType.workOrderTypeId.toString() optionElement.textContent = workOrderType.workOrderType ?? '' workOrderTypeSelectElement.append(optionElement) } }, onshown(modalElement, closeModalFunction) { createCloseModalFunction = closeModalFunction bulmaJS.toggleHtmlClipped() ;( modalElement.querySelector( '#workOrderCreate--workOrderTypeId' ) as HTMLSelectElement ).focus() modalElement .querySelector('form') ?.addEventListener('submit', doCreate) }, onremoved() { bulmaJS.toggleHtmlClipped() ;( document.querySelector( '#button--createWorkOrder' ) as HTMLButtonElement ).focus() } }) }) // Occupancy Type const occupancyTypeIdElement = document.querySelector( '#lotOccupancy--occupancyTypeId' ) as HTMLSelectElement if (isCreate) { const lotOccupancyFieldsContainerElement = document.querySelector( '#container--lotOccupancyFields' ) as HTMLElement occupancyTypeIdElement.addEventListener('change', () => { if (occupancyTypeIdElement.value === '') { // eslint-disable-next-line no-unsanitized/property lotOccupancyFieldsContainerElement.innerHTML = `

Select the ${los.escapedAliases.occupancy} type to load the available fields.

` return } cityssm.postJSON( `${los.urlPrefix}/lotOccupancies/doGetOccupancyTypeFields`, { occupancyTypeId: occupancyTypeIdElement.value }, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { occupancyTypeFields: recordTypes.OccupancyTypeField[] } if (responseJSON.occupancyTypeFields.length === 0) { // eslint-disable-next-line no-unsanitized/property lotOccupancyFieldsContainerElement.innerHTML = `

There are no additional fields for this ${los.escapedAliases.occupancy} type.

` return } lotOccupancyFieldsContainerElement.innerHTML = '' let occupancyTypeFieldIds = '' for (const occupancyTypeField of responseJSON.occupancyTypeFields) { occupancyTypeFieldIds += ',' + occupancyTypeField.occupancyTypeFieldId.toString() const fieldName = `lotOccupancyFieldValue_${occupancyTypeField.occupancyTypeFieldId.toString()}` const fieldId = `lotOccupancy--${fieldName}` const fieldElement = document.createElement('div') fieldElement.className = 'field' fieldElement.innerHTML = `
` ;( fieldElement.querySelector('label') as HTMLLabelElement ).textContent = occupancyTypeField.occupancyTypeField as string if ((occupancyTypeField.occupancyTypeFieldValues ?? '') === '') { const inputElement = document.createElement('input') inputElement.className = 'input' inputElement.id = fieldId inputElement.name = fieldName inputElement.type = 'text' inputElement.required = occupancyTypeField.isRequired as boolean inputElement.minLength = occupancyTypeField.minimumLength as number inputElement.maxLength = occupancyTypeField.maximumLength as number if ((occupancyTypeField.pattern ?? '') !== '') { inputElement.pattern = occupancyTypeField.pattern as string } ;(fieldElement.querySelector('.control') as HTMLElement).append( inputElement ) } else { ;( fieldElement.querySelector('.control') as HTMLElement ).innerHTML = `
` const selectElement = fieldElement.querySelector( 'select' ) as HTMLSelectElement selectElement.required = occupancyTypeField.isRequired as boolean const optionValues = ( occupancyTypeField.occupancyTypeFieldValues as string ).split('\n') for (const optionValue of optionValues) { const optionElement = document.createElement('option') optionElement.value = optionValue optionElement.textContent = optionValue selectElement.append(optionElement) } } console.log(fieldElement) lotOccupancyFieldsContainerElement.append(fieldElement) } lotOccupancyFieldsContainerElement.insertAdjacentHTML( 'beforeend', // eslint-disable-next-line no-secrets/no-secrets `` ) } ) }) } else { const originalOccupancyTypeId = occupancyTypeIdElement.value occupancyTypeIdElement.addEventListener('change', () => { if (occupancyTypeIdElement.value !== originalOccupancyTypeId) { bulmaJS.confirm({ title: 'Confirm Change', message: `Are you sure you want to change the ${los.escapedAliases.occupancy} type?\n This change affects the additional fields associated with this record, and may also affect the available fees.`, contextualColorName: 'warning', okButton: { text: 'Yes, Keep the Change', callbackFunction: () => { refreshAfterSave = true } }, cancelButton: { text: 'Revert the Change', callbackFunction: () => { occupancyTypeIdElement.value = originalOccupancyTypeId } } }) } }) } // Lot Selector const lotNameElement = document.querySelector( '#lotOccupancy--lotName' ) as HTMLInputElement lotNameElement.addEventListener('click', (clickEvent) => { const currentLotName = (clickEvent.currentTarget as HTMLInputElement).value let lotSelectCloseModalFunction: () => void let lotSelectModalElement: HTMLElement let lotSelectFormElement: HTMLFormElement let lotSelectResultsElement: HTMLElement function renderSelectedLotAndClose( lotId: number | string, lotName: string ): void { ;( document.querySelector('#lotOccupancy--lotId') as HTMLInputElement ).value = lotId.toString() ;( document.querySelector('#lotOccupancy--lotName') as HTMLInputElement ).value = lotName setUnsavedChanges() lotSelectCloseModalFunction() } function selectExistingLot(clickEvent: Event): void { clickEvent.preventDefault() const selectedLotElement = clickEvent.currentTarget as HTMLElement renderSelectedLotAndClose( selectedLotElement.dataset.lotId ?? '', selectedLotElement.dataset.lotName ?? '' ) } function searchLots(): void { // eslint-disable-next-line no-unsanitized/property lotSelectResultsElement.innerHTML = los.getLoadingParagraphHTML('Searching...') cityssm.postJSON( `${los.urlPrefix}/lots/doSearchLots`, lotSelectFormElement, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { count: number lots: recordTypes.Lot[] } if (responseJSON.count === 0) { lotSelectResultsElement.innerHTML = `

No results.

` return } const panelElement = document.createElement('div') panelElement.className = 'panel' for (const lot of responseJSON.lots) { const panelBlockElement = document.createElement('a') panelBlockElement.className = 'panel-block is-block' panelBlockElement.href = '#' panelBlockElement.dataset.lotId = lot.lotId.toString() panelBlockElement.dataset.lotName = lot.lotName // eslint-disable-next-line no-unsanitized/property panelBlockElement.innerHTML = `
${cityssm.escapeHTML(lot.lotName ?? '')}
${cityssm.escapeHTML(lot.mapName ?? '')}
${cityssm.escapeHTML(lot.lotStatus as string)}
${lot.lotOccupancyCount! > 0 ? 'Currently Occupied' : ''}
` panelBlockElement.addEventListener('click', selectExistingLot) panelElement.append(panelBlockElement) } lotSelectResultsElement.innerHTML = '' lotSelectResultsElement.append(panelElement) } ) } function createLotAndSelect(submitEvent: SubmitEvent): void { submitEvent.preventDefault() const lotName = ( lotSelectModalElement.querySelector( '#lotCreate--lotName' ) as HTMLInputElement ).value cityssm.postJSON( `${los.urlPrefix}/lots/doCreateLot`, submitEvent.currentTarget, (rawResponseJSON) => { const responseJSON = rawResponseJSON as { success: boolean errorMessage?: string lotId?: number } if (responseJSON.success) { renderSelectedLotAndClose(responseJSON.lotId!, lotName) } else { bulmaJS.alert({ title: `Error Creating ${los.escapedAliases.Lot}`, message: responseJSON.errorMessage ?? '', contextualColorName: 'danger' }) } } ) } cityssm.openHtmlModal('lotOccupancy-selectLot', { onshow(modalElement) { los.populateAliases(modalElement) }, onshown(modalElement, closeModalFunction) { bulmaJS.toggleHtmlClipped() lotSelectModalElement = modalElement lotSelectCloseModalFunction = closeModalFunction bulmaJS.init(modalElement) // search Tab const lotNameFilterElement = modalElement.querySelector( '#lotSelect--lotName' ) as HTMLInputElement if ( (document.querySelector('#lotOccupancy--lotId') as HTMLInputElement) .value !== '' ) { lotNameFilterElement.value = currentLotName } lotNameFilterElement.focus() lotNameFilterElement.addEventListener('change', searchLots) const occupancyStatusFilterElement = modalElement.querySelector( '#lotSelect--occupancyStatus' ) as HTMLSelectElement occupancyStatusFilterElement.addEventListener('change', searchLots) if (currentLotName !== '') { occupancyStatusFilterElement.value = '' } lotSelectFormElement = modalElement.querySelector( '#form--lotSelect' ) as HTMLFormElement lotSelectResultsElement = modalElement.querySelector( '#resultsContainer--lotSelect' ) as HTMLElement lotSelectFormElement.addEventListener('submit', (submitEvent) => { submitEvent.preventDefault() }) searchLots() // Create Tab if (exports.lotNamePattern) { const regex = exports.lotNamePattern as RegExp ;( modalElement.querySelector( '#lotCreate--lotName' ) as HTMLInputElement ).pattern = regex.source } const lotTypeElement = modalElement.querySelector( '#lotCreate--lotTypeId' ) as HTMLSelectElement for (const lotType of exports.lotTypes as recordTypes.LotType[]) { const optionElement = document.createElement('option') optionElement.value = lotType.lotTypeId.toString() optionElement.textContent = lotType.lotType lotTypeElement.append(optionElement) } const lotStatusElement = modalElement.querySelector( '#lotCreate--lotStatusId' ) as HTMLSelectElement for (const lotStatus of exports.lotStatuses as recordTypes.LotStatus[]) { const optionElement = document.createElement('option') optionElement.value = lotStatus.lotStatusId.toString() optionElement.textContent = lotStatus.lotStatus lotStatusElement.append(optionElement) } const mapElement = modalElement.querySelector( '#lotCreate--mapId' ) as HTMLSelectElement for (const map of exports.maps as recordTypes.MapRecord[]) { const optionElement = document.createElement('option') optionElement.value = map.mapId!.toString() optionElement.textContent = (map.mapName ?? '') === '' ? '(No Name)' : map.mapName! mapElement.append(optionElement) } ;( modalElement.querySelector('#form--lotCreate') as HTMLFormElement ).addEventListener('submit', createLotAndSelect) }, onremoved() { bulmaJS.toggleHtmlClipped() } }) }) document .querySelector('.is-lot-view-button') ?.addEventListener('click', () => { const lotId = ( document.querySelector('#lotOccupancy--lotId') as HTMLInputElement ).value if (lotId === '') { bulmaJS.alert({ message: `No ${los.escapedAliases.lot} selected.`, contextualColorName: 'info' }) } else { window.open(los.urlPrefix + '/lots/' + lotId) } }) document .querySelector('.is-clear-lot-button') ?.addEventListener('click', () => { if (lotNameElement.disabled) { bulmaJS.alert({ message: 'You need to unlock the field before clearing it.', contextualColorName: 'info' }) } else { lotNameElement.value = `(No ${los.escapedAliases.Lot})` ;( document.querySelector('#lotOccupancy--lotId') as HTMLInputElement ).value = '' setUnsavedChanges() } }) // Start Date los.initializeDatePickers(formElement) document .querySelector('#lotOccupancy--occupancyStartDateString') ?.addEventListener('change', () => { const endDatePicker = ( document.querySelector( '#lotOccupancy--occupancyEndDateString' ) as HTMLInputElement ).bulmaCalendar.datePicker endDatePicker.min = ( document.querySelector( '#lotOccupancy--occupancyStartDateString' ) as HTMLInputElement ).value endDatePicker.refresh() }) los.initializeUnlockFieldButtons(formElement) /* * Occupants */ //=include lotOccupancyEditOccupants.js if (!isCreate) { //=include lotOccupancyEditComments.js //=include lotOccupancyEditFees.js } })()