|
14 | 14 | import type { PageData } from "./$types"; |
15 | 15 | export let data: PageData; |
16 | 16 |
|
17 | | - const mandateStatsCutoffYears = 7; |
18 | | -
|
19 | | - type MandateWithMember = Prisma.MandateGetPayload<{ |
20 | | - include: { member: true }; |
21 | | - }>; |
22 | | -
|
23 | | - $: groupedByYear = data.mandates.reduce<Record<string, MandateWithMember[]>>( |
24 | | - (acc, mandate) => { |
25 | | - let year = mandate.startDate.getFullYear().toString(); |
26 | | - if (mandate.endDate.getFullYear() !== mandate.startDate.getFullYear()) |
27 | | - year += `-${mandate.endDate.getFullYear()}`; |
28 | | - if (!acc[year]) acc[year] = []; |
29 | | - acc[year]!.push(mandate); |
30 | | - return acc; |
31 | | - }, |
32 | | - {}, |
33 | | - ); |
| 17 | + $: groupedByYear = data.mandates.reduce< |
| 18 | + Record< |
| 19 | + string, |
| 20 | + Array<Prisma.MandateGetPayload<{ include: { member: true } }>> |
| 21 | + > |
| 22 | + >((acc, mandate) => { |
| 23 | + let year = mandate.startDate.getFullYear().toString(); |
| 24 | + if (mandate.endDate.getFullYear() !== mandate.startDate.getFullYear()) |
| 25 | + year += `-${mandate.endDate.getFullYear()}`; |
| 26 | + if (!acc[year]) acc[year] = []; |
| 27 | + acc[year]!.push(mandate); |
| 28 | + return acc; |
| 29 | + }, {}); |
34 | 30 | $: years = Object.keys(groupedByYear).sort((a, b) => |
35 | 31 | b.localeCompare(a, languageTag()), |
36 | 32 | ); |
37 | | -
|
38 | | - // Mandates per årskurs |
39 | | - function getStudyYear(mandate: MandateWithMember): number | null { |
40 | | - const start = mandate.startDate; |
41 | | - const classYear = mandate.member.classYear; |
42 | | - if (!classYear || isNaN(start.getTime())) return null; |
43 | | -
|
44 | | - const startAcademicYear = |
45 | | - start.getMonth() >= 7 |
46 | | - ? start.getFullYear() // Aug-Dec -> same year |
47 | | - : start.getFullYear() - 1; // Jan-Jul -> previous year |
48 | | -
|
49 | | - const studyYear = startAcademicYear - classYear + 1; |
50 | | - return studyYear >= 1 ? studyYear : null; |
51 | | - } |
52 | | - $: mandateYearRatios = (() => { |
53 | | - let totalMandateCount = 0; |
54 | | - const counts: Record<number, number> = {}; |
55 | | - for (const mandate of data.mandates) { |
56 | | - const studyYear = getStudyYear(mandate); |
57 | | - if (studyYear === null || studyYear > mandateStatsCutoffYears) { |
58 | | - continue; |
59 | | - } |
60 | | - counts[studyYear] = (counts[studyYear] ?? 0) + 1; |
61 | | - totalMandateCount++; |
62 | | - } |
63 | | -
|
64 | | - // Dynamically generate stats for all årskurser present |
65 | | - return Object.keys(counts) |
66 | | - .map(Number) |
67 | | - .sort((a, b) => a - b) |
68 | | - .map((studyYear) => ({ |
69 | | - studyYear, |
70 | | - percentage: counts ? (counts[studyYear]! / totalMandateCount) * 100 : 0, |
71 | | - })); |
72 | | - })(); |
73 | 33 | let isEditing = false; |
74 | 34 | let isAdding = false; |
75 | 35 | </script> |
|
79 | 39 | class="mb-4 flex flex-col items-start gap-2 md:flex-row md:items-center md:gap-8" |
80 | 40 | > |
81 | 41 | {#if data.position.committee} |
82 | | - <a |
83 | | - href="/committees/{data.position.committee?.shortName}" |
84 | | - class="group self-start" |
85 | | - > |
| 42 | + <a href="/committees/{data.position.committee?.shortName}" class="group"> |
86 | 43 | <figure |
87 | 44 | class="h-32 w-32 transition-transform group-hover:scale-95 md:h-40 md:w-40" |
88 | 45 | > |
|
143 | 100 | {/each} |
144 | 101 | </div> |
145 | 102 | {/if} |
146 | | - {#if mandateYearRatios.length !== 0} |
147 | | - <div class="flex-box mt-4 w-full border-t pt-4"> |
148 | | - <h2 class="flex items-center gap-2 text-lg"> |
149 | | - {m.positions_historical_mandate_distribution_per_study_year()} |
150 | | - <span class="text-sm text-neutral-400"> |
151 | | - ({mandateStatsCutoffYears} {m.positions_years()}) |
152 | | - </span> |
153 | | - </h2> |
154 | | - {#each mandateYearRatios as { studyYear, percentage }} |
155 | | - <div class="flex w-64 flex-row items-center gap-2"> |
156 | | - <div class="bar-label w-24"> |
157 | | - {m.positions_study_year()} {studyYear} |
158 | | - </div> |
159 | | - <progress class="progress" value={percentage} max="100"></progress> |
160 | | - <div class="text-xs text-neutral-400">{percentage.toFixed(1)}%</div> |
161 | | - </div> |
162 | | - {/each} |
163 | | - </div> |
164 | | - {/if} |
165 | 103 | </div> |
166 | 104 | </div> |
167 | 105 |
|
|
0 commit comments