MED-104: create booking view with categories

This commit is contained in:
Danel Kungla
2025-08-28 14:11:54 +03:00
parent 31bc4b6cff
commit ad28352fc8
9 changed files with 72 additions and 18 deletions

View File

@@ -1,13 +1,13 @@
import { use } from 'react'; import { HomeLayoutPageHeader } from '@/app/home/(user)/_components/home-page-header';
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 { PageBody } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
import { withI18n } from '~/lib/i18n/with-i18n'; import { withI18n } from '~/lib/i18n/with-i18n';
import { HomeLayoutPageHeader } from '../../../_components/home-page-header';
export const generateMetadata = async () => { export const generateMetadata = async () => {
const i18n = await createI18nServerInstance(); const i18n = await createI18nServerInstance();
const title = i18n.t('booking:title'); const title = i18n.t('booking:title');
@@ -17,9 +17,17 @@ export const generateMetadata = async () => {
}; };
}; };
function BookingHandlePage() { async function BookingHandlePage({ params }: { params: { handle: string } }) {
const handle = await params.handle;
const { category } = await loadCategory({ handle });
return ( return (
<> <>
<AppBreadcrumbs
values={{
[handle]: category?.name || handle,
}}
/>
<HomeLayoutPageHeader <HomeLayoutPageHeader
title={<Trans i18nKey={'booking:title'} />} title={<Trans i18nKey={'booking:title'} />}
description={<Trans i18nKey={'booking:description'} />} description={<Trans i18nKey={'booking:description'} />}

View File

@@ -1,5 +1,6 @@
import { use } from 'react'; import { use } from 'react';
import { AppBreadcrumbs } from '@kit/ui/makerkit/app-breadcrumbs';
import { PageBody } from '@kit/ui/page'; import { PageBody } from '@kit/ui/page';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
@@ -22,15 +23,27 @@ export const generateMetadata = async () => {
function BookingPage() { function BookingPage() {
const { heroCategories, ttoCategories } = use(loadTtoServices()); const { heroCategories, ttoCategories } = use(loadTtoServices());
console.log('ttoCategories', heroCategories, ttoCategories);
if (!heroCategories.length && !ttoCategories.length) {
return (
<>
<AppBreadcrumbs />
<h3 className="mt-8">
<Trans i18nKey="booking:noCategories" />
</h3>
</>
);
}
return ( return (
<> <>
<AppBreadcrumbs />
<HomeLayoutPageHeader <HomeLayoutPageHeader
title={<Trans i18nKey={'booking:title'} />} title={<Trans i18nKey={'booking:title'} />}
description={<Trans i18nKey={'booking:description'} />} description={<Trans i18nKey={'booking:description'} />}
/> />
<PageBody> <PageBody className="space-y-2">
<OrderCards heroCategories={heroCategories} /> <OrderCards heroCategories={heroCategories} />
<ServiceCategories categories={ttoCategories} /> <ServiceCategories categories={ttoCategories} />
</PageBody> </PageBody>

View File

@@ -24,7 +24,7 @@ export default function OrderCards({
heroCategories: ServiceCategory[]; heroCategories: ServiceCategory[];
}) { }) {
return ( return (
<div className="mt-4 grid grid-cols-3 gap-6"> <div className="xs:grid-cols-3 mt-4 grid grid-cols-1 gap-2">
{heroCategories.map(({ name, description, color, handle }) => ( {heroCategories.map(({ name, description, color, handle }) => (
<Card <Card
key={name} key={name}

View File

@@ -23,7 +23,7 @@ const ServiceCategories = ({
categories: ServiceCategory[]; categories: ServiceCategory[];
}) => { }) => {
return ( return (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3"> <div className="grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3">
{categories.map((category, index) => ( {categories.map((category, index) => (
<Card <Card
key={index} key={index}

View File

@@ -42,7 +42,7 @@ async function analysesLoader() {
const serviceCategories = productCategories.filter( const serviceCategories = productCategories.filter(
({ parent_category }) => parent_category?.handle === 'tto-categories', ({ parent_category }) => parent_category?.handle === 'tto-categories',
); );
console.log('serviceCategories', serviceCategories);
return { return {
analyses: analyses:
category?.products?.map<OrderAnalysisCard>( category?.products?.map<OrderAnalysisCard>(

View File

@@ -0,0 +1,31 @@
import { cache } from 'react';
import { getProductCategories } from '@lib/data';
import { ServiceCategory } from '../../_components/service-categories';
async function categoryLoader({
handle,
}: {
handle: string;
}): Promise<{ category: ServiceCategory | null }> {
const response = await getProductCategories({
handle,
fields: '*products, is_active, metadata',
});
const category = response.product_categories[0];
return {
category: {
color:
typeof category?.metadata?.color === 'string'
? category?.metadata?.color
: 'primary',
description: category?.description || '',
handle: category?.handle || '',
name: category?.name || '',
},
};
}
export const loadCategory = cache(categoryLoader);

View File

@@ -8,7 +8,7 @@ async function ttoServicesLoader() {
const response = await getProductCategories({ const response = await getProductCategories({
fields: '*products, is_active, metadata', fields: '*products, is_active, metadata',
}); });
console.log('response.product_categories', response.product_categories);
const heroCategories = response.product_categories?.filter( const heroCategories = response.product_categories?.filter(
({ parent_category, is_active, metadata }) => ({ parent_category, is_active, metadata }) =>
parent_category?.handle === 'tto-categories' && parent_category?.handle === 'tto-categories' &&

View File

@@ -1,8 +1,9 @@
{ {
"title": "Vali teenus", "title": "Vali teenus",
"description": "Vali sobiv teenus või pakett vastavalt oma tervisemurele või -eesmärgile.", "description": "Vali sobiv teenus või pakett vastavalt oma tervisemurele või -eesmärgile.",
"analysisPackages": { "analysisPackages": {
"title": "Analüüside paketid", "title": "Analüüside paketid",
"description": "Tutvu personaalsete analüüsi pakettidega ja telli" "description": "Tutvu personaalsete analüüsi pakettidega ja telli"
} },
"noCategories": "Teenuste loetelu ei leitud, proovi hiljem uuesti"
} }

View File

@@ -80,7 +80,8 @@
"dashboard": "Ülevaade", "dashboard": "Ülevaade",
"settings": "Settings", "settings": "Settings",
"profile": "Profile", "profile": "Profile",
"application": "Application" "application": "Application",
"pickTime": "Vali aeg"
}, },
"roles": { "roles": {
"owner": { "owner": {