feat(MED-168): clean up types, show nested elements
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { redirect } from 'next/navigation';
|
import { redirect } from 'next/navigation';
|
||||||
|
|
||||||
@@ -64,8 +65,7 @@ export default async function AnalysisResultsPage({
|
|||||||
<Trans i18nKey="analysis-results:pageTitle" />
|
<Trans i18nKey="analysis-results:pageTitle" />
|
||||||
</h4>
|
</h4>
|
||||||
<p className="text-muted-foreground text-sm">
|
<p className="text-muted-foreground text-sm">
|
||||||
{analysisResponse?.elements &&
|
{orderedAnalysisElements.length > 0 ? (
|
||||||
analysisResponse.elements?.length > 0 ? (
|
|
||||||
<Trans i18nKey="analysis-results:description" />
|
<Trans i18nKey="analysis-results:description" />
|
||||||
) : (
|
) : (
|
||||||
<Trans i18nKey="analysis-results:descriptionEmpty" />
|
<Trans i18nKey="analysis-results:descriptionEmpty" />
|
||||||
@@ -106,7 +106,16 @@ export default async function AnalysisResultsPage({
|
|||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{orderedAnalysisElements ? (
|
{orderedAnalysisElements ? (
|
||||||
orderedAnalysisElements.map((element, index) => (
|
orderedAnalysisElements.map((element, index) => (
|
||||||
<Analysis key={index} element={element} />
|
<React.Fragment key={element.analysisIdOriginal}>
|
||||||
|
<Analysis element={element} />
|
||||||
|
{element.results?.nestedElements?.map((nestedElement, nestedIndex) => (
|
||||||
|
<Analysis
|
||||||
|
key={`nested-${nestedElement.analysisElementOriginalId}-${nestedIndex}`}
|
||||||
|
nestedElement={nestedElement}
|
||||||
|
isNestedElement
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</React.Fragment>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div className="text-muted-foreground text-sm">
|
<div className="text-muted-foreground text-sm">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useMemo } from 'react';
|
|||||||
import { ArrowDown } from 'lucide-react';
|
import { ArrowDown } from 'lucide-react';
|
||||||
|
|
||||||
import { cn } from '@kit/ui/utils';
|
import { cn } from '@kit/ui/utils';
|
||||||
import { AnalysisResultDetailsElementResults } from '@/packages/features/accounts/src/types/analysis-results';
|
import type { AnalysisResultDetailsElementResults } from '@/packages/features/user-analyses/src/types/analysis-results';
|
||||||
|
|
||||||
export enum AnalysisResultLevel {
|
export enum AnalysisResultLevel {
|
||||||
NORMAL = 0,
|
NORMAL = 0,
|
||||||
@@ -11,6 +11,8 @@ export enum AnalysisResultLevel {
|
|||||||
CRITICAL = 2,
|
CRITICAL = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AnalysisResultLevelBarResults = Pick<AnalysisResultDetailsElementResults, 'normLower' | 'normUpper' | 'responseValue'>;
|
||||||
|
|
||||||
const Level = ({
|
const Level = ({
|
||||||
isActive = false,
|
isActive = false,
|
||||||
color,
|
color,
|
||||||
@@ -60,28 +62,19 @@ const Level = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AnalysisLevelBarSkeleton = () => {
|
|
||||||
return (
|
|
||||||
<div className="mt-4 flex h-3 w-[60%] sm:w-[35%] max-w-[360px] gap-1 sm:mt-0">
|
|
||||||
<Level color="gray-200" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const AnalysisLevelBar = ({
|
const AnalysisLevelBar = ({
|
||||||
level,
|
level,
|
||||||
results,
|
results: {
|
||||||
|
normLower: lower,
|
||||||
|
normUpper: upper,
|
||||||
|
responseValue: value,
|
||||||
|
},
|
||||||
normRangeText,
|
normRangeText,
|
||||||
}: {
|
}: {
|
||||||
level: AnalysisResultLevel;
|
level: AnalysisResultLevel;
|
||||||
results: AnalysisResultDetailsElementResults;
|
results: AnalysisResultLevelBarResults;
|
||||||
normRangeText: string | null;
|
normRangeText: string | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const { normLower: lower, normUpper: upper, responseValue: value, normStatus } = results;
|
|
||||||
const normLowerIncluded = results?.normLowerIncluded || false;
|
|
||||||
const normUpperIncluded = results?.normUpperIncluded || false;
|
|
||||||
|
|
||||||
// Calculate arrow position based on value within normal range
|
// Calculate arrow position based on value within normal range
|
||||||
const arrowLocation = useMemo(() => {
|
const arrowLocation = useMemo(() => {
|
||||||
// If no response value, center the arrow
|
// If no response value, center the arrow
|
||||||
@@ -147,7 +140,6 @@ const AnalysisLevelBar = ({
|
|||||||
|
|
||||||
// Show appropriate levels based on available norm bounds
|
// Show appropriate levels based on available norm bounds
|
||||||
const hasLowerBound = lower !== null;
|
const hasLowerBound = lower !== null;
|
||||||
const isLowerBoundZero = hasLowerBound && lower === 0;
|
|
||||||
const hasUpperBound = upper !== null;
|
const hasUpperBound = upper !== null;
|
||||||
|
|
||||||
// Determine which section the value falls into
|
// Determine which section the value falls into
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { AnalysisResultDetailsElement } from '@/packages/features/accounts/src/types/analysis-results';
|
import type {
|
||||||
|
AnalysisResultDetailsElementResults,
|
||||||
|
AnalysisResultDetailsElement,
|
||||||
|
AnalysisResultsDetailsElementNested,
|
||||||
|
} from '@/packages/features/user-analyses/src/types/analysis-results';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { Info } from 'lucide-react';
|
import { Info } from 'lucide-react';
|
||||||
|
|
||||||
@@ -21,14 +25,45 @@ export enum AnalysisStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Analysis = ({
|
const Analysis = ({
|
||||||
element,
|
element: elementOriginal,
|
||||||
|
nestedElement,
|
||||||
|
isNestedElement = false,
|
||||||
}: {
|
}: {
|
||||||
element: AnalysisResultDetailsElement;
|
element?: AnalysisResultDetailsElement;
|
||||||
|
nestedElement?: AnalysisResultsDetailsElementNested;
|
||||||
|
isNestedElement?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const element = (() => {
|
||||||
|
if (isNestedElement) {
|
||||||
|
return nestedElement!;
|
||||||
|
}
|
||||||
|
return elementOriginal!;
|
||||||
|
})();
|
||||||
|
const results: AnalysisResultDetailsElementResults = useMemo(() => {
|
||||||
|
if (isNestedElement) {
|
||||||
|
const nestedElement = element as AnalysisResultsDetailsElementNested;
|
||||||
|
return {
|
||||||
|
analysisElementOriginalId: nestedElement.analysisElementOriginalId,
|
||||||
|
normLower: nestedElement.normLower,
|
||||||
|
normUpper: nestedElement.normUpper,
|
||||||
|
normStatus: nestedElement.normStatus,
|
||||||
|
responseTime: nestedElement.responseTime,
|
||||||
|
responseValue: nestedElement.responseValue,
|
||||||
|
responseValueIsNegative: nestedElement.responseValueIsNegative,
|
||||||
|
responseValueIsWithinNorm: nestedElement.responseValueIsWithinNorm,
|
||||||
|
normLowerIncluded: nestedElement.normLowerIncluded,
|
||||||
|
normUpperIncluded: nestedElement.normUpperIncluded,
|
||||||
|
unit: nestedElement.unit,
|
||||||
|
status: nestedElement.status,
|
||||||
|
nestedElements: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (element as AnalysisResultDetailsElement).results;
|
||||||
|
}, [element, isNestedElement]);
|
||||||
|
|
||||||
const name = element.analysisName || '';
|
const name = element.analysisName || '';
|
||||||
const results = element.results;
|
|
||||||
|
|
||||||
const hasIsWithinNorm = results?.responseValueIsWithinNorm !== null;
|
const hasIsWithinNorm = results?.responseValueIsWithinNorm !== null;
|
||||||
const hasIsNegative = results?.responseValueIsNegative !== null;
|
const hasIsNegative = results?.responseValueIsNegative !== null;
|
||||||
@@ -58,8 +93,8 @@ const Analysis = ({
|
|||||||
return responseValue;
|
return responseValue;
|
||||||
})();
|
})();
|
||||||
const unit = results?.unit || '';
|
const unit = results?.unit || '';
|
||||||
const normLower = results?.normLower;
|
const normLower = results?.normLower ?? null;
|
||||||
const normUpper = results?.normUpper;
|
const normUpper = results?.normUpper ?? null;
|
||||||
const normStatus = results?.normStatus ?? null;
|
const normStatus = results?.normStatus ?? null;
|
||||||
|
|
||||||
const [showTooltip, setShowTooltip] = useState(false);
|
const [showTooltip, setShowTooltip] = useState(false);
|
||||||
@@ -82,13 +117,18 @@ const Analysis = ({
|
|||||||
const isCancelled = Number(results?.status) === 5;
|
const isCancelled = Number(results?.status) === 5;
|
||||||
const hasNestedElements = results?.nestedElements.length > 0;
|
const hasNestedElements = results?.nestedElements.length > 0;
|
||||||
|
|
||||||
const normRangeText = normLower !== null ? `${normLower} - ${normUpper || ''}` : null;
|
const normRangeText = (() => {
|
||||||
|
if (normLower === null && normUpper === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return `${normLower ?? '...'} - ${normUpper ?? '...'}`;
|
||||||
|
})();
|
||||||
const hasTextualResponse = hasIsNegative || hasIsWithinNorm;
|
const hasTextualResponse = hasIsNegative || hasIsWithinNorm;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-border rounded-lg border px-5">
|
<div className={cn("border-border rounded-lg border px-5", { 'ml-8': isNestedElement })}>
|
||||||
<div className="flex flex-col items-center justify-between gap-2 pt-3 pb-6 sm:py-3 sm:h-[65px] sm:flex-row sm:gap-0">
|
<div className="flex flex-col items-center justify-between gap-2 pt-3 pb-6 sm:py-3 sm:h-[65px] sm:flex-row sm:gap-0">
|
||||||
<div className="flex items-center gap-2 font-semibold">
|
<div className={cn("flex items-center gap-2 font-semibold", { 'font-bold': isNestedElement })}>
|
||||||
{name}
|
{name}
|
||||||
{results?.responseTime && (
|
{results?.responseTime && (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AnalysisResultDetailsMapped } from "@/packages/features/accounts/src/types/analysis-results";
|
import type { AnalysisResultDetailsMapped } from "@/packages/features/user-analyses/src/types/analysis-results";
|
||||||
|
|
||||||
type AnalysisTestResponse = Omit<AnalysisResultDetailsMapped, 'order' | 'orderedAnalysisElementIds' | 'summary' | 'elements'>;
|
type AnalysisTestResponse = Omit<AnalysisResultDetailsMapped, 'order' | 'orderedAnalysisElementIds' | 'summary' | 'elements'>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { cache } from 'react';
|
import { cache } from 'react';
|
||||||
|
|
||||||
import { AnalysisResultDetailsMapped } from '@kit/accounts/types/analysis-results';
|
import type { AnalysisResultDetailsMapped } from '@/packages/features/user-analyses/src/types/analysis-results';
|
||||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||||
import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api';
|
import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
import { Tables } from '@kit/supabase/database';
|
|
||||||
|
|
||||||
export type AnalysisOrder = Tables<{ schema: 'medreport' }, 'analysis_orders'>;
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
import * as z from 'zod';
|
|
||||||
|
|
||||||
import { Database } from '@kit/supabase/database';
|
|
||||||
|
|
||||||
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[];
|
|
||||||
|
|
||||||
const ElementSchema = z.object({
|
|
||||||
unit: z.string(),
|
|
||||||
norm_lower: z.number(),
|
|
||||||
norm_upper: z.number(),
|
|
||||||
norm_status: z.number(),
|
|
||||||
analysis_name: z.string(),
|
|
||||||
response_time: z.string(),
|
|
||||||
response_value: z.number(),
|
|
||||||
response_value_is_negative: z.boolean(),
|
|
||||||
norm_lower_included: z.boolean(),
|
|
||||||
norm_upper_included: z.boolean(),
|
|
||||||
status: z.string(),
|
|
||||||
analysis_element_original_id: z.string(),
|
|
||||||
original_response_element: z.object({
|
|
||||||
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const OrderSchema = z.object({
|
|
||||||
status: z.string(),
|
|
||||||
medusa_order_id: z.string(),
|
|
||||||
created_at: z.coerce.date(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const DoctorAnalysisFeedbackSchema = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
status: z.string(),
|
|
||||||
user_id: z.string(),
|
|
||||||
created_at: z.coerce.date(),
|
|
||||||
created_by: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const SummarySchema = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
value: z.string(),
|
|
||||||
status: z.string(),
|
|
||||||
user_id: z.string(),
|
|
||||||
created_at: z.coerce.date(),
|
|
||||||
created_by: z.string(),
|
|
||||||
updated_at: z.coerce.date().nullable(),
|
|
||||||
updated_by: z.string(),
|
|
||||||
doctor_user_id: z.string().nullable(),
|
|
||||||
analysis_order_id: z.number(),
|
|
||||||
doctor_analysis_feedback: z.array(DoctorAnalysisFeedbackSchema),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AnalysisResultDetailsSchema = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
analysis_order_id: z.number(),
|
|
||||||
order_number: z.string(),
|
|
||||||
order_status: z.string(),
|
|
||||||
user_id: z.string(),
|
|
||||||
created_at: z.coerce.date(),
|
|
||||||
updated_at: z.coerce.date().nullable(),
|
|
||||||
elements: z.array(ElementSchema),
|
|
||||||
order: OrderSchema,
|
|
||||||
summary: SummarySchema.nullable(),
|
|
||||||
});
|
|
||||||
export type AnalysisResultDetails = z.infer<typeof AnalysisResultDetailsSchema>;
|
|
||||||
|
|
||||||
export type AnalysisResultDetailsElementResults = {
|
|
||||||
unit: string | null;
|
|
||||||
normLower: number | null;
|
|
||||||
normUpper: number | null;
|
|
||||||
normStatus: number | null;
|
|
||||||
responseTime: string | null;
|
|
||||||
responseValue: number | null;
|
|
||||||
responseValueIsNegative: boolean | null;
|
|
||||||
responseValueIsWithinNorm: boolean | null;
|
|
||||||
normLowerIncluded: boolean;
|
|
||||||
normUpperIncluded: boolean;
|
|
||||||
status: string;
|
|
||||||
analysisElementOriginalId: string;
|
|
||||||
nestedElements: {
|
|
||||||
analysisElementOriginalId: string;
|
|
||||||
normLower?: number | null;
|
|
||||||
normLowerIncluded: boolean;
|
|
||||||
normStatus: number;
|
|
||||||
normUpper?: number | null;
|
|
||||||
normUpperIncluded: boolean;
|
|
||||||
responseTime: string;
|
|
||||||
responseValue: number;
|
|
||||||
status: number;
|
|
||||||
unit: string;
|
|
||||||
}[];
|
|
||||||
labComment?: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AnalysisResultDetailsElement = {
|
|
||||||
analysisIdOriginal: string;
|
|
||||||
isWaitingForResults: boolean;
|
|
||||||
analysisName: string;
|
|
||||||
results: AnalysisResultDetailsElementResults;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AnalysisResultDetailsMapped = {
|
|
||||||
id: number;
|
|
||||||
order: {
|
|
||||||
status: string;
|
|
||||||
medusaOrderId: string;
|
|
||||||
createdAt: Date | string;
|
|
||||||
};
|
|
||||||
elements: {
|
|
||||||
id: string;
|
|
||||||
unit: string;
|
|
||||||
norm_lower: number;
|
|
||||||
norm_upper: number;
|
|
||||||
norm_status: number;
|
|
||||||
analysis_name: string;
|
|
||||||
response_time: string;
|
|
||||||
response_value: number;
|
|
||||||
norm_lower_included: boolean;
|
|
||||||
norm_upper_included: boolean;
|
|
||||||
status: string;
|
|
||||||
analysis_element_original_id: string;
|
|
||||||
}[];
|
|
||||||
orderedAnalysisElementIds: number[];
|
|
||||||
orderedAnalysisElements: AnalysisResultDetailsElement[];
|
|
||||||
summary: {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
user_id: string;
|
|
||||||
created_at: Date;
|
|
||||||
created_by: string;
|
|
||||||
value?: string;
|
|
||||||
} | null;
|
|
||||||
};
|
|
||||||
@@ -2,9 +2,9 @@ import { SupabaseClient } from '@supabase/supabase-js';
|
|||||||
|
|
||||||
import { Database } from '@kit/supabase/database';
|
import { Database } from '@kit/supabase/database';
|
||||||
import { toArray } from '@kit/shared/utils';
|
import { toArray } from '@kit/shared/utils';
|
||||||
import type { UuringElement, UuringuVastus } from '@kit/shared/types/medipost-analysis';
|
import type { UuringuVastus } from '@kit/shared/types/medipost-analysis';
|
||||||
|
|
||||||
import type { AnalysisResultDetails, AnalysisResultDetailsMapped, UserAnalysis } from '../types/analysis-results';
|
import type { AnalysisResultDetails, AnalysisResultDetailsMapped, AnalysisResultsDetailsElementNested, UserAnalysis } from '../types/analysis-results';
|
||||||
import type { AnalysisOrder } from '../types/analysis-orders';
|
import type { AnalysisOrder } from '../types/analysis-orders';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,28 +166,14 @@ class UserAnalysesApi {
|
|||||||
if (!nestedAnalysisElement) {
|
if (!nestedAnalysisElement) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
results.nestedElements.push({
|
|
||||||
...nestedAnalysisElement,
|
|
||||||
analysisElementOriginalId,
|
|
||||||
analysisName: nestedAnalysisElement.analysis_name_lab,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mappedOrderedAnalysisElements.forEach(({ results }) => {
|
nestedElement.analysisElementOriginalId = analysisElementOriginalId;
|
||||||
results?.nestedElements.forEach(({ analysisElementOriginalId }) => {
|
nestedElement.analysisName = nestedAnalysisElement.analysis_name_lab as string | undefined;
|
||||||
const nestedAnalysisElement = nestedAnalysisElements.find(({ id }) => id === analysisElementOriginalId);
|
}
|
||||||
if (nestedAnalysisElement) {
|
results.nestedElements = results.nestedElements.sort((a, b) => a.analysisName?.localeCompare(b.analysisName ?? '') ?? 0);
|
||||||
results?.nestedElements.push({
|
}
|
||||||
...nestedAnalysisElement,
|
} else {
|
||||||
analysisElementOriginalId,
|
console.error('Failed to get nested analysis elements by ids=', nestedAnalysisElementIds, nestedAnalysisElementsError);
|
||||||
analysisName: nestedAnalysisElement.analysis_name_lab,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('Nested analysis element not found for analysis element original id=', analysisElementOriginalId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,16 +204,12 @@ class UserAnalysesApi {
|
|||||||
analysisName: analysisNameLab,
|
analysisName: analysisNameLab,
|
||||||
results: {
|
results: {
|
||||||
nestedElements: (() => {
|
nestedElements: (() => {
|
||||||
const nestedElements = elementResponse.original_response_element?.UuringuElement as UuringElement[] | undefined;
|
const nestedElements = toArray(elementResponse.original_response_element?.UuringuElement)
|
||||||
if (!nestedElements) {
|
return nestedElements.map<AnalysisResultsDetailsElementNested>((element) => {
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return toArray(nestedElements).map((element) => {
|
|
||||||
const mappedResponse = this.mapUuringVastus({
|
const mappedResponse = this.mapUuringVastus({
|
||||||
uuringVastus: element.UuringuVastus as UuringuVastus | undefined,
|
uuringVastus: element.UuringuVastus as UuringuVastus | undefined,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
status: element.UuringOlek,
|
|
||||||
unit: element.Mootyhik ?? null,
|
unit: element.Mootyhik ?? null,
|
||||||
normLower: mappedResponse.normLower,
|
normLower: mappedResponse.normLower,
|
||||||
normUpper: mappedResponse.normUpper,
|
normUpper: mappedResponse.normUpper,
|
||||||
@@ -239,6 +221,7 @@ class UserAnalysesApi {
|
|||||||
normLowerIncluded: mappedResponse.normLowerIncluded,
|
normLowerIncluded: mappedResponse.normLowerIncluded,
|
||||||
normUpperIncluded: mappedResponse.normUpperIncluded,
|
normUpperIncluded: mappedResponse.normUpperIncluded,
|
||||||
analysisElementOriginalId: element.UuringId,
|
analysisElementOriginalId: element.UuringId,
|
||||||
|
status: elementResponse.status,
|
||||||
analysisName: undefined,
|
analysisName: undefined,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -251,12 +234,13 @@ class UserAnalysesApi {
|
|||||||
normStatus: elementResponse.norm_status,
|
normStatus: elementResponse.norm_status,
|
||||||
responseTime: elementResponse.response_time,
|
responseTime: elementResponse.response_time,
|
||||||
responseValue: elementResponse.response_value,
|
responseValue: elementResponse.response_value,
|
||||||
responseValueIsNegative: elementResponse.response_value_is_negative === true,
|
responseValueIsNegative: elementResponse.response_value_is_negative === null ? null : elementResponse.response_value_is_negative === true,
|
||||||
responseValueIsWithinNorm: elementResponse.response_value_is_within_norm === true,
|
responseValueIsWithinNorm: elementResponse.response_value_is_within_norm === null ? null : elementResponse.response_value_is_within_norm === true,
|
||||||
normLowerIncluded: elementResponse.norm_lower_included,
|
normLowerIncluded: elementResponse.norm_lower_included,
|
||||||
normUpperIncluded: elementResponse.norm_upper_included,
|
normUpperIncluded: elementResponse.norm_upper_included,
|
||||||
status: elementResponse.status,
|
status: elementResponse.status,
|
||||||
analysisElementOriginalId: elementResponse.analysis_element_original_id,
|
analysisElementOriginalId: elementResponse.analysis_element_original_id,
|
||||||
|
elementResponse,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as z from 'zod';
|
|
||||||
|
|
||||||
import { Database } from '@kit/supabase/database';
|
import { Database } from '@kit/supabase/database';
|
||||||
|
import { AnalysisOrderStatus, NormStatus } from '@kit/shared/types/medipost-analysis';
|
||||||
|
|
||||||
export type UserAnalysisElement =
|
export type UserAnalysisElement =
|
||||||
Database['medreport']['Tables']['analysis_response_elements']['Row'];
|
Database['medreport']['Tables']['analysis_response_elements']['Row'];
|
||||||
@@ -10,66 +9,109 @@ export type UserAnalysisResponse =
|
|||||||
};
|
};
|
||||||
export type UserAnalysis = UserAnalysisResponse[];
|
export type UserAnalysis = UserAnalysisResponse[];
|
||||||
|
|
||||||
const ElementSchema = z.object({
|
type ElementSchema = {
|
||||||
unit: z.string(),
|
unit: string,
|
||||||
norm_lower: z.number(),
|
norm_lower: number,
|
||||||
norm_upper: z.number(),
|
norm_upper: number,
|
||||||
norm_status: z.number(),
|
norm_status: number,
|
||||||
analysis_name: z.string(),
|
analysis_name: string,
|
||||||
response_time: z.string(),
|
response_time: string,
|
||||||
response_value: z.number(),
|
response_value: number,
|
||||||
response_value_is_negative: z.boolean(),
|
response_value_is_negative: boolean,
|
||||||
response_value_is_within_norm: z.boolean(),
|
response_value_is_within_norm: boolean,
|
||||||
norm_lower_included: z.boolean(),
|
norm_lower_included: boolean,
|
||||||
norm_upper_included: z.boolean(),
|
norm_upper_included: boolean,
|
||||||
status: z.string(),
|
status: string,
|
||||||
analysis_element_original_id: z.string(),
|
analysis_element_original_id: string,
|
||||||
original_response_element: z.object({
|
original_response_element: {
|
||||||
|
UuringuElement: {
|
||||||
|
UuringIdOID: string,
|
||||||
|
UuringId: string,
|
||||||
|
TLyhend: string,
|
||||||
|
KNimetus: string,
|
||||||
|
UuringNimi: string,
|
||||||
|
UuringuKommentaar: string | null,
|
||||||
|
TellijaUuringId: number,
|
||||||
|
TeostajaUuringId: string,
|
||||||
|
UuringOlek: keyof typeof AnalysisOrderStatus,
|
||||||
|
Mootyhik: string | null,
|
||||||
|
Kood: {
|
||||||
|
HkKood: number,
|
||||||
|
HkKoodiKordaja: number,
|
||||||
|
Koefitsient: number,
|
||||||
|
Hind: number,
|
||||||
|
},
|
||||||
|
UuringuVastus: {
|
||||||
|
VastuseVaartus: string,
|
||||||
|
VastuseAeg: string,
|
||||||
|
NormiStaatus: keyof typeof NormStatus,
|
||||||
|
ProoviJarjenumber: number,
|
||||||
|
},
|
||||||
|
UuringuTaitjaAsutuseJnr: number,
|
||||||
|
},
|
||||||
|
UuringuKommentaar: string | null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
}),
|
type OrderSchema = {
|
||||||
});
|
status: string,
|
||||||
|
medusa_order_id: string,
|
||||||
|
created_at: string,
|
||||||
|
};
|
||||||
|
|
||||||
const OrderSchema = z.object({
|
type DoctorAnalysisFeedbackSchema = {
|
||||||
status: z.string(),
|
id: number,
|
||||||
medusa_order_id: z.string(),
|
status: string,
|
||||||
created_at: z.coerce.date(),
|
user_id: string,
|
||||||
});
|
created_at: string,
|
||||||
|
created_by: string,
|
||||||
|
};
|
||||||
|
|
||||||
const DoctorAnalysisFeedbackSchema = z.object({
|
type SummarySchema = {
|
||||||
id: z.number(),
|
id: number,
|
||||||
status: z.string(),
|
value: string,
|
||||||
user_id: z.string(),
|
status: string,
|
||||||
created_at: z.coerce.date(),
|
user_id: string,
|
||||||
created_by: z.string(),
|
created_at: string,
|
||||||
});
|
created_by: string,
|
||||||
|
updated_at: string | null,
|
||||||
|
updated_by: string,
|
||||||
|
doctor_user_id: string | null,
|
||||||
|
analysis_order_id: number,
|
||||||
|
doctor_analysis_feedback: DoctorAnalysisFeedbackSchema[],
|
||||||
|
};
|
||||||
|
|
||||||
const SummarySchema = z.object({
|
export type AnalysisResultDetails = {
|
||||||
id: z.number(),
|
id: number,
|
||||||
value: z.string(),
|
analysis_order_id: number,
|
||||||
status: z.string(),
|
order_number: string,
|
||||||
user_id: z.string(),
|
order_status: string,
|
||||||
created_at: z.coerce.date(),
|
user_id: string,
|
||||||
created_by: z.string(),
|
created_at: string,
|
||||||
updated_at: z.coerce.date().nullable(),
|
updated_at: string | null,
|
||||||
updated_by: z.string(),
|
elements: ElementSchema[],
|
||||||
doctor_user_id: z.string().nullable(),
|
|
||||||
analysis_order_id: z.number(),
|
|
||||||
doctor_analysis_feedback: z.array(DoctorAnalysisFeedbackSchema),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AnalysisResultDetailsSchema = z.object({
|
|
||||||
id: z.number(),
|
|
||||||
analysis_order_id: z.number(),
|
|
||||||
order_number: z.string(),
|
|
||||||
order_status: z.string(),
|
|
||||||
user_id: z.string(),
|
|
||||||
created_at: z.coerce.date(),
|
|
||||||
updated_at: z.coerce.date().nullable(),
|
|
||||||
elements: z.array(ElementSchema),
|
|
||||||
order: OrderSchema,
|
order: OrderSchema,
|
||||||
summary: SummarySchema.nullable(),
|
summary: SummarySchema | null,
|
||||||
});
|
};
|
||||||
export type AnalysisResultDetails = z.infer<typeof AnalysisResultDetailsSchema>;
|
|
||||||
|
export type AnalysisResultsDetailsElementNested = {
|
||||||
|
analysisElementOriginalId: string;
|
||||||
|
analysisName?: string;
|
||||||
|
} & Pick<
|
||||||
|
AnalysisResultDetailsElementResults,
|
||||||
|
'unit' |
|
||||||
|
'normLower' |
|
||||||
|
'normUpper' |
|
||||||
|
'normStatus' |
|
||||||
|
'responseTime' |
|
||||||
|
'responseValue' |
|
||||||
|
'responseValueIsNegative' |
|
||||||
|
'responseValueIsWithinNorm' |
|
||||||
|
'normLowerIncluded' |
|
||||||
|
'normUpperIncluded' |
|
||||||
|
'status' |
|
||||||
|
'analysisElementOriginalId'
|
||||||
|
>;
|
||||||
|
|
||||||
export type AnalysisResultDetailsElementResults = {
|
export type AnalysisResultDetailsElementResults = {
|
||||||
unit: string | null;
|
unit: string | null;
|
||||||
@@ -84,19 +126,7 @@ export type AnalysisResultDetailsElementResults = {
|
|||||||
normUpperIncluded: boolean;
|
normUpperIncluded: boolean;
|
||||||
status: string;
|
status: string;
|
||||||
analysisElementOriginalId: string;
|
analysisElementOriginalId: string;
|
||||||
nestedElements: {
|
nestedElements: AnalysisResultsDetailsElementNested[];
|
||||||
analysisElementOriginalId: string;
|
|
||||||
normLower?: number | null;
|
|
||||||
normLowerIncluded: boolean;
|
|
||||||
normStatus: number | null;
|
|
||||||
normUpper?: number | null;
|
|
||||||
normUpperIncluded: boolean;
|
|
||||||
responseTime: string | null;
|
|
||||||
responseValue: number | null;
|
|
||||||
status: number;
|
|
||||||
unit: string | null;
|
|
||||||
analysisName?: string | null;
|
|
||||||
}[];
|
|
||||||
labComment?: string | null;
|
labComment?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,27 +144,13 @@ export type AnalysisResultDetailsMapped = {
|
|||||||
medusaOrderId: string;
|
medusaOrderId: string;
|
||||||
createdAt: Date | string;
|
createdAt: Date | string;
|
||||||
};
|
};
|
||||||
elements: {
|
|
||||||
id: string;
|
|
||||||
unit: string;
|
|
||||||
norm_lower: number;
|
|
||||||
norm_upper: number;
|
|
||||||
norm_status: number;
|
|
||||||
analysis_name: string;
|
|
||||||
response_time: string;
|
|
||||||
response_value: number;
|
|
||||||
norm_lower_included: boolean;
|
|
||||||
norm_upper_included: boolean;
|
|
||||||
status: string;
|
|
||||||
analysis_element_original_id: string;
|
|
||||||
}[];
|
|
||||||
orderedAnalysisElementIds: number[];
|
orderedAnalysisElementIds: number[];
|
||||||
orderedAnalysisElements: AnalysisResultDetailsElement[];
|
orderedAnalysisElements: AnalysisResultDetailsElement[];
|
||||||
summary: {
|
summary: {
|
||||||
id: number;
|
id: number;
|
||||||
status: string;
|
status: string;
|
||||||
user_id: string;
|
user_id: string;
|
||||||
created_at: Date;
|
created_at: string;
|
||||||
created_by: string;
|
created_by: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
} | null;
|
} | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user