0% menganggap dokumen ini bermanfaat (0 suara)
236 tayangan

Source Code Flutter

Dokumen tersebut merangkum proses pengerjaan proyek MIROTA mulai dari desain awal, penggunaan database, CRUD, API, state management, dan hasil akhir proyek berupa aplikasi Flutter. Proyek ini berlangsung selama 23 hari dan menggunakan beberapa teknologi seperti Figma, MySQL, PHPMyAdmin, dan API untuk menampilkan berita.

Diunggah oleh

aris febriansyah
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai DOCX, PDF, TXT atau baca online di Scribd
0% menganggap dokumen ini bermanfaat (0 suara)
236 tayangan

Source Code Flutter

Dokumen tersebut merangkum proses pengerjaan proyek MIROTA mulai dari desain awal, penggunaan database, CRUD, API, state management, dan hasil akhir proyek berupa aplikasi Flutter. Proyek ini berlangsung selama 23 hari dan menggunakan beberapa teknologi seperti Figma, MySQL, PHPMyAdmin, dan API untuk menampilkan berita.

Diunggah oleh

aris febriansyah
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai DOCX, PDF, TXT atau baca online di Scribd
Anda di halaman 1/ 29

MIROTA

Oleh Kelompok A1 :

VIRGIL HUTASOIT (2015344015)


ARIS FEBRIANSYAH (2015344033)

JURUSAN TEKNIK ELEKTRO


PROGRAM STUDI D4 TEKNIK OTOMASI
POLITEKNIK NEGERI BALI
2022
1. Proses Pengerjaan
Proses pengerjaan project MIROTA yaitu berlangsung selama 23 HARI hari terhitung sejak
pembuatan design UI pada figma hingga pengetesan tahap akhir yang sesuai dengan time
schedule pada kontrak kerja atau dibawah ini :

2. Design UI Awal
Awal design UI dibuat pada FIGMA
3. DATABASE
Database secara teknis merupakan sebuah sebutan yang digunakan untuk menyimpan sebuah
data pada suatu lokasi, pada projek ini menggunakan database mysql phpmyadmin yang
menggunakan xampp sebagai media koneksi karena menggunakan xampp maka database
disimpan pada localhost saja sehingga membuat orang selain host tidak bisa mengakses data,
pada database projek ini digunakan untuk mengontrol user yang masuk atau login maupun
register yang dilakukan oleh admin. Pada database kami membuat 6 tabel data yang saling
memiliki relasi.
4. CRUD
CRUD merupakan bagian dari database yaitu CREATE, READ, UPDATE dan DELET. Pada
projek menggunakan CRUD untuk membuat akun, login dengan tabel database sebagai
berikut:
5. API
API adalah mekanisme yang memungkinkan dua komponen perangkat lunak untuk saling
berkomunikasi menggunakan serangkaian definisi dan protokol. API sendiri dapat berupa
dummy data maupun data – data yang lain, API dapat dikoneksikan pada berbagai
Programming seperti flutter/dart sehingga pada projek ini kami menggunakan API untuk
menampilkan berita pada aplikasi “MIROTA”. API yang kami gunakan bersumber dari
Postman yang di konversi dari Bahasa pemograman json menjadi Bahasa pemograman dart
dengan bantuan “app.quictype.io”
6. State Management
Menurut sepengetahuan kami mengenai state management yaitu seperti statefull dan stateless
yang biasa kami gunakan, namun state management digunakan untuk memisahkan mana
yang antara logic dan view.
7. Hasil
8. Source Code

(Souce Code Aplikasi Flutter)

⮚ Main.dart

import 'package:flutter/material.dart';
import 'package:presensi/home-page.dart';
import 'package:presensi/login-page.dart';
import 'package:presensi/simpan-page.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {


const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
}
}

⮚ login-page.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:presensi/home-page.dart';
import 'package:http/http.dart' as myHttp;
import 'package:presensi/models/login-response.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LoginPage extends StatefulWidget {


const LoginPage({Key? key}) : super(key: key);

@override
State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {


final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
late Future<String> _name, _token;

@override
void initState() {
// TODO: implement initState
super.initState();
_token = _prefs.then((SharedPreferences prefs) {
return prefs.getString("token") ?? "";
});

_name = _prefs.then((SharedPreferences prefs) {


return prefs.getString("name") ?? "";
});
checkToken(_token, _name);
}

checkToken(token, name) async {


String tokenStr = await token;
String nameStr = await name;
if (tokenStr != "" && nameStr != "") {
Future.delayed(Duration(seconds: 1), () async {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => HomePage()))
.then((value) {
setState(() {});
});
});
}
}

