Spice up website

This commit is contained in:
Andras Schmelczer 2026-01-31 22:04:28 +00:00
parent f7d586a1e9
commit 7627818e98
9 changed files with 831 additions and 164 deletions

View file

@ -6,6 +6,7 @@ interface PropertiesPaneProps {
total: number;
loading: boolean;
hexagonId: string | null;
postcodeId?: string | null;
onLoadMore: () => void;
onClose: () => void;
}
@ -17,6 +18,7 @@ export function PropertiesPane({
total,
loading,
hexagonId,
postcodeId,
onLoadMore,
onClose,
}: PropertiesPaneProps) {
@ -36,10 +38,11 @@ export function PropertiesPane({
});
}, [properties, sortBy]);
if (!hexagonId) {
const selectionId = hexagonId || postcodeId;
if (!selectionId) {
return (
<div className="flex items-center justify-center h-full text-gray-500">
Click a hexagon to view properties
<div className="flex items-center justify-center h-full text-warm-500">
Click a hexagon or postcode to view properties
</div>
);
}
@ -47,27 +50,29 @@ export function PropertiesPane({
return (
<div className="flex flex-col h-full">
{/* Header */}
<div className="p-4 border-b border-gray-200">
<div className="p-4 border-b border-warm-200">
<div className="flex justify-between items-center">
<h2 className="text-lg font-semibold">Properties in Hexagon</h2>
<h2 className="text-lg font-semibold">
{postcodeId ? `Properties in ${postcodeId}` : 'Properties in Hexagon'}
</h2>
<button
onClick={onClose}
className="text-gray-500 hover:text-gray-700 text-2xl leading-none"
className="text-warm-500 hover:text-warm-700 text-2xl leading-none"
>
×
</button>
</div>
<p className="text-sm text-gray-600">
<p className="text-sm text-warm-600">
Showing {properties.length} of {total} properties
</p>
</div>
{/* Sort controls */}
<div className="p-2 border-b border-gray-200">
<div className="p-2 border-b border-warm-200">
<select
value={sortBy}
onChange={(e) => setSortBy(e.target.value as SortBy)}
className="w-full p-2 border border-gray-300 rounded text-sm"
className="w-full p-2 border border-warm-300 rounded text-sm"
>
<option value="price">Price (High to Low)</option>
<option value="size">Size (Large to Small)</option>
@ -88,7 +93,7 @@ export function PropertiesPane({
<button
onClick={onLoadMore}
disabled={loading}
className="w-full p-4 text-blue-600 hover:bg-blue-50 disabled:opacity-50"
className="w-full p-4 text-teal-600 hover:bg-teal-50 disabled:opacity-50"
>
{loading ? 'Loading...' : `Load More (${total - properties.length} remaining)`}
</button>
@ -135,17 +140,17 @@ function PropertyCard({ property }: { property: Property }) {
const age = getNum(property, 'Approximate construction age', 'construction_age_band');
return (
<div className="p-4 border-b border-gray-100 hover:bg-gray-50">
<div className="p-4 border-b border-warm-100 hover:bg-warm-50">
{/* Address & postcode */}
<div className="font-semibold">{property.address || 'Unknown Address'}</div>
<div className="text-sm text-gray-600">{property.postcode}</div>
<div className="text-sm text-warm-600">{property.postcode}</div>
{/* Price */}
{price !== undefined && (
<div className="mt-2 text-lg font-bold text-green-700">
<div className="mt-2 text-lg font-bold text-teal-700">
£{fmt(price)}
{pricePerSqm !== undefined && (
<span className="text-sm font-normal text-gray-600">
<span className="text-sm font-normal text-warm-600">
{' '}
(£{fmt(pricePerSqm)}/m²)
</span>
@ -157,42 +162,42 @@ function PropertyCard({ property }: { property: Property }) {
<div className="mt-2 grid grid-cols-2 gap-x-4 gap-y-1 text-sm">
{property.property_type && (
<div>
<span className="text-gray-500">Type:</span> {property.property_type}
<span className="text-warm-500">Type:</span> {property.property_type}
</div>
)}
{property.built_form && (
<div>
<span className="text-gray-500">Built form:</span> {property.built_form}
<span className="text-warm-500">Built form:</span> {property.built_form}
</div>
)}
{property.duration && (
<div>
<span className="text-gray-500">Tenure:</span> {formatDuration(property.duration)}
<span className="text-warm-500">Tenure:</span> {formatDuration(property.duration)}
</div>
)}
{floorArea !== undefined && (
<div>
<span className="text-gray-500">Floor area:</span> {fmt(floorArea)}m²
<span className="text-warm-500">Floor area:</span> {fmt(floorArea)}m²
</div>
)}
{rooms !== undefined && (
<div>
<span className="text-gray-500">Rooms:</span> {fmt(rooms)}
<span className="text-warm-500">Rooms:</span> {fmt(rooms)}
</div>
)}
{age !== undefined && (
<div>
<span className="text-gray-500">Built:</span> {formatAge(age)}
<span className="text-warm-500">Built:</span> {formatAge(age)}
</div>
)}
{property.current_energy_rating && (
<div>
<span className="text-gray-500">EPC rating:</span> {property.current_energy_rating}
<span className="text-warm-500">EPC rating:</span> {property.current_energy_rating}
</div>
)}
{property.potential_energy_rating && (
<div>
<span className="text-gray-500">EPC potential:</span>{' '}
<span className="text-warm-500">EPC potential:</span>{' '}
{property.potential_energy_rating}
</div>
)}