feature(collections): Заготовка под апи. Переключалка коллекций
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
Makefile
8
Makefile
@@ -8,10 +8,6 @@ clean:
|
|||||||
codegen: clean
|
codegen: clean
|
||||||
fvm flutter pub run build_runner build --delete-conflicting-outputs
|
fvm flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
|
||||||
watchgen: clean
|
|
||||||
fvm flutter pub run build_runner watch --delete-conflicting-outputs
|
|
||||||
|
|
||||||
|
|
||||||
iosPod:
|
iosPod:
|
||||||
cd ios && rm -rf Podfile.lock Pods Runner.xcworkspace && fvm flutter clean && fvm flutter pub get && pod install
|
cd ios && rm -rf Podfile.lock Pods Runner.xcworkspace && fvm flutter clean && fvm flutter pub get && pod install
|
||||||
|
|
||||||
@@ -31,8 +27,8 @@ macosPodUpdate:
|
|||||||
cd macos && pod install --repo-update
|
cd macos && pod install --repo-update
|
||||||
|
|
||||||
androidBuild: clean
|
androidBuild: clean
|
||||||
fvm flutter build apk --split-per-abi
|
fvm flutter build apk
|
||||||
mv `pwd`/build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk /tmp/$(PROJECT_NAME)-$(env)-$(ver).apk
|
mv `pwd`/build/app/outputs/flutter-apk/app-release.apk /tmp/$(PROJECT_NAME)-$(env)-$(ver).apk
|
||||||
echo /tmp/$(PROJECT_NAME)-$(env)-$(ver).apk
|
echo /tmp/$(PROJECT_NAME)-$(env)-$(ver).apk
|
||||||
open /tmp
|
open /tmp
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
||||||
import 'package:remever/common/functions.dart';
|
import 'package:remever/common/functions.dart';
|
||||||
|
import 'package:remever/common/resources.dart';
|
||||||
|
import 'package:remever/common/storage.dart';
|
||||||
import 'package:talker_dio_logger/talker_dio_logger_interceptor.dart';
|
import 'package:talker_dio_logger/talker_dio_logger_interceptor.dart';
|
||||||
import 'package:talker_dio_logger/talker_dio_logger_settings.dart';
|
import 'package:talker_dio_logger/talker_dio_logger_settings.dart';
|
||||||
|
|
||||||
@@ -17,17 +19,17 @@ InterceptorsWrapper get _auth {
|
|||||||
RequestOptions options,
|
RequestOptions options,
|
||||||
RequestInterceptorHandler handler,
|
RequestInterceptorHandler handler,
|
||||||
) async {
|
) async {
|
||||||
// try {
|
try {
|
||||||
// String? token = await authSecStorage.read(key: StorageKeys.authToken);
|
String? token = await authSecStorage.read(key: StorageKeys.accessToken);
|
||||||
|
|
||||||
// if (token != null) {
|
if (token != null) {
|
||||||
// options.headers['Authorization'] = 'Bearer $token';
|
options.headers['Authorization'] = 'Bearer $token';
|
||||||
// }
|
}
|
||||||
// } catch (e) {
|
} catch (e) {
|
||||||
// getIt<LogService>().log(
|
// getIt<LogService>().log(
|
||||||
// entity: LogEntity.error(message: 'Error to load access token $e'),
|
// entity: LogEntity.error(message: 'Error to load access token $e'),
|
||||||
// );
|
// );
|
||||||
// }
|
}
|
||||||
|
|
||||||
return handler.next(options);
|
return handler.next(options);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import 'package:remever/screens/collections/widgets/collection_card.dart';
|
|||||||
import 'package:remever/screens/collections/widgets/collections_app_bar.dart';
|
import 'package:remever/screens/collections/widgets/collections_app_bar.dart';
|
||||||
import 'package:remever/screens/collections/widgets/collections_filters.dart';
|
import 'package:remever/screens/collections/widgets/collections_filters.dart';
|
||||||
import 'package:remever/services/collection/collections_interface.dart';
|
import 'package:remever/services/collection/collections_interface.dart';
|
||||||
|
import 'package:remever/services/collection/collections_service.dart';
|
||||||
|
import 'package:remever/services/tickets/tickets_interface.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class CollectionScreen extends StatefulWidget {
|
class CollectionScreen extends StatefulWidget {
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:remever/common/resources.dart';
|
import 'package:remever/common/resources.dart';
|
||||||
import 'package:remever/common/widgets/typography.dart';
|
import 'package:remever/common/widgets/typography.dart';
|
||||||
import 'package:remever/common/widgets/wspace.dart';
|
|
||||||
import 'package:remever/components/extensions/context.dart';
|
import 'package:remever/components/extensions/context.dart';
|
||||||
import 'package:remever/components/extensions/state.dart';
|
import 'package:remever/components/extensions/state.dart';
|
||||||
import 'package:remever/widgets/debug/app_debug.dart';
|
|
||||||
|
|
||||||
class CollectionsFilters extends StatefulWidget {
|
class CollectionsFilters extends StatefulWidget {
|
||||||
const CollectionsFilters({super.key});
|
const CollectionsFilters({super.key});
|
||||||
@@ -16,37 +12,52 @@ class CollectionsFilters extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CollectionsFiltersState extends State<CollectionsFilters> {
|
class _CollectionsFiltersState extends State<CollectionsFilters> {
|
||||||
|
static const List<String> _filterOptions = ['Все', 'Публичные', 'Подписки'];
|
||||||
|
String _selected = 'Все';
|
||||||
|
|
||||||
|
void _onFilterSelected(String title) {
|
||||||
|
safeSetState(() {
|
||||||
|
_selected = title;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppDebug(
|
return Padding(
|
||||||
builder: (context, isDebug) {
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 28).r,
|
||||||
if (!isDebug) return HSpace(20);
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
return Padding(
|
children: _buildFilterButtons(),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 28).r,
|
),
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
_buildFilterButton(AppColors.white, 'Все', () {
|
|
||||||
safeSetState(() {});
|
|
||||||
}),
|
|
||||||
_buildFilterButton(AppColors.gray_bg, 'Публичные', () {
|
|
||||||
safeSetState(() {});
|
|
||||||
}),
|
|
||||||
_buildFilterButton(AppColors.gray_bg, 'Подписки', () {
|
|
||||||
safeSetState(() {});
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
List<Widget> _buildFilterButtons() {
|
||||||
/// Построение кнопки фильтра
|
return _filterOptions
|
||||||
///
|
.map(
|
||||||
Widget _buildFilterButton(Color color, String title, void Function()? onTap) {
|
(title) => _FilterButton(
|
||||||
|
title: title,
|
||||||
|
isSelected: _selected == title,
|
||||||
|
onTap: () => _onFilterSelected(title),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FilterButton extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final bool isSelected;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
const _FilterButton({
|
||||||
|
required this.title,
|
||||||
|
required this.isSelected,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -54,7 +65,7 @@ class _CollectionsFiltersState extends State<CollectionsFilters> {
|
|||||||
height: 36.h,
|
height: 36.h,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)).r,
|
borderRadius: const BorderRadius.all(Radius.circular(16)).r,
|
||||||
color: color,
|
color: isSelected ? AppColors.white : AppColors.bg,
|
||||||
),
|
),
|
||||||
child: Center(child: AppTypography(title, type: SemiBold14px())),
|
child: Center(child: AppTypography(title, type: SemiBold14px())),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import 'package:remever/models/crud_collection_dto.dart';
|
|||||||
/// Интерфейс взаимодействия с коллекциями
|
/// Интерфейс взаимодействия с коллекциями
|
||||||
///
|
///
|
||||||
abstract interface class CollectionsInterface {
|
abstract interface class CollectionsInterface {
|
||||||
|
/// работа с api
|
||||||
|
Future<void> getCollectionsFromApi();
|
||||||
|
Future<void> createCollectionApi();
|
||||||
|
|
||||||
/// Получение списка коллекций
|
/// Получение списка коллекций
|
||||||
Stream<List<Collection>> watchCollectionsList({String? search});
|
Stream<List<Collection>> watchCollectionsList({String? search});
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
|
import 'package:remever/common/services/api_client.dart';
|
||||||
import 'package:remever/database/database.dart';
|
import 'package:remever/database/database.dart';
|
||||||
import 'package:remever/inject.dart';
|
import 'package:remever/inject.dart';
|
||||||
import 'package:remever/models/crud_collection_dto.dart';
|
import 'package:remever/models/crud_collection_dto.dart';
|
||||||
@@ -35,4 +37,37 @@ final class CollectionsService implements CollectionsInterface {
|
|||||||
// TODO: implement makeCollectionPublic
|
// TODO: implement makeCollectionPublic
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> getCollectionsFromApi() async {
|
||||||
|
try {
|
||||||
|
final Response<dynamic> response = await apiClient.get(
|
||||||
|
'/collections',
|
||||||
|
queryParameters: <String, dynamic>{'perPage': 20, 'page': 1},
|
||||||
|
);
|
||||||
|
|
||||||
|
print('data');
|
||||||
|
} catch (e) {
|
||||||
|
print('Response error $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> createCollectionApi() async {
|
||||||
|
try {
|
||||||
|
final Response<dynamic> response = await apiClient.post(
|
||||||
|
'/collections',
|
||||||
|
data: {
|
||||||
|
"title": "Основы программирования для утюгов",
|
||||||
|
"description":
|
||||||
|
"Коллекция карточек по основам программирования для начинающих",
|
||||||
|
"is_public": true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
print('data');
|
||||||
|
} catch (e) {
|
||||||
|
print('Response error $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import 'package:remever/models/create_ticket_dto.dart';
|
|||||||
/// Интерфейс взаимодействия с билетами в коллекция
|
/// Интерфейс взаимодействия с билетами в коллекция
|
||||||
///
|
///
|
||||||
abstract interface class TicketsInterface {
|
abstract interface class TicketsInterface {
|
||||||
|
/// работа с api
|
||||||
|
Future<void> getTicketsFromApi();
|
||||||
|
Future<void> createTicketApi();
|
||||||
|
|
||||||
/// Получение списка билетов
|
/// Получение списка билетов
|
||||||
Stream<List<Ticket>> watchTicketsList(String collectionId);
|
Stream<List<Ticket>> watchTicketsList(String collectionId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
|
import 'package:remever/common/services/api_client.dart';
|
||||||
import 'package:remever/database/database.dart';
|
import 'package:remever/database/database.dart';
|
||||||
import 'package:remever/inject.dart';
|
import 'package:remever/inject.dart';
|
||||||
import 'package:remever/models/create_ticket_dto.dart';
|
import 'package:remever/models/create_ticket_dto.dart';
|
||||||
@@ -32,4 +34,40 @@ final class TicketsService implements TicketsInterface {
|
|||||||
newCollectionId,
|
newCollectionId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> getTicketsFromApi() async {
|
||||||
|
try {
|
||||||
|
final Response<dynamic> response = await apiClient.get('/cards');
|
||||||
|
|
||||||
|
print('data');
|
||||||
|
} catch (e) {
|
||||||
|
print('Response error $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> createTicketApi() async {
|
||||||
|
try {
|
||||||
|
final Response<dynamic> response = await apiClient.post(
|
||||||
|
'/cards',
|
||||||
|
data: {
|
||||||
|
"title": "Основы программирования",
|
||||||
|
"question":
|
||||||
|
"Коллекция карточек по основам программирования для начинающих",
|
||||||
|
"question_picture_id": 1,
|
||||||
|
"answer":
|
||||||
|
"Коллекция карточек по основам программирования для начинающих",
|
||||||
|
"answer_picture_id": 2,
|
||||||
|
"is_public": true,
|
||||||
|
"is_reverse": false,
|
||||||
|
"collection_id": 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
print('data');
|
||||||
|
} catch (e) {
|
||||||
|
print('Response error $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: remever
|
|||||||
description: ""
|
description: ""
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
|
||||||
version: 1.0.0+7
|
version: 1.0.0+8
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.0
|
sdk: ^3.7.0
|
||||||
|
|||||||
Reference in New Issue
Block a user