Files
upstream-jitsi-meet/react/features/salesforce/components/web/SearchResultsSection.tsx
upstream-mirror 1d2bfcac0c
Some checks failed
Prosody Plugin Tests / test (push) Failing after 10m11s
Close stale issues and PRs / stale (push) Failing after 1s
snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
2026-09-15 15:56:32 +05:00

184 lines
6.7 KiB
TypeScript

import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
import {
IconRecordAccount,
IconRecordContact,
IconRecordLead,
IconRecordOpportunity
} from '../../../base/icons/svg';
import { BUTTON_TYPES } from '../../../base/ui/constants.web';
import {
IAccountMatch,
IContactMatch,
ILeadMatch,
IOpportunityMatch,
ISearchResults,
SalesforceObjectType
} from '../../types';
import { RecordListItem } from './RecordListItem';
interface IProps {
linkingId: string | null;
onLink: (type: SalesforceObjectType, data: IAccountMatch | ILeadMatch | IContactMatch | IOpportunityMatch) => void;
results: ISearchResults;
}
const useStyles = makeStyles()(theme => {
return {
section: {
marginBottom: '16px'
},
groupTitle: {
fontSize: '0.75rem',
fontWeight: 600,
color: theme.palette.text03,
textTransform: 'uppercase',
margin: '16px 0 8px 0'
},
list: {
listStyle: 'none',
margin: 0,
padding: 0
},
noResults: {
textAlign: 'center',
color: theme.palette.text03,
padding: '24px'
}
};
});
/**
* Component for displaying Salesforce search results with link buttons.
*
* @param {IProps} props - Component props.
* @returns {React.ReactElement}
*/
export const SearchResultsSection = ({ results, linkingId, onLink }: IProps) => {
const { t } = useTranslation();
const { classes } = useStyles();
const hasResults = results.accounts.length
|| results.leads.length
|| results.contacts.length
|| results.opportunities.length;
const handleLinkAccount = useCallback((account: IAccountMatch) => {
onLink('Account', account);
}, [ onLink ]);
const handleLinkLead = useCallback((lead: ILeadMatch) => {
onLink('Lead', lead);
}, [ onLink ]);
const handleLinkContact = useCallback((contact: IContactMatch) => {
onLink('Contact', contact);
}, [ onLink ]);
const handleLinkOpportunity = useCallback((opportunity: IOpportunityMatch) => {
onLink('Opportunity', opportunity);
}, [ onLink ]);
if (!hasResults) {
return (
<div className = { classes.noResults }>
{t('dialog.searchResultsNotFound')}
</div>
);
}
return (
<div className = { classes.section }>
{!!results.accounts.length && (
<>
<h4 className = { classes.groupTitle }>{t('record.type.account')}</h4>
<ul className = { classes.list }>
{results.accounts.map(account => (
<RecordListItem
actionLabelKey = 'dialog.link'
actionType = { BUTTON_TYPES.PRIMARY }
disabled = { linkingId !== null }
icon = { IconRecordAccount }
isLoading = { linkingId === account.accountId }
key = { account.accountId }
name = { account.accountName }
onAction = { handleLinkAccount }
record = { account } />
))}
</ul>
</>
)}
{!!results.leads.length && (
<>
<h4 className = { classes.groupTitle }>{t('record.type.lead')}</h4>
<ul className = { classes.list }>
{results.leads.map(lead => (
<RecordListItem
actionLabelKey = 'dialog.link'
actionType = { BUTTON_TYPES.PRIMARY }
disabled = { linkingId !== null }
icon = { IconRecordLead }
isLoading = { linkingId === lead.leadId }
key = { lead.leadId }
metadata = { lead.leadCompany }
name = { lead.leadName }
onAction = { handleLinkLead }
record = { lead } />
))}
</ul>
</>
)}
{!!results.contacts.length && (
<>
<h4 className = { classes.groupTitle }>{t('record.type.contact')}</h4>
<ul className = { classes.list }>
{results.contacts.map(contact => (
<RecordListItem
actionLabelKey = 'dialog.link'
actionType = { BUTTON_TYPES.PRIMARY }
disabled = { linkingId !== null }
icon = { IconRecordContact }
isLoading = { linkingId === contact.contactId }
key = { contact.contactId }
metadata = { contact.contactEmail }
name = { contact.contactName }
onAction = { handleLinkContact }
record = { contact } />
))}
</ul>
</>
)}
{!!results.opportunities.length && (
<>
<h4 className = { classes.groupTitle }>{t('record.type.opportunity')}</h4>
<ul className = { classes.list }>
{results.opportunities.map(opp => (
<RecordListItem
actionLabelKey = 'dialog.link'
actionType = { BUTTON_TYPES.PRIMARY }
disabled = { linkingId !== null }
icon = { IconRecordOpportunity }
isLoading = { linkingId === opp.opportunityId }
key = { opp.opportunityId }
metadata = { `${opp.opportunityStage}${
opp.amount !== undefined ? ` \u2022 $${opp.amount.toLocaleString()}` : ''
}` }
name = { opp.opportunityName }
onAction = { handleLinkOpportunity }
record = { opp } />
))}
</ul>
</>
)}
</div>
);
};
export default SearchResultsSection;