Commit 290c7207 authored by Ester Alfonzo's avatar Ester Alfonzo

estucturacion del proyecto utilizando Clean Arquitecture

parent e3a8b5a0
import 'dart:io';
import 'package:flutter/material.dart';
class AppTheme {
AppTheme._();
static const Color _lightPrimaryColor = Color(0xFFF1882D);
static const Color _lightSecondaryColor = Color(0xFF1D2B4E);
static const Color _lightOnPrimaryColor = Colors.white;
static const Color _lightOnSecondaryColor = Colors.white;
static const Color _lightTextInputColor = Colors.white;
static const Color _lightSurfaceColor = Color(0xFFF2F0F7);
static const Color _lightHintTextColor = Color(0xFFCFCFCF);
static const Color _darkPrimaryColor = Colors.white24;
static const Color _darkSecondaryColor = Color(0xFFF1882D);
static const Color _darkOnPrimaryColor = Colors.white;
static const Color _darkPrimaryVariantColor = Colors.black;
static const Color _darkOnSecondaryColor = Colors.white;
static const Color _darkSurfaceColor = Color(0xFF1D2B4E);
static const Map<int, Color> granate = <int, Color>{
50: Color(0XFFFFE7E5),
100: Color(0xFFF9D8C7),
200: Color(0xFFF3AB91),
300: Color(0xFFDB6E57),
400: Color(0xFFB83A2E),
500: Color(0xFF990301),
600: Color(0xFF75000A),
700: Color(0xFF620011),
800: Color(0xFF4F0014),
900: Color(0xFF410016)
};
static const Map<int, Color> naranja = <int, Color>{
100: Color(0xFFFEF1D3),
200: Color(0xFFFEDFA8),
300: Color(0xFFFDC77D),
400: Color(0xFFFBB15C),
500: Color(0xFFF1882D),
600: Color(0xFFD66C1C),
700: Color(0xFFB34F13),
800: Color(0xFF90370C),
900: Color(0xFF772607)
};
static const Map<int, Color> grey = <int, Color>{
50: Color(0xFFF2F0F7),
100: Color(0xFFF2F2F2),
200: Color(0xFFF5F5F5),
300: Color(0xFFD3D3D3),
400: Color(0xFFB4B4B4),
500: Color(0xFF858488),
600: Color(0xFF404040),
700: Color(0xFF333333),
800: Color(0xFF260000),
900: Color(0xFF190000),
};
static const Map<int, Color> marino = <int, Color>{
100: Color(0xFFD3DCF5),
200: Color(0xFFA9B9EC),
300: Color(0xFF7385C7),
400: Color(0xFF445390),
500: Color(0xFF1D2B4E),
600: Color(0xFF0F163D),
700: Color(0xFF0A1033),
800: Color(0xFF060A29),
900: Color(0xFF040722),
};
static final ThemeData customLightTheme = ThemeData(
//brightness: Brightness.light,
//primarySwatch: MaterialColor(0xFF151E47, CompanyColors.marino),
appBarTheme: const AppBarTheme(
backgroundColor: _lightPrimaryColor,
),
fontFamily: 'Roboto',
colorScheme: const ColorScheme.light(
primary: _lightPrimaryColor,
onPrimary: _lightOnPrimaryColor,
secondary: _lightSecondaryColor,
onSecondary: _lightOnSecondaryColor,
background: _lightPrimaryColor,
onBackground: Colors.white,
surface: _lightSurfaceColor,
onSurface: Colors.black,
error: Colors.red,
onError: Colors.white,
),
primaryColor: _lightPrimaryColor,
cardColor: _lightSurfaceColor,
scaffoldBackgroundColor: Colors.white,
inputDecorationTheme: _lightInputDecorationTheme,
elevatedButtonTheme: _lightElevatedButtonThemeData,
textButtonTheme: _lightTextButtonThemeData,
textTheme: _lightTextTheme,
floatingActionButtonTheme: _lightFloatingActionButtonTheme,
);
static final _lightTextButtonThemeData = TextButtonThemeData(
style: TextButton.styleFrom(
primary: _lightPrimaryColor,
textStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
);
static final TextTheme _lightTextTheme = TextTheme(
bodyText1: TextStyle(
fontSize: 16,
color: Colors.black,
),
bodyText2: TextStyle(
fontSize: 14,
color: Colors.black,
),
button: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
);
static final _lightElevatedButtonThemeData = ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
elevation: 0,
minimumSize: const Size.fromHeight(45),
primary: _lightSecondaryColor,
onPrimary: _lightOnSecondaryColor,
textStyle: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
),
),
);
static final _lightFloatingActionButtonTheme = FloatingActionButtonThemeData(
elevation: 5,
backgroundColor: _lightPrimaryColor,
iconSize: 24,
);
static final _lightInputDecorationTheme = InputDecorationTheme(
prefixIconColor: _lightHintTextColor, //GRAY500
border: const OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: _lightPrimaryColor, width: 1),
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
disabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: _lightPrimaryColor, width: .3),
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
suffixIconColor: _lightHintTextColor,
filled: true,
hintStyle: TextStyle(
fontWeight: FontWeight.bold, color: _lightHintTextColor, fontSize: 14),
fillColor: _lightTextInputColor,
floatingLabelStyle: const TextStyle(
color: Color(0xFFF1882D),
fontWeight: FontWeight.bold,
),
errorStyle: TextStyle(
color: Colors.red,
fontSize: 12,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
labelStyle: const TextStyle(
color: Color(0xFFF98C27),
fontSize: 12,
fontWeight: FontWeight.bold,
),
errorMaxLines: 1,
);
static final ThemeData customDarkTheme = ThemeData(
//brightness: Brightness.light,
//primarySwatch: MaterialColor(0xFF151E47, CompanyColors.marino),
appBarTheme: AppBarTheme(backgroundColor: _darkPrimaryColor),
fontFamily: 'Roboto',
colorScheme: const ColorScheme.dark(
primary: _darkPrimaryColor,
onPrimary: _darkOnPrimaryColor,
secondary: _darkSecondaryColor,
onSecondary: _darkOnSecondaryColor,
background: _darkPrimaryColor,
onBackground: Colors.white,
surface: _darkSurfaceColor,
onSurface: Colors.white,
error: Colors.red,
onError: Colors.white,
),
primaryColor: _darkPrimaryColor,
cardColor: _darkSurfaceColor,
//scaffoldBackgroundColor: grey[300],
scaffoldBackgroundColor: _darkPrimaryVariantColor,
// backgroundColor: CompanyColors.grey[200],
//indicatorColor: CompanyColors.granate[500],
/*inputDecorationTheme: _lightInputDecorationTheme,
elevatedButtonTheme: _lightElevatedButtonThemeData,
textButtonTheme: _lightTextButtonThemeData,
textTheme: _lightTextTheme,
floatingActionButtonTheme: _lightFloatingActionButtonTheme,*/
);
}
import 'dart:io';
import 'package:etramite_flutter/clases/SharedPref.dart';
class ConectionApi {
List<Cookie> cookies = [];
ConectionApi();
void setCookie(List<Cookie> c) async {
if (c.isEmpty == false) {
await sharedPrefs.save('cookie', c[0].toString());
}
}
Future<List<Cookie>> getCookie() async {
final String? coo = sharedPrefs.read('cookie');
Cookie cook = Cookie.fromSetCookieValue(coo.toString());
return [cook];
}
Future<bool?> deleteCookie() async {
bool? remove = await sharedPrefs.remove('cookie');
return remove;
}
}
import 'dart:io';
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
InputDecoration inputDecorationStyle(String label, bool dense) {
return InputDecoration(
//labelText: label,
contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 6),
enabled: false,
isDense: dense,
hintText: 'Ingresar',
hintMaxLines: null,
);
}
InputDecoration inputDecorationCrearTramiteStyle(String label, bool dense) {
return const InputDecoration(
//labelText: label,
contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 6),
//fillColor: Colors.white,
//isDense: dense,
/*border: const UnderlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(15)),
),*/
errorMaxLines: 3,
hintText: 'Ingresar',
hintMaxLines: null,
);
}
InputDecoration inputDecorationStyleDropDownSearch(String label, bool dense) {
return InputDecoration(
contentPadding: const EdgeInsets.only(left: 5),
alignLabelWithHint: true,
//floatingLabelBehavior: FloatingLabelBehavior.auto,
/*label: Padding(
padding: const EdgeInsets.only(top: 3),
child: Text(
label,
textAlign: TextAlign.justify,
),
),*/
//isDense: dense,
//fillColor: Colors.white,
hintText: 'Ingresar',
/* border: const UnderlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(8)),
),*/
/*labelStyle: const TextStyle(
color: Color(0xFFF98C27),
fontSize: 12,
fontWeight: FontWeight.bold,
),*/
hintMaxLines: null,
);
}
InputDecoration searchDecoration(BuildContext context) {
return InputDecoration(
fillColor: Theme.of(context).cardColor,
isDense: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
width: 1,
),
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
),
prefixIcon: const Icon(
FontAwesomeIcons.magnifyingGlass,
size: 15,
),
);
}
DropdownButtonProps dropdownButtonDecoration(BuildContext context) {
return DropdownButtonProps(
padding: const EdgeInsets.all(4),
alignment: Alignment.centerRight,
icon: Icon(
FontAwesomeIcons.chevronDown,
size: 14,
color: Theme.of(context).colorScheme.primary,
//color: ThemeData,
),
);
}
BoxConstraints dropdownButtonTamanho(context) {
return BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.85,
maxWidth: MediaQuery.of(context).size.width * 0.98,
minHeight: MediaQuery.of(context).size.height * 0.5,
minWidth: MediaQuery.of(context).size.width * 0.98,
);
}
/**
* keytool -keystore /home/ealfonzo/.android/debug.keystore -list -v -alias androiddebugkey -storepass android -keypass android
*/
import 'package:flutter/material.dart';
class AppRouter {
static const String HOME = '/';
static const String SPLASH = '/splash';
static const String LOGIN = '/login';
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case HOME:
return MaterialPageRoute(builder: (_) => HomeScreen());
case SPLASH:
return MaterialPageRoute(builder: (_) => SplashScreen());
case LOGIN:
return MaterialPageRoute(builder: (_) => LoginScreen());
/*case SHOW_INFO:
var show = settings.arguments as Show;
return MaterialPageRoute(
builder: (_) => ShowInfoScreen(show: show),
);*/
default:
return MaterialPageRoute(
builder: (_) => Scaffold(
body: Center(
child: Text('No route defined for ${settings.name}'),
),
),
);
}
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
class Authentication {
static Future<FirebaseApp> initializeFirebase(BuildContext context) async {
FirebaseApp firebaseApp = await Firebase.initializeApp();
// TODO: Add auto login logic
return firebaseApp;
}
static Future<void> signOut({required BuildContext context}) async {
try {
await FirebaseAuth.instance.signOut();
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
Authentication.customSnackBar(
content: 'Error signing out. Try again.',
),
);
}
}
static Future<dynamic> signInWithGoogle(BuildContext context) async {
print('signInWithGoogle');
FirebaseAuth auth = FirebaseAuth.instance;
dynamic userProfile;
dynamic token;
try {
final GoogleSignIn googleSignIn = GoogleSignIn(
clientId:
'753850511112-fmc4ros60g9dljoi0ed9sh9dj4hslif6.apps.googleusercontent.com');
final GoogleSignInAccount? googleSignInAccount =
await googleSignIn.signIn();
if (googleSignInAccount != null) {
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
/*print('credential');
print(credential);
print('idToken');
print(googleSignInAuthentication.idToken);
print('accessToken');
print(googleSignInAuthentication.accessToken);*/
token = googleSignInAuthentication.idToken;
try {
final UserCredential userCredential =
await auth.signInWithCredential(credential);
AdditionalUserInfo? user;
user = userCredential.additionalUserInfo;
userProfile = user?.profile;
//print('user');
//print(user?.profile);
} on FirebaseAuthException catch (e) {
if (e.code == 'account-exists-with-different-credential') {
ScaffoldMessenger.of(context).showSnackBar(
Authentication.customSnackBar(
content: 'La cuenta ya existe con una credencial diferente.',
),
);
} else if (e.code == 'invalid-credential') {
ScaffoldMessenger.of(context).showSnackBar(
Authentication.customSnackBar(
content:
'Ocurrió un error al acceder a las credenciales. Intente nuevamente.',
),
);
}
return null;
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
Authentication.customSnackBar(
content:
'Se produjo un error al utilizar el inicio de sesión de Google. Intente nuevamente.',
),
);
return null;
}
return {'userProfile': userProfile, 'token': token};
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
Authentication.customSnackBar(
content:
'Se produjo un error al utilizar el inicio de sesión de Google. Intente nuevamente.',
),
);
return null;
}
return null;
}
static SnackBar customSnackBar({required String content}) {
return SnackBar(
backgroundColor: Colors.black,
content: Text(
content,
style: const TextStyle(color: Colors.redAccent, letterSpacing: 0.5),
),
);
}
}
import 'package:shared_preferences/shared_preferences.dart';
class SharedPrefs {
SharedPreferences? _sharedPrefs;
init() async {
_sharedPrefs = await SharedPreferences.getInstance();
}
String read(String key) {
String? value = _sharedPrefs?.getString(key);
//print("retorno1 $value");
return '$value';
}
bool? containsKey(String key) {
bool? contain = _sharedPrefs?.containsKey(key);
return contain;
}
Future<bool?> save(String key, String value) async {
return _sharedPrefs?.setString(key, value);
}
Future<bool?> remove(String key) async {
return _sharedPrefs?.remove(key);
}
}
final sharedPrefs = SharedPrefs();
import 'dart:convert';
import 'user.dart';
Login loginFromJson(String str) => Login.fromJson(json.decode(str));
String loginToJson(Login data) => json.encode(data.toJson());
class Login {
Login({
required this.logged,
this.csrf,
required this.user,
required this.permissionList,
this.msg,
required this.appVersion,
this.error,
});
bool logged;
dynamic csrf;
User user;
List<String> permissionList;
dynamic msg;
String appVersion;
dynamic error;
factory Login.fromJson(Map<String, dynamic> json) => Login(
logged: json["logged"],
csrf: json["csrf"],
user: User.fromJson(json["user"]),
permissionList: List<String>.from(json["permissionList"].map((x) => x)),
msg: json["msg"],
appVersion: json["appVersion"],
error: json["error"],
);
Map<String, dynamic> toJson() => {
"logged": logged,
"csrf": csrf,
"user": user.toJson(),
"permissionList": List<dynamic>.from(permissionList.map((x) => x)),
"msg": msg,
"appVersion": appVersion,
"error": error,
};
}
class User {
User({
required this.id,
required this.username,
required this.name,
required this.surname,
this.image,
required this.nameAndSurname,
});
int id;
String username;
String name;
String surname;
dynamic image;
String nameAndSurname;
factory User.fromJson(Map<String, dynamic> json) => User(
id: json["id"],
username: json["username"],
name: json["name"],
surname: json["surname"],
image: json["image"],
nameAndSurname: json["nameAndSurname"],
);
Map<String, dynamic> toJson() => {
"id": id,
"username": username,
"name": name,
"surname": surname,
"image": image,
"nameAndSurname": nameAndSurname,
};
}
import 'dart:io';
import 'package:flutter/material.dart';
import 'core/MyHttpOverrides.dart';
import 'my_app.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
HttpOverrides.global = MyHttpOverrides();
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp.runWidget());
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sizer/sizer.dart';
import 'core/router.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Sizer(
builder: (context, orientation, deviceType) {
return MaterialApp(
/* localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],*/
supportedLocales: [
Locale('es'), // Spanish
],
theme: ThemeData(
brightness: Brightness.light,
scaffoldBackgroundColor: Colors.grey.shade900,
primaryColor: COLOR_CONST.PRIMARY,
hoverColor: COLOR_CONST.GRAY2,
fontFamily: 'Oswald',
colorScheme: ColorScheme.fromSwatch()
.copyWith(secondary: COLOR_CONST.PRIMARY),
),
onGenerateRoute: AppRouter.generateRoute,
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state is Uninitialized) {
return SplashScreen();
} else if (state is Unauthenticated) {
return LoginScreen();
} else if (state is Authenticated) {
return HomeScreen();
}
return Container(
child: Center(child: Text('Unhandle State $state')),
);
},
),
);
},
);
}
static Widget runWidget() {
return FutureBuilder(
future: Future.sync(() => true),
builder: (context, snapshot) {
if (snapshot.hasData) {
final UserRepository userRepository = UserRepository();
/*final TimerRepository timerRepository = TimerRepository();
final HomeRepository homeRepository = HomeRepository();
final ShowRepository showRepository = ShowRepository();
final ProductsRepository productsRepository = ProductsRepository();
final BookTimeSlotRepository bookTimeSlotRepository =
BookTimeSlotRepository();
final SessionRepository sessionRepository =
SessionRepository(pref: LocalPref());
final SeatSlotRepository seatSlotRepository = SeatSlotRepository();*/
return MultiRepositoryProvider(
providers: [
RepositoryProvider<UserRepository>(
create: (context) => userRepository),
/*RepositoryProvider<TimerRepository>(
create: (context) => timerRepository),
RepositoryProvider<ProductsRepository>(
create: (context) => productsRepository),
RepositoryProvider<HomeRepository>(
create: (context) => homeRepository),
RepositoryProvider<ShowRepository>(
create: (context) => showRepository),
RepositoryProvider<BookTimeSlotRepository>(
create: (context) => bookTimeSlotRepository),
RepositoryProvider<SessionRepository>(
create: (context) => sessionRepository),
RepositoryProvider<SeatSlotRepository>(
create: (context) => seatSlotRepository),*/
],
child: MultiBlocProvider(
providers: [
BlocProvider(
create: (context) =>
AuthenticationBloc(userRepository: userRepository)
..add(AppStarted()),
),
BlocProvider(
create: (context) => HomeBloc(
homeRepository: homeRepository,
userRepository: userRepository,
),
),
BlocProvider(
create: (context) =>
LoginBloc(userRepository: userRepository),
)
],
child: MyApp(),
),
);
}
return Container();
},
);
}
}
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:etramite_flutter/clases/ConectionApi.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
class ApiService {
String apiUrl = "https://tramites.una.py/etramite-backend/";
ConectionApi conection = ConectionApi();
String getApiUrl() {
return apiUrl;
}
Future<Response?> post(
String method, dynamic params, Map<String, dynamic> body) async {
var request = FormData.fromMap(body);
print('comienza el metodo post $method');
var options = Options(
followRedirects: false,
validateStatus: (status) => true,
);
Dio _dio = Dio();
CookieJar _cookieJar = CookieJar();
_dio.interceptors.add(CookieManager(_cookieJar));
try {
if (method != 'login' &&
method != 'login/google' &&
method != 'registrarse') {
List<Cookie> cookie = await conection.getCookie();
await _cookieJar.saveFromResponse(Uri.parse(getApiUrl()), cookie);
await _cookieJar.loadForRequest(Uri.parse(getApiUrl()));
}
Response response = await _dio.post(getApiUrl() + method,
data: request, queryParameters: params, options: options);
//print('Respuesta post method $method : $response');
if (method == 'login' || method == 'login/google') {
var con = await _cookieJar.loadForRequest(Uri.parse(getApiUrl()));
//print('connnn $con');
conection.setCookie(con);
//await conection.getCookieJar().saveFromResponse(Uri.parse(getApiUrl()), get);
}
//print('statuscode ${response.statusCode}, headers: ${response.headers.toString()}');
print('Respuesta post method $method status ${response.statusCode}');
return response;
} catch (e) {
print('Errorrrrr : $e');
return null;
}
}
Future<Response?> get(String method, params) async {
print('comienza el metodo get $method');
var options = Options(
followRedirects: false,
validateStatus: (status) => true,
);
Dio _dio = Dio();
CookieJar _cookieJar = CookieJar();
_dio.interceptors.add(CookieManager(_cookieJar));
try {
var cookie = await conection.getCookie();
await _cookieJar.saveFromResponse(Uri.parse(getApiUrl()), cookie);
await _cookieJar.loadForRequest(Uri.parse(getApiUrl()));
Response response = await _dio.get(getApiUrl() + method,
options: options, queryParameters: params);
print('Respuesta get method $method status ${response.statusCode}');
return response;
} catch (e) {
print('Error: $e');
return null;
}
}
Future<Response?> download(String method, int mode, String path) async {
print('comienza el metodo download $method');
var url = getApiUrl() + method;
Dio _dio = Dio();
CookieJar _cookieJar = CookieJar();
_dio.interceptors.add(CookieManager(_cookieJar));
try {
var cookie = await conection.getCookie();
await _cookieJar.saveFromResponse(Uri.parse(getApiUrl()), cookie);
await _cookieJar.loadForRequest(Uri.parse(getApiUrl()));
Response response = await _dio.get(url,
onReceiveProgress: showDownloadProgress,
options: Options(
followRedirects: false,
validateStatus: (status) => true,
));
//print(response.data);
return response;
} catch (e) {
print("error + $e");
return null;
}
}
Future<Response?> delete(String method, params) async {
print('comienza el metodo delete $method');
var options = Options(
followRedirects: false,
validateStatus: (status) => true,
);
Dio _dio = Dio();
CookieJar _cookieJar = CookieJar();
_dio.interceptors.add(CookieManager(_cookieJar));
try {
var cookie = await conection.getCookie();
await _cookieJar.saveFromResponse(Uri.parse(getApiUrl()), cookie);
await _cookieJar.loadForRequest(Uri.parse(getApiUrl()));
Response response = await _dio.delete(getApiUrl() + method,
options: options, queryParameters: params);
print('Respuesta delete method $method status ${response.statusCode}');
return response;
} catch (e) {
print('Error: $e');
return null;
}
}
}
void showDownloadProgress(received, total) {
if (total != -1) {
//print((received / total * 100).toStringAsFixed(0) + "%");
}
}
/* (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
return client;
};*/
\ No newline at end of file
import 'package:etramite_flutter/clases/SharedPref.dart';
import 'package:etramite_flutter/screens/LoginScreen.dart';
import 'package:etramite_flutter/services/apiService.dart';
import 'package:etramite_flutter/services/toastService.dart' as toast;
import 'package:flutter/material.dart';
Future<dynamic> getLoginDB(BuildContext context, usuario, password) async {
var snapshot = await ApiService().post(
'login', null, {'username': usuario, 'password': password}).then((resp) {
var respuesta = resp?.statusCode;
// print('response $respuesta');
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
///print("cuerpo de la respuesta post a ${resp?.statusMessage}");
var data = resp?.data;
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado, credenciales inválidas");
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexión");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> getLoginGoogle(BuildContext context, token) async {
var snapshot = await ApiService().post(
'login/google',
{'googleIdToken': token},
{'googleIdToken': token},
).then((resp) {
var respuesta = resp?.statusCode;
//print('response $respuesta');
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta post a ${resp?.statusMessage}");
var data = resp?.data;
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado, credenciales inválidas");
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexión");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> registrarse(BuildContext context, dynamic body) async {
var snapshot =
await ApiService().post('registrarse', null, body).then((resp) {
var respuesta = resp?.statusCode;
//print('response $respuesta');
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta post a ${resp?.statusMessage}");
var data = resp?.data;
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexión");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> recuperarPass(BuildContext context, email) async {
var snapshot =
await ApiService().post('resetpass', null, {'email': email}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta post a ${resp?.statusMessage}");
var data = resp?.data;
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
if (resp?.data != null) {
print('retornara solo data');
return resp?.data;
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<void> logout(BuildContext context) async {
var snapshot = await ApiService().get('login', {'logout': null}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError(
"Verifique su conexión e intente de nuevo.",
);
}
if (respuesta == 200) {
//Navigator.of(context, rootNavigator: true).push(context, '/home');
//print("cuerpo de la respuesta post a ${resp?.statusMessage}");
goLoginPage(context);
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
goLoginPage(BuildContext context) async {
await sharedPrefs.save('login', 'no');
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute<void>(
builder: (BuildContext context) => const LoginScreen(),
),
(Route<dynamic> route) => false,
);
}
//Navigator.of(context).pushNamed(RoutePaths.Login);
\ No newline at end of file
import 'dart:convert';
import 'dart:io';
import 'package:etramite_flutter/services/apiService.dart';
import 'package:etramite_flutter/services/authService.dart';
import 'package:etramite_flutter/services/fileStorage.dart';
import 'package:flutter/material.dart';
import 'package:etramite_flutter/services/toastService.dart' as toast;
Future<dynamic> listaTramitesDisponibles(BuildContext context) async {
var snapshot = await ApiService().get('tipos-tramites/suggest',
{'soloActivos': 'S', 'iDisplayLength': 1000}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> listaMatriculas(BuildContext context, dynamic? institu) async {
//print('institucion $institu');
var snapshot = await ApiService()
.get('alummatrics', {'institucionId': institu}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> listaCiudades(BuildContext context, String? search) async {
var snapshot = await ApiService().get('ciudades-etramite/suggest',
{'iDisplayLength': 20, 'sSearch': search}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> listaColegios(BuildContext context, String? search) async {
var snapshot = await ApiService().get('colegios-ealu/suggest',
{'iDisplayLength': 20, 'sSearch': search}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> listaInstituciones(BuildContext context, String? search) async {
var snapshot = await ApiService().get('instituciones/suggest',
{'iDisplayLength': 20, 'iSortCol_0': 1, 'sSearch': search}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> listaTramitesDocs(BuildContext context, dynamic? id) async {
//print('institucion $institu');
var snapshot = await ApiService()
.get('tipos-tramites-reqs/by-tipo-tramite/$id', null)
.then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<void> downloadTramiteArchivo(
BuildContext context, idTramite, filename) async {
var savePath = await getSavePath(context) + "/$filename";
var response = await ApiService()
.download('/mis-tramites/tipodoc/formato/$idTramite', 2, savePath);
//print(response!.headers);
var data = response!.data.toString().replaceAll('"', '').replaceAll('\n', '');
var bytes = base64Decode(data);
try {
File file = File(savePath);
var raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(bytes);
await raf.close();
} catch (e) {
print(e);
}
}
Future<dynamic> saveNewTramite(BuildContext context, dynamic data) async {
var snapshot =
await ApiService().post('mis-tramites', null, data).then((resp) {
//print('response ${resp?.data}');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
print(resp);
if (respuesta == 201) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
if (respuesta! > 401 || respuesta < 401) {
return resp?.data;
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
//for ios
import 'dart:io';
import 'package:etramite_flutter/services/toastService.dart' as toast;
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
//for ios
Future<String> requestAppDocumentsDirectory(BuildContext context) async {
await getPermision(context);
var appDocumentsDirectory = await getApplicationDocumentsDirectory();
return appDocumentsDirectory.path;
}
//for android
Future<String> requestExternalStorageDirectory(BuildContext context) async {
await getPermision(context);
/*var externalDocumentsDirectory = ExtStorage.getExternalStoragePublicDirectory(
ExtStorage.DIRECTORY_DOWNLOADS);*/
var externalDocumentsDirectory = Directory('/storage/emulated/0/Download');
/*var externalDocumentsDirectory =
await getExternalStorageDirectories(type: StorageDirectory.downloads);*/
//print("Lista de directorios $externalDocumentsDirectory");
return externalDocumentsDirectory.path;
}
getPermision(BuildContext context) async {
var status = await Permission.storage.status;
//print("statussss $status");
if (status.isGranted) {
return;
} else {
if (status.isLimited) {
await requestPermision(context);
} else {
await requestPermision(context);
}
}
}
requestPermision(BuildContext context) async {
var request = await Permission.storage.request();
if (request.isGranted) {
return;
} else {
if (request.isDenied || request.isPermanentlyDenied) {
toast.showToastSuccess(
"Debe permitir que se acceda al almacenamiento interno");
} else {
return;
}
}
}
Future<String> getSavePath(BuildContext context) async {
var directorio = Platform.isIOS
? await requestAppDocumentsDirectory(context)
: await requestExternalStorageDirectory(context);
String path = directorio;
//print("directorio, $directorio");
return path;
}
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
Timer _timer = Timer(const Duration(milliseconds: 0), () {});
void configLoading() {
EasyLoading.instance
..displayDuration = const Duration(milliseconds: 15000)
..indicatorType = EasyLoadingIndicatorType.fadingCircle
..loadingStyle = EasyLoadingStyle.dark
..indicatorSize = 35.0
..radius = 10.0
..progressColor = Colors.yellow
..backgroundColor = Colors.green
..indicatorColor = Colors.yellow
..textColor = Colors.yellow
..maskColor = Colors.blue.withOpacity(0.5)
..userInteractions = true
..dismissOnTap = false;
//..customAnimation = CustomAnimation();
}
showPresent(String? message) async {
_timer.cancel();
if (message == '') {
await EasyLoading.show(
maskType: EasyLoadingMaskType.black,
);
} else {
await EasyLoading.show(
status: message,
maskType: EasyLoadingMaskType.black,
);
}
//print('EasyLoading show');
}
dismissPresent() async {
_timer.cancel();
await EasyLoading.dismiss();
//print('EasyLoading dismiss');
}
import 'dart:io';
import 'package:etramite_flutter/clases/ConectionApi.dart';
import 'package:etramite_flutter/services/apiService.dart';
import 'package:etramite_flutter/services/authService.dart';
import 'package:flutter/material.dart';
import 'package:etramite_flutter/services/toastService.dart';
Future<ImageProvider> getFoto(context, imgPath) async {
var cookie = await ConectionApi().getCookie();
Map<String, String> headersMap = {'cookie': cookie.first.toString()};
//print(headersMap);
if (imgPath != '') {
return FileImage(
File(imgPath),
);
}
return NetworkImage(
'https://tramites.una.py/etramite-backend/perfil/foto.png',
headers: headersMap,
/*fit: BoxFit.cover,
errorBuilder:
(BuildContext context, Object exception, StackTrace? stackTrace) {
return Image.asset(
'assets/foto_error.png',
fit: BoxFit.cover,
);
},*/
);
}
Future<dynamic> getDatosPersonales(BuildContext context) async {
var snapshot = await ApiService().get('perfil', null).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> setActualizarDatosPersonales(
BuildContext context, dynamic datos) async {
var snapshot = await ApiService()
.post('perfil/actualizar-datos', null, datos)
.then((resp) {
print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
if (data['success'] == true) {
showToastSuccess(data['successMessage']);
}
return data;
} else {
if (respuesta == 401) {
showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> actualizarContrasenha(
BuildContext context, dynamic datos) async {
var snapshot = await ApiService()
.post('perfil/cambiar-contrasenha', null, datos)
.then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
showToastError("No autorizado");
goLoginPage(context);
}
/*if (respuesta >= 500) {
toast.showToastError("Problemas en el servidor", context, duration: 3);
}*/
return null;
}
}).catchError((error) {
showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
void showToastSuccess(String msg) {
Fluttertoast.showToast(
msg: msg,
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
backgroundColor: Colors.green,
textColor: Colors.white);
}
void showToastError(String msg) {
Fluttertoast.showToast(
msg: msg,
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
backgroundColor: Colors.red,
textColor: Colors.white);
}
void showToastInformation(String msg) {
Fluttertoast.showToast(
msg: msg,
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
backgroundColor: Colors.cyan,
textColor: Colors.white);
}
import 'dart:convert';
import 'dart:io';
import 'package:etramite_flutter/services/fileStorage.dart';
import 'package:flutter/material.dart';
import 'package:etramite_flutter/services/apiService.dart';
import 'package:etramite_flutter/services/toastService.dart' as toast;
import 'authService.dart';
Future<dynamic> info(BuildContext context) async {
var snapshot =
await ApiService().get('/core-session/info', null).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexión");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> cambiarInstitucion(BuildContext context, id) async {
var snapshot = await ApiService()
.get('cambiar-institucion', {'institucion': id}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexión");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> listarTramites(
BuildContext context, int start, int len, String search) async {
var snapshot = await ApiService().get('mis-tramites/datatable',
{'start': start, 'length': len, 'search': search}).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> tramiteDetalle(BuildContext context, id) async {
var snapshot = await ApiService().get('mis-tramites/$id', null).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexión");
print(error);
return null;
});
return snapshot;
}
Future<List<dynamic>> observacionTipoTramite(BuildContext context, id) async {
var snapshot = await ApiService()
.get('tipos-tramites-obs/by-tipo-tramite/$id', null)
.then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print('data $data');
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
}
return null;
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> comentariosTramite(BuildContext context, id) async {
var snapshot = await ApiService()
.get('tramites-comentarios/by-tramite/$id', null)
.then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> enviarComentarioTramite(BuildContext context, data) async {
var snapshot =
await ApiService().post('tramites-comentarios', null, data).then((resp) {
//print('response $resp');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 201) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
toast.showToastSuccess("Comentario Enviado");
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> eliminarComentarioTramite(
BuildContext context, dynamic id) async {
var snapshot =
await ApiService().delete('tramites-comentarios/$id', null).then((resp) {
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 204) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
//var data = resp?.data;
//print(resp);
return {'successMessage': "Comentario borrado con éxito"};
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<void> downloadTramiteArchivoAdjunto(
BuildContext context, idTramite, hash, filename) async {
var savePath = await getSavePath(context) + "/$filename";
//print(savePath);
var response = await ApiService()
.download('public-docsadjuntos/$idTramite/$hash', 1, savePath);
//print(response!.headers);
var data = response!.data.toString().replaceAll('"', '').replaceAll('\n', '');
var bytes = base64Decode(data);
try {
File file = File(savePath);
var raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(bytes);
await raf.close();
} catch (e) {
print(e);
}
}
Future<dynamic> cambiarArchivoAdjunto(dynamic data) async {
var snapshot = await ApiService()
.post('mis-docsadjuntos/cambiar', null, data)
.then((resp) {
print('response ${resp}');
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 200) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
var data = resp?.data;
//print(resp);
return data;
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
}
if (resp!.data != null) {
toast.showToastError(resp.data['errorMessage']);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
Future<dynamic> eliminarTramite(BuildContext context, dynamic id) async {
var snapshot =
await ApiService().delete('mis-tramites/$id', null).then((resp) {
var respuesta = resp?.statusCode;
if (respuesta != null && respuesta < 200) {
toast.showToastError("Verifique su conexión e intente de nuevo.");
}
if (respuesta == 204) {
//print("cuerpo de la respuesta get a ${resp?.statusMessage}");
//var data = resp?.data;
//print(resp);
return {'successMessage': "Trámite borrado con éxito"};
} else {
if (respuesta == 401) {
toast.showToastError("No autorizado");
goLoginPage(context);
}
return null;
}
}).catchError((error) {
toast.showToastError("Verifique su conexion");
print(error);
return null;
});
return snapshot;
}
import 'package:intl/intl.dart';
formatNumber(numero) {
NumberFormat f = NumberFormat("#,##0", "es_AR");
var n = f.format(numero);
return n.toString();
}
import 'package:etramite_flutter/clases/GoogleAuth.dart';
import 'package:flutter/material.dart';
class GoogleSignInButton extends StatefulWidget {
final Function(dynamic token) onGoogleButtomPressed;
final String contentText;
const GoogleSignInButton(
{Key? key,
required this.onGoogleButtomPressed,
required this.contentText})
: super(key: key);
@override
_GoogleSignInButtonState createState() => _GoogleSignInButtonState();
}
class _GoogleSignInButtonState extends State<GoogleSignInButton> {
bool _isSigningIn = false;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
if (_isSigningIn == false) ...[
ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.white),
onPressed: () async {
setState(() {
_isSigningIn = true;
});
var usr = await Authentication.signInWithGoogle(context);
if (usr != null) widget.onGoogleButtomPressed(usr);
setState(() {
_isSigningIn = false;
});
},
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Image.asset(
'assets/google_icon.png',
height: 25,
width: 25,
),
const SizedBox(
width: 15,
),
Text(
widget.contentText,
style: const TextStyle(fontSize: 16, color: Colors.black),
),
],
),
),
] else ...[
CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor,
),
),
],
],
);
}
}
import 'package:flutter/material.dart';
class CustomAnimatedBottomBar extends StatelessWidget {
CustomAnimatedBottomBar({
Key? key,
this.selectedIndex = 0,
this.showElevation = true,
this.iconSize = 22,
this.backgroundColor,
this.itemCornerRadius = 50,
this.containerHeight = 56,
this.animationDuration = const Duration(milliseconds: 270),
this.mainAxisAlignment = MainAxisAlignment.spaceAround,
required this.items,
required this.onItemSelected,
this.curve = Curves.linear,
}) : assert(items.length >= 2 && items.length <= 5),
super(key: key);
final int selectedIndex;
final double iconSize;
final Color? backgroundColor;
final bool showElevation;
final Duration animationDuration;
final List<BottomNavyBarItem> items;
final ValueChanged<int> onItemSelected;
final MainAxisAlignment mainAxisAlignment;
final double itemCornerRadius;
final double containerHeight;
final Curve curve;
@override
Widget build(BuildContext context) {
final bgColor = backgroundColor ?? Theme.of(context).bottomAppBarColor;
return Container(
decoration: BoxDecoration(
color: bgColor,
boxShadow: [
if (showElevation)
const BoxShadow(
color: Colors.black12,
blurRadius: 2,
),
],
),
child: SafeArea(
child: Container(
width: double.infinity,
height: containerHeight,
//alignment: Alignment.center,
//padding: const EdgeInsets.all(4),
child: Row(
mainAxisAlignment: mainAxisAlignment,
crossAxisAlignment: CrossAxisAlignment.center,
children: items.map((item) {
var index = items.indexOf(item);
return GestureDetector(
onTap: () => onItemSelected(index),
child: _ItemWidget(
item: item,
iconSize: iconSize,
isSelected: index == selectedIndex,
backgroundColor: bgColor,
itemCornerRadius: itemCornerRadius,
animationDuration: animationDuration,
curve: curve,
),
);
}).toList(),
),
),
),
);
}
}
class _ItemWidget extends StatelessWidget {
final double iconSize;
final bool isSelected;
final BottomNavyBarItem item;
final Color backgroundColor;
final double itemCornerRadius;
final Duration animationDuration;
final Curve curve;
const _ItemWidget({
Key? key,
required this.item,
required this.isSelected,
required this.backgroundColor,
required this.animationDuration,
required this.itemCornerRadius,
required this.iconSize,
this.curve = Curves.linear,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Semantics(
container: true,
selected: isSelected,
child: AnimatedContainer(
width: isSelected
? MediaQuery.of(context).size.width / 3
: MediaQuery.of(context).size.width / 4,
height: double.maxFinite,
duration: animationDuration,
//curve: curve,
//alignment: Alignment.center,
decoration: BoxDecoration(
color: isSelected
? Theme.of(context).colorScheme.primary
: backgroundColor,
// borderRadius: BorderRadius.circular(itemCornerRadius),
),
child: Container(
width: isSelected
? MediaQuery.of(context).size.width / 3
: MediaQuery.of(context).size.width / 4,
// alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
IconTheme(
data: IconThemeData(
size: iconSize,
color: isSelected
? item.activeColor
: item.inactiveColor == null
? item.activeColor
: item.inactiveColor,
),
child: item.icon,
),
const SizedBox(
height: 5,
),
DefaultTextStyle.merge(
style: TextStyle(
color: item.activeColor,
fontWeight: FontWeight.bold,
fontSize: 12,
),
maxLines: 1,
//textAlign: item.textAlign,
child: item.title,
),
],
),
),
),
);
}
}
class BottomNavyBarItem {
BottomNavyBarItem({
required this.icon,
required this.title,
this.activeColor = Colors.blue,
this.textAlign,
this.inactiveColor,
});
final Widget icon;
final Widget title;
final Color activeColor;
final Color? inactiveColor;
final TextAlign? textAlign;
}
import 'package:flutter/material.dart';
Widget optionsGradient(BuildContext context, String text, ancho) {
return Padding(
padding: const EdgeInsets.only(top: 3.0, bottom: 3),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.white10,
Colors.grey,
],
begin: FractionalOffset(0.0, 0.0),
end: FractionalOffset(1.0, 1.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp,
),
),
width: MediaQuery.of(context).size.width * ancho,
height: 1.0,
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
child: Text(
text.toString(),
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.grey,
decoration: TextDecoration.none,
fontSize: 16.0,
),
),
),
),
Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width * ancho,
height: 1.0,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.grey,
Colors.white10,
],
begin: FractionalOffset(0.0, 0.0),
end: FractionalOffset(1.0, 1.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp,
),
),
),
],
),
);
}
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:etramite_flutter/services/authService.dart' as apiResponse;
import 'package:etramite_flutter/services/toastService.dart' as toast;
Widget buildDialogPage(BuildContext context) {
TextEditingController _emailController = TextEditingController();
_handleRecuperarPass(BuildContext context, email) async {
var _apiResponse = await apiResponse.recuperarPass(context, email);
print(_apiResponse);
if (_apiResponse == null) {
toast.showToastError("Ha ocurrido algun problema");
} else {
if (_apiResponse['success'] == false) {
toast.showToastError(_apiResponse["errorMessage"]);
} else {
toast.showToastError(_apiResponse["successMessage"]);
}
}
}
return AlertDialog(
contentPadding: const EdgeInsets.all(10),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
title: Container(
alignment: Alignment.center,
child: const Text(
'Recupera tu contraseña',
style: TextStyle(
color: Color(0xFF151E47),
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
actions: <Widget>[
Container(
alignment: Alignment.center,
child: ElevatedButton(
child: const Text(
"Recuperar Contraseña",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
onPressed: () {
_handleRecuperarPass(context, _emailController.text);
},
),
),
],
content: Container(
padding: const EdgeInsets.all(10),
child: Container(
padding: const EdgeInsets.all(10),
child: TextField(
controller: _emailController,
decoration: const InputDecoration(
labelText: 'Email',
prefixIcon: Icon(
FontAwesomeIcons.solidEnvelope,
),
),
),
),
),
);
}
import 'package:flutter/material.dart';
import '../core/customStyles.dart';
Widget textInput(BuildContext context, dynamic titulo, dynamic cuerpo,
bool negrita, bool dense) {
FontWeight isNegrita = negrita ? FontWeight.bold : FontWeight.normal;
return TextField(
readOnly: true,
style: TextStyle(
fontSize: 13,
fontWeight: isNegrita,
),
keyboardType: TextInputType.multiline,
controller: TextEditingController(
text: cuerpo.toString(),
),
decoration: inputDecorationStyle(titulo.toString(), dense),
maxLines: null,
);
}
Widget customLoadingBuilder(BuildContext context, String? texto) {
return Container(
alignment: Alignment.center,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor,
),
),
);
}
Widget customTitle(String texto) {
return Container(
padding: const EdgeInsets.all(8),
child: Text(
texto,
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF1D2B4E),
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
);
}
Widget customEmptyBuilder(BuildContext context, String? search) {
return Container(
alignment: Alignment.center,
child: const Text(
'No se encuentraron datos',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
);
}
Widget customErrorBuilder(BuildContext context, String? search, dynamic error) {
return Container(
alignment: Alignment.center,
child: const Text(
'No se pudo recuperar los datos',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
);
}
Widget commonText(BuildContext context, String text) {
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(bottom: 5, top: 12),
child: Text(
text,
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold,
),
),
);
}
......@@ -5,6 +5,8 @@
import FlutterMacOS
import Foundation
import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
}
......@@ -9,6 +9,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.10.0"
bloc:
dependency: transitive
description:
name: bloc
sha256: "658a5ae59edcf1e58aac98b000a71c762ad8f46f1394c34a52050cafb3e11a80"
url: "https://pub.dev"
source: hosted
version: "8.1.1"
boolean_selector:
dependency: transitive
description:
......@@ -57,11 +65,35 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
url: "https://pub.dev"
source: hosted
version: "2.0.1"
file:
dependency: transitive
description:
name: file
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
url: "https://pub.dev"
source: hosted
version: "6.1.4"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
sha256: "434951eea948dbe87f737b674281465f610b8259c16c097b8163ce138749a775"
url: "https://pub.dev"
source: hosted
version: "8.1.2"
flutter_lints:
dependency: "direct dev"
description:
......@@ -75,6 +107,19 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
intl:
dependency: "direct main"
description:
name: intl
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
url: "https://pub.dev"
source: hosted
version: "0.18.0"
js:
dependency: transitive
description:
......@@ -115,6 +160,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
path:
dependency: transitive
description:
......@@ -123,6 +176,126 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.2"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
url: "https://pub.dev"
source: hosted
version: "2.1.10"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
url: "https://pub.dev"
source: hosted
version: "2.0.6"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
url: "https://pub.dev"
source: hosted
version: "2.1.5"
platform:
dependency: transitive
description:
name: platform
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
process:
dependency: transitive
description:
name: process
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
url: "https://pub.dev"
source: hosted
version: "4.2.4"
provider:
dependency: transitive
description:
name: provider
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev"
source: hosted
version: "6.0.5"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
sizer:
dependency: "direct main"
description:
name: sizer
sha256: d2b3cb6cbc4a637f508dacd786bae55df31e5fc088044248a43e4fd1e050c117
url: "https://pub.dev"
source: hosted
version: "2.0.15"
sky_engine:
dependency: transitive
description: flutter
......@@ -176,6 +349,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.16"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
universal_io:
dependency: transitive
description:
name: universal_io
sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
vector_math:
dependency: transitive
description:
......@@ -184,5 +373,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
win32:
dependency: transitive
description:
name: win32
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
url: "https://pub.dev"
source: hosted
version: "3.1.4"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
url: "https://pub.dev"
source: hosted
version: "1.0.0"
sdks:
dart: ">=2.19.2 <3.0.0"
flutter: ">=3.0.0"
......@@ -35,6 +35,10 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
flutter_bloc: ^8.1.2
intl: ^0.18.0
sizer: ^2.0.15
shared_preferences: ^2.1.0
dev_dependencies:
flutter_test:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment