fix(mobile): birthday picker date order follows locale (#29419)

* fix(mobile): birthday picker date order follows locale

* test(mobile): cover date order locales for the birthday picker
This commit is contained in:
Santo Shakil
2026-07-23 02:32:17 +05:30
committed by GitHub
parent 9403e71d23
commit 36dfc98527
2 changed files with 85 additions and 0 deletions
@@ -65,6 +65,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(16.0)),
child: ScrollDatePicker(
viewType: datePickerColumnOrder(DateFormat.yMd(context.locale.toLanguageTag()).pattern),
options: DatePickerOptions(
backgroundColor: context.colorScheme.surfaceContainerHigh,
itemExtent: 50,
@@ -118,3 +119,18 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
);
}
}
List<DatePickerViewType>? datePickerColumnOrder(String? pattern) {
if (pattern == null) {
return null;
}
final positions = {
DatePickerViewType.year: pattern.indexOf('y'),
DatePickerViewType.month: pattern.indexOf('M'),
DatePickerViewType.day: pattern.indexOf('d'),
};
if (positions.values.any((position) => position < 0)) {
return null;
}
return positions.keys.toList()..sort((a, b) => positions[a]!.compareTo(positions[b]!));
}
@@ -0,0 +1,69 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/presentation/widgets/people/person_edit_birthday_modal.widget.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';
import 'package:scroll_date_picker/scroll_date_picker.dart';
void main() {
group('datePickerColumnOrder', () {
test('month first (en_US)', () {
expect(
datePickerColumnOrder('M/d/y'),
orderedEquals([DatePickerViewType.month, DatePickerViewType.day, DatePickerViewType.year]),
);
});
test('day first (pl)', () {
expect(
datePickerColumnOrder('dd.MM.y'),
orderedEquals([DatePickerViewType.day, DatePickerViewType.month, DatePickerViewType.year]),
);
});
test('year first (ko)', () {
expect(
datePickerColumnOrder('y. M. d.'),
orderedEquals([DatePickerViewType.year, DatePickerViewType.month, DatePickerViewType.day]),
);
});
test('null pattern falls back to package default', () {
expect(datePickerColumnOrder(null), isNull);
});
test('missing field falls back to package default', () {
expect(datePickerColumnOrder('M/y'), isNull);
});
});
group('datePickerColumnOrder with real locale patterns', () {
setUpAll(() async {
await initializeDateFormatting();
});
for (final (locales, order, name) in const [
(
['en', 'en-US', 'en-PH'],
[DatePickerViewType.month, DatePickerViewType.day, DatePickerViewType.year],
'month/day/year',
),
(
['en-GB', 'fr', 'fr-FR', 'de', 'de-DE', 'pl'],
[DatePickerViewType.day, DatePickerViewType.month, DatePickerViewType.year],
'day/month/year',
),
(
['ja', 'ja-JP', 'zh', 'zh-CN', 'ko', 'ko-KR'],
[DatePickerViewType.year, DatePickerViewType.month, DatePickerViewType.day],
'year/month/day',
),
(['ky'], [DatePickerViewType.year, DatePickerViewType.day, DatePickerViewType.month], 'year/day/month'),
]) {
for (final locale in locales) {
test('$locale uses $name', () {
expect(datePickerColumnOrder(DateFormat.yMd(locale).pattern), orderedEquals(order));
});
}
}
});
}