import React, { useEffect, useState } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Remove, Visibility, Search } from '@material-ui/icons'; import { EnergyFormatter, formatCurrencyComplete, EnergyTypes, getConfiguration, IPaginatedLoaderHooksFetchDataParameters, IPaginatedLoaderFetchDataReturnValues, usePaginatedLoaderFiltered, checkRecordPassesFilters, ICustomFilterDefinition, CustomFilterInputType, FilterRules, TableMaterial, useLinks, fromGeneralSelectors } from '@energyweb/origin-ui-core'; import { getEnvironment } from '../../features'; import { useDeviceDataLayer } from '../../deviceDataLayer'; import { Order, ANY_VALUE, ANY_OPERATOR } from '../../utils'; import { RemoveOrderConfirmation, OrderDetailsModal } from '../modal'; import moment from 'moment'; const ORDERS_PER_PAGE = 5; interface IOwnProsp { bids: Order[]; } export const BidsTable = (props: IOwnProsp): JSX.Element => { const { bids } = props; const { t } = useTranslation(); const [bidToView, setToView] = useState(); const [bidToRemove, setToRemove] = useState(); const configuration = useSelector(getConfiguration); const deviceTypeService = configuration?.deviceTypeService; const environment = useSelector(getEnvironment); const deviceDataLayer = useDeviceDataLayer(); const deviceClient = deviceDataLayer.deviceClient; const deviceSelector = deviceDataLayer.getAllDevices; const deviceFetcher = deviceDataLayer.fetchAllDevices; const devices = useSelector(deviceSelector) || []; const { exchangePageUrl } = useLinks(); const history = useHistory(); const dispatch = useDispatch(); useEffect(() => { if (deviceClient) { dispatch(deviceFetcher()); } }, [deviceClient]); const columns = [ { id: 'volume', label: t('order.properties.volume') }, { id: 'price', label: t('order.properties.price') }, { id: 'device_type', label: t('order.properties.device_type') }, { id: 'generationFrom', label: t('order.properties.generation_start') }, { id: 'generationTo', label: t('order.properties.generation_end') }, { id: 'filled', label: t('order.properties.filled') } ]; const getFilters = (): ICustomFilterDefinition[] => [ { property: (record: Order) => new Date(record.product.generationFrom).getTime() / 1000, label: t('certificate.properties.generationDateStart'), input: { type: CustomFilterInputType.yearMonth, filterRule: FilterRules.FROM } }, { property: (record: Order) => new Date(record.product.generationTo).getTime() / 1000, label: t('certificate.properties.generationDateEnd'), input: { type: CustomFilterInputType.yearMonth, filterRule: FilterRules.TO } }, { property: ({ product: { deviceType } }: Order) => { return deviceType ? deviceType .filter((device) => !device.includes(';')) .join(', ') .toLowerCase() : undefined; }, label: t('certificate.properties.deviceType'), input: { type: CustomFilterInputType.multiselect, availableOptions: Object.values(EnergyTypes).map((type) => ({ label: `${type[0].toUpperCase()}${type.slice(1).toLowerCase()}`, value: type })), defaultOptions: [] } } ]; async function getPaginatedData({ requestedPageSize, offset, requestedFilters }: IPaginatedLoaderHooksFetchDataParameters): Promise { const filteredAsks = bids.filter((ask) => { return checkRecordPassesFilters(ask, requestedFilters, deviceTypeService); }); return { paginatedData: filteredAsks.slice(offset, offset + requestedPageSize), total: filteredAsks.length }; } const { paginatedData, loadPage, total, pageSize, setPageSize } = usePaginatedLoaderFiltered({ getPaginatedData, initialPageSize: ORDERS_PER_PAGE }); useEffect(() => { setPageSize(ORDERS_PER_PAGE); loadPage(1); }, [bids]); const [currency = 'USD'] = useSelector(fromGeneralSelectors.getCurrencies); const rows = paginatedData.map((bid) => { const { currentVolume, price, product: { deviceType, generationFrom, generationTo }, filled } = bid; const deviceTypeFormatted = (deviceArr: string[]): string => deviceArr.filter((type) => !type.includes(';')).join(', '); return { volume: EnergyFormatter.format(Number(currentVolume), true), price: formatCurrencyComplete(price / 100, currency), device_type: deviceType ? deviceTypeFormatted(deviceType) : '-', generationFrom: generationFrom ? moment(generationFrom) .utcOffset(Number(environment.MARKET_UTC_OFFSET)) .format('MMM, YYYY') : '-', generationTo: generationTo ? moment(generationTo).format('MMM, YYYY') : '-', filled: `${filled * 100}%`, bidId: bid.id }; }); const viewDetails = (rowIndex: number) => { const { bidId } = rows[rowIndex]; const bid = bids.find((o) => o.id === bidId); setToView(bid); }; const removeBid = (rowIndex: number) => { const { bidId } = rows[rowIndex]; const bid = bids.find((o) => o.id === bidId); setToRemove(bid); }; const viewMarket = (rowIndex: number) => { const { bidId } = rows[rowIndex]; const bid = bids.find((o) => o.id === bidId); history.push(`${exchangePageUrl}/view-market`, { redirectDeviceType: bid.product.deviceType || [ANY_VALUE], redirectLocation: bid.product.location || [ANY_VALUE], redirectGridOperator: bid.product.gridOperator || [ANY_OPERATOR], redirectGenerationFrom: bid.product.generationFrom, redirectGenerationTo: bid.product.generationTo }); }; const actions = [ { icon: , name: t('order.actions.viewMarket'), onClick: (row: string) => viewMarket(parseInt(row, 10)) }, { icon: , name: t('order.actions.view'), onClick: (row: string) => viewDetails(parseInt(row, 10)) }, { icon: , name: t('order.actions.remove'), onClick: (row: string) => removeBid(parseInt(row, 10)) } ]; return ( <> viewDetails(parseInt(row, 10))} columns={columns} rows={rows} filters={getFilters()} loadPage={loadPage} total={total} pageSize={pageSize} actions={actions} caption={t('order.captions.open_bids')} /> {bidToView && ( setToView(null)} showCancelOrder={(bid: Order) => { setToView(null); setToRemove(bid); }} /> )} {bidToRemove && ( setToRemove(null)} /> )} ); };