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