Merge branch 'main' into MED-57

This commit is contained in:
Danel Kungla
2025-08-26 11:30:34 +03:00
22 changed files with 507 additions and 225 deletions

View File

@@ -35,6 +35,7 @@ export const selectJobAction = doctorAction(
logger.info({ analysisOrderId }, `Successfully selected`);
revalidateDoctorAnalysis();
return { success: true };
},
{
@@ -60,7 +61,7 @@ export const unselectJobAction = doctorAction(
{ analysisOrderId },
`Successfully removed current doctor from job`,
);
revalidateDoctorAnalysis();
return { success: true };
},
{
@@ -101,6 +102,7 @@ export const giveFeedbackAction = doctorAction(
);
logger.info({ analysisOrderId }, `Successfully submitted feedback`);
revalidateDoctorAnalysis();
return result;
},
{
@@ -108,3 +110,7 @@ export const giveFeedbackAction = doctorAction(
},
),
);
function revalidateDoctorAnalysis() {
revalidatePath('/doctor/analysis');
}

View File

@@ -66,6 +66,27 @@ export const AnalysisResponseSchema = z.object({
updated_at: z.string().nullable(),
analysis_name: z.string().nullable(),
analysis_responses: AnalysisResponsesSchema,
comment: z.string().nullable(),
latestPreviousAnalysis: z
.object({
id: z.number(),
analysis_response_id: z.number(),
analysis_element_original_id: z.string(),
unit: z.string().nullable(),
response_value: z.number(),
response_time: z.string(),
norm_upper: z.number().nullable(),
norm_upper_included: z.boolean().nullable(),
norm_lower: z.number().nullable(),
norm_lower_included: z.boolean().nullable(),
norm_status: z.number().nullable(),
created_at: z.string(),
updated_at: z.string().nullable(),
analysis_name: z.string().nullable(),
comment: z.string().nullable(),
})
.optional()
.nullable(),
});
export type AnalysisResponse = z.infer<typeof AnalysisResponseSchema>;

View File

@@ -15,18 +15,19 @@ export type DoctorJobUnselect = z.infer<typeof doctorJobUnselectSchema>;
export const FeedbackStatus = z.enum(['STARTED', 'DRAFT', 'COMPLETED']);
export const doctorAnalysisFeedbackFormSchema = z.object({
feedbackValue: z.string().min(15),
feedbackValue: z.string().min(10, { message: 'doctor:feedbackLengthError' }),
userId: z.string().uuid(),
});
export type DoctorAnalysisFeedbackForm = z.infer<
typeof doctorAnalysisFeedbackFormSchema
>;
export const doctorAnalysisFeedbackSchema = z.object({
feedbackValue: z.string().min(15),
feedbackValue: z.string(),
userId: z.string().uuid(),
analysisOrderId: z.number(),
status: FeedbackStatus,
});
export type DoctorAnalysisFeedback = z.infer<
typeof doctorAnalysisFeedbackSchema
>;

View File

