import React, { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { BigNumber } from 'ethers'; import { Edit, Remove } from '@material-ui/icons'; import moment from 'moment'; import { checkRecordPassesFilters, CustomFilterInputType, EnergyFormatter, formatCurrencyComplete, fromGeneralSelectors, ICustomFilterDefinition, IPaginatedLoaderHooksFetchDataParameters, Requirements, TableFallback, TableMaterial, usePaginatedLoaderFiltered, usePermissions } from '@energyweb/origin-ui-core'; import { getEnvironment } from '../features/general'; import { fetchSupplies, getSupplies } from '../features/supply'; import { IDeviceWithSupply, ISupplyTableRecord } from '../types'; import { RemoveSupplyConfirmation, UpdateSupplyModal } from '../components/modal'; import { useDeviceDataLayer } from '../deviceDataLayer'; export enum SupplyStatus { Active = 'Active', Paused = 'Paused' } export const SupplyTablePage = () => { const deviceDataLayer = useDeviceDataLayer(); const deviceClient = deviceDataLayer.deviceClient; const { t } = useTranslation(); const currencies = useSelector(fromGeneralSelectors.getCurrencies); const defaultCurrency = (currencies && currencies[0]) ?? 'USD'; const environment = useSelector(getEnvironment); const issuerId = environment?.ISSUER_ID; const dispatch = useDispatch(); const deviceSelector = deviceDataLayer.getMyDevices; const deviceFetcher = deviceDataLayer.fetchMyDevices; const myDevices = useSelector(deviceSelector); const [showUpdateModal, setShowModal] = useState(false); const [entity, setEntity] = useState(null); const [supplyToRemove, setToRemove] = useState(); const supplySettings = useSelector(getSupplies); async function getPaginatedData({ requestedPageSize, offset, requestedFilters }: IPaginatedLoaderHooksFetchDataParameters) { if (!deviceClient) { return { paginatedData: [], total: 0 }; } let entities: IDeviceWithSupply[] = []; entities = myDevices.map((device) => { const matchingSupply = supplySettings?.find( (supply) => supply.deviceId === device.externalDeviceIds.find((external) => external.type === issuerId).id ); if (matchingSupply) { return { facilityName: 'facilityName' in device ? device.facilityName : device.name, deviceType: device.deviceType, toBeCertified: 'meterStats' in device ? device.meterStats?.uncertified : '0', externalDeviceIds: device.externalDeviceIds, active: matchingSupply.active, price: matchingSupply.price, supplyId: matchingSupply.id, supplyCreated: true }; } else { return { facilityName: 'facilityName' in device ? device.facilityName : device.name, deviceType: device.deviceType, toBeCertified: 'meterStats' in device ? device.meterStats?.uncertified : '0', price: 0, externalDeviceIds: device.externalDeviceIds, supplyCreated: false }; } }); const filteredEntities = entities.filter((device) => { return checkRecordPassesFilters(device, requestedFilters); }); let newPaginatedData: ISupplyTableRecord[] = filteredEntities.map((i) => ({ device: i })); newPaginatedData = newPaginatedData.slice(offset, offset + requestedPageSize); const newTotal = newPaginatedData.length; return { paginatedData: newPaginatedData, total: newTotal }; } const { paginatedData, loadPage, total, pageSize } = usePaginatedLoaderFiltered({ getPaginatedData }); useEffect(() => { if (supplySettings !== null && myDevices !== null) { loadPage(1); } }, [supplySettings, myDevices]); useEffect(() => { if (deviceClient) { dispatch(deviceFetcher()); dispatch(fetchSupplies()); } }, [deviceClient]); const currentYear = moment().format('YYYY'); const nextYear = moment().add(1, 'years').format('YYYY'); const columns = [ { id: 'type', label: t('exchange.supply.type') }, { id: 'facility', label: t('exchange.supply.facilityName') }, { id: 'price', label: t('exchange.supply.price') }, { id: 'status', label: t('exchange.supply.status') }, { id: 'certified', label: `${t( 'exchange.supply.meterReadToBeCertified' )} for ${currentYear}/${nextYear} (${EnergyFormatter.displayUnit})` } ] as const; const rows = paginatedData.map(({ device }) => { return { type: device.deviceType.replace(new RegExp(';', 'g'), ' - ') ?? '-', facility: device.facilityName, price: formatCurrencyComplete(device.price || 0 / 100, defaultCurrency), status: device.active ? SupplyStatus.Active : SupplyStatus.Paused, certified: EnergyFormatter.format(BigNumber.from(device.toBeCertified ?? 0).toNumber()) }; }); const editSupply = (index: string) => { const { device } = paginatedData[index]; setEntity({ ...device, deviceType: device.deviceType?.replace(new RegExp(';', 'g'), ' - ') ?? '-' }); setShowModal(true); }; const removeSupply = (index: string) => { const { device } = paginatedData[index]; setToRemove(device); }; const actions = [ { icon: , name: t('exchange.supply.update'), onClick: (idx: string) => editSupply(idx) }, { icon: , name: t('exchange.supply.remove'), onClick: (idx: string) => removeSupply(idx) } ]; const filters: ICustomFilterDefinition[] = [ { property: (device: IDeviceWithSupply) => device.facilityName.toString(), label: t('exchange.supply.facility'), input: { type: CustomFilterInputType.string } }, { property: (device: IDeviceWithSupply) => device.active ? SupplyStatus.Active : SupplyStatus.Paused, label: t('exchange.supply.status'), input: { type: CustomFilterInputType.dropdown, availableOptions: Object.values(SupplyStatus).map((value) => ({ value, label: value })) } } ]; const { canAccessPage } = usePermissions(); if (!canAccessPage?.value) { return ; } if (supplySettings === null || myDevices === null) { return ; } return ( <> {entity && ( )} {supplyToRemove && ( setToRemove(null)} /> )} ); }; SupplyTablePage.displayName = 'SupplyTablePage';