import { $, api, esc, sortByName, seatsLabel, showError, renderHeader } from './common.js';
renderHeader('gruppe');
let members = [];
let points = [];
const form = $('#member-form');
$('#member-hascar').addEventListener('change', (e) => {
$('#member-seats-wrap').hidden = !e.target.checked;
});
// Auswahl "fährt am liebsten mit bei" – alle anderen Mitglieder
function fillRidesWith(selfId, selected) {
$('#member-rideswith').innerHTML = ''
+ sortByName(members.filter((m) => m.id !== selfId))
.map((m) => ``).join('');
}
// Auswahl Standard-Treffpunkt
function fillMemberPoint(selected) {
$('#member-point').innerHTML = ''
+ points.map((p) => ``).join('');
}
function resetForm() {
form.reset();
fillRidesWith();
fillMemberPoint();
$('#member-id').value = '';
$('#member-seats-wrap').hidden = true;
$('#member-cancel').hidden = true;
$('#member-form-title').textContent = 'Mitglied hinzufügen';
}
$('#member-cancel').addEventListener('click', resetForm);
form.addEventListener('submit', async (e) => {
e.preventDefault();
const body = {
name: $('#member-name').value.trim(),
external: $('#member-external').checked,
hasCar: $('#member-hascar').checked,
seats: $('#member-seats').value,
alwaysDrives: $('#member-always').checked,
ridesWith: $('#member-rideswith').value || null,
meetingPoint: $('#member-point').value || null,
};
const id = $('#member-id').value;
try {
if (id) await api('PUT', `/members/${id}`, body);
else await api('POST', '/members', body);
resetForm();
await load();
} catch (err) {
showError(err);
}
});
function edit(id) {
const m = members.find((x) => x.id === id);
$('#member-id').value = m.id;
$('#member-name').value = m.name;
$('#member-external').checked = !!m.external;
fillMemberPoint(m.meetingPoint);
$('#member-hascar').checked = m.hasCar;
$('#member-seats').value = m.seats || 4;
$('#member-always').checked = !!m.alwaysDrives;
fillRidesWith(m.id, m.ridesWith);
$('#member-seats-wrap').hidden = !m.hasCar;
$('#member-cancel').hidden = false;
$('#member-form-title').textContent = 'Mitglied bearbeiten';
$('#member-name').focus();
window.scrollTo({ top: 0, behavior: 'smooth' });
}
async function remove(id) {
const m = members.find((x) => x.id === id);
if (!confirm(`${m.name} wirklich aus der Gruppe löschen?`)) return;
try {
await api('DELETE', `/members/${id}`);
await load();
} catch (err) {
showError(err);
}
}
function render() {
if (!$('#member-id').value) fillRidesWith();
const nameOf = (id) => members.find((m) => m.id === id)?.name;
const pointOf = (id) => points.find((p) => p.id === id)?.name;
$('#members-empty').hidden = members.length > 0;
$('#members-list').innerHTML = sortByName(members).map((m) => `
${esc(m.name)}${m.external ? ' Extern' : ''}
${m.hasCar && pointOf(m.meetingPoint) ? `ab ${esc(pointOf(m.meetingPoint))}` : ''}
${nameOf(m.ridesWith) ? `fährt gern bei ${esc(nameOf(m.ridesWith))} mit` : ''}
${m.hasCar ? `Auto · ${seatsLabel(m.seats)}${m.alwaysDrives ? ' · fährt immer' : ''}` : 'kein Auto'}
`).join('');
}
$('#members-list').addEventListener('click', (e) => {
if (e.target.dataset.edit) edit(e.target.dataset.edit);
if (e.target.dataset.del) remove(e.target.dataset.del);
});
$('#export-btn').addEventListener('click', () => {
const blob = new Blob([JSON.stringify(members, null, 2)], { type: 'application/json' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'hcrb-gruppe.json';
a.click();
URL.revokeObjectURL(a.href);
});
$('#import-file').addEventListener('change', async (e) => {
const file = e.target.files[0];
e.target.value = '';
if (!file) return;
let data;
try {
data = JSON.parse(await file.text());
if (!Array.isArray(data)) throw new Error();
} catch {
alert('Die Datei konnte nicht gelesen werden.');
return;
}
if (!confirm(`${data.length} Mitglieder importieren? Die aktuelle Gruppe wird ersetzt.`)) return;
try {
await api('POST', '/members/import', data);
await load();
} catch (err) {
showError(err);
}
});
// ---------- Treffpunkte ----------
const pointForm = $('#point-form');
function resetPointForm() {
pointForm.reset();
$('#point-id').value = '';
$('#point-cancel').hidden = true;
$('#point-form-title').textContent = 'Treffpunkt hinzufügen';
}
$('#point-cancel').addEventListener('click', resetPointForm);
pointForm.addEventListener('submit', async (e) => {
e.preventDefault();
const body = { name: $('#point-name').value.trim(), address: $('#point-address').value.trim() };
const id = $('#point-id').value;
try {
if (id) await api('PUT', `/meeting-points/${id}`, body);
else await api('POST', '/meeting-points', body);
resetPointForm();
await loadPoints();
} catch (err) {
showError(err);
}
});
function renderPoints() {
$('#points-empty').hidden = points.length > 0;
$('#points-list').innerHTML = points.map((p) => `
${esc(p.name)}
${esc(p.address)}
`).join('');
}
$('#points-list').addEventListener('click', async (e) => {
const { edit: editId, del } = e.target.dataset;
if (editId) {
const p = points.find((x) => x.id === editId);
$('#point-id').value = p.id;
$('#point-name').value = p.name;
$('#point-address').value = p.address;
$('#point-cancel').hidden = false;
$('#point-form-title').textContent = 'Treffpunkt bearbeiten';
$('#point-name').focus();
}
if (del) {
const p = points.find((x) => x.id === del);
if (!confirm(`Treffpunkt „${p.name}“ wirklich löschen?`)) return;
try {
await api('DELETE', `/meeting-points/${del}`);
await loadPoints();
} catch (err) {
showError(err);
}
}
});
async function loadPoints() {
points = await api('GET', '/meeting-points');
renderPoints();
const editing = members.find((m) => m.id === $('#member-id').value);
fillMemberPoint(editing ? $('#member-point').value : undefined);
render();
}
async function load() {
members = await api('GET', '/members');
render();
}
load().then(loadPoints).catch(showError);