completed the mobile app for he boss to review the stock report
This commit is contained in:
206
boss_app2/lib/controller/boss_controller.dart
Normal file
206
boss_app2/lib/controller/boss_controller.dart
Normal file
@ -0,0 +1,206 @@
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:boss_app2/global.dart' as globals;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
// ignore: unused_import
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
//create class LoginController extends ChangeNotifier
|
||||
class BossController extends ChangeNotifier {
|
||||
//create future string login , parameter is String username and password
|
||||
Future<Map> ambilLaporan(
|
||||
String tanggal, String bulan, String tahun, String filter) async {
|
||||
//create string result
|
||||
Map<String, dynamic> result;
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/ambil_laporan?tanggal=$tanggal&bulan=$bulan&tahun=$tahun&filter=$filter"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
final data = jsonDecode(response.body);
|
||||
result = data;
|
||||
} catch (e) {
|
||||
result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Map> ambilLaporanDetail(String no_log) async {
|
||||
//create string result
|
||||
Map<String, dynamic> result;
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/ambil_laporan_detail?no_log=$no_log"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
result = data;
|
||||
} catch (e) {
|
||||
result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Map> ambilProdukAll(
|
||||
int pageNumber, String filter, String cekFilter) async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/ambil_produk_all?page=$pageNumber&filter=$filter&cekfilter=$cekFilter"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
result = data;
|
||||
} catch (e) {
|
||||
result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Map> ambilLaporanProdukDetail(
|
||||
int no_barang, int pageNumber, String filter, String cek_filter) async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/ambil_log_produk_detail?no_barang=$no_barang&page=$pageNumber&haha=$cek_filter&filter=$filter"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
result = data;
|
||||
} catch (e) {
|
||||
result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Map> ambilProdukDetail(int no_barang) async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/ambil_produk_detail?no_barang=$no_barang"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
result = data;
|
||||
} catch (e) {
|
||||
result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Map> ambilLaporanAll(
|
||||
int pageNumber, String filter, String cek_filter) async {
|
||||
Map<String, dynamic> result;
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/ambil_laporan_all?page=$pageNumber&haha=$cek_filter&filter=$filter"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
result = data;
|
||||
} catch (e) {
|
||||
result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<void> laporanRead(String no_log) async {
|
||||
final sharedPreference = await SharedPreferences.getInstance();
|
||||
|
||||
// sharedPreference.remove('notif');
|
||||
try {
|
||||
await http.get(
|
||||
Uri.parse("${globals.http_to_server}api/laporan_read?no_log=$no_log"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
|
||||
// final data = jsonDecode(response.body);
|
||||
final String? _notif = sharedPreference.getString('notif');
|
||||
if (_notif != null) {
|
||||
final List<dynamic> _notifList = jsonDecode(_notif);
|
||||
_notifList
|
||||
.removeWhere((element) => element.toString() == no_log.toString());
|
||||
|
||||
sharedPreference.setString(
|
||||
'notif', (_notifList.isNotEmpty) ? jsonEncode(_notifList) : "");
|
||||
}
|
||||
} catch (e) {
|
||||
// result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> laporanReadAll() async {
|
||||
final sharedPreference = await SharedPreferences.getInstance();
|
||||
|
||||
// sharedPreference.remove('notif');
|
||||
try {
|
||||
await http.get(Uri.parse("${globals.http_to_server}api/laporan_read_all"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
sharedPreference.remove('notif');
|
||||
} catch (e) {
|
||||
// result = {"status": "error", "message": e.toString()};
|
||||
}
|
||||
}
|
||||
}
|
||||
30
boss_app2/lib/controller/datatables_laporan.dart
Normal file
30
boss_app2/lib/controller/datatables_laporan.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MyData extends DataTableSource {
|
||||
// Generate some made-up data
|
||||
final List<Map<String, dynamic>> _data = List.generate(
|
||||
200,
|
||||
(index) => {
|
||||
"id": index,
|
||||
"title": "Item $index",
|
||||
"price": Random().nextInt(10000),
|
||||
},
|
||||
);
|
||||
|
||||
@override
|
||||
bool get isRowCountApproximate => false;
|
||||
@override
|
||||
int get rowCount => _data.length;
|
||||
@override
|
||||
int get selectedRowCount => 0;
|
||||
@override
|
||||
DataRow getRow(int index) {
|
||||
return DataRow(cells: [
|
||||
DataCell(Text(_data[index]['id'].toString())),
|
||||
DataCell(Text(_data[index]["title"])),
|
||||
DataCell(Text(_data[index]["price"].toString())),
|
||||
]);
|
||||
}
|
||||
}
|
||||
107
boss_app2/lib/controller/login_controller.dart
Normal file
107
boss_app2/lib/controller/login_controller.dart
Normal file
@ -0,0 +1,107 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:boss_app2/global.dart' as globals;
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
//create class LoginController extends ChangeNotifier
|
||||
class LoginController extends ChangeNotifier {
|
||||
//create future string login , parameter is String username and password
|
||||
Future<String> login(String username, String password) async {
|
||||
late String _returnString;
|
||||
|
||||
try {
|
||||
//create final sharedPreferences
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
|
||||
//create http get wih basic auth
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
"${globals.http_to_server}api/login_user?username=$username&password=$password"),
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
final data = jsonDecode(response.body);
|
||||
if (response.statusCode == 200) {
|
||||
if (data['data']['level'] == '0') {
|
||||
sharedPreferences.setString('level', 'Superadmin');
|
||||
} else if (data['data']['level'] == '1') {
|
||||
sharedPreferences.setString('level', 'Boss');
|
||||
}
|
||||
_returnString = "1";
|
||||
sharedPreferences.setString('data', jsonEncode(data['data']));
|
||||
} else if (response.statusCode == 401) {
|
||||
_returnString = "2";
|
||||
}
|
||||
} catch (e) {
|
||||
_returnString = "3";
|
||||
}
|
||||
|
||||
//return result
|
||||
return _returnString;
|
||||
}
|
||||
|
||||
Future<int> getNotif() async {
|
||||
int result;
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
try {
|
||||
final response = await http
|
||||
.get(Uri.parse("${globals.http_to_server}api/cek_datanya"), headers: {
|
||||
"Accept": "application/json",
|
||||
"authorization":
|
||||
"Basic ${base64Encode(utf8.encode("Kicap_karan:bb10c6d9f01ec0cb16726b59e36c2f73"))}",
|
||||
"crossDomain": "true"
|
||||
});
|
||||
final data = jsonDecode(response.body);
|
||||
final List datanya = data['data'];
|
||||
|
||||
final String? _notif = sharedPreferences.getString('notif');
|
||||
List<dynamic> _arrayNotif;
|
||||
if (_notif == null) {
|
||||
_arrayNotif = [];
|
||||
} else {
|
||||
_arrayNotif = jsonDecode(_notif);
|
||||
}
|
||||
|
||||
int jumlah = datanya.length;
|
||||
bool cek = false;
|
||||
|
||||
for (var i = 0; i < datanya.length; i++) {
|
||||
cek = false;
|
||||
for (var j = 0; j < _arrayNotif.length; j++) {
|
||||
if (_arrayNotif[j].toString() == datanya[i]['no_log'].toString()) {
|
||||
jumlah = jumlah - 1;
|
||||
cek = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cek == false) {
|
||||
_arrayNotif.add(int.parse(datanya[i]['no_log']));
|
||||
}
|
||||
cek = false;
|
||||
}
|
||||
|
||||
sharedPreferences.setString('notif', jsonEncode(_arrayNotif));
|
||||
// // if (jumlah > 0) {
|
||||
// // NotificationApi.showNotification(
|
||||
// // title: 'Laporan Baru',
|
||||
// // body: 'Ada $jumlah laporan baru',
|
||||
// // payload: 'Laporan Baru',
|
||||
// // );
|
||||
// // }
|
||||
|
||||
result = jumlah;
|
||||
// result = datanya;
|
||||
} catch (e) {
|
||||
// result = [];
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
98
boss_app2/lib/controller/notification_api.dart
Normal file
98
boss_app2/lib/controller/notification_api.dart
Normal file
@ -0,0 +1,98 @@
|
||||
import 'package:boss_app2/page/login.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import 'package:timezone/timezone.dart' as tz;
|
||||
// import 'package:timezone/tzdata.dart' as tz;
|
||||
|
||||
// ignore: avoid_classes_with_only_static_members
|
||||
class NotificationApi {
|
||||
// Below is the code for initializing the plugin using var _notificationPlugin
|
||||
static final _notifications = FlutterLocalNotificationsPlugin();
|
||||
static final onNotifications = BehaviorSubject<String?>();
|
||||
|
||||
static Future showNotification({
|
||||
int id = 0,
|
||||
String? title,
|
||||
String? body,
|
||||
String? payload,
|
||||
}) async =>
|
||||
_notifications.show(
|
||||
id,
|
||||
title,
|
||||
body,
|
||||
await _notificanDetails(),
|
||||
payload: payload,
|
||||
);
|
||||
|
||||
static Future showScheduleNotification() async =>
|
||||
_notifications.zonedSchedule(
|
||||
0,
|
||||
'Cek Laporan',
|
||||
"Laporan Baru Mungkin Ada, Sila Cek Di Aplikasi",
|
||||
// tz.TZDateTime.from(scheduledDate, tz.local),
|
||||
_scheduleDaily(const Time(18)),
|
||||
await _notificanDetails(),
|
||||
payload: "Laporan Baru Mungkin Ada, Sila Cek Di Aplikasi",
|
||||
androidAllowWhileIdle: true,
|
||||
uiLocalNotificationDateInterpretation:
|
||||
UILocalNotificationDateInterpretation.absoluteTime,
|
||||
matchDateTimeComponents: DateTimeComponents.time,
|
||||
);
|
||||
|
||||
static Future _notificanDetails() async {
|
||||
const AndroidNotificationDetails androidPlatformChannelSpecifics =
|
||||
AndroidNotificationDetails(
|
||||
'your channel id',
|
||||
'your channel name',
|
||||
channelDescription: 'your channel description',
|
||||
importance: Importance.max,
|
||||
// priority: Priority.high,
|
||||
// ticker: 'ticker',
|
||||
);
|
||||
return const NotificationDetails(
|
||||
android: androidPlatformChannelSpecifics,
|
||||
iOS: IOSNotificationDetails(),
|
||||
);
|
||||
}
|
||||
|
||||
static Future init(
|
||||
{bool initScheduled = false, BuildContext? context}) async {
|
||||
const android = AndroidInitializationSettings('app_icon');
|
||||
const iOS = IOSInitializationSettings();
|
||||
const settings = InitializationSettings(android: android, iOS: iOS);
|
||||
|
||||
final details = await _notifications.getNotificationAppLaunchDetails();
|
||||
if (details != null && details.didNotificationLaunchApp) {
|
||||
onNotifications.add(details.payload);
|
||||
}
|
||||
|
||||
await _notifications.initialize(
|
||||
settings,
|
||||
onSelectNotification: (payload) async {
|
||||
Navigator.push(
|
||||
context!,
|
||||
MaterialPageRoute(builder: (context) => Login()),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (initScheduled) {
|
||||
final locationName = await FlutterNativeTimezone.getLocalTimezone();
|
||||
tz.setLocalLocation(tz.getLocation(locationName));
|
||||
}
|
||||
}
|
||||
|
||||
static tz.TZDateTime _scheduleDaily(Time time) {
|
||||
final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
|
||||
final scheduledDate = tz.TZDateTime(tz.local, now.year, now.month, now.day,
|
||||
time.hour, time.minute, time.second);
|
||||
// if (scheduledDate.isBefore(now)) {
|
||||
// scheduledDate = scheduledDate.add(const Duration(days: 1));
|
||||
// }
|
||||
return scheduledDate.isBefore(now)
|
||||
? scheduledDate.add(const Duration(days: 1))
|
||||
: scheduledDate;
|
||||
}
|
||||
}
|
||||
3
boss_app2/lib/global.dart
Normal file
3
boss_app2/lib/global.dart
Normal file
@ -0,0 +1,3 @@
|
||||
int inidia = 1;
|
||||
// ignore: non_constant_identifier_names
|
||||
String http_to_server = "http://192.168.43.125/ilham/server2/";
|
||||
44
boss_app2/lib/main.dart
Normal file
44
boss_app2/lib/main.dart
Normal file
@ -0,0 +1,44 @@
|
||||
import 'package:boss_app2/controller/login_controller.dart';
|
||||
// import 'package:boss_app/controller/notification_api.dart';
|
||||
import 'package:boss_app2/page/login.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:timezone/data/latest.dart' as tz;
|
||||
|
||||
import 'controller/boss_controller.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
tz.initializeTimeZones();
|
||||
// final locationName = await FlutterNativeTimezone.getLocalTimezone();
|
||||
// tz.setLocalLocation(tz.getLocation(locationName));
|
||||
// tz.initializeTimeZones();
|
||||
// WidgetsFlutterBinding.ensureInitialized();
|
||||
// NotificationApi().initNotification();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<LoginController>(
|
||||
create: (BuildContext context) => LoginController()),
|
||||
ChangeNotifierProvider<BossController>(
|
||||
create: (BuildContext context) => BossController()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
home: Login(),
|
||||
// home: const notif,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
74
boss_app2/lib/page/before_login.dart
Normal file
74
boss_app2/lib/page/before_login.dart
Normal file
@ -0,0 +1,74 @@
|
||||
// ignore_for_file: avoid_void_async
|
||||
|
||||
// import 'package:boss_app/page/boss/index.dart';
|
||||
// import 'package:boss_app/page/login.dart';
|
||||
// import 'package:boss_app/page/superadmin/index.dart';
|
||||
import 'package:boss_app2/page/boss/index.dart';
|
||||
import 'package:boss_app2/page/login.dart';
|
||||
import 'package:boss_app2/page/superadmin/index.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class BeforeLogin extends StatefulWidget {
|
||||
const BeforeLogin({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_BeforeLoginState createState() => _BeforeLoginState();
|
||||
}
|
||||
|
||||
class _BeforeLoginState extends State<BeforeLogin> {
|
||||
//shared prefs
|
||||
late SharedPreferences sharedPreferences;
|
||||
int _loading = 0;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() async {
|
||||
super.didChangeDependencies();
|
||||
sharedPreferences = await SharedPreferences.getInstance();
|
||||
final level = sharedPreferences.getString('level');
|
||||
|
||||
if (level == null) {
|
||||
sharedPreferences.remove('level');
|
||||
sharedPreferences.remove('data');
|
||||
setState(() {
|
||||
_loading = 3;
|
||||
});
|
||||
}
|
||||
if (level == 'Superadmin') {
|
||||
setState(() {
|
||||
_loading = 1;
|
||||
});
|
||||
}
|
||||
if (level == 'Boss') {
|
||||
setState(() {
|
||||
_loading = 2;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
late Widget retVal;
|
||||
switch (_loading) {
|
||||
case 0:
|
||||
retVal = Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Loading"),
|
||||
),
|
||||
body: const Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
retVal = const SuperadminIndex();
|
||||
break;
|
||||
case 2:
|
||||
retVal = BossIndex();
|
||||
break;
|
||||
case 3:
|
||||
retVal = Login();
|
||||
break;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
717
boss_app2/lib/page/boss/homeAdmin.dart
Normal file
717
boss_app2/lib/page/boss/homeAdmin.dart
Normal file
@ -0,0 +1,717 @@
|
||||
// ignore_for_file: unused_element, non_constant_identifier_names
|
||||
import 'dart:convert';
|
||||
import 'package:boss_app2/controller/boss_controller.dart';
|
||||
import 'package:boss_app2/widgets/ourContainer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:month_picker_dialog/month_picker_dialog.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class HomeAdmin extends StatefulWidget {
|
||||
@override
|
||||
_HomeAdminState createState() => _HomeAdminState();
|
||||
}
|
||||
|
||||
class _HomeAdminState extends State<HomeAdmin> {
|
||||
int _year = DateTime.now().year.toInt();
|
||||
int _bulan = 0;
|
||||
String _hintTextBulanTahun = '-Pilih Bulan / Tahun Terlebih Dahulu';
|
||||
|
||||
//create string tanggal from today
|
||||
// ignore: prefer_final_fields
|
||||
String _tanggal =
|
||||
'${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}';
|
||||
// ignore: prefer_final_fields, prefer_interpolation_to_compose_strings
|
||||
String _headerLaporan = "Laporan Tanggal " +
|
||||
DateTime.now().year.toString() +
|
||||
'-' +
|
||||
DateTime.now().month.toString() +
|
||||
'-' +
|
||||
DateTime.now().day.toString();
|
||||
|
||||
//create list map with field waktu, status, dan ket and push 10 random data
|
||||
// List<Map<String, String>> _listLaporan = [];
|
||||
|
||||
late List<Map<String, String>> _laporan;
|
||||
// late List<Map<String, dynamic>> _laporanDetail;
|
||||
int _loadingLaporan = 0;
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _ambilLaporan(String tanggal, String bulan, String tahun, String filter,
|
||||
BuildContext context) async {
|
||||
final BossController _ambilLaporan =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
setState(() {
|
||||
_loadingLaporan = 0;
|
||||
});
|
||||
try {
|
||||
final Map _data =
|
||||
await _ambilLaporan.ambilLaporan(tanggal, bulan, tahun, filter);
|
||||
// Navigator.pop(context);
|
||||
|
||||
if (_data['status'] == 'success') {
|
||||
//loop the _data['data'] and push to _laporan by field waktu, status, dan ket
|
||||
if (_data['data'].length > 0) {
|
||||
_laporan = <Map<String, String>>[];
|
||||
for (int i = 0; i < _data['data'].length; i++) {
|
||||
_laporan.add({
|
||||
'waktu': _data['data'][i]['waktu'].toString(),
|
||||
'status': _data['data'][i]['status'],
|
||||
'ket': _data['data'][i]['ket'].toString(),
|
||||
'no_log': _data['data'][i]['no_log'].toString(),
|
||||
});
|
||||
}
|
||||
_laporan = _laporan;
|
||||
setState(() {
|
||||
_loadingLaporan = 1;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loadingLaporan = 2;
|
||||
});
|
||||
}
|
||||
} else if (_data['status'] == 'error') {
|
||||
setState(() {
|
||||
_loadingLaporan = 3;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_loadingLaporan = 3;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int _loadingBottomSheet = 0;
|
||||
// ignore: avoid_void_async
|
||||
void _ambilLaporanDetail(String no_log, BuildContext context) async {
|
||||
final BossController _ambilLaporan =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Map<String, dynamic> _result = {'data': 0};
|
||||
|
||||
setState(() {
|
||||
_loadingBottomSheet = 0;
|
||||
|
||||
_bottomSheetModal(context, _result);
|
||||
});
|
||||
|
||||
try {
|
||||
final Map _data = await _ambilLaporan.ambilLaporanDetail(no_log);
|
||||
await _ambilLaporan.laporanRead(no_log);
|
||||
Navigator.pop(context);
|
||||
if (_data['status'] == 'success') {
|
||||
setState(() {
|
||||
_loadingBottomSheet = 1;
|
||||
_bottomSheetModal(context, _data['data'][0]);
|
||||
});
|
||||
} else if (_data['status'] == 'error') {
|
||||
setState(() {
|
||||
_loadingBottomSheet = 2;
|
||||
|
||||
_bottomSheetModal(context, _result);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_loadingBottomSheet = 2;
|
||||
_bottomSheetModal(context, _result);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<dynamic> _bottomSheetModal(
|
||||
BuildContext context, Map<String, dynamic> _result) async {
|
||||
return showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
builder: (context) => SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: (_loadingBottomSheet == 0 || _loadingBottomSheet == 2)
|
||||
? 50
|
||||
: 20,
|
||||
),
|
||||
if (_loadingBottomSheet == 0)
|
||||
const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
else if (_loadingBottomSheet == 1)
|
||||
Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width -
|
||||
(MediaQuery.of(context).size.width * 0.8)) /
|
||||
2,
|
||||
),
|
||||
const Text(
|
||||
'Detail Laporan',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
_detailLaporan(_result),
|
||||
],
|
||||
)
|
||||
else if (_loadingBottomSheet == 2)
|
||||
const Text(
|
||||
'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda'),
|
||||
if (_loadingBottomSheet == 0 || _loadingBottomSheet == 2)
|
||||
const SizedBox(
|
||||
height: 50,
|
||||
)
|
||||
else if (_loadingBottomSheet == 1)
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _detailLaporan(Map<String, dynamic> _result) {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
final Map<String, dynamic> _ket = jsonDecode(_result['ket']);
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
var _detail;
|
||||
final formatter = NumberFormat('#,000');
|
||||
|
||||
if (_result['status'] == 'Penjualan Produk') {
|
||||
//create var list map
|
||||
final List<Map<String, dynamic>> _arrayPenjualan = (_ket['ket'] as List)
|
||||
.map((dynamic item) => item as Map<String, dynamic>)
|
||||
.toList();
|
||||
|
||||
final _widgetTabel = DataTable(
|
||||
columns: const [
|
||||
DataColumn(
|
||||
label: Text('Kode Barang'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Jumlah'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Harga Jual'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Total'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Stok Sebelumnya'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Stok Terkini'),
|
||||
),
|
||||
],
|
||||
rows: _arrayPenjualan
|
||||
.map((Map<String, dynamic> laporan) => DataRow(
|
||||
cells: [
|
||||
DataCell(Text(laporan['kode_barang']!)),
|
||||
DataCell(Text(laporan['jumlah']!.toString())),
|
||||
DataCell(Text("Rp. ${laporan['harga_jual']!}")),
|
||||
DataCell(Text("Rp. ${formatter.format(laporan['total'])}")),
|
||||
DataCell(
|
||||
Text(laporan['jumlah_stok_sebelumnya']!.toString())),
|
||||
DataCell(Text(laporan['jumlah_stok_sekarang']!.toString())),
|
||||
],
|
||||
))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Total Belanja : Rp. ${_ket['total_belanja']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Pembayaran : Rp. ${_ket['pembayaran']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Kembalian : Rp. ${_ket['baki']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal, child: _widgetTabel),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Edit Detail Produk') {
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
var _namanya, _harganya, _fotonya;
|
||||
if (_ket['nama_lama'] != _ket['nama_baru']) {
|
||||
_namanya = Column(
|
||||
children: [
|
||||
Text('Nama : ${_ket['nama_lama']} => ${_ket['nama_baru']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_namanya = const SizedBox();
|
||||
}
|
||||
|
||||
if (_ket['harga_lama'] != _ket['harga_baru']) {
|
||||
_harganya = Column(
|
||||
children: [
|
||||
Text(
|
||||
'Harga : Rp. ${_ket['harga_lama']} => Rp. ${_ket['harga_baru']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_harganya = const SizedBox();
|
||||
}
|
||||
|
||||
if (_ket['foto_lama'] != _ket['foto_baru']) {
|
||||
_fotonya = Text('Foto : ${_ket['foto_lama']} => ${_ket['foto_baru']}');
|
||||
} else {
|
||||
_fotonya = const SizedBox();
|
||||
}
|
||||
|
||||
_detail = Column(
|
||||
children: [
|
||||
_namanya,
|
||||
_harganya,
|
||||
_fotonya,
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penambahan Stok') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Penambahan Stok : ${_ket['penambahan_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Pembelian : Rp. ${_ket['harga_pembelian_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Sebelumnya : ${_ket['jumlah_stok_sebelumnya']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Baru : ${_ket['total_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penambahan Produk Baru') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Kode Barang : ${_ket['kode_barang']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Nama Barang : ${_ket['nama']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Jual : Rp. ${_ket['harga_jual']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Pembelian Stok : Rp. ${_ket['pembelian_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Jumlah : ${_ket['jumlah']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_detail = Container();
|
||||
}
|
||||
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Colors.grey,
|
||||
blurRadius: 10,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(
|
||||
4,
|
||||
4,
|
||||
),
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
children: [
|
||||
Text("Waktu : ${_result['waktu']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Status : ${_result['status']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
_detail,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
_ambilLaporan(_tanggal, '', '', '', context);
|
||||
}
|
||||
|
||||
// final DataTableSource _data = MyData();
|
||||
// ignore: prefer_final_fields
|
||||
int _currentSortColumn = 0;
|
||||
bool _isAscending = true;
|
||||
|
||||
// bool _buttonFilter = false;
|
||||
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final TextEditingController _filterLaporan = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return Scaffold
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
OurContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
const Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
"Form Pilih Bulan / Tahun Laporan",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
enabled: false,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
isDense: true,
|
||||
hintText: _hintTextBulanTahun,
|
||||
filled: true,
|
||||
fillColor: const Color.fromARGB(255, 247, 247, 247),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
|
||||
//create elevated button
|
||||
ElevatedButton(
|
||||
child: const Text('Klik Untuk Pilih Bulan / Tanggal'),
|
||||
onPressed: () {
|
||||
showMonthPicker(
|
||||
context: context,
|
||||
firstDate: DateTime(DateTime.now().year - 1),
|
||||
lastDate: DateTime.now(),
|
||||
initialDate: DateTime.now(),
|
||||
locale: const Locale("id"),
|
||||
).then((date) {
|
||||
// get only month and year on date
|
||||
|
||||
setState(() {
|
||||
_tanggal = '';
|
||||
_bulan = date!.month;
|
||||
_year = date.year;
|
||||
_hintTextBulanTahun =
|
||||
'Bulan ${_bulan.toString()} / Tahun ${_year.toString()}';
|
||||
_headerLaporan =
|
||||
"Laporan Bulan ${_bulan.toString()} / Tahun ${_year.toString()}";
|
||||
});
|
||||
_ambilLaporan('', _bulan.toString(), _year.toString(),
|
||||
'', context);
|
||||
// _tanggal = date.day.toString();
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
OurContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
_headerLaporan,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
//create data table with column "Waktu", "Status", "Aksi" and 10 rows
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: TextFormField(
|
||||
controller: _filterLaporan,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
isDense: true,
|
||||
hintText: 'Berdasarkan Waktu / Status',
|
||||
filled: true,
|
||||
fillColor:
|
||||
const Color.fromARGB(255, 247, 247, 247),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
if (_tanggal == '') {
|
||||
_ambilLaporan('', _bulan.toString(),
|
||||
_year.toString(), _filterLaporan.text, context);
|
||||
} else {
|
||||
_ambilLaporan(
|
||||
_tanggal, '', '', _filterLaporan.text, context);
|
||||
}
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
},
|
||||
child: const Text('Filter'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
_tampilkanLaporan()
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
// title: const Text('Yakin?'),
|
||||
content: const Text(
|
||||
'Ubah Seluruh Laporan Menjadi Sudah Dibaca?',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
actions: <Widget>[
|
||||
Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
final BossController _provider =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
await _provider.laporanReadAll();
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text("Semua Laporan Diubah Menjadi Terbaca"),
|
||||
));
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
"Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda"),
|
||||
));
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.blue,
|
||||
),
|
||||
child: const Text(
|
||||
'Ya',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const Icon(Icons.sticky_note_2_outlined),
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.miniStartFloat,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _tampilkanLaporan() {
|
||||
//create switch case
|
||||
switch (_loadingLaporan) {
|
||||
case 0:
|
||||
return Column(
|
||||
children: const [
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
],
|
||||
);
|
||||
case 1:
|
||||
// ignore: sized_box_for_whitespace
|
||||
return Container(
|
||||
height: 400,
|
||||
child: SingleChildScrollView(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: [
|
||||
DataColumn(
|
||||
label: const Text('Waktu'),
|
||||
onSort: (columnIndex, _) {
|
||||
setState(() {
|
||||
if (_isAscending == false) {
|
||||
_laporan.sort((a, b) {
|
||||
return b['waktu']!.compareTo(a['waktu']!);
|
||||
});
|
||||
_isAscending = true;
|
||||
} else {
|
||||
_isAscending = false;
|
||||
_laporan.sort((a, b) {
|
||||
return a['waktu']!.compareTo(b['waktu']!);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
DataColumn(
|
||||
label: const Text('Status'),
|
||||
onSort: (columnIndex, _) {
|
||||
setState(() {
|
||||
if (_isAscending == false) {
|
||||
_laporan.sort((a, b) {
|
||||
return b['status']!.compareTo(a['status']!);
|
||||
});
|
||||
_isAscending = true;
|
||||
} else {
|
||||
_isAscending = false;
|
||||
_laporan.sort((a, b) {
|
||||
return a['status']!.compareTo(b['status']!);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
const DataColumn(label: Text('Aksi')),
|
||||
],
|
||||
//rows = _laporan
|
||||
rows: _laporan
|
||||
.map((Map<String, dynamic> laporan) => DataRow(
|
||||
cells: [
|
||||
DataCell(Text(laporan['waktu']!)),
|
||||
DataCell(Text(laporan['status']!)),
|
||||
DataCell(
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.article),
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
_ambilLaporanDetail(
|
||||
laporan['no_log']!.toString(),
|
||||
context);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
))
|
||||
.toList(),
|
||||
sortColumnIndex: _currentSortColumn,
|
||||
sortAscending: _isAscending,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
case 2:
|
||||
return Column(
|
||||
children: const [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Align(
|
||||
child: Text('Tidak ada laporan untuk filter ini'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
case 3:
|
||||
return Column(
|
||||
children: const [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Align(
|
||||
child: Text(
|
||||
'Koneksi ke server gagal, Sila Cek Koneksi Internet Anda'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
default:
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
}
|
||||
77
boss_app2/lib/page/boss/index.dart
Normal file
77
boss_app2/lib/page/boss/index.dart
Normal file
@ -0,0 +1,77 @@
|
||||
import 'package:boss_app2/page/boss/homeAdmin.dart';
|
||||
import 'package:boss_app2/page/boss/laporanPenuh.dart';
|
||||
import 'package:boss_app2/page/boss/produk.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BossIndex extends StatefulWidget {
|
||||
@override
|
||||
_BossIndexState createState() => _BossIndexState();
|
||||
}
|
||||
|
||||
class _BossIndexState extends State<BossIndex> {
|
||||
Future<bool> _onWillPop() async {
|
||||
return (await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Yakin?'),
|
||||
content: const Text('Anda Akan Keluar Dari Aplikasi'),
|
||||
actions: <Widget>[
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('Tidak'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.red,
|
||||
),
|
||||
child: const Text('Ya'),
|
||||
),
|
||||
],
|
||||
),
|
||||
)) ??
|
||||
false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return Scaffold
|
||||
return WillPopScope(
|
||||
onWillPop: _onWillPop,
|
||||
child: DefaultTabController(
|
||||
length: 3,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
toolbarHeight: AppBar().preferredSize.height + 8,
|
||||
flexibleSpace: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: const [
|
||||
TabBar(tabs: [
|
||||
Tab(
|
||||
text: 'Home',
|
||||
icon: Icon(Icons.home),
|
||||
),
|
||||
Tab(
|
||||
text: 'Log Produk',
|
||||
icon: Icon(Icons.filter_vintage_sharp),
|
||||
),
|
||||
Tab(
|
||||
text: 'Laporan Penuh',
|
||||
icon: Icon(Icons.checklist_rtl_rounded),
|
||||
),
|
||||
])
|
||||
],
|
||||
),
|
||||
),
|
||||
body: TabBarView(
|
||||
children: [
|
||||
HomeAdmin(),
|
||||
// ProdukAdmin(),
|
||||
ProdukAdmin(),
|
||||
const LaporanPenuh(),
|
||||
],
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
667
boss_app2/lib/page/boss/laporanPenuh.dart
Normal file
667
boss_app2/lib/page/boss/laporanPenuh.dart
Normal file
@ -0,0 +1,667 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:boss_app2/widgets/ourContainer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../controller/boss_controller.dart';
|
||||
|
||||
class LaporanPenuh extends StatefulWidget {
|
||||
const LaporanPenuh({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LaporanPenuhState createState() => _LaporanPenuhState();
|
||||
}
|
||||
|
||||
class _LaporanPenuhState extends State<LaporanPenuh> {
|
||||
late List<Map<String, dynamic>> _laporanAll;
|
||||
int _loadingLaporanAll = 0;
|
||||
late int _pageNumber;
|
||||
int _pageNumberIndex = 1;
|
||||
String _cekFilter = 'tiada';
|
||||
String _filterLaporan = '';
|
||||
final _inputFilterLaporan = TextEditingController();
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _ambilLaporanAll(BuildContext context, int pageNumber, String filter,
|
||||
String cekFilter) async {
|
||||
setState(() {
|
||||
_loadingLaporanAll = 0;
|
||||
_pageNumberIndex = pageNumber;
|
||||
_cekFilter = cekFilter;
|
||||
_filterLaporan = filter;
|
||||
});
|
||||
_laporanAll = [];
|
||||
final BossController _toController =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
final Map _data =
|
||||
await _toController.ambilLaporanAll(pageNumber, filter, cekFilter);
|
||||
|
||||
if (_data['status'] == 'success') {
|
||||
//loop the _data['data'] and push to _laporan by field waktu, status, dan ket
|
||||
if (_data['data'].length > 0) {
|
||||
_laporanAll = (_data['data'] as List)
|
||||
.map((dynamic item) => item as Map<String, dynamic>)
|
||||
.toList();
|
||||
setState(() {
|
||||
_loadingLaporanAll = 1;
|
||||
_pageNumber = (_data['ceil'] / 10).ceil();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loadingLaporanAll = 2;
|
||||
});
|
||||
}
|
||||
} else if (_data['status'] == 'error') {
|
||||
setState(() {
|
||||
_loadingLaporanAll = 3;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_loadingLaporanAll = 3;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_ambilLaporanAll(context, _pageNumberIndex, _filterLaporan, _cekFilter);
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
OurContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
const Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
"Filter Laporan",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _inputFilterLaporan,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
isDense: true,
|
||||
hintText: 'Kode / Nama Produk',
|
||||
filled: true,
|
||||
fillColor: const Color.fromARGB(255, 247, 247, 247),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_inputFilterLaporan.text == '') {
|
||||
_ambilLaporanAll(
|
||||
context, 1, _filterLaporan, 'tiada');
|
||||
} else {
|
||||
_ambilLaporanAll(
|
||||
context, 1, _inputFilterLaporan.text, 'ada');
|
||||
}
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
},
|
||||
child: const Text('Filter'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
OurContainer(
|
||||
child: (_loadingLaporanAll == 0)
|
||||
? Column(
|
||||
children: const [
|
||||
SizedBox(height: 25),
|
||||
Center(child: CircularProgressIndicator())
|
||||
],
|
||||
)
|
||||
: (_loadingLaporanAll == 2)
|
||||
? Column(
|
||||
children: const [
|
||||
SizedBox(height: 25),
|
||||
Center(
|
||||
child: Text(
|
||||
'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda'),
|
||||
)
|
||||
],
|
||||
)
|
||||
: (_loadingLaporanAll == 1)
|
||||
? Column(
|
||||
children: [
|
||||
Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: 450,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: const [
|
||||
DataColumn(label: Text('No')),
|
||||
DataColumn(
|
||||
label: Text('Waktu')),
|
||||
DataColumn(
|
||||
label: Text('Status')),
|
||||
DataColumn(
|
||||
label: Text('Keterangan')),
|
||||
],
|
||||
rows: _laporanAll.map(
|
||||
(Map<String, dynamic> item) {
|
||||
return DataRow(
|
||||
cells: [
|
||||
// DataCell(Text('${_laporanAll.indexOf(item) + 1}')),
|
||||
DataCell(Text(
|
||||
'${item['no_log']}')),
|
||||
DataCell(Text(
|
||||
'${item['waktu']}')),
|
||||
DataCell(Text(
|
||||
'${item['status']}')),
|
||||
DataCell(IconButton(
|
||||
icon: const Icon(
|
||||
Icons.article),
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
_bottomSheetModal(
|
||||
context, item);
|
||||
},
|
||||
)),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
_pageButton(context),
|
||||
],
|
||||
)
|
||||
: const SizedBox()),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
// title: const Text('Yakin?'),
|
||||
content: const Text(
|
||||
'Ubah Seluruh Laporan Menjadi Sudah Dibaca?',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
actions: <Widget>[
|
||||
Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
final BossController _provider =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
await _provider.laporanReadAll();
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text("Semua Laporan Diubah Menjadi Terbaca"),
|
||||
));
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
"Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda"),
|
||||
));
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.blue,
|
||||
),
|
||||
child: const Text(
|
||||
'Ya',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const Icon(Icons.sticky_note_2_outlined),
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.miniStartFloat,
|
||||
);
|
||||
}
|
||||
|
||||
SingleChildScrollView _pageButton(BuildContext context) {
|
||||
final List<Widget> _pageButton = <Widget>[];
|
||||
|
||||
if (_loadingLaporanAll == 1) {
|
||||
if (_pageNumber >= 1 && _pageNumber <= 3) {
|
||||
for (int i = 1; i <= _pageNumber; i++) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberIndex == 1 && i == 1)
|
||||
? Colors.grey
|
||||
: (_pageNumberIndex == 2 && i == 2)
|
||||
? Colors.grey
|
||||
: (_pageNumberIndex == 3 && i == 3)
|
||||
? Colors.grey
|
||||
: Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
if (_pageNumberIndex == 1 && i == 1) {
|
||||
} else if (_pageNumberIndex == 2 && i == 2) {
|
||||
} else if (_pageNumberIndex == 3 && i == 3) {
|
||||
} else {
|
||||
setState(() {
|
||||
_pageNumberIndex = i;
|
||||
// _pageNumber = i;
|
||||
});
|
||||
_ambilLaporanAll(context, i, _filterLaporan, _cekFilter);
|
||||
}
|
||||
},
|
||||
child: Text(i.toString()),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else if (_pageNumber > 3) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLaporanAll(
|
||||
context, _pageNumberIndex - 1, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: const Text('<'),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLaporanAll(context, 1, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: const Text('1'),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
const Text('...'),
|
||||
);
|
||||
|
||||
if (_pageNumberIndex != 1 && _pageNumberIndex != _pageNumber) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: Colors.grey,
|
||||
),
|
||||
onPressed: () {},
|
||||
child: Text(_pageNumberIndex.toString()),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
const Text('...'),
|
||||
);
|
||||
}
|
||||
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary:
|
||||
(_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLaporanAll(
|
||||
context, _pageNumber, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: Text(_pageNumber.toString()),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary:
|
||||
(_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLaporanAll(
|
||||
context, _pageNumberIndex + 1, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: const Text('>'),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_pageButton.add(const SizedBox());
|
||||
}
|
||||
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: _pageButton,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _bottomSheetModal(
|
||||
BuildContext context, Map<String, dynamic> _result) async {
|
||||
final BossController _provider =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
await _provider.laporanRead(_result['no_log'].toString());
|
||||
} catch (e) {
|
||||
// print(e);
|
||||
}
|
||||
|
||||
return showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
builder: (context) => SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width -
|
||||
(MediaQuery.of(context).size.width * 0.8)) /
|
||||
2,
|
||||
),
|
||||
const Text(
|
||||
'Detail Laporan',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
_detailLaporan(_result),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _detailLaporan(Map<String, dynamic> _result) {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
final Map<String, dynamic> _ket = jsonDecode(_result['ket']);
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
var _detail;
|
||||
final formatter = NumberFormat('#,000');
|
||||
|
||||
if (_result['status'] == 'Penjualan Produk') {
|
||||
//create var list map
|
||||
final List<Map<String, dynamic>> _arrayPenjualan = (_ket['ket'] as List)
|
||||
.map((dynamic item) => item as Map<String, dynamic>)
|
||||
.toList();
|
||||
|
||||
final _widgetTabel = DataTable(
|
||||
columns: const [
|
||||
DataColumn(
|
||||
label: Text('Kode Barang'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Jumlah'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Harga Jual'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Total'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Stok Sebelumnya'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Stok Terkini'),
|
||||
),
|
||||
],
|
||||
rows: _arrayPenjualan
|
||||
.map((Map<String, dynamic> laporan) => DataRow(
|
||||
cells: [
|
||||
DataCell(Text(laporan['kode_barang']!)),
|
||||
DataCell(Text(laporan['jumlah']!.toString())),
|
||||
DataCell(Text("Rp. ${laporan['harga_jual']!}")),
|
||||
DataCell(Text("Rp. ${formatter.format(laporan['total'])}")),
|
||||
DataCell(
|
||||
Text(laporan['jumlah_stok_sebelumnya']!.toString())),
|
||||
DataCell(Text(laporan['jumlah_stok_sekarang']!.toString())),
|
||||
],
|
||||
))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Total Belanja : Rp. ${_ket['total_belanja']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Pembayaran : Rp. ${_ket['pembayaran']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Kembalian : Rp. ${_ket['baki']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal, child: _widgetTabel),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Edit Detail Produk') {
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
var _namanya, _harganya, _fotonya;
|
||||
if (_ket['nama_lama'] != _ket['nama_baru']) {
|
||||
_namanya = Column(
|
||||
children: [
|
||||
Text('Nama : ${_ket['nama_lama']} => ${_ket['nama_baru']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_namanya = const SizedBox();
|
||||
}
|
||||
|
||||
if (_ket['harga_lama'] != _ket['harga_baru']) {
|
||||
_harganya = Column(
|
||||
children: [
|
||||
Text(
|
||||
'Harga : Rp. ${_ket['harga_lama']} => Rp. ${_ket['harga_baru']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_harganya = const SizedBox();
|
||||
}
|
||||
|
||||
if (_ket['foto_lama'] != _ket['foto_baru']) {
|
||||
_fotonya = Text('Foto : ${_ket['foto_lama']} => ${_ket['foto_baru']}');
|
||||
} else {
|
||||
_fotonya = const SizedBox();
|
||||
}
|
||||
|
||||
_detail = Column(
|
||||
children: [
|
||||
_namanya,
|
||||
_harganya,
|
||||
_fotonya,
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penambahan Stok') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Penambahan Stok : ${_ket['penambahan_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Pembelian : Rp. ${_ket['harga_pembelian_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Sebelumnya : ${_ket['jumlah_stok_sebelumnya']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Baru : ${_ket['total_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penambahan Produk Baru') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Kode Barang : ${_ket['kode_barang']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Nama Barang : ${_ket['nama']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Jual : Rp. ${_ket['harga_jual']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Pembelian Stok : Rp. ${_ket['pembelian_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Jumlah : ${_ket['jumlah']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penjualan Barang Spesifik') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Jumlah Pembelian : ${_ket['jumlah_pembelian']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Jual : Rp. ${_ket['harga_jual']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Sebelumnya : ${_ket['stok_sebelumnya']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Terbaru : ${_ket['stok_sekarang']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_detail = Container();
|
||||
}
|
||||
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Colors.grey,
|
||||
blurRadius: 10,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(
|
||||
4,
|
||||
4,
|
||||
),
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
children: [
|
||||
Text("Waktu : ${_result['waktu']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text(
|
||||
"Status : ${(_result['status'] == 'Penjualan Barang Spesifik') ? 'Penjualan' : _result['status'].toString()}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
_detail,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
440
boss_app2/lib/page/boss/produk.dart
Normal file
440
boss_app2/lib/page/boss/produk.dart
Normal file
@ -0,0 +1,440 @@
|
||||
import 'package:boss_app2/controller/boss_controller.dart';
|
||||
import 'package:boss_app2/global.dart' as globals;
|
||||
import 'package:boss_app2/page/boss/produkDetail.dart';
|
||||
import 'package:boss_app2/widgets/ourContainer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ProdukAdmin extends StatefulWidget {
|
||||
// const ProdukAdmin({Key? key}) : super(key: key);
|
||||
@override
|
||||
_ProdukAdminState createState() => _ProdukAdminState();
|
||||
}
|
||||
|
||||
class _ProdukAdminState extends State<ProdukAdmin> {
|
||||
late List<Map<String, dynamic>> _produkAll;
|
||||
int _loadingProdukAll = 0;
|
||||
late int _pageNumber;
|
||||
int _pageNumberIndex = 1;
|
||||
String _cekFilter = 'tiada';
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _ambilProdukAll(BuildContext context, int pageNumber, String filter,
|
||||
String cekFilter) async {
|
||||
setState(() {
|
||||
_loadingProdukAll = 0;
|
||||
_pageNumberIndex = pageNumber;
|
||||
_cekFilter = cekFilter;
|
||||
});
|
||||
_produkAll = [];
|
||||
final BossController _toController =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
final Map _data =
|
||||
await _toController.ambilProdukAll(pageNumber, filter, cekFilter);
|
||||
|
||||
if (_data['status'] == 'success') {
|
||||
//loop the _data['data'] and push to _laporan by field waktu, status, dan ket
|
||||
if (_data['data'].length > 0) {
|
||||
_produkAll = (_data['data'] as List)
|
||||
.map((dynamic item) => item as Map<String, dynamic>)
|
||||
.toList();
|
||||
setState(() {
|
||||
_loadingProdukAll = 1;
|
||||
_pageNumber = (_data['ceil'] / 10).ceil();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_loadingProdukAll = 2;
|
||||
});
|
||||
}
|
||||
} else if (_data['status'] == 'error') {
|
||||
setState(() {
|
||||
_loadingProdukAll = 3;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_loadingProdukAll = 3;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
_ambilProdukAll(context, 1, '', _cekFilter);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
final TextEditingController _filterProduk = TextEditingController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
OurContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
const Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Text(
|
||||
"Filter Produk",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _filterProduk,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
isDense: true,
|
||||
hintText: 'Kode / Nama Produk',
|
||||
filled: true,
|
||||
fillColor: const Color.fromARGB(255, 247, 247, 247),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
if (_filterProduk.text == '') {
|
||||
_ambilProdukAll(context, 1, '', 'tiada');
|
||||
} else {
|
||||
_ambilProdukAll(
|
||||
context, 1, _filterProduk.text, 'ada');
|
||||
}
|
||||
},
|
||||
child: const Text('Cari'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (_loadingProdukAll == 0)
|
||||
const Center(child: CircularProgressIndicator())
|
||||
else if (_loadingProdukAll == 1)
|
||||
SizedBox(
|
||||
height: 400,
|
||||
child: SingleChildScrollView(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Column(
|
||||
children: [
|
||||
DataTable(
|
||||
columns: const [
|
||||
DataColumn(
|
||||
label: Text('Kode'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Nama'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Harga'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Stok'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Laporan'),
|
||||
),
|
||||
],
|
||||
rows: _produkAll
|
||||
.map((Map<String, dynamic> item) => DataRow(
|
||||
cells: [
|
||||
DataCell(
|
||||
Row(
|
||||
children: [
|
||||
Text(item['kode_barang']
|
||||
.toString()),
|
||||
const SizedBox(width: 10),
|
||||
GestureDetector(
|
||||
onTap: () => _tampilkanFoto(
|
||||
context,
|
||||
item['no_barang'],
|
||||
item['foto']),
|
||||
child: Hero(
|
||||
tag:
|
||||
"image${item['no_barang']}",
|
||||
child: CircleAvatar(
|
||||
radius: 15,
|
||||
backgroundImage:
|
||||
NetworkImage(
|
||||
"${globals.http_to_server}img/${item['no_barang']}/${item['foto']}",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
Text(item['nama'].toString()),
|
||||
),
|
||||
DataCell(
|
||||
Text("Rp. ${item['harga_jual']}"),
|
||||
),
|
||||
DataCell(
|
||||
Text(item['jumlah'].toString()),
|
||||
),
|
||||
DataCell(IconButton(
|
||||
icon: const Icon(Icons.article),
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
// _ambilLaporanProduk(
|
||||
// context,
|
||||
// int.parse(
|
||||
// item['no_barang']),
|
||||
// 1,
|
||||
// item);
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
ProdukDetail(
|
||||
no_log: int.parse(
|
||||
item['no_barang']),
|
||||
),
|
||||
));
|
||||
},
|
||||
)),
|
||||
],
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
_pageButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
else if (_loadingProdukAll == 2)
|
||||
const Text(
|
||||
'Tidak ada data',
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
else if (_loadingProdukAll == 3)
|
||||
const Text(
|
||||
'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda',
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
// title: const Text('Yakin?'),
|
||||
content: const Text(
|
||||
'Ubah Seluruh Laporan Menjadi Sudah Dibaca?',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
actions: <Widget>[
|
||||
Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
final BossController _provider =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
await _provider.laporanReadAll();
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text("Semua Laporan Diubah Menjadi Terbaca"),
|
||||
));
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text(
|
||||
"Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda"),
|
||||
));
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.blue,
|
||||
),
|
||||
child: const Text(
|
||||
'Ya',
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const Icon(Icons.sticky_note_2_outlined),
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.miniStartFloat,
|
||||
);
|
||||
}
|
||||
|
||||
Future<dynamic> _tampilkanFoto(
|
||||
BuildContext context, String item, String foto) {
|
||||
return showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
builder: (context) => SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'image$item',
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Image.network(
|
||||
"${globals.http_to_server}img/$item/$foto",
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row _pageButton() {
|
||||
final List<Widget> _pageButton = <Widget>[];
|
||||
|
||||
if (_loadingProdukAll == 1) {
|
||||
if (_pageNumber >= 1 && _pageNumber <= 3) {
|
||||
for (int i = 1; i <= _pageNumber; i++) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberIndex == 1 && i == 1)
|
||||
? Colors.grey
|
||||
: (_pageNumberIndex == 2 && i == 2)
|
||||
? Colors.grey
|
||||
: (_pageNumberIndex == 3 && i == 3)
|
||||
? Colors.grey
|
||||
: Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
if (_pageNumberIndex == 1 && i == 1) {
|
||||
// ignore: unnecessary_statements
|
||||
null;
|
||||
} else if (_pageNumberIndex == 2 && i == 2) {
|
||||
// ignore: unnecessary_statements
|
||||
null;
|
||||
} else if (_pageNumberIndex == 3 && i == 3) {
|
||||
// ignore: unnecessary_statements
|
||||
null;
|
||||
} else {
|
||||
setState(() {
|
||||
_pageNumberIndex = i;
|
||||
// _pageNumber = i;
|
||||
});
|
||||
_ambilProdukAll(context, i, '', _cekFilter);
|
||||
}
|
||||
},
|
||||
child: Text(i.toString()),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else if (_pageNumber > 3) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilProdukAll(context, _pageNumberIndex - 1, '', _cekFilter);
|
||||
},
|
||||
child: const Text('<'),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberIndex != 1) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilProdukAll(context, 1, '', _cekFilter);
|
||||
},
|
||||
child: const Text('1'),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
const Text('...'),
|
||||
);
|
||||
|
||||
if (_pageNumberIndex != 1 && _pageNumberIndex != _pageNumber) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: Colors.grey,
|
||||
),
|
||||
onPressed: () {},
|
||||
child: Text(_pageNumberIndex.toString()),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
const Text('...'),
|
||||
);
|
||||
}
|
||||
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary:
|
||||
(_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilProdukAll(context, _pageNumber, '', _cekFilter);
|
||||
},
|
||||
child: Text(_pageNumber.toString()),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary:
|
||||
(_pageNumberIndex != _pageNumber) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilProdukAll(context, _pageNumberIndex + 1, '', _cekFilter);
|
||||
},
|
||||
child: const Text('>'),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_pageButton.add(const SizedBox());
|
||||
}
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: _pageButton,
|
||||
);
|
||||
}
|
||||
}
|
||||
610
boss_app2/lib/page/boss/produkDetail.dart
Normal file
610
boss_app2/lib/page/boss/produkDetail.dart
Normal file
@ -0,0 +1,610 @@
|
||||
// ignore_for_file: unnecessary_statements
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:boss_app2/widgets/ourContainer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../controller/boss_controller.dart';
|
||||
|
||||
class ProdukDetail extends StatefulWidget {
|
||||
// ignore: non_constant_identifier_names
|
||||
final int no_log;
|
||||
// ignore: non_constant_identifier_names
|
||||
const ProdukDetail({Key? key, required this.no_log}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ProdukDetailState createState() => _ProdukDetailState();
|
||||
}
|
||||
|
||||
class _ProdukDetailState extends State<ProdukDetail> {
|
||||
late Map<String, dynamic> _dataProduk;
|
||||
int _loadingProduk = 0;
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _ambilProdukDetail(BuildContext context, int noBarang) async {
|
||||
setState(() {
|
||||
_loadingProduk = 0;
|
||||
});
|
||||
final BossController _toController =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
final Map _data = await _toController.ambilProdukDetail(noBarang);
|
||||
setState(() {
|
||||
_dataProduk = _data['data'];
|
||||
_loadingProduk = 1;
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_loadingProduk = 2;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
late List<Map<String, dynamic>> _laporanProduk;
|
||||
int _loadingLaporan = 0;
|
||||
late int _pageNumberLaporan;
|
||||
int _pageNumberLaporanIndex = 1;
|
||||
String _filterLaporan = "";
|
||||
String _cekFilter = "tiada";
|
||||
bool _cekLengthData = false;
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _ambilLogLaporan(BuildContext context, int noBarang, int pageNumber,
|
||||
String filter, String cekFilter) async {
|
||||
setState(() {
|
||||
_loadingLaporan = 0;
|
||||
_pageNumberLaporanIndex = pageNumber;
|
||||
_cekFilter = cekFilter;
|
||||
_filterLaporan = filter;
|
||||
});
|
||||
_laporanProduk = [];
|
||||
final BossController _toController =
|
||||
Provider.of<BossController>(context, listen: false);
|
||||
|
||||
try {
|
||||
final Map _data = await _toController.ambilLaporanProdukDetail(
|
||||
noBarang, pageNumber, filter, cekFilter);
|
||||
_laporanProduk = (_data['data'] as List)
|
||||
.map((dynamic item) => item as Map<String, dynamic>)
|
||||
.toList();
|
||||
setState(() {
|
||||
if (_laporanProduk.isEmpty) {
|
||||
_cekLengthData = false;
|
||||
} else {
|
||||
_cekLengthData = true;
|
||||
}
|
||||
_laporanProduk = _laporanProduk;
|
||||
_loadingLaporan = 1;
|
||||
_pageNumberLaporan = (_data['ceil'] / 10).ceil();
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_loadingLaporan = 2;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
final TextEditingController _inputFilterLaporan = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_ambilLogLaporan(context, widget.no_log, 1, _filterLaporan, _cekFilter);
|
||||
_ambilProdukDetail(context, widget.no_log);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Detail Produk'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
OurContainer(
|
||||
child: (_loadingProduk == 1)
|
||||
? Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Kode : ${_dataProduk['kode_barang']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text('Nama : ${_dataProduk['nama']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text('Harga Jual : ${_dataProduk['harga_jual']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text('Stok : ${_dataProduk['jumlah']}'),
|
||||
],
|
||||
),
|
||||
)
|
||||
: (_loadingProduk == 0)
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: (_loadingProduk == 2)
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Koneksi Ke Server Bermasalah, Sila Periksa Jaringan Anda'))
|
||||
: Container(),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
OurContainer(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
if (_loadingLaporan == 1)
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Flexible(
|
||||
child: TextFormField(
|
||||
controller: _inputFilterLaporan,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
isDense: true,
|
||||
hintText: 'Berdasarkan Waktu / Status',
|
||||
filled: true,
|
||||
fillColor: const Color.fromARGB(
|
||||
255, 247, 247, 247),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
if (_inputFilterLaporan.text == '') {
|
||||
_ambilLogLaporan(context, widget.no_log, 1,
|
||||
_inputFilterLaporan.text, 'tiada');
|
||||
} else {
|
||||
_ambilLogLaporan(context, widget.no_log, 1,
|
||||
_inputFilterLaporan.text, 'ada');
|
||||
}
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
// }
|
||||
},
|
||||
child: const Text('Filter'),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_cekLengthData)
|
||||
SingleChildScrollView(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: const [
|
||||
DataColumn(
|
||||
label: Text('No'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Waktu'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Status'),
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Keterangan'),
|
||||
),
|
||||
],
|
||||
rows: _laporanProduk
|
||||
.map(
|
||||
(dynamic item) => DataRow(
|
||||
cells: [
|
||||
DataCell(
|
||||
Text(
|
||||
item['no_log'].toString(),
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
Text(
|
||||
item['waktu'].toString(),
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
(item['status'] !=
|
||||
"Penjualan Barang Spesifik")
|
||||
? Text(
|
||||
item['status'].toString(),
|
||||
)
|
||||
: const Text("Penjualan"),
|
||||
),
|
||||
DataCell(IconButton(
|
||||
icon: const Icon(Icons.article),
|
||||
color: Colors.blue,
|
||||
onPressed: () {
|
||||
_bottomSheetModal(
|
||||
context, item);
|
||||
},
|
||||
)),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: Text(
|
||||
'Tidak Ada Rekod Laporan Untuk Filter "${_inputFilterLaporan.text}"',
|
||||
textAlign: TextAlign.center,
|
||||
)),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
else
|
||||
(_loadingLaporan == 0)
|
||||
? const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: (_loadingLaporan == 2)
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Koneksi Ke Serverl Bermasalah, Sila Periksa Jaringan Anda',
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
_pageButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: avoid_void_async
|
||||
void _bottomSheetModal(
|
||||
BuildContext context, Map<String, dynamic> _result) async {
|
||||
return showModalBottomSheet(
|
||||
isScrollControlled: true,
|
||||
context: context,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
builder: (context) => SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: (MediaQuery.of(context).size.width -
|
||||
(MediaQuery.of(context).size.width * 0.8)) /
|
||||
2,
|
||||
),
|
||||
const Text(
|
||||
'Detail Laporan',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
_detailLaporan(_result),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _detailLaporan(Map<String, dynamic> _result) {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
final Map<String, dynamic> _ket = jsonDecode(_result['ket']);
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
var _detail;
|
||||
|
||||
if (_result['status'] == 'Edit Detail Produk') {
|
||||
// ignore: prefer_typing_uninitialized_variables
|
||||
var _namanya, _harganya, _fotonya;
|
||||
if (_ket['nama_lama'] != _ket['nama_baru']) {
|
||||
_namanya = Column(
|
||||
children: [
|
||||
Text('Nama : ${_ket['nama_lama']} => ${_ket['nama_baru']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_namanya = const SizedBox();
|
||||
}
|
||||
|
||||
if (_ket['harga_lama'] != _ket['harga_baru']) {
|
||||
_harganya = Column(
|
||||
children: [
|
||||
Text(
|
||||
'Harga : Rp. ${_ket['harga_lama']} => Rp. ${_ket['harga_baru']}'),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_harganya = const SizedBox();
|
||||
}
|
||||
|
||||
if (_ket['foto_lama'] != _ket['foto_baru']) {
|
||||
_fotonya = Text('Foto : ${_ket['foto_lama']} => ${_ket['foto_baru']}');
|
||||
} else {
|
||||
_fotonya = const SizedBox();
|
||||
}
|
||||
|
||||
_detail = Column(
|
||||
children: [
|
||||
_namanya,
|
||||
_harganya,
|
||||
_fotonya,
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penambahan Stok') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Penambahan Stok : ${_ket['penambahan_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Pembelian : Rp. ${_ket['harga_pembelian_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Sebelumnya : ${_ket['jumlah_stok_sebelumnya']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Baru : ${_ket['total_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penambahan Produk Baru') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Kode Barang : ${_ket['kode_barang']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Nama Barang : ${_ket['nama']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Jual : Rp. ${_ket['harga_jual']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Pembelian Stok : Rp. ${_ket['pembelian_stok']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Jumlah : ${_ket['jumlah']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (_result['status'] == 'Penjualan Barang Spesifik') {
|
||||
_detail = Column(
|
||||
children: [
|
||||
Text("Jumlah Pembelian : ${_ket['jumlah_pembelian']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Harga Jual : Rp. ${_ket['harga_jual']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Sebelumnya : ${_ket['stok_sebelumnya']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text("Stok Terbaru : ${_ket['stok_sekarang']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
_detail = Container();
|
||||
}
|
||||
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width * 0.85,
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Colors.grey,
|
||||
blurRadius: 10,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(
|
||||
4,
|
||||
4,
|
||||
),
|
||||
),
|
||||
]),
|
||||
child: Column(
|
||||
children: [
|
||||
Text("Waktu : ${_result['waktu']}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
Text(
|
||||
"Status : ${(_result['status'] == 'Penjualan Barang Spesifik') ? 'Penjualan' : _result['status'].toString()}"),
|
||||
const Divider(
|
||||
color: Colors.black,
|
||||
),
|
||||
_detail,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
SingleChildScrollView _pageButton() {
|
||||
final List<Widget> _pageButton = <Widget>[];
|
||||
|
||||
if (_loadingLaporan == 1) {
|
||||
if (_pageNumberLaporan >= 1 && _pageNumberLaporan <= 3) {
|
||||
for (int i = 1; i <= _pageNumberLaporan; i++) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberLaporanIndex == 1 && i == 1)
|
||||
? Colors.grey
|
||||
: (_pageNumberLaporanIndex == 2 && i == 2)
|
||||
? Colors.grey
|
||||
: (_pageNumberLaporanIndex == 3 && i == 3)
|
||||
? Colors.grey
|
||||
: Colors.blue,
|
||||
),
|
||||
onPressed: () {
|
||||
if (_pageNumberLaporanIndex == 1 && i == 1) {
|
||||
} else if (_pageNumberLaporanIndex == 2 && i == 2) {
|
||||
} else if (_pageNumberLaporanIndex == 3 && i == 3) {
|
||||
} else {
|
||||
setState(() {
|
||||
_pageNumberLaporanIndex = i;
|
||||
// _pageNumberLaporan = i;
|
||||
});
|
||||
_ambilLogLaporan(
|
||||
context, widget.no_log, i, _filterLaporan, _cekFilter);
|
||||
}
|
||||
},
|
||||
child: Text(i.toString()),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else if (_pageNumberLaporan > 3) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary:
|
||||
(_pageNumberLaporanIndex != 1) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLogLaporan(context, widget.no_log,
|
||||
_pageNumberLaporanIndex - 1, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: const Text('<'),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary:
|
||||
(_pageNumberLaporanIndex != 1) ? Colors.blue : Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLogLaporan(
|
||||
context, widget.no_log, 1, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: const Text('1'),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
const Text('...'),
|
||||
);
|
||||
|
||||
if (_pageNumberLaporanIndex != 1 &&
|
||||
_pageNumberLaporanIndex != _pageNumberLaporan) {
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
null;
|
||||
},
|
||||
child: Text(_pageNumberLaporanIndex.toString()),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
const Text('...'),
|
||||
);
|
||||
}
|
||||
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberLaporanIndex != _pageNumberLaporan)
|
||||
? Colors.blue
|
||||
: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLogLaporan(context, widget.no_log, _pageNumberLaporan,
|
||||
_filterLaporan, _cekFilter);
|
||||
},
|
||||
child: Text(_pageNumberLaporan.toString()),
|
||||
),
|
||||
);
|
||||
_pageButton.add(
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
primary: (_pageNumberLaporanIndex != _pageNumberLaporan)
|
||||
? Colors.blue
|
||||
: Colors.grey,
|
||||
),
|
||||
onPressed: () {
|
||||
_ambilLogLaporan(context, widget.no_log,
|
||||
_pageNumberLaporanIndex + 1, _filterLaporan, _cekFilter);
|
||||
},
|
||||
child: const Text('>'),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_pageButton.add(const SizedBox());
|
||||
}
|
||||
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: _pageButton,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
343
boss_app2/lib/page/login.dart
Normal file
343
boss_app2/lib/page/login.dart
Normal file
@ -0,0 +1,343 @@
|
||||
// ignore_for_file: sized_box_for_whitespace, prefer_const_constructors
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:boss_app2/controller/login_controller.dart';
|
||||
import 'package:boss_app2/controller/notification_api.dart';
|
||||
import 'package:boss_app2/page/before_login.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class Login extends StatefulWidget {
|
||||
// ignore: avoid_unused_constructor_parameters, prefer_const_constructors_in_immutables
|
||||
Login({Key? key, String? payload}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LoginState createState() => _LoginState();
|
||||
}
|
||||
|
||||
class _LoginState extends State<Login> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
//create shared prefs
|
||||
late SharedPreferences sharedPreferences;
|
||||
//create 2 final variables , one for the username and one for the password = TextEditingController
|
||||
final TextEditingController _usernameController = TextEditingController();
|
||||
final TextEditingController _passwordController = TextEditingController();
|
||||
|
||||
bool _isLoading = false;
|
||||
late FocusNode myFocusNode;
|
||||
|
||||
//create void _login with 3 parameters, username, password and context
|
||||
// ignore: avoid_void_async
|
||||
void _login(String username, String password, BuildContext context) async {
|
||||
// create final LoginController loginController = provider.of<LoginController>(context, listen: false);
|
||||
final LoginController _login =
|
||||
Provider.of<LoginController>(context, listen: false);
|
||||
|
||||
//create try catch
|
||||
try {
|
||||
// final Map _returnString = await _login.login(username, password);
|
||||
final String _returnString = await _login.login(username, password);
|
||||
|
||||
//create switch case
|
||||
switch (_returnString) {
|
||||
case "1":
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
Future.delayed(const Duration(milliseconds: 2500), () {
|
||||
// Navigator.of(context).pop(true);
|
||||
// Navigator.pushAndRemoveUntil(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ScanQRCode(),
|
||||
// ),
|
||||
// (route) => false);
|
||||
});
|
||||
return const AlertDialog(
|
||||
title: Text(
|
||||
"Sukses",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
content: Text(
|
||||
"Selamat Login Kembali",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
// Navigator.of(context).pop(true);
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => BeforeLogin(),
|
||||
),
|
||||
(route) => false);
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case "2":
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: const Text("Username Dan Password Salah"),
|
||||
));
|
||||
//focus node
|
||||
myFocusNode.requestFocus();
|
||||
break;
|
||||
|
||||
case "3":
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: const Text(
|
||||
"Error Koneksi Ke Server, Sila Periksa Jaringan Anda"),
|
||||
));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content:
|
||||
const Text("Error Koneksi Ke Server, Sila Periksa Jaringan Anda"),
|
||||
));
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: avoid_void_async, unused_element
|
||||
// void _notification() async {
|
||||
// final LoginController _login =
|
||||
// Provider.of<LoginController>(context, listen: false);
|
||||
|
||||
// //create try catch
|
||||
// try {
|
||||
// // final Map _returnString = await _login.login(username, password);
|
||||
// final List _returnString = await _login.getNotif();
|
||||
// List ini = [1, 2, 3, 4, 5];
|
||||
// bool cek = false;
|
||||
// int jumlah = _returnString.length;
|
||||
// List notif = [];
|
||||
// for (var i = 0; i < _returnString.length; i++) {
|
||||
// cek = false;
|
||||
// for (var j = 0; j < ini.length; j++) {
|
||||
// if (ini[j].toString() == _returnString[i]['no_log'].toString()) {
|
||||
// cek = true;
|
||||
// jumlah = jumlah - 1;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (cek == false) {
|
||||
// notif.add(int.parse(_returnString[i]['no_log']));
|
||||
// }
|
||||
// // cek = false;
|
||||
// }
|
||||
// } catch (e) {
|
||||
// }
|
||||
// // NotificationApi.showNotification(
|
||||
// // title: 'Notification Title',
|
||||
// // body: 'Notification Body',
|
||||
// // payload: 'Notification Payload',
|
||||
// // );
|
||||
// }
|
||||
|
||||
Stream<int> _getnotif(BuildContext context) async* {
|
||||
// List<int> _list = [];
|
||||
final LoginController _login =
|
||||
Provider.of<LoginController>(context, listen: false);
|
||||
|
||||
while (true) {
|
||||
final int _data = await _login.getNotif();
|
||||
await Future.delayed(Duration(seconds: 60));
|
||||
yield _data;
|
||||
}
|
||||
}
|
||||
|
||||
// late Timer timer;
|
||||
|
||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
myFocusNode = FocusNode();
|
||||
|
||||
// var initializationSettingsAndroid =
|
||||
// AndroidInitializationSettings('flutter_devs');
|
||||
// var initializationSettingsIOs = IOSInitializationSettings();
|
||||
// var initSetttings = InitializationSettings(
|
||||
// android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
|
||||
// flutterLocalNotificationsPlugin.initialize(initSetttings,
|
||||
// onSelectNotification: onSelectNotification);
|
||||
NotificationApi.init(initScheduled: true, context: context);
|
||||
|
||||
// listenNotifications();
|
||||
NotificationApi.showScheduleNotification();
|
||||
// _notification();
|
||||
// timer = Timer.periodic(Duration(seconds: 10), (Timer t) => _notification());
|
||||
_getnotif(context).listen((data) async {
|
||||
if (data > 0) {
|
||||
NotificationApi.showNotification(
|
||||
title: 'Laporan Baru',
|
||||
body: 'Ada $data laporan baru',
|
||||
payload: 'Laporan Baru',
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// timer.cancel();
|
||||
super.dispose();
|
||||
myFocusNode.dispose();
|
||||
}
|
||||
|
||||
// @override
|
||||
// // ignore: avoid_void_async
|
||||
// void didChangeDependencies() async {
|
||||
// super.didChangeDependencies();
|
||||
// sharedPreferences = await SharedPreferences.getInstance();
|
||||
// sharedPreferences.remove('notif');
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
//create appbar
|
||||
appBar: AppBar(
|
||||
title: const Text('Halaman Login'),
|
||||
),
|
||||
//create body
|
||||
body: Center(
|
||||
child: SingleChildScrollView(
|
||||
reverse: true,
|
||||
child: _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Form(
|
||||
key: _formKey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
// ignore: avoid_redundant_argument_values
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
// StreamBuilder(),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.8,
|
||||
child: TextFormField(
|
||||
focusNode: myFocusNode,
|
||||
controller: _usernameController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
hintText: "Masukkan Username",
|
||||
labelText: 'Username',
|
||||
),
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Masukkan Username';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.8,
|
||||
child: TextFormField(
|
||||
controller: _passwordController,
|
||||
keyboardType: TextInputType.text,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
hintText: "Masukkan Password",
|
||||
labelText: 'Password',
|
||||
),
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Masukkan Pasword';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width * 0.8,
|
||||
height: 50,
|
||||
child: ElevatedButton(
|
||||
child: const Text('Login'),
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
_login(_usernameController.text,
|
||||
_passwordController.text, context);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// NotificationApi.showNotification(
|
||||
// title: 'Notification Title',
|
||||
// body: 'Notification Body',
|
||||
// payload: 'Notification Payload',
|
||||
// );
|
||||
// // _notification();
|
||||
// // sharedPreferences.re
|
||||
// },
|
||||
// child: Text('sini'),
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// // _notification();
|
||||
// NotificationApi.showScheduleNotification();
|
||||
// },
|
||||
// child: Text('sini 2'),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// void listenNotifications() =>
|
||||
// NotificationApi.onNotifications.stream.listen(onClickedNotification);
|
||||
|
||||
// void onClickedNotification(String? payload) {
|
||||
// Navigator.of(context).push(
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => Login(payload: payload),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// Future onSelectNotification(String payload) {
|
||||
// Navigator.of(context).push(MaterialPageRoute(builder: (_) {
|
||||
// return NewScreen(Login);
|
||||
// }));
|
||||
|
||||
// throw
|
||||
// }
|
||||
}
|
||||
23
boss_app2/lib/page/superadmin/index.dart
Normal file
23
boss_app2/lib/page/superadmin/index.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SuperadminIndex extends StatefulWidget {
|
||||
const SuperadminIndex({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SuperadminIndexState createState() => _SuperadminIndexState();
|
||||
}
|
||||
|
||||
class _SuperadminIndexState extends State<SuperadminIndex> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return Scaffold
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Superadmin'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('Superadmin'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
33
boss_app2/lib/widgets/ourContainer.dart
Normal file
33
boss_app2/lib/widgets/ourContainer.dart
Normal file
@ -0,0 +1,33 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class OurContainer extends StatelessWidget {
|
||||
final Widget? child;
|
||||
|
||||
const OurContainer({Key? key, this.child}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double left = (MediaQuery.of(context).size.width -
|
||||
(MediaQuery.of(context).size.width * 0.9)) /
|
||||
2;
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width * 0.9,
|
||||
margin: EdgeInsets.only(left: left),
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20, top: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Colors.grey,
|
||||
blurRadius: 10,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(
|
||||
4,
|
||||
4,
|
||||
),
|
||||
),
|
||||
]),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user