mirror of
https://github.com/tomru/pfadi-bussle.git
synced 2026-03-04 06:57:12 +01:00
use fixed tarifs and add additional costs
This commit is contained in:
@@ -4,20 +4,17 @@ import Footer from '../../../components/footer'
|
||||
import Header from '../../../components/header'
|
||||
import Input from '../../../components/input'
|
||||
import Select from '../../../components/select'
|
||||
import { AdditionalCosts, BillDocument } from '../../../db/bill'
|
||||
import { AdditionalCost, BillDocument } from '../../../db/bill'
|
||||
import { BookingDocument } from '../../../db/booking'
|
||||
import {
|
||||
BILL_STATUS,
|
||||
MILAGE_RATES,
|
||||
getMilageRateValue,
|
||||
} from '../../../db/enums'
|
||||
import { BILL_STATUS, MILAGE_TARIFS } from '../../../db/enums'
|
||||
import { getBookingByUUID, getMilageMax } from '../../../db/index'
|
||||
import { dateFormatFrontend } from '../../../helpers/date'
|
||||
import { getBillTotal } from '../../../helpers/bill'
|
||||
|
||||
const milageRateOptions = Object.values(MILAGE_RATES).map((rate) => {
|
||||
const milageTarifOptions = Object.values(MILAGE_TARIFS).map((tarif) => {
|
||||
return (
|
||||
<option value={rate} key={rate}>
|
||||
{getRateLabel(rate)} ({getMilageRateValue(rate)} EUR)
|
||||
<option value={tarif} key={tarif}>
|
||||
{getTarifLabel(tarif)}
|
||||
</option>
|
||||
)
|
||||
})
|
||||
@@ -54,26 +51,14 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
}
|
||||
}
|
||||
|
||||
function getRateLabel(rate: MILAGE_RATES) {
|
||||
switch (rate) {
|
||||
case MILAGE_RATES.INTERN_LTE_200:
|
||||
return 'Intern bis zu 200km'
|
||||
case MILAGE_RATES.INTERN_201_1000:
|
||||
return 'Intern 201-1.000km'
|
||||
case MILAGE_RATES.INTERN_1001_2000:
|
||||
return 'Intern 1.001-2.000km'
|
||||
case MILAGE_RATES.INTERN_GTE_2001:
|
||||
return 'Intern ab 2.001km'
|
||||
case MILAGE_RATES.EXTERN_LTE_200:
|
||||
return 'Extern bis zu 200km'
|
||||
case MILAGE_RATES.EXTERN_201_1000:
|
||||
return 'Extern 201-1.000km'
|
||||
case MILAGE_RATES.EXTERN_1001_2000:
|
||||
return 'Extern 1.001-2.000km'
|
||||
case MILAGE_RATES.EXTERN_GTE_2001:
|
||||
return 'Extern ab 2.001km'
|
||||
case MILAGE_RATES.FREE_OF_CHARGE:
|
||||
return 'Frei'
|
||||
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'
|
||||
}
|
||||
@@ -98,8 +83,8 @@ async function saveBill(
|
||||
milageStart: number
|
||||
milageEnd: number
|
||||
milage?: number
|
||||
rate: MILAGE_RATES
|
||||
additionalCosts?: AdditionalCosts[]
|
||||
tarif: MILAGE_TARIFS
|
||||
additionalCosts: AdditionalCost[]
|
||||
status: BILL_STATUS
|
||||
}
|
||||
): Promise<BillDocument> {
|
||||
@@ -129,17 +114,16 @@ export default function BillPage({
|
||||
booking.bill?.milageStart || milageMax
|
||||
)
|
||||
const [milageEnd, setMilageEnd] = useState(booking.bill?.milageEnd)
|
||||
const [rate, setRate] = useState(
|
||||
booking.bill?.rate || MILAGE_RATES.EXTERN_LTE_200
|
||||
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 =
|
||||
Math.round(milage && rate && milage * getMilageRateValue(rate) * 100) /
|
||||
100 || 0
|
||||
const total = getBillTotal({ tarif, milage, additionalCosts })
|
||||
|
||||
// in case the props change, update the internal state
|
||||
useEffect(() => setBooking(bookingProp), [bookingProp])
|
||||
@@ -154,8 +138,9 @@ export default function BillPage({
|
||||
milageStart,
|
||||
milageEnd,
|
||||
milage,
|
||||
rate,
|
||||
tarif,
|
||||
status,
|
||||
additionalCosts,
|
||||
})
|
||||
|
||||
booking.bill = bill
|
||||
@@ -167,11 +152,29 @@ export default function BillPage({
|
||||
setStoringInProgress(false)
|
||||
}
|
||||
|
||||
const onAddAdditionalCost = function (
|
||||
event: React.MouseEvent<HTMLButtonElement>
|
||||
) {
|
||||
event.preventDefault()
|
||||
setAdditionalCosts([...additionalCosts, { name: '', value: 0 }])
|
||||
}
|
||||
|
||||
const onRemoveAdditionalCost = function (
|
||||
event: React.MouseEvent<HTMLButtonElement>,
|
||||
index: number
|
||||
) {
|
||||
event.preventDefault()
|
||||
setAdditionalCosts([
|
||||
...additionalCosts.slice(0, index),
|
||||
...additionalCosts.slice(index + 1),
|
||||
])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-3 flex flex-col min-h-screen">
|
||||
<Header />
|
||||
<main className="flex-grow">
|
||||
<h2 className="text-3xl">Pfadi Bussle Buchung</h2>
|
||||
<h2 className="text-3xl">Abrechnung</h2>
|
||||
<form className="form" onSubmit={onSubmit}>
|
||||
<div>
|
||||
<strong>Buchungszeitraum:</strong>{' '}
|
||||
@@ -205,10 +208,10 @@ export default function BillPage({
|
||||
<Input label="Gefahren" name="milage" readOnly value={milage} />
|
||||
<Select
|
||||
label="Rate"
|
||||
value={rate}
|
||||
onChange={(e) => setRate(e.target.value as MILAGE_RATES)}
|
||||
value={tarif}
|
||||
onChange={(e) => setTarif(e.target.value as MILAGE_TARIFS)}
|
||||
>
|
||||
{milageRateOptions}
|
||||
{milageTarifOptions}
|
||||
</Select>
|
||||
<Select
|
||||
label="Status"
|
||||
@@ -217,7 +220,66 @@ export default function BillPage({
|
||||
>
|
||||
{bookingStatusOptions}
|
||||
</Select>
|
||||
<Input label="Summe" name="milage" readOnly value={total} />
|
||||
<div className="mb-3">
|
||||
<button
|
||||
className="ibtn btn-gray mr-3"
|
||||
onClick={onAddAdditionalCost}
|
||||
title="Zusätzliche Kosten hinzufügen"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<label className="flabel inline">Zusätzliche Kosten</label>
|
||||
</div>
|
||||
{additionalCosts.map((_, index) => {
|
||||
return (
|
||||
<>
|
||||
<div className="mb-3" key={`label${index}`}>
|
||||
<button
|
||||
className="ibtn btn-gray mr-3"
|
||||
onClick={(event) => onRemoveAdditionalCost(event, index)}
|
||||
title="Entfernen"
|
||||
>
|
||||
-
|
||||
</button>
|
||||
<label className="flabel inline">{`Kostenpunkt ${
|
||||
index + 1
|
||||
}`}</label>
|
||||
</div>
|
||||
<div className="ml-10 mb-3" key={`input{index}`}>
|
||||
<Input
|
||||
label={`Name`}
|
||||
name={`additionalCostName${index}`}
|
||||
key={`additionalCostName${index}`}
|
||||
value={additionalCosts[index].name}
|
||||
onChange={(event) => {
|
||||
const newAdditonalCosts = [...additionalCosts]
|
||||
newAdditonalCosts[index] = {
|
||||
value: newAdditonalCosts[index].value,
|
||||
name: event.target.value,
|
||||
}
|
||||
setAdditionalCosts(newAdditonalCosts)
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
label={`Betrag`}
|
||||
name={`additionalCostValue${index}`}
|
||||
key={`additionalCostValue${index}`}
|
||||
value={additionalCosts[index].value}
|
||||
type="number"
|
||||
onChange={(event) => {
|
||||
const newAdditonalCosts = [...additionalCosts]
|
||||
newAdditonalCosts[index] = {
|
||||
name: newAdditonalCosts[index].name,
|
||||
value: Number(event.target.value),
|
||||
}
|
||||
setAdditionalCosts(newAdditonalCosts)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
})}
|
||||
<Input label="Summe" name="total" readOnly value={total} />
|
||||
</div>
|
||||
{storingError && (
|
||||
<div className="error-message flex-grow">{storingError}</div>
|
||||
|
||||
@@ -94,7 +94,7 @@ export default function ShowBooking({
|
||||
<div className="mx-3 flex flex-col min-h-screen">
|
||||
<Header />
|
||||
<main className="flex-grow">
|
||||
<h2 className="text-3xl">Ihre Pfadi Bussle Buchung</h2>
|
||||
<h2 className="text-3xl">Ihre Buchung</h2>
|
||||
<div>
|
||||
<strong>Buchungsstatus:</strong> {getBookingStatus(booking)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user