diff --git a/app/home/(user)/(dashboard)/booking/[handle]/page.tsx b/app/home/(user)/(dashboard)/booking/[handle]/page.tsx
index ebce187..a125346 100644
--- a/app/home/(user)/(dashboard)/booking/[handle]/page.tsx
+++ b/app/home/(user)/(dashboard)/booking/[handle]/page.tsx
@@ -2,12 +2,13 @@ import { HomeLayoutPageHeader } from '@/app/home/(user)/_components/home-page-he
import { loadCategory } from '@/app/home/(user)/_lib/server/load-category';
import { AppBreadcrumbs } from '@kit/ui/makerkit/app-breadcrumbs';
-import { PageBody } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
import { withI18n } from '~/lib/i18n/with-i18n';
+import BookingContainer from '../../../_components/booking/booking-container';
+
export const generateMetadata = async () => {
const i18n = await createI18nServerInstance();
const title = i18n.t('booking:title');
@@ -18,9 +19,13 @@ export const generateMetadata = async () => {
};
async function BookingHandlePage({ params }: { params: { handle: string } }) {
- const handle = await params.handle;
+ const { handle } = await params;
const { category } = await loadCategory({ handle });
+ if (!category) {
+ return
Category not found
;
+ }
+
return (
<>
}
- description={}
+ description=""
/>
-
+
>
);
}
diff --git a/app/home/(user)/_components/booking/booking-container.tsx b/app/home/(user)/_components/booking/booking-container.tsx
new file mode 100644
index 0000000..fb760fa
--- /dev/null
+++ b/app/home/(user)/_components/booking/booking-container.tsx
@@ -0,0 +1,31 @@
+'use client';
+
+import React from 'react';
+
+import { Calendar } from '@kit/ui/shadcn/calendar';
+import { Card } from '@kit/ui/shadcn/card';
+
+import { ServiceCategory } from '../service-categories';
+import { BookingProvider } from './booking.provider';
+import LocationSelector from './location-selector';
+import ServiceSelector from './service-selector';
+import TimeSlots from './time-slots';
+
+const BookingContainer = ({ category }: { category: ServiceCategory }) => {
+ return (
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+
+ );
+};
+
+export default BookingContainer;
diff --git a/app/home/(user)/_components/booking/booking.context.ts b/app/home/(user)/_components/booking/booking.context.ts
new file mode 100644
index 0000000..36d9035
--- /dev/null
+++ b/app/home/(user)/_components/booking/booking.context.ts
@@ -0,0 +1,18 @@
+import { createContext } from 'react';
+
+import { StoreProduct } from '@medusajs/types';
+import { noop } from 'lodash';
+
+const BookingContext = createContext<{
+ timeSlots: string[];
+ selectedService: StoreProduct | null;
+ setSelectedService: (selectedService: any) => void;
+ updateTimeSlots: (serviceId: number) => Promise;
+}>({
+ timeSlots: [],
+ selectedService: null,
+ setSelectedService: (_) => _,
+ updateTimeSlots: async (_) => noop(),
+});
+
+export { BookingContext };
diff --git a/app/home/(user)/_components/booking/booking.provider.tsx b/app/home/(user)/_components/booking/booking.provider.tsx
new file mode 100644
index 0000000..700ceee
--- /dev/null
+++ b/app/home/(user)/_components/booking/booking.provider.tsx
@@ -0,0 +1,47 @@
+import React, { useState } from 'react';
+
+import { StoreProduct } from '@medusajs/types';
+
+import { getAvailableAppointmentsForService } from '~/lib/services/connected-online.service';
+
+import { ServiceCategory } from '../service-categories';
+import { BookingContext } from './booking.context';
+
+export function useBooking() {
+ const context = React.useContext(BookingContext);
+
+ if (!context) {
+ throw new Error('useBooking must be used within a BookingProvider.');
+ }
+
+ return context;
+}
+
+export const BookingProvider: React.FC<{
+ children: React.ReactElement;
+ category: ServiceCategory;
+}> = ({ children, category }) => {
+ const [selectedService, setSelectedService] = useState(
+ category.products[0] || null,
+ );
+ const [timeSlots, setTimeSlots] = useState([]);
+
+ const updateTimeSlots = async (serviceId: number) => {
+ const response = await getAvailableAppointmentsForService(serviceId);
+ console.log('updateTimeSlots response', response);
+ // Fetch time slots based on the selected service ID
+ };
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/app/home/(user)/_components/booking/location-selector.tsx b/app/home/(user)/_components/booking/location-selector.tsx
new file mode 100644
index 0000000..e2e7de1
--- /dev/null
+++ b/app/home/(user)/_components/booking/location-selector.tsx
@@ -0,0 +1,9 @@
+import React from 'react';
+
+import { Card } from '@kit/ui/shadcn/card';
+
+const LocationSelector = () => {
+ return LocationSelector;
+};
+
+export default LocationSelector;
diff --git a/app/home/(user)/_components/booking/service-selector.tsx b/app/home/(user)/_components/booking/service-selector.tsx
new file mode 100644
index 0000000..557048e
--- /dev/null
+++ b/app/home/(user)/_components/booking/service-selector.tsx
@@ -0,0 +1,83 @@
+import React, { useState } from 'react';
+
+import { StoreProduct } from '@medusajs/types';
+import { ArrowUp, ChevronDown } from 'lucide-react';
+
+import { Button } from '@kit/ui/shadcn/button';
+import { Card } from '@kit/ui/shadcn/card';
+import { Label } from '@kit/ui/shadcn/label';
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from '@kit/ui/shadcn/popover';
+import { RadioGroup, RadioGroupItem } from '@kit/ui/shadcn/radio-group';
+
+import { useBooking } from './booking.provider';
+
+const ServiceSelector = ({ products }: { products: StoreProduct[] }) => {
+ const { selectedService, setSelectedService, updateTimeSlots } = useBooking();
+ const [collapsed, setCollapsed] = React.useState(false);
+ const [firstFourProducts, setFirstFourProducts] = useState(
+ products.slice(0, 4),
+ );
+
+ const onServiceSelect = async (productId: StoreProduct['id']) => {
+ const product = products.find((p) => p.id === productId);
+ setSelectedService(product);
+ setCollapsed(false);
+ await updateTimeSlots((product!.metadata!.serviceId as number) || 0);
+ };
+
+ console.log('selectedService', selectedService);
+ return (
+
+ Teenused
+
+
+
+ {firstFourProducts.map((product) => (
+
+
+
+
+ ))}
+
+
+ setCollapsed((_) => !_)}
+ className="flex cursor-pointer items-center justify-between border-t py-1"
+ >
+ Kuva kõik
+
+
+
+
+
+
+ {products.map((product) => (
+
+
+
+
+ ))}
+
+
+
+
+ );
+};
+
+export default ServiceSelector;
diff --git a/app/home/(user)/_components/booking/time-slots.tsx b/app/home/(user)/_components/booking/time-slots.tsx
new file mode 100644
index 0000000..5860e80
--- /dev/null
+++ b/app/home/(user)/_components/booking/time-slots.tsx
@@ -0,0 +1,96 @@
+import React from 'react';
+
+import { formatCurrency } from '@/packages/shared/src/utils';
+import { format } from 'date-fns';
+
+import { Button } from '@kit/ui/shadcn/button';
+import { Card } from '@kit/ui/shadcn/card';
+import { Trans } from '@kit/ui/trans';
+
+import { AvailableAppointmentsResponse } from '~/lib/types/connected-online';
+
+const dummyData: AvailableAppointmentsResponse['Data']['T_Booking'] = [
+ {
+ ServiceID: 1,
+ StartTime: new Date('2024-10-10T10:00:00Z'),
+ EndTime: new Date('2024-10-10T11:00:00Z'),
+ HKServiceID: 0,
+ ClinicID: '',
+ LocationID: 0,
+ UserID: 0,
+ SyncUserID: 0,
+ PayorCode: '',
+ },
+ {
+ ServiceID: 1,
+ StartTime: new Date('2024-10-10T11:00:00Z'),
+ EndTime: new Date('2024-10-10T12:00:00Z'),
+ HKServiceID: 0,
+ ClinicID: '',
+ LocationID: 0,
+ UserID: 0,
+ SyncUserID: 0,
+ PayorCode: '',
+ },
+ {
+ ServiceID: 2,
+ StartTime: new Date('2024-10-10T12:00:00Z'),
+ EndTime: new Date('2024-10-10T13:00:00Z'),
+ HKServiceID: 0,
+ ClinicID: '',
+ LocationID: 0,
+ UserID: 0,
+ SyncUserID: 0,
+ PayorCode: '',
+ },
+];
+
+const TimeSlots = () => {
+ return (
+
+ {dummyData.map((data) => (
+
+
+
{format(data.StartTime.toString(), 'HH:mm')}
+
+
+ Dr. Jüri Mardikas
+
+ Kardioloog
+ Tervisekassa aeg
+
+
+
+ Ülemiste Tervisemaja 2
+
+
+ Ülemiste füsioteraapiakliinik
+
+
+ Sepapaja 2/1
+
+ Tallinn
+
+
+
+
+ {formatCurrency({
+ currencyCode: 'EUR',
+ locale: 'et-EE',
+ value: 20,
+ })}
+
+
+
+
+ ))}
+
+ );
+};
+
+export default TimeSlots;
diff --git a/app/home/(user)/_components/service-categories.tsx b/app/home/(user)/_components/service-categories.tsx
index 9ef3e25..4e0aa20 100644
--- a/app/home/(user)/_components/service-categories.tsx
+++ b/app/home/(user)/_components/service-categories.tsx
@@ -4,17 +4,19 @@ import React from 'react';
import { redirect } from 'next/navigation';
-import { createPath, pathsConfig } from '@/packages/shared/src/config';
+import { pathsConfig } from '@/packages/shared/src/config';
+import { StoreProduct } from '@medusajs/types';
import { ComponentInstanceIcon } from '@radix-ui/react-icons';
import { cn } from '@kit/ui/shadcn';
-import { Card, CardDescription, CardTitle } from '@kit/ui/shadcn/card';
+import { Card, CardDescription } from '@kit/ui/shadcn/card';
export interface ServiceCategory {
name: string;
handle: string;
color: string;
description: string;
+ products: StoreProduct[];
}
const ServiceCategories = ({
diff --git a/app/home/(user)/_lib/server/load-category.ts b/app/home/(user)/_lib/server/load-category.ts
index 2c0479c..1a2514c 100644
--- a/app/home/(user)/_lib/server/load-category.ts
+++ b/app/home/(user)/_lib/server/load-category.ts
@@ -25,6 +25,7 @@ async function categoryLoader({
description: category?.description || '',
handle: category?.handle || '',
name: category?.name || '',
+ products: category?.products || [],
},
};
}
diff --git a/lib/services/connected-online.service.ts b/lib/services/connected-online.service.ts
index b0ad1f6..e0628cc 100644
--- a/lib/services/connected-online.service.ts
+++ b/lib/services/connected-online.service.ts
@@ -51,12 +51,12 @@ export async function getAvailableAppointmentsForService(
: `No booking times present in appointment availability response, service id: ${serviceId}, start time: ${startTime}`;
}
- await logRequestResult(
- ExternalApi.ConnectedOnline,
- ConnectedOnlineMethodName.GetAvailabilities,
- RequestStatus.Fail,
- comment,
- );
+ // await logRequestResult(
+ // ExternalApi.ConnectedOnline,
+ // ConnectedOnlineMethodName.GetAvailabilities,
+ // RequestStatus.Fail,
+ // comment,
+ // );
return null;
}
diff --git a/packages/ui/src/shadcn/radio-group.tsx b/packages/ui/src/shadcn/radio-group.tsx
index 7779e73..f98a019 100644
--- a/packages/ui/src/shadcn/radio-group.tsx
+++ b/packages/ui/src/shadcn/radio-group.tsx
@@ -25,12 +25,12 @@ const RadioGroupItem: React.FC<
return (
-
+