feat(patient-status schema updated)- applied changes

This commit is contained in:
2025-10-30 21:13:33 +05:30
parent 103142b2d3
commit 54f83ab398
9 changed files with 146 additions and 63 deletions

View File

@@ -77,7 +77,6 @@ async function createOrUpdatePatientByInsuranceId(options: {
gender: "",
phone: "",
userId,
status: "inactive",
insuranceId,
};
@@ -219,7 +218,7 @@ router.post(
if (patient && patient.id !== undefined) {
const newStatus =
seleniumResult.eligibility === "Y" ? "active" : "inactive";
seleniumResult.eligibility === "Y" ? "ACTIVE" : "INACTIVE";
await storage.updatePatient(patient.id, { status: newStatus });
outputResult.patientUpdateStatus = `Patient status updated to ${newStatus}`;
@@ -647,7 +646,7 @@ router.post(
// Update patient status based on seleniumResult.eligibility
const newStatus =
seleniumResult?.eligibility === "Y" ? "active" : "inactive";
seleniumResult?.eligibility === "Y" ? "ACTIVE" : "INACTIVE";
await storage.updatePatient(updatedPatient.id, { status: newStatus });
resultItem.patientUpdateStatus = `Patient status updated to ${newStatus}`;

View File

@@ -24,11 +24,14 @@ import {
InsertPatient,
insertPatientSchema,
Patient,
PatientStatus,
patientStatusOptions,
UpdatePatient,
updatePatientSchema,
} from "@repo/db/types";
import { z } from "zod";
import { DateInputField } from "@/components/ui/dateInputField";
import { PatientStatusSchema } from "@repo/db/usedSchemas";
interface PatientFormProps {
patient?: Patient;
@@ -84,7 +87,7 @@ export const PatientForm = forwardRef<PatientFormRef, PatientFormProps>(
policyHolder: "",
allergies: "",
medicalConditions: "",
status: "active",
status: "UNKNOWN",
userId: user?.id,
};
}, [isEditing, patient, extractedInfo, user?.id]);
@@ -297,13 +300,21 @@ export const PatientForm = forwardRef<PatientFormRef, PatientFormProps>(
<FormField
control={form.control}
name="status"
render={({ field }) => (
render={({ field }) => {
const options = Object.values(
patientStatusOptions
) as PatientStatus[]; // ['ACTIVE','INACTIVE','UNKNOWN']
const toLabel = (v: PatientStatus) =>
v[0] + v.slice(1).toLowerCase(); // ACTIVE -> Active
return (
<FormItem>
<FormLabel>Status *</FormLabel>
<Select
onValueChange={field.onChange}
value={field.value}
defaultValue="active"
value={(field.value as PatientStatus) ?? "UNKNOWN"}
onValueChange={(v) =>
field.onChange(v as PatientStatus)
}
>
<FormControl>
<SelectTrigger>
@@ -311,13 +322,17 @@ export const PatientForm = forwardRef<PatientFormRef, PatientFormProps>(
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="active">Active</SelectItem>
<SelectItem value="inactive">Inactive</SelectItem>
{options.map((v) => (
<SelectItem key={v} value={v}>
{toLabel(v)}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
);
}}
/>
<FormField

View File

@@ -39,6 +39,7 @@ import { Checkbox } from "@/components/ui/checkbox";
import { formatDateToHumanReadable } from "@/utils/dateUtils";
import { Patient, UpdatePatient } from "@repo/db/types";
import { PatientFinancialsModal } from "./patient-financial-modal";
import { getPageNumbers } from "@/utils/pageNumberGenerator";
interface PatientApiResponse {
patients: Patient[];
@@ -309,25 +310,6 @@ export function PatientTable({
return colorClasses[id % colorClasses.length];
};
function getPageNumbers(current: number, total: number): (number | "...")[] {
const delta = 2;
const range: (number | "...")[] = [];
const left = Math.max(2, current - delta);
const right = Math.min(total - 1, current + delta);
range.push(1);
if (left > 2) range.push("...");
for (let i = left; i <= right; i++) {
range.push(i);
}
if (right < total - 1) range.push("...");
if (total > 1) range.push(total);
return range;
}
return (
<div className="bg-white shadow rounded-lg overflow-hidden">
<div className="overflow-x-auto">
@@ -440,18 +422,26 @@ export function PatientTable({
</TableCell>
<TableCell>
<div className="col-span-1">
<span
className={cn(
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium",
patient.status === "active"
? "bg-green-100 text-green-800"
: "bg-red-100 text-red-800"
)}
>
{patient.status === "active" ? "Active" : "Inactive"}
{patient.status === "ACTIVE" && (
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
Active
</span>
)}
{patient.status === "INACTIVE" && (
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
Inactive
</span>
)}
{patient.status === "UNKNOWN" && (
<span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-200 text-gray-700">
Unknown
</span>
)}
</div>
</TableCell>
<TableCell className="text-right">
<div className="flex justify-end space-x-2">
{allowDelete && (
@@ -573,15 +563,18 @@ export function PatientTable({
<p>
<span className="text-gray-500">Status:</span>{" "}
<span
className={`${
currentPatient.status === "active"
className={cn(
currentPatient.status === "ACTIVE"
? "text-green-600"
: "text-red-600"
} font-medium`}
: currentPatient.status === "INACTIVE"
? "text-red-600"
: "text-gray-600", // UNKNOWN or fallback
"font-medium"
)}
>
{currentPatient.status
? currentPatient.status.charAt(0).toUpperCase() +
currentPatient.status.slice(1)
currentPatient.status.slice(1).toLowerCase()
: "Unknown"}
</span>
</p>

View File

@@ -251,7 +251,6 @@ export default function InsuranceStatusPage() {
gender: "",
phone: "",
userId: user?.id ?? 1,
status: "active",
insuranceId: memberId,
};
await addPatientMutation.mutateAsync(newPatient);

View File

@@ -254,7 +254,6 @@ export default function PatientsPage() {
gender: "",
phone: "",
userId: user?.id ?? 1,
status: "active",
insuranceId: data.memberId || "",
};

56
migratedb.txt Normal file
View File

@@ -0,0 +1,56 @@
1.
```
npx prisma migrate dev --create-only --name add_patient_status_enum
```
2.
```
-- Create the enum type (quoted name keeps exact case)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'PatientStatus') THEN
CREATE TYPE "PatientStatus" AS ENUM ('ACTIVE', 'INACTIVE', 'UNKNOWN');
END IF;
END$$;
-- 1) Add new enum column (nullable for backfill)
ALTER TABLE "Patient"
ADD COLUMN IF NOT EXISTS "status_new" "PatientStatus";
-- 2) Backfill from old text column to enum (case-insensitive)
UPDATE "Patient"
SET "status_new" = CASE
WHEN "status" IS NULL THEN 'UNKNOWN'::"PatientStatus"
WHEN lower("status") = 'active' THEN 'ACTIVE'::"PatientStatus"
WHEN lower("status") = 'inactive' THEN 'INACTIVE'::"PatientStatus"
ELSE 'UNKNOWN'::"PatientStatus"
END
WHERE "status_new" IS NULL;
-- 3) Safety: ensure no NULLs remain
DO $$
DECLARE cnt INTEGER;
BEGIN
SELECT count(*) INTO cnt FROM "Patient" WHERE "status_new" IS NULL;
IF cnt > 0 THEN
RAISE EXCEPTION 'Migration abort: % rows have NULL status_new', cnt;
END IF;
END$$;
-- 4) Make new column NOT NULL and set DB default to UNKNOWN
ALTER TABLE "Patient"
ALTER COLUMN "status_new" SET DEFAULT 'UNKNOWN',
ALTER COLUMN "status_new" SET NOT NULL;
-- 5) Drop old column and rename new -> status
ALTER TABLE "Patient" DROP COLUMN IF EXISTS "status";
ALTER TABLE "Patient" RENAME COLUMN "status_new" TO "status";
```
3.
```
npx prisma migrate dev
```

View File

@@ -52,7 +52,7 @@ model Patient {
policyHolder String?
allergies String?
medicalConditions String?
status String @default("active")
status PatientStatus @default(UNKNOWN)
userId Int
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id])
@@ -65,6 +65,12 @@ model Patient {
@@index([createdAt])
}
enum PatientStatus {
ACTIVE
INACTIVE
UNKNOWN
}
model Appointment {
id Int @id @default(autoincrement())
patientId Int

View File

@@ -1,5 +1,9 @@
import { PatientUncheckedCreateInputObjectSchema } from "@repo/db/usedSchemas";
import {
PatientStatusSchema,
PatientUncheckedCreateInputObjectSchema,
} from "@repo/db/usedSchemas";
import { z } from "zod";
import { makeEnumOptions } from "../utils";
export type Patient = z.infer<typeof PatientUncheckedCreateInputObjectSchema>;
@@ -28,6 +32,17 @@ export const insuranceIdSchema = z.preprocess(
.nullable()
);
//patient status
export type PatientStatus = z.infer<typeof PatientStatusSchema>;
// enum → select options
export const patientStatusOptions =
makeEnumOptions<
typeof PatientStatusSchema extends z.ZodTypeAny
? z.infer<typeof PatientStatusSchema>
: string
>(PatientStatusSchema);
export const insertPatientSchema = (
PatientUncheckedCreateInputObjectSchema as unknown as z.ZodObject<any>
)

View File

@@ -1,6 +1,7 @@
// using this, as the browser load only the required files , not whole db/shared/schemas/ files.
export * from '../shared/schemas/objects/AppointmentUncheckedCreateInput.schema';
export * from '../shared/schemas/objects/PatientUncheckedCreateInput.schema';
export * from '../shared/schemas/enums/PatientStatus.schema';
export * from '../shared/schemas/objects/UserUncheckedCreateInput.schema';
export * from '../shared/schemas/objects/StaffUncheckedCreateInput.schema'
export * from '../shared/schemas/objects/ClaimUncheckedCreateInput.schema'