codigo actual del servidor, con avances de joan
This commit is contained in:
36
source_code/lib/custom/CommonFunctoins.dart
Normal file
36
source_code/lib/custom/CommonFunctoins.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'dart:io';
|
||||
import 'package:active_ecommerce_seller_app/custom/buttons.dart';
|
||||
import 'package:active_ecommerce_seller_app/custom/localization.dart';
|
||||
import 'package:active_ecommerce_seller_app/helpers/shared_value_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class CommonFunctions{
|
||||
BuildContext context;
|
||||
|
||||
CommonFunctions(this.context);
|
||||
|
||||
appExitDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => Directionality(
|
||||
textDirection: app_language_rtl.$! ? TextDirection.rtl : TextDirection.ltr,
|
||||
child: AlertDialog(
|
||||
content: Text(LangText(context: context).getLocal()!.do_you_want_close_the_app),
|
||||
actions: [
|
||||
Buttons(
|
||||
onPressed: () {
|
||||
Platform.isAndroid ? SystemNavigator.pop() : exit(0);
|
||||
},
|
||||
child: Text(AppLocalizations.of(context)!.yes_ucf)),
|
||||
Buttons(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(AppLocalizations.of(context)!.no_ucf)),
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
33
source_code/lib/custom/buttons.dart
Normal file
33
source_code/lib/custom/buttons.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Buttons extends StatelessWidget{
|
||||
BuildContext? context;
|
||||
dynamic onPressed; Widget? child;Color color = MyTheme.noColor;Alignment? alignment;EdgeInsetsGeometry padding=EdgeInsets.zero;double? width;double height;OutlinedBorder? shape;
|
||||
|
||||
Buttons({Key? key,this.context, this.onPressed, this.child,this.color = MyTheme.noColor,this.alignment,this.padding=EdgeInsets.zero,this.width,this.height=5.0,this.shape}) : super(key: key);
|
||||
|
||||
|
||||
|
||||
Widget _basic() {
|
||||
return TextButton(
|
||||
onPressed: onPressed,
|
||||
style: TextButton.styleFrom(
|
||||
shape:shape,
|
||||
// maximumSize: width!=null?Size(width, height):null,
|
||||
minimumSize: width!=null?Size(width!, height):null,
|
||||
backgroundColor: color,
|
||||
alignment: alignment,
|
||||
padding: padding, elevation: 0.0, primary: MyTheme.black),
|
||||
child: child!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO: implement build
|
||||
return _basic();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
156
source_code/lib/custom/chart.dart
Normal file
156
source_code/lib/custom/chart.dart
Normal file
@@ -0,0 +1,156 @@
|
||||
// import 'package:active_ecommerce_seller_app/data_model/chart_response.dart';
|
||||
// import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
// import 'package:active_ecommerce_seller_app/repositories/shop_repository.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
//
|
||||
// // class TimeSeriesBar extends StatefulWidget {
|
||||
// //
|
||||
// //
|
||||
// // TimeSeriesBar();
|
||||
// //
|
||||
// //
|
||||
// // @override
|
||||
// // State<TimeSeriesBar> createState() => _TimeSeriesBarState();
|
||||
// // }
|
||||
// //
|
||||
// // class _TimeSeriesBarState extends State<TimeSeriesBar> {
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// // /// Create one series with sample hard coded data.
|
||||
// // List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
|
||||
// // final data =
|
||||
// //
|
||||
// // return [
|
||||
// // new charts.Series<TimeSeriesSales, DateTime>(
|
||||
// // id: 'Sales',
|
||||
// // colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
|
||||
// // domainFn: (TimeSeriesSales sales, _) => sales.time,
|
||||
// // measureFn: (TimeSeriesSales sales, _) => sales.sales,
|
||||
// // data: data,
|
||||
// // )
|
||||
// // ];
|
||||
// // }
|
||||
// //
|
||||
// //
|
||||
// // @override
|
||||
// // void initState() {
|
||||
// // getChart();
|
||||
// // // TODO: implement initState
|
||||
// // super.initState();
|
||||
// // }
|
||||
// // @override
|
||||
// // Widget build(BuildContext context) {
|
||||
// // return chartList.isEmpty ?Container():new charts.TimeSeriesChart(
|
||||
// // _createSampleData(),
|
||||
// // animate: false,
|
||||
// // // Set the default renderer to a bar renderer.
|
||||
// // // This can also be one of the custom renderers of the time series chart.
|
||||
// // defaultRenderer: new charts.BarRendererConfig<DateTime>(),
|
||||
// // // It is recommended that default interactions be turned off if using bar
|
||||
// // // renderer, because the line point highlighter is the default for time
|
||||
// // // series chart.
|
||||
// // defaultInteractions: false,
|
||||
// // // If default interactions were removed, optionally add select nearest
|
||||
// // // and the domain highlighter that are typical for bar charts.
|
||||
// // behaviors: [new charts.SelectNearest(), new charts.DomainHighlighter()],
|
||||
// // );
|
||||
// // }
|
||||
// // }
|
||||
// //
|
||||
// // /// Sample time series data type.
|
||||
// // class TimeSeriesSales {
|
||||
// // final DateTime time;
|
||||
// // final int sales;
|
||||
// //
|
||||
// // TimeSeriesSales(this.time, this.sales);
|
||||
// // }
|
||||
// //
|
||||
//
|
||||
// class SimpleBarChart extends StatefulWidget {
|
||||
// final bool? animate;
|
||||
//
|
||||
// SimpleBarChart({this.animate});
|
||||
//
|
||||
// @override
|
||||
// State<SimpleBarChart> createState() => _SimpleBarChartState();
|
||||
//
|
||||
// /// Create one series with sample hard coded data.
|
||||
// }
|
||||
//
|
||||
// class _SimpleBarChartState extends State<SimpleBarChart> {
|
||||
// List<ChartResponse> chartList = [];
|
||||
//
|
||||
// List<charts.Series<dynamic, String>> _createSampleData() {
|
||||
// final data = List.generate(chartList.length, (index) {
|
||||
// return OrdinalSales(
|
||||
// chartList[index].date, (chartList[index].total!.toInt()));
|
||||
// // return OrdinalSales("Sep-"+(10+ index).toString(), (chartList[0].total.toInt()-index));
|
||||
// });
|
||||
//
|
||||
// return [
|
||||
// Series<OrdinalSales, String>(
|
||||
// colorFn: (__, _) =>
|
||||
// charts.ColorUtil.fromDartColor(MyTheme.app_accent_color),
|
||||
// id: 'Sales',
|
||||
// domainFn: (OrdinalSales sales, _) => sales.year!,
|
||||
// measureFn: (OrdinalSales sales, _) => sales.sales,
|
||||
// data: data,
|
||||
// )
|
||||
// ];
|
||||
// }
|
||||
//
|
||||
// getChart() async {
|
||||
// var response = await ShopRepository().chartRequest();
|
||||
// chartList.addAll(response);
|
||||
// setState(() {});
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// getChart();
|
||||
// // TODO: implement initState
|
||||
// super.initState();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return chartList.isEmpty
|
||||
// ? Container()
|
||||
// : BarChart(
|
||||
// _createSampleData(),
|
||||
// domainAxis: OrdinalAxisSpec(
|
||||
// renderSpec: SmallTickRendererSpec(
|
||||
// labelStyle: TextStyleSpec(
|
||||
// fontSize: 10, // size in Pts.
|
||||
// color: charts.ColorUtil.fromDartColor(MyTheme.grey_153),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// defaultRenderer: charts.BarRendererConfig(
|
||||
// maxBarWidthPx: 12,
|
||||
// fillPattern: charts.FillPatternType.solid,
|
||||
// ),
|
||||
// animate: widget.animate,
|
||||
// primaryMeasureAxis: charts.NumericAxisSpec(
|
||||
// renderSpec: charts.GridlineRendererSpec(
|
||||
// labelJustification: charts.TickLabelJustification.outside,
|
||||
// minimumPaddingBetweenLabelsPx: 1,
|
||||
// //axisLineStyle:charts.LineStyleSpec() ,
|
||||
// // Tick and Label styling here.
|
||||
// labelStyle: charts.TextStyleSpec(
|
||||
// fontSize: 10, // size in Pts.
|
||||
// color: charts.MaterialPalette.gray.shadeDefault),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// Sample ordinal data type.
|
||||
// class OrdinalSales {
|
||||
// final String? year;
|
||||
// final int sales;
|
||||
//
|
||||
// OrdinalSales(this.year, this.sales);
|
||||
// }
|
||||
87
source_code/lib/custom/chart2.dart
Normal file
87
source_code/lib/custom/chart2.dart
Normal file
@@ -0,0 +1,87 @@
|
||||
import 'package:active_ecommerce_seller_app/custom/device_info.dart';
|
||||
import 'package:active_ecommerce_seller_app/data_model/chart_response.dart';
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:active_ecommerce_seller_app/repositories/shop_repository.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
|
||||
class MChart extends StatefulWidget {
|
||||
const MChart({super.key});
|
||||
|
||||
@override
|
||||
State<MChart> createState() => _MChartState();
|
||||
}
|
||||
|
||||
class _MChartState extends State<MChart> {
|
||||
List<ChartResponse> chartList = [];
|
||||
|
||||
List<ChartSeries> _createSampleData() {
|
||||
|
||||
final data = List.generate(chartList.length, (index) {
|
||||
return OrdinalSales(
|
||||
chartList[index].date,
|
||||
int.parse(chartList[index].total!.round().toString())
|
||||
// 56
|
||||
);
|
||||
});
|
||||
|
||||
return [
|
||||
StackedColumnSeries<OrdinalSales, String>(
|
||||
// enableTooltip: isTooltipVisible,
|
||||
dataSource: data,
|
||||
xValueMapper: (OrdinalSales sales,da) => sales.year,
|
||||
yValueMapper: (OrdinalSales sales, index) {
|
||||
return sales.sales;
|
||||
},
|
||||
isVisibleInLegend: false,
|
||||
color: MyTheme.app_accent_color,
|
||||
|
||||
enableTooltip: true
|
||||
//enableAnimation: false,
|
||||
// markerSettings: const MarkerSettings(
|
||||
// isVisible: true,
|
||||
// height: 4,
|
||||
// width: 4,
|
||||
// shape: DataMarkerType.circle,
|
||||
// borderWidth: 3,
|
||||
// borderColor: Colors.red),
|
||||
// dataLabelSettings: DataLabelSettings(
|
||||
// isVisible: true,
|
||||
// //position: ChartDataLabelAlignment.Auto
|
||||
// ),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
getChart() async {
|
||||
var response = await ShopRepository().chartRequest();
|
||||
chartList.addAll(response);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getChart();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child:SfCartesianChart(
|
||||
primaryXAxis: CategoryAxis(),
|
||||
//title: ChartTitle(text: 'Flutter Chart'),
|
||||
legend: Legend(isVisible: true),
|
||||
series: _createSampleData(),
|
||||
// tooltipBehavior: _tooltipBehavior,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
class OrdinalSales {
|
||||
final String? year;
|
||||
final int sales;
|
||||
|
||||
OrdinalSales(this.year, this.sales);
|
||||
}
|
||||
55
source_code/lib/custom/common_style.dart
Normal file
55
source_code/lib/custom/common_style.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
import 'package:active_ecommerce_seller_app/custom/device_info.dart';
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MyTextStyle{
|
||||
|
||||
static TextStyle smallFontSize(){
|
||||
return TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.normal
|
||||
);
|
||||
}
|
||||
static TextStyle normalStyle(){
|
||||
return TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.normal
|
||||
);
|
||||
}
|
||||
|
||||
static TextStyle bigFontSize(){
|
||||
return TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.w400
|
||||
);
|
||||
}
|
||||
|
||||
TextStyle dashboardBoxNumber(context){
|
||||
return TextStyle(
|
||||
fontSize: (DeviceInfo(context).getWidth()/100)*5,
|
||||
color: MyTheme.white,
|
||||
fontWeight: FontWeight.bold
|
||||
);
|
||||
}
|
||||
|
||||
TextStyle dashboardBoxText(context){
|
||||
return TextStyle(
|
||||
|
||||
fontSize: (DeviceInfo(context).getWidth()/100)*3.5,
|
||||
color: MyTheme.white,
|
||||
fontWeight: FontWeight.normal
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TextStyle appbarText(){
|
||||
return TextStyle(fontSize: 17,fontWeight: FontWeight.bold,color: MyTheme.app_accent_color);
|
||||
}
|
||||
}
|
||||
11
source_code/lib/custom/customDateTimes.dart
Normal file
11
source_code/lib/custom/customDateTimes.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class CustomDateTime{
|
||||
static String getDate = DateFormat('dMMMM,y').format(DateTime.now());
|
||||
static String getDayName = DateFormat('EEEE').format(DateTime.now());
|
||||
static String getLast7Date = DateFormat('EEEE').format(DateTime.now());
|
||||
|
||||
|
||||
}
|
||||
25
source_code/lib/custom/decorations.dart
Normal file
25
source_code/lib/custom/decorations.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
|
||||
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class MDecoration{
|
||||
static BoxDecoration decoration1({double radius =6.0 ,bool showShadow=true}) {
|
||||
return BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
color: MyTheme.white,
|
||||
boxShadow: [
|
||||
showShadow?BoxShadow(
|
||||
color: MyTheme.black.withOpacity(0.15),
|
||||
blurRadius: 20,
|
||||
spreadRadius: 0.0,
|
||||
offset: const Offset(0.0, 10.0), // shadow direction: bottom right
|
||||
):const BoxShadow()
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
28
source_code/lib/custom/device_info.dart
Normal file
28
source_code/lib/custom/device_info.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class DeviceInfo{
|
||||
BuildContext? context;
|
||||
|
||||
DeviceInfo(this.context);
|
||||
|
||||
double getWidth(){
|
||||
return MediaQuery.of(context!).size.width;
|
||||
}
|
||||
double getWidthInPercent(){
|
||||
return MediaQuery.of(context!).size.width/100;
|
||||
}
|
||||
double getHeight(){
|
||||
return MediaQuery.of(context!).size.height;
|
||||
}
|
||||
double getHeightInPercent(){
|
||||
return MediaQuery.of(context!).size.height/100;
|
||||
}
|
||||
|
||||
double getHeightInPercent2(){
|
||||
return MediaQuery.of(context!).size.aspectRatio;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
56
source_code/lib/custom/dialog_box.dart
Normal file
56
source_code/lib/custom/dialog_box.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
|
||||
|
||||
import 'package:active_ecommerce_seller_app/custom/buttons.dart';
|
||||
import 'package:active_ecommerce_seller_app/custom/localization.dart';
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DialogBox{
|
||||
|
||||
static late BuildContext context;
|
||||
|
||||
static warningShow(BuildContext context ,List<dynamic>? warnings){
|
||||
showDialog(context: context, builder: (context){
|
||||
DialogBox.context = context;
|
||||
return AlertDialog(
|
||||
title: Text(LangText(context: context).getLocal()!.warning_ucf),
|
||||
content: SizedBox(
|
||||
height: 180,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: List.generate(warnings!.length, (index) => Padding(
|
||||
padding:const EdgeInsets.all(8),
|
||||
child:Text("● ${warnings[index]}"),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Buttons(
|
||||
color: MyTheme.medium_grey,
|
||||
padding: EdgeInsets.all(8),
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Text(LangText(context: context).getLocal()!.close_all_capital,style: TextStyle(color: MyTheme.white),),
|
||||
onPressed: (){
|
||||
pop();
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static pop(){
|
||||
Navigator.pop(DialogBox.context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
73
source_code/lib/custom/input_decorations.dart
Normal file
73
source_code/lib/custom/input_decorations.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class InputDecorations {
|
||||
static InputDecoration buildInputDecoration_1(
|
||||
{hint_text = "",
|
||||
Color hintTextColor = MyTheme.app_accent_color,
|
||||
Color borderColor = MyTheme.app_accent_border,
|
||||
Color fillColor = const Color.fromRGBO(255, 255, 255, 0)}) {
|
||||
return InputDecoration(
|
||||
fillColor: fillColor,
|
||||
hintText: hint_text,
|
||||
hintStyle: TextStyle(fontSize: 12.0, color: hintTextColor),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: borderColor, width: 1),
|
||||
borderRadius: const BorderRadius.all(
|
||||
const Radius.circular(10.0),
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: MyTheme.app_accent_color.withOpacity(0.5), width: 1.5),
|
||||
borderRadius: const BorderRadius.all(
|
||||
const Radius.circular(10.0),
|
||||
),
|
||||
),
|
||||
contentPadding: EdgeInsets.only(left: 16.0));
|
||||
}
|
||||
|
||||
static InputDecoration buildInputDecoration_phone
|
||||
// ({hint_text = ""}) {
|
||||
// return InputDecoration(
|
||||
// fillColor: fillColor,
|
||||
//
|
||||
// hintText: hint_text,
|
||||
// hintStyle: TextStyle(fontSize: 12.0, color: MyTheme.app_accent_color),
|
||||
// enabledBorder: OutlineInputBorder(
|
||||
// borderSide: BorderSide(color: MyTheme.app_accent_color.withOpacity(0.8), width: 1.0),
|
||||
// borderRadius: BorderRadius.only(
|
||||
// topRight: Radius.circular(10.0),
|
||||
// bottomRight: Radius.circular(10.0)),
|
||||
// ),
|
||||
// focusedBorder: OutlineInputBorder(
|
||||
// borderSide: BorderSide(color: MyTheme.app_accent_color.withOpacity(0.8), width: 1.0),
|
||||
// borderRadius: BorderRadius.only(
|
||||
// topRight: Radius.circular(10.0),
|
||||
// bottomRight: Radius.circular(10.0))),
|
||||
// contentPadding: EdgeInsets.only(left: 16.0));
|
||||
// }
|
||||
(
|
||||
{hint_text = "",
|
||||
Color hintTextColor = MyTheme.app_accent_color,
|
||||
Color borderColor = MyTheme.app_accent_border,
|
||||
Color fillColor = const Color.fromRGBO(255, 255, 255, 0)}) {
|
||||
return InputDecoration(
|
||||
fillColor: fillColor,
|
||||
hintText: hint_text,
|
||||
hintStyle: TextStyle(fontSize: 12.0, color: hintTextColor),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: borderColor, width: 1),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(10.0),
|
||||
bottomRight: Radius.circular(10.0)),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: borderColor, width: 1.0),
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(10.0),
|
||||
bottomRight: Radius.circular(10.0))),
|
||||
contentPadding: EdgeInsets.only(left: 16.0));
|
||||
}
|
||||
}
|
||||
648
source_code/lib/custom/intl_phone_input.dart
Normal file
648
source_code/lib/custom/intl_phone_input.dart
Normal file
@@ -0,0 +1,648 @@
|
||||
import 'package:active_ecommerce_seller_app/custom/buttons.dart';
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl_phone_number_input/src/models/country_list.dart';
|
||||
import 'package:intl_phone_number_input/src/models/country_model.dart';
|
||||
import 'package:intl_phone_number_input/src/providers/country_provider.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/formatter/as_you_type_formatter.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/phone_number.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/phone_number/phone_number_util.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/selector_config.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/test/test_helper.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/util.dart';
|
||||
import 'package:intl_phone_number_input/src/utils/widget_view.dart';
|
||||
|
||||
import 'package:intl_phone_number_input/src/utils/selector_config.dart';
|
||||
import 'package:intl_phone_number_input/src/widgets/countries_search_list_widget.dart';
|
||||
import 'package:intl_phone_number_input/src/widgets/input_widget.dart';
|
||||
import 'package:intl_phone_number_input/src/widgets/item.dart';
|
||||
|
||||
|
||||
|
||||
/// Enum for [CustomSelectorButton] types.
|
||||
///
|
||||
/// Available type includes:
|
||||
/// * [PhoneInputSelectorType.DROPDOWN]
|
||||
/// * [PhoneInputSelectorType.BOTTOM_SHEET]
|
||||
/// * [PhoneInputSelectorType.DIALOG]
|
||||
|
||||
/// A [TextFormField] for [CustomInternationalPhoneNumberInput].
|
||||
///
|
||||
/// [initialValue] accepts a [PhoneNumber] this is used to set initial values
|
||||
/// for phone the input field and the selector button
|
||||
///
|
||||
/// [selectorButtonOnErrorPadding] is a double which is used to align the selector
|
||||
/// button with the input field when an error occurs
|
||||
///
|
||||
/// [locale] accepts a country locale which will be used to translation, if the
|
||||
/// translation exist
|
||||
///
|
||||
/// [countries] accepts list of string on Country isoCode, if specified filters
|
||||
/// available countries to match the [countries] specified.
|
||||
class CustomInternationalPhoneNumberInput extends StatefulWidget {
|
||||
final SelectorConfig selectorConfig;
|
||||
|
||||
final ValueChanged<PhoneNumber> onInputChanged;
|
||||
final ValueChanged<bool>? onInputValidated;
|
||||
|
||||
final VoidCallback? onSubmit;
|
||||
final ValueChanged<String>? onFieldSubmitted;
|
||||
final String Function(String?)? validator;
|
||||
final ValueChanged<PhoneNumber>? onSaved;
|
||||
|
||||
final TextEditingController? textFieldController;
|
||||
final TextInputType keyboardType;
|
||||
final TextInputAction? keyboardAction;
|
||||
|
||||
final PhoneNumber? initialValue;
|
||||
final String hintText;
|
||||
final String errorMessage;
|
||||
|
||||
final double selectorButtonOnErrorPadding;
|
||||
final double spaceBetweenSelectorAndTextField;
|
||||
final int maxLength;
|
||||
|
||||
final bool isEnabled;
|
||||
final bool formatInput;
|
||||
final bool autoFocus;
|
||||
final bool autoFocusSearch;
|
||||
final AutovalidateMode autoValidateMode;
|
||||
final bool ignoreBlank;
|
||||
final bool countrySelectorScrollControlled;
|
||||
|
||||
final String? locale;
|
||||
|
||||
final TextStyle? textStyle;
|
||||
final TextStyle? selectorTextStyle;
|
||||
final InputBorder? inputBorder;
|
||||
final InputDecoration? inputDecoration;
|
||||
final InputDecoration? searchBoxDecoration;
|
||||
final Color? cursorColor;
|
||||
final TextAlign textAlign;
|
||||
final TextAlignVertical textAlignVertical;
|
||||
final EdgeInsets scrollPadding;
|
||||
|
||||
final FocusNode? focusNode;
|
||||
final Iterable<String>? autofillHints;
|
||||
|
||||
final List<String?>? countries;
|
||||
|
||||
CustomInternationalPhoneNumberInput(
|
||||
{Key? key,
|
||||
this.selectorConfig = const SelectorConfig(),
|
||||
required this.onInputChanged,
|
||||
this.onInputValidated,
|
||||
this.onSubmit,
|
||||
this.onFieldSubmitted,
|
||||
this.validator,
|
||||
this.onSaved,
|
||||
this.textFieldController,
|
||||
this.keyboardAction,
|
||||
this.keyboardType = TextInputType.phone,
|
||||
this.initialValue,
|
||||
this.hintText = 'Phone number',
|
||||
this.errorMessage = 'Invalid phone number',
|
||||
this.selectorButtonOnErrorPadding = 24,
|
||||
this.spaceBetweenSelectorAndTextField = 12,
|
||||
this.maxLength = 15,
|
||||
this.isEnabled = true,
|
||||
this.formatInput = true,
|
||||
this.autoFocus = false,
|
||||
this.autoFocusSearch = false,
|
||||
this.autoValidateMode = AutovalidateMode.disabled,
|
||||
this.ignoreBlank = false,
|
||||
this.countrySelectorScrollControlled = true,
|
||||
this.locale,
|
||||
this.textStyle,
|
||||
this.selectorTextStyle,
|
||||
this.inputBorder,
|
||||
this.inputDecoration,
|
||||
this.searchBoxDecoration,
|
||||
this.textAlign = TextAlign.start,
|
||||
this.textAlignVertical = TextAlignVertical.center,
|
||||
this.scrollPadding = const EdgeInsets.all(20.0),
|
||||
this.focusNode,
|
||||
this.cursorColor,
|
||||
this.autofillHints,
|
||||
this.countries})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _InputWidgetState();
|
||||
}
|
||||
|
||||
class _InputWidgetState extends State<CustomInternationalPhoneNumberInput> {
|
||||
TextEditingController? controller;
|
||||
double selectorButtonBottomPadding = 0;
|
||||
|
||||
Country? country;
|
||||
List<Country> countries = [];
|
||||
bool isNotValid = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
loadCountries();
|
||||
controller = widget.textFieldController ?? TextEditingController();
|
||||
initialiseWidget();
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(fn) {
|
||||
if (this.mounted) {
|
||||
super.setState(fn);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _InputWidgetView(
|
||||
state: this,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(CustomInternationalPhoneNumberInput oldWidget) {
|
||||
if (oldWidget?.initialValue?.hash != widget?.initialValue?.hash) {
|
||||
loadCountries();
|
||||
initialiseWidget();
|
||||
} else {
|
||||
loadCountries(previouslySelectedCountry: country);
|
||||
}
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
/// [initialiseWidget] sets initial values of the widget
|
||||
void initialiseWidget() async {
|
||||
if (widget.initialValue != null) {
|
||||
if (widget.initialValue!.phoneNumber != null &&
|
||||
widget.initialValue!.phoneNumber!.isNotEmpty &&
|
||||
(await PhoneNumberUtil.isValidNumber(
|
||||
phoneNumber: widget.initialValue!.phoneNumber!,
|
||||
isoCode: widget.initialValue!.isoCode!))!) {
|
||||
controller!.text =
|
||||
await PhoneNumber.getParsableNumber(widget.initialValue!);
|
||||
|
||||
phoneNumberControllerListener();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// loads countries from [Countries.countryList] and selected Country
|
||||
void loadCountries({Country? previouslySelectedCountry}) {
|
||||
if (this.mounted) {
|
||||
List<Country> countries =
|
||||
CountryProvider.getCountriesData(countries: widget.countries!.cast<String>());
|
||||
|
||||
final CountryComparator? countryComparator =
|
||||
widget.selectorConfig?.countryComparator;
|
||||
if (countryComparator != null) {
|
||||
countries.sort(countryComparator);
|
||||
}
|
||||
|
||||
Country country = previouslySelectedCountry ??
|
||||
Utils.getInitialSelectedCountry(
|
||||
countries,
|
||||
widget.initialValue?.isoCode ?? '',
|
||||
);
|
||||
|
||||
setState(() {
|
||||
this.countries = countries;
|
||||
this.country = country;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Listener that validates changes from the widget, returns a bool to
|
||||
/// the `ValueCallback` [widget.onInputValidated]
|
||||
void phoneNumberControllerListener() {
|
||||
if (this.mounted) {
|
||||
String parsedPhoneNumberString =
|
||||
controller!.text.replaceAll(RegExp(r'[^\d+]'), '');
|
||||
|
||||
getParsedPhoneNumber(parsedPhoneNumberString, this.country?.alpha2Code)
|
||||
.then((phoneNumber) {
|
||||
if (phoneNumber == null) {
|
||||
String phoneNumber =
|
||||
'${this.country?.dialCode}$parsedPhoneNumberString';
|
||||
|
||||
if (widget.onInputChanged != null) {
|
||||
widget.onInputChanged(PhoneNumber(
|
||||
phoneNumber: phoneNumber,
|
||||
isoCode: this.country?.alpha2Code,
|
||||
dialCode: this.country?.dialCode));
|
||||
}
|
||||
|
||||
if (widget.onInputValidated != null) {
|
||||
widget.onInputValidated!(false);
|
||||
}
|
||||
this.isNotValid = true;
|
||||
} else {
|
||||
if (widget.onInputChanged != null) {
|
||||
widget.onInputChanged(PhoneNumber(
|
||||
phoneNumber: phoneNumber,
|
||||
isoCode: this.country?.alpha2Code,
|
||||
dialCode: this.country?.dialCode));
|
||||
}
|
||||
|
||||
if (widget.onInputValidated != null) {
|
||||
widget.onInputValidated!(true);
|
||||
}
|
||||
this.isNotValid = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a formatted String of [phoneNumber] with [isoCode], returns `null`
|
||||
/// if [phoneNumber] is not valid or if an [Exception] is caught.
|
||||
Future<String?> getParsedPhoneNumber(
|
||||
String phoneNumber, String? isoCode) async {
|
||||
if (phoneNumber.isNotEmpty && isoCode != null) {
|
||||
try {
|
||||
bool isValidPhoneNumber = (await PhoneNumberUtil.isValidNumber(
|
||||
phoneNumber: phoneNumber, isoCode: isoCode))!;
|
||||
|
||||
if (isValidPhoneNumber) {
|
||||
return await PhoneNumberUtil.normalizePhoneNumber(
|
||||
phoneNumber: phoneNumber, isoCode: isoCode);
|
||||
}
|
||||
} on Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Creates or Select [InputDecoration]
|
||||
InputDecoration getInputDecoration(InputDecoration? decoration) {
|
||||
InputDecoration value = decoration ??
|
||||
InputDecoration(
|
||||
border: widget.inputBorder ?? UnderlineInputBorder(),
|
||||
hintText: widget.hintText,
|
||||
);
|
||||
|
||||
if (widget.selectorConfig.setSelectorButtonAsPrefixIcon) {
|
||||
return value.copyWith(
|
||||
prefixIcon: CustomSelectorButton(
|
||||
country: country,
|
||||
countries: countries,
|
||||
onCountryChanged: onCountryChanged,
|
||||
selectorConfig: widget.selectorConfig,
|
||||
selectorTextStyle: widget.selectorTextStyle,
|
||||
searchBoxDecoration: widget.searchBoxDecoration,
|
||||
locale: locale,
|
||||
isEnabled: widget.isEnabled,
|
||||
autoFocusSearchField: widget.autoFocusSearch,
|
||||
isScrollControlled: widget.countrySelectorScrollControlled,
|
||||
));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Validate the phone number when a change occurs
|
||||
void onChanged(String value) {
|
||||
phoneNumberControllerListener();
|
||||
}
|
||||
|
||||
/// Validate and returns a validation error when [FormState] validate is called.
|
||||
///
|
||||
/// Also updates [selectorButtonBottomPadding]
|
||||
String? validator(String? value) {
|
||||
bool isValid =
|
||||
this.isNotValid && (value!.isNotEmpty || widget.ignoreBlank == false);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
if (isValid && widget.errorMessage != null) {
|
||||
setState(() {
|
||||
this.selectorButtonBottomPadding =
|
||||
widget.selectorButtonOnErrorPadding ?? 24;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
this.selectorButtonBottomPadding = 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return isValid ? widget.errorMessage : null;
|
||||
}
|
||||
|
||||
/// Changes Selector Button Country and Validate Change.
|
||||
void onCountryChanged(Country? country) {
|
||||
setState(() {
|
||||
this.country = country;
|
||||
});
|
||||
phoneNumberControllerListener();
|
||||
}
|
||||
|
||||
void _phoneNumberSaved() {
|
||||
if (this.mounted) {
|
||||
String parsedPhoneNumberString =
|
||||
controller!.text.replaceAll(RegExp(r'[^\d+]'), '');
|
||||
|
||||
getParsedPhoneNumber(parsedPhoneNumberString, this.country?.alpha2Code)
|
||||
.then(
|
||||
(phoneNumber) => widget.onSaved?.call(
|
||||
PhoneNumber(
|
||||
phoneNumber: phoneNumber,
|
||||
isoCode: this.country?.alpha2Code,
|
||||
dialCode: this.country?.dialCode),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Saved the phone number when form is saved
|
||||
void onSaved(String? value) {
|
||||
_phoneNumberSaved();
|
||||
}
|
||||
|
||||
/// Corrects duplicate locale
|
||||
String? get locale {
|
||||
if (widget.locale == null) return null;
|
||||
|
||||
if (widget.locale!.toLowerCase() == 'nb' ||
|
||||
widget.locale!.toLowerCase() == 'nn') {
|
||||
return 'no';
|
||||
}
|
||||
return widget.locale;
|
||||
}
|
||||
}
|
||||
|
||||
class _InputWidgetView
|
||||
extends WidgetView<CustomInternationalPhoneNumberInput, _InputWidgetState> {
|
||||
final _InputWidgetState state;
|
||||
|
||||
_InputWidgetView({Key? key, required this.state})
|
||||
: super(key: key, state: state);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final countryCode = state?.country?.alpha2Code ?? '';
|
||||
final dialCode = state?.country?.dialCode ?? '';
|
||||
|
||||
return Container(
|
||||
child: Row(
|
||||
textDirection: TextDirection.ltr,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
CustomSelectorButton(
|
||||
country: state.country,
|
||||
countries: state.countries,
|
||||
onCountryChanged: state.onCountryChanged,
|
||||
selectorConfig: widget.selectorConfig,
|
||||
selectorTextStyle: widget.selectorTextStyle,
|
||||
searchBoxDecoration: widget.searchBoxDecoration,
|
||||
locale: state.locale,
|
||||
isEnabled: widget.isEnabled,
|
||||
autoFocusSearchField: widget.autoFocusSearch,
|
||||
isScrollControlled: widget.countrySelectorScrollControlled,
|
||||
),
|
||||
SizedBox(
|
||||
height: state.selectorButtonBottomPadding,
|
||||
),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
key: Key(TestHelper.TextInputKeyValue),
|
||||
textDirection: TextDirection.ltr,
|
||||
controller: state.controller,
|
||||
focusNode: widget.focusNode,
|
||||
enabled: widget.isEnabled,
|
||||
autofocus: widget.autoFocus,
|
||||
keyboardType: widget.keyboardType,
|
||||
textInputAction: widget.keyboardAction,
|
||||
style: widget.textStyle,
|
||||
decoration: state.getInputDecoration(widget.inputDecoration),
|
||||
textAlign: widget.textAlign,
|
||||
textAlignVertical: widget.textAlignVertical,
|
||||
onEditingComplete: widget.onSubmit,
|
||||
onFieldSubmitted: widget.onFieldSubmitted,
|
||||
autovalidateMode: widget.autoValidateMode,
|
||||
autofillHints: widget.autofillHints,
|
||||
validator: widget.validator ?? state.validator,
|
||||
onSaved: state.onSaved,
|
||||
scrollPadding: widget.scrollPadding,
|
||||
inputFormatters: [
|
||||
LengthLimitingTextInputFormatter(widget.maxLength),
|
||||
widget.formatInput
|
||||
? AsYouTypeFormatter(
|
||||
isoCode: countryCode,
|
||||
dialCode: dialCode,
|
||||
onInputFormatted: (TextEditingValue value) {
|
||||
state.controller!.value = value;
|
||||
},
|
||||
)
|
||||
: FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
onChanged: state.onChanged,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// [CustomSelectorButton]
|
||||
class CustomSelectorButton extends StatelessWidget {
|
||||
final List<Country> countries;
|
||||
final Country? country;
|
||||
final SelectorConfig selectorConfig;
|
||||
final TextStyle? selectorTextStyle;
|
||||
final InputDecoration? searchBoxDecoration;
|
||||
final bool autoFocusSearchField;
|
||||
final String? locale;
|
||||
final bool isEnabled;
|
||||
final bool isScrollControlled;
|
||||
|
||||
final ValueChanged<Country?> onCountryChanged;
|
||||
|
||||
const CustomSelectorButton({
|
||||
Key? key,
|
||||
required this.countries,
|
||||
required this.country,
|
||||
required this.selectorConfig,
|
||||
required this.selectorTextStyle,
|
||||
required this.searchBoxDecoration,
|
||||
required this.autoFocusSearchField,
|
||||
required this.locale,
|
||||
required this.onCountryChanged,
|
||||
required this.isEnabled,
|
||||
required this.isScrollControlled,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return selectorConfig.selectorType == PhoneInputSelectorType.DROPDOWN
|
||||
? countries.isNotEmpty && countries.length > 1
|
||||
? DropdownButtonHideUnderline(
|
||||
child: DropdownButton<Country>(
|
||||
key: Key(TestHelper.DropdownButtonKeyValue),
|
||||
hint: Item(
|
||||
country: country,
|
||||
showFlag: selectorConfig.showFlags,
|
||||
useEmoji: selectorConfig.useEmoji,
|
||||
textStyle: selectorTextStyle,
|
||||
),
|
||||
value: country,
|
||||
items: mapCountryToDropdownItem(countries),
|
||||
onChanged: isEnabled ? onCountryChanged : null,
|
||||
),
|
||||
)
|
||||
: Item(
|
||||
country: country,
|
||||
showFlag: selectorConfig.showFlags,
|
||||
useEmoji: selectorConfig.useEmoji,
|
||||
textStyle: selectorTextStyle,
|
||||
)
|
||||
: Container(
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(
|
||||
color: MyTheme.textfield_grey,
|
||||
width: .5
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(5.0),
|
||||
bottomLeft: Radius.circular(5.0))),
|
||||
child: Buttons(
|
||||
key: Key(TestHelper.DropdownButtonKeyValue),
|
||||
padding: EdgeInsets.zero,
|
||||
color: MyTheme.grey_153,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: const Radius.circular(5.0),
|
||||
bottomLeft: const Radius.circular(5.0),
|
||||
)),
|
||||
onPressed: countries.isNotEmpty &&
|
||||
countries.length > 1 &&
|
||||
isEnabled
|
||||
? () async {
|
||||
Country? selected;
|
||||
if (selectorConfig.selectorType ==
|
||||
PhoneInputSelectorType.BOTTOM_SHEET) {
|
||||
selected = await showCountrySelectorBottomSheet(
|
||||
context, countries);
|
||||
} else {
|
||||
selected =
|
||||
await showCountrySelectorDialog(context, countries);
|
||||
}
|
||||
|
||||
if (selected != null) {
|
||||
onCountryChanged(selected);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Item(
|
||||
country: country,
|
||||
showFlag: selectorConfig.showFlags,
|
||||
useEmoji: selectorConfig.useEmoji,
|
||||
textStyle: TextStyle(
|
||||
color: MyTheme.textfield_grey) //selectorTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Converts the list [countries] to `DropdownMenuItem`
|
||||
List<DropdownMenuItem<Country>> mapCountryToDropdownItem(
|
||||
List<Country> countries) {
|
||||
return countries.map((country) {
|
||||
return DropdownMenuItem<Country>(
|
||||
value: country,
|
||||
child: Item(
|
||||
key: Key(TestHelper.countryItemKeyValue(country.alpha2Code)),
|
||||
country: country,
|
||||
showFlag: selectorConfig.showFlags,
|
||||
useEmoji: selectorConfig.useEmoji,
|
||||
textStyle: selectorTextStyle,
|
||||
withCountryNames: false,
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/// shows a Dialog with list [countries] if the [PhoneInputSelectorType.DIALOG] is selected
|
||||
Future<Country?> showCountrySelectorDialog(
|
||||
BuildContext context, List<Country> countries) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
content: Container(
|
||||
width: double.maxFinite,
|
||||
child: CountrySearchListWidget(
|
||||
countries,
|
||||
locale,
|
||||
searchBoxDecoration: searchBoxDecoration,
|
||||
showFlags: selectorConfig.showFlags,
|
||||
useEmoji: selectorConfig.useEmoji,
|
||||
autoFocus: autoFocusSearchField,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// shows a Dialog with list [countries] if the [PhoneInputSelectorType.BOTTOM_SHEET] is selected
|
||||
Future<Country?> showCountrySelectorBottomSheet(
|
||||
BuildContext context, List<Country> countries) {
|
||||
return showModalBottomSheet(
|
||||
context: context,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
isScrollControlled: isScrollControlled ?? true,
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(12), topRight: Radius.circular(12))),
|
||||
builder: (BuildContext context) {
|
||||
return AnimatedPadding(
|
||||
padding:
|
||||
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: Stack(children: [
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.pop(context),
|
||||
),
|
||||
DraggableScrollableSheet(
|
||||
builder: (BuildContext context, ScrollController controller) {
|
||||
return Container(
|
||||
decoration: ShapeDecoration(
|
||||
color: Theme.of(context).canvasColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(12),
|
||||
topRight: Radius.circular(12),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: CountrySearchListWidget(
|
||||
countries,
|
||||
locale,
|
||||
searchBoxDecoration: searchBoxDecoration,
|
||||
scrollController: controller,
|
||||
showFlags: selectorConfig.showFlags,
|
||||
useEmoji: selectorConfig.useEmoji,
|
||||
autoFocus: autoFocusSearchField,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
]),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
55
source_code/lib/custom/loading.dart
Normal file
55
source_code/lib/custom/loading.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:active_ecommerce_seller_app/custom/localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:one_context/one_context.dart';
|
||||
|
||||
|
||||
|
||||
class Loading{
|
||||
static BuildContext? _buildContext;
|
||||
static late BuildContext _context;
|
||||
|
||||
static setInstance(BuildContext context){
|
||||
_buildContext= context;
|
||||
}
|
||||
|
||||
static getInstance()=>Loading._buildContext;
|
||||
|
||||
Future show()async{
|
||||
|
||||
return showDialog(
|
||||
context: Loading._buildContext!,
|
||||
builder: (BuildContext context) {
|
||||
Loading._context=context;
|
||||
return AlertDialog(
|
||||
content: Row(
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(LangText(context: context).getLocal()!.please_wait_ucf),
|
||||
],
|
||||
));
|
||||
},);
|
||||
}
|
||||
|
||||
hide(){
|
||||
Navigator.of(Loading._context).pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static Widget bottomLoading(bool value){
|
||||
return value? Container(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: CircularProgressIndicator()),
|
||||
):SizedBox(height: 5,width: 5,);
|
||||
}
|
||||
|
||||
}
|
||||
12
source_code/lib/custom/localization.dart
Normal file
12
source_code/lib/custom/localization.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class LangText{
|
||||
BuildContext? context;
|
||||
|
||||
LangText({this.context});
|
||||
|
||||
AppLocalizations? getLocal(){
|
||||
return AppLocalizations.of(context!);
|
||||
}
|
||||
}
|
||||
6
source_code/lib/custom/multi_select.dart
Normal file
6
source_code/lib/custom/multi_select.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
class SelectProduct {
|
||||
SelectProduct({this.id, this.name, this.isSelect});
|
||||
var id;
|
||||
String? name;
|
||||
bool? isSelect;
|
||||
}
|
||||
107
source_code/lib/custom/my_app_bar.dart
Normal file
107
source_code/lib/custom/my_app_bar.dart
Normal file
@@ -0,0 +1,107 @@
|
||||
import 'package:active_ecommerce_seller_app/custom/common_style.dart';
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MyAppBar {
|
||||
bool? centerTitle = false;
|
||||
String? title;
|
||||
BuildContext? context;
|
||||
|
||||
MyAppBar({this.title,this.context,this.centerTitle});
|
||||
|
||||
AppBar show({var elevation= 5.0}) {
|
||||
return AppBar(
|
||||
|
||||
leadingWidth:0.0,
|
||||
centerTitle: centerTitle,
|
||||
elevation: elevation,
|
||||
title: Row(
|
||||
children: [
|
||||
Container(
|
||||
width:24,
|
||||
height: 24,
|
||||
child: IconButton(
|
||||
splashRadius: 15,
|
||||
padding: EdgeInsets.all(0.0),
|
||||
onPressed: (){
|
||||
Navigator.pop(context!);
|
||||
}, icon: Image.asset(
|
||||
'assets/icon/back_arrow.png',
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: MyTheme.app_accent_color,
|
||||
//color: MyTheme.dark_grey,
|
||||
),),
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
Text(title!,style: MyTextStyle().appbarText(),),
|
||||
],
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
/*leading:Container(
|
||||
margin: EdgeInsets.only(left: 10),
|
||||
child: IconButton(
|
||||
|
||||
iconSize: 20,
|
||||
splashRadius: 15,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: (){
|
||||
Navigator.pop(context);
|
||||
}, icon: Image.asset(
|
||||
'assets/icon/back_arrow.png',
|
||||
height: 20,
|
||||
width: 20,
|
||||
//color: MyTheme.dark_grey,
|
||||
),),
|
||||
),*/
|
||||
);
|
||||
}
|
||||
AppBar copyWithBottom({var elevation= 5.0,Widget bottom= const SizedBox(height: 0,width: 0,),Size size=const Size(0, 0)}) {
|
||||
return AppBar(
|
||||
|
||||
leadingWidth:0.0,
|
||||
centerTitle: centerTitle,
|
||||
elevation: elevation,
|
||||
title: Row(
|
||||
children: [
|
||||
Container(
|
||||
width:24,
|
||||
height: 24,
|
||||
child: IconButton(
|
||||
splashRadius: 15,
|
||||
padding: EdgeInsets.all(0.0),
|
||||
onPressed: (){
|
||||
Navigator.pop(context!);
|
||||
}, icon: Image.asset(
|
||||
'assets/icon/back_arrow.png',
|
||||
height: 20,
|
||||
width: 20,
|
||||
color: MyTheme.app_accent_color,
|
||||
//color: MyTheme.dark_grey,
|
||||
),),
|
||||
),
|
||||
SizedBox(width: 10,),
|
||||
Text(title!,style: MyTextStyle().appbarText(),),
|
||||
],
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
bottom: PreferredSize(child: bottom,preferredSize: size,),
|
||||
/*leading:Container(
|
||||
margin: EdgeInsets.only(left: 10),
|
||||
child: IconButton(
|
||||
|
||||
iconSize: 20,
|
||||
splashRadius: 15,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: (){
|
||||
Navigator.pop(context);
|
||||
}, icon: Image.asset(
|
||||
'assets/icon/back_arrow.png',
|
||||
height: 20,
|
||||
width: 20,
|
||||
//color: MyTheme.dark_grey,
|
||||
),),
|
||||
),*/
|
||||
);
|
||||
}
|
||||
}
|
||||
465
source_code/lib/custom/my_widget.dart
Normal file
465
source_code/lib/custom/my_widget.dart
Normal file
@@ -0,0 +1,465 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:active_ecommerce_seller_app/custom/common_style.dart';
|
||||
import 'package:active_ecommerce_seller_app/custom/device_info.dart';
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
|
||||
class MyWidget {
|
||||
BuildContext? myContext;
|
||||
BuildContext? pop;
|
||||
|
||||
MyWidget({this.myContext});
|
||||
|
||||
BuildContext? getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
Container myContainer(
|
||||
{double width = 0.0,
|
||||
double borderWith = 1.0,
|
||||
double height = 0.0,
|
||||
double borderRadius = 0.0,
|
||||
Color bgColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Color borderColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Widget? child,
|
||||
double paddingX = 0.0,
|
||||
paddingY = 0.0,
|
||||
double marginX = 0.0,
|
||||
double marginY = 0.0,
|
||||
Alignment alignment = Alignment.center}) {
|
||||
return Container(
|
||||
alignment: alignment,
|
||||
padding: EdgeInsets.symmetric(horizontal: paddingY, vertical: paddingX),
|
||||
margin: EdgeInsets.symmetric(horizontal: marginY, vertical: marginX),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
border: Border.all(color: borderColor, width: borderWith),
|
||||
color: bgColor,
|
||||
),
|
||||
height: height,
|
||||
width: width,
|
||||
child: child);
|
||||
}
|
||||
|
||||
Container productContainer(
|
||||
{double width = 0.0,
|
||||
double height = 0.0,
|
||||
double borderRadius = 0.0,
|
||||
Color backgroundColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Color borderColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Widget? child,
|
||||
EdgeInsets? padding,
|
||||
EdgeInsets? margin,
|
||||
Alignment alignment = Alignment.center}) {
|
||||
return Container(
|
||||
alignment: alignment,
|
||||
padding: padding,
|
||||
margin: margin,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
border: Border.all(color: borderColor),
|
||||
color: backgroundColor,
|
||||
),
|
||||
height: height,
|
||||
width: width,
|
||||
child: child);
|
||||
}
|
||||
|
||||
static Container customContainer(
|
||||
{double width = 0.0,
|
||||
double height = 0.0,
|
||||
double borderRadius = 0.0,
|
||||
Color backgroundColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Color borderColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Widget? child,
|
||||
EdgeInsets? padding,
|
||||
EdgeInsets? margin,
|
||||
Alignment alignment = Alignment.center}) {
|
||||
return Container(
|
||||
alignment: alignment,
|
||||
padding: padding,
|
||||
margin: margin,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
border: Border.all(color: borderColor),
|
||||
color: backgroundColor,
|
||||
),
|
||||
constraints: BoxConstraints(
|
||||
minHeight: height,
|
||||
maxWidth: width,
|
||||
),
|
||||
child: child);
|
||||
}
|
||||
|
||||
Card customCard(
|
||||
{double width = 0.0,
|
||||
double elevation = 0.0,
|
||||
double height = 0.0,
|
||||
double borderRadius = 0.0,
|
||||
Color backgroundColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Color borderColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
double borderWidth=0.0,
|
||||
Widget? child,
|
||||
EdgeInsets? padding,
|
||||
Color shadowColor = MyTheme.app_accent_shado,
|
||||
EdgeInsets? margin,
|
||||
Alignment alignment = Alignment.center}) {
|
||||
return Card(
|
||||
|
||||
shadowColor: shadowColor,
|
||||
color: backgroundColor,
|
||||
margin: margin,
|
||||
child: child,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(color: borderColor, width: borderWidth),
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
elevation: elevation,
|
||||
//color: backgroundColor,
|
||||
);
|
||||
}
|
||||
|
||||
Container imageContainer(
|
||||
{double width = 0.0,
|
||||
double height = 0.0,
|
||||
BorderRadius borderRadius = BorderRadius.zero,
|
||||
Color backgroundColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Color borderColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
required ImageProvider imageProvider,
|
||||
Widget? child,
|
||||
EdgeInsets? padding,
|
||||
EdgeInsets? margin,
|
||||
BoxFit? fit,
|
||||
Alignment alignment = Alignment.center}) {
|
||||
return Container(
|
||||
alignment: alignment,
|
||||
padding: padding,
|
||||
margin: margin,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: borderRadius,
|
||||
border: Border.all(color: borderColor),
|
||||
color: backgroundColor,
|
||||
image: DecorationImage(
|
||||
image: imageProvider,
|
||||
fit: fit,
|
||||
),
|
||||
),
|
||||
height: height,
|
||||
width: width,
|
||||
);
|
||||
}
|
||||
|
||||
static Widget imageWithPlaceholder(
|
||||
{String? url,
|
||||
double height = 0.0,
|
||||
double elevation = 0.0,
|
||||
BoxBorder? border,
|
||||
width = 0.0,
|
||||
BorderRadiusGeometry radius = BorderRadius.zero,
|
||||
BoxFit fit = BoxFit.cover,
|
||||
Color backgroundColor = Colors.white
|
||||
}) {
|
||||
return Material(
|
||||
color: backgroundColor,
|
||||
elevation: elevation,
|
||||
borderRadius: radius,
|
||||
|
||||
child: Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius,
|
||||
border: border?? Border.all(width: 0,color: MyTheme.noColor),
|
||||
),
|
||||
child: url != null && url.isNotEmpty
|
||||
? ClipRRect(
|
||||
borderRadius: radius,
|
||||
child: FadeInImage.assetNetwork(
|
||||
placeholder: "assets/logo/placeholder.png",
|
||||
image: url,
|
||||
height: height,
|
||||
imageErrorBuilder: (context, object, stackTrace) {
|
||||
return Container(
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius,
|
||||
image:const DecorationImage(
|
||||
image: AssetImage("assets/logo/placeholder.png"),
|
||||
fit: BoxFit.cover
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
},
|
||||
width: width,
|
||||
fit: fit,
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius,
|
||||
image:const DecorationImage(
|
||||
image: AssetImage("assets/logo/placeholder.png"),
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
static Widget fileImage(
|
||||
{File? image,
|
||||
double height = 0.0,
|
||||
double elevation = 0.0,
|
||||
width = 0.0,
|
||||
BorderRadiusGeometry radius = BorderRadius.zero,
|
||||
BoxFit fit = BoxFit.cover,
|
||||
Color backgroundColor = Colors.white
|
||||
}) {
|
||||
return Material(
|
||||
color: backgroundColor,
|
||||
elevation: elevation,
|
||||
borderRadius: radius,
|
||||
child: Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius
|
||||
),
|
||||
child: image != null && image.path.isNotEmpty
|
||||
? ClipRRect(
|
||||
borderRadius: radius,
|
||||
child:Container(
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius,
|
||||
image: DecorationImage(
|
||||
image: FileImage(image),
|
||||
fit: BoxFit.cover
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
: Container(
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: radius,
|
||||
image:const DecorationImage(
|
||||
image: AssetImage("assets/logo/placeholder.png"),
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Widget roundImageWithPlaceholder(
|
||||
{String? url,
|
||||
double height = 0.0,
|
||||
double elevation = 0.0,
|
||||
double borderWidth = 0.0,
|
||||
width = 0.0,
|
||||
double paddingX = 0.0,
|
||||
double paddingY = 0.0,
|
||||
double borderRadius = 0.0,
|
||||
Color backgroundColor = Colors.white,
|
||||
BoxFit fit = BoxFit.cover}) {
|
||||
return Material(
|
||||
color: backgroundColor,
|
||||
elevation: elevation,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
child: MyWidget().myContainer(
|
||||
borderWith: borderWidth,
|
||||
width: width,
|
||||
height: height,
|
||||
paddingY: paddingY,
|
||||
paddingX: paddingX,
|
||||
borderRadius: borderRadius,
|
||||
bgColor: backgroundColor,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
child: url != null && url.isNotEmpty
|
||||
? FadeInImage.assetNetwork(
|
||||
placeholder: "assets/logo/placeholder.png",
|
||||
image: url,
|
||||
|
||||
imageErrorBuilder: (context, object, stackTrace) {
|
||||
return Container(
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
image:const DecorationImage(
|
||||
image: AssetImage("assets/logo/placeholder.png"),
|
||||
fit: BoxFit.cover
|
||||
)
|
||||
),
|
||||
);
|
||||
},
|
||||
height: height,
|
||||
width: width,
|
||||
fit: fit,
|
||||
)
|
||||
: Container(
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
image:const DecorationImage(
|
||||
image: AssetImage("assets/logo/placeholder.png"),
|
||||
fit: BoxFit.cover
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Image boxImage(url) {
|
||||
return Image.asset(
|
||||
url,
|
||||
color: MyTheme.white.withOpacity(0.5),
|
||||
height: 32,
|
||||
width: 32,
|
||||
);
|
||||
}
|
||||
|
||||
static Widget homePageTopBox(BuildContext context,
|
||||
{required String title, required counter, required iconUrl,double elevation = 0.0}) {
|
||||
return customCardView(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.only(top: 14,left: 14),
|
||||
borderRadius:10,
|
||||
backgroundColor: MyTheme.app_accent_color,
|
||||
height: 75,
|
||||
width: DeviceInfo(context).getWidth() / 2 - 20,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: MyTextStyle().dashboardBoxText(context),
|
||||
),
|
||||
Text(
|
||||
counter,
|
||||
style: MyTextStyle().dashboardBoxNumber(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
MyWidget.boxImage(iconUrl)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
static Widget customCardView(
|
||||
{double width = 0.0,
|
||||
double elevation=0.0,
|
||||
double blurSize=20.0,
|
||||
double height = 0.0,
|
||||
double borderRadius = 0.0,
|
||||
Color shadowColor = MyTheme.app_accent_shado,
|
||||
Color borderColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Color backgroundColor = const Color.fromRGBO(255, 255, 255, 0),
|
||||
Widget? child,
|
||||
double borderWidth=0.0,
|
||||
EdgeInsets? padding,
|
||||
EdgeInsets? margin,
|
||||
Alignment alignment = Alignment.center}) {
|
||||
return Container(
|
||||
margin: margin,
|
||||
height: height,
|
||||
width: width,
|
||||
padding: padding,
|
||||
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
border: Border.all(color: borderColor,width: borderWidth),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: shadowColor,
|
||||
offset: Offset(0, 6),
|
||||
blurRadius: blurSize,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
|
||||
/*
|
||||
|
||||
Container(
|
||||
margin: margin,
|
||||
child: Material(
|
||||
elevation:elevation ,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
//color: MyTheme.red,
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(borderRadius),
|
||||
),
|
||||
height: height,
|
||||
width: width,
|
||||
padding: padding,
|
||||
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);*/
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
static Widget imageSlider(List<String> imageUrl, BuildContext context) {
|
||||
return Container(
|
||||
child: CarouselSlider(
|
||||
options: CarouselOptions(height: 400.0),
|
||||
items: imageUrl.map((i) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||
// decoration: BoxDecoration(
|
||||
//
|
||||
// ),
|
||||
child: imageWithPlaceholder(
|
||||
height: 157,
|
||||
width: DeviceInfo(context).getWidth(),
|
||||
fit: BoxFit.cover),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
} */
|
||||
|
||||
static Widget imageSlider({required List<String> imageUrl, BuildContext? context}) {
|
||||
return Container(
|
||||
child: CarouselSlider(
|
||||
|
||||
options: CarouselOptions(height: 400.0,aspectRatio: 16/7,viewportFraction: 1,autoPlay: true,enableInfiniteScroll: true),
|
||||
items: List.generate(
|
||||
imageUrl.length,
|
||||
(index) => imageWithPlaceholder(
|
||||
url: imageUrl[index],
|
||||
height: 157,
|
||||
width: DeviceInfo(context).getWidth(),
|
||||
fit: BoxFit.cover),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
17
source_code/lib/custom/route_transaction.dart
Normal file
17
source_code/lib/custom/route_transaction.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MyTransaction{
|
||||
BuildContext? context;
|
||||
MyTransaction({this.context});
|
||||
|
||||
Future<bool> push(Widget route)async{
|
||||
var value= await Navigator.push(
|
||||
context!,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return route;
|
||||
}),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
14
source_code/lib/custom/select_payment_list.dart
Normal file
14
source_code/lib/custom/select_payment_list.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
class PaymentType{
|
||||
String key,value;
|
||||
PaymentType(this.key, this.value);
|
||||
}
|
||||
class PaymentOption{
|
||||
static List<PaymentType> getList(){
|
||||
List<PaymentType> list = [];
|
||||
list.add(PaymentType("select", "Select"));
|
||||
list.add(PaymentType("offline", "Offline"));
|
||||
list.add(PaymentType("online", "Online"));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
30
source_code/lib/custom/submitButton.dart
Normal file
30
source_code/lib/custom/submitButton.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SubmitBtn{
|
||||
static Widget show({EdgeInsetsGeometry padding= EdgeInsets.zero,Color borderColor=const Color.fromRGBO(255, 255, 255, 0.0) ,double elevation=0.0,Alignment alignment = Alignment.centerLeft,Color backgroundColor=MyTheme.app_accent_color,Function? onTap ,double height=0.0,double width=0.0,double radius=0.0,Widget child= const Text("")}){
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: elevation,
|
||||
backgroundColor: backgroundColor,
|
||||
padding: padding,
|
||||
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(radius),
|
||||
side: BorderSide(color: borderColor)
|
||||
),
|
||||
),
|
||||
onPressed: onTap as void Function()?,
|
||||
child: Container(
|
||||
height: height,
|
||||
width: width,
|
||||
alignment: alignment,
|
||||
child: child),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
28
source_code/lib/custom/toast_component.dart
Normal file
28
source_code/lib/custom/toast_component.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:active_ecommerce_seller_app/my_theme.dart';
|
||||
import 'package:one_context/one_context.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ToastComponent {
|
||||
static showDialog(String msg, {duration = 0, gravity = 0,textStyle = const TextStyle(color: MyTheme.font_grey),Color bgColor =const Color.fromRGBO(239, 239, 239, .9)}) {
|
||||
ToastContext().init(OneContext().context!);
|
||||
Toast.show(
|
||||
msg,
|
||||
duration: duration != 0 ? duration : Toast.lengthLong,
|
||||
gravity: gravity != 0 ? gravity : Toast.bottom,
|
||||
backgroundColor:bgColor,
|
||||
textStyle:textStyle,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Color.fromRGBO(203, 209, 209, 1),
|
||||
),bottom:BorderSide(
|
||||
color: Color.fromRGBO(203, 209, 209, 1),
|
||||
),right: BorderSide(
|
||||
color: Color.fromRGBO(203, 209, 209, 1),
|
||||
),left: BorderSide(
|
||||
color: Color.fromRGBO(203, 209, 209, 1),
|
||||
)),
|
||||
backgroundRadius: 6
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user