Skip to content

Commit

Permalink
feat(digital-guide): add support for levels in rooms section (#534)
Browse files Browse the repository at this point in the history
* feat(digital-guide): add support for levels

* feat(digital-guide): fix linter complaints

* feat(digital-guide): fix linter complaints

* feat(digital-guide): rebase

* feat(digital-guide): decrease padding
  • Loading branch information
mikolaj-jalocha authored Jan 18, 2025
1 parent a8e4fbb commit d34401b
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 36 deletions.
1 change: 1 addition & 0 deletions lib/features/digital_guide_view/data/models/region.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ part "region.g.dart";
class Region with _$Region {
const factory Region({
@JsonKey(name: "adapted_toilets") required List<int> adaptedToiletsIndices,
@JsonKey(name: "rooms") required List<int> roomsIds,
}) = _Region;

factory Region.fromJson(Map<String, dynamic> json) => _$RegionFromJson(json);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:riverpod_annotation/riverpod_annotation.dart";

import "../../../../data/api/digital_guide_get_and_cache.dart";
import "../../../../data/models/digital_guide_response.dart";
import "../../../../data/models/level.dart";
import "../../../../data/models/level_with_regions.dart";
import "../../../../data/models/region.dart";
import "../models/digital_guide_room.dart";

part "rooms_repository.g.dart";

@riverpod
Future<IList<DigitalGuideRoom>> roomsRepository(
Ref ref,
DigitalGuideResponse building,
LevelWithRegions level,
) async {
final String endpoint = "rooms/?building=${building.id}";
Future<DigitalGuideRoom> getDigitalGuideRoom(int roomId) async {
final endpoint = "rooms/$roomId";
return ref.getAndCacheDataFromDigitalGuide(
endpoint,
DigitalGuideRoom.fromJson,
onRetry: () => ref.invalidateSelf(),
);
}

return ref.getAndCacheDataFromDigitalGuide(
endpoint,
(List<dynamic> json) => json
.whereType<Map<String, dynamic>>()
.map(DigitalGuideRoom.fromJson)
.toIList(),
onRetry: () => ref.invalidateSelf(),
);
final roomsIds = level.regions.expand((region) => region.roomsIds);
final rooms = await Future.wait(roomsIds.map(getDigitalGuideRoom));
return rooms.toIList();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:riverpod_annotation/riverpod_annotation.dart";

import "../../../data/models/digital_guide_response.dart";
import "../../../data/models/level.dart";
import "../../../data/repository/levels_repository.dart";
import "../data/models/digital_guide_room.dart";
import "../data/repository/rooms_repository.dart";

part "digital_guide_rooms_use_cases.g.dart";

typedef LevelWithRooms = ({
Level level,
IList<DigitalGuideRoom> rooms,
});

@riverpod
Future<IList<LevelWithRooms>> getLevelsWithRoomsUseCase(
Ref ref,
DigitalGuideResponse digitalGuideData,
) async {
final levels = await ref
.watch(levelsWithRegionsRepositoryProvider(digitalGuideData).future);

final levelsWithRoomsData = await Future.wait(
levels.map((level) async {
final rooms = await ref.watch(roomsRepositoryProvider(level).future);
return (level: level.level, rooms: rooms);
}),
);
return levelsWithRoomsData
.where(
(levelsWithRooms) => levelsWithRooms.rooms.isNotEmpty,
)
.toIList();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";

import "../../../../../config/ui_config.dart";
import "../../../../../theme/app_theme.dart";
import "../../../../navigator/utils/navigation_commands.dart";
import "../../../data/models/level.dart";
import "../../../presentation/widgets/digital_guide_nav_link.dart";
import "../data/models/digital_guide_room.dart";

class DigitalGuideRoomLevel extends ConsumerWidget {
const DigitalGuideRoomLevel({
super.key,
required this.level,
required this.rooms,
});

final Level level;
final IList<DigitalGuideRoom> rooms;

@override
Widget build(BuildContext context, WidgetRef ref) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
level.translations.plTranslation.name,
style: context.textTheme.lightTitle,
),
const SizedBox(height: 10),
ListView.separated(
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => DigitalGuideNavLink(
onTap: () async {
await ref.navigateRoomDetails(
rooms[index],
);
},
text: rooms[index].translations.pl.name,
),
separatorBuilder: (context, index) => SizedBox(
height: index == rooms.length - 1
? DigitalGuideConfig.heightSmall
: DigitalGuideConfig.heightMedium,
),
itemCount: rooms.length,
shrinkWrap: true,
),
const SizedBox(
height: DigitalGuideConfig.heightMedium,
),
],
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import "package:flutter_riverpod/flutter_riverpod.dart";

import "../../../../../config/ui_config.dart";
import "../../../../../widgets/my_error_widget.dart";
import "../../../../navigator/utils/navigation_commands.dart";
import "../../../data/models/digital_guide_response.dart";
import "../../../presentation/widgets/digital_guide_nav_link.dart";
import "../data/models/digital_guide_room.dart";
import "../data/repository/rooms_repository.dart";
import "../domain/digital_guide_rooms_use_cases.dart";
import "digital_guide_room_level.dart";

class DigitalGuideRoomExpansionTileContent extends ConsumerWidget {
const DigitalGuideRoomExpansionTileContent({
Expand All @@ -19,10 +17,11 @@ class DigitalGuideRoomExpansionTileContent extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final roomsInBuilding =
ref.watch(roomsRepositoryProvider(digitalGuideResponse));
return roomsInBuilding.when(
data: (data) => _DigitalGuideRoomExpansionTileContent(rooms: data),
final levelsWithRooms =
ref.watch(getLevelsWithRoomsUseCaseProvider(digitalGuideResponse));
return levelsWithRooms.when(
data: (data) =>
_DigitalGuideRoomExpansionTileContent(levelsWithRooms: data),
error: (error, _) => MyErrorWidget(error),
loading: () => const Center(
child: CircularProgressIndicator(),
Expand All @@ -32,9 +31,9 @@ class DigitalGuideRoomExpansionTileContent extends ConsumerWidget {
}

class _DigitalGuideRoomExpansionTileContent extends ConsumerWidget {
const _DigitalGuideRoomExpansionTileContent({required this.rooms});
const _DigitalGuideRoomExpansionTileContent({required this.levelsWithRooms});

final IList<DigitalGuideRoom> rooms;
final IList<LevelWithRooms> levelsWithRooms;

@override
Widget build(BuildContext context, WidgetRef ref) {
Expand All @@ -43,21 +42,14 @@ class _DigitalGuideRoomExpansionTileContent extends ConsumerWidget {
horizontal: DigitalGuideConfig.paddingMedium,
vertical: DigitalGuideConfig.paddingMedium,
),
child: ListView.separated(
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) => const SizedBox(
height: DigitalGuideConfig.heightMedium,
),
itemCount: rooms.length,
shrinkWrap: true,
itemBuilder: (context, index) => DigitalGuideNavLink(
onTap: () async {
await ref.navigateRoomDetails(
rooms[index],
);
},
text: rooms[index].translations.pl.name,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: levelsWithRooms.map((level) {
return DigitalGuideRoomLevel(
level: level.level,
rooms: level.rooms,
);
}).toList(),
),
);
}
Expand Down

0 comments on commit d34401b

Please sign in to comment.