Skip to content
This repository was archived by the owner on Feb 10, 2025. It is now read-only.

Commit 42070c9

Browse files
committed
fix: alv change
refactor: price utilities
1 parent 9f33d0e commit 42070c9

17 files changed

Lines changed: 341 additions & 327 deletions

File tree

apps/admin-ui/src/component/reservations/requested/util.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ export function reservationPrice(
3838
return getReservationPrice(
3939
reservation.price,
4040
t("RequestedReservation.noPrice"),
41-
"fi",
4241
true
4342
);
4443
}
@@ -95,17 +94,17 @@ export function getReservationPriceDetails(
9594
const taxP = parseFloat(pricing.taxPercentage?.value ?? "");
9695
const taxPercentage = Number.isNaN(taxP) ? 0 : taxP;
9796
return priceUnit === PriceUnit.Fixed
98-
? getReservationPrice(maxPrice, t("RequestedReservation.noPrice"))
97+
? getReservationPrice(maxPrice, t("RequestedReservation.noPrice"), false)
9998
: t("RequestedReservation.ApproveDialog.priceBreakdown", {
10099
volume: formatters.strippedDecimal.format(volume),
101100
units: t(`RequestedReservation.ApproveDialog.priceUnits.${priceUnit}`),
102101
vatPercent: formatters.whole.format(taxPercentage),
103102
unit: t(`RequestedReservation.ApproveDialog.priceUnit.${priceUnit}`),
104-
unitPrice: getReservationPrice(maxPrice, ""),
103+
unitPrice: getReservationPrice(maxPrice, "", false),
105104
price: getReservationPrice(
106105
String(volume * parseFloat(maxPrice)),
107106
t("RequestedReservation.noPrice"),
108-
"fi"
107+
false
109108
),
110109
});
111110
}

