diff --git a/app/home/(user)/(dashboard)/analysis-results/_components/analysis-level-bar.tsx b/app/home/(user)/(dashboard)/analysis-results/_components/analysis-level-bar.tsx index 9b23701..6714f80 100644 --- a/app/home/(user)/(dashboard)/analysis-results/_components/analysis-level-bar.tsx +++ b/app/home/(user)/(dashboard)/analysis-results/_components/analysis-level-bar.tsx @@ -19,7 +19,7 @@ const Level = ({ isLast = false, }: { isActive?: boolean; - color: 'destructive' | 'success' | 'warning'; + color: 'destructive' | 'success' | 'warning' | 'gray-200'; isFirst?: boolean; isLast?: boolean; }) => { @@ -40,6 +40,14 @@ const Level = ({ ); }; +export const AnalysisLevelBarSkeleton = () => { + return ( +
+ +
+ ); +}; + const AnalysisLevelBar = ({ normLowerIncluded = true, normUpperIncluded = true, @@ -50,7 +58,7 @@ const AnalysisLevelBar = ({ level: AnalysisResultLevel; }) => { return ( -
+
{normLowerIncluded && ( <> { + const name = analysisElement.analysis_name_lab || ''; + const status = results?.norm_status || AnalysisStatus.NORMAL; + const value = results?.response_value || 0; + const unit = results?.unit || ''; + const normLowerIncluded = results?.norm_lower_included || false; + const normUpperIncluded = results?.norm_upper_included || false; + const normLower = results?.norm_lower || 0; + const normUpper = results?.norm_upper || 0; + const [showTooltip, setShowTooltip] = useState(false); const isUnderNorm = value < normLower; const getAnalysisResultLevel = () => { + if (!results) { + return null; + } if (isUnderNorm) { switch (status) { case AnalysisStatus.MEDIUM: @@ -59,7 +58,7 @@ const Analysis = ({ }; return ( -
+
{name}
-
-
{value}
-
{unit}
-
-
- {normLower} - {normUpper} -
Normaalne vahemik
-
- + {results ? ( + <> +
+
{value}
+
{unit}
+
+
+ {normLower} - {normUpper} +
+ +
+
+ + + ) : ( + <> +
+
+ +
+
+
+ + + )}
); }; diff --git a/app/home/(user)/(dashboard)/analysis-results/page.tsx b/app/home/(user)/(dashboard)/analysis-results/page.tsx index 0d3687c..4060560 100644 --- a/app/home/(user)/(dashboard)/analysis-results/page.tsx +++ b/app/home/(user)/(dashboard)/analysis-results/page.tsx @@ -1,4 +1,5 @@ -import { Fragment } from 'react'; +import Link from 'next/link'; + import { createI18nServerInstance } from '@/lib/i18n/i18n.server'; import { withI18n } from '@/lib/i18n/with-i18n'; @@ -7,11 +8,17 @@ import { PageBody } from '@kit/ui/page'; import { Button } from '@kit/ui/shadcn/button'; import { loadUserAnalysis } from '../../_lib/server/load-user-analysis'; -import Analysis, { AnalysisStatus } from './_components/analysis'; +import Analysis from './_components/analysis'; +import { listProductTypes } from '@lib/data/products'; +import pathsConfig from '~/config/paths.config'; +import { redirect } from 'next/navigation'; +import { getOrders } from '~/lib/services/order.service'; +import { AnalysisElement, getAnalysisElements } from '~/lib/services/analysis-element.service'; +import type { UserAnalysisElement } from '@kit/accounts/types/accounts'; export const generateMetadata = async () => { const i18n = await createI18nServerInstance(); - const title = i18n.t('account:analysisResults.pageTitle'); + const title = i18n.t('analysis-results:pageTitle'); return { title, @@ -21,45 +28,56 @@ export const generateMetadata = async () => { async function AnalysisResultsPage() { const analysisList = await loadUserAnalysis(); + const orders = await getOrders().catch(() => null); + const { productTypes } = await listProductTypes(); + + if (!orders || !productTypes) { + redirect(pathsConfig.auth.signIn); + } + + const analysisElementIds = [ + ...new Set(orders?.flatMap((order) => order.analysis_element_ids).filter(Boolean) as number[]), + ]; + const analysisElements = await getAnalysisElements({ ids: analysisElementIds }); + const analysisElementsWithResults = analysisElements.reduce((acc, curr) => { + const analysisResponseWithElementResults = analysisList?.find((result) => result.elements.some((element) => element.analysis_element_original_id === curr.analysis_id_original)); + const elementResults = analysisResponseWithElementResults?.elements.find((element) => element.analysis_element_original_id === curr.analysis_id_original) as UserAnalysisElement | undefined; + return { + ...acc, + [curr.id]: { + analysisElement: curr, + results: elementResults, + }, + } + }, {} as Record); + return ( -
+

- +

{analysisList && analysisList.length > 0 ? ( - + ) : ( - + )}

-
- {analysisList?.map((analysis) => ( - - {analysis.elements.map((element) => ( - - ))} - - ))} + {Object.entries(analysisElementsWithResults).map(([id, { analysisElement, results }]) => { + return ( + + ); + })}
); diff --git a/lib/i18n/i18n.settings.ts b/lib/i18n/i18n.settings.ts index 2d9dad2..e41095f 100644 --- a/lib/i18n/i18n.settings.ts +++ b/lib/i18n/i18n.settings.ts @@ -39,6 +39,7 @@ export const defaultI18nNamespaces = [ 'order-analysis', 'cart', 'orders', + 'analysis-results', ]; /** diff --git a/lib/services/analysis-element.service.ts b/lib/services/analysis-element.service.ts index 2777a77..635320c 100644 --- a/lib/services/analysis-element.service.ts +++ b/lib/services/analysis-element.service.ts @@ -1,4 +1,3 @@ -import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { Json, Tables } from '@kit/supabase/database'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; import type { IMaterialGroup, IUuringElement } from './medipost.types'; @@ -9,10 +8,12 @@ export type AnalysisElement = Tables<{ schema: 'medreport' }, 'analysis_elements export async function getAnalysisElements({ originalIds, + ids, }: { originalIds?: string[]; + ids?: number[]; }): Promise { - const query = getSupabaseServerClient() + const query = getSupabaseServerAdminClient() .schema('medreport') .from('analysis_elements') .select(`*, analysis_groups(*)`) @@ -22,6 +23,10 @@ export async function getAnalysisElements({ query.in('analysis_id_original', [...new Set(originalIds)]); } + if (Array.isArray(ids)) { + query.in('id', ids); + } + const { data: analysisElements, error } = await query; if (error) { diff --git a/packages/features/accounts/src/types/accounts.ts b/packages/features/accounts/src/types/accounts.ts index 8048dea..bbc4ddb 100644 --- a/packages/features/accounts/src/types/accounts.ts +++ b/packages/features/accounts/src/types/accounts.ts @@ -1,6 +1,7 @@ import { Database } from '@kit/supabase/database'; -export type UserAnalysis = - (Database['medreport']['Tables']['analysis_responses']['Row'] & { - elements: Database['medreport']['Tables']['analysis_response_elements']['Row'][]; - })[]; +export type UserAnalysisElement = Database['medreport']['Tables']['analysis_response_elements']['Row']; +export type UserAnalysisResponse = Database['medreport']['Tables']['analysis_responses']['Row'] & { + elements: UserAnalysisElement[]; +}; +export type UserAnalysis = UserAnalysisResponse[]; diff --git a/packages/ui/src/makerkit/page.tsx b/packages/ui/src/makerkit/page.tsx index 4f82a7b..e089171 100644 --- a/packages/ui/src/makerkit/page.tsx +++ b/packages/ui/src/makerkit/page.tsx @@ -42,7 +42,7 @@ function PageWithSidebar(props: PageProps) { > {MobileNavigation} -
+
{Children}
diff --git a/public/locales/en/account.json b/public/locales/en/account.json index 95f7e2f..edbf616 100644 --- a/public/locales/en/account.json +++ b/public/locales/en/account.json @@ -122,11 +122,5 @@ "consentToAnonymizedCompanyData": { "label": "Consent to be included in employer statistics", "description": "Consent to be included in anonymized company statistics" - }, - "analysisResults": { - "pageTitle": "My analysis results", - "description": "Super, you've already done your analysis. Here are your important results:", - "descriptionEmpty": "If you've already done your analysis, your results will appear here soon.", - "orderNewAnalysis": "Order new analyses" } } diff --git a/public/locales/en/analysis-results.json b/public/locales/en/analysis-results.json new file mode 100644 index 0000000..3d53e6b --- /dev/null +++ b/public/locales/en/analysis-results.json @@ -0,0 +1,12 @@ +{ + "pageTitle": "My analysis results", + "description": "All analysis results will appear here within 1-3 business days after they have been done.", + "descriptionEmpty": "If you've already done your analysis, your results will appear here soon.", + "orderNewAnalysis": "Order new analyses", + "waitingForResults": "Waiting for results", + "results": { + "range": { + "normal": "Normal range" + } + } +} \ No newline at end of file diff --git a/public/locales/et/account.json b/public/locales/et/account.json index 836c5e4..ade6520 100644 --- a/public/locales/et/account.json +++ b/public/locales/et/account.json @@ -145,11 +145,5 @@ "successTitle": "Tere, {{firstName}} {{lastName}}", "successDescription": "Teie tervisekonto on aktiveeritud ja kasutamiseks valmis!", "successButton": "Jätka" - }, - "analysisResults": { - "pageTitle": "Minu analüüside vastused", - "description": "Super, oled käinud tervist kontrollimas. Siin on sinule olulised näitajad:", - "descriptionEmpty": "Kui oled juba käinud analüüse andmas, siis varsti jõuavad siia sinu analüüside vastused.", - "orderNewAnalysis": "Telli uued analüüsid" } } diff --git a/public/locales/et/analysis-results.json b/public/locales/et/analysis-results.json new file mode 100644 index 0000000..59cfcaa --- /dev/null +++ b/public/locales/et/analysis-results.json @@ -0,0 +1,12 @@ +{ + "pageTitle": "Minu analüüside vastused", + "description": "Kõikide analüüside tulemused ilmuvad 1-3 tööpäeva jooksul peale nende andmist.", + "descriptionEmpty": "Kui oled juba käinud analüüse andmas, siis varsti jõuavad siia sinu analüüside vastused.", + "orderNewAnalysis": "Telli uued analüüsid", + "waitingForResults": "Tulemuse ootel", + "results": { + "range": { + "normal": "Normaalne vahemik" + } + } +} \ No newline at end of file diff --git a/styles/theme.css b/styles/theme.css index 2b766a7..46641c3 100644 --- a/styles/theme.css +++ b/styles/theme.css @@ -135,8 +135,8 @@ --animate-accordion-down: accordion-down 0.2s ease-out; --animate-accordion-up: accordion-up 0.2s ease-out; - --breakpoint-xs: 30rem; - --breakpoint-sm: 48rem; + --breakpoint-xs: 48rem; + --breakpoint-sm: 64rem; --breakpoint-md: 70rem; --breakpoint-lg: 80rem; --breakpoint-xl: 96rem; diff --git a/utils/medusa-product.ts b/utils/medusa-product.ts index a93669b..ef4384f 100644 --- a/utils/medusa-product.ts +++ b/utils/medusa-product.ts @@ -5,7 +5,7 @@ export const getAnalysisElementMedusaProductIds = (products: ({ metadata?: { ana const mapped = products .flatMap((product) => { - const value = product?.metadata?.analysisElementMedusaProductIds; + const value = product?.metadata?.analysisElementMedusaProductIds?.replaceAll("'", '"'); try { return JSON.parse(value as string); } catch (e) {