Skip to content

Commit 41c304e

Browse files
feat: add support for all period types from @dhis2/multi-calendar-dates
Expand the period type mappings to include all 52 period types supported by @dhis2/multi-calendar-dates library, including all 12 financial year variants (FYJAN-FYDEC), weekly variants, quarterly variants, and six-monthly variants. This ensures that when a period type like FinancialSep is enabled on the server, it correctly appears in the fixed periods dropdown. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 70a1447 commit 41c304e

7 files changed

Lines changed: 292 additions & 107 deletions

File tree

i18n/en.pot

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ msgstr ""
55
"Content-Type: text/plain; charset=utf-8\n"
66
"Content-Transfer-Encoding: 8bit\n"
77
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
8-
"POT-Creation-Date: 2026-01-27T09:57:38.828Z\n"
9-
"PO-Revision-Date: 2026-01-27T09:57:38.828Z\n"
8+
"POT-Creation-Date: 2026-01-29T11:57:17.738Z\n"
9+
"PO-Revision-Date: 2026-01-29T11:57:17.738Z\n"
1010

1111
msgid "view only"
1212
msgstr "view only"
@@ -880,18 +880,42 @@ msgstr "Six-monthly April"
880880
msgid "Yearly"
881881
msgstr "Yearly"
882882

883-
msgid "Financial year (Start November)"
884-
msgstr "Financial year (Start November)"
883+
msgid "Financial year (Start January)"
884+
msgstr "Financial year (Start January)"
885885

886-
msgid "Financial year (Start October)"
887-
msgstr "Financial year (Start October)"
886+
msgid "Financial year (Start February)"
887+
msgstr "Financial year (Start February)"
888888

889-
msgid "Financial year (Start July)"
890-
msgstr "Financial year (Start July)"
889+
msgid "Financial year (Start March)"
890+
msgstr "Financial year (Start March)"
891891

892892
msgid "Financial year (Start April)"
893893
msgstr "Financial year (Start April)"
894894

895+
msgid "Financial year (Start May)"
896+
msgstr "Financial year (Start May)"
897+
898+
msgid "Financial year (Start June)"
899+
msgstr "Financial year (Start June)"
900+
901+
msgid "Financial year (Start July)"
902+
msgstr "Financial year (Start July)"
903+
904+
msgid "Financial year (Start August)"
905+
msgstr "Financial year (Start August)"
906+
907+
msgid "Financial year (Start September)"
908+
msgstr "Financial year (Start September)"
909+
910+
msgid "Financial year (Start October)"
911+
msgstr "Financial year (Start October)"
912+
913+
msgid "Financial year (Start November)"
914+
msgstr "Financial year (Start November)"
915+
916+
msgid "Financial year (Start December)"
917+
msgstr "Financial year (Start December)"
918+
895919
msgid "Today"
896920
msgstr "Today"
897921

