.
This commit is contained in:
parent
f99bd4e5c9
commit
a04ac2d857
16 changed files with 132 additions and 74 deletions
|
|
@ -291,7 +291,69 @@ describe('LocationSearch', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('shows an empty state for invalid place queries', async () => {
|
||||
it('preserves the server unified ordering and sends the viewport centre', async () => {
|
||||
const fetchMock = vi.fn((input: string | URL | Request) => {
|
||||
const url = new URL(String(input), 'http://localhost');
|
||||
if (url.pathname === '/api/places') {
|
||||
return Promise.resolve(
|
||||
jsonResponse({
|
||||
places: [],
|
||||
postcodes: [],
|
||||
addresses: [],
|
||||
// Intentionally out of "bucket" order: an address outranks a place. The hook must
|
||||
// render them in this server order rather than re-bucketing or re-filtering.
|
||||
results: [
|
||||
{
|
||||
type: 'address',
|
||||
address: '1 High Street',
|
||||
postcode: 'CR0 1AA',
|
||||
lat: 51.37,
|
||||
lon: -0.1,
|
||||
score: 930,
|
||||
},
|
||||
{
|
||||
type: 'place',
|
||||
name: 'Croydon',
|
||||
slug: 'croydon',
|
||||
place_type: 'town',
|
||||
lat: 51.37,
|
||||
lon: -0.1,
|
||||
score: 880,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
}
|
||||
return Promise.resolve(new Response(null, { status: 404 }));
|
||||
});
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
|
||||
render(
|
||||
<LocationSearch
|
||||
onFlyTo={vi.fn()}
|
||||
onLocationSearched={vi.fn()}
|
||||
getViewportCenter={() => ({ lat: 51.5, lng: -0.12 })}
|
||||
/>
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByRole('textbox'), { target: { value: 'high street' } });
|
||||
|
||||
// The address (first in the server list) renders before the place, unfiltered.
|
||||
const firstResult = await screen.findByText('1 High Street');
|
||||
const place = screen.getByText('Croydon');
|
||||
expect(
|
||||
firstResult.compareDocumentPosition(place) & Node.DOCUMENT_POSITION_FOLLOWING
|
||||
).toBeTruthy();
|
||||
|
||||
const placesCall = fetchMock.mock.calls.find(([input]) =>
|
||||
String(input).includes('/api/places')
|
||||
);
|
||||
const calledUrl = new URL(String(placesCall?.[0]), 'http://localhost');
|
||||
expect(calledUrl.searchParams.get('lat')).toBe('51.5');
|
||||
expect(calledUrl.searchParams.get('lng')).toBe('-0.12');
|
||||
});
|
||||
|
||||
it('shows an empty state for invalid place queries (legacy server, no results key)', async () => {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn(() =>
|
||||
|
|
@ -314,6 +376,23 @@ describe('LocationSearch', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('shows the empty state when the new server returns an empty results array', async () => {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn(() =>
|
||||
Promise.resolve(jsonResponse({ places: [], postcodes: [], addresses: [], results: [] }))
|
||||
)
|
||||
);
|
||||
|
||||
render(<LocationSearch onFlyTo={vi.fn()} onLocationSearched={vi.fn()} />);
|
||||
|
||||
fireEvent.change(screen.getByRole('textbox'), { target: { value: 'zzzznowhere' } });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('No matching places or postcodes')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps only the three most recent local searches', async () => {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
|
|
|
|||
|
|
@ -937,6 +937,10 @@ export default memo(function Map({
|
|||
dimensions.width < DESKTOP_TOP_CARDS_ROW_MIN_MAP_WIDTH;
|
||||
const showLocationSearch = !hideLocationSearch && !hideDesktopTopCardsForWidth;
|
||||
const showLegend = !hideLegend && !hideDesktopTopCardsForWidth;
|
||||
const getViewportCenter = useCallback(() => {
|
||||
const center = mapRef.current?.getCenter();
|
||||
return center ? { lat: center.lat, lng: center.lng } : null;
|
||||
}, []);
|
||||
const desktopTopCardsLayoutClass = stackDesktopTopCards
|
||||
? 'flex-col items-start'
|
||||
: 'items-start justify-between';
|
||||
|
|
@ -1099,6 +1103,7 @@ export default memo(function Map({
|
|||
onLocationSearched={onLocationSearched}
|
||||
onCurrentLocationFound={onCurrentLocationFound}
|
||||
onMouseEnter={handleMouseLeave}
|
||||
getViewportCenter={getViewportCenter}
|
||||
className={DESKTOP_TOP_CARD_CLASS}
|
||||
inputClassName={DESKTOP_LOCATION_SEARCH_INPUT_CLASS}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -103,7 +103,10 @@ export default function MobileDrawer({
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div data-tutorial="right-pane" className="pointer-events-none fixed inset-0 z-50 flex flex-col">
|
||||
<div
|
||||
data-tutorial="right-pane"
|
||||
className="pointer-events-none fixed inset-0 z-50 flex flex-col"
|
||||
>
|
||||
<div className="h-[10%] shrink-0" aria-hidden="true" />
|
||||
|
||||
{/* Panel — bottom 90% */}
|
||||
|
|
|
|||
|
|
@ -192,9 +192,7 @@ export function useExportController({
|
|||
const detail = err instanceof Error && err.message.trim() ? ` ${err.message}` : '';
|
||||
showExportNotice({
|
||||
kind: 'error',
|
||||
message: timedOut
|
||||
? t('header.exportTimedOut')
|
||||
: `${t('header.exportFailed')}${detail}`,
|
||||
message: timedOut ? t('header.exportTimedOut') : `${t('header.exportFailed')}${detail}`,
|
||||
});
|
||||
} finally {
|
||||
window.clearTimeout(timeoutId);
|
||||
|
|
|
|||
|
|
@ -78,11 +78,7 @@ export default function ExportMenu({ open, exporting, onClose, onExport }: Expor
|
|||
} else {
|
||||
inputRefs.current[idx + 1]?.focus();
|
||||
}
|
||||
} else if (
|
||||
e.key === 'Backspace' &&
|
||||
postcodes[idx] === '' &&
|
||||
postcodes.length > 1
|
||||
) {
|
||||
} else if (e.key === 'Backspace' && postcodes[idx] === '' && postcodes.length > 1) {
|
||||
e.preventDefault();
|
||||
focusIndexRef.current = Math.max(0, idx - 1);
|
||||
removeAt(idx);
|
||||
|
|
@ -98,11 +94,7 @@ export default function ExportMenu({ open, exporting, onClose, onExport }: Expor
|
|||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 bg-black/50 z-[90]"
|
||||
onClick={onClose}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div className="fixed inset-0 bg-black/50 z-[90]" onClick={onClose} aria-hidden="true" />
|
||||
<div
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
|
|
|
|||
|
|
@ -68,9 +68,7 @@ export function FeatureLabel({
|
|||
{GroupIcon && <GroupIcon className={iconClass} />}
|
||||
{translatedDesc ? (
|
||||
<div className="min-w-0">
|
||||
<div className={`flex ${wrap ? 'items-start' : 'items-center'} gap-1`}>
|
||||
{nameContent}
|
||||
</div>
|
||||
<div className={`flex ${wrap ? 'items-start' : 'items-center'} gap-1`}>{nameContent}</div>
|
||||
<span className="text-xs text-warm-400 dark:text-warm-500 block">{translatedDesc}</span>
|
||||
</div>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -144,12 +144,7 @@ export function useHexagonSelection({
|
|||
);
|
||||
|
||||
const fetchPostcodeStats = useCallback(
|
||||
async (
|
||||
postcode: string,
|
||||
signal?: AbortSignal,
|
||||
includeFilters = true,
|
||||
fields?: string[]
|
||||
) => {
|
||||
async (postcode: string, signal?: AbortSignal, includeFilters = true, fields?: string[]) => {
|
||||
const params = new URLSearchParams({ postcode });
|
||||
const filterStr = includeFilters ? buildFilterString(filters, features) : '';
|
||||
if (filterStr) params.append('filters', filterStr);
|
||||
|
|
|
|||
|
|
@ -214,22 +214,19 @@ const de: Translations = {
|
|||
'Relax one constraint at a time': 'Lockere eine Einschränkung nach der anderen',
|
||||
'When the search becomes too narrow, loosen a single filter and watch which postcodes reappear. This makes compromise explicit instead of relying on guesswork.':
|
||||
'Wenn die Suche zu eng wird, lockere einen einzelnen Filter und sieh, welche Postcodes wieder auftauchen. So werden Kompromisse sichtbar statt geraten.',
|
||||
'Turn vague areas into specific postcodes':
|
||||
'Verwandle vage Gebiete in konkrete Postcodes',
|
||||
'Turn vague areas into specific postcodes': 'Verwandle vage Gebiete in konkrete Postcodes',
|
||||
'Broad town or borough searches hide large differences between streets. Perfect Postcode helps you move from a general area to postcodes that satisfy your hard requirements.':
|
||||
'Breite Stadt- oder Borough-Suchen verdecken große Unterschiede zwischen Straßen. Perfect Postcode hilft dir, von einem allgemeinen Gebiet zu Postcodes zu gelangen, die deine Muss-Kriterien erfüllen.',
|
||||
'Keep trade-offs visible': 'Halte Kompromisse sichtbar',
|
||||
'When there are too many or too few matches, adjust one constraint at a time and see exactly which postcodes reappear. That makes compromises explicit instead of relying on guesswork.':
|
||||
'Wenn es zu viele oder zu wenige Treffer gibt, ändere jeweils eine Anforderung und sieh genau, welche Postcodes wieder auftauchen. So werden Kompromisse sichtbar statt geraten.',
|
||||
'Why postcode-level comparison matters':
|
||||
'Warum Vergleiche auf Postcode-Ebene wichtig sind',
|
||||
'Why postcode-level comparison matters': 'Warum Vergleiche auf Postcode-Ebene wichtig sind',
|
||||
'Two nearby postcodes can differ on schools, road noise, transport access, property mix, and price. Comparing at postcode level reduces the chance of treating a whole town as one uniform market.':
|
||||
'Zwei nahegelegene Postcodes können sich bei Schulen, Straßenlärm, Verkehrsanbindung, Immobilienmix und Preis stark unterscheiden. Der Vergleich auf Postcode-Ebene verhindert, dass eine ganze Stadt wie ein einheitlicher Markt behandelt wird.',
|
||||
'How to use the results': 'So nutzt du die Ergebnisse',
|
||||
'Treat matching postcodes as a research queue: check live listings, visit streets, confirm schools and admissions, and review current official sources.':
|
||||
'Behandle passende Postcodes wie eine Recherche-Liste: Prüfe Live-Inserate, geh durch die Straßen, bestätige Schulen und Admissions und nutze aktuelle offizielle Quellen.',
|
||||
'Can I save a postcode property search?':
|
||||
'Kann ich eine Postcode-Immobiliensuche speichern?',
|
||||
'Can I save a postcode property search?': 'Kann ich eine Postcode-Immobiliensuche speichern?',
|
||||
'Yes. Licensed users can save searches and return to them later. Saved searches are designed for shortlists and comparison notes.':
|
||||
'Ja. Lizenzierte Nutzer können Suchen speichern und später darauf zurückgreifen. Gespeicherte Suchen sind für Auswahllisten und Vergleichsnotizen gedacht.',
|
||||
'Can I search without knowing the area?': 'Kann ich suchen, ohne die Gegend zu kennen?',
|
||||
|
|
@ -268,8 +265,7 @@ const de: Translations = {
|
|||
'Pendeln nach Postcode, nicht nur nach Ortsname',
|
||||
'Two streets in the same town can have very different station access, road routes, and public transport options. Postcode-level travel-time filtering keeps that difference visible.':
|
||||
'Zwei Straßen in derselben Stadt können sehr unterschiedliche Bahnhofsanbindungen, Straßenrouten und ÖPNV-Optionen haben. Fahrzeitfilter auf Postcode-Ebene halten diesen Unterschied sichtbar.',
|
||||
'Balance journey time with the rest of the move':
|
||||
'Fahrzeit mit dem restlichen Umzug abwägen',
|
||||
'Balance journey time with the rest of the move': 'Fahrzeit mit dem restlichen Umzug abwägen',
|
||||
'A fast commute only helps if the area also fits your budget, housing needs, school preferences, safety threshold, broadband requirement, and tolerance for road noise.':
|
||||
'Ein kurzer Arbeitsweg hilft nur, wenn die Gegend auch zu Budget, Wohnbedarf, Schulwünschen, Sicherheitsgefühl, Breitbandbedarf und Lärmtoleranz passt.',
|
||||
'How travel-time filters should be interpreted': 'Wie Fahrzeitfilter zu verstehen sind',
|
||||
|
|
@ -320,8 +316,7 @@ const de: Translations = {
|
|||
'Die Schulqualität ist ein Teil der engeren Auswahl',
|
||||
'Perfect Postcode helps you compare nearby school data with the other practical constraints that shape a family move: space, price, commute, parks, safety, and local services.':
|
||||
'Mit Perfect Postcode vergleichst du Schuldaten in der Nähe mit den anderen praktischen Faktoren eines Familienumzugs: Platz, Preis, Pendelweg, Parks, Sicherheit und lokale Infrastruktur.',
|
||||
'Check catchments before making decisions':
|
||||
'Catchments vor Entscheidungen prüfen',
|
||||
'Check catchments before making decisions': 'Catchments vor Entscheidungen prüfen',
|
||||
'Admissions rules and catchment boundaries can change. Use postcode-level school data to find promising areas, then verify current admissions details with the school or local authority.':
|
||||
'Admissions-Regeln und Catchment-Grenzen können sich ändern. Nutze Schuldaten auf Postcode-Ebene, um vielversprechende Gebiete zu finden, und prüfe aktuelle Details bei Schule oder Local Authority.',
|
||||
'How to treat school filters': 'Wie du Schulfilter einordnest',
|
||||
|
|
@ -474,12 +469,10 @@ const de: Translations = {
|
|||
'Make commute constraints explicit': 'Mache Pendelanforderungen klar',
|
||||
'If access to the centre, a station, hospital, university, or business park matters, use travel-time filters first and then compare the remaining postcodes by property data.':
|
||||
'Wenn die Erreichbarkeit des Zentrums, eines Bahnhofs, Krankenhauses, einer Universität oder eines Business Parks wichtig ist, nutze zuerst Fahrzeitfilter und vergleiche dann die übrigen Postcodes anhand der Immobiliendaten.',
|
||||
'Compare value, not just headline price':
|
||||
'Wert vergleichen, nicht nur den Angebotspreis',
|
||||
'Compare value, not just headline price': 'Wert vergleichen, nicht nur den Angebotspreis',
|
||||
'Use price, property type, and floor-area filters together. This helps distinguish lower-cost areas from areas that simply contain smaller or different homes.':
|
||||
'Nutze Preis-, Immobilientyp- und Wohnflächenfilter gemeinsam. So kannst du günstigere Gebiete von Gebieten unterscheiden, in denen einfach kleinere oder andere Immobilien stehen.',
|
||||
'Screen environmental and local-service signals':
|
||||
'Umwelt- und Infrastruktur-Signale prüfen',
|
||||
'Screen environmental and local-service signals': 'Umwelt- und Infrastruktur-Signale prüfen',
|
||||
'Road noise, parks, broadband, crime, and amenities can affect whether a property works day to day. Use them as screening criteria before booking viewings.':
|
||||
'Straßenlärm, Parks, Breitband, Kriminalität und Infrastruktur können entscheiden, ob eine Immobilie im Alltag funktioniert. Nutze sie als Screening-Kriterien, bevor du Besichtigungen buchst.',
|
||||
'Can I use this for commuter villages around Bristol?':
|
||||
|
|
@ -604,8 +597,7 @@ const de: Translations = {
|
|||
logIn: 'Anmelden',
|
||||
createAccount: 'Konto erstellen',
|
||||
resetPassword: 'Passwort zurücksetzen',
|
||||
valueProp:
|
||||
'Speichere Suchen, merke Immobilien und erstelle eine Shortlist passender Gebiete.',
|
||||
valueProp: 'Speichere Suchen, merke Immobilien und erstelle eine Shortlist passender Gebiete.',
|
||||
continueWithGoogle: 'Weiter mit Google',
|
||||
email: 'E-Mail',
|
||||
emailPlaceholder: 'name@beispiel.de',
|
||||
|
|
|
|||
|
|
@ -322,8 +322,7 @@ const fr: Translations = {
|
|||
'La qualité des écoles n’est qu’une partie de la sélection',
|
||||
'Perfect Postcode helps you compare nearby school data with the other practical constraints that shape a family move: space, price, commute, parks, safety, and local services.':
|
||||
'Perfect Postcode vous aide à comparer les données des écoles à proximité avec les autres contraintes pratiques d’un déménagement familial : espace, prix, trajet, parcs, sécurité et services locaux.',
|
||||
'Check catchments before making decisions':
|
||||
'Vérifier les catchment areas avant de décider',
|
||||
'Check catchments before making decisions': 'Vérifier les catchment areas avant de décider',
|
||||
'Admissions rules and catchment boundaries can change. Use postcode-level school data to find promising areas, then verify current admissions details with the school or local authority.':
|
||||
'Les règles d’admission et les limites de catchment peuvent changer. Utilisez les données scolaires par code postal pour repérer des secteurs prometteurs, puis vérifiez les admissions à jour auprès de l’école ou de l’autorité locale.',
|
||||
'How to treat school filters': 'Comment traiter les filtres scolaires',
|
||||
|
|
@ -382,8 +381,7 @@ const fr: Translations = {
|
|||
'Ce qu’une vérification du code postal ne peut pas prouver',
|
||||
'It can’t confirm the condition of a home, future development, legal title, lender requirements, or current street-level experience. Those still need direct checks.':
|
||||
'Il ne peut pas confirmer l’état d’un logement, les futurs projets, le titre de propriété, les exigences du prêteur ou le ressenti actuel dans la rue. Ces points demandent encore des vérifications directes.',
|
||||
'Can I use the checker before a viewing?':
|
||||
'Puis-je utiliser cet outil avant une visite ?',
|
||||
'Can I use the checker before a viewing?': 'Puis-je utiliser cet outil avant une visite ?',
|
||||
'Yes. That’s one of the main use cases: screen the postcode first, then decide whether the viewing is worth the time.':
|
||||
'Oui. C’est l’un des principaux cas d’utilisation : examinez d’abord le code postal, puis décidez si la visite vaut le temps consacré.',
|
||||
'Does the checker include exact property condition?':
|
||||
|
|
@ -482,8 +480,7 @@ const fr: Translations = {
|
|||
'Compare value, not just headline price': 'Comparez la valeur, pas seulement le prix affiché',
|
||||
'Use price, property type, and floor-area filters together. This helps distinguish lower-cost areas from areas that simply contain smaller or different homes.':
|
||||
'Utilisez ensemble les filtres de prix, de type de bien et de surface. Cela distingue les secteurs vraiment moins chers de ceux qui comptent simplement des logements plus petits ou différents.',
|
||||
'Screen environmental and local-service signals':
|
||||
'Examiner environnement et services locaux',
|
||||
'Screen environmental and local-service signals': 'Examiner environnement et services locaux',
|
||||
'Road noise, parks, broadband, crime, and amenities can affect whether a property works day to day. Use them as screening criteria before booking viewings.':
|
||||
'Le bruit routier, les parcs, le haut débit, la criminalité et les services de proximité peuvent affecter la vie quotidienne dans un logement. Utilisez-les comme critères de tri avant de réserver des visites.',
|
||||
'Can I use this for commuter villages around Bristol?':
|
||||
|
|
|
|||
|
|
@ -205,7 +205,8 @@ const hi: Translations = {
|
|||
'Relax one constraint at a time': 'एक बार में एक constraint ढीला करें',
|
||||
'When the search becomes too narrow, loosen a single filter and watch which postcodes reappear. This makes compromise explicit instead of relying on guesswork.':
|
||||
'जब search बहुत संकरी हो जाए, तो एक फ़िल्टर ढीला करें और देखें कौन से पोस्टकोड वापस आते हैं. इससे guesswork के बजाय compromise साफ दिखता है.',
|
||||
'Turn vague areas into specific postcodes': 'धुंधले area ideas को specific postcodes में बदलें',
|
||||
'Turn vague areas into specific postcodes':
|
||||
'धुंधले area ideas को specific postcodes में बदलें',
|
||||
'Broad town or borough searches hide large differences between streets. Perfect Postcode helps you move from a general area to postcodes that satisfy your hard requirements.':
|
||||
'Town या borough-level searches सड़कों के बीच बड़े फर्क छिपा देती हैं. Perfect Postcode आपको general area से उन पोस्टकोड तक ले जाता है जो आपकी hard requirements पूरी करते हैं.',
|
||||
'Keep trade-offs visible': 'Trade-offs साफ रखें',
|
||||
|
|
@ -217,7 +218,8 @@ const hi: Translations = {
|
|||
'How to use the results': 'परिणामों का उपयोग कैसे करें',
|
||||
'Treat matching postcodes as a research queue: check live listings, visit streets, confirm schools and admissions, and review current official sources.':
|
||||
'Matching postcodes को research queue की तरह लें: live listings देखें, streets visit करें, schools और admissions confirm करें, और current official sources check करें.',
|
||||
'Can I save a postcode property search?': 'क्या मैं postcode property search सेव कर सकता हूँ?',
|
||||
'Can I save a postcode property search?':
|
||||
'क्या मैं postcode property search सेव कर सकता हूँ?',
|
||||
'Yes. Licensed users can save searches and return to them later. Saved searches are designed for shortlists and comparison notes.':
|
||||
'हाँ. Licensed users searches सेव कर सकते हैं और बाद में वहीं लौट सकते हैं. Saved searches shortlist और comparison notes के लिए बनाई गई हैं.',
|
||||
'Can I search without knowing the area?': 'क्या area जाने बिना search कर सकता हूँ?',
|
||||
|
|
@ -231,8 +233,7 @@ const hi: Translations = {
|
|||
'Greater Manchester के आसपास broad search को narrow करने के लिए regional guide.',
|
||||
'Start a postcode search': 'Postcode search शुरू करें',
|
||||
'Commute property search': 'Commute के हिसाब से प्रॉपर्टी खोजें',
|
||||
'Search for places to live by commute time':
|
||||
'Commute time के हिसाब से रहने की जगहें खोजें',
|
||||
'Search for places to live by commute time': 'Commute time के हिसाब से रहने की जगहें खोजें',
|
||||
'Commute property search - Find places to live by travel time':
|
||||
'Commute property search - travel time से रहने की जगहें खोजें',
|
||||
'Filter postcodes by commute time, then compare price, schools, safety, broadband, road noise, parks and property data on one map.':
|
||||
|
|
@ -260,8 +261,7 @@ const hi: Translations = {
|
|||
'Journey time को move की बाकी जरूरतों से balance करें',
|
||||
'A fast commute only helps if the area also fits your budget, housing needs, school preferences, safety threshold, broadband requirement, and tolerance for road noise.':
|
||||
'Fast commute तभी मदद करता है जब area आपके बजट, housing needs, school preferences, safety threshold, ब्रॉडबैंड जरूरत और road noise tolerance से भी match करता हो.',
|
||||
'How travel-time filters should be interpreted':
|
||||
'Travel-time filters को कैसे पढ़ें',
|
||||
'How travel-time filters should be interpreted': 'Travel-time filters को कैसे पढ़ें',
|
||||
'Travel-time modelling is useful for comparing areas consistently. Before committing, check current timetables, disruption patterns, parking, cycling conditions, and walking routes.':
|
||||
'Travel-time modelling इलाकों की consistent comparison के लिए useful है. Commit करने से पहले current timetables, disruption patterns, parking, cycling conditions और walking routes जरूर check करें.',
|
||||
'Why commute filters are combined with property data':
|
||||
|
|
@ -305,7 +305,8 @@ const hi: Translations = {
|
|||
'Verify admissions before deciding': 'फैसले से पहले admissions verify करें',
|
||||
'School data can point to promising areas, but admissions rules and catchments can change. Confirm current arrangements with schools and local authorities.':
|
||||
'School data promising areas दिखा सकता है, लेकिन admissions rules और catchments बदल सकते हैं. Schools और local authorities से current arrangements confirm करें.',
|
||||
'School quality is one part of the shortlist': 'School quality shortlist का सिर्फ एक हिस्सा है',
|
||||
'School quality is one part of the shortlist':
|
||||
'School quality shortlist का सिर्फ एक हिस्सा है',
|
||||
'Perfect Postcode helps you compare nearby school data with the other practical constraints that shape a family move: space, price, commute, parks, safety, and local services.':
|
||||
'Perfect Postcode nearby school data को उन practical constraints के साथ compare करने में मदद करता है जो family move को shape करती हैं: space, price, commute, parks, safety और local services.',
|
||||
'Check catchments before making decisions': 'फैसले से पहले catchments check करें',
|
||||
|
|
@ -317,7 +318,8 @@ const hi: Translations = {
|
|||
'Family trade-offs to compare': 'Compare करने लायक family trade-offs',
|
||||
'Combine schools with parks, road noise, crime, property size, commute, broadband, and price so the shortlist reflects the whole move.':
|
||||
'Schools को parks, road noise, crime, property size, commute, broadband और price के साथ मिलाएं ताकि shortlist पूरा move दिखाए.',
|
||||
'Does this show school catchment guarantees?': 'क्या यह school catchment guarantee दिखाता है?',
|
||||
'Does this show school catchment guarantees?':
|
||||
'क्या यह school catchment guarantee दिखाता है?',
|
||||
'No. It helps identify promising areas, but catchments and admissions must be verified with the school or local authority.':
|
||||
'नहीं. यह promising areas पहचानने में मदद करता है, लेकिन catchments और admissions school या local authority से verify करने होंगे.',
|
||||
'Can I combine school filters with parks and safety?':
|
||||
|
|
@ -396,8 +398,7 @@ const hi: Translations = {
|
|||
'Compare price with property type': 'Price को property type के साथ compare करें',
|
||||
'Median prices alone can be misleading if the local property mix changes. Add property type, tenure, floor area, and price filters so similar areas are compared fairly.':
|
||||
'अगर local property mix बदलता है, तो सिर्फ median prices misleading हो सकती हैं. Similar areas की fair comparison के लिए property type, tenure, floor area और price filters जोड़ें.',
|
||||
'Keep family and environment trade-offs visible':
|
||||
'Family और environment trade-offs साफ रखें',
|
||||
'Keep family and environment trade-offs visible': 'Family और environment trade-offs साफ रखें',
|
||||
'Layer school context, parks, road noise, broadband, and crime signals on top of the property filters. That makes it easier to decide which compromises are acceptable.':
|
||||
'Property filters के ऊपर school context, parks, road noise, broadband और crime signals layer करें. इससे तय करना आसान होता है कि कौन से compromises acceptable हैं.',
|
||||
'Can Perfect Postcode tell me the best area in Birmingham?':
|
||||
|
|
@ -460,8 +461,7 @@ const hi: Translations = {
|
|||
'Make commute constraints explicit': 'Commute constraints साफ करें',
|
||||
'If access to the centre, a station, hospital, university, or business park matters, use travel-time filters first and then compare the remaining postcodes by property data.':
|
||||
'अगर centre, station, hospital, university या business park तक access मायने रखती है, तो पहले travel-time filters लगाएं और फिर बचे postcodes को property data से compare करें.',
|
||||
'Compare value, not just headline price':
|
||||
'सिर्फ headline price नहीं, value compare करें',
|
||||
'Compare value, not just headline price': 'सिर्फ headline price नहीं, value compare करें',
|
||||
'Use price, property type, and floor-area filters together. This helps distinguish lower-cost areas from areas that simply contain smaller or different homes.':
|
||||
'Price, property type और floor-area filters साथ इस्तेमाल करें. इससे सच में lower-cost areas को उन areas से अलग करना आसान होता है जहां बस छोटे या अलग homes हैं.',
|
||||
'Screen environmental and local-service signals':
|
||||
|
|
|
|||
|
|
@ -471,8 +471,7 @@ const hu: Translations = {
|
|||
'Make commute constraints explicit': 'Tedd egyértelművé az ingázási korlátokat',
|
||||
'If access to the centre, a station, hospital, university, or business park matters, use travel-time filters first and then compare the remaining postcodes by property data.':
|
||||
'Ha fontos a központ, állomás, kórház, egyetem vagy business park elérése, először használd az utazási idő szűrőit, majd hasonlítsd össze a fennmaradó irányítószámokat ingatlanadatok alapján.',
|
||||
'Compare value, not just headline price':
|
||||
'Az értéket nézd, ne csak a kiemelt árat',
|
||||
'Compare value, not just headline price': 'Az értéket nézd, ne csak a kiemelt árat',
|
||||
'Use price, property type, and floor-area filters together. This helps distinguish lower-cost areas from areas that simply contain smaller or different homes.':
|
||||
'Használd együtt az ár-, ingatlantípus- és alapterület-szűrőket. Ez segít megkülönböztetni az olcsóbb területeket azoktól, ahol egyszerűen kisebb vagy eltérő otthonok vannak.',
|
||||
'Screen environmental and local-service signals':
|
||||
|
|
|
|||
|
|
@ -133,7 +133,8 @@ const zh: Translations = {
|
|||
'按邮编筛选历史成交价与当前估值。',
|
||||
'Compare value with commute, schools, broadband, crime, noise, and amenities.':
|
||||
'把房价与通勤、学校、宽带、治安、噪音和周边设施放在一起比较。',
|
||||
'Build a shortlist before spending weekends on viewings.': '把周末花在看房前,先整理出候选名单。',
|
||||
'Build a shortlist before spending weekends on viewings.':
|
||||
'把周末花在看房前,先整理出候选名单。',
|
||||
'Find postcodes that fit the budget before listings appear':
|
||||
'抢在房源上架之前,先锁定符合预算的邮编',
|
||||
'Start with a maximum price and property type, then colour the map by price per square metre or estimated current price. This helps reveal areas where similar homes have historically traded within reach, even when there are no live listings today.':
|
||||
|
|
@ -1074,7 +1075,8 @@ const zh: Translations = {
|
|||
dsConservationAreasUse: '英格兰指定保护区边界。用于标记邮编代表点是否位于保护区内。',
|
||||
dsListedBuildingsName: 'Historic England 受保护建筑',
|
||||
dsListedBuildingsOrigin: 'Historic England 英格兰国家遗产名录',
|
||||
dsListedBuildingsUse: '英格兰受保护建筑点位记录。用于标记地址似乎与附近受保护建筑条目匹配的房产。',
|
||||
dsListedBuildingsUse:
|
||||
'英格兰受保护建筑点位记录。用于标记地址似乎与附近受保护建筑条目匹配的房产。',
|
||||
dsNaptanName: 'NaPTAN(公共交通站点)',
|
||||
dsNaptanOrigin: 'Department for Transport',
|
||||
dsNaptanUse: '英格兰各地铁路、公交、地铁/有轨电车、渡轮和机场的站点位置。',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue