Flutter / Mobile
This commit is contained in:
parent
9fe873ccb2
commit
dbcd1755f5
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"cmake.sourceDirectory": "C:/Users/Romi/Documents/GitHub/absen/linux"
|
"cmake.sourceDirectory": "C:/Users/Romi/Documents/TA/mobileabsen/linux"
|
||||||
}
|
}
|
|
@ -1,3 +1,6 @@
|
||||||
|
import java.util.Properties
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("kotlin-android")
|
id("kotlin-android")
|
||||||
|
@ -5,6 +8,12 @@ plugins {
|
||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val keystoreProperties = Properties()
|
||||||
|
val keystorePropertiesFile = rootProject.file("key.properties")
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.example.absen"
|
namespace = "com.example.absen"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
|
@ -30,11 +39,21 @@ android {
|
||||||
versionName = flutter.versionName
|
versionName = flutter.versionName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
create("release") {
|
||||||
|
keyAlias = keystoreProperties["keyAlias"] as String
|
||||||
|
keyPassword = keystoreProperties["keyPassword"] as String
|
||||||
|
storeFile = keystoreProperties["storeFile"]?.let { file(it) }
|
||||||
|
storePassword = keystoreProperties["storePassword"] as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
// signingConfig = signingConfigs.getByName("debug")
|
||||||
|
signingConfig = signingConfigs.getByName("release")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,3 +61,9 @@ android {
|
||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// ...
|
||||||
|
implementation("com.google.android.material:material:1.8.0")
|
||||||
|
// ...
|
||||||
|
}
|
|
@ -1,54 +1,49 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- Izin yang dibutuhkan -->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
|
||||||
<application
|
|
||||||
android:label="absen"
|
|
||||||
android:name="${applicationName}"
|
|
||||||
android:icon="@mipmap/ic_launcher">
|
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name="${applicationName}"
|
||||||
|
android:label="Abensiku"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
android:networkSecurityConfig="@xml/network_security_config">
|
||||||
|
|
||||||
|
<!-- Google Maps API key harus di sini -->
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.geo.API_KEY"
|
||||||
|
android:value="AIzaSyCj4UPomrFAUt61rUNOus0Rx2D_Cxm1hM8"/>
|
||||||
|
|
||||||
|
<!-- Theme normal flutter -->
|
||||||
|
<meta-data
|
||||||
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
|
android:resource="@style/NormalTheme"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:taskAffinity=""
|
|
||||||
android:theme="@style/LaunchTheme"
|
android:theme="@style/LaunchTheme"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:windowSoftInputMode="adjustResize">
|
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="com.google.android.geo.API_KEY"
|
|
||||||
android:value="AIzaSyCj4UPomrFAUt61rUNOus0Rx2D_Cxm1hM8"/>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
|
||||||
android:resource="@style/NormalTheme"
|
|
||||||
|
|
||||||
/>
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
<!-- Flutter embedding marker -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
</application>
|
</application>
|
||||||
<!-- Required to query activities that can process text, see:
|
|
||||||
https://developer.android.com/training/package-visibility and
|
|
||||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
|
||||||
|
|
||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
<!-- Jika kamu pakai clear-text HTTP -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config>
|
||||||
|
<!-- Mengizinkan HTTP (cleartext) ke IP lokal 192.168.1.33 -->
|
||||||
|
<domain-config cleartextTrafficPermitted="true">
|
||||||
|
<domain includeSubdomains="true">192.168.1.6</domain>
|
||||||
|
</domain-config>
|
||||||
|
</network-security-config>
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 87 KiB |
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -70,7 +71,7 @@ class _CheckinPhotoScreenState extends State<CheckinPhotoScreen> {
|
||||||
if (!_isPhotoReady()) return;
|
if (!_isPhotoReady()) return;
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
final token = widget.token;
|
final token = widget.token;
|
||||||
final uri = Uri.parse('http://localhost:8000/api/employee/attendance');
|
final uri = Uri.parse('${AppConfig.baseUrl}/api/employee/attendance');
|
||||||
final request =
|
final request =
|
||||||
http.MultipartRequest('POST', uri)
|
http.MultipartRequest('POST', uri)
|
||||||
..headers['Authorization'] = 'Bearer $token'
|
..headers['Authorization'] = 'Bearer $token'
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
|
import 'package:absen/models/attendance_area.dart';
|
||||||
import 'package:absen/widgets/google_map_web_view.dart';
|
import 'package:absen/widgets/google_map_web_view.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:absen/models/attendance_area.dart';
|
|
||||||
|
|
||||||
import 'checkin_photo_screen.dart';
|
import 'checkin_photo_screen.dart';
|
||||||
|
|
||||||
|
@ -47,7 +48,6 @@ class _CheckinScreenState extends State<CheckinScreen> {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocationPermission permission = await Geolocator.checkPermission();
|
LocationPermission permission = await Geolocator.checkPermission();
|
||||||
if (permission == LocationPermission.denied) {
|
if (permission == LocationPermission.denied) {
|
||||||
permission = await Geolocator.requestPermission();
|
permission = await Geolocator.requestPermission();
|
||||||
|
@ -64,7 +64,6 @@ class _CheckinScreenState extends State<CheckinScreen> {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position? pos;
|
Position? pos;
|
||||||
try {
|
try {
|
||||||
pos = await Geolocator.getCurrentPosition(
|
pos = await Geolocator.getCurrentPosition(
|
||||||
|
@ -98,9 +97,7 @@ class _CheckinScreenState extends State<CheckinScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _fetchAttendanceAreas() async {
|
Future<void> _fetchAttendanceAreas() async {
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse('${AppConfig.baseUrl}/api/employee/attendance/areas');
|
||||||
'http://localhost:8000/api/employee/attendance/areas',
|
|
||||||
);
|
|
||||||
final token = widget.token;
|
final token = widget.token;
|
||||||
try {
|
try {
|
||||||
final resp = await http.get(
|
final resp = await http.get(
|
||||||
|
@ -154,7 +151,7 @@ class _CheckinScreenState extends State<CheckinScreen> {
|
||||||
if (_position == null) return;
|
if (_position == null) return;
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse(
|
||||||
'http://localhost:8000/api/employee/attendance/check-location',
|
'${AppConfig.baseUrl}/api/employee/attendance/check-location',
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -70,7 +71,7 @@ class _CheckoutPhotoScreenState extends State<CheckoutPhotoScreen> {
|
||||||
if (!_isPhotoReady()) return;
|
if (!_isPhotoReady()) return;
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
final token = widget.token;
|
final token = widget.token;
|
||||||
final uri = Uri.parse('http://localhost:8000/api/employee/attendance');
|
final uri = Uri.parse('${AppConfig.baseUrl}/api/employee/attendance');
|
||||||
final request =
|
final request =
|
||||||
http.MultipartRequest('POST', uri)
|
http.MultipartRequest('POST', uri)
|
||||||
..headers['Authorization'] = 'Bearer $token'
|
..headers['Authorization'] = 'Bearer $token'
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
|
import 'package:absen/models/attendance_area.dart';
|
||||||
import 'package:absen/widgets/google_map_web_view.dart';
|
import 'package:absen/widgets/google_map_web_view.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:geolocator/geolocator.dart';
|
import 'package:geolocator/geolocator.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:absen/models/attendance_area.dart';
|
|
||||||
|
|
||||||
import 'checkout_photo_screen.dart';
|
import 'checkout_photo_screen.dart';
|
||||||
|
|
||||||
|
@ -43,7 +44,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||||
Future<void> _checkTodayStatus() async {
|
Future<void> _checkTodayStatus() async {
|
||||||
setState(() => _checkedStatus = false);
|
setState(() => _checkedStatus = false);
|
||||||
final url = Uri.parse(
|
final url = Uri.parse(
|
||||||
'http://localhost:8000/api/employee/attendance/today-status',
|
'${AppConfig.baseUrl}/api/employee/attendance/today-status',
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
final resp = await http.get(
|
final resp = await http.get(
|
||||||
|
@ -69,9 +70,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _fetchAttendanceAreas() async {
|
Future<void> _fetchAttendanceAreas() async {
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse('${AppConfig.baseUrl}/api/employee/attendance/areas');
|
||||||
'http://localhost:8000/api/employee/attendance/areas',
|
|
||||||
);
|
|
||||||
// Asumsikan endpoint mengembalikan JSON array: [ { center_lat, center_lng, radius }, ... ]
|
// Asumsikan endpoint mengembalikan JSON array: [ { center_lat, center_lng, radius }, ... ]
|
||||||
try {
|
try {
|
||||||
final resp = await http.get(
|
final resp = await http.get(
|
||||||
|
@ -203,7 +202,7 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||||
}
|
}
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
final uri = Uri.parse(
|
final uri = Uri.parse(
|
||||||
'http://localhost:8000/api/employee/attendance/check-location',
|
'${AppConfig.baseUrl}/api/employee/attendance/check-location',
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
final resp = await http.post(
|
final resp = await http.post(
|
||||||
|
@ -374,7 +373,6 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
myLocationEnabled: true,
|
myLocationEnabled: true,
|
||||||
myLocationButtonEnabled: false,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
class AppConfig {
|
||||||
|
static const String baseUrl = 'http://192.168.1.6:8000';
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
@ -18,7 +19,7 @@ class DashboardScreen extends StatelessWidget {
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchTodayStatus(String token) async {
|
Future<Map<String, dynamic>> fetchTodayStatus(String token) async {
|
||||||
final url = Uri.parse(
|
final url = Uri.parse(
|
||||||
'http://localhost:8000/api/employee/attendance/today-status',
|
'${AppConfig.baseUrl}/api/employee/attendance/today-status',
|
||||||
);
|
);
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
url,
|
url,
|
||||||
|
@ -33,7 +34,7 @@ class DashboardScreen extends StatelessWidget {
|
||||||
|
|
||||||
Future<List<Map<String, dynamic>>> fetchLastActivities(String token) async {
|
Future<List<Map<String, dynamic>>> fetchLastActivities(String token) async {
|
||||||
final url = Uri.parse(
|
final url = Uri.parse(
|
||||||
'http://localhost:8000/api/employee/attendance/history?length=3&start=0',
|
'${AppConfig.baseUrl}/api/employee/attendance/history?length=3&start=0',
|
||||||
);
|
);
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
url,
|
url,
|
||||||
|
@ -54,7 +55,7 @@ class DashboardScreen extends StatelessWidget {
|
||||||
final todayStr =
|
final todayStr =
|
||||||
"${today.year.toString().padLeft(4, '0')}-${today.month.toString().padLeft(2, '0')}-${today.day.toString().padLeft(2, '0')}";
|
"${today.year.toString().padLeft(4, '0')}-${today.month.toString().padLeft(2, '0')}-${today.day.toString().padLeft(2, '0')}";
|
||||||
final url = Uri.parse(
|
final url = Uri.parse(
|
||||||
'http://localhost:8000/api/employee/permission/history?start_date=$todayStr&length=5',
|
'${AppConfig.baseUrl}/api/employee/permission/history?start_date=$todayStr&length=5',
|
||||||
);
|
);
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
url,
|
url,
|
||||||
|
@ -237,14 +238,14 @@ class DashboardScreen extends StatelessWidget {
|
||||||
now.month,
|
now.month,
|
||||||
now.day,
|
now.day,
|
||||||
8,
|
8,
|
||||||
30,
|
00,
|
||||||
);
|
);
|
||||||
final endTime = DateTime(
|
final endTime = DateTime(
|
||||||
now.year,
|
now.year,
|
||||||
now.month,
|
now.month,
|
||||||
now.day,
|
now.day,
|
||||||
17,
|
17,
|
||||||
30,
|
00,
|
||||||
);
|
);
|
||||||
DateTime? checkInTime;
|
DateTime? checkInTime;
|
||||||
DateTime? checkOutTime;
|
DateTime? checkOutTime;
|
||||||
|
@ -433,20 +434,43 @@ class DashboardScreen extends StatelessWidget {
|
||||||
type == 'in' ? 'Check-in' : 'Check-out';
|
type == 'in' ? 'Check-in' : 'Check-out';
|
||||||
final date = item['date'] ?? '';
|
final date = item['date'] ?? '';
|
||||||
final time = item['time'] ?? '';
|
final time = item['time'] ?? '';
|
||||||
|
|
||||||
final status = item['status'] ?? '-';
|
final status = item['status'] ?? '-';
|
||||||
final statusColor =
|
late Color statusColor;
|
||||||
status == 'accepted'
|
late String statusText;
|
||||||
? const Color(0xFF1BCFB4)
|
|
||||||
: (status == 'late'
|
switch (status) {
|
||||||
? const Color(0xFFFFC542)
|
case 'pending':
|
||||||
: (status == 'pending'
|
statusColor = const Color(0xFFFFC542);
|
||||||
? const Color(0xFFFFC542)
|
statusText = 'Menunggu';
|
||||||
: const Color(0xFFE57373)));
|
break;
|
||||||
final statusText =
|
case 'accepted':
|
||||||
status == 'late'
|
statusColor = const Color(0xFF1BCFB4);
|
||||||
? 'Terlambat'
|
statusText = 'Diterima';
|
||||||
: (status[0].toUpperCase() +
|
break;
|
||||||
status.substring(1));
|
case 'jam_kerja_kurang':
|
||||||
|
statusColor = const Color(0xFFE57373);
|
||||||
|
statusText = 'Jam Kerja Kurang';
|
||||||
|
break;
|
||||||
|
case 'lembur':
|
||||||
|
statusColor = const Color(0xFF4F8DFD);
|
||||||
|
statusText = 'Lembur';
|
||||||
|
break;
|
||||||
|
case 'late':
|
||||||
|
statusColor = const Color(0xFFFF7043);
|
||||||
|
statusText = 'Terlambat';
|
||||||
|
break;
|
||||||
|
case 'rejected':
|
||||||
|
statusColor = const Color(0xFFD32F2F);
|
||||||
|
statusText = 'Ditolak';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statusColor = const Color(0xFF9E9E9E);
|
||||||
|
statusText =
|
||||||
|
status[0].toUpperCase() +
|
||||||
|
status.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
return _ActivityTile(
|
return _ActivityTile(
|
||||||
icon: icon,
|
icon: icon,
|
||||||
title: title,
|
title: title,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:dotted_border/dotted_border.dart';
|
import 'package:dotted_border/dotted_border.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
@ -34,6 +35,7 @@ class _IzinScreenState extends State<IzinScreen> {
|
||||||
'Cuti Tahunan',
|
'Cuti Tahunan',
|
||||||
'Izin Sakit',
|
'Izin Sakit',
|
||||||
'Izin Setengah Hari',
|
'Izin Setengah Hari',
|
||||||
|
'Dinas di Luar',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Pick start/end dates
|
// Pick start/end dates
|
||||||
|
@ -95,7 +97,7 @@ class _IzinScreenState extends State<IzinScreen> {
|
||||||
|
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
|
|
||||||
final uri = Uri.parse('http://localhost:8000/api/employee/permission');
|
final uri = Uri.parse('${AppConfig.baseUrl}/api/employee/permission');
|
||||||
final req =
|
final req =
|
||||||
http.MultipartRequest('POST', uri)
|
http.MultipartRequest('POST', uri)
|
||||||
..headers['Authorization'] = 'Bearer ${widget.token}'
|
..headers['Authorization'] = 'Bearer ${widget.token}'
|
||||||
|
@ -323,7 +325,7 @@ class _IzinScreenState extends State<IzinScreen> {
|
||||||
|
|
||||||
// Photo proof
|
// Photo proof
|
||||||
const Text(
|
const Text(
|
||||||
'Foto Bukti (Optional)',
|
'Foto Bukti',
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
import 'dashboard_screen.dart';
|
import 'dashboard_screen.dart';
|
||||||
import 'register_screen.dart';
|
|
||||||
|
|
||||||
class LoginScreen extends StatefulWidget {
|
class LoginScreen extends StatefulWidget {
|
||||||
const LoginScreen({Key? key}) : super(key: key);
|
const LoginScreen({Key? key}) : super(key: key);
|
||||||
|
@ -23,17 +23,29 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
// final url = Uri.parse('http://localhost:8000/api/login');
|
final url = Uri.parse('${AppConfig.baseUrl}/api/login');
|
||||||
final url = Uri.parse('http://localhost:8000/api/login');
|
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
url,
|
url,
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Platform': 'mobile', // ✅ penting!
|
||||||
|
},
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
'email': _emailController.text.trim(),
|
'email': _emailController.text.trim(),
|
||||||
'password': _passwordController.text,
|
'password': _passwordController.text,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// final response = await http.post(
|
||||||
|
// url,
|
||||||
|
// headers: {'Content-Type': 'application/json'},
|
||||||
|
// body: jsonEncode({
|
||||||
|
// 'email': _emailController.text.trim(),
|
||||||
|
// 'password': _passwordController.text,
|
||||||
|
// }),
|
||||||
|
// );
|
||||||
|
|
||||||
final data = jsonDecode(response.body);
|
final data = jsonDecode(response.body);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
// Login berhasil
|
// Login berhasil
|
||||||
|
@ -79,12 +91,31 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<String> fetchUserNameByToken(String token) async {
|
||||||
|
// final url = Uri.parse('http://192.168.1.130:8000/api/user-by-token/$token');
|
||||||
|
// final response = await http.get(
|
||||||
|
// url,
|
||||||
|
// headers: {'Authorization': 'Bearer $token', 'Accept': 'application/json'},
|
||||||
|
// );
|
||||||
|
// if (response.statusCode == 200) {
|
||||||
|
// final data = jsonDecode(response.body);
|
||||||
|
// return data['data']?['name'] ?? '';
|
||||||
|
// } else {
|
||||||
|
// return '';
|
||||||
|
// }
|
||||||
|
// }
|
||||||
Future<String> fetchUserNameByToken(String token) async {
|
Future<String> fetchUserNameByToken(String token) async {
|
||||||
final url = Uri.parse('http://localhost:8000/api/user-by-token/$token');
|
final url = Uri.parse('${AppConfig.baseUrl}/api/user-by-token/$token');
|
||||||
|
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
url,
|
url,
|
||||||
headers: {'Authorization': 'Bearer $token', 'Accept': 'application/json'},
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'X-Platform': 'mobile',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final data = jsonDecode(response.body);
|
final data = jsonDecode(response.body);
|
||||||
return data['data']?['name'] ?? '';
|
return data['data']?['name'] ?? '';
|
||||||
|
@ -214,30 +245,30 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Row(
|
// Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
// children: [
|
||||||
const Text("Don't have an account? "),
|
// const Text("Don't have an account? "),
|
||||||
GestureDetector(
|
// GestureDetector(
|
||||||
onTap: () {
|
// onTap: () {
|
||||||
Navigator.push(
|
// Navigator.push(
|
||||||
context,
|
// context,
|
||||||
MaterialPageRoute(
|
// MaterialPageRoute(
|
||||||
builder: (context) => const RegisterScreen(),
|
// builder: (context) => const RegisterScreen(),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
child: const Text(
|
// child: const Text(
|
||||||
'Sign up',
|
// 'Sign up',
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
color: Colors.blue,
|
// color: Colors.blue,
|
||||||
fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 24),
|
// const SizedBox(height: 24),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
@ -13,7 +14,7 @@ import 'riwayat_screen.dart';
|
||||||
// - iOS simulator: 'http://localhost:8000'
|
// - iOS simulator: 'http://localhost:8000'
|
||||||
// - Perangkat nyata: 'http://<IP_PC>:8000'
|
// - Perangkat nyata: 'http://<IP_PC>:8000'
|
||||||
// Untuk Web, gunakan host yang bisa diakses browser.
|
// Untuk Web, gunakan host yang bisa diakses browser.
|
||||||
const String baseUrl = 'http://localhost:8000';
|
const String baseUrl = '${AppConfig.baseUrl}';
|
||||||
|
|
||||||
class ProfileScreen extends StatefulWidget {
|
class ProfileScreen extends StatefulWidget {
|
||||||
final String token;
|
final String token;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
final url = Uri.parse('http://localhost:8000/api/register');
|
final url = Uri.parse('${AppConfig.baseUrl}/api/register');
|
||||||
// Ganti jika base URL berbeda
|
// Ganti jika base URL berbeda
|
||||||
try {
|
try {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:absen/config/config.dart';
|
||||||
import 'package:absen/profile_screen.dart';
|
import 'package:absen/profile_screen.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
@ -32,7 +33,7 @@ class _RiwayatScreenState extends State<RiwayatScreen>
|
||||||
|
|
||||||
Future<List<Map<String, dynamic>>> fetchAbsensi() async {
|
Future<List<Map<String, dynamic>>> fetchAbsensi() async {
|
||||||
String urlStr =
|
String urlStr =
|
||||||
'http://localhost:8000/api/employee/attendance/history?length=20&start=0';
|
'${AppConfig.baseUrl}/api/employee/attendance/history?length=20&start=0';
|
||||||
if (_startDate != null) {
|
if (_startDate != null) {
|
||||||
urlStr += '&start_date=${DateFormat('yyyy-MM-dd').format(_startDate!)}';
|
urlStr += '&start_date=${DateFormat('yyyy-MM-dd').format(_startDate!)}';
|
||||||
}
|
}
|
||||||
|
@ -57,7 +58,7 @@ class _RiwayatScreenState extends State<RiwayatScreen>
|
||||||
|
|
||||||
Future<List<Map<String, dynamic>>> fetchPermission() async {
|
Future<List<Map<String, dynamic>>> fetchPermission() async {
|
||||||
String urlStr =
|
String urlStr =
|
||||||
'http://localhost:8000/api/employee/permission/history?length=20&start=0';
|
'${AppConfig.baseUrl}/api/employee/permission/history?length=20&start=0';
|
||||||
if (_startDate != null) {
|
if (_startDate != null) {
|
||||||
urlStr += '&start_date=${DateFormat('yyyy-MM-dd').format(_startDate!)}';
|
urlStr += '&start_date=${DateFormat('yyyy-MM-dd').format(_startDate!)}';
|
||||||
}
|
}
|
||||||
|
@ -294,6 +295,41 @@ class _RiwayatScreenState extends State<RiwayatScreen>
|
||||||
itemCount: data.length,
|
itemCount: data.length,
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
final item = data[i];
|
final item = data[i];
|
||||||
|
final status = item['status'] ?? '-';
|
||||||
|
late Color statusColor;
|
||||||
|
late String statusText;
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case 'pending':
|
||||||
|
statusColor = const Color(0xFFFFC542);
|
||||||
|
statusText = 'Menunggu';
|
||||||
|
break;
|
||||||
|
case 'accepted':
|
||||||
|
statusColor = const Color(0xFF1BCFB4);
|
||||||
|
statusText = 'Diterima';
|
||||||
|
break;
|
||||||
|
case 'jam_kerja_kurang':
|
||||||
|
statusColor = const Color(0xFFE57373);
|
||||||
|
statusText = 'Jam Kerja Kurang';
|
||||||
|
break;
|
||||||
|
case 'lembur':
|
||||||
|
statusColor = const Color(0xFF4F8DFD);
|
||||||
|
statusText = 'Lembur';
|
||||||
|
break;
|
||||||
|
case 'late':
|
||||||
|
statusColor = const Color(0xFFFF7043);
|
||||||
|
statusText = 'Terlambat';
|
||||||
|
break;
|
||||||
|
case 'rejected':
|
||||||
|
statusColor = const Color(0xFFD32F2F);
|
||||||
|
statusText = 'Ditolak';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
statusColor = const Color(0xFF9E9E9E);
|
||||||
|
statusText =
|
||||||
|
status[0].toUpperCase() + status.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
|
@ -317,29 +353,13 @@ class _RiwayatScreenState extends State<RiwayatScreen>
|
||||||
vertical: 6,
|
vertical: 6,
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color:
|
color: statusColor.withOpacity(0.15),
|
||||||
item['status'] == 'accepted'
|
|
||||||
? const Color(
|
|
||||||
0xFF1BCFB4,
|
|
||||||
).withOpacity(0.15)
|
|
||||||
: (item['status'] == 'pending'
|
|
||||||
? const Color(
|
|
||||||
0xFFFFC542,
|
|
||||||
).withOpacity(0.15)
|
|
||||||
: const Color(
|
|
||||||
0xFFE57373,
|
|
||||||
).withOpacity(0.15)),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
item['status'] ?? '-',
|
statusText,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color:
|
color: statusColor,
|
||||||
item['status'] == 'accepted'
|
|
||||||
? const Color(0xFF1BCFB4)
|
|
||||||
: (item['status'] == 'pending'
|
|
||||||
? const Color(0xFFFFC542)
|
|
||||||
: const Color(0xFFE57373)),
|
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
104
pubspec.lock
104
pubspec.lock
|
@ -1,6 +1,22 @@
|
||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.7"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -25,6 +41,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
checked_yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: checked_yaml
|
||||||
|
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.3"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.2"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -158,6 +190,14 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_launcher_icons:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_launcher_icons
|
||||||
|
sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.14.4"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
@ -204,10 +244,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: geolocator_android
|
name: geolocator_android
|
||||||
sha256: "114072db5d1dce0ec0b36af2697f55c133bc89a2c8dd513e137c0afe59696ed4"
|
sha256: "179c3cb66dfa674fc9ccbf2be872a02658724d1c067634e2c427cf6df7df901a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.1+1"
|
version: "5.0.2"
|
||||||
geolocator_apple:
|
geolocator_apple:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -260,10 +300,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: google_maps_flutter_android
|
name: google_maps_flutter_android
|
||||||
sha256: ab83128296fbeaa52e8f2b3bf53bcd895e64778edddcdc07bc8f33f4ea78076c
|
sha256: "356ee9c65f38a104f7c4988e6952e52addb3b6cb1601839dd2010d7a502afcf0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.16.1"
|
version: "2.16.2"
|
||||||
google_maps_flutter_ios:
|
google_maps_flutter_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -284,10 +324,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: google_maps_flutter_web
|
name: google_maps_flutter_web
|
||||||
sha256: a9822dbf31a3f76f239f6bda346511b051d3edf739806e9091be2729e8b645de
|
sha256: ce2cac714e5462bf761ff2fdfc3564c7e5d7ed0578268dccb0a54dbdb1e6214e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.12+1"
|
version: "0.5.12+2"
|
||||||
html:
|
html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -312,6 +352,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.2"
|
version: "4.1.2"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.4"
|
||||||
image_picker:
|
image_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -384,6 +432,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.19.0"
|
version: "0.19.0"
|
||||||
|
json_annotation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: json_annotation
|
||||||
|
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.9.0"
|
||||||
latlong2:
|
latlong2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -436,10 +492,10 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: logger
|
name: logger
|
||||||
sha256: be4b23575aac7ebf01f225a241eb7f6b5641eeaf43c6a8613510fc2f8cf187d1
|
sha256: "2621da01aabaf223f8f961e751f2c943dbb374dc3559b982f200ccedadaa6999"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0"
|
version: "2.6.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -528,6 +584,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -552,6 +616,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
posix:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: posix
|
||||||
|
sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.3"
|
||||||
proj4dart:
|
proj4dart:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -765,6 +837,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.5.0"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.7.0 <4.0.0"
|
dart: ">=3.7.0 <4.0.0"
|
||||||
flutter: ">=3.27.0"
|
flutter: ">=3.27.0"
|
||||||
|
|
|
@ -51,6 +51,7 @@ dependencies:
|
||||||
# web
|
# web
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
flutter_launcher_icons: ^0.14.4
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
@ -62,6 +63,10 @@ dev_dependencies:
|
||||||
flutter_lints: ^5.0.0
|
flutter_lints: ^5.0.0
|
||||||
http: ^1.4.0
|
http: ^1.4.0
|
||||||
|
|
||||||
|
flutter_launcher_icons:
|
||||||
|
android: true
|
||||||
|
ios: true
|
||||||
|
image_path: "assets/logom2.png"
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
@ -73,6 +78,7 @@ flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/logom.png
|
- assets/logom.png
|
||||||
|
- assets/logom2.jpg
|
||||||
# To add assets to your application, add an assets section, like this:
|
# To add assets to your application, add an assets section, like this:
|
||||||
# assets:
|
# assets:
|
||||||
# - images/a_dot_burr.jpeg
|
# - images/a_dot_burr.jpeg
|
||||||
|
|
Loading…
Reference in New Issue