MED-104: create booking view with categories
This commit is contained in:
@@ -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'} />}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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>(
|
||||||
|
|||||||
31
app/home/(user)/_lib/server/load-category.ts
Normal file
31
app/home/(user)/_lib/server/load-category.ts
Normal 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);
|
||||||
@@ -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' &&
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
Reference in New Issue
Block a user