c75d3c8121
Gold/Silver/Bronze FIFA-style score badges overlaid on location imagery. List/grid view toggle on Results and Properties pages (persisted in localStorage). IntelligenceMatchCard for match results grid view; PropertyIntelligenceCard for property grid view with warm brown theme. LocationPreview component with Google Maps link. 10 mock properties enriched with Unsplash building images. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { useState } from 'react'
|
|
import { Box, IconButton, Tooltip, Typography } from '@mui/material'
|
|
import { MapPin, Map } from 'lucide-react'
|
|
|
|
interface Props {
|
|
imageUrl?: string
|
|
lat?: number
|
|
lng?: number
|
|
address?: string
|
|
cityLabel?: string
|
|
height?: number
|
|
}
|
|
|
|
// TODO: replace placeholder with Google Maps Static API:
|
|
// https://maps.googleapis.com/maps/api/staticmap?center={lat},{lng}&zoom=15&size=800x400&key=YOUR_KEY
|
|
|
|
function buildMapsUrl(lat?: number, lng?: number, address?: string): string {
|
|
if (lat != null && lng != null) {
|
|
return `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`
|
|
}
|
|
if (address) {
|
|
return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`
|
|
}
|
|
return 'https://www.google.com/maps'
|
|
}
|
|
|
|
export function LocationPreview({ imageUrl, lat, lng, address, cityLabel, height = 180 }: Props) {
|
|
const [imgError, setImgError] = useState(false)
|
|
const mapsUrl = buildMapsUrl(lat, lng, address)
|
|
const showImage = !!imageUrl && !imgError
|
|
|
|
return (
|
|
<Box sx={{ position: 'relative', width: '100%', height, overflow: 'hidden', flexShrink: 0 }}>
|
|
{showImage ? (
|
|
<img
|
|
src={imageUrl}
|
|
alt={cityLabel ?? 'Standort'}
|
|
onError={() => setImgError(true)}
|
|
style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
|
|
/>
|
|
) : (
|
|
<Box
|
|
sx={{
|
|
width: '100%',
|
|
height: '100%',
|
|
background: 'linear-gradient(160deg,#dce8f2 0%,#b8cfe0 100%)',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: 0.5,
|
|
}}
|
|
>
|
|
<MapPin size={28} color="#7ba3bf" />
|
|
{cityLabel && (
|
|
<Typography variant="body2" sx={{ color: '#5a87a3', fontWeight: 600, letterSpacing: 0.5 }}>
|
|
{cityLabel}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
)}
|
|
|
|
{/* Google Maps button */}
|
|
<Tooltip title="In Google Maps öffnen" placement="top">
|
|
<IconButton
|
|
component="a"
|
|
href={mapsUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
size="small"
|
|
sx={{
|
|
position: 'absolute',
|
|
bottom: 8,
|
|
right: 8,
|
|
bgcolor: 'rgba(255,255,255,0.88)',
|
|
backdropFilter: 'blur(4px)',
|
|
width: 28,
|
|
height: 28,
|
|
'&:hover': { bgcolor: 'white' },
|
|
}}
|
|
>
|
|
<Map size={14} color="#1e3a5f" />
|
|
</IconButton>
|
|
</Tooltip>
|
|
</Box>
|
|
)
|
|
}
|