new features
This commit is contained in:
@@ -19,6 +19,7 @@ export interface FahrzeugBuchung {
|
|||||||
beginn: Date;
|
beginn: Date;
|
||||||
ende: Date;
|
ende: Date;
|
||||||
buchungs_art: BuchungsArt;
|
buchungs_art: BuchungsArt;
|
||||||
|
ganztaegig: boolean;
|
||||||
gebucht_von: string;
|
gebucht_von: string;
|
||||||
kontakt_person?: string | null;
|
kontakt_person?: string | null;
|
||||||
kontakt_telefon?: string | null;
|
kontakt_telefon?: string | null;
|
||||||
@@ -42,6 +43,7 @@ export interface FahrzeugBuchungListItem {
|
|||||||
buchungs_art: BuchungsArt;
|
buchungs_art: BuchungsArt;
|
||||||
beginn: Date;
|
beginn: Date;
|
||||||
ende: Date;
|
ende: Date;
|
||||||
|
ganztaegig: boolean;
|
||||||
abgesagt: boolean;
|
abgesagt: boolean;
|
||||||
gebucht_von: string;
|
gebucht_von: string;
|
||||||
gebucht_von_name?: string | null;
|
gebucht_von_name?: string | null;
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ async function getOrderById(id: number) {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...orderResult.rows[0],
|
bestellung: orderResult.rows[0],
|
||||||
positionen: positionen.rows,
|
positionen: positionen.rows,
|
||||||
dateien: dateien.rows,
|
dateien: dateien.rows,
|
||||||
erinnerungen: erinnerungen.rows,
|
erinnerungen: erinnerungen.rows,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ function rowToListItem(row: any): FahrzeugBuchungListItem {
|
|||||||
buchungs_art: row.buchungs_art,
|
buchungs_art: row.buchungs_art,
|
||||||
beginn: new Date(row.beginn),
|
beginn: new Date(row.beginn),
|
||||||
ende: new Date(row.ende),
|
ende: new Date(row.ende),
|
||||||
|
ganztaegig: row.ganztaegig ?? false,
|
||||||
abgesagt: row.abgesagt,
|
abgesagt: row.abgesagt,
|
||||||
gebucht_von: row.gebucht_von,
|
gebucht_von: row.gebucht_von,
|
||||||
gebucht_von_name: row.gebucht_von_name ?? null,
|
gebucht_von_name: row.gebucht_von_name ?? null,
|
||||||
@@ -41,6 +42,7 @@ function rowToBuchung(row: any): FahrzeugBuchung {
|
|||||||
beginn: new Date(row.beginn),
|
beginn: new Date(row.beginn),
|
||||||
ende: new Date(row.ende),
|
ende: new Date(row.ende),
|
||||||
buchungs_art: row.buchungs_art,
|
buchungs_art: row.buchungs_art,
|
||||||
|
ganztaegig: row.ganztaegig ?? false,
|
||||||
gebucht_von: row.gebucht_von,
|
gebucht_von: row.gebucht_von,
|
||||||
kontakt_person: row.kontakt_person ?? null,
|
kontakt_person: row.kontakt_person ?? null,
|
||||||
kontakt_telefon: row.kontakt_telefon ?? null,
|
kontakt_telefon: row.kontakt_telefon ?? null,
|
||||||
@@ -78,7 +80,7 @@ class BookingService {
|
|||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
b.id, b.fahrzeug_id, b.titel, b.buchungs_art::text AS buchungs_art,
|
b.id, b.fahrzeug_id, b.titel, b.buchungs_art::text AS buchungs_art,
|
||||||
b.beginn, b.ende, b.abgesagt, b.gebucht_von,
|
b.beginn, b.ende, b.abgesagt, b.gebucht_von, b.ganztaegig,
|
||||||
f.bezeichnung AS fahrzeug_name, f.amtliches_kennzeichen AS fahrzeug_kennzeichen,
|
f.bezeichnung AS fahrzeug_name, f.amtliches_kennzeichen AS fahrzeug_kennzeichen,
|
||||||
u.name AS gebucht_von_name
|
u.name AS gebucht_von_name
|
||||||
FROM fahrzeug_buchungen b
|
FROM fahrzeug_buchungen b
|
||||||
@@ -103,7 +105,7 @@ class BookingService {
|
|||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
b.id, b.fahrzeug_id, b.titel, b.buchungs_art::text AS buchungs_art,
|
b.id, b.fahrzeug_id, b.titel, b.buchungs_art::text AS buchungs_art,
|
||||||
b.beginn, b.ende, b.abgesagt, b.gebucht_von,
|
b.beginn, b.ende, b.abgesagt, b.gebucht_von, b.ganztaegig,
|
||||||
f.bezeichnung AS fahrzeug_name, f.amtliches_kennzeichen AS fahrzeug_kennzeichen,
|
f.bezeichnung AS fahrzeug_name, f.amtliches_kennzeichen AS fahrzeug_kennzeichen,
|
||||||
u.name AS gebucht_von_name
|
u.name AS gebucht_von_name
|
||||||
FROM fahrzeug_buchungen b
|
FROM fahrzeug_buchungen b
|
||||||
@@ -125,7 +127,7 @@ class BookingService {
|
|||||||
SELECT
|
SELECT
|
||||||
b.id, b.fahrzeug_id, b.titel, b.beschreibung,
|
b.id, b.fahrzeug_id, b.titel, b.beschreibung,
|
||||||
b.buchungs_art::text AS buchungs_art,
|
b.buchungs_art::text AS buchungs_art,
|
||||||
b.beginn, b.ende,
|
b.beginn, b.ende, b.ganztaegig,
|
||||||
b.gebucht_von, b.kontakt_person, b.kontakt_telefon,
|
b.gebucht_von, b.kontakt_person, b.kontakt_telefon,
|
||||||
b.abgesagt, b.abgesagt_grund,
|
b.abgesagt, b.abgesagt_grund,
|
||||||
b.erstellt_am, b.aktualisiert_am,
|
b.erstellt_am, b.aktualisiert_am,
|
||||||
@@ -300,6 +302,7 @@ class BookingService {
|
|||||||
if (data.buchungsArt !== undefined) addField('buchungs_art', data.buchungsArt, 'fahrzeug_buchung_art');
|
if (data.buchungsArt !== undefined) addField('buchungs_art', data.buchungsArt, 'fahrzeug_buchung_art');
|
||||||
if (data.kontaktPerson !== undefined) addField('kontakt_person', data.kontaktPerson);
|
if (data.kontaktPerson !== undefined) addField('kontakt_person', data.kontaktPerson);
|
||||||
if (data.kontaktTelefon !== undefined) addField('kontakt_telefon', data.kontaktTelefon);
|
if (data.kontaktTelefon !== undefined) addField('kontakt_telefon', data.kontaktTelefon);
|
||||||
|
if (data.ganztaegig !== undefined) addField('ganztaegig', data.ganztaegig);
|
||||||
|
|
||||||
if (setClauses.length === 0) {
|
if (setClauses.length === 0) {
|
||||||
throw new Error('No fields to update');
|
throw new Error('No fields to update');
|
||||||
|
|||||||
@@ -393,7 +393,9 @@ class EventsService {
|
|||||||
* Capped at 100 instances and 2 years from the start date. */
|
* Capped at 100 instances and 2 years from the start date. */
|
||||||
private generateRecurrenceDates(startDate: Date, _endDate: Date, config: WiederholungConfig): Date[] {
|
private generateRecurrenceDates(startDate: Date, _endDate: Date, config: WiederholungConfig): Date[] {
|
||||||
const dates: Date[] = [];
|
const dates: Date[] = [];
|
||||||
const limitDate = config.bis ? new Date(config.bis + 'T23:59:59Z') : new Date(0);
|
const defaultLimit = new Date(startDate);
|
||||||
|
defaultLimit.setUTCFullYear(defaultLimit.getUTCFullYear() + 2);
|
||||||
|
const limitDate = config.bis ? new Date(config.bis + 'T23:59:59Z') : defaultLimit;
|
||||||
const interval = config.intervall ?? 1;
|
const interval = config.intervall ?? 1;
|
||||||
// Cap at 100 instances max, and 2 years
|
// Cap at 100 instances max, and 2 years
|
||||||
const maxDate = new Date(startDate);
|
const maxDate = new Date(startDate);
|
||||||
|
|||||||
@@ -396,8 +396,9 @@ class VehicleService {
|
|||||||
|
|
||||||
// Auto-update next service date on the vehicle when result is 'bestanden'
|
// Auto-update next service date on the vehicle when result is 'bestanden'
|
||||||
if (data.ergebnis === 'bestanden' && data.naechste_faelligkeit) {
|
if (data.ergebnis === 'bestanden' && data.naechste_faelligkeit) {
|
||||||
|
const column = data.art === '§57a Prüfung' ? 'paragraph57a_faellig_am' : 'naechste_wartung_am';
|
||||||
await pool.query(
|
await pool.query(
|
||||||
`UPDATE fahrzeuge SET naechste_wartung_am = $1 WHERE id = $2`,
|
`UPDATE fahrzeuge SET ${column} = $1 WHERE id = $2`,
|
||||||
[data.naechste_faelligkeit, fahrzeugId]
|
[data.naechste_faelligkeit, fahrzeugId]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -443,8 +444,9 @@ class VehicleService {
|
|||||||
|
|
||||||
// Auto-update next service date on the vehicle when result is 'bestanden'
|
// Auto-update next service date on the vehicle when result is 'bestanden'
|
||||||
if (data.ergebnis === 'bestanden' && data.naechste_faelligkeit) {
|
if (data.ergebnis === 'bestanden' && data.naechste_faelligkeit) {
|
||||||
|
const column = data.art === '§57a Prüfung' ? 'paragraph57a_faellig_am' : 'naechste_wartung_am';
|
||||||
await pool.query(
|
await pool.query(
|
||||||
`UPDATE fahrzeuge SET naechste_wartung_am = $1 WHERE id = $2`,
|
`UPDATE fahrzeuge SET ${column} = $1 WHERE id = $2`,
|
||||||
[data.naechste_faelligkeit, fahrzeugId]
|
[data.naechste_faelligkeit, fahrzeugId]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,12 +56,17 @@ const VehicleBookingQuickAddWidget: React.FC = () => {
|
|||||||
|
|
||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
mutationFn: () => {
|
mutationFn: () => {
|
||||||
|
const beginnDate = new Date(beginn);
|
||||||
|
const endeDate = new Date(ende);
|
||||||
|
if (isNaN(beginnDate.getTime()) || isNaN(endeDate.getTime())) {
|
||||||
|
return Promise.reject(new Error('Ungültiges Datum'));
|
||||||
|
}
|
||||||
const data: CreateBuchungInput = {
|
const data: CreateBuchungInput = {
|
||||||
fahrzeugId,
|
fahrzeugId,
|
||||||
titel: titel.trim(),
|
titel: titel.trim(),
|
||||||
beschreibung: beschreibung.trim() || null,
|
beschreibung: beschreibung.trim() || null,
|
||||||
beginn: new Date(beginn).toISOString(),
|
beginn: beginnDate.toISOString(),
|
||||||
ende: new Date(ende).toISOString(),
|
ende: endeDate.toISOString(),
|
||||||
buchungsArt: 'intern',
|
buchungsArt: 'intern',
|
||||||
};
|
};
|
||||||
return bookingApi.create(data);
|
return bookingApi.create(data);
|
||||||
@@ -120,7 +125,7 @@ const VehicleBookingQuickAddWidget: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{(vehicles ?? []).map((v) => (
|
{(vehicles ?? []).map((v) => (
|
||||||
<MenuItem key={v.id} value={v.id}>
|
<MenuItem key={v.id} value={v.id}>
|
||||||
{v.bezeichnung}{v.amtliches_kennzeichen ? ` (${v.amtliches_kennzeichen})` : ''}
|
{v.bezeichnung}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -287,10 +287,17 @@ function FahrzeugBuchungen() {
|
|||||||
setDialogLoading(true);
|
setDialogLoading(true);
|
||||||
setDialogError(null);
|
setDialogError(null);
|
||||||
try {
|
try {
|
||||||
|
const beginnDate = new Date(form.beginn);
|
||||||
|
const endeDate = new Date(form.ende);
|
||||||
|
if (isNaN(beginnDate.getTime()) || isNaN(endeDate.getTime())) {
|
||||||
|
setDialogError('Ungültiges Datum. Bitte Beginn und Ende prüfen.');
|
||||||
|
setDialogLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const payload: CreateBuchungInput = {
|
const payload: CreateBuchungInput = {
|
||||||
...form,
|
...form,
|
||||||
beginn: new Date(form.beginn).toISOString(),
|
beginn: beginnDate.toISOString(),
|
||||||
ende: new Date(form.ende).toISOString(),
|
ende: endeDate.toISOString(),
|
||||||
ganztaegig: form.ganztaegig || false,
|
ganztaegig: form.ganztaegig || false,
|
||||||
};
|
};
|
||||||
if (editingBooking) {
|
if (editingBooking) {
|
||||||
@@ -374,6 +381,7 @@ function FahrzeugBuchungen() {
|
|||||||
buchungsArt: detailBooking.buchungs_art,
|
buchungsArt: detailBooking.buchungs_art,
|
||||||
kontaktPerson: '',
|
kontaktPerson: '',
|
||||||
kontaktTelefon: '',
|
kontaktTelefon: '',
|
||||||
|
ganztaegig: detailBooking.ganztaegig || false,
|
||||||
});
|
});
|
||||||
setDialogError(null);
|
setDialogError(null);
|
||||||
setAvailability(null);
|
setAvailability(null);
|
||||||
@@ -698,9 +706,10 @@ function FahrzeugBuchungen() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
{format(parseISO(detailBooking.beginn), 'dd.MM.yyyy HH:mm')}
|
{detailBooking.ganztaegig
|
||||||
{' – '}
|
? `${format(parseISO(detailBooking.beginn), 'dd.MM.yyyy')} – ${format(parseISO(detailBooking.ende), 'dd.MM.yyyy')} (Ganztägig)`
|
||||||
{format(parseISO(detailBooking.ende), 'dd.MM.yyyy HH:mm')}
|
: `${format(parseISO(detailBooking.beginn), 'dd.MM.yyyy HH:mm')} – ${format(parseISO(detailBooking.ende), 'dd.MM.yyyy HH:mm')}`
|
||||||
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
{detailBooking.gebucht_von_name && (
|
{detailBooking.gebucht_von_name && (
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
|
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
|
||||||
@@ -778,7 +787,6 @@ function FahrzeugBuchungen() {
|
|||||||
{vehicles.map((v) => (
|
{vehicles.map((v) => (
|
||||||
<MenuItem key={v.id} value={v.id}>
|
<MenuItem key={v.id} value={v.id}>
|
||||||
{v.bezeichnung}
|
{v.bezeichnung}
|
||||||
{v.amtliches_kennzeichen ? ` (${v.amtliches_kennzeichen})` : ''}
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ const EMPTY_BOOKING_FORM: CreateBuchungInput = {
|
|||||||
buchungsArt: 'intern',
|
buchungsArt: 'intern',
|
||||||
kontaktPerson: '',
|
kontaktPerson: '',
|
||||||
kontaktTelefon: '',
|
kontaktTelefon: '',
|
||||||
|
ganztaegig: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -1446,7 +1447,7 @@ function VeranstaltungFormDialog({
|
|||||||
try {
|
try {
|
||||||
const createPayload: CreateVeranstaltungInput = {
|
const createPayload: CreateVeranstaltungInput = {
|
||||||
...form,
|
...form,
|
||||||
wiederholung: (!editingEvent && wiederholungAktiv && wiederholungBis)
|
wiederholung: ((!editingEvent || (editingEvent.wiederholung && !editingEvent.wiederholung_parent_id)) && wiederholungAktiv && wiederholungBis)
|
||||||
? {
|
? {
|
||||||
typ: wiederholungTyp,
|
typ: wiederholungTyp,
|
||||||
bis: wiederholungBis,
|
bis: wiederholungBis,
|
||||||
@@ -1458,7 +1459,7 @@ function VeranstaltungFormDialog({
|
|||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
if (editingEvent) {
|
if (editingEvent) {
|
||||||
await eventsApi.updateEvent(editingEvent.id, form);
|
await eventsApi.updateEvent(editingEvent.id, createPayload);
|
||||||
notification.showSuccess('Veranstaltung aktualisiert');
|
notification.showSuccess('Veranstaltung aktualisiert');
|
||||||
} else {
|
} else {
|
||||||
await eventsApi.createEvent(createPayload);
|
await eventsApi.createEvent(createPayload);
|
||||||
@@ -1636,10 +1637,10 @@ function VeranstaltungFormDialog({
|
|||||||
{(!editingEvent || (editingEvent && editingEvent.wiederholung)) && (
|
{(!editingEvent || (editingEvent && editingEvent.wiederholung)) && (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
{editingEvent && editingEvent.wiederholung ? (
|
{editingEvent && editingEvent.wiederholung && editingEvent.wiederholung_parent_id ? (
|
||||||
<>
|
<>
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ fontStyle: 'italic' }}>
|
<Typography variant="body2" color="text.secondary" sx={{ fontStyle: 'italic' }}>
|
||||||
Wiederholung kann nicht bearbeitet werden
|
Wiederholung kann nicht bearbeitet werden (Einzeltermin einer Serie)
|
||||||
</Typography>
|
</Typography>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Switch checked disabled />}
|
control={<Switch checked disabled />}
|
||||||
@@ -1659,7 +1660,7 @@ function VeranstaltungFormDialog({
|
|||||||
)}
|
)}
|
||||||
{wiederholungAktiv && (
|
{wiederholungAktiv && (
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<FormControl fullWidth size="small" disabled={!!editingEvent}>
|
<FormControl fullWidth size="small" disabled={!!editingEvent?.wiederholung_parent_id}>
|
||||||
<InputLabel id="wiederholung-typ-label">Wiederholung</InputLabel>
|
<InputLabel id="wiederholung-typ-label">Wiederholung</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
labelId="wiederholung-typ-label"
|
labelId="wiederholung-typ-label"
|
||||||
@@ -1684,12 +1685,12 @@ function VeranstaltungFormDialog({
|
|||||||
onChange={(e) => setWiederholungIntervall(Math.max(1, Math.min(52, parseInt(e.target.value) || 1)))}
|
onChange={(e) => setWiederholungIntervall(Math.max(1, Math.min(52, parseInt(e.target.value) || 1)))}
|
||||||
inputProps={{ min: 1, max: 52 }}
|
inputProps={{ min: 1, max: 52 }}
|
||||||
fullWidth
|
fullWidth
|
||||||
disabled={!!editingEvent}
|
disabled={!!editingEvent?.wiederholung_parent_id}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(wiederholungTyp === 'monatlich_erster_wochentag' || wiederholungTyp === 'monatlich_letzter_wochentag') && (
|
{(wiederholungTyp === 'monatlich_erster_wochentag' || wiederholungTyp === 'monatlich_letzter_wochentag') && (
|
||||||
<FormControl fullWidth size="small" disabled={!!editingEvent}>
|
<FormControl fullWidth size="small" disabled={!!editingEvent?.wiederholung_parent_id}>
|
||||||
<InputLabel id="wiederholung-wochentag-label">Wochentag</InputLabel>
|
<InputLabel id="wiederholung-wochentag-label">Wochentag</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
labelId="wiederholung-wochentag-label"
|
labelId="wiederholung-wochentag-label"
|
||||||
@@ -1712,7 +1713,7 @@ function VeranstaltungFormDialog({
|
|||||||
onChange={(e) => setWiederholungBis(e.target.value)}
|
onChange={(e) => setWiederholungBis(e.target.value)}
|
||||||
InputLabelProps={{ shrink: true }}
|
InputLabelProps={{ shrink: true }}
|
||||||
fullWidth
|
fullWidth
|
||||||
disabled={!!editingEvent}
|
disabled={!!editingEvent?.wiederholung_parent_id}
|
||||||
helperText="Letztes Datum für Wiederholungen"
|
helperText="Letztes Datum für Wiederholungen"
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -2085,6 +2086,7 @@ export default function Kalender() {
|
|||||||
buchungsArt: detailBooking.buchungs_art,
|
buchungsArt: detailBooking.buchungs_art,
|
||||||
kontaktPerson: '',
|
kontaktPerson: '',
|
||||||
kontaktTelefon: '',
|
kontaktTelefon: '',
|
||||||
|
ganztaegig: (detailBooking as any).ganztaegig || false,
|
||||||
});
|
});
|
||||||
setBookingDialogError(null);
|
setBookingDialogError(null);
|
||||||
setAvailability(null);
|
setAvailability(null);
|
||||||
@@ -2128,7 +2130,17 @@ export default function Kalender() {
|
|||||||
}
|
}
|
||||||
const beginnIso = fromGermanDateTime(bookingForm.beginn)!;
|
const beginnIso = fromGermanDateTime(bookingForm.beginn)!;
|
||||||
const endeIso = fromGermanDateTime(bookingForm.ende)!;
|
const endeIso = fromGermanDateTime(bookingForm.ende)!;
|
||||||
if (new Date(endeIso) <= new Date(beginnIso)) {
|
const beginnDate = new Date(beginnIso);
|
||||||
|
const endeDate = new Date(endeIso);
|
||||||
|
if (isNaN(beginnDate.getTime())) {
|
||||||
|
setBookingDialogError('Ungültiges Beginn-Datum');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isNaN(endeDate.getTime())) {
|
||||||
|
setBookingDialogError('Ungültiges Ende-Datum');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (endeDate <= beginnDate) {
|
||||||
setBookingDialogError('Ende muss nach dem Beginn liegen');
|
setBookingDialogError('Ende muss nach dem Beginn liegen');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2137,8 +2149,8 @@ export default function Kalender() {
|
|||||||
try {
|
try {
|
||||||
const payload: CreateBuchungInput = {
|
const payload: CreateBuchungInput = {
|
||||||
...bookingForm,
|
...bookingForm,
|
||||||
beginn: (() => { const iso = fromGermanDateTime(bookingForm.beginn); return iso ? new Date(iso).toISOString() : new Date(bookingForm.beginn).toISOString(); })(),
|
beginn: beginnDate.toISOString(),
|
||||||
ende: (() => { const iso = fromGermanDateTime(bookingForm.ende); return iso ? new Date(iso).toISOString() : new Date(bookingForm.ende).toISOString(); })(),
|
ende: endeDate.toISOString(),
|
||||||
};
|
};
|
||||||
if (editingBooking) {
|
if (editingBooking) {
|
||||||
await bookingApi.update(editingBooking.id, payload);
|
await bookingApi.update(editingBooking.id, payload);
|
||||||
@@ -2874,11 +2886,6 @@ export default function Kalender() {
|
|||||||
<Typography variant="body2" fontWeight={600}>
|
<Typography variant="body2" fontWeight={600}>
|
||||||
{vehicle.bezeichnung}
|
{vehicle.bezeichnung}
|
||||||
</Typography>
|
</Typography>
|
||||||
{vehicle.amtliches_kennzeichen && (
|
|
||||||
<Typography variant="caption" color="text.secondary">
|
|
||||||
{vehicle.amtliches_kennzeichen}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{weekDays.map((day) => {
|
{weekDays.map((day) => {
|
||||||
const cellBookings = getBookingsForCell(vehicle.id, day);
|
const cellBookings = getBookingsForCell(vehicle.id, day);
|
||||||
@@ -3010,9 +3017,10 @@ export default function Kalender() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
{fnsFormat(parseISO(detailBooking.beginn), 'dd.MM.yyyy HH:mm')}
|
{(detailBooking as any).ganztaegig
|
||||||
{' – '}
|
? `${fnsFormat(parseISO(detailBooking.beginn), 'dd.MM.yyyy')} – ${fnsFormat(parseISO(detailBooking.ende), 'dd.MM.yyyy')} (Ganztägig)`
|
||||||
{fnsFormat(parseISO(detailBooking.ende), 'dd.MM.yyyy HH:mm')}
|
: `${fnsFormat(parseISO(detailBooking.beginn), 'dd.MM.yyyy HH:mm')} – ${fnsFormat(parseISO(detailBooking.ende), 'dd.MM.yyyy HH:mm')}`
|
||||||
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
{detailBooking.gebucht_von_name && (
|
{detailBooking.gebucht_von_name && (
|
||||||
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
|
<Typography variant="body2" color="text.secondary" sx={{ mt: 0.5 }}>
|
||||||
@@ -3074,7 +3082,7 @@ export default function Kalender() {
|
|||||||
>
|
>
|
||||||
{vehicles.map((v) => (
|
{vehicles.map((v) => (
|
||||||
<MenuItem key={v.id} value={v.id}>
|
<MenuItem key={v.id} value={v.id}>
|
||||||
{v.bezeichnung}{v.amtliches_kennzeichen ? ` (${v.amtliches_kennzeichen})` : ''}
|
{v.bezeichnung}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
@@ -3088,6 +3096,19 @@ export default function Kalender() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={bookingForm.ganztaegig || false}
|
||||||
|
onChange={(e) => {
|
||||||
|
const checked = e.target.checked;
|
||||||
|
setBookingForm((f) => ({ ...f, ganztaegig: checked }));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Ganztägig"
|
||||||
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth size="small" label="Beginn" placeholder="TT.MM.JJJJ HH:MM" required
|
fullWidth size="small" label="Beginn" placeholder="TT.MM.JJJJ HH:MM" required
|
||||||
value={bookingForm.beginn}
|
value={bookingForm.beginn}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export interface FahrzeugBuchungListItem {
|
|||||||
buchungs_art: BuchungsArt;
|
buchungs_art: BuchungsArt;
|
||||||
beginn: string; // ISO
|
beginn: string; // ISO
|
||||||
ende: string; // ISO
|
ende: string; // ISO
|
||||||
|
ganztaegig: boolean;
|
||||||
abgesagt: boolean;
|
abgesagt: boolean;
|
||||||
gebucht_von: string;
|
gebucht_von: string;
|
||||||
gebucht_von_name?: string | null;
|
gebucht_von_name?: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user