/
query.getAttributes.handler.ts
98 lines (94 loc) · 3.09 KB
/
query.getAttributes.handler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import { prisma } from '@weareinreach/db'
import { handleError } from '~api/lib/errorHandler'
import { type TRPCHandlerParams } from '~api/types/handler'
import { type TGetAttributesSchema } from './query.getAttributes.schema'
const getAttributesFromDb = async (input: TGetAttributesSchema) => {
const { id, slug, category, includeUnsupported } = input
const orgId =
id ?? (await prisma.organization.findUniqueOrThrow({ where: { slug }, select: { id: true } })).id
const result = await prisma.attributeSupplement.findMany({
where: {
attribute: {
active: true,
...(!includeUnsupported ? { tag: { not: 'incompatible-info' } } : {}),
categories: { some: { category: { active: true, tag: category } } },
},
organization: { id: orgId },
active: true,
},
select: {
attribute: {
select: {
id: true,
tag: true,
icon: true,
iconBg: true,
tsKey: true,
tsNs: true,
categories: {
select: { category: { select: { id: true, tag: true, icon: true, renderVariant: true } } },
},
},
},
id: true,
data: true,
boolean: true,
text: { select: { key: true, ns: true, tsKey: { select: { text: true } } } },
country: { select: { cca2: true, id: true, tsKey: true, tsNs: true } },
govDist: { select: { abbrev: true, id: true, tsKey: true, tsNs: true } },
language: { select: { id: true, languageName: true, nativeName: true } },
},
})
const flattened = result.flatMap(({ attribute, ...supplement }) => {
const { categories, ...attributeData } = attribute
return categories.map(({ category: categoryResult }) => ({
categoryId: categoryResult.id,
categoryTag: categoryResult.tag,
categoryIcon: categoryResult.icon,
categoryRenderVariant: categoryResult.renderVariant,
...attributeData,
supplement,
}))
})
return flattened
}
type DatabaseResult = Awaited<ReturnType<typeof getAttributesFromDb>>
type SingleResult = DatabaseResult[number]
type GroupedResult = {
id: SingleResult['categoryId']
tag: SingleResult['categoryTag']
icon: SingleResult['categoryIcon']
renderVariant: SingleResult['categoryRenderVariant']
attributes: Omit<SingleResult, 'categoryId' | 'categoryIcon' | 'categoryTag' | 'categoryRenderVariant'>[]
}
const groupByCategory = (result: DatabaseResult) => {
const grouped = result.reduce<GroupedResult[]>((prev, curr) => {
const { categoryIcon, categoryId, categoryTag, categoryRenderVariant, ...attribute } = curr
const existingIdx = prev.findIndex(({ id }) => id === categoryId)
if (existingIdx < 0) {
return [
...prev,
{
id: curr.categoryId,
tag: curr.categoryTag,
icon: curr.categoryIcon,
renderVariant: curr.categoryRenderVariant,
attributes: [{ ...attribute }],
},
]
}
prev[existingIdx]?.attributes?.push(attribute)
return prev
}, [])
return grouped
}
const getAttributes = async ({ input }: TRPCHandlerParams<TGetAttributesSchema>) => {
try {
const dbResult = await getAttributesFromDb(input)
const formattedResult = groupByCategory(dbResult)
return formattedResult
} catch (error) {
return handleError(error)
}
}
export default getAttributes