41 lines
6.6 KiB
JavaScript
41 lines
6.6 KiB
JavaScript
export const passengerDefaults = { infoPlacesEnabled: true, infoFareEnabled: true, lastTripNoticeEnabled: true, weatherHintEnabled: true, places: [], fareRules: [], fareByType: [] };
|
||
export const cityFareDefaults = cityId => cityId === 1 ? [
|
||
{ cityId: 1, type: 'bus', price: '1,05 BYN', payment: 'QR-кодом или наличными', checkedAt: '2026-10-11' },
|
||
{ cityId: 1, type: 'minibus', price: '2,10 BYN', payment: 'QR-кодом или наличными', checkedAt: '2026-10-11' },
|
||
] : [];
|
||
const today = () => new Intl.DateTimeFormat('sv-SE', { timeZone: 'Europe/Minsk' }).format(Date.now());
|
||
export function BoardPassengerSettings({ settings, stops, routes, cityId, set }) {
|
||
const editPlace = (index, patch) => set('places', settings.places.map((value, i) => i === index ? { ...value, ...patch } : value));
|
||
const editRule = (index, patch) => set('fareRules', settings.fareRules.map((value, i) => i === index ? { ...value, ...patch } : value));
|
||
return <div className="device-passenger-settings">
|
||
<h3>Важные места</h3><p className="device-night-hint">До трёх остановок назначения. Укажите короткое название для пассажиров; табло найдёт ближайший прямой рейс с учётом его конечной и направления.</p>
|
||
{settings.places.map((place, index) => <fieldset className="device-passenger-editor" key={index}><legend>Место {index + 1}</legend>
|
||
<label>Остановка назначения<select aria-label={`Остановка места ${index + 1}`} required value={place.stopId || ''} onChange={e => { const stop = stops.find(s => s.id === Number(e.target.value)); editPlace(index, { stopId: Number(e.target.value), name: stop?.name.slice(0, 48) || '' }); }}>
|
||
<option value="">Выберите остановку</option>{stops.filter(s => s.id !== settings.stopId).map(stop => <option key={stop.id} value={stop.id} disabled={settings.places.some((p, i) => i !== index && p.stopId === stop.id)}>{stop.name}{stop.description ? ` · ${stop.description}` : ''}</option>)}
|
||
</select></label><label>Название на табло<input aria-label={`Название места ${index + 1}`} required maxLength={48} value={place.name} onChange={e => editPlace(index, { name: e.target.value })} /></label>
|
||
<button type="button" onClick={() => set('places', settings.places.filter((_, i) => i !== index))}>Удалить место {index + 1}</button>
|
||
</fieldset>)}
|
||
<button type="button" disabled={settings.places.length >= 3 || !stops.length} onClick={() => set('places', [...settings.places, { stopId: 0, name: '' }])}>Добавить место</button>
|
||
<h3>Оплата поездки</h3><p className="device-night-hint">Основные тарифы по типу транспорта. Только подтверждённые цена с валютой, способы оплаты и дата проверки. Без подходящего тарифа карточка скрыта.</p>
|
||
{['bus', 'minibus'].map(type => {
|
||
const rule = settings.fareByType.find(r => r.type === type && r.cityId === cityId), label = type === 'bus' ? 'автобуса' : 'маршрутки';
|
||
const edit = patch => set('fareByType', settings.fareByType.map(r => r.type === type && r.cityId === cityId ? { ...r, ...patch } : r));
|
||
return <fieldset className="device-passenger-editor" key={type}><legend>Тариф {label}</legend>
|
||
<label className="device-check"><input type="checkbox" checked={!!rule} onChange={e => set('fareByType', [...settings.fareByType.filter(r => r.type !== type), ...(e.target.checked ? [{ cityId, type, price: '', payment: '', checkedAt: today() }] : [])])} />Использовать тариф {label}</label>
|
||
{rule && <><div className="device-form-grid"><label>Стоимость с валютой<input aria-label={`Стоимость ${label}`} required maxLength={40} value={rule.price} onChange={e => edit({ price: e.target.value })} /></label><label>Проверено<input aria-label={`Дата проверки ${label}`} required type="date" max={today()} value={rule.checkedAt} onChange={e => edit({ checkedAt: e.target.value })} /></label></div>
|
||
<label>Способы оплаты<input aria-label={`Способы оплаты ${label}`} required maxLength={100} value={rule.payment} onChange={e => edit({ payment: e.target.value })} /></label></>}
|
||
</fieldset>;
|
||
})}
|
||
<h3>Исключения для маршрутов</h3><p className="device-night-hint">Индивидуальный тариф заменяет основной тариф типа транспорта.</p>
|
||
{settings.fareRules.map((rule, index) => <fieldset className="device-passenger-editor" key={index}><legend>Тариф {index + 1}</legend>
|
||
<label>Маршрут<select aria-label={`Маршрут тарифа ${index + 1}`} required value={rule.routeId || ''} onChange={e => editRule(index, { routeId: Number(e.target.value) })}>
|
||
<option value="">Выберите маршрут</option>{!routes.some(r => r.id === rule.routeId) && rule.routeId > 0 && <option value={rule.routeId}>Маршрут {rule.routeId} · сохранённый тариф</option>}
|
||
{routes.map(route => <option key={route.id} value={route.id} disabled={settings.fareRules.some((r, i) => i !== index && r.routeId === route.id)}>№{route.route_number} · {route.name}</option>)}
|
||
</select></label><div className="device-form-grid"><label>Стоимость с валютой<input aria-label={`Стоимость тарифа ${index + 1}`} required maxLength={40} value={rule.price} onChange={e => editRule(index, { price: e.target.value })} /></label><label>Проверено<input aria-label={`Дата проверки тарифа ${index + 1}`} required type="date" max={today()} value={rule.checkedAt} onChange={e => editRule(index, { checkedAt: e.target.value })} /></label></div>
|
||
<label>Способы оплаты<input aria-label={`Способы оплаты тарифа ${index + 1}`} required maxLength={100} value={rule.payment} onChange={e => editRule(index, { payment: e.target.value })} /></label>
|
||
<button type="button" onClick={() => set('fareRules', settings.fareRules.filter((_, i) => i !== index))}>Удалить тариф {index + 1}</button>
|
||
</fieldset>)}
|
||
<button type="button" disabled={settings.fareRules.length >= 32 || !routes.length} onClick={() => set('fareRules', [...settings.fareRules, { routeId: 0, price: '', payment: '', checkedAt: today() }])}>Добавить тариф</button>
|
||
</div>;
|
||
}
|