Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Digital guide API foundation and adapted toilets #514

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
61cb8f2
feat/create foundation for many tiles in digital guide and fetch adap…
24bartixx Dec 23, 2024
309ca90
feat: adapted toilet detail view
24bartixx Dec 27, 2024
e15d7b4
refractor: move checking whether there are adapted toilets to digital…
24bartixx Dec 27, 2024
0c45e56
refractor: switch expression in an extension instead of swtich statement
24bartixx Dec 27, 2024
0f0e1e0
fix: use text theme
24bartixx Dec 27, 2024
fbbb969
fix: _stringToBool lowercase
24bartixx Dec 30, 2024
27e9441
refractor: List to IList
24bartixx Dec 30, 2024
9feae8f
refractor: avoid null assertations
24bartixx Dec 30, 2024
c619620
refractor: implement IsNeedAuthorizationEnum in adapted toilet model
24bartixx Dec 30, 2024
eb1544d
refractor: simplify ununderstandable function
24bartixx Jan 4, 2025
ab11f58
refactor: avoid null asserations
24bartixx Jan 4, 2025
22df51b
refactor: IMap instread of Map
24bartixx Jan 4, 2025
8612111
refactor: minor improvements
24bartixx Jan 4, 2025
d4b9065
refactor: improvements
24bartixx Jan 4, 2025
e89c8e4
refactor: divide digital guide repo separating levels repo
24bartixx Jan 4, 2025
07a724a
refactor: convert list delegate to builder based delegate
24bartixx Jan 4, 2025
499842a
refactor: AdaptedToiletLevel widget
24bartixx Jan 4, 2025
d4e873a
fix: format
24bartixx Jan 4, 2025
73173b5
refactor: List to IList and formatting
24bartixx Jan 9, 2025
9aeae6b
refactor: change maps and lists to immutable
24bartixx Jan 9, 2025
8da3ff6
Merge branch 'main' into feat/digital-guide-foundation-and-adapted-to…
24bartixx Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/config/nav_bar_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ extension IsRouteATabViewX on PageRouteInfo<dynamic> {
DepartmentDetailRoute.name => context.localize.department,
ScienceClubDetailRoute.name => context.localize.scientific_cirlces,
GuideDetailRoute.name => context.localize.guide,
DigitalGuideRoute.name => context.localize.digital_guide,
_ => null,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class DigitalGuideResponse with _$DigitalGuideResponse {
required List<int> images,
@JsonKey(name: "evacuation_map") required int evacuationMapId,
String? imageUrl,
@JsonKey(name: "levels") required List<int> levelsIndices,
}) = _DigitalGuideResponse;

factory DigitalGuideResponse.fromJson(Map<String, dynamic> json) =>
Expand Down Expand Up @@ -87,6 +88,48 @@ class DigitalGuideTranslation with _$DigitalGuideTranslation {
_$DigitalGuideTranslationFromJson(json);
}

@freezed
class LevelNotFull with _$LevelNotFull {
simon-the-shark marked this conversation as resolved.
Show resolved Hide resolved
const factory LevelNotFull({
required int id,
@JsonKey(name: "floor_number") required int floorNumber,
required LevelTranslations translations,
@JsonKey(name: "regions") required List<int> regionIndices,
}) = _LevelNotFull;

factory LevelNotFull.fromJson(Map<String, dynamic> json) =>
_$LevelNotFullFromJson(json);
}

@freezed
class LevelTranslations with _$LevelTranslations {
const factory LevelTranslations({
@JsonKey(name: "pl") required LevelTranslation plTranslation,
}) = _LevelTranslations;

factory LevelTranslations.fromJson(Map<String, dynamic> json) =>
_$LevelTranslationsFromJson(json);
}

@freezed
class LevelTranslation with _$LevelTranslation {
const factory LevelTranslation({
required String name,
}) = _LevelTranslation;

factory LevelTranslation.fromJson(Map<String, dynamic> json) =>
_$LevelTranslationFromJson(json);
}

@freezed
class Region with _$Region {
const factory Region({
@JsonKey(name: "adapted_toilets") required List<int> adaptedToiletsIndices,
}) = _Region;

factory Region.fromJson(Map<String, dynamic> json) => _$RegionFromJson(json);
}

bool _stringToBool(String value) {
return value.toLowerCase() == "true";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class DigitalGuideResponseExtended {
required this.surroundingId,
required this.images,
required this.imageUrl,
required this.levels,
required this.entraces,
required this.evacuation,
});
Expand All @@ -42,12 +43,26 @@ class DigitalGuideResponseExtended {
final int surroundingId;
final List<int> images;
final String? imageUrl;
final List<Level> levels;
final DigitalGuideEvacuation evacuation;
final IList<DigitalGuideEntrace> entraces;

bool hasAdaptedToilets() {
for (final level in levels) {
for (final region in level.regions) {
if (region.adaptedToiletsIndices.isNotEmpty) {
return true;
}
}
}

return false;
}
24bartixx marked this conversation as resolved.
Show resolved Hide resolved
simon-the-shark marked this conversation as resolved.
Show resolved Hide resolved

factory DigitalGuideResponseExtended.fromDigitalGuideResponse({
required DigitalGuideResponse digitalGuideResponse,
required String? imageUrl,
required List<Level> levels,
required DigitalGuideEvacuation evacuation,
required IList<DigitalGuideEntrace> entraces,
}) {
Expand All @@ -67,8 +82,35 @@ class DigitalGuideResponseExtended {
surroundingId: digitalGuideResponse.surroundingId,
images: digitalGuideResponse.images,
imageUrl: imageUrl,
levels: levels,
entraces: entraces,
evacuation: evacuation,
);
}
}

