Merge pull request #52 from MR-medreport/MED-105-v3

feat(MED-123): update "order analysis" page
This commit is contained in:
2025-08-18 14:14:45 +03:00
committed by GitHub
9 changed files with 137 additions and 35 deletions

View File

@@ -5,6 +5,8 @@ import { Trans } from '@kit/ui/trans';
import { HomeLayoutPageHeader } from '../../_components/home-page-header';
import { loadAnalyses } from '../../_lib/server/load-analyses';
import OrderAnalysesCards from '../../_components/order-analyses-cards';
import { createPageViewLog, PAGE_VIEW_ACTION } from '~/lib/services/audit/pageView.service';
import { loadCurrentUserAccount } from '../../_lib/server/load-user-account';
export const generateMetadata = async () => {
const { t } = await createI18nServerInstance();
@@ -15,8 +17,18 @@ export const generateMetadata = async () => {
};
async function OrderAnalysisPage() {
const account = await loadCurrentUserAccount();
if (!account) {
throw new Error('Account not found');
}
const { analyses, countryCode } = await loadAnalyses();
await createPageViewLog({
accountId: account.id,
action: PAGE_VIEW_ACTION.VIEW_ORDER_ANALYSIS,
});
return (
<>
<HomeLayoutPageHeader

View File

@@ -8,6 +8,7 @@ import { toTitleCase } from '@/lib/utils';
import Dashboard from '../_components/dashboard';
import { loadCurrentUserAccount } from '../_lib/server/load-user-account';
import DashboardCards from '../_components/dashboard-cards';
export const generateMetadata = async () => {
const i18n = await createI18nServerInstance();
@@ -26,6 +27,7 @@ async function UserHomePage() {
return (
<>
<DashboardCards />
<PageHeader title={
<>
<Trans i18nKey={'common:welcome'} />

View File

@@ -0,0 +1,45 @@
import { Trans } from '@kit/ui/trans';
import {
Card,
CardHeader,
CardDescription,
CardFooter,
} from '@kit/ui/card';
import Link from 'next/link';
import { Button } from '@kit/ui/button';
import { ChevronRight, HeartPulse } from 'lucide-react';
export default function DashboardCards() {
return (
<div className='flex gap-4 lg:px-4'>
<Card
variant="gradient-success"
className="flex flex-col justify-between"
>
<CardHeader className="flex-row">
<div
className={'flex size-8 items-center-safe justify-center-safe rounded-full text-white bg-primary\/10 mb-6'}
>
<HeartPulse className="size-4 fill-green-500" />
</div>
<div className='ml-auto flex size-8 items-center-safe justify-center-safe rounded-full text-white bg-warning'>
<Link href='/home/order-analysis'>
<Button size="icon" variant="outline" className="px-2 text-black">
<ChevronRight className="size-4 stroke-2" />
</Button>
</Link>
</div>
</CardHeader>
<CardFooter className="flex flex-col items-start gap-2">
<h5>
<Trans i18nKey='dashboard:heroCard.orderAnalysis.title' />
</h5>
<CardDescription className="text-primary">
<Trans i18nKey='dashboard:heroCard.orderAnalysis.description' />
</CardDescription>
</CardFooter>
</Card>
</div>
);
}

View File

@@ -7,11 +7,14 @@ import {
Card,
CardHeader,
CardFooter,
CardDescription,
} from '@kit/ui/card';
import { StoreProduct, StoreProductVariant } from '@medusajs/types';
import { useState } from 'react';
import { handleAddToCart } from '~/lib/services/medusaCart.service';
import { useRouter } from 'next/navigation';
import { InfoTooltip } from '~/components/ui/info-tooltip';
import { Trans } from '@kit/ui/trans';
export default function OrderAnalysesCards({
analyses,
@@ -21,7 +24,7 @@ export default function OrderAnalysesCards({
countryCode: string;
}) {
const router = useRouter();
const [isAddingToCart, setIsAddingToCart] = useState(false);
const handleSelect = async (selectedVariant: StoreProductVariant) => {
if (!selectedVariant?.id || isAddingToCart) return null
@@ -44,37 +47,62 @@ export default function OrderAnalysesCards({
<div className="grid grid-cols-3 gap-6 mt-4">
{analyses.map(({
title,
variants
}) => (
<Card
key={title}
variant="gradient-success"
className="flex flex-col justify-between"
>
<CardHeader className="items-end-safe">
<div className='flex size-8 items-center-safe justify-center-safe rounded-full text-white bg-warning'>
<Button
size="icon"
variant="outline"
className="px-2 text-black"
onClick={() => handleSelect(variants![0]!)}
variants,
description,
subtitle,
status,
metadata,
}) => {
const isAvailable = status === 'published' && !!metadata?.analysisIdOriginal;
return (
<Card
key={title}
variant={isAvailable ? "gradient-success" : "gradient-warning"}
className="flex flex-col justify-between"
>
<CardHeader className="flex-row">
<div
className={'flex size-8 items-center-safe justify-center-safe rounded-full text-white bg-primary\/10 mb-6'}
>
{isAddingToCart ? <Loader2 className="size-4 stroke-2 animate-spin" /> : <ShoppingCart className="size-4 stroke-2" />}
</Button>
</div>
</CardHeader>
<CardFooter className="flex flex-col items-start gap-2">
<div
className={'flex size-8 items-center-safe justify-center-safe rounded-full text-white bg-primary\/10 mb-6'}
>
<HeartPulse className="size-4 fill-green-500" />
</div>
<h5>
{title}
</h5>
</CardFooter>
</Card>
))}
<HeartPulse className="size-4 fill-green-500" />
</div>
{isAvailable && (
<div className='ml-auto flex size-8 items-center-safe justify-center-safe rounded-full text-white bg-warning'>
<Button
size="icon"
variant="outline"
className="px-2 text-black"
onClick={() => handleSelect(variants![0]!)}
>
{isAddingToCart ? <Loader2 className="size-4 stroke-2 animate-spin" /> : <ShoppingCart className="size-4 stroke-2" />}
</Button>
</div>
)}
</CardHeader>
<CardFooter className="flex flex-col items-start gap-2">
<h5>
{title}
{description && (
<>
{' '}
<InfoTooltip content={`${description}`} />
</>
)}
</h5>
{isAvailable && subtitle && (
<CardDescription>
{subtitle}
</CardDescription>
)}
{!isAvailable && (
<CardDescription>
<Trans i18nKey={'order-analysis:analysisNotAvailable'} />
</CardDescription>
)}
</CardFooter>
</Card>
);
})}
</div>
);
}

View File

@@ -3,6 +3,7 @@ import { getSupabaseServerClient } from '@kit/supabase/server-client';
export enum PAGE_VIEW_ACTION {
VIEW_ANALYSIS_RESULTS = 'VIEW_ANALYSIS_RESULTS',
REGISTRATION_SUCCESS = 'REGISTRATION_SUCCESS',
VIEW_ORDER_ANALYSIS = 'VIEW_ORDER_ANALYSIS',
}
export const createPageViewLog = async ({

View File

@@ -12,5 +12,11 @@
"cholesterol": "Cholesterol",
"ldlCholesterol": "LDL Cholesterol",
"smoking": "Smoking",
"recommendedForYou": "Recommended for you"
"recommendedForYou": "Recommended for you",
"heroCard": {
"orderAnalysis": {
"title": "Order analysis",
"description": "Select an analysis to get started"
}
}
}

View File

@@ -1,4 +1,5 @@
{
"title": "Select analysis",
"description": "Select the analysis that suits your needs"
"description": "Select the analysis that suits your needs",
"analysisNotAvailable": "Analysis is not available currently"
}

View File

@@ -12,5 +12,11 @@
"cholesterol": "Kolesterool",
"ldlCholesterol": "LDL kolesterool",
"smoking": "Suitsetamine",
"recommendedForYou": "Soovitused sulle"
"recommendedForYou": "Soovitused sulle",
"heroCard": {
"orderAnalysis": {
"title": "Telli analüüs",
"description": "Telli endale sobiv analüüs"
}
}
}

View File

@@ -1,4 +1,5 @@
{
"title": "Vali analüüs",
"description": "Vali enda vajadustele sobiv analüüs"
"description": "Vali enda vajadustele sobiv analüüs",
"analysisNotAvailable": "Analüüsi tellimine ei ole hetkel saadaval"
}