@@ -1,5 +1,7 @@
import 'server-only';
import { isBefore } from 'date-fns';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { AnalysisResultDetails } from '../schema/doctor-analysis-detail-view.schema';
@@ -360,7 +362,7 @@ export async function getAnalysisResultsForDoctor(
): Promise<AnalysisResultDetails> {
const supabase = getSupabaseServerClient();
const { data: analysisResponse, error } = await supabase
const { data: analysisResponseElements, error } = await supabase
.schema('medreport')
.from(`analysis_response_elements`)
.select(
@@ -373,20 +375,26 @@ export async function getAnalysisResultsForDoctor(
throw new Error('Something went wrong.');
}
const firstAnalysisResponse = analysisResponse?.[0];
const firstAnalysisResponse = analysisResponseElements?.[0];
const userId = firstAnalysisResponse?.analysis_responses.user_id;
const medusaOrderId =
firstAnalysisResponse?.analysis_responses?.analysis_order_id
?.medusa_order_id;
if (!analysisResponse?.length || !userId || !medusaOrderId) {
if (!analysisResponseElements?.length || !userId || !medusaOrderId) {
throw new Error('Failed to retrieve full analysis data.');
}
const responseElementAnalysisElementOriginalIds =
analysisResponseElements.map(
({ analysis_element_original_id }) => analysis_element_original_id,
);
const [
{ data: medusaOrderItems, error: medusaOrderError },
{ data: accountWithParams, error: accountError },
{ data: doctorFeedback, error: feedbackError },
{ data: previousAnalyses, error: previousAnalysesError },
] = await Promise.all([
supabase
.schema('public')
@@ -403,7 +411,7 @@ export async function getAnalysisResultsForDoctor(
.eq('is_personal_account', true)
.eq('primary_owner_user_id', userId)
.limit(1),
await supabase
supabase
.schema('medreport')
.from('doctor_analysis_feedback')
.select(`*`)
@@ -412,9 +420,39 @@ export async function getAnalysisResultsForDoctor(
firstAnalysisResponse.analysis_responses.analysis_order_id.id,
)
.limit(1),
supabase
.schema('medreport')
.from('analysis_response_elements')
.select(
`
*,
analysis_responses!inner(
user_id
)
`,
)
.in(
'analysis_element_original_id',
responseElementAnalysisElementOriginalIds,
)
.not(
'analysis_response_id',
'eq',
firstAnalysisResponse.analysis_response_id,
)
.eq(
'analysis_responses.user_id',
firstAnalysisResponse.analysis_responses.user_id,
)
.order('response_time'),
]);
if (medusaOrderError || accountError || feedbackError) {
if (
medusaOrderError ||
accountError ||
feedbackError ||
previousAnalysesError
) {
throw new Error('Something went wrong.');
}
@@ -433,8 +471,25 @@ export async function getAnalysisResultsForDoctor(
account_params,
} = accountWithParams[0];
const analysisResponseElementsWithPreviousData = [];
for (const analysisResponseElement of analysisResponseElements) {
const latestPreviousAnalysis = previousAnalyses.find(
({ analysis_element_original_id, response_time }) =>
analysis_element_original_id ===
analysisResponseElement.analysis_element_original_id &&
isBefore(
new Date(response_time),
new Date(analysisResponseElement.response_time),
),
);
analysisResponseElementsWithPreviousData.push({
...analysisResponseElement,
latestPreviousAnalysis,
});
}
return {
analysisResponse,
analysisResponse: analysisResponseElementsWithPreviousData,
order: {
title: medusaOrderItems?.[0]?.item_id.product_title ?? '-',
isPackage:

View File

@@ -13,7 +13,7 @@ export function InfoTooltip({
content,
icon,
}: {
content?: string;
content?: string | null;
icon?: JSX.Element;
}) {
if (!content) return null;

View File

@@ -549,6 +549,7 @@ export type Database = {
analysis_element_original_id: string
analysis_name: string | null
analysis_response_id: number
comment: string | null
created_at: string
id: number
norm_lower: number | null
@@ -566,6 +567,7 @@ export type Database = {
analysis_element_original_id: string
analysis_name?: string | null
analysis_response_id: number
comment?: string | null
created_at?: string
id?: number
norm_lower?: number | null
@@ -583,6 +585,7 @@ export type Database = {
analysis_element_original_id?: string
analysis_name?: string | null
analysis_response_id?: number
comment?: string | null
created_at?: string
id?: number
norm_lower?: number | null
@@ -1723,7 +1726,9 @@ export type Database = {
Returns: Json
}
create_team_account: {
Args: { account_name: string; new_personal_code: string }
Args:
| { account_name: string }
| { account_name: string; new_personal_code: string }
Returns: {
application_role: Database["medreport"]["Enums"]["application_role"]
city: string | null
@@ -1911,6 +1916,22 @@ export type Database = {
}
Returns: undefined
}
update_analysis_order_status: {
Args: {
order_id: number
medusa_order_id_param: string
status_param: Database["medreport"]["Enums"]["analysis_order_status"]
}
Returns: {
analysis_element_ids: number[] | null
analysis_ids: number[] | null
created_at: string
id: number
medusa_order_id: string
status: Database["medreport"]["Enums"]["analysis_order_status"]
user_id: string
}
}
upsert_order: {
Args: {
target_account_id: string

View File

@@ -21,6 +21,7 @@ export function useSignUpWithEmailAndPassword() {
const response = await client.auth.signUp({
...credentials,
options: {
emailRedirectTo,
captchaToken,
},
});