import 'dart:io'; import 'package:dio/dio.dart'; import 'package:eatvio_app/core/const.dart'; import 'package:eatvio_app/core/firebase_api.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/utils/toasts.dart'; import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; import 'package:eatvio_app/features/dev_tools/test_cases.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class DevToolsScreen extends StatelessWidget { const DevToolsScreen({super.key}); static const name = 'devToolsScreen'; static const path = '/dev-tools-screen'; @override Widget build(BuildContext context) { return const DevToolsScreenContent(); } } class DevToolsScreenContent extends StatefulWidget { const DevToolsScreenContent({super.key}); @override State createState() => _DevToolsScreenContentState(); } class _DevToolsScreenContentState extends State { String baseUrlForTest = ''; final List testCases = [ Test850task(), GetChatRoomPreviews(), GetChatRoom(), SendMessage(), GetChatMessages(), GetChatRoomIdByUserSlug(), GetBlogPostList(), GetRecipes(), CreateRecipeTask(), GetDiets(), GetPlans(), GetBlogPostComments(), SendBlogPostComment(), GetDietsComments(), SendDietsComment(), GetPlansComments(), SendPlansComment(), GetRecipesComments(), ]; final controller = TextEditingController(); late final List testsStates; @override void initState() { super.initState(); setState(() { baseUrlForTest = baseUrl; }); testsStates = List.generate(testCases.length, (index) => TestState.notRun); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Для разработчиков')), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Column( children: [ Padding(padding: const EdgeInsets.all(8.0), child: Row(children: [Text('BaseUrl: $baseUrlForTest')])), Row( children: [ Expanded(child: CustomTextFormField(controller: controller, hintText: 'type new base url')), IconButton( onPressed: () { setState(() { baseUrlForTest = controller.text; baseUrl = baseUrlForTest.toLowerCase(); sl().options.baseUrl = baseUrl; controller.clear(); }); }, icon: const Icon(Icons.done), ), ], ), const SizedBox(height: 10), CustomOutlinedButton( text: baseUrl == 'https://dev2.eatvio.com' ? 'Set production base url' : 'Set dev2 base url', onPressed: () { setState(() { if (baseUrl == 'https://eatvio.ru') { baseUrlForTest = 'https://dev2.eatvio.com'; } else { baseUrlForTest = 'https://eatvio.ru'; } baseUrl = baseUrlForTest.toLowerCase(); sl().options.baseUrl = baseUrl; controller.clear(); }); }, buttonStyle: const ButtonStyle(), ), SizedBox(height: baseUrlForTest != baseUrl ? 40 : 10), if (baseUrl.toLowerCase() != 'https://eatvio.ru') ListView.builder( shrinkWrap: true, itemCount: testCases.length, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) => Padding( padding: const EdgeInsets.only(bottom: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded(child: Text('${index + 1}. ${testCases[index].name}')), Row( mainAxisSize: MainAxisSize.min, children: [ CustomOutlinedButton( text: 'run', height: 20, width: 60, onPressed: () async { if (testsStates[index] == TestState.loading) return; setState(() { testsStates[index] = TestState.loading; }); final result = await testCases[index].run(baseUrl: baseUrlForTest); if (result) { setState(() { testsStates[index] = TestState.success; }); showSuccessToast('${testCases[index].name} passed'); } else { setState(() { testsStates[index] = TestState.fail; }); showErrorToast('${testCases[index].name} failed'); } }, buttonStyle: const ButtonStyle(), ), const SizedBox(width: 5), switch (testsStates[index]) { TestState.success => Container(width: 20, height: 20, color: Colors.green), TestState.fail => Container(width: 20, height: 20, color: Colors.red), TestState.notRun => Container(width: 20, height: 20, color: Colors.grey), TestState.loading => const SizedBox( width: 20, height: 20, child: SizedBox(height: 20, width: 20, child: Center(child: CircularProgressIndicator())), ), }, ], ), ], ), ), ), const SizedBox(height: 10), CustomOutlinedButton( text: 'add token to server', buttonStyle: const ButtonStyle(), onPressed: () async { try { final dio = sl(); final String platform; if (Platform.isAndroid) { platform = 'android'; } else { platform = 'ios'; } await dio.post('/api/profile/notification/token/register', data: {'token': await FirebaseApi().getToken(), 'platform': platform}); showInfoToast('Токен добавлен'); } catch (e) { showInfoToast('Не удалось добавть токен'); } }, ), const SizedBox(height: 10), CustomOutlinedButton( text: 'copy token', buttonStyle: const ButtonStyle(), onPressed: () async { try { final token = await FirebaseApi().getToken(); if (token != null) { Clipboard.setData(ClipboardData(text: token)); showInfoToast('Токен скопирован'); } else { showInfoToast('Token is null'); } } catch (e) { showInfoToast('Не получилось скопировать токен'); } }, ), const SizedBox(height: 10), CustomOutlinedButton( text: 'remove token from server', buttonStyle: const ButtonStyle(), onPressed: () async { try { final dio = sl(); final String platform; if (Platform.isAndroid) { platform = 'android'; } else { platform = 'ios'; } await dio.post('/api/profile/notification/token/unregister', data: {'token': await FirebaseApi().getToken(), 'platform': platform}); showInfoToast('Токен удалён'); } catch (e) { showInfoToast('Не удалось удалить токен'); } }, ), const SizedBox(height: 10), CustomOutlinedButton( text: 'send notification', buttonStyle: const ButtonStyle(), onPressed: () async { try { final dio = sl(); Future.delayed(const Duration(seconds: 3), () async { await dio.post('/api/profile/notification/token/test'); }); } catch (e) { showInfoToast('Не удалось добавть токен'); } }, ), const SizedBox(height: 300), ], ), ), ), ); } } enum TestState { success, fail, notRun, loading }