deploy
This commit is contained in:
parent
273d7a83ee
commit
084117cea8
48 changed files with 2283 additions and 890 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useMemo, useState, useCallback } from 'react';
|
||||
import { useMemo, useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Property } from '../../types';
|
||||
import { formatDuration, formatAge, formatNumber, formatTransactionDate } from '../../lib/format';
|
||||
|
|
@ -7,7 +7,6 @@ import InfoPopup from '../ui/InfoPopup';
|
|||
import { SearchInput } from '../ui/SearchInput';
|
||||
import { EmptyState } from '../ui/EmptyState';
|
||||
import { InfoIcon } from '../ui/icons';
|
||||
import { BookmarkIcon } from '../ui/icons/BookmarkIcon';
|
||||
import { ts } from '../../i18n/server';
|
||||
|
||||
interface PropertiesPaneProps {
|
||||
|
|
@ -17,10 +16,6 @@ interface PropertiesPaneProps {
|
|||
hexagonId: string | null;
|
||||
onLoadMore: () => void;
|
||||
onNavigateToSource?: (slug: string) => void;
|
||||
onSaveProperty?: (property: Property) => void;
|
||||
onUnsaveProperty?: (id: string) => void;
|
||||
isPropertySaved?: (address?: string, postcode?: string) => boolean;
|
||||
getSavedPropertyId?: (address?: string, postcode?: string) => string | undefined;
|
||||
}
|
||||
|
||||
export function PropertiesPane({
|
||||
|
|
@ -30,15 +25,15 @@ export function PropertiesPane({
|
|||
hexagonId,
|
||||
onLoadMore,
|
||||
onNavigateToSource,
|
||||
onSaveProperty,
|
||||
onUnsaveProperty,
|
||||
isPropertySaved,
|
||||
getSavedPropertyId,
|
||||
}: PropertiesPaneProps) {
|
||||
const { t } = useTranslation();
|
||||
const [search, setSearch] = useState('');
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setSearch('');
|
||||
}, [hexagonId]);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
const query = search.trim().toLowerCase();
|
||||
return query
|
||||
|
|
@ -100,14 +95,7 @@ export function PropertiesPane({
|
|||
) : (
|
||||
<>
|
||||
{filtered.map((property, idx) => (
|
||||
<PropertyCard
|
||||
key={idx}
|
||||
property={property}
|
||||
onSave={onSaveProperty}
|
||||
onUnsave={onUnsaveProperty}
|
||||
isSaved={isPropertySaved?.(property.address, property.postcode)}
|
||||
savedId={getSavedPropertyId?.(property.address, property.postcode)}
|
||||
/>
|
||||
<PropertyCard key={idx} property={property} />
|
||||
))}
|
||||
{properties.length < total && (
|
||||
<button
|
||||
|
|
@ -151,27 +139,8 @@ function PropertyLoadingSkeleton() {
|
|||
);
|
||||
}
|
||||
|
||||
function PropertyCard({
|
||||
property,
|
||||
onSave,
|
||||
onUnsave,
|
||||
isSaved,
|
||||
savedId,
|
||||
}: {
|
||||
property: Property;
|
||||
onSave?: (property: Property) => void;
|
||||
onUnsave?: (id: string) => void;
|
||||
isSaved?: boolean;
|
||||
savedId?: string;
|
||||
}) {
|
||||
function PropertyCard({ property }: { property: Property }) {
|
||||
const { t } = useTranslation();
|
||||
const handleToggleSave = useCallback(() => {
|
||||
if (isSaved && savedId && onUnsave) {
|
||||
onUnsave(savedId);
|
||||
} else if (onSave) {
|
||||
onSave(property);
|
||||
}
|
||||
}, [isSaved, savedId, onSave, onUnsave, property]);
|
||||
const price = getNum(property, 'Last known price');
|
||||
const estimatedPrice = getNum(property, 'Estimated current price');
|
||||
const pricePerSqm = getNum(property, 'Price per sqm');
|
||||
|
|
@ -197,19 +166,6 @@ function PropertyCard({
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
{onSave && (
|
||||
<button
|
||||
onClick={handleToggleSave}
|
||||
className={`shrink-0 p-1 rounded ${
|
||||
isSaved
|
||||
? 'text-teal-600 dark:text-teal-400'
|
||||
: 'text-warm-300 dark:text-warm-600 hover:text-warm-500 dark:hover:text-warm-400'
|
||||
}`}
|
||||
title={isSaved ? t('propertyCard.unsaveProperty') : t('propertyCard.saveProperty')}
|
||||
>
|
||||
<BookmarkIcon className="w-4 h-4" filled={isSaved} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{property.property_sub_type && (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue