Skip to content

Commit 7a2c5e0

Browse files
committed
feat: hide non-active questions by default
1 parent d8db1d5 commit 7a2c5e0

File tree

8 files changed

+105
-14
lines changed

8 files changed

+105
-14
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"next-logger": "^5.0.1",
3838
"nextleton": "^0.6.1",
3939
"node-cron": "^3.0.3",
40+
"nuqs": "^2.3.1",
4041
"pino": "^9.5.0",
4142
"postcss": "^8.4.49",
4243
"prisma": "6.1.0",

src/app/layout.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import './global.css'
22

33
import { PropsWithChildren, ReactElement } from 'react'
4+
import { NuqsAdapter } from 'nuqs/adapters/next/app'
45

56
import Header from '../components/Header'
67
import Footer from '../components/Footer'
@@ -13,7 +14,9 @@ export default async function RootLayout({ children }: PropsWithChildren): Promi
1314
<html lang="en">
1415
<body className="flex flex-col min-h-screen">
1516
<Header />
16-
<main className="container p-4 sm:p-16 sm:pt-4 min-h-fit grow">{children}</main>
17+
<main className="container p-4 sm:p-16 sm:pt-4 min-h-fit grow">
18+
<NuqsAdapter>{children}</NuqsAdapter>
19+
</main>
1720
<Footer />
1821
</body>
1922
</html>

src/app/team/[groupId]/[teamId]/graph/page.tsx

+26-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as R from 'remeda'
22
import React, { ReactElement, Suspense } from 'react'
33
import { Metadata } from 'next'
44
import { BodyLong, Detail, Heading, Skeleton } from '@navikt/ds-react'
5+
import { SearchParams } from 'nuqs'
56

67
import { TeamNotAccesible, TeamNotFound } from '../../../../../components/errors/ErrorMessages'
78
import { userHasAdGroup } from '../../../../../auth/authentication'
@@ -12,6 +13,8 @@ import OverallScoreGraph from '../../../../../components/graphs/OverallScoreGrap
1213
import { getWeekNumber } from '../../../../../utils/date'
1314
import ScorePerQuestion from '../../../../../components/graphs/ScorePerQuestion'
1415
import { raise } from '../../../../../utils/ts-utils'
16+
import OnlyCurrentQuestionsToggle from '../../../../../components/graphs/OnlyCurrentQuestionsToggle'
17+
import { loadSearchParams } from '../../../../../components/graphs/only-current-search-params'
1518

1619
export const metadata: Metadata = {
1720
title: 'Helsesjekk | Team | Graf',
@@ -23,10 +26,13 @@ type Props = {
2326
groupId: string
2427
teamId: string
2528
}>
29+
searchParams: Promise<SearchParams>
2630
}
2731

