import React, { useState, useEffect } from 'react'; import { DeviceDetailView } from '../../devices/DetailView/DeviceDetailView'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { utils } from 'ethers'; import { makeStyles, createStyles, useTheme } from '@material-ui/core'; import { Skeleton } from '@material-ui/lab'; import { getCertificates, getCertificatesClient, getCertificationRequestsClient } from '../../../features/certificates'; import { deduplicate, formatDate, EnergyFormatter, LightenColor } from '../../../utils'; import { useOriginConfiguration } from '../../../utils/configuration'; import { DeviceDTO } from '@energyweb/origin-device-registry-irec-form-api-client'; import { fromGeneralSelectors } from '../../../features'; import { ClaimDataDTO } from '@energyweb/issuer-api-client'; import moment from 'moment'; interface IProps { id: number; } interface IEnrichedEvent { txHash: string; label: string; description: string; timestamp: number; } type TCertificateData = { label: string; data: string | string[]; link?: string; }; export function CertificateDetailView(props: IProps) { const { t } = useTranslation(); const { id } = props; const certificates = useSelector(getCertificates); const environment = useSelector(fromGeneralSelectors.getEnvironment); const exchangeClient = useSelector(fromGeneralSelectors.getExchangeClient); const deviceClient = useSelector(fromGeneralSelectors.getDeviceClient); const certificatesClient = useSelector(getCertificatesClient); const certificationRequestsClient = useSelector(getCertificationRequestsClient); const [events, setEvents] = useState([]); const useStyles = makeStyles(() => createStyles({ eventsLoader: { padding: '20px' } }) ); const originContext = useOriginConfiguration(); const originBgColor = originContext?.styleConfig?.MAIN_BACKGROUND_COLOR; const originTextColor = originContext?.styleConfig?.TEXT_COLOR_DEFAULT; const originSimpleTextColor = originContext?.styleConfig?.SIMPLE_TEXT_COLOR; const bgColorDarken = LightenColor(originBgColor, -2); const textColorDarken = LightenColor(originTextColor, -4); const classes = useStyles(useTheme()); const selectedCertificate = id !== null && typeof id !== 'undefined' ? certificates.filter((c) => c.id === id).pop() : null; async function enrichEvent() { const { data: allCertificateEvents } = await certificatesClient.getAllEvents( selectedCertificate.id ); const { data: { address: exchangeDepositAddress } } = await exchangeClient.accountClient.getAccount(); const transformAddress = (address: string) => { switch (utils.getAddress(address)) { case environment.EXCHANGE_WALLET_PUB: return t('certificate.event.participants.exchange.wallet'); case exchangeDepositAddress: return t('certificate.event.participants.exchange.depositAddress'); default: return address; } }; const jointEvents = allCertificateEvents.map(async (event: any) => { let label: string; let description: string; switch (event.name) { case 'IssuanceSingle': label = t('certificate.event.name.certified'); description = t('certificate.event.description.certificationRequestApproved'); break; case 'TransferSingle': if (event.from === '0x0000000000000000000000000000000000000000') { label = t('certificate.event.name.initialOwner'); description = transformAddress(event.to); } else if (event.to === '0x0000000000000000000000000000000000000000') { label = ''; description = ''; } else { label = t('certificate.event.name.changedOwnership'); description = t('certificate.event.description.transferred', { amount: EnergyFormatter.format(event.value, true), newOwner: transformAddress(event.to), oldOwner: transformAddress(event.from) }); } break; case 'ClaimSingle': label = t('certificate.event.name.claimed'); description = t('certificate.event.description.claimed', { amount: EnergyFormatter.format(event._value, true), claimer: transformAddress(event._claimIssuer) }); break; default: label = event.name; } return { txHash: event.transactionHash, label, description, timestamp: event.timestamp }; }); const resolvedEvents = await Promise.all(jointEvents); const { data: request } = await certificationRequestsClient.getByCertificate( selectedCertificate.id ); if (request) { resolvedEvents.unshift({ txHash: '', label: t('certificate.event.name.requested'), description: t('certificate.event.description.requested', { requestor: transformAddress(request.owner), amount: EnergyFormatter.format(request.energy, true) }), timestamp: moment((request as any).createdAt).unix() }); } const filteredEvents = resolvedEvents?.filter((event) => !!event.label || !!event.description) || []; setEvents(deduplicate(filteredEvents).sort((a, b) => a.timestamp - b.timestamp)); } const [certificateData, setCertificateData] = useState>([]); const [eventsDisplay, setEventsDisplay] = useState([]); const [device, setDevice] = useState(null); const fetchDeviceById = async (issuerId: string) => { const { data: allDevices }: { data: DeviceDTO[] } = await deviceClient.getAll(); const selectedDevice = allDevices.find((d) => d.externalDeviceIds.find( (deviceExternalId) => deviceExternalId.type === environment.ISSUER_ID && deviceExternalId.id === issuerId ) ); setDevice(selectedDevice); }; useEffect(() => { async function init() { if (!selectedCertificate) { return; } await enrichEvent(); } init(); }, [selectedCertificate?.id]); useEffect(() => { if (selectedCertificate?.deviceId) { fetchDeviceById(selectedCertificate.deviceId); } }, [selectedCertificate]); useEffect(() => { if (events) { const toDisplay = events.reverse().map((event, index) => (

{formatDate(event.timestamp * 1000, true)} {event.txHash && ( <> {' '} -{' '} {event.txHash} )}
{event.label} {event.description ? ` - ${event.description}` : ''}

)); setEventsDisplay(toDisplay); } }, [events]); useEffect(() => { if (selectedCertificate && device) { const dataToDisplay: Array = [ [ { label: t('certificate.properties.id'), data: selectedCertificate.id.toString() }, { label: t('certificate.properties.claimed'), data: selectedCertificate.isClaimed ? selectedCertificate.isOwned ? t('general.responses.partially') : t('general.responses.yes') : t('general.responses.no') }, { label: t('certificate.properties.creationDate'), data: formatDate( selectedCertificate.creationTime * 1000, false, device.timezone ) } ], [ { label: `${ selectedCertificate.isClaimed ? t('certificate.properties.remainingEnergy') : t('certificate.properties.certifiedEnergy') } (${EnergyFormatter.displayUnit})`, data: EnergyFormatter.format(selectedCertificate.energy.publicVolume) }, { label: t('certificate.properties.generationDateStart'), data: formatDate( selectedCertificate.generationStartTime * 1000, true, device.timezone ) }, { label: t('certificate.properties.generationDateEnd'), data: formatDate( selectedCertificate.generationEndTime * 1000, true, device.timezone ) } ] ]; if (selectedCertificate.isClaimed) { const claims = selectedCertificate.myClaims.map((c) => c.claimData); const uniqueClaims: ClaimDataDTO[] = [...new Set(claims)]; const claimInfo = [ { label: `${t('certificate.properties.claimedEnergy')} (${ EnergyFormatter.displayUnit })`, data: EnergyFormatter.format(selectedCertificate.energy.claimedVolume) || [ '' ] } ]; if (uniqueClaims.length > 0) { const fieldData = uniqueClaims.map((oneBeneficiary) => { const { periodStartDate, periodEndDate } = oneBeneficiary; oneBeneficiary.periodStartDate = periodStartDate && `[From: ${formatDate(periodStartDate)}`; oneBeneficiary.periodEndDate = periodEndDate && `To: ${formatDate(periodEndDate)}]`; return Object.values(oneBeneficiary) .filter((value) => value !== '') .join(', '); }); claimInfo.push({ label: t('certificate.properties.claimBeneficiary'), data: fieldData }); } dataToDisplay.push(claimInfo); } setCertificateData(dataToDisplay); } }, [selectedCertificate, device]); if (certificates === null) { return ; } return (
{selectedCertificate ? (
{certificateData.map((row, rowIndex) => ( {row.map((col) => ( ))} ))}
{col.label}
{typeof col.data === 'string' ? ( col.data ) : ( <> {col.data.length > 1 ? (
    {col.data.map( (text, idx) => (
  1. {text}
  2. ) )}
) : ( col.data[0] )} )}
) : (
{t('certificate.feedback.certificateNotFound')}
)}
{selectedCertificate && device && ( )} {selectedCertificate && (
{eventsDisplay.length === 0 ? (
) : (
{eventsDisplay}
)}
)}
); }