diff --git a/app/home/(user)/_components/dashboard.tsx b/app/home/(user)/_components/dashboard.tsx
new file mode 100644
index 0000000..f6cc187
--- /dev/null
+++ b/app/home/(user)/_components/dashboard.tsx
@@ -0,0 +1,237 @@
+'use client';
+
+import { InfoTooltip } from '@/components/ui/info-tooltip';
+import { toTitleCase } from '@/lib/utils';
+import { BlendingModeIcon, RulerHorizontalIcon } from '@radix-ui/react-icons';
+import {
+ Activity,
+ ChevronRight,
+ Clock9,
+ Droplets,
+ LineChart,
+ Pill,
+ Scale,
+ TrendingUp,
+ User,
+} from 'lucide-react';
+
+import { usePersonalAccountData } from '@kit/accounts/hooks/use-personal-account-data';
+import { useUserWorkspace } from '@kit/accounts/hooks/use-user-workspace';
+import { Button } from '@kit/ui/button';
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardProps,
+} from '@kit/ui/card';
+import { PageDescription } from '@kit/ui/page';
+import { Trans } from '@kit/ui/trans';
+import { cn } from '@kit/ui/utils';
+
+const dummyCards = [
+ {
+ title: 'dashboard:gender',
+ description: 'dashboard:male',
+ icon: ,
+ iconBg: 'bg-success',
+ },
+ {
+ title: 'dashboard:age',
+ description: '43',
+ icon: ,
+ iconBg: 'bg-success',
+ },
+ {
+ title: 'dashboard:height',
+ description: '183',
+ icon: ,
+ iconBg: 'bg-success',
+ },
+ {
+ title: 'dashboard:weight',
+ description: '92kg',
+ icon: ,
+ iconBg: 'bg-warning',
+ },
+ {
+ title: 'dashboard:bmi',
+ description: '27.5',
+ icon: ,
+ iconBg: 'bg-warning',
+ },
+ {
+ title: 'dashboard:bloodPressure',
+ description: '160/98',
+ icon: ,
+ iconBg: 'bg-warning',
+ },
+ {
+ title: 'dashboard:cholesterol',
+ description: '5',
+ icon: ,
+ iconBg: 'bg-destructive',
+ },
+ {
+ title: 'dashboard:ldlCholesterol',
+ description: '3,6',
+ icon: ,
+ iconBg: 'bg-warning',
+ },
+ {
+ title: 'Score 2',
+ description: 'Normis',
+ icon: ,
+ iconBg: 'bg-success',
+ },
+ {
+ title: 'dashboard:smoking',
+ description: 'dashboard:respondToQuestion',
+ descriptionColor: 'text-primary',
+ icon: (
+
+ ),
+ cardVariant: 'gradient-success' as CardProps['variant'],
+ },
+];
+
+const dummyRecommendations = [
+ {
+ icon: ,
+ color: 'bg-cyan/10 text-cyan',
+ title: 'Kolesterooli kontroll',
+ description: 'HDL-kolestrool',
+ tooltipContent: 'Selgitus',
+ price: '20,00 €',
+ buttonText: 'Telli',
+ },
+ {
+ icon: ,
+ color: 'bg-primary/10 text-primary',
+ title: 'Kolesterooli kontroll',
+ tooltipContent: 'Selgitus',
+ description: 'LDL-Kolesterool',
+ buttonText: 'Broneeri',
+ },
+ {
+ icon: ,
+ color: 'bg-destructive/10 text-destructive',
+ title: 'Vererõhu kontroll',
+ tooltipContent: 'Selgitus',
+ description: 'Score-Risk 2',
+ price: '20,00 €',
+ buttonText: 'Telli',
+ },
+];
+
+export default function Dashboard() {
+ const userWorkspace = useUserWorkspace();
+ const account = usePersonalAccountData(userWorkspace.user.id);
+
+ return (
+ <>
+
+
+
+ {account?.data?.name ? `, ${toTitleCase(account.data.name)}` : ''}
+
+
+ :
+
+
+
+ {dummyCards.map(
+ ({
+ title,
+ description,
+ icon,
+ iconBg,
+ cardVariant,
+ descriptionColor,
+ }) => (
+
+
+
+ {icon}
+
+
+
+
+
+
+
+
+
+
+
+ ),
+ )}
+
+
+
+
+
+
+
+
+ {dummyRecommendations.map(
+ (
+ {
+ icon,
+ color,
+ title,
+ description,
+ tooltipContent,
+ price,
+ buttonText,
+ },
+ index,
+ ) => {
+ return (
+
+
+
+ {icon}
+
+
+
+ {title}
+
+
+
+ {description}
+
+
+
+
+
{price}
+
+
+
+ );
+ },
+ )}
+
+
+ >
+ );
+}
diff --git a/app/home/(user)/_components/home-menu-navigation.tsx b/app/home/(user)/_components/home-menu-navigation.tsx
index d91e498..6f2db1a 100644
--- a/app/home/(user)/_components/home-menu-navigation.tsx
+++ b/app/home/(user)/_components/home-menu-navigation.tsx
@@ -1,65 +1,43 @@
-import {
- BorderedNavigationMenu,
- BorderedNavigationMenuItem,
-} from '@kit/ui/bordered-navigation-menu';
-import { If } from '@kit/ui/if';
+import { ShoppingCart } from 'lucide-react';
+
+import { Button } from '@kit/ui/button';
+import { Trans } from '@kit/ui/trans';
+import { cn } from '@kit/ui/utils';
import { AppLogo } from '~/components/app-logo';
import { ProfileAccountDropdownContainer } from '~/components/personal-account-dropdown-container';
-import featuresFlagConfig from '~/config/feature-flags.config';
-import { personalAccountNavigationConfig } from '~/config/personal-account-navigation.config';
+import { Search } from '~/components/ui/search';
+import { SIDEBAR_WIDTH } from '../../../../packages/ui/src/shadcn/constants';
// home imports
-import { HomeAccountSelector } from '../_components/home-account-selector';
import { UserNotifications } from '../_components/user-notifications';
import { type UserWorkspace } from '../_lib/server/load-user-workspace';
export function HomeMenuNavigation(props: { workspace: UserWorkspace }) {
- const { workspace, user, accounts } = props.workspace;
-
- const routes = personalAccountNavigationConfig.routes.reduce<
- Array<{
- path: string;
- label: string;
- Icon?: React.ReactNode;
- end?: boolean | ((path: string) => boolean);
- }>
- >((acc, item) => {
- if ('children' in item) {
- return [...acc, ...item.children];
- }
-
- if ('divider' in item) {
- return acc;
- }
-
- return [...acc, item];
- }, []);
+ const { workspace, user } = props.workspace;
return (
-
-
+
+
-
-
- {routes.map((route) => (
-
- ))}
-
+
}
+ />
-
+
diff --git a/app/home/(user)/_components/home-sidebar.tsx b/app/home/(user)/_components/home-sidebar.tsx
index e434119..e1e53b6 100644
--- a/app/home/(user)/_components/home-sidebar.tsx
+++ b/app/home/(user)/_components/home-sidebar.tsx
@@ -1,61 +1,29 @@
-import { If } from '@kit/ui/if';
import {
Sidebar,
SidebarContent,
- SidebarFooter,
SidebarHeader,
SidebarNavigation,
} from '@kit/ui/shadcn-sidebar';
-import { cn } from '@kit/ui/utils';
+import { Trans } from '@kit/ui/trans';
-import { AppLogo } from '~/components/app-logo';
-import { ProfileAccountDropdownContainer } from '~/components/personal-account-dropdown-container';
-import featuresFlagConfig from '~/config/feature-flags.config';
import { personalAccountNavigationConfig } from '~/config/personal-account-navigation.config';
-import { UserNotifications } from '~/home/(user)/_components/user-notifications';
-// home imports
-import type { UserWorkspace } from '../_lib/server/load-user-workspace';
-import { HomeAccountSelector } from './home-account-selector';
-
-interface HomeSidebarProps {
- workspace: UserWorkspace;
-}
-
-export function HomeSidebar(props: HomeSidebarProps) {
- const { workspace, user, accounts } = props.workspace;
+export function HomeSidebar() {
const collapsible = personalAccountNavigationConfig.sidebarCollapsedStyle;
return (
-
-
-
- }
- >
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
);
}
diff --git a/app/home/(user)/layout.tsx b/app/home/(user)/layout.tsx
index 6ede447..97f38ae 100644
--- a/app/home/(user)/layout.tsx
+++ b/app/home/(user)/layout.tsx
@@ -39,7 +39,7 @@ function SidebarLayout({ children }: React.PropsWithChildren) {
-
+
@@ -58,8 +58,8 @@ function HeaderLayout({ children }: React.PropsWithChildren) {
return (
-
-
+
+
@@ -67,7 +67,14 @@ function HeaderLayout({ children }: React.PropsWithChildren) {
- {children}
+
+
+
+
+
+ {children}
+
+
);
diff --git a/app/home/(user)/page.tsx b/app/home/(user)/page.tsx
index 3327e1f..cc64e11 100644
--- a/app/home/(user)/page.tsx
+++ b/app/home/(user)/page.tsx
@@ -4,6 +4,7 @@ import { Trans } from '@kit/ui/trans';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
import { withI18n } from '~/lib/i18n/with-i18n';
+import Dashboard from './_components/dashboard';
// local imports
import { HomeLayoutPageHeader } from './_components/home-page-header';
@@ -21,10 +22,12 @@ function UserHomePage() {
<>
}
- description={}
+ description={<>>}
/>
-
+
+
+
>
);
}
diff --git a/components/ui/info-tooltip.tsx b/components/ui/info-tooltip.tsx
new file mode 100644
index 0000000..7883844
--- /dev/null
+++ b/components/ui/info-tooltip.tsx
@@ -0,0 +1,16 @@
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@kit/ui/tooltip";
+import { Info } from "lucide-react";
+
+export function InfoTooltip({ content }: { content?: string }) {
+ if (!content) return null;
+ return (
+
+
+
+
+
+ {content}
+
+
+ );
+}
diff --git a/components/ui/search.tsx b/components/ui/search.tsx
new file mode 100644
index 0000000..84dac99
--- /dev/null
+++ b/components/ui/search.tsx
@@ -0,0 +1,33 @@
+import React, { JSX, ReactNode } from 'react';
+
+import { cn } from '@kit/ui/utils';
+
+export type SearchProps = React.InputHTMLAttributes & {
+ startElement?: string | JSX.Element;
+ className?: string;
+};
+
+const Search = React.forwardRef(
+ ({ className, startElement, ...props }, ref) => {
+ return (
+
+ {!!startElement && startElement}
+
+
+ );
+ },
+);
+
+Search.displayName = 'Search';
+
+export { Search };
diff --git a/config/paths.config.ts b/config/paths.config.ts
index 340e208..f4cce84 100644
--- a/config/paths.config.ts
+++ b/config/paths.config.ts
@@ -13,6 +13,12 @@ const PathsSchema = z.object({
}),
app: z.object({
home: z.string().min(1),
+ booking: z.string().min(1),
+ myOrders: z.string().min(1),
+ analysisResults: z.string().min(1),
+ orderAnalysisPackage: z.string().min(1),
+ orderAnalysis: z.string().min(1),
+ orderHealthAnalysis: z.string().min(1),
personalAccountSettings: z.string().min(1),
personalAccountBilling: z.string().min(1),
personalAccountBillingReturn: z.string().min(1),
@@ -47,6 +53,13 @@ const pathsConfig = PathsSchema.parse({
accountMembers: `/home/[account]/members`,
accountBillingReturn: `/home/[account]/billing/return`,
joinTeam: '/join',
+ // these routes are added as placeholders and can be changed when the pages are added
+ booking: '/booking',
+ myOrders: '/my-orders',
+ analysisResults: '/analysis-results',
+ orderAnalysisPackage: '/order-analysis-package',
+ orderAnalysis: '/order-analysis',
+ orderHealthAnalysis: '/order-health-analysis'
},
} satisfies z.infer);
diff --git a/config/personal-account-navigation.config.tsx b/config/personal-account-navigation.config.tsx
index d534f32..f52c78e 100644
--- a/config/personal-account-navigation.config.tsx
+++ b/config/personal-account-navigation.config.tsx
@@ -1,47 +1,72 @@
-import { CreditCard, Home, User } from 'lucide-react';
+import {
+ FileLineChart,
+ HeartPulse,
+ LineChart,
+ MousePointerClick,
+ ShoppingCart,
+ Stethoscope,
+ TestTube2,
+} from 'lucide-react';
import { z } from 'zod';
import { NavigationConfigSchema } from '@kit/ui/navigation-schema';
-import featureFlagsConfig from '~/config/feature-flags.config';
import pathsConfig from '~/config/paths.config';
-const iconClasses = 'w-4';
+const iconClasses = 'w-4 stroke-[1.5px]';
const routes = [
{
- label: 'common:routes.application',
children: [
{
- label: 'common:routes.home',
+ label: 'common:routes.overview',
path: pathsConfig.app.home,
- Icon: ,
+ Icon: ,
+ end: true,
+ },
+ {
+ label: 'common:routes.booking',
+ path: pathsConfig.app.booking,
+ Icon: ,
+ end: true,
+ },
+ {
+ label: 'common:routes.myOrders',
+ path: pathsConfig.app.myOrders,
+ Icon: ,
+ end: true,
+ },
+ {
+ label: 'common:routes.analysisResults',
+ path: pathsConfig.app.analysisResults,
+ Icon: ,
+ end: true,
+ },
+ {
+ label: 'common:routes.orderAnalysisPackage',
+ path: pathsConfig.app.orderAnalysisPackage,
+ Icon: ,
+ end: true,
+ },
+ {
+ label: 'common:routes.orderAnalysis',
+ path: pathsConfig.app.orderAnalysis,
+ Icon: ,
+ end: true,
+ },
+ {
+ label: 'common:routes.orderHealthAnalysis',
+ path: pathsConfig.app.orderHealthAnalysis,
+ Icon: ,
end: true,
},
],
},
- {
- label: 'common:routes.settings',
- children: [
- {
- label: 'common:routes.profile',
- path: pathsConfig.app.personalAccountSettings,
- Icon: ,
- },
- featureFlagsConfig.enablePersonalAccountBilling
- ? {
- label: 'common:routes.billing',
- path: pathsConfig.app.personalAccountBilling,
- Icon: ,
- }
- : undefined,
- ].filter((route) => !!route),
- },
] satisfies z.infer['routes'];
export const personalAccountNavigationConfig = NavigationConfigSchema.parse({
routes,
- style: process.env.NEXT_PUBLIC_USER_NAVIGATION_STYLE,
- sidebarCollapsed: process.env.NEXT_PUBLIC_HOME_SIDEBAR_COLLAPSED,
- sidebarCollapsedStyle: process.env.NEXT_PUBLIC_SIDEBAR_COLLAPSED_STYLE,
+ style: 'custom',
+ sidebarCollapsed: false,
+ sidebarCollapsedStyle: 'icon',
});
diff --git a/lib/i18n/i18n.settings.ts b/lib/i18n/i18n.settings.ts
index bb70925..78308fa 100644
--- a/lib/i18n/i18n.settings.ts
+++ b/lib/i18n/i18n.settings.ts
@@ -32,6 +32,7 @@ export const defaultI18nNamespaces = [
'teams',
'billing',
'marketing',
+ 'dashboard',
];
/**
diff --git a/lib/utils.ts b/lib/utils.ts
index 405dd01..1eb8901 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -1,5 +1,5 @@
-import { clsx, type ClassValue } from "clsx";
-import { twMerge } from "tailwind-merge";
+import { type ClassValue, clsx } from 'clsx';
+import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
@@ -9,3 +9,12 @@ export function toArray(input?: T | T[] | null): T[] {
if (!input) return [];
return Array.isArray(input) ? input : [input];
}
+
+export function toTitleCase(str?: string) {
+ if (!str) return '';
+ return str.replace(
+ /\w\S*/g,
+ (text: string) =>
+ text.charAt(0).toUpperCase() + text.substring(1).toLowerCase(),
+ );
+}
diff --git a/packages/features/notifications/src/components/notifications-popover.tsx b/packages/features/notifications/src/components/notifications-popover.tsx
index c2c0116..208351b 100644
--- a/packages/features/notifications/src/components/notifications-popover.tsx
+++ b/packages/features/notifications/src/components/notifications-popover.tsx
@@ -121,12 +121,12 @@ export function NotificationsPopover(params: {
return (
-