fix(visits): reach every lab result, condition, document and visit from the link pickers

The visit form's lab picker offered the newest 200 results, the condition
picker the newest 100 conditions, the document pickers the newest thousand
documents and the document sheet's visit picker the newest 100 visits.
On a long record everything older could not be linked.

Each picker now opens on the records around the date of the thing being
linked, pages older and newer from there, and searches through the list
route itself. Records already linked always show, from the labels the
record's own read carries and from what was picked in the sheet.

The lab list takes a q filter over analyte and panel, the condition list
from/to/q/offset/sortDir, and the visit list an offset.
This commit is contained in:
Marc-André Bombeck committed 2026-10-15 11:24:40 +02:00
1 parent dad9a7778e
commit 73c4dda224
35 files changed
+1714 -251

No files matched your search

+6 -2
View File
@@ -63,6 +63,7 @@ export const GET = apiHandler(async (request: NextRequest) => {
practitionerId: params.get("practitionerId") ?? undefined,
episodeId: params.get("episodeId") ?? undefined,
limit: params.get("limit") ?? undefined,
offset: params.get("offset") ?? undefined,
});
if (!parsed.success) {
return returnAllZodIssues(parsed.error, 422, {
@@ -72,6 +73,7 @@ export const GET = apiHandler(async (request: NextRequest) => {
const query = parsed.data;
const take = query.limit ?? 100;
const skip = query.offset ?? 0;
const now = new Date();
const where = {
@@ -112,8 +114,9 @@ export const GET = apiHandler(async (request: NextRequest) => {
// `gt` and `gte` are different keys, so the caller's lower bound and this
// arm's floor both survive the spread; only the `lte` pair collided.
where: { ...where, occurredAt: { ...where.occurredAt, gt: now } },
orderBy: { occurredAt: "asc" },
orderBy: [{ occurredAt: "asc" }, { id: "asc" }],
take,
skip,
include: ENCOUNTER_INCLUDE,
}),
prisma.encounter.findMany({
@@ -121,8 +124,9 @@ export const GET = apiHandler(async (request: NextRequest) => {
...where,
occurredAt: { ...where.occurredAt, lte: pastCeiling },
},
orderBy: { occurredAt: "desc" },
orderBy: [{ occurredAt: "desc" }, { id: "desc" }],
take,
skip,
include: ENCOUNTER_INCLUDE,
}),
]);
+19 -1
View File
@@ -43,6 +43,11 @@ export const GET = apiHandler(async (request: NextRequest) => {
const parsed = illnessEpisodeListQuerySchema.safeParse({
limit: params.get("limit") ?? undefined,
includeResolved: params.get("includeResolved") ?? undefined,
offset: params.get("offset") ?? undefined,
from: params.get("from") ?? undefined,
to: params.get("to") ?? undefined,
sortDir: params.get("sortDir") ?? undefined,
q: params.get("q") ?? undefined,
});
if (!parsed.success) {
return returnAllZodIssues(parsed.error, 422, {
@@ -50,15 +55,28 @@ export const GET = apiHandler(async (request: NextRequest) => {
});
}
const { from, to, q, offset, sortDir } = parsed.data;
const limit = parsed.data.limit ?? 50;
const order = sortDir ?? "desc";
const rows = await prisma.illnessEpisode.findMany({
where: {
userId: user.id,
deletedAt: null,
...(parsed.data.includeResolved === "false" ? { resolvedAt: null } : {}),
...(from || to
? {
onsetAt: {
...(from ? { gte: new Date(from) } : {}),
...(to ? { lte: new Date(to) } : {}),
},
}
: {}),
...(q ? { label: { contains: q, mode: "insensitive" as const } } : {}),
},
orderBy: { onsetAt: "desc" },
// `id` breaks ties so offset paging never repeats or drops a row.
orderBy: [{ onsetAt: order }, { id: order }],
take: limit,
skip: offset ?? 0,
});
annotate({
+7 -1
View File
@@ -85,7 +85,7 @@ export const GET = apiHandler(async (request: NextRequest) => {
return returnAllZodIssues(parsed.error, 422);
}
const { biomarkerId, analyte, panel, from, to, limit, offset, sortDir } =
const { biomarkerId, analyte, panel, q, from, to, limit, offset, sortDir } =
parsed.data;
const where = {
@@ -94,6 +94,12 @@ export const GET = apiHandler(async (request: NextRequest) => {
...(biomarkerId && { biomarkerId }),
...(analyte && { analyte }),
...(panel && { panel }),
...(q && {
OR: [
{ analyte: { contains: q, mode: "insensitive" as const } },
{ panel: { contains: q, mode: "insensitive" as const } },
],
}),
...(from || to
? {
takenAt: {