src/components/PeriodDimension/PeriodTransfer.js

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getNowInCalendar } from '@dhis2/multi-calendar-dates'
22
import { IconInfo16, NoticeBox, TabBar, Tab, Transfer } from '@dhis2/ui'
33
import PropTypes from 'prop-types'
4-
import React, { useEffect, useState, useMemo } from 'react'
4+
import React, { useRef, useState, useMemo } from 'react'
55
import PeriodIcon from '../../assets/DimensionItemIcons/PeriodIcon.js' //TODO: Reimplement the icon.js
66
import i18n from '../../locales/index.js'
77
import {
@@ -137,9 +137,7 @@ const PeriodTransfer = ({
137137
reversePeriods: false,
138138
})
139139

140-
const [allPeriods, setAllPeriods] = useState(
141-
defaultRelativePeriodType?.getPeriods() || []
142-
)
140+
const [userPeriods, setUserPeriods] = useState(null)
143141
const [isRelative, setIsRelative] = useState(true)
144142
const [relativeFilter, setRelativeFilter] = useState({
145143
periodType: defaultRelativePeriodType?.id || '',
@@ -149,32 +147,69 @@ const PeriodTransfer = ({
149147
year: defaultFixedPeriodYear.toString(),
150148
})
151149

152-
useEffect(() => {
153-
if (!defaultRelativePeriodType) {
154-
return
150+
const effectiveRelativeFilterType = filteredRelativeOptions.some(
151+
(opt) => opt.id === relativeFilter.periodType
152+
)
153+
? relativeFilter.periodType
154+
: defaultRelativePeriodType?.id || ''
155+
156+
const effectiveFixedFilterType = filteredFixedOptions.some(
157+
(opt) => opt.id === fixedFilter.periodType
158+
)
159+
? fixedFilter.periodType
160+
: defaultFixedPeriodType?.id || ''
161+
162+
const prevEffectiveRelativeRef = useRef(effectiveRelativeFilterType)
163+
const prevEffectiveFixedRef = useRef(effectiveFixedFilterType)
164+
165+
if (prevEffectiveRelativeRef.current !== effectiveRelativeFilterType) {
166+
prevEffectiveRelativeRef.current = effectiveRelativeFilterType
167+
if (relativeFilter.periodType !== effectiveRelativeFilterType) {
168+
setRelativeFilter({ periodType: effectiveRelativeFilterType })
155169
}
156-
setRelativeFilter({ periodType: defaultRelativePeriodType.id })
157170
if (isRelative) {
158-
setAllPeriods(defaultRelativePeriodType.getPeriods())
171+
setUserPeriods(null)
159172
}
160-
}, [defaultRelativePeriodType]) // eslint-disable-line react-hooks/exhaustive-deps
173+
}
161174

162-
useEffect(() => {
163-
if (!defaultFixedPeriodType) {
164-
return
175+
if (prevEffectiveFixedRef.current !== effectiveFixedFilterType) {
176+
prevEffectiveFixedRef.current = effectiveFixedFilterType
177+
if (fixedFilter.periodType !== effectiveFixedFilterType) {
178+
setFixedFilter((prev) => ({
179+
...prev,
180+
periodType: effectiveFixedFilterType,
181+
}))
165182
}
166-
setFixedFilter((prev) => ({
167-
...prev,
168-
periodType: defaultFixedPeriodType.id,
169-
}))
170183
if (!isRelative) {
171-
setAllPeriods(
172-
defaultFixedPeriodType.getPeriods(
173-
fixedPeriodConfig(Number(fixedFilter.year))
174-
) || []
184+
setUserPeriods(null)
185+
}
186+
}
187+
188+
const derivedPeriods = useMemo(() => {
189+
if (isRelative) {
190+
const opt = filteredRelativeOptions.find(
191+
(o) => o.id === effectiveRelativeFilterType
192+
)
193+
return opt?.getPeriods() || []
194+
} else {
195+
const opt = filteredFixedOptions.find(
196+
(o) => o.id === effectiveFixedFilterType
197+
)
198+
return (
199+
opt?.getPeriods(fixedPeriodConfig(Number(fixedFilter.year))) ||
200+
[]
175201
)
176202
}
177-
}, [defaultFixedPeriodType]) // eslint-disable-line react-hooks/exhaustive-deps
203+
}, [
204+
isRelative,
205+
effectiveRelativeFilterType,
206+
effectiveFixedFilterType,
207+
filteredRelativeOptions,
208+
filteredFixedOptions,
209+
fixedFilter.year,
210+
])
211+
212+
const allPeriods = userPeriods !== null ? userPeriods : derivedPeriods
178213

179214
const isActive = (value) => {
180215
const item = selectedItems.find((item) => item.id === value)
@@ -184,21 +219,7 @@ const PeriodTransfer = ({
184219
const onIsRelativeClick = (state) => {
185220
if (state !== isRelative) {
186221
setIsRelative(state)
187-
if (state) {
188-
const selectedOption = filteredRelativeOptions.find(
189-
(opt) => opt.id === relativeFilter.periodType
190-
)
191-
setAllPeriods(selectedOption?.getPeriods() || [])
192-
} else {
193-
const selectedOption = filteredFixedOptions.find(
194-
(opt) => opt.id === fixedFilter.periodType
195-
)
196-
setAllPeriods(
197-
selectedOption?.getPeriods(
198-
fixedPeriodConfig(Number(fixedFilter.year))
199-
) || []
200-
)
201-
}
222+
setUserPeriods(null)
202223
}
203224
}
204225

@@ -233,20 +254,20 @@ const PeriodTransfer = ({
233254
<div className="filterContainer">
234255
{isRelative ? (
235256
<RelativePeriodFilter
236-
currentFilter={relativeFilter.periodType}
257+
currentFilter={effectiveRelativeFilterType}
237258
onSelectFilter={(filter) => {
238259
setRelativeFilter({ periodType: filter })
239260
const selectedOption = filteredRelativeOptions.find(
240261
(opt) => opt.id === filter
241262
)
242-
setAllPeriods(selectedOption?.getPeriods() || [])
263+
setUserPeriods(selectedOption?.getPeriods() || [])
243264
}}
244265
dataTest={`${dataTest}-relative-period-filter`}
245266
availableOptions={filteredRelativeOptions}
246267
/>
247268
) : (
248269
<FixedPeriodFilter
249-
currentPeriodType={fixedFilter.periodType}
270+
currentPeriodType={effectiveFixedFilterType}
250271
currentYear={fixedFilter.year}
251272
onSelectPeriodType={(periodType) => {
252273
onSelectFixedPeriods({
@@ -276,7 +297,7 @@ const PeriodTransfer = ({
276297
const selectedOption = filteredFixedOptions.find(
277298
(opt) => opt.id === filter.periodType
278299
)
279-
setAllPeriods(
300+
setUserPeriods(
280301
selectedOption?.getPeriods(
281302
fixedPeriodConfig(Number(filter.year))
282303
) || []

src/components/PeriodDimension/__tests__/fixedPeriods.spec.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,18 @@ describe('fixedPeriods utils', () => {
3131
'SIXMONTHLY',
3232
'SIXMONTHLYAPR',
3333
'YEARLY',
34-
'FYNOV',
35-
'FYOCT',
36-
'FYJUL',
34+
'FYJAN',
35+
'FYFEB',
36+
'FYMAR',
3737
'FYAPR',
38+
'FYMAY',
39+
'FYJUN',
40+
'FYJUL',
41+
'FYAUG',
42+
'FYSEP',
43+
'FYOCT',
44+
'FYNOV',
45+
'FYDEC',
3846
])
3947
})
4048
})

src/components/PeriodDimension/__tests__/utils.spec.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,17 @@ describe('utils', () => {
2727
'SIXMONTHLY',
2828
'SIXMONTHLYAPR',
2929
'YEARLY',
30-
'FYNOV',
31-
'FYJUL',
30+
'FYJAN',
31+
'FYFEB',
32+
'FYMAR',
3233
'FYAPR',
34+
'FYMAY',
35+
'FYJUN',
36+
'FYJUL',
37+
'FYAUG',
38+
'FYSEP',
39+
'FYNOV',
40+
'FYDEC',
3341
])
3442
})
3543

src/components/PeriodDimension/utils/enabledPeriodTypes.js

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,103 @@
22
export const SERVER_PT_TO_MULTI_CALENDAR_PT = {
33
Daily: 'DAILY',
44
Weekly: 'WEEKLY',
5+
WeeklyMonday: 'WEEKLYMON',
6+
WeeklyTuesday: 'WEEKLYTUE',
57
WeeklyWednesday: 'WEEKLYWED',
68
WeeklyThursday: 'WEEKLYTHU',
9+
WeeklyFriday: 'WEEKLYFRI',
710
WeeklySaturday: 'WEEKLYSAT',
811
WeeklySunday: 'WEEKLYSUN',
912
BiWeekly: 'BIWEEKLY',
1013
Monthly: 'MONTHLY',
1114
BiMonthly: 'BIMONTHLY',
1215
Quarterly: 'QUARTERLY',
16+
QuarterlyJan: 'QUARTERLYJAN',
17+
QuarterlyFeb: 'QUARTERLYFEB',
18+
QuarterlyMar: 'QUARTERLYMAR',
19+
QuarterlyApr: 'QUARTERLYAPR',
20+
QuarterlyMay: 'QUARTERLYMAY',
21+
QuarterlyJun: 'QUARTERLYJUN',
22+
QuarterlyJul: 'QUARTERLYJUL',
23+
QuarterlyAug: 'QUARTERLYAUG',
24+
QuarterlySep: 'QUARTERLYSEP',
25+
QuarterlyOct: 'QUARTERLYOCT',
26+
QuarterlyNov: 'QUARTERLYNOV',
27+
QuarterlyDec: 'QUARTERLYDEC',
1328
SixMonthly: 'SIXMONTHLY',
29+
SixMonthlyJan: 'SIXMONTHLYJAN',
30+
SixMonthlyFeb: 'SIXMONTHLYFEB',
31+
SixMonthlyMar: 'SIXMONTHLYMAR',
1432
SixMonthlyApril: 'SIXMONTHLYAPR',
33+
SixMonthlyMay: 'SIXMONTHLYMAY',
34+
SixMonthlyJun: 'SIXMONTHLYJUN',
35+
SixMonthlyJul: 'SIXMONTHLYJUL',
36+
SixMonthlyAug: 'SIXMONTHLYAUG',
37+
SixMonthlySep: 'SIXMONTHLYSEP',
38+
SixMonthlyOct: 'SIXMONTHLYOCT',
39+
SixMonthlyNov: 'SIXMONTHLYNOV',
40+
SixMonthlyDec: 'SIXMONTHLYDEC',
1541
Yearly: 'YEARLY',
42+
FinancialJan: 'FYJAN',
43+
FinancialFeb: 'FYFEB',
44+
FinancialMar: 'FYMAR',
1645
FinancialApril: 'FYAPR',
46+
FinancialMay: 'FYMAY',
47+
FinancialJun: 'FYJUN',
1748
FinancialJuly: 'FYJUL',
49+
FinancialAug: 'FYAUG',
50+
FinancialSep: 'FYSEP',
1851
FinancialOct: 'FYOCT',
1952
FinancialNov: 'FYNOV',
53+
FinancialDec: 'FYDEC',
2054
}
2155

2256
// Mapping from relative period categories to their corresponding fixed period types
2357
export const RP_CATEGORY_TO_FP_DEPENDENCIES = {
2458
DAILY: ['Daily'],
2559
WEEKLY: [
2660
'Weekly',
61+
'WeeklyMonday',
62+
'WeeklyTuesday',
2763
'WeeklyWednesday',
2864
'WeeklyThursday',
65+
'WeeklyFriday',
2966
'WeeklySaturday',
3067
'WeeklySunday',
3168
],
3269
BIWEEKLY: ['BiWeekly'],
3370
MONTHLY: ['Monthly'],
3471
BIMONTHLY: ['BiMonthly'],
35-
QUARTERLY: ['Quarterly'],
36-
SIXMONTHLY: ['SixMonthly', 'SixMonthlyApril'],
72+
QUARTERLY: [
73+
'Quarterly',
74+
'QuarterlyJan',
75+
'QuarterlyFeb',
76+
'QuarterlyMar',
77+
'QuarterlyApr',
78+
'QuarterlyMay',
79+
'QuarterlyJun',
80+
'QuarterlyJul',
81+
'QuarterlyAug',
82+
'QuarterlySep',
83+
'QuarterlyOct',
84+
'QuarterlyNov',
85+
'QuarterlyDec',
86+
],
87+
SIXMONTHLY: [
88+
'SixMonthly',
89+
'SixMonthlyJan',
90+
'SixMonthlyFeb',
91+
'SixMonthlyMar',
92+
'SixMonthlyApril',
93+
'SixMonthlyMay',
94+
'SixMonthlyJun',
95+
'SixMonthlyJul',
96+
'SixMonthlyAug',
97+
'SixMonthlySep',
98+
'SixMonthlyOct',
99+
'SixMonthlyNov',
100+
'SixMonthlyDec',
101+
],
37102
YEARLY: ['Yearly'],
38103
}
39104

0 commit comments

Comments
 (0)