Future login(email, password) async {


LoginResponseModel? loginResponseModel;
Map<String, String> body = {"email": email, "password": password};
var response = await myHttp.post(
Uri.parse('https://punyawa.com/presensi/public/api/login'),
body: body);
if (response.statusCode == 401) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Email atau password salah")));
} else {
loginResponseModel =
LoginResponseModel.fromJson(json.decode(response.body));
print('HASIL ' + response.body);
saveUser(loginResponseModel.data.token, loginResponseModel.data.name);
}
}
Future saveUser(token, name) async {
try {
print("LEWAT SINI " + token + " | " + name);
final SharedPreferences pref = await _prefs;
pref.setString("name", name);
pref.setString("token", token);
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => HomePage()))
.then((value) {
setState(() {});
});
} catch (err) {
print('ERROR :' + err.toString());
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(err.toString())));
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text("LOGIN")),
SizedBox(height: 20),
Text("Email"),
TextField(
controller: emailController,
),
SizedBox(height: 20),
Text("Password"),
TextField(
controller: passwordController,
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
login(emailController.text, passwordController.text);
},
child: Text("Masuk"))
],
),
),
)),
);
}
}
⮚ home-page.dart
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:presensi/models/home-response.dart';
import 'package:presensi/simpan-page.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as myHttp;

class HomePage extends StatefulWidget {


const HomePage({Key? key}) : super(key: key);

@override
State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {


final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
late Future<String> _name, _token;
HomeResponseModel? homeResponseModel;
Datum? hariIni;
List<Datum> riwayat = [];

@override
void initState() {
// TODO: implement initState
super.initState();
_token = _prefs.then((SharedPreferences prefs) {
return prefs.getString("token") ?? "";
});
_name = _prefs.then((SharedPreferences prefs) {
return prefs.getString("name") ?? "";
});
}

Future getData() async {


final Map<String, String> headres = {
'Authorization': 'Bearer ' + await _token
};
var response = await myHttp.get(
Uri.parse('https://punyawa.com/presensi/public/api/get-presensi'),
headers: headres);
homeResponseModel =
HomeResponseModel.fromJson(json.decode(response.body));
riwayat.clear();
homeResponseModel!.data.forEach((element) {
if (element.isHariIni) {
hariIni = element;
} else {
riwayat.add(element);
}
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else {
return SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FutureBuilder(
future: _name,
builder: (BuildContext context,
AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return CircularProgressIndicator();
} else {
if (snapshot.hasData) {
print(snapshot.data);
return Text(snapshot.data!,
style: TextStyle(fontSize: 18));
} else {
return Text("-", style: TextStyle(fontSize: 18));
}
}
}),
SizedBox(
height: 20,
),
Container(
width: 400,
decoration: BoxDecoration(color: Colors.blue[800]),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(children: [
Text(hariIni?.tanggal ?? '-',
style:
TextStyle(color: Colors.white, fontSize: 16)),
SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(hariIni?.masuk ?? '-',
style: TextStyle(
color: Colors.white, fontSize: 24)),
Text("Masuk",
style: TextStyle(
color: Colors.white, fontSize: 16))
],
),
Column(
children: [
Text(hariIni?.pulang ?? '-',
style: TextStyle(
color: Colors.white, fontSize: 24)),
Text("Pulang",
style: TextStyle(
color: Colors.white, fontSize: 16))
],
)
],
)
]),
),
),
SizedBox(height: 20),
Text("Riwayat Presensi"),
Expanded(
child: ListView.builder(
itemCount: riwayat.length,
itemBuilder: (context, index) => Card(
child: ListTile(
leading: Text(riwayat[index].tanggal),
title: Row(children: [
Column(
children: [
Text(riwayat[index].masuk,
style: TextStyle(fontSize: 18)),
Text("Masuk", style: TextStyle(fontSize: 14))
],
),
SizedBox(width: 20),
Column(
children: [
Text(riwayat[index].pulang,
style: TextStyle(fontSize: 18)),
Text("Pulang", style: TextStyle(fontSize: 14))
],
),
]),
),
),
),
),
],
),
));
}
}),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => SimpanPage()))
.then((value) {
setState(() {});
});
},
child: Icon(Icons.add),
),
);
}
}

⮚ simpan-page.dart

import 'dart:convert';

import 'package:flutter/material.dart';

import 'package:flutter/src/foundation/key.dart';

import 'package:flutter/src/widgets/framework.dart';

import 'package:location/location.dart';

import 'package:presensi/models/save-presensi-response.dart';

import 'package:shared_preferences/shared_preferences.dart';

import 'package:syncfusion_flutter_maps/maps.dart';

import 'package:http/http.dart' as myHttp;

