import { useTranslation } from 'react-i18next';
import {
FieldValueDirectAnswer as FieldValueDirectAnswerType,
BuiltInFieldType,
Address,
UnknownFieldValueDirectAnswer
} from '@yext/search-headless-react';
import React, { useMemo } from 'react';
import { UnknownFieldTypeDisplayComponent } from './DirectAnswer';
/**
* Props for FieldValueDirectAnswer.
*/
interface FieldValueDirectAnswerProps {
/** A field value direct answer result. */
result: FieldValueDirectAnswerType,
/** Handle onClick event for "View Details" link. */
viewDetailsClickHandler?: () => void,
/** {@inheritDoc DirectAnswerProps.UnknownFieldTypeDisplay} */
UnknownFieldTypeDisplay?: UnknownFieldTypeDisplayComponent,
/** CSS classes for customizing the component styling. */
cssClasses?: FieldValueDirectAnswerCssClasses
}
/**
* The CSS class interface for FieldValueDirectAnswer.
*/
interface FieldValueDirectAnswerCssClasses {
header?: string,
body?: string,
content?: string,
answerContainer?: string
}
/**
* Renders a field value direct answer provided by the Search API.
*
* @internal
*/
export function FieldValueDirectAnswer({
result,
viewDetailsClickHandler,
UnknownFieldTypeDisplay,
cssClasses = {}
}: FieldValueDirectAnswerProps): React.JSX.Element {
const { t } = useTranslation();
const title = `${result.entityName} / ${result.fieldName}`;
const link = result.relatedResult.link ?? result.relatedResult.rawData.landingPageUrl as string;
const resultContent = useMemo(() => {
return getResultContent(result, UnknownFieldTypeDisplay);
}, [result, UnknownFieldTypeDisplay]);
return (
{title &&
{title}
}
{resultContent}
{link &&
}
);
}
function DefaultUnknownFieldTypeDisplay(
{ result }: { result: UnknownFieldValueDirectAnswer }
): React.JSX.Element {
let val: string | number;
if (typeof result.value !== 'string' && typeof result.value !== 'number') {
console.warn(`Unknown field type for direct answer with "${result.fieldApiName}" fieldApiName. Rendering result's value as a string.`
+ '\nConsider using prop "UnknownFieldTypeDisplay" in DirectAnswer component to properly render result of unknown field type.');
val = JSON.stringify(result.value);
} else {
val = result.value;
}
return getTextJsxElement(val);
}
function getResultContent(
result: FieldValueDirectAnswerType,
UnknownFieldTypeDisplay: UnknownFieldTypeDisplayComponent = DefaultUnknownFieldTypeDisplay
): React.JSX.Element {
switch (result.fieldType) {
case BuiltInFieldType.InstagramHandle:
return getAnchorTagJsxElement(`https://www.instagram.com/${result.value}`, result.value);
case BuiltInFieldType.TwitterHandle:
return getAnchorTagJsxElement(`https://twitter.com/${result.value}`, `@${result.value}`);
case BuiltInFieldType.FacebookURL:
case BuiltInFieldType.AndroidAppURL:
case BuiltInFieldType.IOSAppURL:
return getAnchorTagJsxElement(result.value);
case BuiltInFieldType.ComplexURL:
const url = result.value.url;
const displayUrl = result.value.preferDisplayUrl ? result.value.displayUrl : url;
return getAnchorTagJsxElement(url, displayUrl);
case BuiltInFieldType.URL:
return Array.isArray(result.value)
? getListJsxElement(result.value, url => getAnchorTagJsxElement(url))
: getAnchorTagJsxElement(result.value);
case BuiltInFieldType.Phone:
return getAnchorTagJsxElement(`tel:${result.value}`, result.value);
case BuiltInFieldType.Email:
return getListJsxElement(result.value, e => getAnchorTagJsxElement(`mailto:${e}`, e));
case BuiltInFieldType.Address:
return getAddressJsxElement(result.value);
case BuiltInFieldType.RichText:
//TODO: SLAP-2340
console.warn('Rendering markdown for rich text direct answer is currently not supported. Displaying the unrendered markdown string(s) as is.');
return Array.isArray(result.value)
? getListJsxElement(result.value, val => getTextJsxElement(val))
: getTextJsxElement(result.value);
case BuiltInFieldType.Hours:
return {JSON.stringify(result.value)}
;
case 'unknown':
return ;
default:
return Array.isArray(result.value)
? getListJsxElement(result.value as (string | number)[], val => getTextJsxElement(val))
: getTextJsxElement(result.value as string | number);
}
}
function getListJsxElement(
list: T[],
getItemJsxElement: (el: T) => React.JSX.Element
): React.JSX.Element {
return (
{list.map((el, i) =>
-
{getItemJsxElement(el)}
)}
);
}
function getTextJsxElement(text: string | number): React.JSX.Element {
return {text}
;
}
function getAnchorTagJsxElement(href: string, displayText?: string): React.JSX.Element {
return {displayText ?? href};
}
function getAddressJsxElement(address: Address): React.JSX.Element {
// user specified display Address in KM
if (address.extraDescription) {
return {address.extraDescription}
;
}
const formattedCity = address.city ? address.city + ',' : '';
const formattedCityRegionPostalCode = [formattedCity, address.region, address.postalCode].join(' ').trim();
return
{address.line1 &&
{address.line1}
}
{address.line2 &&
{address.line2}
}
{address.line3 &&
{address.line3}
}
{formattedCityRegionPostalCode &&
{formattedCityRegionPostalCode}
}
{address.countryCode}
;
}