refactor(api): extract resource summary read procedures
This commit is contained in:
@@ -218,6 +218,14 @@ export const ResourceListQuerySchema = ResourceDirectoryQuerySchema.extend({
|
||||
})).optional(),
|
||||
});
|
||||
|
||||
const RESOURCE_DIRECTORY_SELECT = {
|
||||
id: true,
|
||||
eid: true,
|
||||
displayName: true,
|
||||
chapter: true,
|
||||
isActive: true,
|
||||
} as const;
|
||||
|
||||
export async function listStaffResources(
|
||||
ctx: Pick<TRPCContext, "db">,
|
||||
input: z.infer<typeof ResourceListQuerySchema>,
|
||||
@@ -436,6 +444,131 @@ export async function listStaffResources(
|
||||
return { resources, total, page, limit, nextCursor };
|
||||
}
|
||||
|
||||
export async function listResourceDirectoryEntries(
|
||||
ctx: Pick<TRPCContext, "db">,
|
||||
input: z.infer<typeof ResourceDirectoryQuerySchema>,
|
||||
) {
|
||||
const {
|
||||
chapter,
|
||||
chapters,
|
||||
isActive,
|
||||
search,
|
||||
eids,
|
||||
countryIds,
|
||||
excludedCountryIds,
|
||||
includeWithoutCountry,
|
||||
resourceTypes,
|
||||
excludedResourceTypes,
|
||||
includeWithoutResourceType,
|
||||
rolledOff,
|
||||
departed,
|
||||
page,
|
||||
limit,
|
||||
cursor,
|
||||
} = input;
|
||||
const parsedCursor = parseResourceCursor(cursor);
|
||||
type WhereClause = Record<string, unknown>;
|
||||
const andClauses: WhereClause[] = [];
|
||||
const chapterFilters = Array.from(
|
||||
new Set([
|
||||
...(chapter ? [chapter] : []),
|
||||
...(chapters ?? []),
|
||||
]),
|
||||
);
|
||||
|
||||
if (!eids) {
|
||||
andClauses.push({ isActive });
|
||||
} else {
|
||||
andClauses.push({ eid: { in: eids } });
|
||||
}
|
||||
if (chapterFilters.length === 1) {
|
||||
andClauses.push({ chapter: chapterFilters[0] });
|
||||
} else if (chapterFilters.length > 1) {
|
||||
andClauses.push({ chapter: { in: chapterFilters } });
|
||||
}
|
||||
if (search) {
|
||||
andClauses.push({
|
||||
OR: [
|
||||
{ displayName: { contains: search, mode: "insensitive" as const } },
|
||||
{ eid: { contains: search, mode: "insensitive" as const } },
|
||||
],
|
||||
});
|
||||
}
|
||||
if (countryIds && countryIds.length > 0) {
|
||||
const countryClauses: WhereClause[] = [{ countryId: { in: countryIds } }];
|
||||
if (includeWithoutCountry) {
|
||||
countryClauses.push({ countryId: null });
|
||||
}
|
||||
andClauses.push(countryClauses.length === 1 ? countryClauses[0]! : { OR: countryClauses });
|
||||
}
|
||||
if (excludedCountryIds && excludedCountryIds.length > 0) {
|
||||
andClauses.push({ NOT: { countryId: { in: excludedCountryIds } } });
|
||||
}
|
||||
if (!includeWithoutCountry) {
|
||||
andClauses.push({ NOT: { countryId: null } });
|
||||
}
|
||||
if (resourceTypes && resourceTypes.length > 0) {
|
||||
const resourceTypeClauses: WhereClause[] = [{ resourceType: { in: resourceTypes } }];
|
||||
if (includeWithoutResourceType) {
|
||||
resourceTypeClauses.push({ resourceType: null });
|
||||
}
|
||||
andClauses.push(
|
||||
resourceTypeClauses.length === 1 ? resourceTypeClauses[0]! : { OR: resourceTypeClauses },
|
||||
);
|
||||
}
|
||||
if (excludedResourceTypes && excludedResourceTypes.length > 0) {
|
||||
andClauses.push({ NOT: { resourceType: { in: excludedResourceTypes } } });
|
||||
}
|
||||
if (!includeWithoutResourceType) {
|
||||
andClauses.push({ NOT: { resourceType: null } });
|
||||
}
|
||||
if (rolledOff !== undefined) {
|
||||
andClauses.push({ rolledOff });
|
||||
}
|
||||
if (departed !== undefined) {
|
||||
andClauses.push({ departed });
|
||||
}
|
||||
|
||||
const where = andClauses.length > 0 ? { AND: andClauses } : {};
|
||||
const skip = cursor ? 0 : (page - 1) * limit;
|
||||
const orderBy = [{ displayName: "asc" as const }, { id: "asc" as const }];
|
||||
const whereWithCursor = parsedCursor
|
||||
? {
|
||||
AND: [
|
||||
...((where as { AND?: WhereClause[] }).AND ?? []),
|
||||
{
|
||||
OR: [
|
||||
{ displayName: { gt: parsedCursor.displayName } },
|
||||
{ displayName: parsedCursor.displayName, id: { gt: parsedCursor.id } },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
: where;
|
||||
|
||||
const [rawResources, total] = await Promise.all([
|
||||
ctx.db.resource.findMany({
|
||||
where: whereWithCursor,
|
||||
select: RESOURCE_DIRECTORY_SELECT,
|
||||
skip,
|
||||
take: limit + 1,
|
||||
orderBy,
|
||||
}),
|
||||
ctx.db.resource.count({ where }),
|
||||
]);
|
||||
|
||||
const hasMore = rawResources.length > limit;
|
||||
const resources = hasMore ? rawResources.slice(0, limit) : rawResources;
|
||||
const nextCursor = hasMore
|
||||
? JSON.stringify({
|
||||
displayName: resources[resources.length - 1]!.displayName,
|
||||
id: resources[resources.length - 1]!.id,
|
||||
})
|
||||
: null;
|
||||
|
||||
return { resources, total, page, limit, nextCursor };
|
||||
}
|
||||
|
||||
function buildResourceSummaryWhere(input: {
|
||||
search?: string;
|
||||
country?: string;
|
||||
|
||||
Reference in New Issue
Block a user