73 lines
2.9 KiB
TypeScript
73 lines
2.9 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import type { FeatureFilters } from '../../types';
|
|
import {
|
|
buildRightmoveExactPostcodeRedirectUrl,
|
|
buildPropertySearchUrls,
|
|
H3_RADIUS_MILES,
|
|
type HexagonLocation,
|
|
} from '../../lib/external-search';
|
|
import outcodeIds from '../../lib/rightmove-outcodes.json';
|
|
|
|
const rightmoveOutcodes = outcodeIds as Record<string, string>;
|
|
|
|
function getRightmoveLocationId(postcode: string | undefined): string | undefined {
|
|
if (!postcode) return undefined;
|
|
const outcode = postcode.trim().split(/\s+/)[0].toUpperCase();
|
|
const id = rightmoveOutcodes[outcode];
|
|
return id ? `OUTCODE^${id}` : undefined;
|
|
}
|
|
|
|
export default function ExternalSearchLinks({
|
|
location,
|
|
filters,
|
|
}: {
|
|
location: HexagonLocation;
|
|
filters: FeatureFilters;
|
|
}) {
|
|
const { t } = useTranslation();
|
|
const rightmoveLocationId = getRightmoveLocationId(location.postcode);
|
|
const urls = useMemo(
|
|
() => buildPropertySearchUrls({ location, filters, rightmoveLocationId }),
|
|
[location, filters, rightmoveLocationId]
|
|
);
|
|
const rightmoveHref = useMemo(() => {
|
|
if (!urls?.rightmove) return null;
|
|
if (!location.isPostcode || !location.postcode) return urls.rightmove;
|
|
return buildRightmoveExactPostcodeRedirectUrl(location.postcode, urls.rightmove);
|
|
}, [location.isPostcode, location.postcode, urls?.rightmove]);
|
|
const radiusMiles = location.isPostcode ? 0 : (H3_RADIUS_MILES[location.resolution] ?? 1);
|
|
const label = radiusMiles === 0 ? t('externalSearch.exact') : `${radiusMiles}mi radius`;
|
|
|
|
if (!urls) return null;
|
|
|
|
const linkClass =
|
|
'flex-1 text-center text-xs py-1.5 px-2 rounded border border-warm-200 dark:border-warm-700 bg-white dark:bg-warm-800 text-teal-600 dark:text-teal-400 hover:bg-warm-50 dark:hover:bg-warm-700 font-medium';
|
|
const disabledClass =
|
|
'flex-1 text-center text-xs py-1.5 px-2 rounded border border-warm-200 dark:border-warm-700 bg-white dark:bg-warm-800 text-warm-400 dark:text-warm-500 font-medium cursor-default';
|
|
|
|
return (
|
|
<div className="p-3 border-b border-warm-200 dark:border-navy-700">
|
|
<h3 className="text-xs font-semibold text-warm-500 dark:text-warm-400 uppercase tracking-wider mb-2">
|
|
{t('externalSearch.searchOn', { radius: label })}
|
|
</h3>
|
|
<div className="flex flex-wrap gap-2">
|
|
{rightmoveHref ? (
|
|
<a href={rightmoveHref} target="_blank" rel="noopener noreferrer" className={linkClass}>
|
|
Rightmove
|
|
</a>
|
|
) : (
|
|
<span className={disabledClass} title={t('externalSearch.outcodeNotRecognised')}>
|
|
Rightmove
|
|
</span>
|
|
)}
|
|
<a href={urls.onthemarket} target="_blank" rel="noopener noreferrer" className={linkClass}>
|
|
OnTheMarket
|
|
</a>
|
|
<a href={urls.zoopla} target="_blank" rel="noopener noreferrer" className={linkClass}>
|
|
Zoopla
|
|
</a>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|