import { GetServerSideProps, NextApiHandler, NextApiRequest } from 'next' import React, { useEffect, useState } from 'react' import Footer from '../../../../components/footer' import Header from '../../../../components/header' import Input from '../../../../components/input' import Select from '../../../../components/select' import { AdditionalCost, BillDocument } from '../../../../db/bill' import { BookingDocument } from '../../../../db/booking' import { BILL_STATUS, MILAGE_TARIFS } from '../../../../db/enums' import { getBookingByUUID, getMilageMax } from '../../../../db/index' import { dateFormatFrontend } from '../../../../helpers/date' import { getBillTotal } from '../../../../helpers/bill' import { getBookingStatus } from '../../../../helpers/booking' import authenticate from '../../../../lib/authenticate' import withSession from '../../../../lib/session' export const getServerSideProps: GetServerSideProps = withSession( async ({ req, res, params }) => { const { uuid: uuids } = params const authenticatedUser = authenticate(req, res) if (!authenticatedUser) { // TODO: not sure if needed req?.session.destroy() return { props: {} } } req.session.set('user', authenticatedUser) await req.session.save() const uuid = Array.isArray(uuids) ? uuids[0] : uuids const booking = await getBookingByUUID(uuid) if (!booking) { res.statusCode = 404 res.end() return { props: {} } } const milageMax = await getMilageMax() await booking.populate('booker').populate('bill').execPopulate() // TODO: hack, not sure why _id is not serilizable const bookingJSON = JSON.parse(JSON.stringify(booking.toJSON())) return { props: { booking: bookingJSON, milageMax }, } } ) const milageTarifOptions = Object.values(MILAGE_TARIFS).map((tarif) => { return ( ) }) const bookingStatusOptions = Object.values(BILL_STATUS).map((status) => { return ( ) }) function getTarifLabel(tarif: MILAGE_TARIFS) { switch (tarif) { case MILAGE_TARIFS.EXTERN: return 'Extern' case MILAGE_TARIFS.INTERN: return 'Intern' case MILAGE_TARIFS.NOCHARGE: return 'Frei von Kosten' default: return 'Keine' } } function getBillStatusLabel(status: BILL_STATUS) { switch (status) { case BILL_STATUS.UNINVOICED: return 'Nicht gestellt' case BILL_STATUS.INVOICED: return 'Gestellt' case BILL_STATUS.PAID: return 'Bezahlt' default: return 'Unbekannt!!!' } } async function saveBill( booking: BookingDocument, bill: { milageStart: number milageEnd: number milage?: number tarif: MILAGE_TARIFS additionalCosts: AdditionalCost[] status: BILL_STATUS } ): Promise { const response = await fetch(`/api/booking/${booking.uuid}/bill`, { method: booking.bill?._id ? 'PATCH' : 'POST', mode: 'cors', cache: 'no-cache', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', }, referrerPolicy: 'no-referrer', body: JSON.stringify(bill), }) return response.json() } export default function BillPage({ booking: bookingProp, milageMax, }: { booking: BookingDocument milageMax: number }) { const [booking, setBooking] = useState(bookingProp) const [milageStart, setMilageStart] = useState( booking?.bill?.milageStart || milageMax ) const [milageEnd, setMilageEnd] = useState(booking?.bill?.milageEnd) const [tarif, setTarif] = useState( booking?.bill?.tarif || MILAGE_TARIFS.EXTERN ) const [status, setStatus] = useState(booking?.bill?.status) const [additionalCosts, setAdditionalCosts] = useState([]) const [storingInProgress, setStoringInProgress] = useState(false) const [storingError, setStoringError] = useState(null) const milage = (0 < milageStart && milageStart < milageEnd && milageEnd - milageStart) || 0 const total = getBillTotal({ tarif, milage, additionalCosts }) // in case the props change, update the internal state useEffect(() => setBooking(bookingProp), [bookingProp]) const onSubmit = async (event: React.FormEvent) => { event.preventDefault() setStoringInProgress(true) setStoringError(null) try { const bill = await saveBill(booking, { milageStart, milageEnd, milage, tarif, status, additionalCosts, }) booking.bill = bill setBooking(booking) } catch (error) { setStoringError('Buchung konnte nicht gespeichert werden!') console.error('Failed to store booking', error) } setStoringInProgress(false) } const onAddAdditionalCost = function ( event: React.MouseEvent ) { event.preventDefault() setAdditionalCosts([...additionalCosts, { name: '', value: 0 }]) } const onRemoveAdditionalCost = function ( event: React.MouseEvent, index: number ) { event.preventDefault() setAdditionalCosts([ ...additionalCosts.slice(0, index), ...additionalCosts.slice(index + 1), ]) } return (

Abrechnung

{booking && (
Buchungszeitraum:{' '} {dateFormatFrontend(new Date(booking.startDate))} -{' '} {dateFormatFrontend(new Date(booking.endDate))}
Bucher: {booking.booker.name}
Buchungsstatus: {getBookingStatus(booking)}
>) => setMilageStart(Number(e.target.value)) } /> >) => setMilageEnd(Number(e.target.value)) } />
{additionalCosts.map((_, index) => { return ( <>
{ const newAdditonalCosts = [...additionalCosts] newAdditonalCosts[index] = { value: newAdditonalCosts[index].value, name: event.target.value, } setAdditionalCosts(newAdditonalCosts) }} /> { const newAdditonalCosts = [...additionalCosts] newAdditonalCosts[index] = { name: newAdditonalCosts[index].name, value: Number(event.target.value), } setAdditionalCosts(newAdditonalCosts) }} />
) })}
{storingError && (
{storingError}
)}
)}
) }