add cart functionality for tto services

This commit is contained in:
Helena
2025-09-19 16:23:19 +03:00
parent 3c272505d6
commit b59148630a
26 changed files with 921 additions and 221 deletions

View File

@@ -15,7 +15,10 @@ import { toast } from '@kit/ui/sonner';
import { Trans } from '@kit/ui/trans';
import { cn } from '@kit/ui/utils';
import { updateReservationTime } from '~/lib/services/reservation.service';
import { createInitialReservationAction } from '../../_lib/server/actions';
import { EnrichedCartItem } from '../cart/types';
import { ServiceProvider, TimeSlot } from './booking.context';
import { useBooking } from './booking.provider';
@@ -32,7 +35,15 @@ const getServiceProviderTitle = (
const PAGE_SIZE = 7;
const TimeSlots = ({ countryCode }: { countryCode: string }) => {
const TimeSlots = ({
countryCode,
cartItem,
onComplete,
}: {
countryCode: string;
cartItem?: EnrichedCartItem;
onComplete?: () => void;
}) => {
const [currentPage, setCurrentPage] = useState(1);
const {
@@ -133,6 +144,9 @@ const TimeSlots = ({ countryCode }: { countryCode: string }) => {
booking.selectedLocationId ? booking.selectedLocationId : null,
comments,
).then(() => {
if (onComplete) {
onComplete();
}
router.push(pathsConfig.app.cart);
});
@@ -143,6 +157,49 @@ const TimeSlots = ({ countryCode }: { countryCode: string }) => {
});
};
const handleChangeTime = async (
timeSlot: TimeSlot,
reservationId: number,
cartId: string,
) => {
const syncedService = timeSlot.syncedService;
if (!syncedService) {
return toast.error(t('booking:serviceNotFound'));
}
const bookTimePromise = updateReservationTime(
reservationId,
timeSlot.StartTime,
Number(syncedService.id),
timeSlot.UserID,
timeSlot.SyncUserID,
booking.selectedLocationId ? booking.selectedLocationId : null,
cartId,
);
toast.promise(() => bookTimePromise, {
success: <Trans i18nKey={'booking:bookTimeSuccess'} />,
error: <Trans i18nKey={'booking:bookTimeError'} />,
loading: <Trans i18nKey={'booking:bookTimeLoading'} />,
});
if (onComplete) {
onComplete();
}
};
const handleTimeSelect = async (timeSlot: TimeSlot) => {
if (cartItem?.reservation.id) {
return handleChangeTime(
timeSlot,
cartItem.reservation.id,
cartItem.cart_id,
);
}
return handleBookTime(timeSlot);
};
return (
<div className="flex w-full flex-col gap-4">
<div className="flex h-full w-full flex-col gap-2 overflow-auto">
@@ -154,9 +211,12 @@ const TimeSlots = ({ countryCode }: { countryCode: string }) => {
);
const price =
booking.selectedService?.variants?.[0]?.calculated_price
?.calculated_amount;
?.calculated_amount ?? cartItem?.unit_price;
return (
<Card className="grid w-full xs:flex justify-center-safe gap-3 xs:justify-between p-4" key={index}>
<Card
className="xs:flex xs:justify-between grid w-full justify-center-safe gap-3 p-4"
key={index}
>
<div>
<span>{formatDateAndTime(timeSlot.StartTime.toString())}</span>
<div className="flex">
@@ -177,11 +237,9 @@ const TimeSlots = ({ countryCode }: { countryCode: string }) => {
)}
{isEHIF && <span>{t('booking:ehifBooking')}</span>}
</div>
<div className="flex text-xs">
{timeSlot.location?.address}
</div>
<div className="flex text-xs">{timeSlot.location?.address}</div>
</div>
<div className="flex-end flex items-center justify-between not-last:xs:justify-center gap-2">
<div className="flex-end not-last:xs:justify-center flex items-center justify-between gap-2">
<span className="text-sm font-semibold">
{formatCurrency({
currencyCode: 'EUR',
@@ -189,7 +247,7 @@ const TimeSlots = ({ countryCode }: { countryCode: string }) => {
value: price ?? '',
})}
</span>
<Button onClick={() => handleBookTime(timeSlot)} size="sm">
<Button onClick={() => handleTimeSelect(timeSlot)} size="sm">
<Trans i18nKey="common:book" />
</Button>
</div>