28-
async function Page({ params }: Props): Promise<ReactElement> {
32+
async function Page({ params, searchParams }: Props): Promise<ReactElement> {
2933
const pageParams = await params
34+
const queryParams = await loadSearchParams(searchParams)
35+
3036
const team = await getTeamByAdGroupAndTeamId(pageParams.groupId, pageParams.teamId)
3137
if (!team) {
3238
return (
@@ -54,7 +60,7 @@ async function Page({ params }: Props): Promise<ReactElement> {
5460
<OverallGraph teamId={team.id} />
5561
</Suspense>
5662
<Suspense fallback={<Skeleton height={300} variant="rounded" />}>
57-
<PerQuestionGraph teamId={team.id} />
63+
<PerQuestionGraph teamId={team.id} showOld={queryParams['show-old'] ?? false} />
5864
</Suspense>
5965
</div>
6066
)
@@ -102,7 +108,7 @@ async function OverallGraph({ teamId }: { teamId: string }): Promise<ReactElemen
102108
)
103109
}
104110

105-
async function PerQuestionGraph({ teamId }: { teamId: string }): Promise<ReactElement> {
111+
async function PerQuestionGraph({ teamId, showOld }: { teamId: string; showOld: boolean }): Promise<ReactElement> {
106112
const teamMetrics = await getTeamScorePerQuestion(teamId)
107113

108114
if ('error' in teamMetrics) {
@@ -128,17 +134,24 @@ async function PerQuestionGraph({ teamId }: { teamId: string }): Promise<ReactEl
128134

129135
return (
130136
<div>
131-
<Heading size="medium" level="3">
132-
Score per spørsmål per uke
133-
</Heading>
134-
<Detail>
135-
{teamMetrics.length} målinger siden Uke {getWeekNumber(earliest.timestamp)},{' '}
136-
{earliest.timestamp.getFullYear()}
137-
</Detail>
137+
<div className="flex justify-between">
138+
<div>
139+
<Heading size="medium" level="3">
140+
Score per spørsmål per uke
141+
</Heading>
142+
<Detail>
143+
{teamMetrics.length} målinger siden Uke {getWeekNumber(earliest.timestamp)},{' '}
144+
{earliest.timestamp.getFullYear()}
145+
</Detail>
146+
</div>
147+
<OnlyCurrentQuestionsToggle />
148+
</div>
138149
<div className="mt-4">
139-
{teamMetrics.map((it) => (
140-
<ScorePerQuestion key={it.question.questionId} question={it.question} scoring={it.scoring} />
141-
))}
150+
{teamMetrics
151+
.filter((it) => (showOld ? true : it.question.isCurrent))
152+
.map((it) => (
153+
<ScorePerQuestion key={it.question.questionId} question={it.question} scoring={it.scoring} />
154+
))}
142155
</div>
143156
</div>
144157
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use client'
2+
3+
import React, { ReactElement, startTransition } from 'react'
4+
import { Switch } from '@navikt/ds-react'
5+
import { useQueryState } from 'nuqs'
6+
7+
import { showOldSearchParams } from './only-current-search-params'
8+
9+
function OnlyCurrentQuestionsToggle(): ReactElement {
10+
const [showOld, setShowOld] = useQueryState('show-old', showOldSearchParams['show-old'])
11+
12+
return (
13+
<Switch
14+
position="right"
15+
checked={showOld}
16+
onChange={(event) =>
17+
startTransition(async () => {
18+
await setShowOld(event.target.checked)
19+
})
20+
}
21+
>
22+
Vis gamle spørsmål
23+
</Switch>
24+
)
25+
}
26+
27+
export default OnlyCurrentQuestionsToggle
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { createLoader, parseAsBoolean } from 'nuqs/server'
2+
3+
export const showOldSearchParams = {
4+
'show-old': parseAsBoolean.withDefault(false).withOptions({
5+
clearOnDefault: true,
6+
shallow: false,
7+
}),
8+
}
9+
10+
export const loadSearchParams = createLoader(showOldSearchParams)

src/db/score.ts

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getYear } from 'date-fns'
44
import { scoreAsked, ScoredAsk, ScoredQuestion } from '../metrics/metrics'
55
import { getWeekNumber } from '../utils/date'
66
import { QuestionScorePerWeek, QuestionType } from '../safe-types'
7+
import { questionsFromJsonb } from '../questions/jsonb-utils'
78

89
import { prisma } from './prisma'
910

@@ -85,13 +86,16 @@ export async function getTeamScorePerQuestion(teamId: string): Promise<QuestionS
8586
R.map(scoreAsked),
8687
)
8788

89+
const currentQuestionIds = questionsFromJsonb(team.questions).map((it) => it.questionId)
90+
8891
const scoredQuestionToScorePerWeek = (
8992
scoredQuestion: ScoredQuestion & { timestamp: Date },
9093
): QuestionScorePerWeek => ({
9194
question: {
9295
questionId: scoredQuestion.id,
9396
question: scoredQuestion.question,
9497
answers: scoredQuestion.answers,
98+
isCurrent: currentQuestionIds.includes(scoredQuestion.id),
9599
},
96100
scoring: [
97101
{

src/safe-types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export type QuestionScorePerWeek = {
4444
questionId: string
4545
question: string
4646
answers: Record<AnswerLevel, string>
47+
isCurrent: boolean
4748
}
4849
scoring: QuestionScoring[]
4950
}

yarn.lock

+32
Original file line numberDiff line numberDiff line change
@@ -3692,6 +3692,7 @@ __metadata:
36923692
next-logger: "npm:^5.0.1"
36933693
nextleton: "npm:^0.6.1"
36943694
node-cron: "npm:^3.0.3"
3695+
nuqs: "npm:^2.3.1"
36953696
pino: "npm:^9.5.0"
36963697
pino-pretty: "npm:^13.0.0"
36973698
postcss: "npm:^8.4.49"
@@ -4784,6 +4785,13 @@ __metadata:
47844785
languageName: node
47854786
linkType: hard
47864787

4788+
"mitt@npm:^3.0.1":
4789+
version: 3.0.1
4790+
resolution: "mitt@npm:3.0.1"
4791+
checksum: 10/287c70d8e73ffc25624261a4989c783768aed95ecb60900f051d180cf83e311e3e59865bfd6e9d029cdb149dc20ba2f128a805e9429c5c4ce33b1416c65bbd14
4792+
languageName: node
4793+
linkType: hard
4794+
47874795
"mkdirp@npm:^3.0.1":
47884796
version: 3.0.1
47894797
resolution: "mkdirp@npm:3.0.1"
@@ -5004,6 +5012,30 @@ __metadata:
50045012
languageName: node
50055013
linkType: hard
50065014

5015+
"nuqs@npm:^2.3.1":
5016+
version: 2.3.1
5017+
resolution: "nuqs@npm:2.3.1"
5018+
dependencies:
5019+
mitt: "npm:^3.0.1"
5020+
peerDependencies:
5021+
"@remix-run/react": ">=2"
5022+
next: ">=14.2.0"
5023+
react: ">=18.2.0 || ^19.0.0-0"
5024+
react-router: ^6 || ^7
5025+
react-router-dom: ^6 || ^7
5026+
peerDependenciesMeta:
5027+
"@remix-run/react":
5028+
optional: true
5029+
next:
5030+
optional: true
5031+
react-router:
5032+
optional: true
5033+
react-router-dom:
5034+
optional: true
5035+
checksum: 10/2abf3b7040a621273546562fe7c9d5dcb0381c439e26cedde5544920a201416ed631f21b99962033db7fc56e83f7de4be11d7bd960dba477acb670553cb84eb6
5036+
languageName: node
5037+
linkType: hard
5038+
50075039
"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1":
50085040
version: 4.1.1
50095041
resolution: "object-assign@npm:4.1.1"

0 commit comments

Comments
 (0)