Make EV charging an amenity toggle and drop filter select

This commit is contained in:
Tero Halla-aho 2025-12-06 23:51:23 +02:00
parent c08dca02e7
commit 3d13bf3ba3
2 changed files with 16 additions and 45 deletions

View file

@ -137,6 +137,7 @@ export default function NewListingPage() {
{ key: 'microwave', label: t('amenityMicrowave'), icon: '🍲', checked: hasMicrowave, toggle: setHasMicrowave },
{ key: 'parking', label: t('amenityFreeParking'), icon: '🅿️', checked: hasFreeParking, toggle: setHasFreeParking },
{ key: 'ski', label: t('amenitySkiPass'), icon: '⛷️', checked: hasSkiPass, toggle: setHasSkiPass },
{ key: 'ev', label: t('amenityEvAvailable'), icon: '⚡', checked: evChargingAvailable, toggle: setEvChargingAvailable },
];
function updateTranslation(locale: Locale, field: keyof LocaleFields, value: string) {
@ -704,28 +705,6 @@ export default function NewListingPage() {
</span>
</button>
))}
<div className="amenity-ev">
<div className="amenity-ev-label">{t('evChargingLabel')}</div>
<div style={{ color: '#cbd5e1', fontSize: 12, marginBottom: 6 }}>{t('evChargingExplain')}</div>
<div className="ev-toggle-group">
{[
{ value: true, label: t('evChargingYes'), icon: '⚡' },
{ value: false, label: t('evChargingNo'), icon: '🚗' },
].map((opt) => (
<button
key={String(opt.value)}
type="button"
className={`ev-toggle ${evChargingAvailable === opt.value ? 'active' : ''}`}
onClick={() => setEvChargingAvailable(opt.value)}
>
<span aria-hidden className="amenity-emoji">
{opt.icon}
</span>
{opt.label}
</button>
))}
</div>
</div>
</div>
<div style={{ display: 'grid', gap: 8, gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))' }}>
<label>

View file

@ -183,7 +183,6 @@ export default function ListingsIndexPage() {
const [query, setQuery] = useState('');
const [city, setCity] = useState('');
const [region, setRegion] = useState('');
const [evCharging, setEvCharging] = useState<'ALL' | 'YES' | 'NO'>('ALL');
const [listings, setListings] = useState<ListingResult[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
@ -207,10 +206,7 @@ export default function ListingsIndexPage() {
});
}, [listings, addressCenter, radiusKm]);
const filtered = useMemo(() => {
if (evCharging === 'ALL') return filteredByAddress;
return filteredByAddress.filter((l) => (evCharging === 'YES' ? l.evChargingAvailable : !l.evChargingAvailable));
}, [filteredByAddress, evCharging]);
const filtered = filteredByAddress;
const amenityOptions = [
{ key: 'sauna', label: t('amenitySauna'), icon: amenityIcons.sauna },
@ -226,6 +222,7 @@ export default function ListingsIndexPage() {
{ key: 'microwave', label: t('amenityMicrowave'), icon: amenityIcons.microwave },
{ key: 'parking', label: t('amenityFreeParking'), icon: amenityIcons.parking },
{ key: 'skipass', label: t('amenitySkiPass'), icon: amenityIcons.ski },
{ key: 'ev', label: t('amenityEvAvailable'), icon: amenityIcons.ev },
];
async function fetchListings() {
@ -236,10 +233,13 @@ export default function ListingsIndexPage() {
if (query) params.set('q', query);
if (city) params.set('city', city);
if (region) params.set('region', region);
if (evCharging !== 'ALL') params.set('evCharging', evCharging === 'YES' ? 'true' : 'false');
if (startDate) params.set('availableStart', startDate);
if (endDate) params.set('availableEnd', endDate);
amenities.forEach((a) => params.append('amenity', a));
const evSelected = amenities.includes('ev');
if (evSelected) params.set('evCharging', 'true');
amenities
.filter((a) => a !== 'ev')
.forEach((a) => params.append('amenity', a));
const res = await fetch(`/api/listings?${params.toString()}`, { cache: 'no-store' });
const data = await res.json();
if (!res.ok || data.error) {
@ -321,14 +321,6 @@ export default function ListingsIndexPage() {
{t('regionFilter')}
<input value={region} onChange={(e) => setRegion(e.target.value)} placeholder={t('regionFilter')} />
</label>
<label>
{t('evChargingLabel')}
<select value={evCharging} onChange={(e) => setEvCharging(e.target.value as any)}>
<option value="ALL">{t('evChargingAny')}</option>
<option value="YES">{t('evChargingYes')}</option>
<option value="NO">{t('evChargingNo')}</option>
</select>
</label>
</div>
<div style={{ display: 'grid', gap: 10, gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', marginTop: 12 }}>
<label>