diff --git a/app/home/(user)/_components/compare-packages-modal.tsx b/app/home/(user)/_components/compare-packages-modal.tsx new file mode 100644 index 0000000..d830b45 --- /dev/null +++ b/app/home/(user)/_components/compare-packages-modal.tsx @@ -0,0 +1,204 @@ +import { JSX } from 'react'; + +import { QuestionMarkCircledIcon } from '@radix-ui/react-icons'; +import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; +import { Check, X } from 'lucide-react'; + +import { + Dialog, + DialogContent, + DialogTitle, + DialogTrigger, +} from '@kit/ui/dialog'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@kit/ui/table'; + +import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; +import { withI18n } from '~/lib/i18n/with-i18n'; + +import { PackageHeader } from '../../../../components/package-header'; +import { InfoTooltip } from '../../../../components/ui/info-tooltip'; + +const dummyCards = [ + { + titleKey: 'product:standard.label', + price: 40, + nrOfAnalyses: 4, + tagColor: 'bg-cyan', + }, + { + titleKey: 'product:standardPlus.label', + price: 85, + nrOfAnalyses: 10, + tagColor: 'bg-warning', + }, + { + titleKey: 'product:premium.label', + price: 140, + nrOfAnalyses: '12+', + tagColor: 'bg-purple', + }, +]; + +const dummyRows = [ + { + analysisNameKey: 'product:clinicalBloodDraw.label', + tooltipContentKey: 'product:clinicalBloodDraw.description', + includedInStandard: 1, + includedInStandardPlus: 1, + includedInPremium: 1, + }, + { + analysisNameKey: 'product:crp.label', + tooltipContentKey: 'product:crp.description', + includedInStandard: 1, + includedInStandardPlus: 1, + includedInPremium: 1, + }, + { + analysisNameKey: 'product:ferritin.label', + tooltipContentKey: 'product:ferritin.description', + includedInStandard: 0, + includedInStandardPlus: 1, + includedInPremium: 1, + }, + { + analysisNameKey: 'product:vitaminD.label', + tooltipContentKey: 'product:vitaminD.description', + includedInStandard: 0, + includedInStandardPlus: 1, + includedInPremium: 1, + }, + { + analysisNameKey: 'product:glucose.label', + tooltipContentKey: 'product:glucose.description', + includedInStandard: 1, + includedInStandardPlus: 1, + includedInPremium: 1, + }, + { + analysisNameKey: 'product:alat.label', + tooltipContentKey: 'product:alat.description', + includedInStandard: 1, + includedInStandardPlus: 1, + includedInPremium: 1, + }, + { + analysisNameKey: 'product:ast.label', + tooltipContentKey: 'product:ast.description', + includedInStandard: 1, + includedInStandardPlus: 1, + includedInPremium: 1, + }, +]; + +const CheckWithBackground = () => { + return ( +
+ +
+ ); +}; + +const ComparePackagesModal = async ({ + triggerElement, +}: { + triggerElement: JSX.Element; +}) => { + const { t, language } = await createI18nServerInstance(); + + return ( + + {triggerElement} + +

+ {t('common:close')} +

+ + + } + preventAutoFocus + > + + {t('common:comparePackages')} + +
+
+

{t('product:healthPackageComparison.label')}

+

+ {t('product:healthPackageComparison.description')} +

+
+ + + + + {dummyCards.map( + ({ titleKey, price, nrOfAnalyses, tagColor }) => ( + + + + ), + )} + + + + {dummyRows.map( + ( + { + analysisNameKey, + tooltipContentKey, + includedInStandard, + includedInStandardPlus, + includedInPremium, + }, + index, + ) => ( + + + {t(analysisNameKey)}{' '} + } + /> + + + {!!includedInStandard && } + + + {!!includedInStandardPlus && } + + + {!!includedInPremium && } + + + ), + )} + +
+
+
+
+
+
+ ); +}; + +export default withI18n(ComparePackagesModal); diff --git a/app/select-package/page.tsx b/app/select-package/page.tsx index 91871ea..6e1b52a 100644 --- a/app/select-package/page.tsx +++ b/app/select-package/page.tsx @@ -20,6 +20,7 @@ import { MedReportLogo } from '../../components/med-report-logo'; import { PackageHeader } from '../../components/package-header'; import { ButtonTooltip } from '../../components/ui/button-tooltip'; import pathsConfig from '../../config/paths.config'; +import ComparePackagesModal from '../home/(user)/_components/compare-packages-modal'; export const generateMetadata = async () => { const { t } = await createI18nServerInstance(); @@ -63,10 +64,14 @@ async function SelectPackagePage() {

{t('marketing:selectPackage')}

- + + {t('marketing:comparePackages')} + + + } + />
{dummyCards.map( diff --git a/components/package-header.tsx b/components/package-header.tsx index d2d0313..274d148 100644 --- a/components/package-header.tsx +++ b/components/package-header.tsx @@ -1,6 +1,6 @@ -import { formatCurrency } from "@kit/shared/utils"; -import { Badge } from "@kit/ui/badge"; -import { cn } from "@kit/ui/utils"; +import { formatCurrency } from '@kit/shared/utils'; +import { Badge } from '@kit/ui/badge'; +import { cn } from '@kit/ui/utils'; export const PackageHeader = ({ title, @@ -18,7 +18,6 @@ export const PackageHeader = ({ return (

{title}

- {analysesNr}

{formatCurrency({ currencyCode: 'eur', @@ -26,6 +25,7 @@ export const PackageHeader = ({ value: price, })}

+ {analysesNr}
); -}; \ No newline at end of file +}; diff --git a/components/ui/info-tooltip.tsx b/components/ui/info-tooltip.tsx index 7883844..b0f2ed4 100644 --- a/components/ui/info-tooltip.tsx +++ b/components/ui/info-tooltip.tsx @@ -1,13 +1,27 @@ -import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@kit/ui/tooltip"; -import { Info } from "lucide-react"; +import { JSX } from 'react'; -export function InfoTooltip({ content }: { content?: string }) { +import { Info } from 'lucide-react'; + +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@kit/ui/tooltip'; + +export function InfoTooltip({ + content, + icon, +}: { + content?: string; + icon?: JSX.Element; +}) { if (!content) return null; return ( - + {icon || } {content} diff --git a/package.json b/package.json index 45a1b03..d8242ea 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@marsidev/react-turnstile": "^1.1.0", "@nosecone/next": "1.0.0-beta.7", "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-visually-hidden": "^1.2.3", "@supabase/ssr": "^0.6.1", "@supabase/supabase-js": "2.49.4", "@tanstack/react-query": "5.76.1", diff --git a/packages/ui/src/makerkit/page.tsx b/packages/ui/src/makerkit/page.tsx index fa4bddd..3d823b1 100644 --- a/packages/ui/src/makerkit/page.tsx +++ b/packages/ui/src/makerkit/page.tsx @@ -75,7 +75,7 @@ function PageWithHeader(props: PageProps) { const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props); return ( -
+
= ({ className, ...props }) => ( -> = ({ className, children, ...props }) => ( + React.ComponentPropsWithoutRef & { + customClose?: React.JSX.Element; + preventAutoFocus?: boolean; + } +> = ({ className, children, customClose, preventAutoFocus, ...props }) => ( e.preventDefault() : props.onOpenAutoFocus + } + onCloseAutoFocus={ + preventAutoFocus ? (e) => e.preventDefault() : props.onOpenAutoFocus + } {...props} > {children} - - - Close + + {customClose || ( + <> + + Close + + )} ); + DialogContent.displayName = DialogPrimitive.Content.displayName; const DialogHeader = ({ diff --git a/packages/ui/src/shadcn/tooltip.tsx b/packages/ui/src/shadcn/tooltip.tsx index 1ab8c1f..606b9ef 100644 --- a/packages/ui/src/shadcn/tooltip.tsx +++ b/packages/ui/src/shadcn/tooltip.tsx @@ -6,8 +6,18 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip'; import { cn } from '../lib/utils'; -const TooltipProvider = TooltipPrimitive.Provider; - +function TooltipProvider({ + delayDuration = 0, + ...props +}: React.ComponentProps) { + return ( + + ); +} const Tooltip = TooltipPrimitive.Root; const TooltipTrigger = TooltipPrimitive.Trigger; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1837337..80b71bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -83,6 +83,9 @@ importers: '@radix-ui/react-icons': specifier: ^1.3.2 version: 1.3.2(react@19.1.0) + '@radix-ui/react-visually-hidden': + specifier: ^1.2.3 + version: 1.2.3(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@supabase/ssr': specifier: ^0.6.1 version: 0.6.1(@supabase/supabase-js@2.49.4) @@ -13116,7 +13119,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.0.3 + '@types/node': 22.15.32 merge-stream: 2.0.0 supports-color: 8.1.1 diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 550cb54..870bf33 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -17,6 +17,7 @@ "imageInputLabel": "Click here to upload an image", "cancel": "Cancel", "clear": "Clear", + "close": "Close", "notFound": "Not Found", "backToHomePage": "Back to Home Page", "goBack": "Go Back", @@ -59,6 +60,10 @@ "shoppingCart": "Shopping cart", "search": "Search{{end}}", "myActions": "My actions", + "healthPackageComparison": { + "label": "Health package comparison", + "description": "Alljärgnevalt on antud eelinfo (sugu, vanus ja kehamassiindeksi) põhjal tehtud personalne terviseauditi valik. Tabelis on võimalik soovitatud terviseuuringute paketile lisada üksikuid uuringuid juurde." + }, "routes": { "home": "Home", "overview": "Overview", diff --git a/public/locales/en/product.json b/public/locales/en/product.json index 72a305a..e2aaf81 100644 --- a/public/locales/en/product.json +++ b/public/locales/en/product.json @@ -11,5 +11,33 @@ "label": "Premium", "description": "Sobib, kui soovid lisaks peamistele tervisenäitajatele ülevaadet, kas organismis on olulisemaid vitamiine ja mineraalaineid piisavalt." }, - "nrOfAnalyses": "{{nr}} analyses" + "nrOfAnalyses": "{{nr}} analyses", + "clinicalBloodDraw": { + "label": "Kliiniline vereanalüüs", + "description": "Pending" + }, + "crp": { + "label": "C-reaktiivne valk (CRP)", + "description": "Pending" + }, + "ferritin": { + "label": "Ferritiin", + "description": "Pending" + }, + "vitaminD": { + "label": "D-vitamiin", + "description": "Pending" + }, + "glucose": { + "label": "Glükoos", + "description": "Pending" + }, + "alat": { + "label": "Alaniini aminotransferaas", + "description": "Pending" + }, + "ast": { + "label": "Aspartaadi aminotransferaas", + "description": "Pending" + } } \ No newline at end of file diff --git a/public/locales/et/common.json b/public/locales/et/common.json index a05a890..36da315 100644 --- a/public/locales/et/common.json +++ b/public/locales/et/common.json @@ -17,6 +17,7 @@ "imageInputLabel": "Click here to upload an image", "cancel": "Cancel", "clear": "Clear", + "close": "Sulge", "notFound": "Not Found", "backToHomePage": "Back to Home Page", "goBack": "Tagasi", @@ -59,6 +60,10 @@ "shoppingCart": "Ostukorv", "search": "Otsi{{end}}", "myActions": "Minu toimingud", + "healthPackageComparison": { + "label": "Tervisepakketide võrdlus", + "description": "Alljärgnevalt on antud eelinfo (sugu, vanus ja kehamassiindeksi) põhjal tehtud personalne terviseauditi valik. Tabelis on võimalik soovitatud terviseuuringute paketile lisada üksikuid uuringuid juurde." + }, "routes": { "home": "Home", "overview": "Ülevaade", diff --git a/public/locales/et/product.json b/public/locales/et/product.json index 52eeaa2..01876f9 100644 --- a/public/locales/et/product.json +++ b/public/locales/et/product.json @@ -11,5 +11,33 @@ "label": "Premium", "description": "Sobib, kui soovid lisaks peamistele tervisenäitajatele ülevaadet, kas organismis on olulisemaid vitamiine ja mineraalaineid piisavalt." }, - "nrOfAnalyses": "{{nr}} analüüsi" + "nrOfAnalyses": "{{nr}} analüüsi", + "clinicalBloodDraw": { + "label": "Kliiniline vereanalüüs", + "description": "Pending" + }, + "crp": { + "label": "C-reaktiivne valk (CRP)", + "description": "Pending" + }, + "ferritin": { + "label": "Ferritiin", + "description": "Pending" + }, + "vitaminD": { + "label": "D-vitamiin", + "description": "Pending" + }, + "glucose": { + "label": "Glükoos", + "description": "Pending" + }, + "alat": { + "label": "Alaniini aminotransferaas", + "description": "Pending" + }, + "ast": { + "label": "Aspartaadi aminotransferaas", + "description": "Pending" + } } \ No newline at end of file diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 64026ee..f71e765 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -17,6 +17,7 @@ "imageInputLabel": "Click here to upload an image", "cancel": "Cancel", "clear": "Clear", + "close": "Close", "notFound": "Not Found", "backToHomePage": "Back to Home Page", "goBack": "Go Back", @@ -59,6 +60,10 @@ "shoppingCart": "Shopping cart", "search": "Search{{end}}", "myActions": "My actions", + "healthPackageComparison": { + "label": "Health package comparison", + "description": "Alljärgnevalt on antud eelinfo (sugu, vanus ja kehamassiindeksi) põhjal tehtud personalne terviseauditi valik. Tabelis on võimalik soovitatud terviseuuringute paketile lisada üksikuid uuringuid juurde." + }, "routes": { "home": "Home", "overview": "Overview", diff --git a/public/locales/ru/product.json b/public/locales/ru/product.json index 72a305a..e2aaf81 100644 --- a/public/locales/ru/product.json +++ b/public/locales/ru/product.json @@ -11,5 +11,33 @@ "label": "Premium", "description": "Sobib, kui soovid lisaks peamistele tervisenäitajatele ülevaadet, kas organismis on olulisemaid vitamiine ja mineraalaineid piisavalt." }, - "nrOfAnalyses": "{{nr}} analyses" + "nrOfAnalyses": "{{nr}} analyses", + "clinicalBloodDraw": { + "label": "Kliiniline vereanalüüs", + "description": "Pending" + }, + "crp": { + "label": "C-reaktiivne valk (CRP)", + "description": "Pending" + }, + "ferritin": { + "label": "Ferritiin", + "description": "Pending" + }, + "vitaminD": { + "label": "D-vitamiin", + "description": "Pending" + }, + "glucose": { + "label": "Glükoos", + "description": "Pending" + }, + "alat": { + "label": "Alaniini aminotransferaas", + "description": "Pending" + }, + "ast": { + "label": "Aspartaadi aminotransferaas", + "description": "Pending" + } } \ No newline at end of file