class Level {
const Level({
required this.id,
required this.floorNumber,
required this.translations,
required this.regions,
});

final int id;
final int floorNumber;
final LevelTranslations translations;
final List<Region> regions;

factory Level.create({
required LevelNotFull levelNotFull,
required List<Region> regions,
}) {
return Level(
id: levelNotFull.id,
floorNumber: levelNotFull.floorNumber,
translations: levelNotFull.translations,
regions: regions,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "../../tabs/entraces/data/repository/entraces_repository.dart";
import "../../tabs/evacuation/data/repository/evacuation_repository.dart";
import "../models/digital_guide_response.dart";
import "../models/digital_guide_response_extended.dart";
import "levels_repository.dart";

part "digital_guide_repository.g.dart";

Expand All @@ -24,9 +25,13 @@ Future<DigitalGuideResponseExtended> getDigitalGuideDataExtended(
await ref.watch(getDigitalGuideEvacuationProvider(id).future);
final entraces = await ref
.watch(getDigitalGuideEntracesProvider(digitalGuideResponse.id).future);
final levels = await ref.watch(
LevelsRespositoryProvider(digitalGuideResponse.levelsIndices).future,
);
return DigitalGuideResponseExtended.fromDigitalGuideResponse(
digitalGuideResponse: digitalGuideResponse,
imageUrl: imageUrl,
levels: levels,
evacuation: evacuation,
entraces: entraces,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:riverpod_annotation/riverpod_annotation.dart";

import "../../../../api_base_rest/client/dio_client.dart";
import "../../../../config/env.dart";
import "../models/digital_guide_response.dart";
import "../models/digital_guide_response_extended.dart";

part "levels_repository.g.dart";

@riverpod
Future<List<Level>> levelsRespository(Ref ref, List<int> levelsIndices) async {
final dio = ref.read(restClientProvider);
dio.options.headers["Authorization"] =
"Token ${Env.digitalGuideAuthorizationToken}";

final levelsFutures = levelsIndices.map((levelID) async {
final levelResponse =
await dio.get("${Env.digitalGuideUrl}/levels/$levelID");
final levelNotFull =
LevelNotFull.fromJson(levelResponse.data as Map<String, dynamic>);
final regionsFutures = levelNotFull.regionIndices.map((regionID) async {
final regionResponse =
await dio.get("${Env.digitalGuideUrl}/regions/$regionID");
return Region.fromJson(regionResponse.data as Map<String, dynamic>);
}).toList();
final regions = await Future.wait(regionsFutures);
return Level.create(levelNotFull: levelNotFull, regions: regions);
}).toList();

final levelsList = await Future.wait(levelsFutures);
levelsList.sort(
(level1, level2) => level1.floorNumber.compareTo(level2.floorNumber),
);

return levelsList;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "package:flutter/widgets.dart";
import "../../../../utils/context_extensions.dart";
import "../../../../widgets/my_expansion_tile.dart";
import "../../data/models/digital_guide_response_extended.dart";
import "../../tabs/adapted_toilets/presentation/adapted_toilets_expansion_tile_content.dart";
import "../../tabs/amenities/presentation/amenities_expansion_tile_content.dart";
import "../../tabs/evacuation/evacuation_widget.dart";
import "../../tabs/localization/presentation/localization_expansion_tile_content.dart";
Expand Down Expand Up @@ -53,10 +54,15 @@ class DigitalGuideFeaturesSection extends StatelessWidget {
title: context.localize.elevators,
content: [LocalizationExpansionTileContent()],
),
(
title: context.localize.toilets,
content: [LocalizationExpansionTileContent()],
),
if (digitalGuideResponseExtended.hasAdaptedToilets())
(
title: context.localize.adapted_toilets,
content: [
AdaptedToiletsExpansionTileContent(
digitalGuideResponseExtended: digitalGuideResponseExtended,
),
],
),
(
title: context.localize.micro_navigation,
content: [LocalizationExpansionTileContent()],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ class DigitalGuideNavLink extends StatelessWidget {
Expanded(
child: Text(
text,
style: context.textTheme.title,
style: context.textTheme.body,
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
),
Icon(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import "package:flutter/material.dart";

import "../../../../../../utils/context_extensions.dart";
import "adapted_toilet_not_full.dart";

class AdaptedToilet {
const AdaptedToilet({
required this.translations,
required this.isAccessAccessibleForPwd,
required this.hasAdditionalPurpose,
required this.isNeedAuthorization,
required this.isEntranceGraphicallyMarked,
required this.isMarked,
required this.imagesURLs,
required this.doorsIndices,
});

final AdaptedToiletTranslations translations;
final bool isAccessAccessibleForPwd;
final int hasAdditionalPurpose;
final IsNeedAuthorizationEnum isNeedAuthorization;
final bool isEntranceGraphicallyMarked;
final bool isMarked;
final List<String> imagesURLs;
final List<int> doorsIndices;

factory AdaptedToilet.create({
required AdaptedToiletNotFull adaptedToiletNotFull,
required List<String> imagesURLs,
}) {
return AdaptedToilet(
translations: adaptedToiletNotFull.translations,
isAccessAccessibleForPwd: adaptedToiletNotFull.isAccessAccessibleForPwd,
hasAdditionalPurpose: adaptedToiletNotFull.hasAdditionalPurpose,
isNeedAuthorization: adaptedToiletNotFull.isNeedAuthorization,
isEntranceGraphicallyMarked:
adaptedToiletNotFull.isEntranceGraphicallyMarked,
isMarked: adaptedToiletNotFull.isMarked,
imagesURLs: imagesURLs,
doorsIndices: adaptedToiletNotFull.doorsIndices,
);
}
}

extension AdaptedToiletLocalization on AdaptedToilet {
String getDescription(BuildContext context) {
return switch (hasAdditionalPurpose) {
1 => context.localize.adapted_toilet_description,
2 => context.localize.adapted_toilet_description_men,
3 => context.localize.adapted_toilet_description_women,
_ => context.localize.adapted_toilet_description,
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// ignore_for_file: invalid_annotation_target

import "package:freezed_annotation/freezed_annotation.dart";

part "adapted_toilet_not_full.freezed.dart";
part "adapted_toilet_not_full.g.dart";

@freezed
class AdaptedToiletNotFull with _$AdaptedToiletNotFull {
simon-the-shark marked this conversation as resolved.
Show resolved Hide resolved
const factory AdaptedToiletNotFull({
required AdaptedToiletTranslations translations,
@JsonKey(name: "is_access_accessible_for_pwd", fromJson: _stringToBool)
required bool isAccessAccessibleForPwd,
@JsonKey(name: "has_additional_purpose", fromJson: _stringToInt)
required int hasAdditionalPurpose,
@JsonKey(name: "is_need_authorization", fromJson: isNeedAuthorizationToEnum)
required IsNeedAuthorizationEnum isNeedAuthorization,
@JsonKey(name: "is_entrance_graphically_marked", fromJson: _stringToBool)
required bool isEntranceGraphicallyMarked,
@JsonKey(name: "is_marked", fromJson: _stringToBool) required bool isMarked,
@JsonKey(name: "images") required List<int> imagesIndices,
@JsonKey(name: "doors") required List<int> doorsIndices,
}) = _AdaptedToiletNotFull;

factory AdaptedToiletNotFull.fromJson(Map<String, dynamic> json) =>
_$AdaptedToiletNotFullFromJson(json);
}

@freezed
class AdaptedToiletTranslations with _$AdaptedToiletTranslations {
const factory AdaptedToiletTranslations({
@JsonKey(name: "pl") required AdaptedToiletTranslation plTranslation,
}) = _AdaptedToiletTranslations;

factory AdaptedToiletTranslations.fromJson(Map<String, dynamic> json) =>
_$AdaptedToiletTranslationsFromJson(json);
}

@freezed
class AdaptedToiletTranslation with _$AdaptedToiletTranslation {
const factory AdaptedToiletTranslation({
required String location,
@JsonKey(name: "toilet_description") required String toiletDescription,
@JsonKey(name: "number_of_cabins") required String numberOfCabins,
@JsonKey(name: "is_access_accessible_for_pwd_comment")
required String isAccessAccessibleForPwdComment,
@JsonKey(name: "is_need_authorization_comment")
required String isNeedAuthorizationComment,
@JsonKey(name: "is_area_allowing_movement_in_front_entrance_comment")
required String isAreaAllowingMovementInFrontEntranceComment,
@JsonKey(name: "is_entrance_graphically_marked_comment")
required String isEntranceGraphicallyMarkedComment,
@JsonKey(name: "is_marked_comment") required String isMarkedComment,
required String comment,
}) = _AdaptedToiletTranslation;

factory AdaptedToiletTranslation.fromJson(Map<String, dynamic> json) =>
_$AdaptedToiletTranslationFromJson(json);
}

bool _stringToBool(String str) {
return str.toLowerCase() == "true";
}

int _stringToInt(String str) {
return int.tryParse(str) ?? 1;
}

IsNeedAuthorizationEnum isNeedAuthorizationToEnum(String str) {
return switch (str.toLowerCase()) {
"true" => IsNeedAuthorizationEnum.yes,
"false" => IsNeedAuthorizationEnum.no,
"unknown" => IsNeedAuthorizationEnum.unknown,
_ => IsNeedAuthorizationEnum.unknown,
};
}

enum IsNeedAuthorizationEnum { yes, no, unknown }
Loading
Loading