Skip to content

Commit

Permalink
feat(condo): DOMA-8515 new Meters design (#4791)
Browse files Browse the repository at this point in the history
* feat(condo): DOMA-8515 new Meters design

* feat(condo): DOMA-8515 add overdue highlighting for verification date

* feat(condo): DOMA-8515 request meters directly

* feat(condo): DOMA-8515 adapt filters for Meters

* feat(condo): DOMA-8515 change menu and title name for Meters section

* feat(condo): DOMA-8515 add separate create pages

* feat(condo): DOMA-8515 added meter info page and update meter page

* feat(callcenter): DOMA-8515 support new meters design in callcenter

* feat(condo): DOMA-8515 cast for intl

* feat(condo): DOMA-8515 added archiveDate field to Meter and PropertyMeter models

* feat(condo): DOMA-8515 add filters by status for Meter and PropertyMeter tables

* fix(condo): DOMA-8515 update gql type to string

* feat(condo): DOMA-8515 get all reporting periods and find the right one

* feat(condo): DOMA-8515 change default date range value

* feat(condo): DOMA-8515 regenerate migration

* feat(condo): DOMA-8515 added update meter readings logic

* feat(condo): DOMA-8515 added b2b logo and updated no meter tips

* feat(condo): DOMA-8515 separated create and update meter forms, page naming

* fix(condo): DOMA-8515 pr fixes

* fix(condo): DOMA-8515 pr fix - separated useFilters

* fix(condo): DOMA-8515 pr fixes

* feat(condo): DOMA-8515 support changes in callcenter

* feat(condo): DOMA-8515 save meter type to query

* feat(condo): DOMA-8515 add checkbox selection to property meter readings table

* feat(condo): DOMA-8515 added consumption column render and pr fixes

* feat(callcenter): DOMA-8515 fix breaking changes in callcenter

* feat(condo): DOMA-8515 small design fixes

* fix(condo): DOMA-8515 trigger build

* feat(condo): DOMA-8515 added remember property when adding readings and pr fixes

* feat(condo): DOMA-8515 added meter step to onboarding

* fix(condo): DOMA-8515 delete TourSteps on migration down

* fix(condo): DOMA-8515 restrict editing readings for archived meter

* fix(condo): DOMA-8515 fixed migrations
  • Loading branch information
abshnko authored Jun 18, 2024
1 parent 8c0e217 commit 04ea1ed
Show file tree
Hide file tree
Showing 62 changed files with 4,861 additions and 1,057 deletions.
2 changes: 1 addition & 1 deletion apps/callcenter
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface IDeleteActionButtonWithConfirmModal {
showButtonIcon?: boolean
cancelMessage?: string
messageType?: TypographyTextProps['type']
cancelButtonType?: ButtonProps['type']
disabled?: boolean
}

Expand All @@ -35,6 +36,7 @@ export const DeleteButtonWithConfirmModal: React.FC<IDeleteActionButtonWithConfi
showButtonIcon = false,
cancelMessage,
messageType = 'primary',
cancelButtonType = 'secondary',
disabled,
}) => {
const intl = useIntl()
Expand Down Expand Up @@ -92,7 +94,7 @@ export const DeleteButtonWithConfirmModal: React.FC<IDeleteActionButtonWithConfi
{okButtonLabel}
</Button>,
showCancelButton && (
<Button key='cancel' type='secondary' onClick={handleCancel}>
<Button key='cancel' type={cancelButtonType} onClick={handleCancel}>
{CancelMessage}
</Button>
),
Expand Down
140 changes: 140 additions & 0 deletions apps/condo/domains/meter/components/AddressAndUnitInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { Property as PropertyType } from '@app/condo/schema'
import { Col, ColProps, Form, FormInstance, Row } from 'antd'
import { Gutter } from 'antd/lib/grid/row'
import { DefaultOptionType } from 'antd/lib/select'
import get from 'lodash/get'
import React, { Dispatch, SetStateAction } from 'react'

import { useIntl } from '@open-condo/next/intl'
import { Typography } from '@open-condo/ui'

import { useValidations } from '@condo/domains/common/hooks/useValidations'
import { MeterPageTypes, METER_TAB_TYPES } from '@condo/domains/meter/utils/clientSchema'
import { usePropertyValidations } from '@condo/domains/property/components/BasePropertyForm/usePropertyValidations'
import { PropertyAddressSearchInput } from '@condo/domains/property/components/PropertyAddressSearchInput'
import { UnitInfo } from '@condo/domains/property/components/UnitInfo'
import { PropertyFormItemTooltip } from '@condo/domains/property/PropertyFormItemTooltip'


const FORM_ROW_MEDIUM_VERTICAL_GUTTER: [Gutter, Gutter] = [0, 20]
const FORM_ROW_SMALL_VERTICAL_GUTTER: [Gutter, Gutter] = [0, 4]
const FORM_ITEM_WRAPPER_COLUMN_STYLE: ColProps = { style: { width: '100%', padding: 0 } }

type PropertyUnitInitialValues = {
propertyId?: string
unitName?: string
unitType?: string
}

type AddressAndUnitInfoProps = {
form?: FormInstance,
organizationId: string,
meterType: MeterPageTypes,
getHandleSelectPropertyAddress: (form: FormInstance) => (_: unknown, option: DefaultOptionType) => void,
handleDeselectPropertyAddress: () => void
selectedPropertyId: string,
isMatchSelectedProperty: boolean
isNoMeterForAddress?: boolean,
notFoundMetersForAddressTooltip?: JSX.Element,
isNoMeterForUnitName?: boolean
property?: PropertyType,
propertyLoading?: boolean
setSelectedUnitName?: Dispatch<SetStateAction<string>>,
setSelectedUnitType?: Dispatch<SetStateAction<string>>,
initialValues?: PropertyUnitInitialValues,
}


export const AddressAndUnitInfo = (props: AddressAndUnitInfoProps): JSX.Element => {
const intl = useIntl()
const AddressLabel = intl.formatMessage({ id: 'field.Address' })
const AddressPlaceholder = intl.formatMessage({ id: 'placeholder.Address' })
const ClientInfoMessage = intl.formatMessage({ id: 'ClientInfo' })

const {
getHandleSelectPropertyAddress,
handleDeselectPropertyAddress,
selectedPropertyId, isMatchSelectedProperty,
organizationId,
isNoMeterForAddress,
notFoundMetersForAddressTooltip,
isNoMeterForUnitName,
meterType,
property,
propertyLoading,
setSelectedUnitName,
setSelectedUnitType,
form,
initialValues,
} = props

const { requiredValidator } = useValidations()
const { addressValidator } = usePropertyValidations()
const validations = {
property: [requiredValidator, addressValidator(selectedPropertyId, isMatchSelectedProperty)],
}

return (
<Row justify='space-between' gutter={FORM_ROW_MEDIUM_VERTICAL_GUTTER}>
<Col span={24}>
{meterType !== METER_TAB_TYPES.propertyMeter && (
<Typography.Title level={3}>
{ClientInfoMessage}
</Typography.Title>
)}
</Col>
<Col span={24}>
<Row gutter={FORM_ROW_SMALL_VERTICAL_GUTTER}>
<Col span={24}>
<Form.Item
name='property'
label={AddressLabel}
rules={validations.property}
wrapperCol={FORM_ITEM_WRAPPER_COLUMN_STYLE}
shouldUpdate
tooltip={<PropertyFormItemTooltip />}
initialValue={initialValues && initialValues.propertyId}
>
<PropertyAddressSearchInput
organizationId={organizationId}
autoFocus={true}
onSelect={getHandleSelectPropertyAddress(form)}
placeholder={AddressPlaceholder}
onClear={handleDeselectPropertyAddress}
/>
</Form.Item>
</Col>
{notFoundMetersForAddressTooltip && isNoMeterForAddress && (
<Col span={24}>
<Typography.Text size='small' type='secondary'>{notFoundMetersForAddressTooltip}</Typography.Text>
</Col>
)}
</Row>
</Col>

{!isNoMeterForAddress && (
selectedPropertyId || initialValues) && meterType === METER_TAB_TYPES.meter && (property || initialValues) && (
<Col span={24}>
<Row gutter={FORM_ROW_SMALL_VERTICAL_GUTTER}>
<Col span={24}>
<UnitInfo
property={property}
loading={propertyLoading}
setSelectedUnitName={setSelectedUnitName}
setSelectedUnitType={setSelectedUnitType}
form={form}
required
initialValues={{ unitName: get(initialValues, 'unitName'), unitType: get(initialValues, 'unitType') }}
/>
</Col>
{notFoundMetersForAddressTooltip && isNoMeterForUnitName && (
<Col span={24}>
<Typography.Text size='small' type='secondary'>{notFoundMetersForAddressTooltip}</Typography.Text>
</Col>
)}
</Row>
</Col>)
}
</Row>
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Col, Row } from 'antd'
import { Gutter } from 'antd/es/grid/row'
import get from 'lodash/get'
import isEmpty from 'lodash/isEmpty'
import uniq from 'lodash/uniq'
import React, { useCallback, useMemo, useState } from 'react'
Expand All @@ -24,7 +25,7 @@ const AccountNumberFormItem = ({ children, initialValues, rules, validateFirst =
required
rules={rules}
name='accountNumber'
initialValue={initialValues.accountNumber}
initialValue={get(initialValues, 'accountNumber')}
validateFirst={validateFirst}
>
{children}
Expand Down Expand Up @@ -100,8 +101,8 @@ const CreateMeterAccountNumberField = ({ initialValues, propertyId, unitName, ru
}

export const BaseMeterModalAccountNumberField = ({ initialValues, rules, disabled, validateFirst = false }) => {
const propertyId = initialValues.propertyId
const unitName = initialValues.unitName
const propertyId = get(initialValues, 'propertyId')
const unitName = get(initialValues, 'unitName')

if (propertyId && unitName) {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Col, Form, Row } from 'antd'
import { Col, Row } from 'antd'
import { Gutter } from 'antd/es/grid/row'
import dayjs, { Dayjs } from 'dayjs'
import get from 'lodash/get'
Expand All @@ -20,7 +20,7 @@ import {
EXISTING_METER_NUMBER_IN_SAME_ORGANIZATION,
} from '@condo/domains/meter/constants/errors'
import { useMeterValidations } from '@condo/domains/meter/hooks/useMeterValidations'
import { METER_PAGE_TYPES, MeterPageTypes } from '@condo/domains/meter/utils/clientSchema'
import { METER_TAB_TYPES, MeterPageTypes } from '@condo/domains/meter/utils/clientSchema'
import { searchMeterResources } from '@condo/domains/meter/utils/clientSchema/search'

import { BaseMeterModalAccountNumberField } from './BaseMeterModalAccountNumberField'
Expand Down Expand Up @@ -107,7 +107,7 @@ export const BaseMeterModalForm: React.FC<BaseMeterModalFormProps> = ({
const ControlReadingsDateMessage = intl.formatMessage({ id: 'pages.condo.meter.ControlReadingsDate' })
const ResourceMessage = intl.formatMessage({ id: 'pages.condo.meter.Resource' })

const isPropertyMeter = meterType === METER_PAGE_TYPES.propertyMeter
const isPropertyMeter = meterType === METER_TAB_TYPES.propertyMeter
const meterResourceId = get(initialValues, ['resource', 'id'])
const initialInstallationDate = useCallback(() => getInitialDateValue(initialValues, ['installationDate']),
[initialValues])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
import { Form } from 'antd'
import { isEmpty } from 'lodash'
import get from 'lodash/get'
import React from 'react'

import { PlusCircle } from '@open-condo/icons'
import { useIntl } from '@open-condo/next/intl'
import { useOrganization } from '@open-condo/next/organization'
import { ActionBar, Tour } from '@open-condo/ui'

import { ButtonWithDisabledTooltip } from '@condo/domains/common/components/ButtonWithDisabledTooltip'
import { METER_PAGE_TYPES } from '@condo/domains/meter/utils/clientSchema'
import { MeterPageTypes, METER_TAB_TYPES } from '@condo/domains/meter/utils/clientSchema'


const PROPERTY_DEPENDENCY = ['property']
const handleShouldUpdate = (prev, next) => prev.unitName !== next.unitName
type CreateMeterReadingsActionBarProps = {
handleSave: () => void
isLoading: boolean,
newMeterReadings: Array<unknown> | unknown
meterType: MeterPageTypes,
}

export const CreateMeterReadingsActionBar = ({
handleSave,
handleAddMeterButtonClick,
isLoading,
newMeterReadings,
meterType,
}) => {
}: CreateMeterReadingsActionBarProps): JSX.Element => {
const intl = useIntl()
const SendMetersReadingMessage = intl.formatMessage({ id: 'pages.condo.meter.SendMetersReading' })
const AddMeterMessage = intl.formatMessage({ id: 'pages.condo.meter.AddMeter' })
const FieldIsRequiredMessage = intl.formatMessage({ id: 'FieldIsRequired' })
const ErrorsContainerTitle = intl.formatMessage({ id: 'errorsContainer.requiredErrors' })
const AddressLabel = intl.formatMessage({ id: 'field.Address' })
const UnitMessage = intl.formatMessage({ id: 'field.UnitName' })
const AddMeterTourStepTitle = intl.formatMessage({ id: 'pages.condo.meter.create.AddMeterTourStepTitle' })
const AddMeterTourStepMessage = intl.formatMessage({ id: 'pages.condo.meter.create.AddMeterTourStepMessage' })

const { link } = useOrganization()
const canManageMeters = get(link, 'role.canManageMeters', false)
const { currentStep } = Tour.useTourContext()

return (
Expand All @@ -45,11 +42,11 @@ export const CreateMeterReadingsActionBar = ({
{
({ getFieldsValue, getFieldValue, getFieldError }) => {
let isSubmitButtonDisabled, isCreateMeterButtonDisabled, errors, requiredErrorMessage
if (meterType === METER_PAGE_TYPES.meter) {
if (meterType === METER_TAB_TYPES.meter) {
const { property, unitName } = getFieldsValue(['property', 'unitName'])
isSubmitButtonDisabled = !property || !unitName || isEmpty(newMeterReadings)
isCreateMeterButtonDisabled = !property || !unitName
const propertyMismatchError = getFieldError('property').find((error)=>error.includes(FieldIsRequiredMessage))
const propertyMismatchError = getFieldError('property').find((error) => error.includes(FieldIsRequiredMessage))
const propertyErrorMessage = !property && AddressLabel
const unitErrorMessage = !unitName && UnitMessage
const fieldsErrorMessages = [propertyErrorMessage, unitErrorMessage]
Expand All @@ -61,7 +58,7 @@ export const CreateMeterReadingsActionBar = ({
errors = [requiredErrorMessage, propertyMismatchError].filter(Boolean).join(',')
} else {
const property = getFieldValue('property')
const propertyMismatchError = getFieldError('property').find((error)=>error.includes(FieldIsRequiredMessage))
const propertyMismatchError = getFieldError('property').find((error) => error.includes(FieldIsRequiredMessage))
const propertyErrorMessage = !property && AddressLabel
isSubmitButtonDisabled = !property || isEmpty(newMeterReadings)
isCreateMeterButtonDisabled = !property
Expand All @@ -85,25 +82,6 @@ export const CreateMeterReadingsActionBar = ({
>
{SendMetersReadingMessage}
</ButtonWithDisabledTooltip>,
canManageMeters && (
<Tour.TourStep
step={1}
title={AddMeterTourStepTitle}
message={AddMeterTourStepMessage}
>
<ButtonWithDisabledTooltip
key='addMeter'
title={requiredErrorMessage}
onClick={handleAddMeterButtonClick}
type='secondary'
disabled={isCreateMeterButtonDisabled}
icon={<PlusCircle size='medium'/>}
focus={currentStep === 1}
>
{AddMeterMessage}
</ButtonWithDisabledTooltip>
</Tour.TourStep>
),
]}
/>
)
Expand Down
Loading

0 comments on commit 04ea1ed

Please sign in to comment.