First Commit
This commit is contained in:
commit
6c69efd3ea
|
|
@ -0,0 +1,28 @@
|
|||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at https://dart.dev/lints.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file('local.properties')
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = '1.0'
|
||||
}
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
android {
|
||||
namespace "com.example.mobile_portal_23"
|
||||
compileSdkVersion flutter.compileSdkVersion
|
||||
ndkVersion flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.example.mobile_portal_23"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
multiDexEnabled = true
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
flutter {
|
||||
source '../..'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<application
|
||||
android:label="MobilePortal"
|
||||
android:name="${applicationName}"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.9.10'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.buildDir = '../build'
|
||||
subprojects {
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx4G
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
pluginManagement {
|
||||
def flutterSdkPath = {
|
||||
def properties = new Properties()
|
||||
file("local.properties").withInputStream { properties.load(it) }
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
return flutterSdkPath
|
||||
}
|
||||
settings.ext.flutterSdkPath = flutterSdkPath()
|
||||
|
||||
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "7.3.0" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
|
|
@ -0,0 +1,14 @@
|
|||
## For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
#
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx1024m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
#
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
#Thu Nov 23 15:42:22 CET 2023
|
||||
org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M"
|
||||
|
|
@ -0,0 +1,468 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:dropdown_search/dropdown_search.dart';
|
||||
//import 'package:flutter/rendering.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../models/employee_model.dart';
|
||||
//import '../http_service.dart';
|
||||
//import '../post_model.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:expandable/expandable.dart';
|
||||
//import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
String appDomain = "iotechnic.eu";
|
||||
//String appDomain = "192.168.0.144";
|
||||
GlobalKey _key = GlobalKey();
|
||||
List<Widget> appbarAct = [
|
||||
const IconButton(
|
||||
icon: Icon(Icons.save),
|
||||
tooltip: 'Open shopping cart',
|
||||
onPressed: null,
|
||||
)
|
||||
];
|
||||
|
||||
class DailyReportApp extends StatelessWidget {
|
||||
final State<StatefulWidget>? homeBodyState = _key.currentState;
|
||||
|
||||
DailyReportApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DailyReport(key: key);
|
||||
/*Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Napi Jelentés'),
|
||||
elevation: 10.0,
|
||||
leading: Icon(Icons.arrow_back_ios_new),
|
||||
actions: appbarAct),
|
||||
body: DailyReport(key: _key),
|
||||
backgroundColor: Colors.grey[300],
|
||||
);*/
|
||||
}
|
||||
}
|
||||
|
||||
class DailyReport extends StatefulWidget {
|
||||
const DailyReport({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DailyReportState createState() => _DailyReportState();
|
||||
}
|
||||
|
||||
class EmpList {
|
||||
String? id;
|
||||
String? name;
|
||||
bool? value;
|
||||
}
|
||||
|
||||
class _DailyReportState extends State<DailyReport> {
|
||||
//final HttpService httpService = HttpService();
|
||||
String dropdownValue = 'One';
|
||||
DateTime selectedDate = DateTime.now();
|
||||
bool datePickerEnabled = false;
|
||||
bool textMessageEnabled = false;
|
||||
bool isSwitched = false;
|
||||
TextEditingController dateinput = TextEditingController();
|
||||
List<Widget> switches = [];
|
||||
List<EmpList> emplist = [];
|
||||
//Future<List<EmployeeLs>> futureEmployee;
|
||||
List<EmployeeLs> employeeList = [];
|
||||
List<WorkLs> workList = [];
|
||||
bool _isData = false;
|
||||
String textMessage = "";
|
||||
// String selectedWork = "";
|
||||
bool saveEnabled = false;
|
||||
bool _textMessageOK = false;
|
||||
WorkLs? selectedWork; // "XST8X8F-6Q9M1FG-PE9948X-SFPHVX9"
|
||||
String? userApiKey; // = "XST8X8F-6Q9M1FG-PE9948X-SPFHVX9";
|
||||
final bool _expanded = false;
|
||||
final bool _appBarSaveEnabled = false;
|
||||
var currentFocus;
|
||||
/*Future<Null> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
userApiKey = prefs.getString("apiKey");
|
||||
}*/
|
||||
|
||||
unfocus() {
|
||||
currentFocus = FocusScope.of(context);
|
||||
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
}
|
||||
}
|
||||
|
||||
/*_loadApiKey() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString('apiKey');
|
||||
}*/
|
||||
|
||||
Future fetchdata() async {
|
||||
print("http://$appDomain/apiGetDailyReport/${employeePageArguments.apiKey!}");
|
||||
var res = await http.get(
|
||||
|
||||
// "http://iotechnic.eu/apiemployeelist/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
|
||||
Uri.parse("http://$appDomain/apiGetDailyReport/${employeePageArguments.apiKey!}")); //userApiKey!));
|
||||
|
||||
//"http://192.168.0.144/apiGetDailyReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
_print(String p) {
|
||||
print(p);
|
||||
}
|
||||
|
||||
_enableSave() {
|
||||
setState(() {
|
||||
appbarAct = [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.save),
|
||||
tooltip: 'Open shopping cart',
|
||||
onPressed: saveEnabled ? _print("Save Click") : null),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
_saveForm() {
|
||||
EasyLoading.show(status: 'Mentés...');
|
||||
// _onLoading2();
|
||||
debugPrint(DateFormat('yyyy-MM-dd').format(selectedDate));
|
||||
debugPrint("Title: ${selectedWork!.title}");
|
||||
debugPrint("WorkId: ${selectedWork!.id}");
|
||||
debugPrint("Message: $textMessage");
|
||||
List<String> emp = [];
|
||||
//print("Jelenlévők: ");
|
||||
for (var hobby in employeeList) {
|
||||
if (hobby.value == true) {
|
||||
//print(hobby.name);
|
||||
emp.add(hobby.id);
|
||||
}
|
||||
}
|
||||
var report = {
|
||||
'userApiKey': userApiKey,
|
||||
'workId': selectedWork?.id,
|
||||
'date': DateFormat('yyyy.MM.dd').format(selectedDate),
|
||||
'msg': textMessage,
|
||||
'employeeList': emp
|
||||
};
|
||||
//print(json.encode(report));
|
||||
postDailyReport(report).then((value) {
|
||||
if (value.contains("OK")) {
|
||||
EasyLoading.showSuccess('Sikeres Mentés');
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
// Navigator.pop(context); //pop dialog
|
||||
EasyLoading.dismiss();
|
||||
|
||||
Navigator.of(context).pop();
|
||||
//_login();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> postDailyReport(var json) async {
|
||||
final response = await http.post(
|
||||
Uri.parse("http://$appDomain/apiPostDailyReport/${employeePageArguments.apiKey!}"),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: jsonEncode(json),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// If the server did return a 201 CREATED response,
|
||||
// then parse the JSON.
|
||||
return response.body;
|
||||
} else {
|
||||
// If the server did not return a 201 CREATED response,
|
||||
// then throw an exception.
|
||||
throw Exception('Failed to create album.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
// empArgs = (ModalRoute.of(context)?.settings.arguments ??
|
||||
// <String, dynamic>{}) as EmployeeArguments;
|
||||
// getSharedPrefs().then((value) {
|
||||
});
|
||||
print("KEY: ${employeePageArguments.apiKey}");
|
||||
fetchdata().then((data) {
|
||||
for (var item in data["employeeList"]) {
|
||||
//debugPrint(item["_id"]);
|
||||
employeeList.add(EmployeeLs(
|
||||
id: item["_id"], name: item["name"], value: false));
|
||||
}
|
||||
for (var item in data["workList"]) {
|
||||
debugPrint(item["_id"]);
|
||||
workList.add(WorkLs(
|
||||
id: item["_id"],
|
||||
title: item["title"],
|
||||
body: item["body"],
|
||||
state: item["state"] ??"",
|
||||
//value: false
|
||||
));
|
||||
}
|
||||
_isData = true;
|
||||
setState(() {
|
||||
debugPrint('Fetch ok.');
|
||||
});
|
||||
//employeeList = data;
|
||||
});
|
||||
|
||||
//userApiKey = _loadApiKey();
|
||||
_enableSave();
|
||||
//_isData = false;
|
||||
dateinput.text = ""; //set the initial value of text field
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Clean up the controller when the widget is removed from the
|
||||
// widget tree.
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Column myUi() {
|
||||
saveEnabled = false;
|
||||
_enableSave();
|
||||
//debugPrint("UI Update." + _isData.toString());
|
||||
return Column(
|
||||
children: employeeList.map((hobby) {
|
||||
if (hobby.value == true) {
|
||||
saveEnabled = true;
|
||||
_enableSave();
|
||||
// debugPrint(hobby.name);
|
||||
}
|
||||
|
||||
return SwitchListTile(
|
||||
//controlAffinity: ListTileControlAffinity.trailing,
|
||||
activeColor: Colors.green,
|
||||
value: hobby.value,
|
||||
title: Text(hobby.name),
|
||||
onChanged: _textMessageOK == false
|
||||
? null
|
||||
: (newValue) {
|
||||
setState(() {
|
||||
hobby.value = newValue;
|
||||
});
|
||||
});
|
||||
}).toList());
|
||||
}
|
||||
|
||||
DropdownSearch workUi() {
|
||||
return DropdownSearch<WorkLs>(
|
||||
|
||||
//mode: Mode.MENU,
|
||||
//showSelectedItem: true,
|
||||
items: workList,
|
||||
/*.map((e) {
|
||||
return DropdownMenuItem<WorkLs>(child: Text(e.title), value: e);
|
||||
}).toList(),*/
|
||||
//showSearchBox: true,
|
||||
//;["Brazil", "Italia (Disabled)", "Tunisia", 'Canada'],
|
||||
//label: "Munka kiválasztása",
|
||||
// hint: "country in menu mode",
|
||||
//popupItemDisabled: (String s) => s.startsWith('I'),
|
||||
onChanged: (data) {
|
||||
//_dateSelected();
|
||||
selectedWork = data;
|
||||
|
||||
//_selectDate(context);
|
||||
setState(() {
|
||||
datePickerEnabled = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => GestureDetector(
|
||||
onTap: () {
|
||||
//_enableSave();
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Napi Jelentés'),
|
||||
elevation: 10.0,
|
||||
leading: const Icon(Icons.arrow_back_ios_new),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.save),
|
||||
tooltip: 'Open shopping cart',
|
||||
onPressed: saveEnabled ? _print("Save Click") : null),
|
||||
]),
|
||||
//body: DailyReport(key: _key),
|
||||
backgroundColor: Colors.grey[300],
|
||||
body: SingleChildScrollView(
|
||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||
//itemExtent: 100,
|
||||
// shrinkWrap: true,
|
||||
child:
|
||||
//saveBegin == true
|
||||
// ? _onLoading()
|
||||
//: _isData == false
|
||||
|
||||
_isData == false
|
||||
? SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 1.3,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
//diameterRatio: 10,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
height: 100,
|
||||
child: workUi(),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||
child: Center(
|
||||
child: TextField(
|
||||
enabled: datePickerEnabled,
|
||||
controller:
|
||||
dateinput, //editing controller of this TextField
|
||||
decoration: const InputDecoration(
|
||||
icon: Icon(Icons
|
||||
.calendar_today), //icon of text field
|
||||
labelText:
|
||||
"Jelentés Dátuma" //label text of field
|
||||
),
|
||||
readOnly:
|
||||
true, //set it true, so that user will not able to edit text
|
||||
onTap: () async {
|
||||
DateTime? pickedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(
|
||||
2000), //DateTime.now() - not to allow to choose before today.
|
||||
lastDate: DateTime.now());
|
||||
|
||||
if (pickedDate != null) {
|
||||
print(
|
||||
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
|
||||
String formattedDate =
|
||||
DateFormat('yyyy.MM.dd')
|
||||
.format(pickedDate);
|
||||
print(
|
||||
formattedDate); //formatted date output using intl package => 2021-03-16
|
||||
//you can implement different kind of Date Format here according to your requirement
|
||||
|
||||
setState(() {
|
||||
textMessageEnabled = true;
|
||||
selectedDate = pickedDate;
|
||||
|
||||
dateinput.text =
|
||||
formattedDate; //set output date to TextField value.
|
||||
});
|
||||
} else {
|
||||
print("Nem választott dátumot!");
|
||||
}
|
||||
},
|
||||
)),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 20, left: 15, right: 15),
|
||||
//margin: const EdgeInsets.only(left: 5, right: 5),
|
||||
height: 100,
|
||||
//child: Padding(
|
||||
//padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
|
||||
|
||||
child: TextField(
|
||||
enabled: textMessageEnabled,
|
||||
//keyboardType: TextInputType.multiline,
|
||||
maxLines: null,
|
||||
onSubmitted: (value) => {
|
||||
textMessage = value,
|
||||
(value.length > 3) == true
|
||||
? _textMessageOK = true
|
||||
: _textMessageOK = false,
|
||||
},
|
||||
|
||||
//expands: true,
|
||||
textInputAction: TextInputAction.done,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Munkafolyamat leírása',
|
||||
),
|
||||
/* onChanged: (value) => {
|
||||
textMessage = value,
|
||||
(value.length > 3) == true
|
||||
? _textMessageOK = true
|
||||
: _textMessageOK = false,
|
||||
//myUi.call()
|
||||
}*/
|
||||
)),
|
||||
//),
|
||||
// The checkboxes will be here
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||
child: Card(
|
||||
//elevation: 2,
|
||||
child: ExpandablePanel(
|
||||
header: Container(
|
||||
height: 35,
|
||||
padding: const EdgeInsets.all(5),
|
||||
color: Colors.indigo,
|
||||
child: const Text(
|
||||
"Jelenlévők kiválasztása",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
collapsed:
|
||||
const Text("Érintse a lenyitáshoz."),
|
||||
expanded: AbsorbPointer(
|
||||
absorbing: !_textMessageOK,
|
||||
child: myUi(),
|
||||
)
|
||||
// tapHeaderToExpand: true,
|
||||
//hasIcon: true,
|
||||
))
|
||||
/* Column(children: [
|
||||
ListTile(
|
||||
title: const Text(
|
||||
"Jelenlévők",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
leading: Icon(Icons.arrow_drop_down_circle),
|
||||
//onTap: ,
|
||||
),
|
||||
_isData == false
|
||||
? Center(child: new CircularProgressIndicator())
|
||||
: myUi(),
|
||||
]),*/
|
||||
),
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Center(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: saveEnabled ? _saveForm : null,
|
||||
icon: const Icon(Icons.save),
|
||||
label: const Text('Save')),
|
||||
// something like 2013-04-20
|
||||
//Text(DateFormat('yyyy.MM.dd').format(selectedDate))
|
||||
),
|
||||
),
|
||||
],
|
||||
))));
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
//import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
//late EmployeeArguments empArgs;
|
||||
String? userApiKey; // = "XST8X8F-6Q9M1FG-PE9948X-SPFHVX9";
|
||||
bool _error = false;
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
|
||||
class reportNav extends StatefulWidget {
|
||||
const reportNav({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<reportNav> createState() => _reportNavState();
|
||||
}
|
||||
|
||||
/*
|
||||
Future<http.Response> fetchData(String userApiKey) async {
|
||||
var url = "http://" + appDomain + "/apiemployee/" + userApiKey;
|
||||
http.Response response = await http.get(Uri.parse(url));
|
||||
return response;
|
||||
|
||||
//return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
*/
|
||||
Future<void> _showMyDialog(BuildContext cont) async {
|
||||
return showDialog<void>(
|
||||
context: cont,
|
||||
barrierDismissible: false, // user must tap button!
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Mobile Portal'),
|
||||
content: const Text("Nem található érvényes api Key."),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('Bezárás'),
|
||||
onPressed: () {
|
||||
Navigator.pop(cont);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
class _reportNavState extends State<reportNav> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
// empArgs = (ModalRoute.of(context)?.settings.arguments ??
|
||||
// <String, dynamic>{}) as EmployeeArguments;
|
||||
// getSharedPrefs().then((value) {
|
||||
});
|
||||
//print("KEY: ${employeePageArguments.apiKey}");
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/*Future<Null> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
userApiKey = prefs.getString("apiKey");
|
||||
|
||||
if (userApiKey == null) {
|
||||
_error = true;
|
||||
WidgetsBinding.instance!
|
||||
.addPostFrameCallback((timeStamp) => _showMyDialog(context));
|
||||
}
|
||||
if (userApiKey!.length != 31) {
|
||||
_error = true;
|
||||
WidgetsBinding.instance!
|
||||
.addPostFrameCallback((timeStamp) => _showMyDialog(context));
|
||||
}
|
||||
}*/
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Jelentések"),
|
||||
/* actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.search),
|
||||
onPressed: () {},
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
),
|
||||
onPressed: () {},
|
||||
)
|
||||
],*/
|
||||
actionsIconTheme: const IconThemeData(
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
//drawer: Drawer(),
|
||||
body: _error ? Container() : page(context));
|
||||
}
|
||||
}
|
||||
|
||||
Container page(BuildContext context) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
EmployeePageArguments employeePageArguments = args['userArgs'];
|
||||
if (employeePageArguments.apiKey == null) {
|
||||
_showMyDialog(context);
|
||||
}
|
||||
|
||||
return Container(
|
||||
child: GridView.count(
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
crossAxisCount: 2,
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.only(top: 24, left: 24, right: 24),
|
||||
children: <Widget>[
|
||||
/* MaterialButton(
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/newDailyReport');
|
||||
},
|
||||
color: Colors.blue,
|
||||
textColor: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add,
|
||||
size: 48,
|
||||
),
|
||||
Text(
|
||||
"Új jelentés",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
],
|
||||
),
|
||||
padding: EdgeInsets.only(top: 32.0),
|
||||
//shape: RoundedRectangleBorder(side:,borderRadius: Radius())), // CircleBorder(),
|
||||
),*/
|
||||
MaterialButton(
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/reportList', arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': null
|
||||
});
|
||||
},
|
||||
color: Colors.blue,
|
||||
textColor: Colors.white,
|
||||
padding: const EdgeInsets.only(top: 32.0),
|
||||
child: const Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.list,
|
||||
size: 48,
|
||||
),
|
||||
Text(
|
||||
"Jelentések",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
],
|
||||
),
|
||||
//shape: RoundedRectangleBorder(side:,borderRadius: Radius())), // CircleBorder(),
|
||||
),
|
||||
MaterialButton(
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/reportCreate', arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': null
|
||||
});
|
||||
},
|
||||
color: Colors.blue,
|
||||
textColor: Colors.white,
|
||||
padding: const EdgeInsets.only(top: 32.0),
|
||||
child: const Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add,
|
||||
size: 48,
|
||||
),
|
||||
Text(
|
||||
"Új jelentés",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold),
|
||||
)
|
||||
],
|
||||
),
|
||||
//shape: RoundedRectangleBorder(side:,borderRadius: Radius())), // CircleBorder(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,765 @@
|
|||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:mobile_portal_23/models/workTimeDetailsModel.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:jiffy/jiffy.dart';
|
||||
|
||||
extension on Duration {
|
||||
String format(String s) => '$this'.split('.')[0].padLeft(8, '0');
|
||||
}
|
||||
|
||||
class workTimeDetails extends StatefulWidget {
|
||||
const workTimeDetails({Key? key}) : super(key: key);
|
||||
static const routeName = '/wtdetails';
|
||||
@override
|
||||
State<workTimeDetails> createState() => _workTimeDetailsState();
|
||||
}
|
||||
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
late WorkTimeDetailsModel workTimeList;
|
||||
bool _isError = false;
|
||||
bool _isData = false;
|
||||
|
||||
final DateFormat nowformat = DateFormat('yyyy.MM');
|
||||
|
||||
class _workTimeDetailsState extends State<workTimeDetails> {
|
||||
final DateFormat formatter = DateFormat('yyyy MMMM');
|
||||
DateTime selectedDate = DateTime.now();
|
||||
|
||||
String appDomain = "iotechnic.eu";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initializeDateFormatting('hu');
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
// empArgs = (ModalRoute.of(context)?.settings.arguments ??
|
||||
// <String, dynamic>{}) as EmployeeArguments;
|
||||
// getSharedPrefs().then((value) {
|
||||
reloadData(nowformat.format(selectedDate));
|
||||
});
|
||||
// });
|
||||
}
|
||||
|
||||
reloadData(String date) {
|
||||
fetchdata(date).then((data) {
|
||||
if (data != null) {
|
||||
// for (var item in data) {
|
||||
workTimeList =
|
||||
WorkTimeDetailsModel.fromJson(data); //{'wd': data['wd']}));
|
||||
// }
|
||||
|
||||
setState(() {
|
||||
_isData = true;
|
||||
debugPrint('Fetch ok.');
|
||||
});
|
||||
} else {
|
||||
_isError = true;
|
||||
}
|
||||
//employeeList = data;
|
||||
});
|
||||
}
|
||||
|
||||
Future fetchdata(String date) async {
|
||||
var res = await http.get(
|
||||
|
||||
// "http://iotechnic.eu/apiGetAllReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
Uri.parse("http://$appDomain/employee/androidAccessList/${employeePageArguments.apiKey!}/$date"));
|
||||
//"http://192.168.0.144/apiGetDailyReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: _isData ? Text(formatter.format(selectedDate)) : const Text("ss"),
|
||||
elevation: 10.0,
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.navigate_before),
|
||||
tooltip: 'Show Snackbar',
|
||||
onPressed: () {
|
||||
selectedDate = Jiffy.parse(selectedDate.toString()).subtract(months: 1).dateTime;
|
||||
reloadData(nowformat.format(selectedDate));
|
||||
}),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.navigate_next_rounded),
|
||||
color: Colors.white,
|
||||
tooltip: 'Go to the next page',
|
||||
onPressed: selectedDate.difference(DateTime.now()).inDays < 0
|
||||
? () {
|
||||
_isData = false;
|
||||
_isError = false;
|
||||
selectedDate = Jiffy.parse(selectedDate.toString()).add(months: 1).dateTime;
|
||||
// String jiffy=selectedDate.
|
||||
reloadData(nowformat.format(selectedDate));
|
||||
}
|
||||
: null,
|
||||
),
|
||||
],
|
||||
// leading: Icon(Icons.arrow_back_ios_new),
|
||||
),
|
||||
body: _isData
|
||||
? detailsPage(
|
||||
context, workTimeList) //reportCard(context, workTimeList)
|
||||
: const Center(child: CircularProgressIndicator()),
|
||||
backgroundColor: Colors.grey[300],
|
||||
);
|
||||
}
|
||||
|
||||
String minToTime(var seconds) {
|
||||
int minutes = (seconds / 60).truncate();
|
||||
int sec = (seconds % 60);
|
||||
String minutesStr = "${minutes.toString().padLeft(2, "0")}.${sec.toString().padLeft(2, "0")}";
|
||||
return minutesStr;
|
||||
}
|
||||
|
||||
/* Widget _buildContent(BuildContext context) {
|
||||
return Container(
|
||||
color: Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: workTimeList
|
||||
.length, //workTimeList.wd?.length, // The length Of the array
|
||||
|
||||
padding: EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: //if (_isData)
|
||||
reportCard(context, workTimeList, index)),
|
||||
));
|
||||
}*/
|
||||
Widget Arrive(e, Wd wtd) {
|
||||
var dateformat = DateFormat.E('hu');
|
||||
final DateFormat formatter = DateFormat('HH:mm');
|
||||
return //Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||
|
||||
/* Expanded(
|
||||
// flex: 1,
|
||||
child: Text(
|
||||
wtd.date!.substring(8, 11).toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87),
|
||||
)),
|
||||
Expanded(
|
||||
//flex: 1,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
wtd.isHoliday == true
|
||||
? dateformat
|
||||
.format(DateFormat("yyyy.MM.DD").parse(wtd.date.toString()))
|
||||
: dateformat
|
||||
.format(DateFormat("yyyy.MM.DD.").parse(wtd.date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold, color: Colors.blue),
|
||||
)),*/
|
||||
Expanded(
|
||||
flex: 8,
|
||||
child:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(
|
||||
'É: ${formatter.format(DateFormat("H:mm")
|
||||
.parse(e.start.substring(12, e.start.length)))} ' +
|
||||
e.arriveLoc,
|
||||
overflow: TextOverflow.ellipsis),
|
||||
if (e.stop == '-')
|
||||
const Text('--:--')
|
||||
else
|
||||
Text(
|
||||
'T: ${formatter.format(DateFormat("H:mm")
|
||||
.parse(e.stop.substring(12, e.stop.length)))} ' +
|
||||
e.getawayLoc,
|
||||
overflow: TextOverflow.ellipsis),
|
||||
]));
|
||||
}
|
||||
|
||||
Container startStopWidget(BuildContext context, Wd wtd) {
|
||||
var dateformat = DateFormat.E('hu');
|
||||
|
||||
final DateFormat formatter = DateFormat('HH:mm');
|
||||
List<Widget> v = [];
|
||||
v.add(Expanded(
|
||||
// flex: 1,
|
||||
child: Text(
|
||||
wtd.date!.substring(8, 10).toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black87),
|
||||
)));
|
||||
v.add(
|
||||
Expanded(
|
||||
//flex: 1,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
wtd.isHoliday == true
|
||||
? dateformat
|
||||
.format(DateFormat("yyyy.MM.DD").parse(wtd.date.toString()))
|
||||
: dateformat
|
||||
.format(DateFormat("yyyy.MM.DD.").parse(wtd.date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold, color: Colors.blue),
|
||||
)),
|
||||
);
|
||||
if (wtd.isHoliday == false) {
|
||||
for (var e in wtd.startStop!) {
|
||||
v.add(Expanded(
|
||||
flex: 8,
|
||||
child:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text(
|
||||
'É: ${formatter.format(DateFormat("yyyy.MM.dd. H:mm")
|
||||
.parse(e.start.toString()))} ${e.arriveLoc}',
|
||||
overflow: TextOverflow.ellipsis),
|
||||
if (e.stop == '-')
|
||||
const Text('--:--')
|
||||
else
|
||||
Text(
|
||||
'T: ${formatter.format(DateFormat("yyyy.MM.dd. H:mm")
|
||||
.parse(e.stop.toString()))} ${e.getawayLoc}',
|
||||
overflow: TextOverflow.ellipsis),
|
||||
])));
|
||||
debugPrint(wtd.toString());
|
||||
}
|
||||
}
|
||||
return Container(
|
||||
color: const Color.fromARGB(255, 206, 206, 206),
|
||||
margin: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: wtd.isHoliday == true
|
||||
? [
|
||||
Text(wtd.date.toString()),
|
||||
const Text("Szabadság"),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
]
|
||||
: //wtd.startStop!.map((e) => Arrive(e, wtd)).toList()),
|
||||
[
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children:
|
||||
v /*[
|
||||
Expanded(
|
||||
// flex: 1,
|
||||
child: Text(
|
||||
wtd.date!.substring(8, 11).toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black87),
|
||||
)
|
||||
),
|
||||
Expanded(
|
||||
//flex: 1,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
wtd.isHoliday == true
|
||||
? dateformat.format(DateFormat("yyyy.MM.DD")
|
||||
.parse(wtd.date.toString()))
|
||||
: dateformat.format(DateFormat("yyyy.MM.DD.")
|
||||
.parse(wtd.date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)
|
||||
),
|
||||
|
||||
wtd.startStop!.map((e) => Arrive(e, wtd)).toList()),
|
||||
]*/
|
||||
)
|
||||
]));
|
||||
}
|
||||
|
||||
Container detailsPage(BuildContext context, WorkTimeDetailsModel item) {
|
||||
return Container(
|
||||
child: ListView.builder(
|
||||
itemCount: item.wd!.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
_isData = false;
|
||||
return //startStopWidget(context, item.wd![index]);
|
||||
//reportCard2(context, item.wd![index]);
|
||||
buildCard(context, item.wd![index]);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
Widget buildCard(BuildContext context, Wd itemx) {
|
||||
var dayformat = DateFormat.d('hu');
|
||||
var dateformat = DateFormat.E('hu');
|
||||
final DateFormat formatter = DateFormat('HH:mm');
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: ExpandablePanel(
|
||||
header: Column(children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
itemx.isHoliday == true
|
||||
? '${dayformat.format(DateFormat("yyyy.MM.dd")
|
||||
.parse(itemx.date.toString()))}.'
|
||||
: '${dayformat.format(DateFormat("yyyy.MM.dd.")
|
||||
.parse(itemx.date.toString()))}.',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
itemx.isHoliday == true
|
||||
? dateformat.format(DateFormat("yyyy.MM.dd")
|
||||
.parse(itemx.date.toString()))
|
||||
: dateformat.format(DateFormat("yyyy.MM.dd.")
|
||||
.parse(itemx.date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
color: Colors.blue,
|
||||
thickness: 1,
|
||||
)
|
||||
]),
|
||||
//Text("Header"),
|
||||
|
||||
collapsed: //Text('collapsed'),
|
||||
itemx.isHoliday == true
|
||||
? const Text("Szabadság")
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
//Text(itemx.fullHours.toString()),
|
||||
|
||||
Text('Normál óra'),
|
||||
Text('Túlóra óra'),
|
||||
Text('Összes óra'),
|
||||
]),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
formatter.format(DateFormat("mm")
|
||||
.parse(itemx.hours.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
Text(
|
||||
formatter.format(DateFormat("mm")
|
||||
.parse(itemx.overTime.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
Text(
|
||||
formatter.format(DateFormat("mm")
|
||||
.parse(itemx.fullHours.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
]),
|
||||
]),
|
||||
expanded: itemx.isHoliday == true
|
||||
? const Text("Szabadság")
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
//Text(itemx.fullHours.toString()),
|
||||
|
||||
Text('Érkezés'),
|
||||
Text('Távozás'),
|
||||
Text('Óra'),
|
||||
]),
|
||||
Column(
|
||||
children: itemx.startStop!
|
||||
.map<Widget>((e) => _getrow(e))
|
||||
.toList())
|
||||
]),
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getrow(StartStop e) {
|
||||
final DateFormat formatter = DateFormat('HH:mm');
|
||||
var start = DateFormat("yyyy.MM.dd. HH:mm").parse(e.start.toString());
|
||||
DateTime stop;
|
||||
late Duration diff;
|
||||
if (e.stop != '-') {
|
||||
stop = DateFormat("yyyy.MM.dd. HH:mm").parse(e.stop.toString());
|
||||
diff = stop.difference(start);
|
||||
}
|
||||
return Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||
Text(formatter.format(start), textAlign: TextAlign.center),
|
||||
if (e.stop == '-') ...[
|
||||
const Text('--:--'),
|
||||
const Text('--:--')
|
||||
] else ...[
|
||||
Text(formatter.format(stop), textAlign: TextAlign.center),
|
||||
Text(
|
||||
formatter.format(DateFormat("mm").parse(diff.inMinutes.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
Card reportCard2(BuildContext context, Wd itemx) {
|
||||
var dateformat = DateFormat.E('hu');
|
||||
final DateFormat formatter = DateFormat('HH:mm');
|
||||
return Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child:
|
||||
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
itemx.isHoliday == true
|
||||
? dateformat.format(DateFormat("yyyy.MM.dd")
|
||||
.parse(itemx.date.toString()))
|
||||
: dateformat.format(DateFormat("yyyy.MM.dd.")
|
||||
.parse(itemx.date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)),
|
||||
const Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
//Text(itemx.fullHours.toString()),
|
||||
|
||||
Text('Normál óra'),
|
||||
Text('Túlóra óra'),
|
||||
Text('Összes óra'),
|
||||
]),
|
||||
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||
Text(
|
||||
formatter
|
||||
.format(DateFormat("mm").parse(itemx.hours.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
Text(
|
||||
formatter.format(
|
||||
DateFormat("mm").parse(itemx.overTime.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
Text(
|
||||
formatter.format(
|
||||
DateFormat("mm").parse(itemx.fullHours.toString())),
|
||||
textAlign: TextAlign.center),
|
||||
]),
|
||||
])));
|
||||
}
|
||||
|
||||
Card reportCard(BuildContext context, WorkTimeDetailsModel itemx) {
|
||||
int workHour = 0;
|
||||
bool workOpened = false;
|
||||
//bool? isHoliday = item.wd![index].isHoliday;
|
||||
var dateformat = DateFormat.E('hu');
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: ListView.builder(
|
||||
itemCount: itemx.wd?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
List<Text> start = itemx.wd![index].isHoliday != true
|
||||
? itemx.wd![index].startStop!
|
||||
.map(
|
||||
(e) => Text(
|
||||
e.start.toString(),
|
||||
//item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
//.cast<StartStop>()
|
||||
.toList()
|
||||
: [const Text("Szabi")];
|
||||
bool? isHoliday = itemx.wd![index].isHoliday;
|
||||
return ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.blue,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
isHoliday == true
|
||||
? dateformat.format(DateFormat("yyyy.MM.DD")
|
||||
.parse(itemx.wd![index].date.toString()))
|
||||
: dateformat.format(DateFormat("yyyy.MM.DD.")
|
||||
.parse(itemx.wd![index].date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
title: isHoliday == false
|
||||
? Column(children: [
|
||||
Row(
|
||||
children:
|
||||
start /*itemx.wd![index].startStop!
|
||||
.map(
|
||||
(e) => Text(
|
||||
e.start.toString(),
|
||||
//item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
.toList(),*/
|
||||
),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
])
|
||||
: const Text("Szabi"));
|
||||
//Text(itemx.wd![index].date.toString());
|
||||
},
|
||||
),
|
||||
/*Column(
|
||||
children: [
|
||||
ListTile(
|
||||
tileColor: Colors.blue,
|
||||
onTap: () {},
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
isHoliday == true
|
||||
? dateformat.format(DateFormat("yyyy.MM.DD")
|
||||
.parse(item.wd![index].date.toString()))
|
||||
: dateformat.format(DateFormat("yyyy.MM.DD.")
|
||||
.parse(item.wd![index].date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)),
|
||||
title: Text(
|
||||
item.wd?[index].date as String,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
subtitle: isHoliday == true
|
||||
? Text(
|
||||
"Szabadság",
|
||||
style: TextStyle(
|
||||
color: Colors.yellow,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18),
|
||||
)
|
||||
: item.wd![index].notes != null
|
||||
? Text(
|
||||
item.wd![index].notes as String,
|
||||
style:
|
||||
TextStyle(color: Colors.black.withOpacity(0.6)),
|
||||
)
|
||||
: Text("Nincs")),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Row(children: [
|
||||
Text(
|
||||
'KL', //+ item.workNumber!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'Órák: ' +
|
||||
Duration(minutes: item.month!.fullWorkHours!.toInt())
|
||||
.format(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'PO:', // + item.poNumber!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Row(children: [
|
||||
Text(
|
||||
item.wd![index].date.toString(),
|
||||
//item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]
|
||||
/* .map(
|
||||
(e) => Text(
|
||||
e.date.toString(),
|
||||
//item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
.toList(),*/
|
||||
),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
]))),
|
||||
],
|
||||
),*/
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Widget _buildContent(BuildContext context) {
|
||||
return Container(
|
||||
color: Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: workTimeList.wd?.length, // The length Of the array
|
||||
|
||||
padding: EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: //if (_isData)
|
||||
reportCard(context, workTimeList, index)),
|
||||
));
|
||||
}
|
||||
*/
|
||||
|
||||
/* Card reportCard(BuildContext context, WorkTimeDetailsModel item, int index) {
|
||||
int workHour = 0;
|
||||
bool workOpened = false;
|
||||
bool? isHoliday = item.wd![index].isHoliday;
|
||||
var dateformat = new DateFormat.E('hu');
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
tileColor: Colors.blue,
|
||||
onTap: () {},
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
//"$item.month.fullWorkHours",
|
||||
isHoliday == true
|
||||
? dateformat.format(DateFormat("yyyy.MM.DD")
|
||||
.parse(item.wd![index].date.toString()))
|
||||
: dateformat.format(DateFormat("yyyy.MM.DD.")
|
||||
.parse(item.wd![index].date.toString())),
|
||||
//item.month?.fullWorkHours.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)),
|
||||
title: Text(
|
||||
item.wd?[index].date as String,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
subtitle: isHoliday == true
|
||||
? Text(
|
||||
"Szabadság",
|
||||
style: TextStyle(
|
||||
color: Colors.yellow,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18),
|
||||
)
|
||||
: item.wd![index].notes != null
|
||||
? Text(
|
||||
item.wd![index].notes as String,
|
||||
style:
|
||||
TextStyle(color: Colors.black.withOpacity(0.6)),
|
||||
)
|
||||
: Text("Nincs")),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Row(children: [
|
||||
Text(
|
||||
'KL', //+ item.workNumber!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'Órák: ' +
|
||||
Duration(minutes: item.month!.fullWorkHours!.toInt())
|
||||
.format(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'PO:', // + item.poNumber!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Row(children: [
|
||||
Text(
|
||||
item.wd![index].date.toString(),
|
||||
//item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]
|
||||
/* .map(
|
||||
(e) => Text(
|
||||
e.date.toString(),
|
||||
//item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
.toList(),*/
|
||||
),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
]))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}*/
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
class EmployeePageArguments {
|
||||
final String? name;
|
||||
final String? id;
|
||||
final String? apiKey;
|
||||
final bool? isForeman;
|
||||
final bool? mobilePortalAccessEnabled;
|
||||
EmployeePageArguments(
|
||||
{this.name,
|
||||
this.id,
|
||||
this.apiKey,
|
||||
this.isForeman,
|
||||
this.mobilePortalAccessEnabled});
|
||||
|
||||
/*EmployeePageArguments.fromJson(Map<String, dynamic> json) {
|
||||
name = json['name'];
|
||||
id = json['id'];
|
||||
apiKey = json['apiKey'];
|
||||
isForeman = json['isForeman'];
|
||||
mobilePortalAccessEnabled = json["mobilePortalAccessEnabled"];
|
||||
}*/
|
||||
}
|
||||
|
||||
class QRCodeModel {
|
||||
late final String? name;
|
||||
late final String? id;
|
||||
late final String? qrCode;
|
||||
|
||||
QRCodeModel(
|
||||
{this.name,
|
||||
this.id,
|
||||
this.qrCode
|
||||
});
|
||||
|
||||
QRCodeModel.fromJson(Map<String, dynamic> json) {
|
||||
name = json['name'];
|
||||
id = json['id'];
|
||||
qrCode = json['qrCode'];
|
||||
|
||||
}
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['name'] = name;
|
||||
data['id'] = id;
|
||||
data['qrCode'] = qrCode;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class WorkStateModel {
|
||||
late final String? workState;
|
||||
|
||||
WorkStateModel(
|
||||
{this.workState,
|
||||
|
||||
});
|
||||
|
||||
WorkStateModel.fromJson(Map<String, dynamic> json) {
|
||||
workState = json['workState'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ReportArguments {
|
||||
final List<DailyReport> report;
|
||||
//final String userApiKey;
|
||||
final String workName;
|
||||
final String workId;
|
||||
final bool state;
|
||||
//final bool isForeman;
|
||||
ReportArguments(
|
||||
this.report, //this.userApiKey,
|
||||
this.workName,
|
||||
this.workId,
|
||||
this.state,
|
||||
//this.isForeman
|
||||
);
|
||||
|
||||
}
|
||||
class EmployeeArguments {
|
||||
String? name;
|
||||
String? id;
|
||||
bool? isForeman;
|
||||
bool? mobilePortalAccessEnabled;
|
||||
EmployeeArguments(
|
||||
{this.name, this.id, this.isForeman, this.mobilePortalAccessEnabled});
|
||||
|
||||
EmployeeArguments.fromJson(Map<String, dynamic> json) {
|
||||
name = json['name'];
|
||||
id = json['id'];
|
||||
isForeman = json['isForeman'];
|
||||
mobilePortalAccessEnabled = json["mobilePortalAccessEnabled"];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['name'] = name;
|
||||
data['id'] = id;
|
||||
data['isForeman'] = isForeman;
|
||||
data['mobilePortalAccessEnabled'] = mobilePortalAccessEnabled;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class DeviceArguments {
|
||||
final String Id;
|
||||
final String Name;
|
||||
final String Brand;
|
||||
|
||||
DeviceArguments(this.Id, this.Name, this.Brand);
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'main_page.dart' as main_page;
|
||||
import 'register_page.dart' as register_page;
|
||||
import 'app_worktime/worktime_details.dart' as worktime_page;
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'app_worktime/reportNavPage.dart' as dailyReportNav_page;
|
||||
import 'package:mobile_portal_23/widgets/reportList.dart' as reportList_page;
|
||||
import 'package:mobile_portal_23/widgets/reportNew.dart' as reportNew_page;
|
||||
import 'package:mobile_portal_23/widgets/reportDetails.dart' as reportDetails_page;
|
||||
import 'package:mobile_portal_23/report_selectWork.dart' as reportSelectWork_page;
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Mobile Portal',
|
||||
theme: ThemeData(
|
||||
// This is the theme of your application.
|
||||
//
|
||||
// TRY THIS: Try running your application with "flutter run". You'll see
|
||||
// the application has a purple toolbar. Then, without quitting the app,
|
||||
// try changing the seedColor in the colorScheme below to Colors.green
|
||||
// and then invoke "hot reload" (save your changes or press the "hot
|
||||
// reload" button in a Flutter-supported IDE, or press "r" if you used
|
||||
// the command line to start the app).
|
||||
//
|
||||
// Notice that the counter didn't reset back to zero; the application
|
||||
// state is not lost during the reload. To reset the state, use hot
|
||||
// restart instead.
|
||||
//
|
||||
// This works for code too, not just values: Most code changes can be
|
||||
// tested with just a hot reload.
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
|
||||
useMaterial3: true,
|
||||
),
|
||||
//home: const MyHomePage(title: 'Munkaidő rögzítő'),
|
||||
routes: {
|
||||
//'/':(context)=>const MyHomePage(title: 'Munkaidő rögzítő'),
|
||||
//'/register':(context)=>const register_page.RegisterPage(),
|
||||
register_page.RegisterPage.routeName:(context)=>const register_page.RegisterPage(),
|
||||
'/':(context)=>const main_page.MainPage(),
|
||||
'/wtdetails': (context) => const worktime_page.workTimeDetails(),
|
||||
'/reportNav': (context)=> const dailyReportNav_page.reportNav(),
|
||||
//'/reportCreate': (context)=> testRepCreate_page.ReportCreate(),//reportSelectWork_page.reportCreate(),
|
||||
'/reportCreate': (context)=> const reportSelectWork_page.reportCreate(),
|
||||
'/reportList':(context)=> const reportList_page.dailyReportList(),
|
||||
'/reportNew': (context)=>const reportNew_page.reportNew(),
|
||||
'/reportDetails': (context)=>const reportDetails_page.reportDetails(),
|
||||
},
|
||||
builder: EasyLoading.init(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
|
||||
// This widget is the home page of your application. It is stateful, meaning
|
||||
// that it has a State object (defined below) that contains fields that affect
|
||||
// how it looks.
|
||||
|
||||
// This class is the configuration for the state. It holds the values (in this
|
||||
// case the title) provided by the parent (in this case the App widget) and
|
||||
// used by the build method of the State. Fields in a Widget subclass are
|
||||
// always marked "final".
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
int _counter = 0;
|
||||
|
||||
void _incrementCounter() {
|
||||
setState(() {
|
||||
// This call to setState tells the Flutter framework that something has
|
||||
// changed in this State, which causes it to rerun the build method below
|
||||
// so that the display can reflect the updated values. If we changed
|
||||
// _counter without calling setState(), then the build method would not be
|
||||
// called again, and so nothing would appear to happen.
|
||||
_counter++;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// This method is rerun every time setState is called, for instance as done
|
||||
// by the _incrementCounter method above.
|
||||
//
|
||||
// The Flutter framework has been optimized to make rerunning build methods
|
||||
// fast, so that you can just rebuild anything that needs updating rather
|
||||
// than having to individually change instances of widgets.
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
// TRY THIS: Try changing the color here to a specific color (to
|
||||
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
|
||||
// change color while the other colors stay the same.
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
// Here we take the value from the MyHomePage object that was created by
|
||||
// the App.build method, and use it to set our appbar title.
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: Center(
|
||||
// Center is a layout widget. It takes a single child and positions it
|
||||
// in the middle of the parent.
|
||||
child: Column(
|
||||
// Column is also a layout widget. It takes a list of children and
|
||||
// arranges them vertically. By default, it sizes itself to fit its
|
||||
// children horizontally, and tries to be as tall as its parent.
|
||||
//
|
||||
// Column has various properties to control how it sizes itself and
|
||||
// how it positions its children. Here we use mainAxisAlignment to
|
||||
// center the children vertically; the main axis here is the vertical
|
||||
// axis because Columns are vertical (the cross axis would be
|
||||
// horizontal).
|
||||
//
|
||||
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
|
||||
// action in the IDE, or press "p" in the console), to see the
|
||||
// wireframe for each widget.
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all<Color>(Colors.blue),
|
||||
),
|
||||
onPressed: () { Navigator.pushNamed(context, '/main');},
|
||||
child: const Text('TextButton')
|
||||
),
|
||||
const Text(
|
||||
'You have pushed the button this many times:',
|
||||
),
|
||||
Text(
|
||||
'$_counter',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _incrementCounter,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.add),
|
||||
), // This trailing comma makes auto-formatting nicer for build methods.
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,999 @@
|
|||
//import 'dart:ffi';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'dart:async';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:nfc_manager/platform_tags.dart';
|
||||
import 'services/storage.dart' as storage;
|
||||
import 'services/device_info.dart' as device_info;
|
||||
import 'classes/named_route_args.dart';
|
||||
import 'package:location/location.dart';
|
||||
import 'common_widgets/custom_icon_button.dart';
|
||||
import 'classes/common_classes.dart';
|
||||
import 'package:nfc_manager/nfc_manager.dart';
|
||||
import "package:hex/hex.dart";
|
||||
import 'package:geolocator/geolocator.dart' as geolocator;
|
||||
import 'package:geocoding/geocoding.dart' as geocoding;
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
|
||||
import 'dart:io';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
class MainPage extends StatefulWidget {
|
||||
const MainPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<MainPage> createState() => _MainPageState();
|
||||
}
|
||||
|
||||
class _MainPageState extends State<MainPage> with TickerProviderStateMixin{
|
||||
String appDomain = "iotechnic.eu";
|
||||
|
||||
bool _showNFClogo = false;
|
||||
bool _reportButtonDisabled = true;
|
||||
final bool _nfcOk = false;
|
||||
final bool _deviceRegistered = false;
|
||||
bool _initOK = false;
|
||||
bool _isApiKeyValid = false;
|
||||
bool _isScanVisible = false;
|
||||
bool _isLocationMocked=false;
|
||||
bool _isLocationValid=false;
|
||||
geolocator.Position? _currentPosition;
|
||||
late LocationData _currentLocation;
|
||||
String _currentAddress = "";
|
||||
String result = "";
|
||||
String accessName = "";
|
||||
String accessMsg = "";
|
||||
String accessWorktime = "";
|
||||
String accessDateTime = "";
|
||||
String accessLocation = "";
|
||||
String appVersion = "";
|
||||
String appCode = "";
|
||||
String qrdata="";
|
||||
String currentWorkState="";
|
||||
QRCodeModel currentQRcode=QRCodeModel();
|
||||
WorkStateModel workState=WorkStateModel();
|
||||
late EmployeeArguments ea;
|
||||
EmployeePageArguments employeePageArgs = EmployeePageArguments();
|
||||
device_info.DeviceInfo di=device_info.DeviceInfo();
|
||||
var deviceData = <String, dynamic>{};
|
||||
|
||||
Future ?apiKey ;
|
||||
bool apiKeyValid=false;
|
||||
Map<String, dynamic> _deviceData = <String, dynamic>{};
|
||||
// Location
|
||||
final Location location = Location();
|
||||
bool _loading = false;
|
||||
LocationData? _location;
|
||||
String? _error;
|
||||
|
||||
late final AnimationController _controller = AnimationController(
|
||||
duration: const Duration(seconds: 1),
|
||||
vsync: this,
|
||||
lowerBound: 0.5,
|
||||
upperBound: 1.0,
|
||||
value: 1,
|
||||
)..repeat(reverse: true);
|
||||
late final Animation<double> _animation = CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.easeInOutCirc,
|
||||
);
|
||||
|
||||
// Aktuális QR kód lekérése szervertől
|
||||
Future<bool> getQRCode(String userApiKey) async {
|
||||
if (userApiKey.isEmpty) return false;
|
||||
var url = "http://$appDomain/apiGetQRCode/$userApiKey";
|
||||
http.Response response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
var resp = jsonDecode(response.body);
|
||||
currentQRcode = QRCodeModel.fromJson(resp);
|
||||
setState(() {
|
||||
qrdata=currentQRcode.qrCode!;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
//return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
|
||||
// Aktuális Munkaidő állapot lekérése szervertől
|
||||
Future<bool> getWorkState(String userApiKey) async {
|
||||
if (userApiKey.isEmpty) return false;
|
||||
var url = "http://$appDomain/apiGetWorkState/$userApiKey";
|
||||
http.Response response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
var resp = jsonDecode(response.body);
|
||||
workState = WorkStateModel.fromJson(resp);
|
||||
setState(() {
|
||||
currentWorkState=workState.workState!;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
//return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
|
||||
Future<bool> checkApiKeyValidity(String userApiKey) async {
|
||||
if (userApiKey.isEmpty) return false;
|
||||
var url = "http://$appDomain/apiemployee/$userApiKey";
|
||||
http.Response response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
var resp = jsonDecode(response.body);
|
||||
ea = EmployeeArguments.fromJson(resp);
|
||||
setState(() {
|
||||
_reportButtonDisabled = false;
|
||||
});
|
||||
if (ea.mobilePortalAccessEnabled == false) {
|
||||
_showAccessDeniedDialog();
|
||||
}
|
||||
employeePageArgs = EmployeePageArguments(
|
||||
name: ea.name,
|
||||
id: ea.id,
|
||||
apiKey: userApiKey,
|
||||
isForeman: ea.isForeman,
|
||||
mobilePortalAccessEnabled: ea.mobilePortalAccessEnabled);
|
||||
setState(() {
|
||||
_reportButtonDisabled = !ea.isForeman!;
|
||||
});
|
||||
if (ea.id!.isNotEmpty) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
//return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
@override
|
||||
void dispose(){
|
||||
NfcManager.instance;
|
||||
_controller.dispose();
|
||||
NfcManager.instance;
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.landscapeRight,
|
||||
DeviceOrientation.landscapeLeft,
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
super.dispose();
|
||||
}
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initStateA
|
||||
super.initState();
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
|
||||
di.initPlatformState().then((value)
|
||||
{
|
||||
deviceData = value;
|
||||
|
||||
//checkApiKey();
|
||||
//saveApiKey();
|
||||
storage.SecureStorage sc= storage.SecureStorage();
|
||||
//sc.deleteSecureData('API');
|
||||
Future<bool> res= storage.SecureStorage().checkContainsKey('API');// sc.checkContainsKey('API');
|
||||
res.then((value) {
|
||||
//_isApiKeyValid=value;
|
||||
//apiKeyValid=value;
|
||||
if (value==false)
|
||||
{
|
||||
Navigator.pushNamed(context, '/register', arguments: DeviceArguments(
|
||||
deviceData['id'], deviceData['device'], deviceData['brand']));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Future<String> userApiKey=sc.readSecureData("API");
|
||||
userApiKey.then((apiKey) => checkApiKeyValidity(apiKey).then((apiKeyState) {
|
||||
// print("API key State: $apiKeyState");
|
||||
|
||||
setState(() {
|
||||
_isApiKeyValid = apiKeyState;
|
||||
if (ea.isForeman==true)
|
||||
{
|
||||
_reportButtonDisabled=false;
|
||||
}
|
||||
if (ea.mobilePortalAccessEnabled==true)
|
||||
{
|
||||
NfcManager.instance.isAvailable().then((nfcState){
|
||||
if (_isApiKeyValid && !_isLocationMocked)
|
||||
{
|
||||
_showNFClogo=true;
|
||||
_tagRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
_showNFClogo=false;
|
||||
}
|
||||
} );
|
||||
getWorkState(apiKey);
|
||||
getQRCode(apiKey);
|
||||
/* NfcManager.instance.isAvailable().then((nfcvalue) {
|
||||
if (nfcvalue) {
|
||||
_nfcOk = true;
|
||||
_showNFClogo = true;
|
||||
if (_location?.isMock == false) {
|
||||
_tagRead();
|
||||
}
|
||||
}
|
||||
});*/
|
||||
}
|
||||
_getLocation();
|
||||
// _getCurrentLocation();
|
||||
_isApiKeyValid = apiKeyState;
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
//sc.writeSecureData("API", deviceData['id']);
|
||||
//sc.checkContainsKey('API');
|
||||
//sc.readSecureData("API");
|
||||
});
|
||||
|
||||
_getLocation();
|
||||
PackageInfo.fromPlatform().then((value) => {
|
||||
appCode=value.buildNumber,
|
||||
appVersion=value.version
|
||||
});//getAppVersion() as PackageInfo;
|
||||
|
||||
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_initOK=true;
|
||||
_deviceData = deviceData;
|
||||
|
||||
});
|
||||
//getWorkState(apiKey as String);
|
||||
|
||||
//apiKey=//_getApiKey();
|
||||
// _storage.write(key: 'API', value: _deviceData['id']);
|
||||
}
|
||||
Future<void> _getLocation() async {
|
||||
setState(() {
|
||||
_error = null;
|
||||
_loading = true;
|
||||
_isLocationValid=false;
|
||||
_isScanVisible=false;
|
||||
});
|
||||
try {
|
||||
final locationResult = await location.getLocation();
|
||||
setState(() {
|
||||
_location = locationResult;
|
||||
_loading = false;
|
||||
_isLocationValid = true;
|
||||
_isLocationMocked=locationResult.isMock!;
|
||||
_isScanVisible = true;
|
||||
_currentLocation=locationResult;
|
||||
_getAddressFromLatLng(locationResult.latitude,locationResult.longitude);
|
||||
|
||||
});
|
||||
} on PlatformException catch (err) {
|
||||
setState(() {
|
||||
_error = err.code;
|
||||
_loading = false;
|
||||
_isLocationValid=false;
|
||||
_isScanVisible=false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* String _getAppBarTitle() => kIsWeb
|
||||
? 'Web Browser info'
|
||||
: switch (defaultTargetPlatform) {
|
||||
TargetPlatform.android => 'Android DI $apiKeyValid ${_deviceData['id']}',
|
||||
TargetPlatform.iOS => 'iOS Device Info',
|
||||
TargetPlatform.linux => 'Linux Device Info',
|
||||
TargetPlatform.windows => 'Windows Device Info',
|
||||
TargetPlatform.macOS => 'MacOS Device Info',
|
||||
TargetPlatform.fuchsia => 'Fuchsia Device Info',
|
||||
};*/
|
||||
Widget nfcLogo() {
|
||||
if (_location?.isMock==true) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Image(
|
||||
color: Colors.white,
|
||||
image: AssetImage('graphics/nfcdenied.png'),
|
||||
width: 128,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return ScaleTransition(
|
||||
scale: _animation,
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Image(
|
||||
color: Colors.white,
|
||||
image: AssetImage('assets/nfc.png'),
|
||||
width: 128,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Future _scanQR() async {
|
||||
/*try {
|
||||
String qrResult = await BarcodeScanner.scan();
|
||||
setState(() {
|
||||
_login(qrResult);
|
||||
/* result = qrResult;
|
||||
TcpClient a = new TcpClient(socket, 'iotechnic.eu', 8080);
|
||||
|
||||
_getId();
|
||||
a.sendAccess(
|
||||
deviceId,
|
||||
result,
|
||||
_currentAddress,
|
||||
_currentPosition.latitude.toString(),
|
||||
_currentPosition.longitude.toString());*/
|
||||
});
|
||||
} on PlatformException catch (ex) {
|
||||
if (ex.code == BarcodeScanner.CameraAccessDenied) {
|
||||
setState(() {
|
||||
result = "Camera permission was denied";
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
result = "Unknown Error $ex";
|
||||
});
|
||||
}
|
||||
} on FormatException {
|
||||
setState(() {
|
||||
result = "You pressed the back button before scanning anything";
|
||||
});
|
||||
} catch (ex) {
|
||||
setState(() {
|
||||
result = "Unknown Error $ex";
|
||||
});
|
||||
}*/
|
||||
}
|
||||
_loginQR(qrCode) {
|
||||
setState(() {
|
||||
_showNFClogo = false;
|
||||
});
|
||||
//DeviceInfo devInfo = _getDeviceInfo() as DeviceInfo;
|
||||
|
||||
String indexRequest = '{'
|
||||
'"cmd":"ACCESSNOGEOQR",'
|
||||
'"CID1":"${deviceData['id']}",'
|
||||
'"CID2":"${deviceData['device']} ${deviceData['brand']}",'
|
||||
'"address":"$_currentAddress",'
|
||||
'"qrCode":"$qrCode",'
|
||||
'"LAT":"${_currentLocation.latitude}",'
|
||||
'"LON":"${_currentLocation.longitude}",'
|
||||
'"mode":"GETAWAY"}';
|
||||
|
||||
debugPrint('Connecting...');
|
||||
//AESEncryption enc = new AESEncryption();
|
||||
//enc.encryptMsg(indexRequest);
|
||||
//connect to google port 80
|
||||
Socket.connect("iotechnic.eu", 8080).then((socket) {
|
||||
if (kDebugMode) {
|
||||
print('Connected to: '
|
||||
'${socket.remoteAddress.address}:${socket.remotePort}');
|
||||
}
|
||||
|
||||
//Establish the onData, and onDone callbacks
|
||||
socket.listen((data) {
|
||||
//print(new String.fromCharCodes(data).trim());
|
||||
var decoded = utf8.decode(data);
|
||||
//var jsonString = json.encode(new String.fromCharCodes(data).trim());
|
||||
Map<String, dynamic> resp = jsonDecode(decoded);
|
||||
debugPrint(decoded);
|
||||
debugPrint(resp['data']);
|
||||
getWorkState(employeePageArgs.apiKey as String);
|
||||
if (resp['data'] == 'VALID CODE') {
|
||||
setState(() {
|
||||
result = "";
|
||||
accessName = resp['employeeName'];
|
||||
accessMsg = resp['message'];
|
||||
accessLocation = resp['city'];
|
||||
accessWorktime = resp['worktime'];
|
||||
accessDateTime = resp['datetime'];
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
result = resp['data'];
|
||||
accessName = "";
|
||||
accessMsg = "";
|
||||
accessLocation = "";
|
||||
accessWorktime = "";
|
||||
accessDateTime = "";
|
||||
});
|
||||
}
|
||||
Timer.periodic(const Duration(seconds: 5), (timer) {
|
||||
//print(DateTime.now());
|
||||
timer.cancel();
|
||||
result = "Üzemkész";
|
||||
accessName = "";
|
||||
accessMsg = "";
|
||||
accessLocation = "";
|
||||
accessWorktime = "";
|
||||
accessDateTime = "";
|
||||
setState(() {
|
||||
_showNFClogo = true;
|
||||
});
|
||||
});
|
||||
}, onDone: () {
|
||||
if (kDebugMode) {
|
||||
print("Done");
|
||||
}
|
||||
socket.destroy();
|
||||
});
|
||||
|
||||
//Send the request
|
||||
debugPrint("Request->$indexRequest");
|
||||
socket.write(indexRequest);
|
||||
//socket.write(enc);
|
||||
socket.flush();
|
||||
});
|
||||
}
|
||||
_login(rfid) {
|
||||
setState(() {
|
||||
_showNFClogo = false;
|
||||
});
|
||||
//DeviceInfo devInfo = _getDeviceInfo() as DeviceInfo;
|
||||
|
||||
String indexRequest = '{'
|
||||
'"cmd":"ACCESSNOGEO",'
|
||||
'"CID1":"${deviceData['id']}",'
|
||||
'"CID2":"${deviceData['device']} ${deviceData['brand']}",'
|
||||
'"address":"$_currentAddress",'
|
||||
'"rfid":"$rfid",'
|
||||
'"LAT":"${_currentLocation.latitude}",'
|
||||
'"LON":"${_currentLocation.longitude}",'
|
||||
'"mode":"GETAWAY"}';
|
||||
|
||||
debugPrint('Connecting...');
|
||||
//AESEncryption enc = new AESEncryption();
|
||||
//enc.encryptMsg(indexRequest);
|
||||
//connect to google port 80
|
||||
Socket.connect("iotechnic.eu", 8080).then((socket) {
|
||||
if (kDebugMode) {
|
||||
print('Connected to: '
|
||||
'${socket.remoteAddress.address}:${socket.remotePort}');
|
||||
}
|
||||
|
||||
//Establish the onData, and onDone callbacks
|
||||
socket.listen((data) {
|
||||
//print(new String.fromCharCodes(data).trim());
|
||||
var decoded = utf8.decode(data);
|
||||
//var jsonString = json.encode(new String.fromCharCodes(data).trim());
|
||||
Map<String, dynamic> resp = jsonDecode(decoded);
|
||||
debugPrint(decoded);
|
||||
debugPrint(resp['data']);
|
||||
getWorkState(employeePageArgs.apiKey as String);
|
||||
if (resp['data'] == 'VALID CODE') {
|
||||
setState(() {
|
||||
result = "";
|
||||
accessName = resp['employeeName'];
|
||||
accessMsg = resp['message'];
|
||||
accessLocation = resp['city'];
|
||||
accessWorktime = resp['worktime'];
|
||||
accessDateTime = resp['datetime'];
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
result = resp['data'];
|
||||
accessName = "";
|
||||
accessMsg = "";
|
||||
accessLocation = "";
|
||||
accessWorktime = "";
|
||||
accessDateTime = "";
|
||||
});
|
||||
}
|
||||
Timer.periodic(const Duration(seconds: 5), (timer) {
|
||||
//print(DateTime.now());
|
||||
timer.cancel();
|
||||
result = "Üzemkész";
|
||||
accessName = "";
|
||||
accessMsg = "";
|
||||
accessLocation = "";
|
||||
accessWorktime = "";
|
||||
accessDateTime = "";
|
||||
setState(() {
|
||||
_showNFClogo = true;
|
||||
});
|
||||
});
|
||||
}, onDone: () {
|
||||
if (kDebugMode) {
|
||||
print("Done");
|
||||
}
|
||||
socket.destroy();
|
||||
});
|
||||
|
||||
//Send the request
|
||||
debugPrint("Request->$indexRequest");
|
||||
socket.write(indexRequest);
|
||||
//socket.write(enc);
|
||||
socket.flush();
|
||||
});
|
||||
}
|
||||
|
||||
_getAddressFromLatLng(lat,lon) async {
|
||||
try {
|
||||
List<geocoding.Placemark> placemarks = await geocoding.placemarkFromCoordinates(
|
||||
//_currentPosition!.latitude, _currentPosition!.longitude);
|
||||
lat,lon);
|
||||
geocoding.Placemark place = placemarks[0];
|
||||
|
||||
setState(() {
|
||||
_currentAddress =
|
||||
"${place.locality}, ${place.thoroughfare}, ${place.subThoroughfare}";
|
||||
result = "Üzemkész";
|
||||
});
|
||||
} catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showAccessDeniedDialog() {
|
||||
return showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Hozzáférés elutasítva'),
|
||||
content: const Text('Az applikációs hozzáférése nincs engedélyezve!'),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
SystemNavigator.pop();
|
||||
},
|
||||
child: const Text('Kilépés')),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
void _tagRead() {
|
||||
const HexEncoder(upperCase: true);
|
||||
|
||||
//print(HEX.encode(const [1, 2, 3, 12]));
|
||||
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
|
||||
MifareClassic? nfca = MifareClassic.from(tag);
|
||||
String nfcResult = HEX.encode(nfca!.identifier).toUpperCase();
|
||||
if (kDebugMode) {
|
||||
print("TAG: $nfcResult");
|
||||
}
|
||||
_getLocation();
|
||||
|
||||
_login(nfcResult);
|
||||
//ag.data;
|
||||
/* setState(() {
|
||||
tagOk = true;
|
||||
});*/
|
||||
/* if (tagOk = true) {
|
||||
Future.delayed(Duration(milliseconds: 3000), () {
|
||||
setState(() {
|
||||
tagOk = false;
|
||||
});
|
||||
|
||||
NfcManager.instance.stopSession();
|
||||
});
|
||||
}*/
|
||||
});
|
||||
}
|
||||
showQRCode() {
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(
|
||||
20.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
contentPadding: const EdgeInsets.only(
|
||||
top: 10.0,
|
||||
),
|
||||
title: Text(
|
||||
"Státusz: $currentWorkState",
|
||||
style: const TextStyle(fontSize: 24.0),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
content: Container(
|
||||
//height: 400,
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
||||
child: qrdata.isNotEmpty ? QrImageView(
|
||||
data: qrdata,
|
||||
version: QrVersions.auto,
|
||||
size: 200.0,
|
||||
embeddedImageEmitsError: true,
|
||||
)
|
||||
: const Text('HIBA!'),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton(
|
||||
child: const Text('Bezár'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//var qrResult;
|
||||
/*return MaterialApp(
|
||||
theme: ThemeData(
|
||||
useMaterial3: true,
|
||||
colorSchemeSeed: const Color(0x9f4376f8),
|
||||
),*/
|
||||
//return
|
||||
// bool _positionIsMocked = _location?.isMock ?? false;//_currentPosition?.isMocked ?? false;
|
||||
return
|
||||
Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("Mobile Portal V$appCode$appVersion"),//_getAppBarTitle()),
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.qr_code),
|
||||
tooltip: 'Show Snackbar',
|
||||
onPressed: () {
|
||||
getWorkState(employeePageArgs.apiKey as String);
|
||||
getQRCode(employeePageArgs.apiKey as String);
|
||||
showQRCode();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
elevation: 4,
|
||||
),
|
||||
/* floatingActionButton: new Visibility(
|
||||
visible: _isScanVisible && _showNFClogo && _isApiKeyValid ,
|
||||
child: new FloatingActionButton.extended(
|
||||
icon: Icon(Icons.qr_code),
|
||||
label: Text("Beolvasás"),
|
||||
//onPressed: _scanQR,
|
||||
onPressed: () async {
|
||||
MobileScanner(
|
||||
// fit: BoxFit.contain,
|
||||
controller: MobileScannerController(
|
||||
detectionSpeed: DetectionSpeed.normal,
|
||||
facing: CameraFacing.front,
|
||||
torchEnabled: true,
|
||||
),
|
||||
onDetect: (capture) {
|
||||
final List<Barcode> barcodes = capture.barcodes;
|
||||
final Uint8List? image = capture.image;
|
||||
|
||||
for (final barcode in barcodes) {
|
||||
qrResult=barcode;
|
||||
debugPrint('Barcode found! ${barcode.rawValue}');
|
||||
}
|
||||
setState(() {
|
||||
if (qrResult is String) {
|
||||
//result = res;
|
||||
_login(qrResult);
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
},
|
||||
);
|
||||
}),//floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
),*/
|
||||
floatingActionButton: Visibility(
|
||||
visible: _isScanVisible && _showNFClogo && _isApiKeyValid ,
|
||||
child: FloatingActionButton.extended(
|
||||
icon: const Icon(Icons.qr_code),
|
||||
label: const Text("Beolvasás"),
|
||||
//onPressed: _scanQR,
|
||||
onPressed: () async {
|
||||
var qrResult = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SimpleBarcodeScannerPage(),
|
||||
));
|
||||
setState(() {
|
||||
if (qrResult is String) {
|
||||
//result = res;
|
||||
_loginQR(qrResult);
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
//floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
),
|
||||
body:
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(14.0),
|
||||
child: _initOK
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 1,
|
||||
//fit: FlexFit.tight,
|
||||
child:
|
||||
SizedBox(
|
||||
//width: 300,
|
||||
height: 50,
|
||||
//color: Colors.amber,
|
||||
child:
|
||||
Column(
|
||||
children: <Widget>[
|
||||
Text(currentWorkState),
|
||||
Text(currentQRcode.name as String,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 2,
|
||||
fit: FlexFit.tight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 1,
|
||||
fit: FlexFit.tight,
|
||||
child: Container(
|
||||
width: 200,
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
//borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.indigo[600],
|
||||
), //BoxDecoration
|
||||
child: Transform.scale(
|
||||
scale: 2,
|
||||
child: CustomIconButton(
|
||||
icon: const Icon(Icons.pending_actions),
|
||||
isDisabled: _isApiKeyValid == false,
|
||||
color: _isScanVisible ||
|
||||
!_isLocationMocked ||
|
||||
_isApiKeyValid == true
|
||||
? Colors.indigo[600]!
|
||||
: Colors.grey.shade50,
|
||||
onPressed: () {
|
||||
if (_isApiKeyValid == true) {
|
||||
Navigator.pushNamed(context, '/wtdetails',
|
||||
arguments: {
|
||||
'userArgs': employeePageArgs,
|
||||
'dataArgs': null
|
||||
});
|
||||
}
|
||||
}),
|
||||
),
|
||||
), //Container
|
||||
), //Flexible
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
), //SizedBox
|
||||
Flexible(
|
||||
flex: 1,
|
||||
fit: FlexFit.tight,
|
||||
child: Container(
|
||||
width: 200,
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
//borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.indigo[600],
|
||||
),
|
||||
child: Transform.scale(
|
||||
scale: 2,
|
||||
child: CustomIconButton(
|
||||
icon: const Icon(Icons.list),
|
||||
isDisabled: _reportButtonDisabled ||
|
||||
_isApiKeyValid == false,
|
||||
color: Colors.indigo[600]!,
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/reportNav',
|
||||
arguments: {
|
||||
'userArgs': employeePageArgs,
|
||||
'dataArgs': null
|
||||
});
|
||||
//WorkTimeDetails()));
|
||||
},
|
||||
), //BoxDecoration
|
||||
), //Container
|
||||
),
|
||||
) //Flexible
|
||||
],
|
||||
), //Row
|
||||
),
|
||||
|
||||
/*const SizedBox(
|
||||
height: 5,
|
||||
),*/ //SixedBox
|
||||
Flexible(
|
||||
flex: 4,
|
||||
fit: FlexFit.tight,
|
||||
child: Container(
|
||||
width: 380,
|
||||
height: 200,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.blue), //BoxDecoration
|
||||
child: _isApiKeyValid == true
|
||||
? Column(
|
||||
children: <Widget>[
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
if (!_isLocationValid) ...[
|
||||
//Text("Várakozás heladatokra..."),
|
||||
const CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
if (!_isScanVisible) ...[
|
||||
TextButton(
|
||||
child: const Text(
|
||||
"Várakozás heladatokra...",
|
||||
style: TextStyle(
|
||||
fontSize: 24.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
_getLocation();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const Icon(
|
||||
Icons.location_on_outlined,
|
||||
size: 64,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
if (_isScanVisible && !_showNFClogo)
|
||||
Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
accessName,
|
||||
style: const TextStyle(
|
||||
fontSize: 30.0,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
Text(
|
||||
accessMsg,
|
||||
style: const TextStyle(
|
||||
fontSize: 30.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
accessDateTime,
|
||||
style: const TextStyle(
|
||||
fontSize: 30.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
accessWorktime,
|
||||
style: const TextStyle(
|
||||
fontSize: 30.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
accessLocation,
|
||||
style: const TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
]),
|
||||
if (_isScanVisible) ...[
|
||||
Text(
|
||||
result,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 30.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
if (_showNFClogo)
|
||||
nfcLogo()
|
||||
],
|
||||
],
|
||||
)
|
||||
: const Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Hozzáférés nem engedélyezett!',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 30.0,
|
||||
fontWeight: FontWeight.bold),
|
||||
|
||||
),
|
||||
],
|
||||
)), //Container
|
||||
), //Flexible
|
||||
|
||||
],
|
||||
)
|
||||
: Container(
|
||||
alignment: Alignment.topCenter,
|
||||
margin: const EdgeInsets.only(top: 20),
|
||||
child: const CircularProgressIndicator(
|
||||
value: 0.8,
|
||||
)) //Column
|
||||
)
|
||||
|
||||
); //Padding
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(_getAppBarTitle()),
|
||||
elevation: 4,
|
||||
),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Location: ${_error ?? '${_location ?? "unknown"}'}',
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
ElevatedButton(
|
||||
onPressed: _getLocation,
|
||||
child: _loading
|
||||
? const CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
)
|
||||
: const Text('Get'),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
);*/
|
||||
// );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
/*
|
||||
class Employee {
|
||||
final String id;
|
||||
final String name;
|
||||
//final bool value;
|
||||
Employee({
|
||||
@required this.id,
|
||||
@required this.name,
|
||||
//@required this.value,
|
||||
});
|
||||
|
||||
factory Employee.fromJson(Map<String, dynamic> json) {
|
||||
return Employee(
|
||||
id: json['_id'] as String,
|
||||
name: json['name'] as String,
|
||||
//value: json['value'] as bool,
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
class EmployeeLs {
|
||||
String id;
|
||||
String name;
|
||||
bool value;
|
||||
EmployeeLs({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.value,
|
||||
});
|
||||
|
||||
factory EmployeeLs.fromJson(Map<String, dynamic> json) {
|
||||
return EmployeeLs(
|
||||
id: json['_id'] as String,
|
||||
name: json['name'] as String,
|
||||
value: json['value'] ?? false //as bool,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WorkLs {
|
||||
String id;
|
||||
String title;
|
||||
String body;
|
||||
String state;
|
||||
//bool value;
|
||||
WorkLs({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.body,
|
||||
required this.state,
|
||||
// @required this.value,
|
||||
});
|
||||
@override
|
||||
String toString() {
|
||||
return '$title ';
|
||||
}
|
||||
|
||||
factory WorkLs.fromJson(Map<String, dynamic> json) {
|
||||
return WorkLs(
|
||||
id: json['_id'] as String,
|
||||
title: json['title'] as String,
|
||||
body: json['body'] as String,
|
||||
state: json['state'] as String,
|
||||
// value: json['value'] as bool,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
|
||||
class ModelReportList {
|
||||
String? sId;
|
||||
String? title;
|
||||
String? body;
|
||||
String? poNumber;
|
||||
String? workNumber;
|
||||
String? state;
|
||||
late List<DailyReport> dailyReport;
|
||||
|
||||
ModelReportList(
|
||||
{required this.sId,
|
||||
required this.title,
|
||||
required this.body,
|
||||
required this.poNumber,
|
||||
required this.workNumber,
|
||||
required this.state,
|
||||
required this.dailyReport});
|
||||
|
||||
ModelReportList.fromJson(Map<String, dynamic> json) {
|
||||
sId = json['_id'];
|
||||
title = json['title'];
|
||||
body = json['body'];
|
||||
poNumber = json['poNumber'];
|
||||
workNumber = json['workNumber'];
|
||||
state = json['state'];
|
||||
if (json['dailyReport'] != null) {
|
||||
dailyReport = <DailyReport>[];
|
||||
json['dailyReport'].forEach((v) {
|
||||
dailyReport.add(DailyReport.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['_id'] = sId;
|
||||
data['title'] = title;
|
||||
data['body'] = body;
|
||||
data['poNumber'] = poNumber;
|
||||
data['workNumber'] = workNumber;
|
||||
data['state'] = state;
|
||||
data['dailyReport'] = dailyReport.map((v) => v.toJson()).toList();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class DailyReport {
|
||||
late List<String> employeeList;
|
||||
String? sId;
|
||||
String? date;
|
||||
String? foremanId;
|
||||
String? workTitle;
|
||||
|
||||
DailyReport(
|
||||
{required this.employeeList,
|
||||
required this.sId,
|
||||
required this.date,
|
||||
required this.foremanId,
|
||||
required this.workTitle});
|
||||
|
||||
DailyReport.fromJson(Map<String, dynamic> json) {
|
||||
employeeList = json['employeeList'].cast<String>();
|
||||
sId = json['_id'];
|
||||
date = json['date'];
|
||||
foremanId = json['foremanId'];
|
||||
workTitle = json['workTitle'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['employeeList'] = employeeList;
|
||||
data['_id'] = sId;
|
||||
data['date'] = date;
|
||||
data['foremanId'] = foremanId;
|
||||
data['workTitle'] = workTitle;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class WorkListModel {
|
||||
String? _sId;
|
||||
String? _title;
|
||||
String? _body;
|
||||
String? _poNumber;
|
||||
String? _workNumber;
|
||||
String? _state;
|
||||
|
||||
WorkListModel(
|
||||
{String? sId,
|
||||
String? title,
|
||||
String? body,
|
||||
String? poNumber,
|
||||
String? workNumber,
|
||||
String? state}) {
|
||||
if (sId != null) {
|
||||
_sId = sId;
|
||||
}
|
||||
if (title != null) {
|
||||
_title = title;
|
||||
}
|
||||
if (body != null) {
|
||||
_body = body;
|
||||
}
|
||||
if (poNumber != null) {
|
||||
_poNumber = poNumber;
|
||||
}
|
||||
if (workNumber != null) {
|
||||
_workNumber = workNumber;
|
||||
}
|
||||
if (state != null) {
|
||||
_state = state;
|
||||
}
|
||||
}
|
||||
|
||||
String? get sId => _sId;
|
||||
set sId(String? sId) => _sId = sId;
|
||||
String? get title => _title;
|
||||
set title(String? title) => _title = title;
|
||||
String? get body => _body;
|
||||
set body(String? body) => _body = body;
|
||||
String? get poNumber => _poNumber;
|
||||
set poNumber(String? poNumber) => _poNumber = poNumber;
|
||||
String? get workNumber => _workNumber;
|
||||
set workNumber(String? workNumber) => _workNumber = workNumber;
|
||||
String? get state => _state;
|
||||
set state(String? state) => _state = state;
|
||||
|
||||
WorkListModel.fromJson(Map<String, dynamic> json) {
|
||||
_sId = json['_id'];
|
||||
_title = json['title'];
|
||||
_body = json['body'];
|
||||
_poNumber = json['poNumber'];
|
||||
_workNumber = json['workNumber'];
|
||||
_state = json['state'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['_id'] = _sId;
|
||||
data['title'] = _title;
|
||||
data['body'] = _body;
|
||||
data['poNumber'] = _poNumber;
|
||||
data['workNumber'] = _workNumber;
|
||||
data['state'] = _state;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
|
||||
class WorkTimeDetailsModel {
|
||||
final List<Wd>? wd;
|
||||
final List<dynamic>? munkaszunet;
|
||||
final Month? month;
|
||||
final Weekend? weekend;
|
||||
|
||||
WorkTimeDetailsModel({
|
||||
this.wd,
|
||||
this.munkaszunet,
|
||||
this.month,
|
||||
this.weekend,
|
||||
});
|
||||
|
||||
WorkTimeDetailsModel.fromJson(Map<String, dynamic> json)
|
||||
: wd = (json['wd'] as List?)
|
||||
?.map((dynamic e) => Wd.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
munkaszunet = json['munkaszunet'] as List?,
|
||||
month = (json['month'] as Map<String, dynamic>?) != null
|
||||
? Month.fromJson(json['month'] as Map<String, dynamic>)
|
||||
: null,
|
||||
weekend = (json['weekend'] as Map<String, dynamic>?) != null
|
||||
? Weekend.fromJson(json['weekend'] as Map<String, dynamic>)
|
||||
: null;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'wd': wd?.map((e) => e.toJson()).toList(),
|
||||
'munkaszunet': munkaszunet,
|
||||
'month': month?.toJson(),
|
||||
'weekend': weekend?.toJson()
|
||||
};
|
||||
}
|
||||
|
||||
class Wd {
|
||||
final String? date;
|
||||
final bool? isMunkaszunet;
|
||||
final bool? isHoliday;
|
||||
final bool? isWeekend;
|
||||
final String? location;
|
||||
final String? notes;
|
||||
final List<StartStop>? startStop;
|
||||
final int? fullHours;
|
||||
final int? hours;
|
||||
final int? overTime;
|
||||
|
||||
Wd({
|
||||
this.date,
|
||||
this.isMunkaszunet,
|
||||
this.isHoliday,
|
||||
this.isWeekend,
|
||||
this.location,
|
||||
this.notes,
|
||||
this.startStop,
|
||||
this.fullHours,
|
||||
this.hours,
|
||||
this.overTime,
|
||||
});
|
||||
|
||||
Wd.fromJson(Map<String, dynamic> json)
|
||||
: date = json['date'] as String?,
|
||||
isMunkaszunet = json['isMunkaszunet'] as bool?,
|
||||
isHoliday = json['isHoliday'] as bool?,
|
||||
isWeekend = json['isWeekend'] as bool?,
|
||||
location = json['location'] as String?,
|
||||
notes = json['notes'] as String?,
|
||||
startStop = (json['startStop'] as List?)
|
||||
?.map((dynamic e) => StartStop.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
fullHours = json['fullHours'] as int?,
|
||||
hours = json['hours'] as int?,
|
||||
overTime = json['overTime'] as int?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'date': date,
|
||||
'isMunkaszunet': isMunkaszunet,
|
||||
'isHoliday': isHoliday,
|
||||
'isWeekend': isWeekend,
|
||||
'location': location,
|
||||
'notes': notes,
|
||||
'startStop': startStop?.map((e) => e.toJson()).toList(),
|
||||
'fullHours': fullHours,
|
||||
'hours': hours,
|
||||
'overTime': overTime
|
||||
};
|
||||
}
|
||||
|
||||
class StartStop {
|
||||
final String? start;
|
||||
final String? stop;
|
||||
final String? arriveLoc;
|
||||
final String? getawayLoc;
|
||||
final ArriveCoords? arriveCoords;
|
||||
final GetavayCoords? getavayCoords;
|
||||
|
||||
StartStop({
|
||||
this.start,
|
||||
this.stop,
|
||||
this.arriveLoc,
|
||||
this.getawayLoc,
|
||||
this.arriveCoords,
|
||||
this.getavayCoords,
|
||||
});
|
||||
|
||||
StartStop.fromJson(Map<String, dynamic> json)
|
||||
: start = json['start'] as String?,
|
||||
stop = json['stop'] as String?,
|
||||
arriveLoc = json['arriveLoc'] as String?,
|
||||
getawayLoc = json['getawayLoc'] as String?,
|
||||
arriveCoords = (json['arriveCoords'] as Map<String, dynamic>?) != null
|
||||
? ArriveCoords.fromJson(
|
||||
json['arriveCoords'] as Map<String, dynamic>)
|
||||
: null,
|
||||
getavayCoords = (json['getavayCoords'] as Map<String, dynamic>?) != null
|
||||
? GetavayCoords.fromJson(
|
||||
json['getavayCoords'] as Map<String, dynamic>)
|
||||
: null;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'start': start,
|
||||
'stop': stop,
|
||||
'arriveLoc': arriveLoc,
|
||||
'getawayLoc': getawayLoc,
|
||||
'arriveCoords': arriveCoords?.toJson(),
|
||||
'getavayCoords': getavayCoords?.toJson()
|
||||
};
|
||||
}
|
||||
|
||||
class ArriveCoords {
|
||||
late final double? lat;
|
||||
late final double? lon;
|
||||
|
||||
ArriveCoords({
|
||||
this.lat,
|
||||
this.lon,
|
||||
});
|
||||
|
||||
ArriveCoords.fromJson(Map<String, dynamic> json) {
|
||||
if (json.isNotEmpty &&
|
||||
json['lat'] != null &&
|
||||
json['lon'] != null &&
|
||||
json['lat'] != 0 &&
|
||||
json['lon'] != 0) {
|
||||
lat = (json['lat'] as double).toDouble();
|
||||
lon = (json['lon'] as double).toDouble();
|
||||
} else {
|
||||
lat = 0.0;
|
||||
lon = 0.0;
|
||||
}
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'lat': lat, 'lon': lon};
|
||||
}
|
||||
|
||||
class GetavayCoords {
|
||||
late final double? lat;
|
||||
late final double? lon;
|
||||
|
||||
GetavayCoords({
|
||||
this.lat,
|
||||
this.lon,
|
||||
});
|
||||
|
||||
GetavayCoords.fromJson(Map<String, dynamic> json) {
|
||||
if (json.isNotEmpty &&
|
||||
json['lat'] != null &&
|
||||
json['lon'] != null &&
|
||||
json['lat'] != 0 &&
|
||||
json['lon'] != 0) {
|
||||
lat = (json['lat'] as double).toDouble();
|
||||
lon = (json['lon'] as double).toDouble();
|
||||
} else {
|
||||
lat = 0.0;
|
||||
lon = 0.0;
|
||||
}
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'lat': lat, 'lon': lon};
|
||||
}
|
||||
|
||||
class Month {
|
||||
final int? overTime;
|
||||
final int? workHours;
|
||||
final int? fullWorkHours;
|
||||
|
||||
Month({
|
||||
this.overTime,
|
||||
this.workHours,
|
||||
this.fullWorkHours,
|
||||
});
|
||||
|
||||
Month.fromJson(Map<String, dynamic> json)
|
||||
: overTime = json['overTime'] as int?,
|
||||
workHours = json['workHours'] as int?,
|
||||
fullWorkHours = json['fullWorkHours'] as int?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'overTime': overTime,
|
||||
'workHours': workHours,
|
||||
'fullWorkHours': fullWorkHours
|
||||
};
|
||||
}
|
||||
|
||||
class Weekend {
|
||||
final Saturday? saturday;
|
||||
final Sunday? sunday;
|
||||
|
||||
Weekend({
|
||||
this.saturday,
|
||||
this.sunday,
|
||||
});
|
||||
|
||||
Weekend.fromJson(Map<String, dynamic> json)
|
||||
: saturday = (json['Saturday'] as Map<String, dynamic>?) != null
|
||||
? Saturday.fromJson(json['Saturday'] as Map<String, dynamic>)
|
||||
: null,
|
||||
sunday = (json['Sunday'] as Map<String, dynamic>?) != null
|
||||
? Sunday.fromJson(json['Sunday'] as Map<String, dynamic>)
|
||||
: null;
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'Saturday': saturday?.toJson(), 'Sunday': sunday?.toJson()};
|
||||
}
|
||||
|
||||
class Saturday {
|
||||
final int? overTime;
|
||||
final int? workHours;
|
||||
final int? fullWorkHours;
|
||||
final int? days;
|
||||
|
||||
Saturday({
|
||||
this.overTime,
|
||||
this.workHours,
|
||||
this.fullWorkHours,
|
||||
this.days,
|
||||
});
|
||||
|
||||
Saturday.fromJson(Map<String, dynamic> json)
|
||||
: overTime = json['overTime'] as int?,
|
||||
workHours = json['workHours'] as int?,
|
||||
fullWorkHours = json['fullWorkHours'] as int?,
|
||||
days = json['days'] as int?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'overTime': overTime,
|
||||
'workHours': workHours,
|
||||
'fullWorkHours': fullWorkHours,
|
||||
'days': days
|
||||
};
|
||||
}
|
||||
|
||||
class Sunday {
|
||||
final int? overTime;
|
||||
final int? workHours;
|
||||
final int? fullWorkHours;
|
||||
final int? days;
|
||||
|
||||
Sunday({
|
||||
this.overTime,
|
||||
this.workHours,
|
||||
this.fullWorkHours,
|
||||
this.days,
|
||||
});
|
||||
|
||||
Sunday.fromJson(Map<String, dynamic> json)
|
||||
: overTime = json['overTime'] as int?,
|
||||
workHours = json['workHours'] as int?,
|
||||
fullWorkHours = json['fullWorkHours'] as int?,
|
||||
days = json['days'] as int?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'overTime': overTime,
|
||||
'workHours': workHours,
|
||||
'fullWorkHours': fullWorkHours,
|
||||
'days': days
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
//import 'dart:js_interop';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
//import 'package:mobile_portal_23/services/device_info.dart';
|
||||
//import 'services/storage.dart' as storage;
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
//import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'services/storage.dart' as storage;
|
||||
import 'dart:convert';
|
||||
import 'classes/named_route_args.dart';
|
||||
//import 'dart:developer';
|
||||
|
||||
class RegisterPage extends StatefulWidget {
|
||||
const RegisterPage({Key? key}) : super(key: key);
|
||||
static const routeName = '/register';
|
||||
@override
|
||||
State<RegisterPage> createState() => _RegisterPageState();
|
||||
}
|
||||
String appDomain = "iotechnic.eu";
|
||||
class _RegisterPageState extends State<RegisterPage> {
|
||||
final usernameTxtController = TextEditingController();
|
||||
final passwordTxtController = TextEditingController();
|
||||
//Map<String, dynamic> _deviceData = <String, dynamic>{};
|
||||
// Eszköz regisztráció
|
||||
Future deviceRegistration(String userName, String password) async {
|
||||
storage.SecureStorage sc= storage.SecureStorage();
|
||||
//final DeviceInfo deviceInfo =
|
||||
/* _deviceData=
|
||||
ModalRoute.of(context)!.settings.arguments as Map<String,dynamic>;*/
|
||||
final args=ModalRoute.of(context)!.settings.arguments as DeviceArguments;
|
||||
|
||||
var url = "http://$appDomain/apiRegisterDevice";
|
||||
var report = {
|
||||
'deviceId': args.Id,
|
||||
'username': userName,
|
||||
'password': password,
|
||||
'deviceType': '${args.Name} ${args.Brand}'
|
||||
};
|
||||
//log('data: $report');
|
||||
final response = await http.post(
|
||||
Uri.parse(url),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: jsonEncode(report),
|
||||
);
|
||||
|
||||
|
||||
if (response.statusCode == 404) {
|
||||
var resp = jsonDecode(response.body);
|
||||
//log('resp:'+ resp['message']);
|
||||
EasyLoading.showError(resp['message']);
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
// Navigator.pop(context); //pop dialog
|
||||
EasyLoading.dismiss();
|
||||
|
||||
// Navigator.of(context).pop();
|
||||
//_login();
|
||||
});
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
var resp = jsonDecode(response.body);
|
||||
if (resp['apiKey']==null)
|
||||
{
|
||||
EasyLoading.showError(resp['message']);
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
// Navigator.pop(context); //pop dialog
|
||||
EasyLoading.dismiss();
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
EasyLoading.showSuccess(resp['message']);
|
||||
sc.writeSecureData("API", resp['apiKey']);
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
// Navigator.pop(context); //pop dialog
|
||||
EasyLoading.dismiss();
|
||||
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
}
|
||||
// _saveApiKey(resp['apiKey']);
|
||||
|
||||
//_login();
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
//return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
usernameTxtController.dispose();
|
||||
passwordTxtController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
title: const Text("Eszköz regisztráció"),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 60.0),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 200,
|
||||
height: 150,
|
||||
/*decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
borderRadius: BorderRadius.circular(50.0)),*/
|
||||
child: Image.asset('assets/cloudlogo.png')),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: TextField(
|
||||
controller: usernameTxtController,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Teljes név',
|
||||
hintText: 'Teljes név pl.: Gipsz Jakab'),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
||||
//padding: EdgeInsets.symmetric(horizontal: 15),
|
||||
child: TextField(
|
||||
controller: passwordTxtController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Jelszó',
|
||||
hintText: 'Adja meg KL portal jelszavát!'),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: (){
|
||||
//TODO FORGOT PASSWORD SCREEN GOES HERE
|
||||
},
|
||||
child: const Text(
|
||||
'Forgot Password',
|
||||
style: TextStyle(color: Colors.blue, fontSize: 15),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
width: 250,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.orange, borderRadius: BorderRadius.circular(20)),
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
if(usernameTxtController.text.isNotEmpty && passwordTxtController.text.isNotEmpty)
|
||||
{ deviceRegistration(usernameTxtController.text, passwordTxtController.text);}
|
||||
/*Navigator.pop(
|
||||
context);*/
|
||||
},
|
||||
child: const Text(
|
||||
'Belépés',
|
||||
style: TextStyle(color: Colors.white, fontSize: 25),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobile_portal_23/widgets/reportNew.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class reportCreate extends StatefulWidget {
|
||||
static const routeName = '/reportCreate';
|
||||
const reportCreate({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<reportCreate> createState() => _reportCreateState();
|
||||
}
|
||||
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
|
||||
class _reportCreateState extends State<reportCreate> {
|
||||
String appDomain = "iotechnic.eu";
|
||||
// String? userApiKey; // = "XST8X8F-6Q9M1FG-PE9948X-SPFHVX9";
|
||||
//late List<ModelReportList> reportList = [];
|
||||
|
||||
late List<WorkListModel> workList = [];
|
||||
Future<void> _saveFavoriteWorks(List<String> favoriteWorks) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setStringList('favoriteWorks', favoriteWorks);
|
||||
}
|
||||
|
||||
Future<void> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// userApiKey = prefs.getString("apiKey");
|
||||
favoriteWorks = prefs.getStringList("favoriteWorks") ?? [];
|
||||
}
|
||||
|
||||
Future fetchdata() async {
|
||||
var res = await http.get(
|
||||
|
||||
// "http://iotechnic.eu/apiGetAllReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
Uri.parse("http://$appDomain/apiGetAllWork/${employeePageArguments.apiKey!}"));
|
||||
//"http://192.168.0.144/apiGetDailyReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
late List<String> favoriteWorks = [];
|
||||
final bool _showFaworites = false;
|
||||
// late EmployeeArguments empArgs;
|
||||
bool _isError = false;
|
||||
bool _isData = false;
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
});
|
||||
getSharedPrefs().then((value) {
|
||||
fetchdata().then((data) {
|
||||
if (data != null) {
|
||||
for (var item in data) {
|
||||
// reportList.add(ModelReportList.fromJson(item));
|
||||
workList.add(WorkListModel.fromJson(item));
|
||||
}
|
||||
_isData = true;
|
||||
setState(() {
|
||||
debugPrint('Fetch ok.');
|
||||
});
|
||||
} else {
|
||||
_isError = true;
|
||||
}
|
||||
//employeeList = data;
|
||||
/* empArgs = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as EmployeeArguments;*/
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Új jelentés')), body: page(context));
|
||||
}
|
||||
|
||||
Container page(BuildContext context) {
|
||||
return _isData == false
|
||||
? _isError
|
||||
? Container(
|
||||
child: const AlertDialog(
|
||||
title: Text('Hálózati Hiba!'),
|
||||
content: Icon(Icons.error_outline),
|
||||
elevation: 24,
|
||||
backgroundColor: Colors.red),
|
||||
)
|
||||
: Container(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 1.3,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
))
|
||||
: gridList(context);
|
||||
}
|
||||
|
||||
Container gridList(BuildContext context) {
|
||||
//List<ModelReportList> _reportList = [];
|
||||
List<WorkListModel> workList = [];
|
||||
if (_showFaworites) {
|
||||
workList = workList
|
||||
.where((element) => favoriteWorks.contains(element.sId))
|
||||
.toList();
|
||||
} else {
|
||||
workList = workList;
|
||||
}
|
||||
return Container(
|
||||
color: const Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: workList.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: reportCard(context, workList[index]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Card reportCard(BuildContext context, WorkListModel item) {
|
||||
int workHour = 0;
|
||||
bool workOpened = false;
|
||||
bool isFaworite = favoriteWorks.contains(item.sId);
|
||||
if (item.state!.contains("Opened")) workOpened = true;
|
||||
/* item.dailyReport.forEach((element) {
|
||||
workHour += element.employeeList.length;
|
||||
});*/
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
tileColor: workOpened ? Colors.indigo : Colors.grey,
|
||||
trailing: IconButton(
|
||||
onPressed: () {
|
||||
if (isFaworite) {
|
||||
favoriteWorks.remove(item.sId);
|
||||
} else {
|
||||
String? id = item.sId;
|
||||
favoriteWorks.add(id!);
|
||||
}
|
||||
_saveFavoriteWorks(favoriteWorks);
|
||||
},
|
||||
icon: isFaworite
|
||||
? Icon(
|
||||
Icons.star,
|
||||
color: favoriteWorks.contains(item.sId)
|
||||
? Colors.yellow
|
||||
: null,
|
||||
)
|
||||
: const Icon(Icons.star_border)),
|
||||
onTap: workOpened
|
||||
? () {
|
||||
ReportArguments reportArgs = ReportArguments(
|
||||
List.empty(),
|
||||
//userApiKey!,
|
||||
item.title!,
|
||||
item.sId!,
|
||||
item.state == "Opened" ? true : false,
|
||||
//empArgs.isForeman!
|
||||
);
|
||||
|
||||
Navigator.pushNamed(context, reportNew.routeName,
|
||||
arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': reportArgs
|
||||
});
|
||||
}
|
||||
: null,
|
||||
title: Text(
|
||||
item.title!,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
/*subtitle: Text(
|
||||
item.body!,
|
||||
style: TextStyle(color: Colors.yellow.withOpacity(0.6)),
|
||||
),*/
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Text(
|
||||
item.body!.replaceAll("\n", " "),
|
||||
style: TextStyle(color: Colors.green.withOpacity(0.6)),
|
||||
),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Row(children: [
|
||||
|
||||
Text(
|
||||
'KL${item.workNumber!}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
const VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'PO: ${item.poNumber!}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]),
|
||||
]))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
|
||||
class DeviceInfo{
|
||||
static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
|
||||
|
||||
|
||||
Future<Map<String, dynamic>> initPlatformState() async {
|
||||
var deviceData = <String, dynamic>{};
|
||||
|
||||
try {
|
||||
if (kIsWeb) {
|
||||
deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo);
|
||||
} else {
|
||||
deviceData = switch (defaultTargetPlatform) {
|
||||
TargetPlatform.android =>
|
||||
_readAndroidBuildData(await deviceInfoPlugin.androidInfo),
|
||||
TargetPlatform.iOS =>
|
||||
_readIosDeviceInfo(await deviceInfoPlugin.iosInfo),
|
||||
TargetPlatform.linux =>
|
||||
_readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo),
|
||||
TargetPlatform.windows =>
|
||||
_readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo),
|
||||
TargetPlatform.macOS =>
|
||||
_readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo),
|
||||
TargetPlatform.fuchsia => <String, dynamic>{
|
||||
'Error:': 'Fuchsia platform isn\'t supported'
|
||||
},
|
||||
};
|
||||
}
|
||||
return deviceData;
|
||||
} on PlatformException {
|
||||
deviceData = <String, dynamic>{
|
||||
'Error:': 'Failed to get platform version.'
|
||||
};
|
||||
return deviceData;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
|
||||
return <String, dynamic>{
|
||||
'version.securityPatch': build.version.securityPatch,
|
||||
'version.sdkInt': build.version.sdkInt,
|
||||
'version.release': build.version.release,
|
||||
'version.previewSdkInt': build.version.previewSdkInt,
|
||||
'version.incremental': build.version.incremental,
|
||||
'version.codename': build.version.codename,
|
||||
'version.baseOS': build.version.baseOS,
|
||||
'board': build.board,
|
||||
'bootloader': build.bootloader,
|
||||
'brand': build.brand,
|
||||
'device': build.device,
|
||||
'display': build.display,
|
||||
'fingerprint': build.fingerprint,
|
||||
'hardware': build.hardware,
|
||||
'host': build.host,
|
||||
'id': build.id,
|
||||
'manufacturer': build.manufacturer,
|
||||
'model': build.model,
|
||||
'product': build.product,
|
||||
'supported32BitAbis': build.supported32BitAbis,
|
||||
'supported64BitAbis': build.supported64BitAbis,
|
||||
'supportedAbis': build.supportedAbis,
|
||||
'tags': build.tags,
|
||||
'type': build.type,
|
||||
'isPhysicalDevice': build.isPhysicalDevice,
|
||||
'systemFeatures': build.systemFeatures,
|
||||
'displaySizeInches':
|
||||
((build.displayMetrics.sizeInches * 10).roundToDouble() / 10),
|
||||
'displayWidthPixels': build.displayMetrics.widthPx,
|
||||
'displayWidthInches': build.displayMetrics.widthInches,
|
||||
'displayHeightPixels': build.displayMetrics.heightPx,
|
||||
'displayHeightInches': build.displayMetrics.heightInches,
|
||||
'displayXDpi': build.displayMetrics.xDpi,
|
||||
'displayYDpi': build.displayMetrics.yDpi,
|
||||
'serialNumber': build.serialNumber,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> _readIosDeviceInfo(IosDeviceInfo data) {
|
||||
return <String, dynamic>{
|
||||
'name': data.name,
|
||||
'systemName': data.systemName,
|
||||
'systemVersion': data.systemVersion,
|
||||
'model': data.model,
|
||||
'localizedModel': data.localizedModel,
|
||||
'identifierForVendor': data.identifierForVendor,
|
||||
'isPhysicalDevice': data.isPhysicalDevice,
|
||||
'utsname.sysname:': data.utsname.sysname,
|
||||
'utsname.nodename:': data.utsname.nodename,
|
||||
'utsname.release:': data.utsname.release,
|
||||
'utsname.version:': data.utsname.version,
|
||||
'utsname.machine:': data.utsname.machine,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> _readLinuxDeviceInfo(LinuxDeviceInfo data) {
|
||||
return <String, dynamic>{
|
||||
'name': data.name,
|
||||
'version': data.version,
|
||||
'id': data.id,
|
||||
'idLike': data.idLike,
|
||||
'versionCodename': data.versionCodename,
|
||||
'versionId': data.versionId,
|
||||
'prettyName': data.prettyName,
|
||||
'buildId': data.buildId,
|
||||
'variant': data.variant,
|
||||
'variantId': data.variantId,
|
||||
'machineId': data.machineId,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> _readWebBrowserInfo(WebBrowserInfo data) {
|
||||
return <String, dynamic>{
|
||||
'browserName': data.browserName,
|
||||
'appCodeName': data.appCodeName,
|
||||
'appName': data.appName,
|
||||
'appVersion': data.appVersion,
|
||||
'deviceMemory': data.deviceMemory,
|
||||
'language': data.language,
|
||||
'languages': data.languages,
|
||||
'platform': data.platform,
|
||||
'product': data.product,
|
||||
'productSub': data.productSub,
|
||||
'userAgent': data.userAgent,
|
||||
'vendor': data.vendor,
|
||||
'vendorSub': data.vendorSub,
|
||||
'hardwareConcurrency': data.hardwareConcurrency,
|
||||
'maxTouchPoints': data.maxTouchPoints,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> _readMacOsDeviceInfo(MacOsDeviceInfo data) {
|
||||
return <String, dynamic>{
|
||||
'computerName': data.computerName,
|
||||
'hostName': data.hostName,
|
||||
'arch': data.arch,
|
||||
'model': data.model,
|
||||
'kernelVersion': data.kernelVersion,
|
||||
'majorVersion': data.majorVersion,
|
||||
'minorVersion': data.minorVersion,
|
||||
'patchVersion': data.patchVersion,
|
||||
'osRelease': data.osRelease,
|
||||
'activeCPUs': data.activeCPUs,
|
||||
'memorySize': data.memorySize,
|
||||
'cpuFrequency': data.cpuFrequency,
|
||||
'systemGUID': data.systemGUID,
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> _readWindowsDeviceInfo(WindowsDeviceInfo data) {
|
||||
return <String, dynamic>{
|
||||
'numberOfCores': data.numberOfCores,
|
||||
'computerName': data.computerName,
|
||||
'systemMemoryInMegabytes': data.systemMemoryInMegabytes,
|
||||
'userName': data.userName,
|
||||
'majorVersion': data.majorVersion,
|
||||
'minorVersion': data.minorVersion,
|
||||
'buildNumber': data.buildNumber,
|
||||
'platformId': data.platformId,
|
||||
'csdVersion': data.csdVersion,
|
||||
'servicePackMajor': data.servicePackMajor,
|
||||
'servicePackMinor': data.servicePackMinor,
|
||||
'suitMask': data.suitMask,
|
||||
'productType': data.productType,
|
||||
'reserved': data.reserved,
|
||||
'buildLab': data.buildLab,
|
||||
'buildLabEx': data.buildLabEx,
|
||||
'digitalProductId': data.digitalProductId,
|
||||
'displayVersion': data.displayVersion,
|
||||
'editionId': data.editionId,
|
||||
'installDate': data.installDate,
|
||||
'productId': data.productId,
|
||||
'productName': data.productName,
|
||||
'registeredOwner': data.registeredOwner,
|
||||
'releaseId': data.releaseId,
|
||||
'deviceId': data.deviceId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
|
||||
class SecureStorage {
|
||||
final FlutterSecureStorage storage = const FlutterSecureStorage();
|
||||
|
||||
writeSecureData(String key, String value) async {
|
||||
await storage.write(key: key, value: value);
|
||||
log('Data writed to secure storage: $key $value');
|
||||
//print('Data writed to secure storage: $key $value');
|
||||
}
|
||||
|
||||
Future<String> readSecureData(String key) async {
|
||||
log('Data start read from secure storage: $key');
|
||||
String value = await storage.read(key: key) ?? 'No data found!';
|
||||
log('Data read from secure storage: $value');
|
||||
//print('Data read from secure storage: $value');
|
||||
return value;
|
||||
}
|
||||
Future<bool> checkContainsKey(String key) async {
|
||||
bool value = await storage.containsKey(key: key);
|
||||
log('Key $key checked: $value');
|
||||
//print('Key $key checked: $value');
|
||||
return value;
|
||||
}
|
||||
deleteSecureData(String key) async {
|
||||
await storage.delete(key: key);
|
||||
log('Data deleted from secure storage: $key');
|
||||
//print('Data deleted from secure storage: $key');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
|
||||
import 'package:mobile_portal_23/widgets/reportDetails.dart';
|
||||
|
||||
class reportCardWidget extends StatefulWidget {
|
||||
// reportCardWidget({Key? key}) : super(key: key);
|
||||
|
||||
final ModelReportList reportListItem;
|
||||
const reportCardWidget(this.reportListItem, {super.key});
|
||||
@override
|
||||
State<reportCardWidget> createState() => _reportCardWidgetState();
|
||||
}
|
||||
|
||||
List<String> favoriteWorks = [];
|
||||
//late List<ModelReportList> reportList = [];
|
||||
bool _showFaworites = false;
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
Future<void> _saveFavoriteWorks(List<String> favoriteWorks) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setStringList('favoriteWorks', favoriteWorks);
|
||||
}
|
||||
|
||||
Future<void> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// userApiKey = prefs.getString("apiKey");
|
||||
favoriteWorks = prefs.getStringList("favoriteWorks") ?? [];
|
||||
}
|
||||
|
||||
class _reportCardWidgetState extends State<reportCardWidget> {
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
});
|
||||
getSharedPrefs();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return reportCard(context, widget.reportListItem);
|
||||
}
|
||||
|
||||
Card reportCard(BuildContext context, ModelReportList item) {
|
||||
int workHour = 0;
|
||||
bool workOpened = false;
|
||||
bool isFaworite = favoriteWorks.contains(item.sId);
|
||||
if (item.state!.contains("Opened")) workOpened = true;
|
||||
for (var element in item.dailyReport) {
|
||||
workHour += element.employeeList.length;
|
||||
}
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
badges.Badge(
|
||||
showBadge: !workOpened,
|
||||
position: badges.BadgePosition.topEnd(top: 3, end: 3),
|
||||
badgeContent: const Icon(Icons.lock_outlined),
|
||||
child: ListTile(
|
||||
tileColor: workOpened ? Colors.blue : Colors.grey,
|
||||
trailing: IconButton(
|
||||
onPressed: () {
|
||||
if (isFaworite) {
|
||||
favoriteWorks.remove(item.sId);
|
||||
} else {
|
||||
String? id = item.sId;
|
||||
favoriteWorks.add(id!);
|
||||
}
|
||||
_saveFavoriteWorks(favoriteWorks);
|
||||
setState(() {});
|
||||
},
|
||||
icon: isFaworite
|
||||
? Icon(
|
||||
Icons.star,
|
||||
color: favoriteWorks.contains(item.sId)
|
||||
? Colors.yellow
|
||||
: null,
|
||||
)
|
||||
: const Icon(Icons.star_border)),
|
||||
/* Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
// size: 48,
|
||||
color: Colors.white,
|
||||
|
||||
),*/
|
||||
onTap: () {
|
||||
ReportArguments reportArgs = ReportArguments(
|
||||
item.dailyReport,
|
||||
//userApiKey!,
|
||||
item.title!,
|
||||
item.sId!,
|
||||
item.state == "Opened" ? true : false,
|
||||
//employeePageArguments.isForeman!
|
||||
);
|
||||
Navigator.pushNamed(context, reportDetails.routeName,
|
||||
arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': reportArgs
|
||||
});
|
||||
},
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
item.dailyReport.length.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)),
|
||||
title: Text(
|
||||
item.title!,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
subtitle: Text(
|
||||
item.body!,
|
||||
style: TextStyle(color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Row(children: [
|
||||
Text(
|
||||
'KL${item.workNumber!}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
const VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'Órák: ${workHour * 8} h',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
const VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'PO:${item.poNumber!}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
]))),
|
||||
/* ButtonBar(
|
||||
alignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// Perform some action
|
||||
ReportArguments arg = new ReportArguments(
|
||||
reportList[index].dailyReport, userApiKey!);
|
||||
Navigator.pushNamed(context, reportDetails.routeName,
|
||||
arguments: arg);
|
||||
},
|
||||
icon: const Icon(Icons.mode_edit),
|
||||
label: const Text('Megnyitás')),
|
||||
],
|
||||
),*/
|
||||
//Image.asset('assets/card-sample-image-2.jpg'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
import 'package:mobile_portal_23/models/employee_model.dart';
|
||||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
String appDomain = "iotechnic.eu";
|
||||
|
||||
class ReportCreate extends StatefulWidget {
|
||||
const ReportCreate({Key? key}) : super(key: key);
|
||||
static const routeName = '/reportNew';
|
||||
@override
|
||||
State<ReportCreate> createState() => _ReportCreateState();
|
||||
}
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
late ReportArguments reportArguments;
|
||||
|
||||
Future<List<EmployeeLs>> fetchData(String userApiKey) async {
|
||||
var url = "http://$appDomain/apiemployeelist/$userApiKey";
|
||||
http.Response response = await http.get(Uri.parse(url));
|
||||
var resp = jsonDecode(response.body);
|
||||
if (kDebugMode) {
|
||||
print(resp.toString());
|
||||
}
|
||||
|
||||
return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
|
||||
|
||||
class _ReportCreateState extends State<ReportCreate> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
late List<String> favoriteWorks = [];
|
||||
bool _isError = false;
|
||||
bool _isData = false;
|
||||
final bool _showFaworites = false;
|
||||
late List<WorkListModel> workList = [];
|
||||
// late EmployeeArguments empArgs;
|
||||
|
||||
Future<void> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// userApiKey = prefs.getString("apiKey");
|
||||
favoriteWorks = prefs.getStringList("favoriteWorks") ?? [];
|
||||
}
|
||||
|
||||
Future fetchdata() async {
|
||||
var res = await http.get(
|
||||
|
||||
// "http://iotechnic.eu/apiGetAllReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
Uri.parse("http://$appDomain/apiGetAllWork/${employeePageArguments.apiKey!}"));
|
||||
//"http://192.168.0.144/apiGetDailyReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
});
|
||||
getSharedPrefs().then((value) {
|
||||
fetchdata().then((data) {
|
||||
if (data != null) {
|
||||
for (var item in data) {
|
||||
// reportList.add(ModelReportList.fromJson(item));
|
||||
workList.add(WorkListModel.fromJson(item));
|
||||
}
|
||||
_isData = true;
|
||||
setState(() {
|
||||
debugPrint('Fetch ok.');
|
||||
});
|
||||
} else {
|
||||
_isError = true;
|
||||
}
|
||||
//employeeList = data;
|
||||
/* empArgs = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as EmployeeArguments;*/
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
int currentStep = 0;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<String> emp = [];
|
||||
|
||||
/* final arguments =
|
||||
ModalRoute.of(context)!.settings.arguments as ReportArguments;*/
|
||||
final args = ModalRoute
|
||||
.of(context)!
|
||||
.settings
|
||||
.arguments as Map;
|
||||
|
||||
// employeePageArguments = args['userArgs'];
|
||||
//reportArguments = args['dataArgs'];
|
||||
return Scaffold(
|
||||
//resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: const Text("Új jelentés"),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.search),
|
||||
onPressed: () {},
|
||||
),
|
||||
|
||||
],
|
||||
actionsIconTheme: const IconThemeData(
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
//drawer: Drawer(),
|
||||
|
||||
body: page(context),
|
||||
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
color: Colors.cyan,
|
||||
child: Container(
|
||||
height: 50.0,
|
||||
),
|
||||
|
||||
)
|
||||
|
||||
);
|
||||
//visible: _enableSave,
|
||||
|
||||
|
||||
}
|
||||
|
||||
Widget page(BuildContext context) {
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Stepper(
|
||||
type: StepperType.horizontal,
|
||||
currentStep: currentStep,
|
||||
onStepCancel: () => currentStep == 0
|
||||
? null
|
||||
: setState(() {
|
||||
currentStep -= 1;
|
||||
}),
|
||||
onStepContinue: () {
|
||||
bool isLastStep = (currentStep == getSteps().length - 1);
|
||||
if (isLastStep) {
|
||||
//Do something with this information
|
||||
} else {
|
||||
setState(() {
|
||||
currentStep += 1;
|
||||
});
|
||||
}
|
||||
},
|
||||
onStepTapped: (step) => setState(() {
|
||||
currentStep = step;
|
||||
}),
|
||||
steps: getSteps(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Step> getSteps() {
|
||||
return <Step>[
|
||||
Step(
|
||||
state: currentStep > 0 ? StepState.complete : StepState.indexed,
|
||||
isActive: currentStep >= 0,
|
||||
title: const Text("Ibrányi"),
|
||||
content: selectWork(context)
|
||||
),
|
||||
Step(
|
||||
state: currentStep > 1 ? StepState.complete : StepState.indexed,
|
||||
isActive: currentStep >= 1,
|
||||
title: const Text("Address"),
|
||||
content: const Column(
|
||||
children: [
|
||||
Text("Ibrányi"),
|
||||
],
|
||||
),
|
||||
),
|
||||
Step(
|
||||
state: currentStep > 2 ? StepState.complete : StepState.indexed,
|
||||
isActive: currentStep >= 2,
|
||||
title: const Text("Misc"),
|
||||
content: const Column(
|
||||
children: [
|
||||
Text("Ibrányi"),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Container selectWork(BuildContext context) {
|
||||
return _isData == false
|
||||
? _isError
|
||||
? Container(
|
||||
child: const AlertDialog(
|
||||
title: Text('Hálózati Hiba!'),
|
||||
content: Icon(Icons.error_outline),
|
||||
elevation: 24,
|
||||
backgroundColor: Colors.red),
|
||||
)
|
||||
: Container(
|
||||
child: SizedBox(
|
||||
height: MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.height / 1.3,
|
||||
width: MediaQuery
|
||||
.of(context)
|
||||
.size
|
||||
.width,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
))
|
||||
: gridList(context);
|
||||
}
|
||||
|
||||
Container gridList(BuildContext context) {
|
||||
//List<ModelReportList> _reportList = [];
|
||||
List<WorkListModel> workList = [];
|
||||
if (_showFaworites) {
|
||||
workList = workList
|
||||
.where((element) => favoriteWorks.contains(element.sId))
|
||||
.toList();
|
||||
} else {
|
||||
workList = workList;
|
||||
}
|
||||
return Container(
|
||||
color: const Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: workList.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: reportCard(context, workList[index]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
Card reportCard(BuildContext context, WorkListModel item) {
|
||||
int workHour = 0;
|
||||
bool workOpened = false;
|
||||
bool isFaworite = favoriteWorks.contains(item.sId);
|
||||
if (item.state!.contains("Opened")) workOpened = true;
|
||||
/* item.dailyReport.forEach((element) {
|
||||
workHour += element.employeeList.length;
|
||||
});*/
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
tileColor: workOpened ? Colors.indigo : Colors.grey,
|
||||
trailing: IconButton(
|
||||
onPressed: () {
|
||||
if (isFaworite) {
|
||||
favoriteWorks.remove(item.sId);
|
||||
} else {
|
||||
String? id = item.sId;
|
||||
favoriteWorks.add(id!);
|
||||
}
|
||||
// _saveFavoriteWorks(favoriteWorks);
|
||||
},
|
||||
icon: isFaworite
|
||||
? Icon(
|
||||
Icons.star,
|
||||
color: favoriteWorks.contains(item.sId)
|
||||
? Colors.yellow
|
||||
: null,
|
||||
)
|
||||
: const Icon(Icons.star_border)),
|
||||
onTap: workOpened
|
||||
? () {
|
||||
ReportArguments reportArgs = ReportArguments(
|
||||
List.empty(),
|
||||
//userApiKey!,
|
||||
item.title!,
|
||||
item.sId!,
|
||||
item.state == "Opened" ? true : false,
|
||||
//empArgs.isForeman!
|
||||
);
|
||||
|
||||
/** Navigator.pushNamed(context, reportNew.routeName,
|
||||
arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': reportArgs
|
||||
});*/
|
||||
}
|
||||
: null,
|
||||
title: Text(
|
||||
item.title!,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
/*subtitle: Text(
|
||||
item.body!,
|
||||
style: TextStyle(color: Colors.yellow.withOpacity(0.6)),
|
||||
),*/
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Text(
|
||||
item.body!.replaceAll("\n", " "),
|
||||
style: TextStyle(color: Colors.green.withOpacity(0.6)),
|
||||
),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Row(children: [
|
||||
|
||||
Text(
|
||||
'KL${item.workNumber!}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
const VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'PO: ${item.poNumber!}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]),
|
||||
]))),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:convert';
|
||||
import 'package:mobile_portal_23/models/modelEmployee.dart';
|
||||
import 'package:mobile_portal_23/widgets/reportNew.dart';
|
||||
|
||||
class reportDetails extends StatefulWidget {
|
||||
const reportDetails({Key? key}) : super(key: key);
|
||||
static const routeName = '/reportDetails';
|
||||
@override
|
||||
State<reportDetails> createState() => _reportDetailsState();
|
||||
}
|
||||
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
late ReportArguments reportArguments;
|
||||
//late String userApiKey = ""; //"X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH";
|
||||
bool _isData = false;
|
||||
List<ModelEmployee> employeeList = [];
|
||||
|
||||
class _reportDetailsState extends State<reportDetails> {
|
||||
String appDomain = "iotechnic.eu";
|
||||
|
||||
Future fetchEmployeeList() async {
|
||||
var res = await http.get(Uri.parse("http://$appDomain/apiemployeelist/${employeePageArguments.apiKey!}"));
|
||||
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
initializeDateFormatting();
|
||||
Intl.defaultLocale = "HU"; //sets global,
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
/*final arguments = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as ReportArguments;*/
|
||||
//var args = ModalRoute.of(context)!.settings.arguments;
|
||||
//userApiKey = arguments.userApiKey; // as List<DailyReport>;
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
reportArguments = args['dataArgs'];
|
||||
|
||||
fetchEmployeeList().then((data) {
|
||||
if (data != null) {
|
||||
for (var item in data) {
|
||||
employeeList.add(ModelEmployee.fromJson(item));
|
||||
}
|
||||
_isData = true;
|
||||
setState(() {
|
||||
debugPrint('Fetch ok.');
|
||||
});
|
||||
}
|
||||
//employeeList = data;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
/* final arguments = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as ReportArguments;*/
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
reportArguments = args['dataArgs'];
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Minden jelentés"),
|
||||
/* actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.search),
|
||||
onPressed: () {},
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
),
|
||||
onPressed: () {},
|
||||
)
|
||||
],*/
|
||||
actionsIconTheme: const IconThemeData(
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: reportArguments.state //arguments.state
|
||||
? null
|
||||
: const BottomAppBar(
|
||||
child: SizedBox(
|
||||
height: 30,
|
||||
child: Icon(
|
||||
Icons.lock,
|
||||
color: Colors.red,
|
||||
))),
|
||||
//drawer: Drawer(),
|
||||
body: _isData
|
||||
? gridList(context)
|
||||
: Container(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 1.3,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
)),
|
||||
floatingActionButton: Visibility(
|
||||
visible: reportArguments.state && employeePageArguments.isForeman!,
|
||||
child: FloatingActionButton(
|
||||
onPressed: () => {
|
||||
Navigator.pushNamed(context, reportNew.routeName, arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': reportArguments
|
||||
}).then((value) {
|
||||
setState(() {});
|
||||
}),
|
||||
},
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
));
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
Container gridList(BuildContext context) {
|
||||
/*final arguments = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as ReportArguments;*/
|
||||
//var args = ModalRoute.of(context)!.settings.arguments;
|
||||
List<DailyReport> reportDetailsList =
|
||||
reportArguments.report; //arguments.report; // as List<DailyReport>;
|
||||
return Container(
|
||||
color: const Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: reportDetailsList.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
/* gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisSpacing: 1,
|
||||
mainAxisSpacing: 1,
|
||||
crossAxisCount: 1,
|
||||
childAspectRatio: (4 / 3),
|
||||
),
|
||||
*/
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: reportDetailsCard(context, index),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Card reportDetailsCard(BuildContext context, int index) {
|
||||
bool workOpened = false;
|
||||
ModelEmployee findEmployee(String id) =>
|
||||
employeeList.firstWhere((emlement2) => emlement2.sId == id);
|
||||
//String languageCode = Localizations.localeOf(context).languageCode;
|
||||
/* final arguments = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as ReportArguments;*/
|
||||
//var args = ModalRoute.of(context)!.settings.arguments;
|
||||
List<DailyReport> reportDetailsList =
|
||||
reportArguments.report; //arguments.report;
|
||||
|
||||
String? foreManName = findEmployee(reportDetailsList[index].foremanId!)
|
||||
.name; //employeeList.where((element) => element.sId == reportDetailsList[index].foremanId!);
|
||||
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
tileColor: reportArguments.state ? Colors.cyan : Colors.grey,
|
||||
trailing: employeePageArguments.isForeman!
|
||||
? Icon(
|
||||
Icons.edit,
|
||||
|
||||
// size: 48,
|
||||
color: reportArguments.state ? Colors.white : Colors.grey,
|
||||
)
|
||||
: null,
|
||||
onTap: reportArguments.state && employeePageArguments.isForeman!
|
||||
? () {
|
||||
/* ReportArguments arg = new ReportArguments(
|
||||
reportList[index].dailyReport, userApiKey!);
|
||||
Navigator.pushNamed(context, reportDetails.routeName,
|
||||
arguments: arg);*/
|
||||
}
|
||||
: null,
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
//reportDetailsList[index].employeeList.length.toString(),
|
||||
DateFormat('EE').format(DateFormat('yyyy.MM.dd')
|
||||
.parse(reportDetailsList[index].date!)),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)),
|
||||
title: Text(
|
||||
foreManName!,
|
||||
// reportDetailsList[index].foremanId!,
|
||||
|
||||
style: const TextStyle(color: Colors.white, fontSize: 18),
|
||||
),
|
||||
subtitle: Text(
|
||||
reportDetailsList[index].date!,
|
||||
style: TextStyle(color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Row(children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
reportDetailsList[index].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
),
|
||||
]),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Column(
|
||||
children: reportDetailsList[index]
|
||||
.employeeList
|
||||
.map(
|
||||
(e) => Text(
|
||||
'• ${findEmployee(e).name!}',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
]))),
|
||||
/* ButtonBar(
|
||||
alignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// Perform some action
|
||||
|
||||
/* Navigator.pushNamed(context, reportDetails.routeName,
|
||||
arguments: reportList[index]);*/
|
||||
},
|
||||
icon: const Icon(Icons.mode_edit),
|
||||
label: const Text('Szerkeszt')),
|
||||
],
|
||||
),*/
|
||||
//Image.asset('assets/card-sample-image-2.jpg'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,376 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:mobile_portal_23/widgets/reportCardWidget.dart';
|
||||
|
||||
class dailyReportList extends StatefulWidget {
|
||||
const dailyReportList({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<dailyReportList> createState() => _dailyReportListState();
|
||||
}
|
||||
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
//late EmployeeArguments empArgs;
|
||||
bool _isError = false;
|
||||
bool _isData = false;
|
||||
//String? userApiKey; // = "XST8X8F-6Q9M1FG-PE9948X-SPFHVX9";
|
||||
List<String> favoriteWorks = [];
|
||||
List<ModelReportList> reportList = [];
|
||||
bool _showFaworites = false;
|
||||
Future<void> _saveFavoriteWorks(List<String> favoriteWorks) async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setStringList('favoriteWorks', favoriteWorks);
|
||||
}
|
||||
|
||||
Future<void> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
// userApiKey = prefs.getString("apiKey");
|
||||
favoriteWorks = prefs.getStringList("favoriteWorks") ?? [];
|
||||
}
|
||||
|
||||
class _dailyReportListState extends State<dailyReportList> {
|
||||
String appDomain = "iotechnic.eu";
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
// empArgs = (ModalRoute.of(context)?.settings.arguments ??
|
||||
// <String, dynamic>{}) as EmployeeArguments;
|
||||
// getSharedPrefs().then((value) {
|
||||
fetchdata().then((data) {
|
||||
if (data != null) {
|
||||
for (var item in data) {
|
||||
reportList.add(ModelReportList.fromJson(item));
|
||||
}
|
||||
_isData = true;
|
||||
setState(() {
|
||||
debugPrint('Fetch ok.');
|
||||
});
|
||||
} else {
|
||||
_isError = true;
|
||||
}
|
||||
//employeeList = data;
|
||||
});
|
||||
});
|
||||
// });
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future fetchdata() async {
|
||||
var res = await http.get(
|
||||
|
||||
// "http://iotechnic.eu/apiGetAllReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
Uri.parse("http://$appDomain/apiGetAllReport/${employeePageArguments.apiKey!}"));
|
||||
//"http://192.168.0.144/apiGetDailyReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Minden jelentés"),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.search),
|
||||
onPressed: !_showFaworites
|
||||
? () {
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: ReportSearchDelegate(),
|
||||
);
|
||||
setState(() {});
|
||||
}
|
||||
: null,
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
getSharedPrefs();
|
||||
_showFaworites = !_showFaworites;
|
||||
setState(() {});
|
||||
},
|
||||
icon: _showFaworites
|
||||
? const Icon(Icons.star, color: Colors.yellow)
|
||||
: const Icon(Icons.star_border)),
|
||||
/* IconButton(
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
),
|
||||
onPressed: () {},
|
||||
)*/
|
||||
],
|
||||
actionsIconTheme: const IconThemeData(
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
//drawer: Drawer(),
|
||||
body: page(context));
|
||||
}
|
||||
}
|
||||
|
||||
class ReportSearchDelegate extends SearchDelegate {
|
||||
@override
|
||||
Widget? buildLeading(BuildContext context) => IconButton(
|
||||
onPressed: () => close(context, null),
|
||||
icon: const Icon(Icons.arrow_back));
|
||||
|
||||
@override
|
||||
List<Widget>? buildActions(BuildContext context) {
|
||||
// TODO: implement buildActions
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (query.isEmpty) {
|
||||
close(context, null);
|
||||
} else {
|
||||
query = "";
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.clear));
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildResults(BuildContext context) {
|
||||
return Container(
|
||||
color: const Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: reportList.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) =>
|
||||
Container(child: reportCardWidget(reportList[index])
|
||||
//reportCard(context, reportList[index]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildSuggestions(BuildContext context) {
|
||||
// TODO: implement buildSuggestions
|
||||
List<ModelReportList> suggestions = reportList.where((element) {
|
||||
final result = element.title!.toLowerCase();
|
||||
final input = query.toLowerCase();
|
||||
return result.contains(input);
|
||||
}).toList();
|
||||
return Container(
|
||||
color: const Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: suggestions.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) =>
|
||||
Container(child: reportCardWidget(suggestions[index])
|
||||
//reportCard(context, suggestions[index]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Container page(BuildContext context) {
|
||||
return _isData == false
|
||||
? _isError
|
||||
? Container(
|
||||
child: const AlertDialog(
|
||||
title: Text('Hálózati Hiba!'),
|
||||
content: Icon(Icons.error_outline),
|
||||
elevation: 24,
|
||||
backgroundColor: Colors.red),
|
||||
)
|
||||
: Container(
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height / 1.3,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
))
|
||||
: gridList(context);
|
||||
}
|
||||
|
||||
Container gridList(BuildContext context) {
|
||||
List<ModelReportList> reportList = [];
|
||||
if (_showFaworites) {
|
||||
reportList = reportList
|
||||
.where((element) => favoriteWorks.contains(element.sId))
|
||||
.toList();
|
||||
} else {
|
||||
reportList = reportList;
|
||||
}
|
||||
return Container(
|
||||
color: const Color(0xffECF0F1),
|
||||
child: ListView.builder(
|
||||
itemCount: reportList.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: reportCardWidget(
|
||||
reportList[index]) //reportCard(context, _reportList[index]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
/*
|
||||
Card reportCard(BuildContext context, ModelReportList item) {
|
||||
int workHour = 0;
|
||||
bool workOpened = false;
|
||||
bool isFaworite = favoriteWorks.contains(item.sId);
|
||||
if (item.state!.contains("Opened")) workOpened = true;
|
||||
item.dailyReport.forEach((element) {
|
||||
workHour += element.employeeList.length;
|
||||
});
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
Badge(
|
||||
showBadge: !workOpened,
|
||||
position: BadgePosition.topEnd(top: 3, end: 3),
|
||||
badgeContent: Icon(Icons.lock_outlined),
|
||||
child: ListTile(
|
||||
tileColor: workOpened ? Colors.blue : Colors.grey,
|
||||
trailing: IconButton(
|
||||
onPressed: () {
|
||||
if (isFaworite) {
|
||||
favoriteWorks.remove(item.sId);
|
||||
} else {
|
||||
String? id = item.sId;
|
||||
favoriteWorks.add(id!);
|
||||
}
|
||||
_saveFavoriteWorks(favoriteWorks);
|
||||
},
|
||||
icon: isFaworite
|
||||
? Icon(
|
||||
Icons.star,
|
||||
color: favoriteWorks.contains(item.sId)
|
||||
? Colors.yellow
|
||||
: null,
|
||||
)
|
||||
: Icon(Icons.star_border)),
|
||||
/* Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
// size: 48,
|
||||
color: Colors.white,
|
||||
|
||||
),*/
|
||||
onTap: () {
|
||||
ReportArguments reportArgs = new ReportArguments(
|
||||
item.dailyReport,
|
||||
//userApiKey!,
|
||||
item.title!,
|
||||
item.sId!,
|
||||
item.state == "Opened" ? true : false,
|
||||
//employeePageArguments.isForeman!
|
||||
);
|
||||
Navigator.pushNamed(context, reportDetails.routeName, arguments: {
|
||||
'userArgs': employeePageArguments,
|
||||
'dataArgs': reportArgs
|
||||
});
|
||||
},
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.white,
|
||||
child: Text(
|
||||
item.dailyReport.length.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue),
|
||||
)),
|
||||
title: Text(
|
||||
item.title!,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
subtitle: Text(
|
||||
item.body!,
|
||||
style: TextStyle(color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
Row(children: [
|
||||
Text(
|
||||
'KL' + item.workNumber!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'Órák: ' + (workHour * 8).toString() + ' h',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
VerticalDivider(color: Colors.grey, thickness: 1, width: 30),
|
||||
Text(
|
||||
'PO:' + item.poNumber!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
]),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
item.dailyReport[0].workTitle!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
]))),
|
||||
/* ButtonBar(
|
||||
alignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// Perform some action
|
||||
ReportArguments arg = new ReportArguments(
|
||||
reportList[index].dailyReport, userApiKey!);
|
||||
Navigator.pushNamed(context, reportDetails.routeName,
|
||||
arguments: arg);
|
||||
},
|
||||
icon: const Icon(Icons.mode_edit),
|
||||
label: const Text('Megnyitás')),
|
||||
],
|
||||
),*/
|
||||
//Image.asset('assets/card-sample-image-2.jpg'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}*/
|
||||
|
|
@ -0,0 +1,489 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_portal_23/classes/common_classes.dart';
|
||||
import 'package:mobile_portal_23/models/employee_model.dart';
|
||||
import 'package:mobile_portal_23/models/reportListModel.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
//import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
|
||||
//String? userApiKey;
|
||||
TextEditingController dateinput = TextEditingController();
|
||||
String appDomain = "iotechnic.eu";
|
||||
bool _enableSave = false;
|
||||
bool _textMessageOK = false;
|
||||
String textMessage = "";
|
||||
late EmployeePageArguments employeePageArguments;
|
||||
late ReportArguments reportArguments;
|
||||
/*Future<Null> getSharedPrefs() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
userApiKey = prefs.getString("apiKey");
|
||||
}*/
|
||||
|
||||
class reportNew extends StatefulWidget {
|
||||
const reportNew({Key? key}) : super(key: key);
|
||||
static const routeName = '/reportNew';
|
||||
@override
|
||||
State<reportNew> createState() => _reportNewState();
|
||||
}
|
||||
|
||||
Future fetchReport(BuildContext context) async {
|
||||
var res = await http.get(Uri.parse("http://$appDomain/apiGetAllReport/${employeePageArguments.apiKey!}"));
|
||||
if (res.statusCode == 200) {
|
||||
var data = json.decode(res.body);
|
||||
//return obj;
|
||||
if (data != null) {
|
||||
for (var item in data) {
|
||||
ModelReportList mr = ModelReportList.fromJson(item);
|
||||
|
||||
if (mr.sId == reportArguments.workId) {
|
||||
reportArguments.report.clear();
|
||||
reportArguments.report.addAll(mr.dailyReport);
|
||||
}
|
||||
}
|
||||
|
||||
//employeeList = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future fetchEmployeeData(String userApiKey) async {
|
||||
var res = await http.get(
|
||||
|
||||
// "http://iotechnic.eu/apiemployeelist/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
Uri.parse("http://$appDomain/apiGetDailyReport/$userApiKey"));
|
||||
//"http://192.168.0.144/apiGetDailyReport/X8B0PQS-2KYMCV3-G5WD74N-8G0CRAH");
|
||||
if (res.statusCode == 200) {
|
||||
var obj = json.decode(res.body);
|
||||
return obj;
|
||||
} else {
|
||||
throw ("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<EmployeeLs>> fetchData(String userApiKey) async {
|
||||
var url = "http://$appDomain/apiemployeelist/$userApiKey";
|
||||
http.Response response = await http.get(Uri.parse(url));
|
||||
var resp = jsonDecode(response.body);
|
||||
print(resp.toString());
|
||||
|
||||
return resp.map<EmployeeLs>((m) => EmployeeLs.fromJson(m)).toList();
|
||||
}
|
||||
|
||||
Future<String> postDailyReport(var json) async {
|
||||
final response = await http.post(
|
||||
Uri.parse("http://$appDomain/apiPostDailyReport/${employeePageArguments.apiKey!}"),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: jsonEncode(json),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// If the server did return a 201 CREATED response,
|
||||
// then parse the JSON.
|
||||
return response.body;
|
||||
} else {
|
||||
// If the server did not return a 201 CREATED response,
|
||||
// then throw an exception.
|
||||
throw Exception('Failed to create album.');
|
||||
}
|
||||
}
|
||||
|
||||
_saveForm(BuildContext context, ReportArguments arguments,
|
||||
List<EmployeeLs> employeeList) {
|
||||
EasyLoading.show(status: 'Mentés...');
|
||||
// _onLoading2();
|
||||
print("SUBMITTED!");
|
||||
print(dateinput.text);
|
||||
print("Title: ${arguments.workName}");
|
||||
print("WorkId: ${arguments.workId}");
|
||||
print("Message: $textMessage");
|
||||
List<String> emp = [];
|
||||
//print("Jelenlévők: ");
|
||||
for (var hobby in employeeList) {
|
||||
if (hobby.value == true) {
|
||||
//print(hobby.name);
|
||||
emp.add(hobby.id);
|
||||
}
|
||||
}
|
||||
var report = {
|
||||
'userApiKey': employeePageArguments.apiKey,
|
||||
'workId': arguments.workId,
|
||||
'date': dateinput.text,
|
||||
'msg': textMessage,
|
||||
'employeeList': emp
|
||||
};
|
||||
//print(json.encode(report));
|
||||
postDailyReport(report).then((value) {
|
||||
if (value.contains("OK")) {
|
||||
EasyLoading.showSuccess('Sikeres Mentés');
|
||||
fetchReport(context).then((value) {
|
||||
Future.delayed(const Duration(seconds: 3), () {
|
||||
// Navigator.pop(context); //pop dialog
|
||||
EasyLoading.dismiss();
|
||||
|
||||
Navigator.of(context).pop();
|
||||
//_login();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class _reportNewState extends State<reportNew> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
List<EmployeeLs> employeeList = [];
|
||||
bool _isData = false;
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
// getSharedPrefs().then((args) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
/*final arguments = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as ReportArguments;*/
|
||||
//var args = ModalRoute.of(context)!.settings.arguments;
|
||||
//userApiKey = arguments.userApiKey; // as List<DailyReport>;
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
reportArguments = args['dataArgs'];
|
||||
fetchData(employeePageArguments.apiKey!).then((value) {
|
||||
setState(() {
|
||||
employeeList.addAll(value);
|
||||
_isData = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
// });
|
||||
dateinput.text = DateFormat('yyyy.MM.dd').format(DateTime.now());
|
||||
//set output date to TextField value
|
||||
super.initState();
|
||||
}
|
||||
|
||||
checkize() {
|
||||
_enableSave = false;
|
||||
for (var item in employeeList) {
|
||||
if (item.value == true) {
|
||||
setState(() {
|
||||
if (_textMessageOK) _enableSave = true;
|
||||
});
|
||||
|
||||
print("Save Enabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildLastName() {
|
||||
return Form(
|
||||
key: _formKey,
|
||||
//margin: const EdgeInsets.only(left: 40),
|
||||
child: TextFormField(
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
textMessage = "";
|
||||
_textMessageOK = false;
|
||||
checkize();
|
||||
return 'A mező nem lehet üres!';
|
||||
}
|
||||
if (value.length < 3) {
|
||||
textMessage = "";
|
||||
_textMessageOK = false;
|
||||
checkize();
|
||||
return "Legalább 3 karakter!";
|
||||
} else {
|
||||
textMessage = value;
|
||||
_textMessageOK = true;
|
||||
checkize();
|
||||
return null;
|
||||
}
|
||||
},
|
||||
onChanged: (_) {
|
||||
_formKey.currentState!.validate();
|
||||
},
|
||||
onFieldSubmitted: (_) {
|
||||
_formKey.currentState!.validate();
|
||||
},
|
||||
style: const TextStyle(
|
||||
color: Color.fromARGB(255, 3, 163, 29),
|
||||
fontFamily: 'RadikalLight'),
|
||||
decoration: //_buildInputDecoration("Last name", ''),
|
||||
const InputDecoration(labelText: 'Munka leírása')));
|
||||
}
|
||||
|
||||
Container gridList(BuildContext context) {
|
||||
//_enableSave = false;
|
||||
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
child: ListView.builder(
|
||||
itemCount: employeeList.length, // The length Of the array
|
||||
|
||||
padding: const EdgeInsets.all(5),
|
||||
shrinkWrap: true,
|
||||
|
||||
itemBuilder: (context, index) => Container(
|
||||
child: employeeWidget(context, index),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
SwitchListTile employeeWidget(BuildContext context, index) {
|
||||
return SwitchListTile(
|
||||
//controlAffinity: ListTileControlAffinity.trailing,
|
||||
activeColor: Colors.green,
|
||||
value: employeeList[index].value,
|
||||
title: Text(employeeList[index].name),
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
employeeList[index].value = newValue;
|
||||
checkize();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<String> emp = [];
|
||||
/* final arguments =
|
||||
ModalRoute.of(context)!.settings.arguments as ReportArguments;*/
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
reportArguments = args['dataArgs'];
|
||||
//<String, dynamic>{}) as ReportArguments;
|
||||
return Scaffold(
|
||||
//resizeToAvoidBottomInset: false,
|
||||
appBar: AppBar(
|
||||
title: const Text("Új jelentés"),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.search),
|
||||
onPressed: () {},
|
||||
),
|
||||
/* IconButton(
|
||||
icon: Icon(
|
||||
Icons.save,
|
||||
//color: Colors.white,
|
||||
),
|
||||
onPressed: _enableSave
|
||||
? () {
|
||||
print("Save");
|
||||
}
|
||||
: null)*/
|
||||
],
|
||||
actionsIconTheme: const IconThemeData(
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
//drawer: Drawer(),
|
||||
|
||||
body: SingleChildScrollView(
|
||||
child: page(context),
|
||||
),
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
color: Colors.cyan,
|
||||
child: Container(
|
||||
height: 50.0,
|
||||
),
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
|
||||
floatingActionButton: Visibility(
|
||||
visible: _enableSave,
|
||||
child: FloatingActionButton(
|
||||
onPressed: _enableSave
|
||||
? () => {
|
||||
if (_formKey.currentState!.validate())
|
||||
{
|
||||
/* print("SUBMITTED!"),
|
||||
print(dateinput.text),
|
||||
print("Title: " + arguments.workName),
|
||||
print("WorkId: " + arguments.workId),
|
||||
print("Message: " + textMessage),
|
||||
|
||||
//print("Jelenlévők: ");
|
||||
for (var hobby in employeeList)
|
||||
{
|
||||
if (hobby.value == true)
|
||||
{
|
||||
//print(hobby.name);
|
||||
emp.add(hobby.id),
|
||||
}
|
||||
},
|
||||
print(emp),*/
|
||||
// TODO submit
|
||||
|
||||
_saveForm(context, reportArguments, employeeList)
|
||||
}
|
||||
// Navigator.pushNamed(context, reportNew.routeName,
|
||||
// arguments: arguments),
|
||||
}
|
||||
: null,
|
||||
child: const Icon(Icons.save),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Widget page(BuildContext context) {
|
||||
/* final arguments = (ModalRoute.of(context)?.settings.arguments ??
|
||||
<String, dynamic>{}) as ReportArguments;*/
|
||||
final args = ModalRoute.of(context)!.settings.arguments as Map;
|
||||
|
||||
employeePageArguments = args['userArgs'];
|
||||
reportArguments = args['dataArgs'];
|
||||
List<DailyReport> reportDetailsList =
|
||||
reportArguments.report; // as List<DailyReport>;
|
||||
String textMessage = "";
|
||||
|
||||
DateTime selectedDate = DateTime.now();
|
||||
return Container(
|
||||
child: Column(children: [
|
||||
Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
tileColor: Colors.cyan,
|
||||
/* trailing: IconButton(
|
||||
color: Colors.green,
|
||||
icon: Icon(
|
||||
Icons.save,
|
||||
//color: Colors.white,
|
||||
),
|
||||
onPressed: _enableSave
|
||||
? () {
|
||||
print("Save");
|
||||
}
|
||||
: null),*/
|
||||
/* ReportArguments arg = new ReportArguments(
|
||||
reportList[index].dailyReport, userApiKey!);
|
||||
Navigator.pushNamed(context, reportDetails.routeName,
|
||||
arguments: arg);*/
|
||||
|
||||
title: Text(
|
||||
reportArguments.workName,
|
||||
// reportDetailsList[index].foremanId!,
|
||||
|
||||
style: const TextStyle(color: Colors.white, fontSize: 18),
|
||||
),
|
||||
/*subtitle: Text(
|
||||
"Date",
|
||||
style: TextStyle(color: Colors.black.withOpacity(0.6)),
|
||||
),*/
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: IntrinsicHeight(
|
||||
child: Column(children: [
|
||||
/* Row(children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
arguments.workName,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
),
|
||||
]),
|
||||
Divider(
|
||||
thickness: 1.0,
|
||||
),*/
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||
child: Center(
|
||||
child: TextField(
|
||||
//enabled: datePickerEnabled,
|
||||
controller:
|
||||
dateinput, //editing controller of this TextField
|
||||
decoration: const InputDecoration(
|
||||
icon:
|
||||
Icon(Icons.calendar_today), //icon of text field
|
||||
labelText: "Jelentés Dátuma" //label text of field
|
||||
),
|
||||
readOnly:
|
||||
true, //set it true, so that user will not able to edit text
|
||||
onTap: () async {
|
||||
DateTime? pickedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(
|
||||
2020), //DateTime.now() - not to allow to choose before today.
|
||||
lastDate: DateTime.now());
|
||||
|
||||
if (pickedDate != null) {
|
||||
//print(pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
|
||||
String formattedDate =
|
||||
DateFormat('yyyy.MM.dd').format(pickedDate);
|
||||
//print(formattedDate); //formatted date output using intl package => 2021-03-16
|
||||
//you can implement different kind of Date Format here according to your requirement
|
||||
|
||||
// setState(() {
|
||||
//textMessageEnabled = true;
|
||||
selectedDate = pickedDate;
|
||||
|
||||
dateinput.text =
|
||||
formattedDate; //set output date to TextField value.
|
||||
// });
|
||||
} else {
|
||||
print("Nem választott dátumot!");
|
||||
}
|
||||
},
|
||||
)),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 20, left: 15, right: 15),
|
||||
//margin: const EdgeInsets.only(left: 5, right: 5),
|
||||
height: 100,
|
||||
//child: Padding(
|
||||
//padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
|
||||
|
||||
child: _buildLastName(),
|
||||
),
|
||||
const Divider(
|
||||
thickness: 1.0,
|
||||
),
|
||||
SizedBox(
|
||||
height: 300,
|
||||
child: _isData
|
||||
? gridList(context)
|
||||
: SizedBox(
|
||||
height:
|
||||
MediaQuery.of(context).size.height / 1.3,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
))
|
||||
//ListView(children: UsersUi(arguments.userApiKey)),
|
||||
|
||||
/*new Column(
|
||||
children: reportDetailsList[index]
|
||||
.employeeList
|
||||
.map(
|
||||
(e) => new Text(
|
||||
'• ' + findEmployee(e).name!,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.black.withOpacity(0.6)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
*/
|
||||
]))),
|
||||
],
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
name: mobile_portal_23
|
||||
description: "Mobile Portal 2023"
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=3.2.0 <4.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
device_info_plus: ^9.1.1
|
||||
flutter_secure_storage: ^9.0.0
|
||||
http: ^0.13.0
|
||||
flutter_easyloading: ^3.0.3
|
||||
location: ^5.0.3
|
||||
nfc_manager: ^3.3.0
|
||||
hex: ^0.2.0
|
||||
geolocator: ^10.1.0
|
||||
geocoding: ^2.1.1
|
||||
expandable: ^5.0.1
|
||||
intl: ^0.18.1
|
||||
jiffy: ^6.2.1
|
||||
dropdown_search: ^5.0.6
|
||||
badges: ^3.1.2
|
||||
shared_preferences: ^2.2.2
|
||||
simple_barcode_scanner: ^0.1.0
|
||||
#mobile_scanner: ^3.5.7
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
flutter_native_splash: ^2.3.9
|
||||
package_info_plus: ^5.0.1
|
||||
qr_flutter: ^4.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
flutter_icons:
|
||||
android: true
|
||||
ios: true
|
||||
image_path: "assets/cloudlogo.png"
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
flutter_native_splash:
|
||||
color: "#9ae79a"
|
||||
image: assets/cloudlogo.png
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
assets:
|
||||
- assets/cloudlogo.png
|
||||
- assets/nfc.png
|
||||
- assets/nfcdenied.png
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add custom fonts to your application, add a fonts section here,
|
||||
# in this "flutter" section. Each entry in this list should have a
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:mobile_portal_23/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue