Skip to content

Commit 13f3607

Browse files
committed
feat: score journal
1 parent 5b708eb commit 13f3607

File tree

4 files changed

+151
-43
lines changed

4 files changed

+151
-43
lines changed

frontend/app/api/generated.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,13 +1559,13 @@ export type PointHistoryQueryVariables = Exact<{
15591559
}>;
15601560

15611561

1562-
export type PointHistoryQuery = { __typename?: 'Query', myCurrentProject: { __typename?: 'Project', journal: { __typename?: 'ScoreJournalConnection', edges: Array<{ __typename?: 'ScoreJournalEdge', node: { __typename?: 'ScoreJournal', id: string, sourceType: ScoreSourceType, reason?: string | null, points: number, createdAt: any, challenge?: { __typename?: 'Challenge', name: string } | null, source?:
1563-
| { __typename: 'Challenge' }
1564-
| { __typename: 'Event' }
1565-
| { __typename: 'ListeningAchievement' }
1566-
| { __typename: 'ReadingAchievement' }
1567-
| { __typename: 'SimpleAchievement' }
1568-
| { __typename: 'StreakAchievement' }
1562+
export type PointHistoryQuery = { __typename?: 'Query', myCurrentProject: { __typename?: 'Project', journal: { __typename?: 'ScoreJournalConnection', edges: Array<{ __typename?: 'ScoreJournalEdge', node: { __typename?: 'ScoreJournal', id: string, sourceType: ScoreSourceType, reason?: string | null, points: number, createdAt: any, source?:
1563+
| { __typename: 'Challenge', id: string, name: string }
1564+
| { __typename: 'Event', id: string, name: string }
1565+
| { __typename: 'ListeningAchievement', id: string, name: string }
1566+
| { __typename: 'ReadingAchievement', id: string, name: string }
1567+
| { __typename: 'SimpleAchievement', id: string, name: string }
1568+
| { __typename: 'StreakAchievement', id: string, name: string }
15691569
| null } }> } } };
15701570

15711571
export type StandingsGlobalPageQueryVariables = Exact<{
@@ -1956,13 +1956,22 @@ export const PointHistoryDocument = gql`
19561956
node {
19571957
id
19581958
sourceType
1959-
challenge {
1960-
name
1961-
}
1959+
reason
19621960
source {
19631961
__typename
1962+
... on Achievement {
1963+
id
1964+
name
1965+
}
1966+
... on Challenge {
1967+
id
1968+
name
1969+
}
1970+
... on Event {
1971+
id
1972+
name
1973+
}
19641974
}
1965-
reason
19661975
points
19671976
createdAt
19681977
}

frontend/app/components/profile/ProfilePointHistory.vue

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,22 @@ gql(`
77
node {
88
id
99
sourceType
10-
challenge {
11-
name
12-
}
10+
reason
1311
source {
1412
__typename
13+
... on Achievement {
14+
id
15+
name
16+
}
17+
... on Challenge {
18+
id
19+
name
20+
}
21+
... on Event {
22+
id
23+
name
24+
}
1525
}
16-
reason
1726
points
1827
createdAt
1928
}
@@ -30,6 +39,21 @@ const { data, fetching, error } = usePointHistoryQuery({
3039
variables: { first: 100 },
3140
pause: computed(() => !isAuthReady.value || !open.value),
3241
})
42+
43+
function getScoreJournalName(journal: Partial<ScoreJournal>) {
44+
switch (journal.sourceType) {
45+
case ScoreSourceType.Achievement:
46+
return journal.source?.name
47+
case ScoreSourceType.Challenge:
48+
return journal.source?.name
49+
case ScoreSourceType.Event:
50+
return journal.source?.name
51+
case ScoreSourceType.Manual:
52+
return journal.reason
53+
default:
54+
return journal.reason
55+
}
56+
}
3357
</script>
3458

3559
<template>
@@ -49,18 +73,44 @@ const { data, fetching, error } = usePointHistoryQuery({
4973

5074
<LoadingState v-if="fetching" />
5175
<ErrorState v-else-if="error" :error />
52-
<div
76+
<DesignPanel
5377
v-else-if="data?.myCurrentProject.journal.edges.length"
54-
class="space-y-list-section-gap"
78+
class="space-y-list-section-inset p-list-section-inset"
5579
>
56-
<div
57-
v-for="journal in data.myCurrentProject.journal.edges"
80+
<template
81+
v-for="(journal, index) in data.myCurrentProject.journal.edges"
5882
:key="journal.node.id"
5983
>
60-
<span>{{ journal.node.reason }}</span>
61-
<span>{{ journal.node.points }}</span>
62-
</div>
63-
</div>
84+
<div
85+
class="px-3 py-2 rounded-list-inset flex gap-2.5 items-center justify-between"
86+
>
87+
<div>
88+
<p class="text-label">
89+
{{ getScoreJournalName(journal.node) }}
90+
</p>
91+
<span class="text-caption text-text-muted">
92+
{{ formatDate(journal.node.createdAt) }}
93+
</span>
94+
</div>
95+
<span
96+
:class="[
97+
'text-label',
98+
{
99+
'text-accent-contrast': journal.node.points > 0,
100+
'text-text-hint': journal.node.points < 0,
101+
},
102+
]"
103+
>
104+
{{ journal.node.points > 0 ? '+' : '-' }}
105+
{{ journal.node.points }}
106+
</span>
107+
</div>
108+
<hr
109+
v-if="index < data.myCurrentProject.journal.edges.length - 1"
110+
class="mx-3 border-border-default"
111+
/>
112+
</template>
113+
</DesignPanel>
64114
<EmptyState v-else />
65115
</PageLayout>
66116
</template>

frontend/app/utils/formatters.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,36 +20,32 @@ export function capitalizeFirst(str: string): string {
2020
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
2121
}
2222

23+
/**
24+
* Get the current locale from i18n
25+
*/
26+
function getLocale(): string {
27+
const nuxtApp = useNuxtApp()
28+
return nuxtApp.$i18n?.locale?.value || 'en'
29+
}
30+
2331
export function formatDate(dateString: string) {
2432
const date = new Date(dateString)
25-
return date.toLocaleDateString('en-US', {
33+
return date.toLocaleDateString(getLocale(), {
2634
month: 'long',
2735
day: 'numeric',
2836
year: 'numeric',
2937
})
3038
}
3139

3240
export function formatDateRange(startDate: string, endDate: string) {
41+
const locale = getLocale()
3342
const start = new Date(startDate)
3443
const end = new Date(endDate)
3544

36-
const startMonth = start.toLocaleDateString('en-US', { month: 'short' })
37-
const endMonth = end.toLocaleDateString('en-US', { month: 'short' })
38-
const startDay = start.getDate()
39-
const endDay = end.getDate()
40-
const startYear = start.getFullYear()
41-
const endYear = end.getFullYear()
42-
43-
// Same month and year
44-
if (startMonth === endMonth && startYear === endYear) {
45-
return `${startMonth} ${startDay}-${endDay}, ${startYear}`
46-
}
47-
48-
// Same year, different months
49-
if (startYear === endYear) {
50-
return `${startMonth} ${startDay} - ${endMonth} ${endDay}, ${startYear}`
51-
}
52-
53-
// Different years
54-
return `${startMonth} ${startDay}, ${startYear} - ${endMonth} ${endDay}, ${endYear}`
45+
const formatter = new Intl.DateTimeFormat(locale, {
46+
month: 'short',
47+
day: 'numeric',
48+
year: 'numeric',
49+
})
50+
return formatter.formatRange(start, end)
5551
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
type: http_request
2+
model: http_request
3+
id: rq_KV7Pn2H44p
4+
createdAt: 2025-11-27T13:05:40.352277
5+
updatedAt: 2025-11-28T11:32:28.873110
6+
workspaceId: wk_XKsmbMdFg7
7+
folderId: null
8+
authentication: {}
9+
authenticationType: null
10+
body:
11+
query: |
12+
query ScoreJournal {
13+
myCurrentProject {
14+
journal(first: 100) {
15+
edges {
16+
node {
17+
id
18+
sourceType
19+
source {
20+
__typename
21+
... on Achievement {
22+
id
23+
name
24+
}
25+
... on Challenge {
26+
id
27+
name
28+
}
29+
... on Event {
30+
id
31+
name
32+
}
33+
}
34+
points
35+
createdAt
36+
reason
37+
}
38+
}
39+
}
40+
}
41+
}
42+
bodyType: graphql
43+
description: ''
44+
headers:
45+
- enabled: true
46+
name: Content-Type
47+
value: application/json
48+
id: zNW4Vjp7UA
49+
method: POST
50+
name: ''
51+
sortPriority: -1764248740350.0
52+
url: ${[ HOST ]}/graphql
53+
urlParameters: []

0 commit comments

Comments
 (0)