class SimpanPage extends StatefulWidget {

const SimpanPage({Key? key}) : super(key: key);


@override

State<SimpanPage> createState() => _SimpanPageState();

class _SimpanPageState extends State<SimpanPage> {

final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

late Future<String> _token;

@override

void initState() {

super.initState();

_token = _prefs.then((SharedPreferences prefs) {

return prefs.getString("token") ?? "";

});

Future<LocationData?> _currenctLocation() async {

bool serviceEnable;

PermissionStatus permissionGranted;

Location location = new Location();


serviceEnable = await location.serviceEnabled();

if (!serviceEnable) {

serviceEnable = await location.requestService();

if (!serviceEnable) {

return null;

permissionGranted = await location.hasPermission();

if (permissionGranted == PermissionStatus.denied) {

permissionGranted = await location.requestPermission();

if (permissionGranted != PermissionStatus.granted) {

return null;

return await location.getLocation();

Future savePresensi(latitude, longitude) async {

SavePresensiResponseModel savePresensiResponseModel;

Map<String, String> body = {


"latitude": latitude.toString(),

"longitude": longitude.toString()

};

Map<String, String> headers = {'Authorization': 'Bearer ' + await _token};

var response = await myHttp.post(

Uri.parse("https://punyawa.com/presensi/public/api/save-presensi"),

body: body,

headers: headers);

savePresensiResponseModel =

SavePresensiResponseModel.fromJson(json.decode(response.body));

if (savePresensiResponseModel.success) {

ScaffoldMessenger.of(context)

.showSnackBar(SnackBar(content: Text('Sukses simpan Presensi')));

Navigator.pop(context);

} else {

ScaffoldMessenger.of(context)

.showSnackBar(SnackBar(content: Text('Gagal simpan Presensi')));

}
@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text("Presensi"),

),

body: FutureBuilder<LocationData?>(

future: _currenctLocation(),

builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {

if (snapshot.hasData) {

final LocationData currentLocation = snapshot.data;

print("KODING : " +

currentLocation.latitude.toString() +

"|"+

currentLocation.longitude.toString());

return SafeArea(

child: Column(

children: [

Container(

height: 300,

child: SfMaps(

layers: [
MapTileLayer(

initialFocalLatLng: MapLatLng(

currentLocation.latitude!,

currentLocation.longitude!),

initialZoomLevel: 15,

initialMarkersCount: 1,

urlTemplate:

"https://tile.openstreetmap.org/{z}/{x}/{y}.png",

markerBuilder: (BuildContext context, int index) {

return MapMarker(

latitude: currentLocation.latitude!,

longitude: currentLocation.longitude!,

child: Icon(

Icons.location_on,

color: Colors.red,

),

);

},

],

),

),

SizedBox(
height: 20,

),

ElevatedButton(

onPressed: () {

savePresensi(currentLocation.latitude,

currentLocation.longitude);

},

child: Text("Simpan Presensi"))

],

));

} else {

return Center(

child: CircularProgressIndicator(),

);

}),

);

⮚ home-response.dart

// To parse this JSON data, do

// final homeResponseModel = homeResponseModelFromJson(jsonString);

import 'dart:convert';
HomeResponseModel homeResponseModelFromJson(String str) =>

HomeResponseModel.fromJson(json.decode(str));

String homeResponseModelToJson(HomeResponseModel data) =>

json.encode(data.toJson());

class HomeResponseModel {

HomeResponseModel({

required this.success,

required this.data,

required this.message,

});

bool success;

List<Datum> data;

String message;

factory HomeResponseModel.fromJson(Map<String, dynamic> json) =>

HomeResponseModel(

success: json["success"],

data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),

message: json["message"],

);

Map<String, dynamic> toJson() => {


"success": success,

"data": List<dynamic>.from(data.map((x) => x.toJson())),

"message": message,

};

class Datum {

Datum({

required this.id,

required this.userId,

required this.latitude,

required this.longitude,

required this.tanggal,

required this.masuk,

required this.pulang,

required this.createdAt,

required this.updatedAt,

required this.isHariIni,

});

int id;

String userId;

String latitude;
String longitude;

String tanggal;

String masuk;

String pulang;

DateTime createdAt;

DateTime updatedAt;

bool isHariIni;

factory Datum.fromJson(Map<String, dynamic> json) => Datum(

id: json["id"],

userId: json["user_id"],

latitude: json["latitude"],

longitude: json["longitude"],

tanggal: json["tanggal"],

masuk: json["masuk"],

pulang: json["pulang"],

createdAt: DateTime.parse(json["created_at"]),

updatedAt: DateTime.parse(json["updated_at"]),

isHariIni: json["is_hari_ini"],

);

Map<String, dynamic> toJson() => {

"id": id,
"user_id": userId,

"latitude": latitude,

"longitude": longitude,

"tanggal": tanggal,

"masuk": masuk,

"pulang": pulang,

"created_at": createdAt.toIso8601String(),

"updated_at": updatedAt.toIso8601String(),

"is_hari_ini": isHariIni,

};

⮚ Login-Response.dart
// To parse this JSON data, do
//
// final loginResponseModel = loginResponseModelFromJson(jsonString);

import 'dart:convert';

LoginResponseModel loginResponseModelFromJson(String str) =>


LoginResponseModel.fromJson(json.decode(str));

String loginResponseModelToJson(LoginResponseModel data) =>


json.encode(data.toJson());

class LoginResponseModel {
LoginResponseModel({
required this.success,
required this.message,
required this.data,
});

bool success;
String message;
Data data;

factory LoginResponseModel.fromJson(Map<String, dynamic> json) =>


LoginResponseModel(
success: json["success"],
message: json["message"],
data: Data.fromJson(json["data"]),
);

Map<String, dynamic> toJson() => {


"success": success,
"message": message,
"data": data.toJson(),
};
}

class Data {
Data({
required this.id,
required this.name,
required this.email,
required this.emailVerifiedAt,
required this.createdAt,
required this.updatedAt,
required this.token,
required this.tokenType,
});

int id;
String name;
String email;
dynamic emailVerifiedAt;
DateTime createdAt;
DateTime updatedAt;
String token;
String tokenType;

factory Data.fromJson(Map<String, dynamic> json) => Data(


id: json["id"],
name: json["name"],
email: json["email"],
emailVerifiedAt: json["email_verified_at"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
token: json["token"],
tokenType: json["token_type"],
);

Map<String, dynamic> toJson() => {


"id": id,
"name": name,
"email": email,
"email_verified_at": emailVerifiedAt,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
"token": token,
"token_type": tokenType,
};
}
⮚ Save-Presensi-response.dart
// To parse this JSON data, do
//
// final savePresensiResponseModel =
savePresensiResponseModelFromJson(jsonString);

import 'dart:convert';

SavePresensiResponseModel savePresensiResponseModelFromJson(String str) =>


SavePresensiResponseModel.fromJson(json.decode(str));

String savePresensiResponseModelToJson(SavePresensiResponseModel data) =>


json.encode(data.toJson());

class SavePresensiResponseModel {
SavePresensiResponseModel({
required this.success,
required this.data,
required this.message,
});

bool success;
Data data;
String message;

factory SavePresensiResponseModel.fromJson(Map<String, dynamic> json) =>


SavePresensiResponseModel(
success: json["success"],
data: Data.fromJson(json["data"]),
message: json["message"],
);

Map<String, dynamic> toJson() => {


"success": success,
"data": data.toJson(),
"message": message,
};
}

class Data {
Data({
required this.id,
required this.userId,
required this.latitude,
required this.longitude,
required this.tanggal,
required this.masuk,
required this.pulang,
required this.createdAt,
required this.updatedAt,
});

int id;
String userId;
String latitude;
String longitude;
DateTime tanggal;
String masuk;
dynamic pulang;
DateTime createdAt;
DateTime updatedAt;

factory Data.fromJson(Map<String, dynamic> json) => Data(


id: json["id"],
userId: json["user_id"],
latitude: json["latitude"],
longitude: json["longitude"],
tanggal: DateTime.parse(json["tanggal"]),
masuk: json["masuk"],
pulang: json["pulang"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);

Map<String, dynamic> toJson() => {


"id": id,
"user_id": userId,
"latitude": latitude,
"longitude": longitude,
"tanggal":
"${tanggal.year.toString().padLeft(4, '0')}-${tanggal.month.toString().padLeft(2,
'0')}-${tanggal.day.toString().padLeft(2, '0')}",
"masuk": masuk,
"pulang": pulang,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
};
}

9. Eror
Dalam Aplikasi ini kami mendapatkan eror dimana aplikasi Mirota tidak bisa berjalan
dengan yang diharapkan hal ini terjadi dikarenakan beberpa kendalan diantaranya
dikarenakan konfigurasi tipe data yang masih belum sinkron dan perbedaan tipe data yang
disajikan antara database dengan flutter seperti gambar dibawah ini
10. Kesimpulan
Kami mengakui dalam pembuatan proyek ini masih banyak kurang dan jauh dari kayta
sempurna, hal ini dikarenakan kurangnya pengalaman dan belum pahamnya kami
terhadap materi flutter, namun kami akan perbaiki semua dikemudian hari yang nantinya
akan bisa membuat aplikasi yang bisa sesuai dengan kontrak perjanjian sebelumnya

Lampiran :

Semua file dalam kodingan ini akan kamki sertakan dalam bentuk winrar

Anda mungkin juga menyukai