apps/ui/components/calendar/ReservationCalendarControls.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ function TogglerLabelContent({
257257
areControlsVisible: boolean;
258258
togglerLabel: string;
259259
t: TFunction;
260-
price?: string;
260+
price: string | null;
261261
}) {
262262
if (areControlsVisible) {
263263
return <div>&nbsp;</div>;
@@ -287,7 +287,6 @@ function ReservationCalendarControls({
287287
const { control, watch, handleSubmit, setValue } = reservationForm;
288288
const formDate = watch("date");
289289
const formDuration = watch("duration");
290-
const date = new Date(formDate ?? "");
291290
const dateValue = useMemo(() => fromUIDate(formDate ?? ""), [formDate]);
292291
const duration = !Number.isNaN(Number(formDuration))
293292
? Number(formDuration)
@@ -306,14 +305,14 @@ function ReservationCalendarControls({
306305
})();
307306

308307
const price =
309-
date != null && duration != null
308+
dateValue != null && duration != null
310309
? getReservationUnitPrice({
311310
reservationUnit,
312-
pricingDate: date,
311+
pricingDate: dateValue,
313312
minutes: duration,
314313
trailingZeros: true,
315314
})
316-
: undefined;
315+
: null;
317316

318317
const lastOpeningDate = maxBy(
319318
reservationUnit.reservableTimeSpans,

apps/ui/components/reservation-unit/Head.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ import IconWithText from "../common/IconWithText";
1818
import { Images } from "./Images";
1919
import {
2020
getActivePricing,
21-
getPrice,
21+
getPriceString,
2222
getReservationUnitName,
2323
getUnitName,
24+
isReservationUnitPaid,
2425
} from "@/modules/reservationUnit";
2526
import BreadcrumbWrapper from "../common/BreadcrumbWrapper";
2627
import { isReservationStartInFuture } from "@/modules/reservation";
@@ -154,14 +155,10 @@ function Head({
154155
const maxReservationDuration = formatDuration(maxDur / 60, t, true);
155156

156157
const pricing = getActivePricing(reservationUnit);
157-
const unitPrice = pricing ? getPrice({ pricing }) : undefined;
158+
const unitPrice = pricing ? getPriceString({ pricing }) : undefined;
158159

159-
const unitPriceSuffix =
160-
pricing &&
161-
getPrice({ pricing, asNumeral: true }) !== "0" &&
162-
subventionSuffix != null
163-
? subventionSuffix
164-
: undefined;
160+
const isPaid = isReservationUnitPaid(reservationUnit.pricings);
161+
const hasSubventionSuffix = pricing && isPaid && subventionSuffix != null;
165162

166163
const reservationUnitName = getReservationUnitName(reservationUnit);
167164

@@ -241,7 +238,7 @@ function Head({
241238
text={
242239
<>
243240
{unitPrice}
244-
{unitPriceSuffix}
241+
{hasSubventionSuffix ? subventionSuffix : null}
245242
</>
246243
}
247244
/>
@@ -252,7 +249,7 @@ function Head({
252249
)}
253250
</div>
254251
<Images
255-
images={orderImages(reservationUnit.images ?? [])}
252+
images={orderImages(reservationUnit.images)}
256253
contextName={reservationUnitName}
257254
/>
258255
</RightContainer>

apps/ui/components/reservation-unit/QuickReservation.tsx

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import { chunkArray, fromUIDate, toUIDate } from "common/src/common/util";
66
import { fontBold, fontMedium, H4 } from "common/src/common/typography";
77
import type { ReservationUnitPageQuery } from "@gql/gql-types";
88
import { breakpoints } from "common";
9-
import { getReservationUnitPrice } from "@/modules/reservationUnit";
9+
import {
10+
getReservationUnitPrice,
11+
isReservationUnitPaid,
12+
} from "@/modules/reservationUnit";
1013
import Carousel from "../Carousel";
1114
import { getLastPossibleReservationDate } from "@/components/reservation-unit/utils";
1215
import type { FocusTimeSlot } from "@/components/calendar/ReservationCalendarControls";
@@ -172,22 +175,23 @@ function QuickReservation({
172175
const dateValue = useMemo(() => fromUIDate(formDate ?? ""), [formDate]);
173176
const duration = watch("duration");
174177

175-
const getPrice = useCallback(
176-
(asNumeral = false) => {
177-
if (reservationUnit == null || dateValue == null || duration == null) {
178-
return null;
179-
}
180-
return getReservationUnitPrice({
181-
reservationUnit,
182-
pricingDate: dateValue,
183-
minutes: duration,
184-
trailingZeros: true,
185-
asNumeral,
186-
});
187-
},
188-
[duration, reservationUnit, dateValue]
178+
const isFreeOfCharge = !isReservationUnitPaid(
179+
reservationUnit?.pricings ?? [],
180+
dateValue ?? new Date()
189181
);
190182

183+
const getPrice = useCallback(() => {
184+
if (reservationUnit == null || dateValue == null || duration == null) {
185+
return null;
186+
}
187+
return getReservationUnitPrice({
188+
reservationUnit,
189+
pricingDate: dateValue,
190+
minutes: duration,
191+
trailingZeros: true,
192+
});
193+
}, [duration, reservationUnit, dateValue]);
194+
191195
// A map of all available times for the day, chunked into groups of 8
192196
const timeChunks: string[][] = useMemo(() => {
193197
const itemsPerChunk = 8;
@@ -302,7 +306,7 @@ function QuickReservation({
302306
<>
303307
{t("reservationUnit:price")}:{" "}
304308
<PriceValue>{getPrice()}</PriceValue>
305-
{getPrice(true) !== "0" && subventionSuffix}
309+
{!isFreeOfCharge && subventionSuffix}
306310
</>
307311
)}
308312
</Price>

apps/ui/components/reservation-unit/RelatedUnits.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import IconWithText from "../common/IconWithText";
1414
import Carousel from "../Carousel";
1515
import {
1616
getActivePricing,
17-
getPrice,
17+
getPriceString,
1818
getReservationUnitName,
1919
getUnitName,
2020
} from "@/modules/reservationUnit";
@@ -126,7 +126,8 @@ function RelatedUnits({ units }: PropsType): JSX.Element | null {
126126
{units.map((unit) => {
127127
const name = getReservationUnitName(unit);
128128
const pricing = getActivePricing(unit);
129-
const unitPrice = pricing != null ? getPrice({ pricing }) : undefined;
129+
const unitPrice =
130+
pricing != null ? getPriceString({ pricing }) : undefined;
130131
const reservationUnitTypeName =
131132
unit.reservationUnitType != null
132133
? getTranslation(unit.reservationUnitType, "name")

apps/ui/components/reservation/EditStep0.tsx

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
getPossibleTimesForDay,
3838
getReservationUnitPrice,
3939
getTimeString,
40+
isReservationUnitPaid,
4041
} from "@/modules/reservationUnit";
4142
import { formatDuration, isTouchDevice } from "@/modules/util";
4243
import { BlackButton, MediumButton } from "@/styles/util";
@@ -280,22 +281,14 @@ export function EditStep0({
280281
reservationUnit?.bufferTimeBefore,
281282
]);
282283

283-
const isSlotFree = useCallback(
284-
(start: Date): boolean => {
285-
const price = getReservationUnitPrice({
286-
reservationUnit,
287-
pricingDate: start,
288-
asNumeral: true,
289-
});
290-
return price === "0";
291-
},
292-
[reservationUnit]
293-
);
294-
295284
const slotPropGetter = useMemo(() => {
296285
if (!reservationUnit) {
297286
return undefined;
298287
}
288+
const isSlotFree = (start: Date): boolean => {
289+
return isReservationUnitPaid(reservationUnit.pricings, start);
290+
};
291+
299292
return getSlotPropGetter({
300293
reservableTimes,
301294
activeApplicationRounds,
@@ -307,9 +300,9 @@ export function EditStep0({
307300
: undefined,
308301
reservationsMinDaysBefore: reservationUnit.reservationsMinDaysBefore ?? 0,
309302
reservationsMaxDaysBefore: reservationUnit.reservationsMaxDaysBefore ?? 0,
310-
customValidation: (date) => isSlotFree(date),
303+
customValidation: isSlotFree,
311304
});
312-
}, [activeApplicationRounds, reservationUnit, isSlotFree, reservableTimes]);
305+
}, [activeApplicationRounds, reservationUnit, reservableTimes]);
313306

314307
// TODO submit should be completely unnecessary
315308
// just disable nextStep button if the form is invalid
@@ -318,15 +311,18 @@ export function EditStep0({
318311
if (!focusSlot?.start || !focusSlot?.end) {
319312
return;
320313
}
314+
const { start } = focusSlot;
315+
const isFree = isReservationUnitPaid(reservationUnit.pricings, start);
321316
const newReservation: PendingReservation = {
322317
begin: focusSlot.start.toISOString(),
323318
end: focusSlot.end.toISOString(),
324-
price: getReservationUnitPrice({
325-
reservationUnit,
326-
pricingDate: focusSlot?.start ? new Date(focusSlot.start) : undefined,
327-
minutes: 0,
328-
asNumeral: true,
329-
}),
319+
price: isFree
320+
? "0"
321+
: (getReservationUnitPrice({
322+
reservationUnit,
323+
pricingDate: focusSlot.start,
324+
minutes: 0,
325+
}) ?? undefined),
330326
};
331327

332328
const resUnit = getWithoutThisReservation(reservationUnit, reservation);

apps/ui/components/reservation/ReservationCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,12 @@ function ReservationCard({ reservation, type }: PropsT): JSX.Element {
210210
new Date(reservation.end),
211211
new Date(reservation.begin)
212212
),
213-
trailingZeros: true,
213+
trailingZeros: false,
214214
})
215215
: getReservationPrice(
216216
reservation.price ?? undefined,
217217
t("prices:priceFree"),
218+
false,
218219
i18n.language
219220
);
220221

apps/ui/components/reservation/ReservationInfoCard.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,14 @@ import styled from "styled-components";
77
import { getReservationPrice, formatters as getFormatters } from "common";
88
import { breakpoints } from "common/src/common/style";
99
import { H4, Strong } from "common/src/common/typography";
10-
import type { ReservationInfoCardFragment } from "@gql/gql-types";
11-
import { getReservationUnitPrice } from "@/modules/reservationUnit";
10+
import {
11+
ReservationStateChoice,
12+
type ReservationInfoCardFragment,
13+
} from "@gql/gql-types";
14+
import {
15+
getReservationUnitPrice,
16+
isReservationUnitPaid,
17+
} from "@/modules/reservationUnit";
1218
import {
1319
capitalize,
1420
formatDuration,
@@ -127,7 +133,7 @@ export function ReservationInfoCard({
127133
return null;
128134
}
129135

130-
const price: string | undefined =
136+
const price: string | null =
131137
begin &&
132138
(reservation?.state === "REQUIRES_HANDLING" ||
133139
shouldDisplayReservationUnitPrice)
@@ -140,18 +146,13 @@ export function ReservationInfoCard({
140146
: getReservationPrice(
141147
reservation?.price,
142148
t("prices:priceFree"),
143-
i18n.language,
144-
true
149+
true,
150+
i18n.language
145151
);
146152

147153
const shouldDisplayTaxPercentage: boolean =
148-
reservation.state === "REQUIRES_HANDLING" && begin
149-
? getReservationUnitPrice({
150-
reservationUnit,
151-
pricingDate: new Date(begin),
152-
minutes: 0,
153-
asNumeral: true,
154-
}) !== "0"
154+
reservation.state === ReservationStateChoice.RequiresHandling && begin
155+
? isReservationUnitPaid(reservationUnit.pricings, new Date(begin))
155156
: Number(reservation?.price) > 0;
156157

157158
const name = getTranslation(reservationUnit, "name");

apps/ui/components/search/SingleSearchReservationUnitCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import IconWithText from "../common/IconWithText";
1717
import { truncatedText } from "@/styles/util";
1818
import {
1919
getActivePricing,
20-
getPrice,
20+
getPriceString,
2121
getReservationUnitName,
2222
getUnitName,
2323
} from "@/modules/reservationUnit";
@@ -263,7 +263,7 @@ function ReservationUnitCard({ reservationUnit }: PropsT): JSX.Element {
263263
const unitName = getUnitName(reservationUnit.unit ?? undefined);
264264

265265
const pricing = getActivePricing(reservationUnit);
266-
const unitPrice = pricing != null ? getPrice({ pricing }) : undefined;
266+
const unitPrice = pricing != null ? getPriceString({ pricing }) : undefined;
267267

268268
const reservationUnitTypeName =
269269
reservationUnit.reservationUnitType != null

0 commit comments

Comments
 (0)