Trying to make JQuery Component reactivity

feature/component
Ernest Litvinenko 2023-11-15 15:42:51 +03:00
parent ce70aa6250
commit f2deb92086
3 changed files with 276 additions and 131 deletions

View File

@ -1,149 +1,255 @@
import {BlockPropsType, QueryBlockType} from "./types.ts";
import $ from "jquery";
import {BlocksDataValueType, QueryBlockType} from "./types.ts";
// import $ from "jquery";
import {Component} from "./library/Component.ts";
const Block = (props: BlockPropsType) => {
const query: QueryBlockType = {
aex_only: props.aex_only === '1' ? 'Да' : 'Нет',
mst_pr_aex: props.mst_pr_aex === '1' ? 'Да' : 'Нет',
mst_pr_virt: props.mst_pr_virt === '1' ? 'Да' : 'Нет',
max_ves: props.max_ves === '0' ? 'Не установлено' : props.max_ves,
max_obyom: props.max_obyom === '0' ? 'Не установлено' : props.max_obyom,
max_ves_gm: props.max_ves_gm === '0' ? 'Не установлено' : props.max_ves_gm,
max_obyom_gm: props.max_obyom_gm === '0' ? 'Не установлено' : props.max_obyom_gm,
max_l_gm: props.max_l_gm === '0' ? 'Не установлено' : props.max_l_gm,
max_w_gm: props.max_w_gm === '0' ? 'Не установлено' : props.max_w_gm,
max_h_gm: props.max_h_gm === '0' ? 'Не установлено' : props.max_h_gm,
person_count: 'Не установлено',
features: props.features || '',
contact_profile: null,
features_changeable: ""
}
class Block extends Component {
component(props: BlocksDataValueType): string {
return `
<div class="border-2 border-primary rounded px-2 py-4 shadow-xl office mb-4 office-block">
<div class="flex justify-between mb-2">
<div>
<h2 class="text-lg">${this.props!.title}</h2>
<span class="text-base opacity-50">${this.props!.addr}</span>
</div>
<div>
<span class="text-sm sm:text-base font-bold block">${this.props!.code}</span>
<span class="text-sm sm:text-base opacity-50">КЛАДР: ${this.props!.kladr_code}</span>
</div>
</div>
if (props.changeable_info) {
query.person_count = `${props.changeable_info.person_count}` || query.person_count
query.features_changeable = `${props.changeable_info.features}` || ''
if (props.changeable_info.contact_person) {
query.contact_profile = {
id: props.changeable_info.contact_person.id!,
fullName: props.changeable_info.contact_person.full_name!,
email: props.changeable_info.contact_person.email!,
phone: props.changeable_info.contact_person.phone!
}
<hr />
<div class="hidden office-block__additional-info">
<div>
<span class="font-bold">
Обрабатываемые транспортные средства:
</span>
<div>
<ul class="[&_li]:text-primary [&_li]:font-bold [&_li]:pl-2">
Не указано
</ul>
</div>
</div>
}
<div>
<span class="font-bold">Прием/Выдача груза осуществляется только путем автоэкспедирования (забора/доставки)</span>
<span class="text-primary font-bold">${this.props!.aex_only}</span>
</div>
<div>
<span class="font-bold">Наличие услуги автоэкспедирования на станции</span>
<span class="text-primary font-bold">${this.props!.mst_pr_aex}</span>
</div>
<div>
<span class="font-bold">Виртуальный склад</span>
<span class="text-primary font-bold">${this.props!.mst_pr_virt}</span>
</div>
}
const str = `<div class="border-2 border-primary rounded px-2 py-4 shadow-xl office mb-4 office-block">
<div class="flex justify-between mb-2">
<div>
<h2 class="text-lg">${props.title}</h2>
<span class="text-base opacity-50">${props.addr}</span>
</div>
<div>
<span class="text-sm sm:text-base font-bold block">${props.code}</span>
<span class="text-sm sm:text-base opacity-50">КЛАДР: ${props.kladr_code}</span>
</div>
</div>
<div>
<span class="font-bold">Максимальный вес по ТТН: <span class="text-primary font-bold">${this.props!.max_ves}</span>, кг</span>
</div>
<hr />
<div class="hidden office-block__additional-info">
<div>
<span class="font-bold">
Обрабатываемые транспортные средства:
</span>
<div>
<ul class="[&_li]:text-primary [&_li]:font-bold [&_li]:pl-2">
Не указано
</ul>
</div>
</div>
<div>
<span class="font-bold">Максимальный объем по ТТН: <span class="text-primary font-bold">${this.props!.max_obyom}</span>, м3</span>
</div>
<div>
<span class="font-bold">Максимальный вес 1 усредненного груза: <span class="text-primary">${this.props!.max_ves_gm}</span>, кг</span>
</div>
<div>
<span class="font-bold">Максимальный объем 1 усредненного груза: <span class="text-primary">${this.props!.max_obyom_gm}</span>, м3</span>
</div>
<div>
<span class="font-bold">Максимальные габариты груза</span>
<p>Длина: <span class="text-primary font-bold">${this.props!.max_l_gm}</span>, м</p>
<p>Ширина: <span class="text-primary font-bold">${this.props!.max_w_gm}</span>, м</p>
<p>Высота: <span class="text-primary font-bold">${this.props!.max_h_gm}</span>, м</p>
</div>
<div>
<span class="font-bold">Прием/Выдача груза осуществляется только путем автоэкспедирования (забора/доставки)</span>
<span class="text-primary font-bold">${query.aex_only}</span>
</div>
<div>
<span class="font-bold">Наличие услуги автоэкспедирования на станции</span>
<span class="text-primary font-bold">${query.mst_pr_aex}</span>
</div>
<div>
<span class="font-bold">Виртуальный склад</span>
<span class="text-primary font-bold">${query.mst_pr_virt}</span>
</div>
<div>
<span class="font-bold">Максимальный вес по ТТН: <span class="text-primary font-bold">${query.max_ves}</span>, кг</span>
</div>
<div>
<span class="font-bold">Максимальный объем по ТТН: <span class="text-primary font-bold">${query.max_obyom}</span>, м3</span>
</div>
<div>
<span class="font-bold">Максимальный вес 1 усредненного груза: <span class="text-primary">${query.max_ves_gm}</span>, кг</span>
</div>
<div>
<span class="font-bold">Максимальный объем 1 усредненного груза: <span class="text-primary">${query.max_obyom_gm}</span>, м3</span>
</div>
<div>
<span class="font-bold">Максимальные габариты груза</span>
<p>Длина: <span class="text-primary font-bold">${query.max_l_gm}</span>, м</p>
<p>Ширина: <span class="text-primary font-bold">${query.max_w_gm}</span>, м</p>
<p>Высота: <span class="text-primary font-bold">${query.max_h_gm}</span>, м</p>
</div>
<div>
<span class="font-bold">Количество сотрудников</span>
<div class="inline-flex items-center">
<span class="text-primary font-bold">${query.person_count}</span>, чел
</div>
</div>
<div>
<span class="font-bold">Количество сотрудников</span>
<div class="inline-flex items-center">
<span class="text-primary font-bold">${this.props!.person_count}</span>, чел
</div>
</div>
<div>
<span class="block font-bold">Особые условия работы филиала</span>
<div class="inline-flex items-center">
<p>${props.features}</p>
</div>
</div>
<div>
<span class="block font-bold">Особые условия работы филиала</span>
<div class="inline-flex items-center">
<p>${this.props!.features}</p>
</div>
</div>
<div>
<span class="block font-bold">Контактное лицо</span>
<div class="">
${query.contact_profile ?
`
<p>${query.contact_profile && query.contact_profile.fullName}</p>
<p>${query.contact_profile && query.contact_profile.phone}</p>
<p>${query.contact_profile && query.contact_profile.email}</p>` : `<span>Данные не установлены</span>`}
<div>
<span class="block font-bold">Контактное лицо</span>
<div class="">
${this.props!.contact_profile ?
`
<p>${this.props!.contact_profile && this.props!.contact_profile.fullName}</p>
<p>${this.props!.contact_profile && this.props!.contact_profile.phone}</p>
<p>${this.props!.contact_profile && this.props!.contact_profile.email}</p>` : `<span>Данные не установлены</span>`}
</div>
</div>
</div>
</div>
<div>
<span class="block font-bold">Особенности филиала</span>
<div class="inline-flex items-center">
<textarea class="block border-primary border-2 px-4 py-2 disabled:border-[1px] disabled:border-[#a2a2a2] mb-4" cols="30" disabled>${props.changeable_info ? props.changeable_info.features || '' : ''}</textarea>
</div>
</div>
<button class="bg-primary text-white font-bold px-4 py-2 text-sm w-full">Изменить</button>
</div>
<div>
<span class="block font-bold">Особенности филиала</span>
<div class="inline-flex items-center">
<textarea class="block border-primary border-2 px-4 py-2 disabled:border-[1px] disabled:border-[#a2a2a2] mb-4" cols="30" disabled>${this.props!.changeable_info ? this.props!.changeable_info.features || '' : ''}</textarea>
</div>
</div>
<button class="bg-primary text-white font-bold px-4 py-2 text-sm w-full">Изменить</button>
</div>
</div>`
return str
</div>`
}
}
export const toggleBlocks = (element: JQuery<HTMLElement>) => {
const jqSelector = '.office-block.active .office-block__additional-info'
$(jqSelector).addClass('hidden')
$('.office-block.active').toggleClass('active')
element.toggleClass('active')
$(jqSelector).removeClass('hidden')
}
export default Block
// const Block = (props: BlockPropsType) => {
// const query: QueryBlockType = {
// aex_only: props.aex_only === '1' ? 'Да' : 'Нет',
// mst_pr_aex: props.mst_pr_aex === '1' ? 'Да' : 'Нет',
// mst_pr_virt: props.mst_pr_virt === '1' ? 'Да' : 'Нет',
// max_ves: props.max_ves === '0' ? 'Не установлено' : props.max_ves,
// max_obyom: props.max_obyom === '0' ? 'Не установлено' : props.max_obyom,
// max_ves_gm: props.max_ves_gm === '0' ? 'Не установлено' : props.max_ves_gm,
// max_obyom_gm: props.max_obyom_gm === '0' ? 'Не установлено' : props.max_obyom_gm,
// max_l_gm: props.max_l_gm === '0' ? 'Не установлено' : props.max_l_gm,
// max_w_gm: props.max_w_gm === '0' ? 'Не установлено' : props.max_w_gm,
// max_h_gm: props.max_h_gm === '0' ? 'Не установлено' : props.max_h_gm,
// person_count: 'Не установлено',
// features: props.features || '',
// contact_profile: null,
// features_changeable: ""
// }
//
// if (props.changeable_info) {
// query.person_count = `${props.changeable_info.person_count}` || query.person_count
// query.features_changeable = `${props.changeable_info.features}` || ''
// if (props.changeable_info.contact_person) {
// query.contact_profile = {
// id: props.changeable_info.contact_person.id!,
// fullName: props.changeable_info.contact_person.full_name!,
// email: props.changeable_info.contact_person.email!,
// phone: props.changeable_info.contact_person.phone!
// }
//
// }
//
// }
// const str = `<div class="border-2 border-primary rounded px-2 py-4 shadow-xl office mb-4 office-block">
// <div class="flex justify-between mb-2">
// <div>
// <h2 class="text-lg">${props.title}</h2>
// <span class="text-base opacity-50">${props.addr}</span>
// </div>
// <div>
// <span class="text-sm sm:text-base font-bold block">${props.code}</span>
// <span class="text-sm sm:text-base opacity-50">КЛАДР: ${props.kladr_code}</span>
// </div>
// </div>
//
// <hr />
// <div class="hidden office-block__additional-info">
// <div>
// <span class="font-bold">
// Обрабатываемые транспортные средства:
// </span>
// <div>
// <ul class="[&_li]:text-primary [&_li]:font-bold [&_li]:pl-2">
// Не указано
// </ul>
// </div>
// </div>
//
// <div>
// <span class="font-bold">Прием/Выдача груза осуществляется только путем автоэкспедирования (забора/доставки)</span>
// <span class="text-primary font-bold">${query.aex_only}</span>
// </div>
// <div>
// <span class="font-bold">Наличие услуги автоэкспедирования на станции</span>
// <span class="text-primary font-bold">${query.mst_pr_aex}</span>
// </div>
// <div>
// <span class="font-bold">Виртуальный склад</span>
// <span class="text-primary font-bold">${query.mst_pr_virt}</span>
// </div>
//
// <div>
// <span class="font-bold">Максимальный вес по ТТН: <span class="text-primary font-bold">${query.max_ves}</span>, кг</span>
// </div>
//
// <div>
// <span class="font-bold">Максимальный объем по ТТН: <span class="text-primary font-bold">${query.max_obyom}</span>, м3</span>
// </div>
// <div>
// <span class="font-bold">Максимальный вес 1 усредненного груза: <span class="text-primary">${query.max_ves_gm}</span>, кг</span>
// </div>
// <div>
// <span class="font-bold">Максимальный объем 1 усредненного груза: <span class="text-primary">${query.max_obyom_gm}</span>, м3</span>
// </div>
// <div>
// <span class="font-bold">Максимальные габариты груза</span>
// <p>Длина: <span class="text-primary font-bold">${query.max_l_gm}</span>, м</p>
// <p>Ширина: <span class="text-primary font-bold">${query.max_w_gm}</span>, м</p>
// <p>Высота: <span class="text-primary font-bold">${query.max_h_gm}</span>, м</p>
// </div>
//
// <div>
// <span class="font-bold">Количество сотрудников</span>
// <div class="inline-flex items-center">
// <span class="text-primary font-bold">${query.person_count}</span>, чел
// </div>
// </div>
//
//
// <div>
// <span class="block font-bold">Особые условия работы филиала</span>
// <div class="inline-flex items-center">
// <p>${props.features}</p>
// </div>
// </div>
//
// <div>
// <span class="block font-bold">Контактное лицо</span>
// <div class="">
// ${query.contact_profile ?
// `
// <p>${query.contact_profile && query.contact_profile.fullName}</p>
// <p>${query.contact_profile && query.contact_profile.phone}</p>
// <p>${query.contact_profile && query.contact_profile.email}</p>` : `<span>Данные не установлены</span>`}
//
//
//
//
// </div>
// </div>
//
// <div>
// <span class="block font-bold">Особенности филиала</span>
// <div class="inline-flex items-center">
// <textarea class="block border-primary border-2 px-4 py-2 disabled:border-[1px] disabled:border-[#a2a2a2] mb-4" cols="30" disabled>${props.changeable_info ? props.changeable_info.features || '' : ''}</textarea>
// </div>
// </div>
// <button class="bg-primary text-white font-bold px-4 py-2 text-sm w-full">Изменить</button>
// </div>
//
//
// </div>`
// return str
// }
//
// export const toggleBlocks = (element: JQuery<HTMLElement>) => {
// const jqSelector = '.office-block.active .office-block__additional-info'
//
// $(jqSelector).addClass('hidden')
// $('.office-block.active').toggleClass('active')
//
// element.toggleClass('active')
// $(jqSelector).removeClass('hidden')
// }
//
// export default Block

39
src/library/Component.ts Normal file
View File

@ -0,0 +1,39 @@
export type ComponentProps = {
[x: string]: any
children?: JQuery<HTMLElement>[]
}
export class Component {
_element: JQuery<HTMLElement> | undefined
props: ComponentProps | undefined
constructor(props: ComponentProps) {
this.props = new Proxy<ComponentProps>({...props}, {
set: (target: ComponentProps, p: string, newValue: any): boolean => {
target[p] = newValue
this.rerender()
return true
}
})
}
component(): string {
return ``
}
rerender() {
const component = $(this.component())
this._element.replaceWith(component)
this._element = component
}
render() {
this._element = $(this.component())
this.props?.children && this._element.append(...this.props.children)
}
mount(element: JQuery<HTMLElement>) {
this.render()
element.append(this._element)
}
}

View File

@ -1,6 +1,6 @@
import {ListOfficesResponse} from './backend/types.ts'
export type BlocksDataValueType = {
export type BlocksDataValueType = {
block: JQuery<HTMLElement>,
data: ListOfficesResponse[0]
}