From 56ef7425749c692943138fd6f9fb28e70a73861b Mon Sep 17 00:00:00 2001 From: Yasm1nNac1mento Date: Sat, 1 Feb 2025 15:31:10 -0300 Subject: [PATCH 1/2] feat(#65): Tela de trilha --- lib/core/di/locator.dart | 2 + lib/ui/journey/view/journey_view.dart | 9 +- lib/ui/trails/di/di.dart | 11 ++ lib/ui/trails/model/trails_model.dart | 21 ++++ lib/ui/trails/model/trails_request.dart | 23 ++++ lib/ui/trails/service/trails_service.dart | 26 +++++ lib/ui/trails/view/trails_view.dart | 110 ++++++++++++++++++ lib/ui/trails/viewmodel/trails_viewmodel.dart | 22 ++++ 8 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 lib/ui/trails/di/di.dart create mode 100644 lib/ui/trails/model/trails_model.dart create mode 100644 lib/ui/trails/model/trails_request.dart create mode 100644 lib/ui/trails/service/trails_service.dart create mode 100644 lib/ui/trails/view/trails_view.dart create mode 100644 lib/ui/trails/viewmodel/trails_viewmodel.dart diff --git a/lib/core/di/locator.dart b/lib/core/di/locator.dart index 7ccffb8..053dd6b 100644 --- a/lib/core/di/locator.dart +++ b/lib/core/di/locator.dart @@ -12,6 +12,7 @@ import 'package:aranduapp/ui/recover_account/di/di_recover_account.dart'; import 'package:aranduapp/ui/register_account/di/di_register_account.dart'; import 'package:aranduapp/ui/join_subjects/di/di_join_subjects.dart'; import 'package:aranduapp/ui/subjects/di/di.dart'; +import 'package:aranduapp/ui/trails/di/di.dart'; import 'package:get_it/get_it.dart'; final GetIt locator = GetIt.instance; @@ -31,4 +32,5 @@ void setupLocator() { setupAuthDI(); setupEditDeleteUser(); setupJoinSubjectsDI(); + setupTrailsDI(); } diff --git a/lib/ui/journey/view/journey_view.dart b/lib/ui/journey/view/journey_view.dart index b98ce59..cd5026a 100644 --- a/lib/ui/journey/view/journey_view.dart +++ b/lib/ui/journey/view/journey_view.dart @@ -1,8 +1,9 @@ -import 'package:aranduapp/core/log/log.dart'; +//import 'package:aranduapp/core/log/log.dart'; import 'package:aranduapp/ui/journey/viewmodel/journey_viewmodel.dart'; import 'package:aranduapp/ui/shared/erro_screen.dart'; import 'package:aranduapp/ui/shared/loading_widget.dart'; import 'package:aranduapp/ui/subjects/model/subject_model.dart'; +import 'package:aranduapp/ui/trails/view/trails_view.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; @@ -103,7 +104,11 @@ class _JourneyScreen extends StatelessWidget { size: 32, ), onTap: () { - Log.d("tap"); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => Trails(journey: journey), + ), + ); }, ); }); diff --git a/lib/ui/trails/di/di.dart b/lib/ui/trails/di/di.dart new file mode 100644 index 0000000..a889556 --- /dev/null +++ b/lib/ui/trails/di/di.dart @@ -0,0 +1,11 @@ +import 'package:aranduapp/ui/trails/service/trails_service.dart'; +import 'package:aranduapp/ui/trails/viewmodel/trails_viewmodel.dart'; +import 'package:get_it/get_it.dart'; + + +void setupTrailsDI() { + + GetIt.instance.registerLazySingleton(() => TrailsService()); + GetIt.instance.registerFactory(() => TrailsViewmodel()); + +} diff --git a/lib/ui/trails/model/trails_model.dart b/lib/ui/trails/model/trails_model.dart new file mode 100644 index 0000000..5060483 --- /dev/null +++ b/lib/ui/trails/model/trails_model.dart @@ -0,0 +1,21 @@ +import 'dart:convert'; + +class TrailsModel { + final String id; + final String name; + + TrailsModel({ + required this.id, + required this.name, + + }); + + factory TrailsModel.fromJsonString(String jsonString) { + Map json = jsonDecode(jsonString); + + return TrailsModel( + id: json['_id']! as String, + name: json['name']! as String, + ); + } +} \ No newline at end of file diff --git a/lib/ui/trails/model/trails_request.dart b/lib/ui/trails/model/trails_request.dart new file mode 100644 index 0000000..d946a55 --- /dev/null +++ b/lib/ui/trails/model/trails_request.dart @@ -0,0 +1,23 @@ +import 'dart:convert'; + +class TrailsRequest { + final String journeyId; + + TrailsRequest({ + required this.journeyId, + }); + + Map toJson() { + return { + 'journeyId': journeyId, + }; + } + + factory TrailsRequest.fromJsonString(String jsonString) { + final json = jsonDecode(jsonString); + + return TrailsRequest( + journeyId: json['journeyId']! as String, + ); + } +} diff --git a/lib/ui/trails/service/trails_service.dart b/lib/ui/trails/service/trails_service.dart new file mode 100644 index 0000000..9f98d89 --- /dev/null +++ b/lib/ui/trails/service/trails_service.dart @@ -0,0 +1,26 @@ +import 'package:aranduapp/core/log/log.dart'; +import 'package:aranduapp/core/network/studio_maker_api.dart'; +import 'package:aranduapp/ui/trails/model/trails_model.dart'; +import 'package:aranduapp/ui/trails/model/trails_request.dart'; +import 'package:dio/dio.dart'; + +class TrailsService { + Future> getTrails(TrailsRequest trailsRequest) async { + Response response = await StudioMakerApi.getInstance() + .get(path: '/trails/journey/${trailsRequest.journeyId}'); + + List journeyList = response.data as List; + + Log.i(journeyList); + + var res = journeyList.map((e) { + final Map journeyMap = e as Map; + + return TrailsModel( + id: journeyMap['_id']! as String, + name: journeyMap['name']! as String); + }).toList(); + + return res; + } +} diff --git a/lib/ui/trails/view/trails_view.dart b/lib/ui/trails/view/trails_view.dart new file mode 100644 index 0000000..f671b41 --- /dev/null +++ b/lib/ui/trails/view/trails_view.dart @@ -0,0 +1,110 @@ +import 'package:aranduapp/core/log/log.dart'; +import 'package:aranduapp/ui/journey/model/journey_model.dart'; +import 'package:aranduapp/ui/shared/erro_screen.dart'; +import 'package:aranduapp/ui/shared/loading_widget.dart'; +import 'package:aranduapp/ui/trails/viewmodel/trails_viewmodel.dart'; +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:provider/provider.dart'; + +class Trails extends StatelessWidget { + final JourneyModel journey; + + const Trails({super.key, required this.journey}); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider.value( + value: GetIt.instance(), + child: _TrailsScreen(journey: journey), + ); + } +} + +class _TrailsScreen extends StatelessWidget { + final JourneyModel journey; + + const _TrailsScreen({required this.journey}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: _buildAppBar(context), + body: _buildTrails(context), + ); + } + + AppBar _buildAppBar(BuildContext context) { + return AppBar( + backgroundColor: Theme.of(context).colorScheme.onPrimary, + scrolledUnderElevation: 0, + title: Text( + 'Lógica Booleana', + style: Theme.of(context).textTheme.headlineSmall?.copyWith( + color: Theme.of(context).colorScheme.onSurface, + ), + ), + centerTitle: true, + leading: IconButton( + icon: Icon( + Icons.chevron_left, + color: Theme.of(context).colorScheme.primary, + size: 32, + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ); + } + + Widget _buildTrails(BuildContext context) { + TrailsViewmodel viewModel = Provider.of(context); + + viewModel.getTrailsCommand.execute(journey.id); + + return RefreshIndicator( + onRefresh: () => viewModel.getTrailsCommand.execute(journey.id), + child: ListenableBuilder( + listenable: viewModel.getTrailsCommand, + builder: (context, child) { + if (viewModel.getTrailsCommand.isOk) { + return _buildListView(context); + } else if (viewModel.getTrailsCommand.isError) { + return ErrorScreen(message: "Deslize para baixo\n\n ${viewModel.getTrailsCommand.result!.asError!.error.toString()}"); + } else { + return const LoadingWidget(); + } + }, + ), + ); + } + + ListView _buildListView(BuildContext context) { + + TrailsViewmodel viewModel = Provider.of(context); + + return ListView.builder( + itemCount: viewModel.getTrailsCommand.result!.asValue!.value.length, + shrinkWrap: true, + itemBuilder: (context, index) { + var trails = viewModel.getTrailsCommand.result!.asValue!.value[index]; + return ListTile( + leading: Icon( + Icons.collections_bookmark_rounded, + color: Theme.of(context).colorScheme.primary, + size: 32, + ), + title: Text(trails.name?? "NULL"), + trailing: Icon( + Icons.chevron_right, + color: Theme.of(context).colorScheme.primary, + size: 32, + ), + onTap: () { + Log.d("tap"); + }, + ); + }); + } +} diff --git a/lib/ui/trails/viewmodel/trails_viewmodel.dart b/lib/ui/trails/viewmodel/trails_viewmodel.dart new file mode 100644 index 0000000..5ae9bc0 --- /dev/null +++ b/lib/ui/trails/viewmodel/trails_viewmodel.dart @@ -0,0 +1,22 @@ +import 'package:aranduapp/core/state/command.dart'; +import 'package:aranduapp/ui/trails/model/trails_model.dart'; +import 'package:aranduapp/ui/trails/model/trails_request.dart'; +import 'package:aranduapp/ui/trails/service/trails_service.dart'; +import 'package:async/async.dart'; +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; + +class TrailsViewmodel extends ChangeNotifier { + late Command1, String> getTrailsCommand; + + TrailsViewmodel() { + getTrailsCommand = Command1(getTrails); + } + + Future>> getTrails(String journeyId) async { + List res = await GetIt.instance() + .getTrails(TrailsRequest(journeyId: journeyId)); + + return Result.value(res); + } +} From 8c6889f8d6bf755950598b3af022d94c482ca203 Mon Sep 17 00:00:00 2001 From: Gabriel Costa de Oliveira Date: Sat, 1 Feb 2025 17:35:46 -0300 Subject: [PATCH 2/2] fix(#63): integrando com tela de conteudo --- lib/ui/journey/view/journey_view.dart | 4 ++-- lib/ui/trails/model/trails_model.dart | 19 +++---------------- lib/ui/trails/service/trails_service.dart | 11 ++++++++--- lib/ui/trails/view/trails_view.dart | 20 +++++++++++++++----- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/lib/ui/journey/view/journey_view.dart b/lib/ui/journey/view/journey_view.dart index cd5026a..3c37e24 100644 --- a/lib/ui/journey/view/journey_view.dart +++ b/lib/ui/journey/view/journey_view.dart @@ -96,8 +96,8 @@ class _JourneyScreen extends StatelessWidget { color: Theme.of(context).colorScheme.primary, size: 32, ), - title: Text(journey.title?? "NUll"), - subtitle: Text(journey.description?? "NULL"), + title: Text(journey.title), + subtitle: Text(journey.description?? "Sem descrição"), trailing: Icon( Icons.chevron_right, color: Theme.of(context).colorScheme.primary, diff --git a/lib/ui/trails/model/trails_model.dart b/lib/ui/trails/model/trails_model.dart index 5060483..a128d59 100644 --- a/lib/ui/trails/model/trails_model.dart +++ b/lib/ui/trails/model/trails_model.dart @@ -1,21 +1,8 @@ -import 'dart:convert'; - class TrailsModel { final String id; final String name; + final String? contectId; - TrailsModel({ - required this.id, - required this.name, - - }); - - factory TrailsModel.fromJsonString(String jsonString) { - Map json = jsonDecode(jsonString); + TrailsModel({required this.id, required this.name, this.contectId}); +} - return TrailsModel( - id: json['_id']! as String, - name: json['name']! as String, - ); - } -} \ No newline at end of file diff --git a/lib/ui/trails/service/trails_service.dart b/lib/ui/trails/service/trails_service.dart index 9f98d89..646cebb 100644 --- a/lib/ui/trails/service/trails_service.dart +++ b/lib/ui/trails/service/trails_service.dart @@ -14,11 +14,16 @@ class TrailsService { Log.i(journeyList); var res = journeyList.map((e) { - final Map journeyMap = e as Map; + final Map trailsMap = e as Map; + + final list = trailsMap['contents'] as List; return TrailsModel( - id: journeyMap['_id']! as String, - name: journeyMap['name']! as String); + id: trailsMap['_id']! as String, + name: trailsMap['name']! as String, + contectId: list.isNotEmpty ? list[0] as String : null, + ); + }).toList(); return res; diff --git a/lib/ui/trails/view/trails_view.dart b/lib/ui/trails/view/trails_view.dart index f671b41..cf4742b 100644 --- a/lib/ui/trails/view/trails_view.dart +++ b/lib/ui/trails/view/trails_view.dart @@ -1,4 +1,5 @@ import 'package:aranduapp/core/log/log.dart'; +import 'package:aranduapp/ui/content/view/content_view.dart'; import 'package:aranduapp/ui/journey/model/journey_model.dart'; import 'package:aranduapp/ui/shared/erro_screen.dart'; import 'package:aranduapp/ui/shared/loading_widget.dart'; @@ -39,7 +40,7 @@ class _TrailsScreen extends StatelessWidget { backgroundColor: Theme.of(context).colorScheme.onPrimary, scrolledUnderElevation: 0, title: Text( - 'Lógica Booleana', + journey.title, style: Theme.of(context).textTheme.headlineSmall?.copyWith( color: Theme.of(context).colorScheme.onSurface, ), @@ -71,7 +72,9 @@ class _TrailsScreen extends StatelessWidget { if (viewModel.getTrailsCommand.isOk) { return _buildListView(context); } else if (viewModel.getTrailsCommand.isError) { - return ErrorScreen(message: "Deslize para baixo\n\n ${viewModel.getTrailsCommand.result!.asError!.error.toString()}"); + return ErrorScreen( + message: + "Deslize para baixo\n\n ${viewModel.getTrailsCommand.result!.asError!.error.toString()}"); } else { return const LoadingWidget(); } @@ -81,7 +84,6 @@ class _TrailsScreen extends StatelessWidget { } ListView _buildListView(BuildContext context) { - TrailsViewmodel viewModel = Provider.of(context); return ListView.builder( @@ -95,14 +97,22 @@ class _TrailsScreen extends StatelessWidget { color: Theme.of(context).colorScheme.primary, size: 32, ), - title: Text(trails.name?? "NULL"), + title: Text(trails.name), trailing: Icon( Icons.chevron_right, color: Theme.of(context).colorScheme.primary, size: 32, ), onTap: () { - Log.d("tap"); + if (trails.contectId != null) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ContentView( + contentID: trails.contectId!, + ), + ), + ); + } }, ); });