// Property card — consumes API Property Object
function PropertyCard({ property, onRoomClick }) {
const {
name, skcs, areaName, rent, commonfee,
accessText, access, image, activeRoomCount, rooms = [],
} = property;
const [expanded, setExpanded] = React.useState(false);
const [imgFailed, setImgFailed] = React.useState(false);
const activeRooms = rooms.filter(r => r.status !== 'expired');
const visibleRooms = expanded ? activeRooms : activeRooms.slice(0, 2);
const thumbUrl = resolveImg(image);
const seedIdx = React.useMemo(
() => (name || '').split('').reduce((a, c) => a + c.charCodeAt(0), 0),
[name]
);
return (
{/* Header: image + name */}
{thumbUrl && !imgFailed ? (

setImgFailed(true)}
/>
) : (
)}
{skcs || areaName}
{name}
{accessText && (
{accessText.split('\n')[0]}
)}
{/* Rent summary */}
租金(含管理费)
{rent || '—'}
{commonfee &&
管理费 {commonfee}
}
空房 {activeRoomCount ?? activeRooms.length} 套
{/* Rooms list — each row is a tappable entry */}
{visibleRooms.map((r, i) => (
))}
{activeRooms.length > 2 && (
)}
);
}
const cardStyles = {
card: {
background: '#FFFFFF', borderRadius: 16, padding: '14px 14px 8px',
marginBottom: 12, border: '1px solid #EDE6D9',
boxShadow: '0 1px 2px rgba(60, 50, 30, 0.03)',
},
header: { display: 'flex', gap: 12, marginBottom: 12 },
thumb: {
width: 88, height: 88, borderRadius: 10, overflow: 'hidden', flexShrink: 0,
border: '1px solid #EDE6D9', background: '#F4EFE4',
},
titleCol: { flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 4 },
wardRow: {
display: 'flex', alignItems: 'center', gap: 4,
fontSize: 11, color: '#8A7F72', fontWeight: 500, letterSpacing: '0.02em',
},
name: {
fontSize: 15, fontWeight: 600, color: '#1A1A1A', lineHeight: 1.35,
letterSpacing: '0.005em', overflow: 'hidden',
display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
},
access: {
display: 'flex', alignItems: 'flex-start', gap: 4, marginTop: 2,
fontSize: 10, color: '#A89B82',
},
accessText: {
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
display: 'inline-block', maxWidth: '100%',
},
rentBlock: {
background: '#FAF6EE', borderRadius: 10, padding: '10px 12px',
marginBottom: 10, display: 'flex', alignItems: 'center',
justifyContent: 'space-between', gap: 12,
},
rentCol: { flex: 1, minWidth: 0 },
rentLabel: { fontSize: 10, color: '#8A7F72', fontWeight: 500, letterSpacing: '0.04em' },
rentMain: {
fontSize: 16, fontWeight: 700, color: '#C6572B',
fontFamily: '"Inter", "Noto Sans JP", sans-serif', letterSpacing: '-0.01em',
marginTop: 2,
},
rentSub: { fontSize: 10, color: '#8A7F72', fontWeight: 500, marginTop: 1 },
unitCount: {
display: 'flex', alignItems: 'center', gap: 4, fontSize: 12, color: '#6B6258',
background: '#FFFFFF', padding: '5px 10px', borderRadius: 999,
border: '1px solid #EDE6D9', flexShrink: 0,
},
unitDot: {
width: 6, height: 6, borderRadius: 3, background: '#4D8B5E',
boxShadow: '0 0 0 3px rgba(77,139,94,0.15)',
},
rooms: { borderTop: '1px dashed #EDE6D9', paddingTop: 2 },
roomRow: {
width: '100%', display: 'flex', alignItems: 'center',
gap: 10, padding: '12px 4px', borderBottom: '1px dashed #F4EFE4',
background: 'transparent', fontFamily: 'inherit', cursor: 'pointer',
textAlign: 'left', textDecoration: 'none', color: 'inherit',
transition: 'background 150ms ease', boxSizing: 'border-box',
},
roomLeft: { display: 'flex', flexDirection: 'column', gap: 3, flex: 1, minWidth: 0 },
roomUnit: { fontSize: 13, color: '#1A1A1A', fontWeight: 500 },
roomMeta: {
display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, color: '#8A7F72',
flexWrap: 'wrap',
},
metaDot: { width: 3, height: 3, borderRadius: 1.5, background: '#C4BBAA' },
roomRight: { textAlign: 'right', flexShrink: 0 },
roomPrice: {
fontSize: 13, fontWeight: 600, color: '#1A1A1A',
fontFamily: '"Inter", "Noto Sans JP", sans-serif',
},
roomSub: { fontSize: 10, color: '#8A7F72', marginTop: 1 },
roomChev: {
width: 16, display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
},
moreBtn: {
width: '100%', padding: '10px', background: 'transparent', border: 'none',
fontSize: 12, color: '#6B6258', fontWeight: 500, cursor: 'pointer',
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4,
fontFamily: 'inherit',
},
};
Object.assign(window, { PropertyCard });