From c48a4b482f233d8e513ac564f63f9efad7d5c3e4 Mon Sep 17 00:00:00 2001 From: Danel Kungla Date: Mon, 18 Aug 2025 14:54:46 +0300 Subject: [PATCH 1/3] feat(dashboard): add dynamic loading for dashboard component feat(team-account-benefit-statistics): implement benefit statistics card with budget and booking details feat(team-account-health-details): create health details component displaying account health metrics feat(team-account-statistics): develop team account statistics page with charts and customer table feat(load-team-account-health-details): add server-side function to retrieve account health details chore(migrations): create trigger for logging changes in account memberships --- .../{dashboard-demo.tsx => dashboard.tsx} | 2 +- .../team-account-benefit-statistics.tsx | 128 ++++++++++++ .../team-account-health-details.tsx | 34 ++++ .../team-account-layout-page-header.tsx | 9 +- .../team-account-layout-sidebar.tsx | 11 +- ...charts.tsx => team-account-statistics.tsx} | 184 ++++++++---------- .../load-team-account-health-details.ts | 69 +++++++ app/home/[account]/page.tsx | 23 ++- .../personal-account-dropdown-container.tsx | 4 +- config/team-account-navigation.config.tsx | 2 +- packages/ui/src/shadcn/card.tsx | 1 + public/locales/en/account.json | 2 +- public/locales/en/teams.json | 2 +- public/locales/et/common.json | 4 +- public/locales/et/teams.json | 10 +- .../20250818111200_team_account.sql | 2 + 16 files changed, 362 insertions(+), 125 deletions(-) rename app/home/[account]/_components/{dashboard-demo.tsx => dashboard.tsx} (77%) create mode 100644 app/home/[account]/_components/team-account-benefit-statistics.tsx create mode 100644 app/home/[account]/_components/team-account-health-details.tsx rename app/home/[account]/_components/{dashboard-demo-charts.tsx => team-account-statistics.tsx} (88%) create mode 100644 app/home/[account]/_lib/server/load-team-account-health-details.ts create mode 100644 supabase/migrations/20250818111200_team_account.sql diff --git a/app/home/[account]/_components/dashboard-demo.tsx b/app/home/[account]/_components/dashboard.tsx similarity index 77% rename from app/home/[account]/_components/dashboard-demo.tsx rename to app/home/[account]/_components/dashboard.tsx index 63528f4..67208ba 100644 --- a/app/home/[account]/_components/dashboard-demo.tsx +++ b/app/home/[account]/_components/dashboard.tsx @@ -4,7 +4,7 @@ import dynamic from 'next/dynamic'; import { LoadingOverlay } from '@kit/ui/loading-overlay'; -export const DashboardDemo = dynamic(() => import('./dashboard-demo-charts'), { +export const Dashboard = dynamic(() => import('./team-account-statistics'), { ssr: false, loading: () => ( { + return {children}; +}; + +const StatisticsCardTitle = ({ children }: { children: React.ReactNode }) => { + return {children}; +}; + +const StatisticsDescription = ({ children }: { children: React.ReactNode }) => { + return

{children}

; +}; + +const StatisticsValue = ({ children }: { children: React.ReactNode }) => { + return

{children}

; +}; + +const TeamAccountBenefitStatistics = ({ + accountSlug, +}: TeamAccountBenefitStatisticsProps) => { + const { + i18n: { language }, + } = useTranslation(); + + return ( +
+ +
+ +
+ +
+

+ +

+

+ +

+ + + +
+
+ +
+ + Analüüsid + 18 % + 36 broneeringut + + + Eriarstid ja spetsialistid + 22 % + 44 broneeringut + + + Uuringud + 20 % + 40 broneeringut + + + E-konsultatsioon + 17 % + 34 broneeringut + + + Terviseuuringute paketid +
+
+ 23 % + 46 teenuse kasutust +
+
+ 1800 € + Teenuste summa +
+
+
+
+
+ ); +}; + +export default TeamAccountBenefitStatistics; diff --git a/app/home/[account]/_components/team-account-health-details.tsx b/app/home/[account]/_components/team-account-health-details.tsx new file mode 100644 index 0000000..9e599cf --- /dev/null +++ b/app/home/[account]/_components/team-account-health-details.tsx @@ -0,0 +1,34 @@ +import React from 'react'; + +import { Card } from '@kit/ui/card'; +import { cn } from '@kit/ui/utils'; + +import { + NormStatus, + getAccountHealthDetailsFields, +} from '../_lib/server/load-team-account-health-details'; + +const TeamAccountHealthDetails = () => { + const accountHealthDetailsFields = getAccountHealthDetailsFields(); + return ( +
+ {accountHealthDetailsFields.map(({ title, Icon, value, normStatus }) => ( + +
+ +
+
{title}
+ {value} +
+ ))} +
+ ); +}; + +export default TeamAccountHealthDetails; diff --git a/app/home/[account]/_components/team-account-layout-page-header.tsx b/app/home/[account]/_components/team-account-layout-page-header.tsx index cecd62b..7aac363 100644 --- a/app/home/[account]/_components/team-account-layout-page-header.tsx +++ b/app/home/[account]/_components/team-account-layout-page-header.tsx @@ -2,12 +2,13 @@ import { PageHeader } from '@kit/ui/page'; export function TeamAccountLayoutPageHeader( props: React.PropsWithChildren<{ - title: string | React.ReactNode; - description: string | React.ReactNode; - account: string; + title?: string | React.ReactNode; + description?: string | React.ReactNode; }>, ) { return ( - {props.children} + + {props.children} + ); } diff --git a/app/home/[account]/_components/team-account-layout-sidebar.tsx b/app/home/[account]/_components/team-account-layout-sidebar.tsx index 8b3c385..8f53ef4 100644 --- a/app/home/[account]/_components/team-account-layout-sidebar.tsx +++ b/app/home/[account]/_components/team-account-layout-sidebar.tsx @@ -50,15 +50,15 @@ function SidebarContainer(props: { return ( - -
+ +
-
+
- + diff --git a/app/home/[account]/_components/dashboard-demo-charts.tsx b/app/home/[account]/_components/team-account-statistics.tsx similarity index 88% rename from app/home/[account]/_components/dashboard-demo-charts.tsx rename to app/home/[account]/_components/team-account-statistics.tsx index 436853b..4dac5ae 100644 --- a/app/home/[account]/_components/dashboard-demo-charts.tsx +++ b/app/home/[account]/_components/team-account-statistics.tsx @@ -1,8 +1,19 @@ 'use client'; -import { useMemo, useState } from 'react'; +import { use, useMemo, useState } from 'react'; -import { ArrowDown, ArrowUp, Menu, TrendingUp } from 'lucide-react'; +import { redirect } from 'next/navigation'; + +import { Database } from '@/packages/supabase/src/database.types'; +import { + ArrowDown, + ArrowUp, + ChevronRight, + Euro, + Menu, + TrendingUp, + User, +} from 'lucide-react'; import { Area, AreaChart, @@ -38,7 +49,20 @@ import { TableRow, } from '@kit/ui/table'; -export default function DashboardDemo() { +import pathsConfig from '~/config/paths.config'; +import { createPath } from '~/config/team-account-navigation.config'; + +import { loadCurrentUserAccount } from '../../(user)/_lib/server/load-user-account'; +import TeamAccountBenefitStatistics from './team-account-benefit-statistics'; +import TeamAccountHealthDetails from './team-account-health-details'; + +interface TeamAccountStatisticsProps { + teamAccount: Database['medreport']['Tables']['accounts']['Row']; +} + +export default function TeamAccountStatistics({ + teamAccount, +}: TeamAccountStatisticsProps) { const mrr = useMemo(() => generateDemoData(), []); const netRevenue = useMemo(() => generateDemoData(), []); const fees = useMemo(() => generateDemoData(), []); @@ -50,111 +74,67 @@ export default function DashboardDemo() { 'animate-in fade-in flex flex-col space-y-4 pb-36 duration-500' } > -
- - - - MRR - 20% - + - - Monthly recurring revenue - +
Ettevõtte terviseandmed
+
+ -
-
{`$${mrr[1]}`}
+
+ + redirect( + createPath( + pathsConfig.app.accountMembers, + teamAccount.slug || '', + ), + ) + } + > +
+
+ +
+
+ +
+ + Halda töötajaid + +

+ Lisa, muuda või eemalda töötajaid. +

- +
- - - - - - - - - Revenue - 12% - - - - Total revenue including fees - - -
-
{`$${netRevenue[1]}`}
+ + redirect( + createPath( + pathsConfig.app.accountBilling, + teamAccount.slug || '', + ), + ) + } + > +
+
- - - - - -
- - - - - Fees - 9% - - - - Total fees collected - - -
-
{`$${fees[1]}`}
+
+
- - - - - - - - - - - New Customers - -25% - - - - Customers who signed up this month - - -
-
{`${Number(newCustomers[1]).toFixed(0)}`}
-
-
- - - - -
-
- - - - - -
- - - Best Customers - Showing the top customers by MRR - - - - - - + + Halda eelarvet + +

+ Vali kuidas soovid eelarvet töötajate vahel jagada. +

+ +
); diff --git a/app/home/[account]/_lib/server/load-team-account-health-details.ts b/app/home/[account]/_lib/server/load-team-account-health-details.ts new file mode 100644 index 0000000..18fb787 --- /dev/null +++ b/app/home/[account]/_lib/server/load-team-account-health-details.ts @@ -0,0 +1,69 @@ +import React from 'react'; + +import { Clock, TrendingUp, User } from 'lucide-react'; + +interface AccountHealthDetailsField { + title: string; + value: string; + Icon: React.ComponentType<{ + size?: number; + color?: string; + className?: string; + }>; + normStatus: NormStatus; +} + +export enum NormStatus { + CRITICAL = 'CRITICAL', + WARNING = 'WARNING', + NORMAL = 'NORMAL', +} + +export const getAccountHealthDetailsFields = + (): AccountHealthDetailsField[] => { + const test = ''; + return [ + { + title: 'Naised', + value: '50% (16)', + Icon: User, + normStatus: NormStatus.NORMAL, + }, + { + title: 'Mehed', + value: '50% (16)', + Icon: User, + normStatus: NormStatus.NORMAL, + }, + { + title: 'Keskmine vanus', + value: '56', + Icon: Clock, + normStatus: NormStatus.NORMAL, + }, + { + title: 'KMI', + value: '271', + Icon: TrendingUp, + normStatus: NormStatus.WARNING, + }, + { + title: 'Üldkolesterool', + value: '6.1', + Icon: TrendingUp, + normStatus: NormStatus.WARNING, + }, + { + title: 'Vitamiin D', + value: '76', + Icon: TrendingUp, + normStatus: NormStatus.NORMAL, + }, + { + title: 'Suitsetajad', + value: '22%', + Icon: TrendingUp, + normStatus: NormStatus.CRITICAL, + }, + ]; + }; diff --git a/app/home/[account]/page.tsx b/app/home/[account]/page.tsx index ad389bf..e76b6f7 100644 --- a/app/home/[account]/page.tsx +++ b/app/home/[account]/page.tsx @@ -1,15 +1,18 @@ +'use server'; + import { use } from 'react'; import { CompanyGuard } from '@/packages/features/team-accounts/src/components'; +import { createTeamAccountsApi } from '@/packages/features/team-accounts/src/server/api'; +import { getSupabaseServerClient } from '@/packages/supabase/src/clients/server-client'; -import { AppBreadcrumbs } from '@kit/ui/app-breadcrumbs'; import { PageBody } from '@kit/ui/page'; import { Trans } from '@kit/ui/trans'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; -import { DashboardDemo } from './_components/dashboard-demo'; +import { Dashboard } from './_components/dashboard'; import { TeamAccountLayoutPageHeader } from './_components/team-account-layout-page-header'; interface TeamAccountHomePageProps { @@ -27,17 +30,23 @@ export const generateMetadata = async () => { function TeamAccountHomePage({ params }: TeamAccountHomePageProps) { const account = use(params).account; - console.log('TeamAccountHomePage account', account); + const client = getSupabaseServerClient(); + const api = createTeamAccountsApi(client); + const teamAccount = use(api.getTeamAccount(account)); + console.log('teamAccount', teamAccount); return ( <> } - description={} + title={ + + } /> - + ); diff --git a/components/personal-account-dropdown-container.tsx b/components/personal-account-dropdown-container.tsx index 52e8e5c..ce0d76b 100644 --- a/components/personal-account-dropdown-container.tsx +++ b/components/personal-account-dropdown-container.tsx @@ -13,7 +13,7 @@ const paths = { home: pathsConfig.app.home, admin: pathsConfig.app.admin, doctor: pathsConfig.app.doctor, - personalAccountSettings: pathsConfig.app.personalAccountSettings + personalAccountSettings: pathsConfig.app.personalAccountSettings, }; const features = { @@ -28,11 +28,13 @@ export function ProfileAccountDropdownContainer(props: { id: string | null; name: string | null; picture_url: string | null; + application_role: string; }; accounts: { label: string | null; value: string | null; image?: string | null; + application_role: string; }[]; }) { const signOut = useSignOut(); diff --git a/config/team-account-navigation.config.tsx b/config/team-account-navigation.config.tsx index 1f5bdba..b3a7c6b 100644 --- a/config/team-account-navigation.config.tsx +++ b/config/team-account-navigation.config.tsx @@ -53,6 +53,6 @@ export function getTeamAccountSidebarConfig(account: string) { }); } -function createPath(path: string, account: string) { +export function createPath(path: string, account: string) { return path.replace('[account]', account); } diff --git a/packages/ui/src/shadcn/card.tsx b/packages/ui/src/shadcn/card.tsx index 25a7eef..fec5a6b 100644 --- a/packages/ui/src/shadcn/card.tsx +++ b/packages/ui/src/shadcn/card.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { VariantProps, cva } from 'class-variance-authority'; + import { cn } from '.'; const cardVariants = cva('text-card-foreground rounded-xl border', { diff --git a/public/locales/en/account.json b/public/locales/en/account.json index 43ecce4..2939d6f 100644 --- a/public/locales/en/account.json +++ b/public/locales/en/account.json @@ -126,4 +126,4 @@ "updateRoleSuccess": "Role updated", "updateRoleError": "Something went wrong, please try again", "updateRoleLoading": "Updating role..." -} \ No newline at end of file +} diff --git a/public/locales/en/teams.json b/public/locales/en/teams.json index 6a683e2..2c26931 100644 --- a/public/locales/en/teams.json +++ b/public/locales/en/teams.json @@ -1,6 +1,6 @@ { "home": { - "pageTitle": "Home" + "pageTitle": "Dashboard" }, "settings": { "pageTitle": "Settings", diff --git a/public/locales/et/common.json b/public/locales/et/common.json index a259c6a..4c2473a 100644 --- a/public/locales/et/common.json +++ b/public/locales/et/common.json @@ -77,7 +77,7 @@ "account": "Account", "members": "Members", "billing": "Billing", - "dashboard": "Dashboard", + "dashboard": "Ülevaade", "settings": "Settings", "profile": "Profile", "application": "Application" @@ -129,4 +129,4 @@ "expiredAt": "Kehtiv kuni {{expiredAt}}" }, "doctor": "Arst" -} \ No newline at end of file +} diff --git a/public/locales/et/teams.json b/public/locales/et/teams.json index 3953e7f..66a8f74 100644 --- a/public/locales/et/teams.json +++ b/public/locales/et/teams.json @@ -1,6 +1,7 @@ { "home": { - "pageTitle": "Home" + "pageTitle": "Ülevaade", + "headerTitle": "{{companyName}} tervise ülevaade" }, "settings": { "pageTitle": "Settings", @@ -18,6 +19,13 @@ "billing": { "pageTitle": "Billing" }, + "benefitStatistics": { + "budget": { + "title": "Ettevõtte Tervisekassa seis", + "balance": "Eelarve jääk {{balance}}", + "volume": "Eelarve maht {{volume}}" + } + }, "yourTeams": "Your Companies ({{teamsCount}})", "createTeam": "Create a Company", "creatingTeam": "Creating Company...", diff --git a/supabase/migrations/20250818111200_team_account.sql b/supabase/migrations/20250818111200_team_account.sql new file mode 100644 index 0000000..56ab1ae --- /dev/null +++ b/supabase/migrations/20250818111200_team_account.sql @@ -0,0 +1,2 @@ +CREATE TRIGGER log_account_change AFTER DELETE OR UPDATE ON medreport.accounts_memberships FOR EACH ROW EXECUTE FUNCTION audit.log_audit_changes(); + From 937f3e4a71d9140e29550f6a04d1bad3b526f0b9 Mon Sep 17 00:00:00 2001 From: Danel Kungla Date: Mon, 18 Aug 2025 15:59:59 +0300 Subject: [PATCH 2/3] feat(account): refactor team account retrieval and update SQL function for workspace --- app/home/[account]/page.tsx | 2 +- lib/services/account.service.ts | 10 ++-- packages/supabase/src/database.types.ts | 4 +- ...00_mismatch_team_account_workspace_fix.sql | 50 +++++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 supabase/migrations/20250818155200_mismatch_team_account_workspace_fix.sql diff --git a/app/home/[account]/page.tsx b/app/home/[account]/page.tsx index e76b6f7..96bb79c 100644 --- a/app/home/[account]/page.tsx +++ b/app/home/[account]/page.tsx @@ -33,7 +33,7 @@ function TeamAccountHomePage({ params }: TeamAccountHomePageProps) { const client = getSupabaseServerClient(); const api = createTeamAccountsApi(client); const teamAccount = use(api.getTeamAccount(account)); - console.log('teamAccount', teamAccount); + return ( <> ; type Membership = Tables<{ schema: 'medreport' }, 'accounts_memberships'>; -export type AccountWithMemberships = Account & { memberships: Membership[] } +export type AccountWithMemberships = Account & { memberships: Membership[] }; export async function getAccount(id: string): Promise { const { data } = await getSupabaseServerClient() @@ -28,6 +29,7 @@ export async function getAccountAdmin({ .schema('medreport') .from('accounts') .select('*, memberships: accounts_memberships (*)') + .eq('is_personal_account', true); if (primaryOwnerUserId) { query.eq('primary_owner_user_id', primaryOwnerUserId); diff --git a/packages/supabase/src/database.types.ts b/packages/supabase/src/database.types.ts index 9c0ec2f..8142777 100644 --- a/packages/supabase/src/database.types.ts +++ b/packages/supabase/src/database.types.ts @@ -1640,9 +1640,7 @@ export type Database = { Returns: Json } create_team_account: { - Args: - | { account_name: string } - | { account_name: string; new_personal_code: string } + Args: { account_name: string; new_personal_code: string } Returns: { application_role: Database["medreport"]["Enums"]["application_role"] city: string | null diff --git a/supabase/migrations/20250818155200_mismatch_team_account_workspace_fix.sql b/supabase/migrations/20250818155200_mismatch_team_account_workspace_fix.sql new file mode 100644 index 0000000..ffc25e4 --- /dev/null +++ b/supabase/migrations/20250818155200_mismatch_team_account_workspace_fix.sql @@ -0,0 +1,50 @@ +DROP FUNCTION IF EXISTS medreport.team_account_workspace(text); + +CREATE FUNCTION medreport.team_account_workspace(account_slug text) + RETURNS TABLE( + id uuid, + name character varying, + picture_url character varying, + slug text, + role character varying, + role_hierarchy_level integer, + primary_owner_user_id uuid, + subscription_status medreport.subscription_status, + permissions medreport.app_permissions[], + account_role varchar, + application_role medreport.application_role + ) + LANGUAGE plpgsql + SET search_path TO '' +AS $function$begin + return QUERY + select + accounts.id, + accounts.name, + accounts.picture_url, + accounts.slug, + roles.name, + roles.hierarchy_level, + accounts.primary_owner_user_id, + subscriptions.status, + array_agg(role_permissions.permission), + accounts_memberships.account_role, + accounts.application_role + from + medreport.accounts + join medreport.accounts_memberships on accounts.id = accounts_memberships.account_id + left join medreport.subscriptions on accounts.id = subscriptions.account_id + join medreport.roles on accounts_memberships.account_role = roles.name + left join medreport.role_permissions on accounts_memberships.account_role = role_permissions.role + where + accounts.slug = account_slug + and medreport.accounts_memberships.user_id = (select auth.uid()) + group by + accounts.id, + accounts_memberships.account_role, + subscriptions.status, + roles.hierarchy_level, + roles.name; +end;$function$; + +GRANT EXECUTE ON FUNCTION medreport.team_account_workspace(text) TO authenticated, service_role; \ No newline at end of file From 2b79a9e4013020e5af04059383931719ff370277 Mon Sep 17 00:00:00 2001 From: Danel Kungla Date: Mon, 18 Aug 2025 16:50:26 +0300 Subject: [PATCH 3/3] Refactor team account statistics and health details - Simplified the TeamAccountStatistics component by removing unused code and integrating translation for health details. - Updated the load-team-account-health-details to calculate average BMI based on member parameters. - Adjusted the billing page to correctly reference the number of team members. - Enhanced the main account page to pass member parameters to the Dashboard component. - Modified the admin account page to destructure member data from the API response. - Updated the TeamAccountsApi to return member parameters alongside member data. - Added new translations for health details in Estonian locale. --- .../team-account-benefit-statistics.tsx | 55 +- .../team-account-health-details.tsx | 17 +- .../_components/team-account-statistics.tsx | 809 +----------------- .../load-team-account-health-details.ts | 108 +-- app/home/[account]/billing/page.tsx | 4 +- app/home/[account]/page.tsx | 3 +- .../src/components/admin-account-page.tsx | 2 +- .../features/team-accounts/src/server/api.ts | 27 +- public/locales/et/teams.json | 25 +- 9 files changed, 189 insertions(+), 861 deletions(-) diff --git a/app/home/[account]/_components/team-account-benefit-statistics.tsx b/app/home/[account]/_components/team-account-benefit-statistics.tsx index 4b0a017..95f35a6 100644 --- a/app/home/[account]/_components/team-account-benefit-statistics.tsx +++ b/app/home/[account]/_components/team-account-benefit-statistics.tsx @@ -88,35 +88,70 @@ const TeamAccountBenefitStatistics = ({
- Analüüsid + + + 18 % - 36 broneeringut + + + - Eriarstid ja spetsialistid + + + 22 % - 44 broneeringut + + + - Uuringud + + + 20 % - 40 broneeringut + + + E-konsultatsioon 17 % - 34 broneeringut + + + - Terviseuuringute paketid + + +
23 % - 46 teenuse kasutust + + +
1800 € - Teenuste summa + + +
diff --git a/app/home/[account]/_components/team-account-health-details.tsx b/app/home/[account]/_components/team-account-health-details.tsx index 9e599cf..904a2bc 100644 --- a/app/home/[account]/_components/team-account-health-details.tsx +++ b/app/home/[account]/_components/team-account-health-details.tsx @@ -1,19 +1,26 @@ import React from 'react'; import { Card } from '@kit/ui/card'; +import { Trans } from '@kit/ui/trans'; import { cn } from '@kit/ui/utils'; import { NormStatus, getAccountHealthDetailsFields, } from '../_lib/server/load-team-account-health-details'; +import { TeamAccountStatisticsProps } from './team-account-statistics'; -const TeamAccountHealthDetails = () => { - const accountHealthDetailsFields = getAccountHealthDetailsFields(); +const TeamAccountHealthDetails = ({ + memberParams, +}: { + memberParams: TeamAccountStatisticsProps['memberParams']; +}) => { + const accountHealthDetailsFields = + getAccountHealthDetailsFields(memberParams); return (
{accountHealthDetailsFields.map(({ title, Icon, value, normStatus }) => ( - +
{ >
-
{title}
+
+ +
{value}
))} diff --git a/app/home/[account]/_components/team-account-statistics.tsx b/app/home/[account]/_components/team-account-statistics.tsx index 4dac5ae..98b0b83 100644 --- a/app/home/[account]/_components/team-account-statistics.tsx +++ b/app/home/[account]/_components/team-account-statistics.tsx @@ -1,73 +1,31 @@ 'use client'; -import { use, useMemo, useState } from 'react'; - import { redirect } from 'next/navigation'; import { Database } from '@/packages/supabase/src/database.types'; -import { - ArrowDown, - ArrowUp, - ChevronRight, - Euro, - Menu, - TrendingUp, - User, -} from 'lucide-react'; -import { - Area, - AreaChart, - Bar, - BarChart, - CartesianGrid, - Line, - LineChart, - XAxis, -} from 'recharts'; +import { ChevronRight, Euro, User } from 'lucide-react'; -import { Badge } from '@kit/ui/badge'; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from '@kit/ui/card'; -import { - ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from '@kit/ui/chart'; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from '@kit/ui/table'; +import { Card } from '@kit/ui/card'; +import { Trans } from '@kit/ui/makerkit/trans'; import pathsConfig from '~/config/paths.config'; import { createPath } from '~/config/team-account-navigation.config'; -import { loadCurrentUserAccount } from '../../(user)/_lib/server/load-user-account'; import TeamAccountBenefitStatistics from './team-account-benefit-statistics'; import TeamAccountHealthDetails from './team-account-health-details'; -interface TeamAccountStatisticsProps { +export interface TeamAccountStatisticsProps { teamAccount: Database['medreport']['Tables']['accounts']['Row']; + memberParams: Pick< + Database['medreport']['Tables']['account_params']['Row'], + 'weight' | 'height' + >[]; } export default function TeamAccountStatistics({ teamAccount, + memberParams, }: TeamAccountStatisticsProps) { - const mrr = useMemo(() => generateDemoData(), []); - const netRevenue = useMemo(() => generateDemoData(), []); - const fees = useMemo(() => generateDemoData(), []); - const newCustomers = useMemo(() => generateDemoData(), []); - return (
-
Ettevõtte terviseandmed
+
+ +
- +
- Halda töötajaid +

- Lisa, muuda või eemalda töötajaid. +

@@ -128,10 +88,10 @@ export default function TeamAccountStatistics({
- Halda eelarvet +

- Vali kuidas soovid eelarvet töötajate vahel jagada. +

@@ -139,738 +99,3 @@ export default function TeamAccountStatistics({
); } - -function generateDemoData() { - const today = new Date(); - const formatter = new Intl.DateTimeFormat('en-us', { - month: 'long', - year: '2-digit', - }); - - const data: { value: string; name: string }[] = []; - - for (let n = 8; n > 0; n -= 1) { - const date = new Date(today.getFullYear(), today.getMonth() - n, 1); - - data.push({ - name: formatter.format(date), - value: (Math.random() * 10).toFixed(1), - }); - } - - const lastValue = data[data.length - 1]?.value; - - return [data, lastValue] as [typeof data, string]; -} - -function Chart( - props: React.PropsWithChildren<{ data: { value: string; name: string }[] }>, -) { - const chartConfig = { - desktop: { - label: 'Desktop', - color: 'var(--chart-1)', - }, - mobile: { - label: 'Mobile', - color: 'var(--chart-2)', - }, - } satisfies ChartConfig; - - return ( - - - - - } - /> - - - - ); -} - -function CustomersTable() { - const customers = [ - { - name: 'John Doe', - email: 'john@makerkit.dev', - plan: 'Pro', - mrr: '$120.5', - logins: 1020, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Emma Smith', - email: 'emma@makerit.dev', - plan: 'Basic', - mrr: '$65.4', - logins: 570, - status: 'Possible Churn', - trend: 'stale', - }, - { - name: 'Robert Johnson', - email: 'robert@makerkit.dev', - plan: 'Pro', - mrr: '$500.1', - logins: 2050, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Olivia Brown', - email: 'olivia@makerkit.dev', - plan: 'Basic', - mrr: '$10', - logins: 50, - status: 'Churn', - trend: 'down', - }, - { - name: 'Michael Davis', - email: 'michael@makerkit.dev', - plan: 'Pro', - mrr: '$300.2', - logins: 1520, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Emily Jones', - email: 'emily@makerkit.dev', - plan: 'Pro', - mrr: '$75.7', - logins: 780, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Daniel Garcia', - email: 'daniel@makerkit.dev', - plan: 'Basic', - mrr: '$50', - logins: 320, - status: 'Possible Churn', - trend: 'stale', - }, - { - name: 'Liam Miller', - email: 'liam@makerkit.dev', - plan: 'Pro', - mrr: '$90.8', - logins: 1260, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Emma Clark', - email: 'emma@makerkit.dev', - plan: 'Basic', - mrr: '$0', - logins: 20, - status: 'Churn', - trend: 'down', - }, - { - name: 'Elizabeth Rodriguez', - email: 'liz@makerkit.dev', - plan: 'Pro', - mrr: '$145.3', - logins: 1380, - status: 'Healthy', - trend: 'up', - }, - { - name: 'James Martinez', - email: 'james@makerkit.dev', - plan: 'Pro', - mrr: '$120.5', - logins: 940, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Charlotte Ryan', - email: 'carlotte@makerkit.dev', - plan: 'Basic', - mrr: '$80.6', - logins: 460, - status: 'Possible Churn', - trend: 'stale', - }, - { - name: 'Lucas Evans', - email: 'lucas@makerkit.dev', - plan: 'Pro', - mrr: '$210.3', - logins: 1850, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Sophia Wilson', - email: 'sophia@makerkit.dev', - plan: 'Basic', - mrr: '$10', - logins: 35, - status: 'Churn', - trend: 'down', - }, - { - name: 'William Kelly', - email: 'will@makerkit.dev', - plan: 'Pro', - mrr: '$350.2', - logins: 1760, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Oliver Thomas', - email: 'olly@makerkit.dev', - plan: 'Pro', - mrr: '$145.6', - logins: 1350, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Samantha White', - email: 'sam@makerkit.dev', - plan: 'Basic', - mrr: '$60.3', - logins: 425, - status: 'Possible Churn', - trend: 'stale', - }, - { - name: 'Benjamin Lewis', - email: 'ben@makerkit.dev', - plan: 'Pro', - mrr: '$175.8', - logins: 1600, - status: 'Healthy', - trend: 'up', - }, - { - name: 'Zoe Harris', - email: 'zoe@makerkit.dev', - plan: 'Basic', - mrr: '$0', - logins: 18, - status: 'Churn', - trend: 'down', - }, - { - name: 'Zachary Nelson', - email: 'zac@makerkit.dev', - plan: 'Pro', - mrr: '$255.9', - logins: 1785, - status: 'Healthy', - trend: 'up', - }, - ]; - - return ( - - - - Customer - Plan - MRR - Logins - Status - - - - {customers.map((customer) => ( - - - {customer.name} - - {customer.email} - - - {customer.plan} - {customer.mrr} - {customer.logins} - - - {customer.status} - - - - ))} - -
- ); -} - -function BadgeWithTrend(props: React.PropsWithChildren<{ trend: string }>) { - const className = useMemo(() => { - switch (props.trend) { - case 'up': - return 'text-green-500'; - case 'down': - return 'text-destructive'; - case 'stale': - return 'text-orange-500'; - } - }, [props.trend]); - - return ( - - {props.children} - - ); -} - -function Figure(props: React.PropsWithChildren) { - return ( -
- {props.children} -
- ); -} - -function Trend( - props: React.PropsWithChildren<{ - trend: 'up' | 'down' | 'stale'; - }>, -) { - const Icon = useMemo(() => { - switch (props.trend) { - case 'up': - return ; - case 'down': - return ; - case 'stale': - return ; - } - }, [props.trend]); - - return ( -
- - - {Icon} - {props.children} - - -
- ); -} - -export function VisitorsChart() { - const chartData = useMemo( - () => [ - { date: '2024-04-01', desktop: 222, mobile: 150 }, - { date: '2024-04-02', desktop: 97, mobile: 180 }, - { date: '2024-04-03', desktop: 167, mobile: 120 }, - { date: '2024-04-04', desktop: 242, mobile: 260 }, - { date: '2024-04-05', desktop: 373, mobile: 290 }, - { date: '2024-04-06', desktop: 301, mobile: 340 }, - { date: '2024-04-07', desktop: 245, mobile: 180 }, - { date: '2024-04-08', desktop: 409, mobile: 320 }, - { date: '2024-04-09', desktop: 59, mobile: 110 }, - { date: '2024-04-10', desktop: 261, mobile: 190 }, - { date: '2024-04-11', desktop: 327, mobile: 350 }, - { date: '2024-04-12', desktop: 292, mobile: 210 }, - { date: '2024-04-13', desktop: 342, mobile: 380 }, - { date: '2024-04-14', desktop: 137, mobile: 220 }, - { date: '2024-04-15', desktop: 120, mobile: 170 }, - { date: '2024-04-16', desktop: 138, mobile: 190 }, - { date: '2024-04-17', desktop: 446, mobile: 360 }, - { date: '2024-04-18', desktop: 364, mobile: 410 }, - { date: '2024-04-19', desktop: 243, mobile: 180 }, - { date: '2024-04-20', desktop: 89, mobile: 150 }, - { date: '2024-04-21', desktop: 137, mobile: 200 }, - { date: '2024-04-22', desktop: 224, mobile: 170 }, - { date: '2024-04-23', desktop: 138, mobile: 230 }, - { date: '2024-04-24', desktop: 387, mobile: 290 }, - { date: '2024-04-25', desktop: 215, mobile: 250 }, - { date: '2024-04-26', desktop: 75, mobile: 130 }, - { date: '2024-04-27', desktop: 383, mobile: 420 }, - { date: '2024-04-28', desktop: 122, mobile: 180 }, - { date: '2024-04-29', desktop: 315, mobile: 240 }, - { date: '2024-04-30', desktop: 454, mobile: 380 }, - { date: '2024-05-01', desktop: 165, mobile: 220 }, - { date: '2024-05-02', desktop: 293, mobile: 310 }, - { date: '2024-05-03', desktop: 247, mobile: 190 }, - { date: '2024-05-04', desktop: 385, mobile: 420 }, - { date: '2024-05-05', desktop: 481, mobile: 390 }, - { date: '2024-05-06', desktop: 498, mobile: 520 }, - { date: '2024-05-07', desktop: 388, mobile: 300 }, - { date: '2024-05-08', desktop: 149, mobile: 210 }, - { date: '2024-05-09', desktop: 227, mobile: 180 }, - { date: '2024-05-10', desktop: 293, mobile: 330 }, - { date: '2024-05-11', desktop: 335, mobile: 270 }, - { date: '2024-05-12', desktop: 197, mobile: 240 }, - { date: '2024-05-13', desktop: 197, mobile: 160 }, - { date: '2024-05-14', desktop: 448, mobile: 490 }, - { date: '2024-05-15', desktop: 473, mobile: 380 }, - { date: '2024-05-16', desktop: 338, mobile: 400 }, - { date: '2024-05-17', desktop: 499, mobile: 420 }, - { date: '2024-05-18', desktop: 315, mobile: 350 }, - { date: '2024-05-19', desktop: 235, mobile: 180 }, - { date: '2024-05-20', desktop: 177, mobile: 230 }, - { date: '2024-05-21', desktop: 82, mobile: 140 }, - { date: '2024-05-22', desktop: 81, mobile: 120 }, - { date: '2024-05-23', desktop: 252, mobile: 290 }, - { date: '2024-05-24', desktop: 294, mobile: 220 }, - { date: '2024-05-25', desktop: 201, mobile: 250 }, - { date: '2024-05-26', desktop: 213, mobile: 170 }, - { date: '2024-05-27', desktop: 420, mobile: 460 }, - { date: '2024-05-28', desktop: 233, mobile: 190 }, - { date: '2024-05-29', desktop: 78, mobile: 130 }, - { date: '2024-05-30', desktop: 340, mobile: 280 }, - { date: '2024-05-31', desktop: 178, mobile: 230 }, - { date: '2024-06-01', desktop: 178, mobile: 200 }, - { date: '2024-06-02', desktop: 470, mobile: 410 }, - { date: '2024-06-03', desktop: 103, mobile: 160 }, - { date: '2024-06-04', desktop: 439, mobile: 380 }, - { date: '2024-06-05', desktop: 88, mobile: 140 }, - { date: '2024-06-06', desktop: 294, mobile: 250 }, - { date: '2024-06-07', desktop: 323, mobile: 370 }, - { date: '2024-06-08', desktop: 385, mobile: 320 }, - { date: '2024-06-09', desktop: 438, mobile: 480 }, - { date: '2024-06-10', desktop: 155, mobile: 200 }, - { date: '2024-06-11', desktop: 92, mobile: 150 }, - { date: '2024-06-12', desktop: 492, mobile: 420 }, - { date: '2024-06-13', desktop: 81, mobile: 130 }, - { date: '2024-06-14', desktop: 426, mobile: 380 }, - { date: '2024-06-15', desktop: 307, mobile: 350 }, - { date: '2024-06-16', desktop: 371, mobile: 310 }, - { date: '2024-06-17', desktop: 475, mobile: 520 }, - { date: '2024-06-18', desktop: 107, mobile: 170 }, - { date: '2024-06-19', desktop: 341, mobile: 290 }, - { date: '2024-06-20', desktop: 408, mobile: 450 }, - { date: '2024-06-21', desktop: 169, mobile: 210 }, - { date: '2024-06-22', desktop: 317, mobile: 270 }, - { date: '2024-06-23', desktop: 480, mobile: 530 }, - { date: '2024-06-24', desktop: 132, mobile: 180 }, - { date: '2024-06-25', desktop: 141, mobile: 190 }, - { date: '2024-06-26', desktop: 434, mobile: 380 }, - { date: '2024-06-27', desktop: 448, mobile: 490 }, - { date: '2024-06-28', desktop: 149, mobile: 200 }, - { date: '2024-06-29', desktop: 103, mobile: 160 }, - { date: '2024-06-30', desktop: 446, mobile: 400 }, - ], - [], - ); - - const chartConfig = { - visitors: { - label: 'Visitors', - }, - desktop: { - label: 'Desktop', - color: 'var(--chart-1)', - }, - mobile: { - label: 'Mobile', - color: 'var(--chart-2)', - }, - } satisfies ChartConfig; - - return ( - - - Visitors - - Showing total visitors for the last 6 months - - - - - - - - - - - - - - - - - - value.slice(0, 3)} - /> - } - /> - - - - - - - -
-
-
- Trending up by 5.2% this month -
-
- January - June 2024 -
-
-
-
-
- ); -} - -export function PageViewsChart() { - const [activeChart, setActiveChart] = - useState('desktop'); - - const chartData = [ - { date: '2024-04-01', desktop: 222, mobile: 150 }, - { date: '2024-04-02', desktop: 97, mobile: 180 }, - { date: '2024-04-03', desktop: 167, mobile: 120 }, - { date: '2024-04-04', desktop: 242, mobile: 260 }, - { date: '2024-04-05', desktop: 373, mobile: 290 }, - { date: '2024-04-06', desktop: 301, mobile: 340 }, - { date: '2024-04-07', desktop: 245, mobile: 180 }, - { date: '2024-04-08', desktop: 409, mobile: 320 }, - { date: '2024-04-09', desktop: 59, mobile: 110 }, - { date: '2024-04-10', desktop: 261, mobile: 190 }, - { date: '2024-04-11', desktop: 327, mobile: 350 }, - { date: '2024-04-12', desktop: 292, mobile: 210 }, - { date: '2024-04-13', desktop: 342, mobile: 380 }, - { date: '2024-04-14', desktop: 137, mobile: 220 }, - { date: '2024-04-15', desktop: 120, mobile: 170 }, - { date: '2024-04-16', desktop: 138, mobile: 190 }, - { date: '2024-04-17', desktop: 446, mobile: 360 }, - { date: '2024-04-18', desktop: 364, mobile: 410 }, - { date: '2024-04-19', desktop: 243, mobile: 180 }, - { date: '2024-04-20', desktop: 89, mobile: 150 }, - { date: '2024-04-21', desktop: 137, mobile: 200 }, - { date: '2024-04-22', desktop: 224, mobile: 170 }, - { date: '2024-04-23', desktop: 138, mobile: 230 }, - { date: '2024-04-24', desktop: 387, mobile: 290 }, - { date: '2024-04-25', desktop: 215, mobile: 250 }, - { date: '2024-04-26', desktop: 75, mobile: 130 }, - { date: '2024-04-27', desktop: 383, mobile: 420 }, - { date: '2024-04-28', desktop: 122, mobile: 180 }, - { date: '2024-04-29', desktop: 315, mobile: 240 }, - { date: '2024-04-30', desktop: 454, mobile: 380 }, - { date: '2024-05-01', desktop: 165, mobile: 220 }, - { date: '2024-05-02', desktop: 293, mobile: 310 }, - { date: '2024-05-03', desktop: 247, mobile: 190 }, - { date: '2024-05-04', desktop: 385, mobile: 420 }, - { date: '2024-05-05', desktop: 481, mobile: 390 }, - { date: '2024-05-06', desktop: 498, mobile: 520 }, - { date: '2024-05-07', desktop: 388, mobile: 300 }, - { date: '2024-05-08', desktop: 149, mobile: 210 }, - { date: '2024-05-09', desktop: 227, mobile: 180 }, - { date: '2024-05-10', desktop: 293, mobile: 330 }, - { date: '2024-05-11', desktop: 335, mobile: 270 }, - { date: '2024-05-12', desktop: 197, mobile: 240 }, - { date: '2024-05-13', desktop: 197, mobile: 160 }, - { date: '2024-05-14', desktop: 448, mobile: 490 }, - { date: '2024-05-15', desktop: 473, mobile: 380 }, - { date: '2024-05-16', desktop: 338, mobile: 400 }, - { date: '2024-05-17', desktop: 499, mobile: 420 }, - { date: '2024-05-18', desktop: 315, mobile: 350 }, - { date: '2024-05-19', desktop: 235, mobile: 180 }, - { date: '2024-05-20', desktop: 177, mobile: 230 }, - { date: '2024-05-21', desktop: 82, mobile: 140 }, - { date: '2024-05-22', desktop: 81, mobile: 120 }, - { date: '2024-05-23', desktop: 252, mobile: 290 }, - { date: '2024-05-24', desktop: 294, mobile: 220 }, - { date: '2024-05-25', desktop: 201, mobile: 250 }, - { date: '2024-05-26', desktop: 213, mobile: 170 }, - { date: '2024-05-27', desktop: 420, mobile: 460 }, - { date: '2024-05-28', desktop: 233, mobile: 190 }, - { date: '2024-05-29', desktop: 78, mobile: 130 }, - { date: '2024-05-30', desktop: 340, mobile: 280 }, - { date: '2024-05-31', desktop: 178, mobile: 230 }, - { date: '2024-06-01', desktop: 178, mobile: 200 }, - { date: '2024-06-02', desktop: 470, mobile: 410 }, - { date: '2024-06-03', desktop: 103, mobile: 160 }, - { date: '2024-06-04', desktop: 439, mobile: 380 }, - { date: '2024-06-05', desktop: 88, mobile: 140 }, - { date: '2024-06-06', desktop: 294, mobile: 250 }, - { date: '2024-06-07', desktop: 323, mobile: 370 }, - { date: '2024-06-08', desktop: 385, mobile: 320 }, - { date: '2024-06-09', desktop: 438, mobile: 480 }, - { date: '2024-06-10', desktop: 155, mobile: 200 }, - { date: '2024-06-11', desktop: 92, mobile: 150 }, - { date: '2024-06-12', desktop: 492, mobile: 420 }, - { date: '2024-06-13', desktop: 81, mobile: 130 }, - { date: '2024-06-14', desktop: 426, mobile: 380 }, - { date: '2024-06-15', desktop: 307, mobile: 350 }, - { date: '2024-06-16', desktop: 371, mobile: 310 }, - { date: '2024-06-17', desktop: 475, mobile: 520 }, - { date: '2024-06-18', desktop: 107, mobile: 170 }, - { date: '2024-06-19', desktop: 341, mobile: 290 }, - { date: '2024-06-20', desktop: 408, mobile: 450 }, - { date: '2024-06-21', desktop: 169, mobile: 210 }, - { date: '2024-06-22', desktop: 317, mobile: 270 }, - { date: '2024-06-23', desktop: 480, mobile: 530 }, - { date: '2024-06-24', desktop: 132, mobile: 180 }, - { date: '2024-06-25', desktop: 141, mobile: 190 }, - { date: '2024-06-26', desktop: 434, mobile: 380 }, - { date: '2024-06-27', desktop: 448, mobile: 490 }, - { date: '2024-06-28', desktop: 149, mobile: 200 }, - { date: '2024-06-29', desktop: 103, mobile: 160 }, - { date: '2024-06-30', desktop: 446, mobile: 400 }, - ]; - - const chartConfig = { - views: { - label: 'Page Views', - }, - desktop: { - label: 'Desktop', - color: 'var(--chart-1)', - }, - mobile: { - label: 'Mobile', - color: 'var(--chart-2)', - }, - } satisfies ChartConfig; - - const total = useMemo( - () => ({ - desktop: chartData.reduce((acc, curr) => acc + curr.desktop, 0), - mobile: chartData.reduce((acc, curr) => acc + curr.mobile, 0), - }), - [], - ); - - return ( - - -
- Page Views - - - Showing total visitors for the last 3 months - -
- -
- {['desktop', 'mobile'].map((key) => { - const chart = key as keyof typeof chartConfig; - return ( - - ); - })} -
-
- - - - - - { - const date = new Date(value); - return date.toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - }); - }} - /> - { - return new Date(value).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric', - }); - }} - /> - } - /> - - - - -
- ); -} diff --git a/app/home/[account]/_lib/server/load-team-account-health-details.ts b/app/home/[account]/_lib/server/load-team-account-health-details.ts index 18fb787..6aeaa3c 100644 --- a/app/home/[account]/_lib/server/load-team-account-health-details.ts +++ b/app/home/[account]/_lib/server/load-team-account-health-details.ts @@ -2,9 +2,11 @@ import React from 'react'; import { Clock, TrendingUp, User } from 'lucide-react'; +import { TeamAccountStatisticsProps } from '../../_components/team-account-statistics'; + interface AccountHealthDetailsField { title: string; - value: string; + value: string | number; Icon: React.ComponentType<{ size?: number; color?: string; @@ -19,51 +21,59 @@ export enum NormStatus { NORMAL = 'NORMAL', } -export const getAccountHealthDetailsFields = - (): AccountHealthDetailsField[] => { - const test = ''; - return [ - { - title: 'Naised', - value: '50% (16)', - Icon: User, - normStatus: NormStatus.NORMAL, - }, - { - title: 'Mehed', - value: '50% (16)', - Icon: User, - normStatus: NormStatus.NORMAL, - }, - { - title: 'Keskmine vanus', - value: '56', - Icon: Clock, - normStatus: NormStatus.NORMAL, - }, - { - title: 'KMI', - value: '271', - Icon: TrendingUp, - normStatus: NormStatus.WARNING, - }, - { - title: 'Üldkolesterool', - value: '6.1', - Icon: TrendingUp, - normStatus: NormStatus.WARNING, - }, - { - title: 'Vitamiin D', - value: '76', - Icon: TrendingUp, - normStatus: NormStatus.NORMAL, - }, - { - title: 'Suitsetajad', - value: '22%', - Icon: TrendingUp, - normStatus: NormStatus.CRITICAL, - }, - ]; - }; +export const getAccountHealthDetailsFields = ( + memberParams: TeamAccountStatisticsProps['memberParams'], +): AccountHealthDetailsField[] => { + const averageBMI = ( + memberParams.reduce((sum, { height, weight }) => { + const hMeters = height! / 100; + const bmi = weight! / (hMeters * hMeters); + return sum + bmi; + }, 0) / memberParams.length + ).toFixed(0); + + return [ + { + title: 'teams:healthDetails.women', + value: `50% (${memberParams.length})`, + Icon: User, + normStatus: NormStatus.NORMAL, + }, + { + title: 'teams:healthDetails.men', + value: `50% (${memberParams.length})`, + Icon: User, + normStatus: NormStatus.NORMAL, + }, + { + title: 'teams:healthDetails.avgAge', + value: '56', + Icon: Clock, + normStatus: NormStatus.NORMAL, + }, + { + title: 'teams:healthDetails.bmi', + value: averageBMI, + Icon: TrendingUp, + normStatus: NormStatus.WARNING, + }, + { + title: 'teams:healthDetails.cholesterol', + value: '6.1', + Icon: TrendingUp, + normStatus: NormStatus.WARNING, + }, + { + title: 'teams:healthDetails.vitaminD', + value: '76', + Icon: TrendingUp, + normStatus: NormStatus.NORMAL, + }, + { + title: 'teams:healthDetails.smokers', + value: '22%', + Icon: TrendingUp, + normStatus: NormStatus.CRITICAL, + }, + ]; +}; diff --git a/app/home/[account]/billing/page.tsx b/app/home/[account]/billing/page.tsx index a56b07a..9d2da4c 100644 --- a/app/home/[account]/billing/page.tsx +++ b/app/home/[account]/billing/page.tsx @@ -29,14 +29,14 @@ async function TeamAccountBillingPage({ params }: TeamAccountBillingPageProps) { const account = await api.getTeamAccount(accountSlug); const companyParams = await api.getTeamAccountParams(account.id); - const accounts = await api.getMembers(accountSlug); + const { members } = await api.getMembers(accountSlug); return ( ); diff --git a/app/home/[account]/page.tsx b/app/home/[account]/page.tsx index 96bb79c..46a0c2b 100644 --- a/app/home/[account]/page.tsx +++ b/app/home/[account]/page.tsx @@ -33,6 +33,7 @@ function TeamAccountHomePage({ params }: TeamAccountHomePageProps) { const client = getSupabaseServerClient(); const api = createTeamAccountsApi(client); const teamAccount = use(api.getTeamAccount(account)); + const { memberParams } = use(api.getMembers(account)); return ( <> @@ -46,7 +47,7 @@ function TeamAccountHomePage({ params }: TeamAccountHomePageProps) { /> - + ); diff --git a/packages/features/admin/src/components/admin-account-page.tsx b/packages/features/admin/src/components/admin-account-page.tsx index 1acb6a7..7fe9df9 100644 --- a/packages/features/admin/src/components/admin-account-page.tsx +++ b/packages/features/admin/src/components/admin-account-page.tsx @@ -164,7 +164,7 @@ async function TeamAccountPage(props: { account: Account & { memberships: Membership[] }; }) { const api = createTeamAccountsApi(getSupabaseServerClient()); - const members = await api.getMembers(props.account.slug ?? ''); + const { members } = await api.getMembers(props.account.slug ?? ''); return ( <> diff --git a/packages/features/team-accounts/src/server/api.ts b/packages/features/team-accounts/src/server/api.ts index a57b68d..44b0379 100644 --- a/packages/features/team-accounts/src/server/api.ts +++ b/packages/features/team-accounts/src/server/api.ts @@ -308,7 +308,32 @@ export class TeamAccountsApi { throw members.error; } - return members.data; + const memberIds = members.data?.map((member) => member.id) ?? []; + const memberParams = await this.client + .schema('medreport') + .from('account_params') + .select('weight, height') + .in('account_id', memberIds); + + if (memberParams.error) { + throw memberParams.error; + } + + return { members: members.data, memberParams: memberParams.data }; + } + + async getMemberParams(ids: string[]) { + const memberParams = await this.client + .schema('medreport') + .from('account_params') + .select('weight, height') + .in('account_id', ids); + + if (memberParams.error) { + throw memberParams.error; + } + + return memberParams.data; } } diff --git a/public/locales/et/teams.json b/public/locales/et/teams.json index 66a8f74..515d538 100644 --- a/public/locales/et/teams.json +++ b/public/locales/et/teams.json @@ -1,7 +1,12 @@ { "home": { "pageTitle": "Ülevaade", - "headerTitle": "{{companyName}} tervise ülevaade" + "headerTitle": "{{companyName}} tervise ülevaade", + "healthDetails": "Ettevõtte terviseandmed", + "membersSettingsButtonTitle": "Halda töötajaid", + "membersSettingsButtonDescription": "Lisa, muuda või eemalda töötajaid.", + "membersBillingButtonTitle": "Halda eelarvet", + "membersBillingButtonDescription": "Vali kuidas soovid eelarvet töötajate vahel jagada." }, "settings": { "pageTitle": "Settings", @@ -24,8 +29,26 @@ "title": "Ettevõtte Tervisekassa seis", "balance": "Eelarve jääk {{balance}}", "volume": "Eelarve maht {{volume}}" + }, + "data": { + "reservations": "{{value}} broneeringut", + "analysis": "Analüüsid", + "doctorsAndSpecialists": "Eriarstid ja spetsialistid", + "researches": "Uuringud", + "healthResearchPlans": "Terviseuuringute paketid", + "serviceUsage": "{{value}} teenuse kasutust", + "serviceSum": "Teenuste summa" } }, + "healthDetails": { + "women": "Naised", + "men": "Mehed", + "avgAge": "Keskmine vanus", + "bmi": "KMI", + "cholesterol": "Üldkolesterool", + "vitaminD": "Vitamiin D", + "smokers": "Suitsetajad" + }, "yourTeams": "Your Companies ({{teamsCount}})", "createTeam": "Create a Company", "creatingTeam": "Creating Company...",