From 03e4a4793e537e950eb10e17877872791bda510d Mon Sep 17 00:00:00 2001
From: Muhammad Tsaqib Ibadillah Wahid <muhammad.tsaqib@ui.ac.id>
Date: Wed, 7 Dec 2022 22:58:56 +0700
Subject: [PATCH 1/3] Pembuatan model, modelDTO, restService, restServiceImpl,
 dan file-file lainnya terkait pasien. (Untuk kebutuhan fitur register
 pasien).

---
 .../TK/SpringTkApap/auth/setting/Setting.java |   4 +-
 .../user/controller/PasienRestController.java |  61 +++
 .../TK/SpringTkApap/user/model/PasienDTO.java |  30 ++
 .../user/service/PasienRestService.java       |  13 +
 .../user/service/PasienRestServiceImpl.java   |  62 +++
 tk_apap_flutter/lib/DTO/Pasien.dart           |   9 +
 .../lib/pages/createAppointment.dart          |   4 +-
 tk_apap_flutter/lib/pages/login.dart          |  21 +-
 tk_apap_flutter/lib/pages/register.dart       | 411 ++++++++++++++++++
 tk_apap_flutter/pubspec.lock                  |  10 +-
 10 files changed, 608 insertions(+), 17 deletions(-)
 create mode 100644 SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
 create mode 100644 SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/model/PasienDTO.java
 create mode 100644 SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java
 create mode 100644 SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
 create mode 100644 tk_apap_flutter/lib/DTO/Pasien.dart
 create mode 100644 tk_apap_flutter/lib/pages/register.dart

diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java
index 23126f8..74652cf 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java
@@ -5,7 +5,9 @@ public class Setting {
     private Setting() {
     }
 
-    public static final String CLIENT_BASE_URL = "https://apap-tk-53.cs.ui.ac.id";
+    public static final String CLIENT_BASE_URL = "http://localhost:8080";
+//    URL deploy  https://apap-tk-53.cs.ui.ac.id
+//    URL local http://localhost:8080
 
     public static final String CLIENT_LOGIN = CLIENT_BASE_URL + "/validate-ticket";
 
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
new file mode 100644
index 0000000..ecfe39e
--- /dev/null
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
@@ -0,0 +1,61 @@
+package spring.TK.SpringTkApap.user.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.server.ResponseStatusException;
+import spring.TK.SpringTkApap.user.model.PasienDTO;
+import spring.TK.SpringTkApap.user.service.PasienRestService;
+import spring.TK.SpringTkApap.user.model.PasienModel;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+
+@RestController
+@RequestMapping("/api/pasien")
+public class PasienRestController {
+
+    @Autowired
+    PasienRestService pasienRestService;
+
+    @PostMapping("/register")
+    private ResponseEntity<String> registerPasien(@RequestBody PasienDTO pasien, BindingResult bindingResult){
+        if (bindingResult.hasFieldErrors()) {
+            throw new ResponseStatusException(
+                    HttpStatus.BAD_REQUEST, "Request body has invalid type or missing field."
+            );
+        } else {
+            pasienRestService.createPasien(pasien);
+            return ResponseEntity.ok("Created new pasien");
+        }
+    }
+
+    @GetMapping("/{uuid}")
+    private PasienModel getPasien(@PathVariable(name = "uuid") String uuid){
+        try {
+            return pasienRestService.getPasien(uuid);
+        } catch (NoSuchElementException e) {
+            throw new ResponseStatusException(
+                    HttpStatus.NOT_FOUND, "Pasien dengan id " + uuid + " tidak ditemukan."
+            );
+        }
+    }
+
+    @GetMapping("/all")
+    private List<PasienModel> getAllPasien(){
+        return pasienRestService.retrievePasien();
+    }
+
+    @PutMapping(value = "/top-up/{uuid}")
+    private PasienModel topUpSaldo(@PathVariable("uuid") String uuid, @RequestBody PasienModel pasien){
+        try{
+            return pasienRestService.topUpSaldo(uuid, pasien);
+        } catch (NoSuchElementException e) {
+            throw new ResponseStatusException(
+                    HttpStatus.NOT_FOUND, "Pasien dengan id " + uuid + " tidak ditemukan."
+            );
+        }
+    }
+}
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/model/PasienDTO.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/model/PasienDTO.java
new file mode 100644
index 0000000..3a91b87
--- /dev/null
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/model/PasienDTO.java
@@ -0,0 +1,30 @@
+package spring.TK.SpringTkApap.user.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class PasienDTO implements Serializable {
+    @JsonProperty("name")
+    private String name;
+
+    @JsonProperty("username")
+    private String username;
+
+    @JsonProperty("email")
+    private String email;
+
+    @JsonProperty("password")
+    private String password;
+
+    @JsonProperty("umur")
+    private String umur;
+}
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java
new file mode 100644
index 0000000..17167b9
--- /dev/null
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java
@@ -0,0 +1,13 @@
+package spring.TK.SpringTkApap.user.service;
+
+import spring.TK.SpringTkApap.user.model.PasienDTO;
+import spring.TK.SpringTkApap.user.model.PasienModel;
+
+import java.util.List;
+
+public interface PasienRestService {
+    PasienModel createPasien(PasienDTO pasienDTO);
+    List<PasienModel> retrievePasien();
+    PasienModel getPasien(String uuid);
+    PasienModel topUpSaldo(String uuid, PasienModel pasienUpdate);
+}
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
new file mode 100644
index 0000000..a8dff9b
--- /dev/null
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
@@ -0,0 +1,62 @@
+package spring.TK.SpringTkApap.user.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import spring.TK.SpringTkApap.auth.model.RolesEnum;
+import spring.TK.SpringTkApap.auth.service.AuthServiceImpl;
+import spring.TK.SpringTkApap.user.model.PasienDTO;
+import spring.TK.SpringTkApap.user.model.PasienModel;
+import spring.TK.SpringTkApap.user.repository.PasienDB;
+import spring.TK.SpringTkApap.user.service.PasienRestService;
+
+import javax.transaction.Transactional;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
+@Service
+@Transactional
+public class PasienRestServiceImpl implements PasienRestService {
+
+    @Autowired
+    PasienDB pasienDb;
+
+    @Autowired
+    AuthServiceImpl authService;
+
+    @Override
+    public PasienModel createPasien(PasienDTO pasienDTO) {
+        PasienModel pasien = new PasienModel();
+
+        pasien.setNama(pasienDTO.getName());
+        pasien.setUsername(pasienDTO.getUsername());
+        pasien.setEmail(pasienDTO.getEmail());
+        pasien.setPassword(authService.encrypt(pasienDTO.getPassword()));
+        pasien.setRole(RolesEnum.PASIEN);
+        pasien.setUmur(Integer.valueOf(pasienDTO.getUmur()));
+        pasien.setSaldo(0);
+        pasien.setListAppointment(new ArrayList<>());
+
+        return pasienDb.save(pasien); }
+
+    @Override
+    public List<PasienModel> retrievePasien() { return pasienDb.findAll(); }
+
+    @Override
+    public PasienModel getPasien(String uuid) {
+        Optional<PasienModel> pasien = pasienDb.findById(uuid);
+        if(pasien.isPresent()){
+            return pasien.get();
+        }
+        throw new NoSuchElementException();
+    }
+
+    @Override
+    public PasienModel topUpSaldo(String uuid, PasienModel pasienUpdate) {
+        PasienModel pasien = getPasien(uuid);
+        pasien.setSaldo(pasienUpdate.getSaldo());
+
+        return pasienDb.save(pasien);
+    }
+}
diff --git a/tk_apap_flutter/lib/DTO/Pasien.dart b/tk_apap_flutter/lib/DTO/Pasien.dart
new file mode 100644
index 0000000..811cc63
--- /dev/null
+++ b/tk_apap_flutter/lib/DTO/Pasien.dart
@@ -0,0 +1,9 @@
+class Pasien {
+  String name = '';
+  String username = '';
+  String email = '';
+  String password = '';
+  String umur = '';
+
+  Pasien(this.name, this.username, this.email, this.password, this.umur);
+}
\ No newline at end of file
diff --git a/tk_apap_flutter/lib/pages/createAppointment.dart b/tk_apap_flutter/lib/pages/createAppointment.dart
index 2170a5c..0d3c07c 100644
--- a/tk_apap_flutter/lib/pages/createAppointment.dart
+++ b/tk_apap_flutter/lib/pages/createAppointment.dart
@@ -19,7 +19,7 @@ class _CreateAppointmentState extends State<CreateAppointment> {
   // Data yang diperlukan tanggal dan waktu, dropdown [namaDokter - Tarif]
 
   Future<List<Dokter>> getAllDoktor() async {
-    var uri = Uri.parse('http://192.168.226.119:8080/api/doktor/all');
+    var uri = Uri.parse('http://192.168.1.100:8080/api/doktor/all');
     http.Response response = await http.get(uri);
     if (response.statusCode == 200) {
       List<Dokter> list = <Dokter>[];
@@ -94,7 +94,7 @@ class _CreateAppointmentState extends State<CreateAppointment> {
                           onPressed: () async {
                             var response = await http.post(
                               Uri.parse(
-                                  'http://192.168.226.119:8080/api/appointment/create'),
+                                  'http://192.168.1.100:8080/api/appointment/create'),
                               headers: {
                                 "Accept": "application/json",
                                 "content-type": "application/json"
diff --git a/tk_apap_flutter/lib/pages/login.dart b/tk_apap_flutter/lib/pages/login.dart
index 9c28310..70ce3dc 100644
--- a/tk_apap_flutter/lib/pages/login.dart
+++ b/tk_apap_flutter/lib/pages/login.dart
@@ -8,6 +8,7 @@ import 'package:google_fonts/google_fonts.dart';
 import 'package:http/http.dart' as http;
 import 'package:flutter_session_manager/flutter_session_manager.dart';
 import 'package:tk_apap_flutter/pages/HomeScreen.dart';
+import 'package:tk_apap_flutter/pages/register.dart';
 
 class Login extends StatefulWidget {
   static const routeName = '/login';
@@ -24,7 +25,7 @@ class _LoginState extends State<Login> {
   UserLogin user = UserLogin("", "");
   bool _isHidden = true;
 
-  final url = Uri.parse('http://192.168.226.119:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
+  final url = Uri.parse('http://192.168.1.100:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
   final header = <String, String> {
     'Content-Type':
     'application/json; charset=UTF-8'
@@ -100,10 +101,10 @@ class _LoginState extends State<Login> {
                           children: <Widget>[
                             const SizedBox(height: 30,),
                             new Image.asset(
-                            'assets/Logo.png',
-                            width: 180.0,
-                            height: 180.0,
-                            fit: BoxFit.cover,
+                              'assets/Logo.png',
+                              width: 180.0,
+                              height: 180.0,
+                              fit: BoxFit.cover,
                             ),
                             const SizedBox(height: 20,),
                             Container(
@@ -170,7 +171,7 @@ class _LoginState extends State<Login> {
                                       },
                                       decoration: InputDecoration(
                                           suffixIcon:
-                                            InkWell(
+                                          InkWell(
                                             onTap: _togglePasswordView,
                                             child: Icon(
                                               _isHidden ?
@@ -224,13 +225,15 @@ class _LoginState extends State<Login> {
                                           primary: const Color(0xff0d47a1), // Text Color
                                         ),
                                         onPressed: () {
-                                          Navigator.pushReplacement(
+                                          Navigator.push(
                                             context,
                                             MaterialPageRoute(
+                                              builder:
+                                              (context)=>Register()
                                             ),
                                           );
                                         },
-                                        child: const Text('Register',), //TODO: REGISTER PASIEN
+                                        child: const Text('Register',),
 
                                       ),
                                     ],
@@ -260,7 +263,7 @@ class _LoginState extends State<Login> {
     }
     return newMap;
   }
-  
+
   void saveSession(LinkedHashMap<String, dynamic> jsonResponse) async {
     for (var e in jsonResponse.entries) {
       await SessionManager().set(e.key, e.value);
diff --git a/tk_apap_flutter/lib/pages/register.dart b/tk_apap_flutter/lib/pages/register.dart
new file mode 100644
index 0000000..5820b94
--- /dev/null
+++ b/tk_apap_flutter/lib/pages/register.dart
@@ -0,0 +1,411 @@
+import 'dart:collection';
+import 'dart:convert';
+
+import 'package:flutter/services.dart';
+import 'package:font_awesome_flutter/font_awesome_flutter.dart';
+import 'package:tk_apap_flutter/DTO/Pasien.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:http/http.dart' as http;
+import 'package:flutter_session_manager/flutter_session_manager.dart';
+import 'package:tk_apap_flutter/pages/HomeScreen.dart';
+
+import 'Login.dart';
+
+class Register extends StatefulWidget {
+  static const routeName = '/register';
+
+  Register({Key key}) : super(key: key);
+
+  @override
+  _RegisterState createState() => _RegisterState();
+}
+
+class _RegisterState extends State<Register> {
+  final _formKey = GlobalKey<FormState>();
+  // final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+
+  Pasien pasien;
+  String name;
+  String username;
+  String email;
+  String password;
+  String umur;
+
+  bool _isHidden = true;
+
+  final url = Uri.parse('http://192.168.1.100:8080/api/pasien'); //TODO:ubah sesuai IP Address, nanti pakai link web
+
+  // Future save() async {
+  //   var res = await http.post(url,
+  //     headers: {'Content-Type': 'application/json'},
+  //     body: json.encode({
+  //       'name': pasien.name,
+  //       'username': pasien.username,
+  //       'email': pasien.email,
+  //       'password': pasien.password,
+  //       'umur': pasien.umur,
+  //     }));
+  //   print(res.body);
+  //   print("hey");
+  //
+  //   if (res.body != null) {
+  //     Navigator.pop(context);
+  //   }
+
+    // final body = jsonEncode(<String, String>{
+    //   'name': pasien.name,
+    //   'username': pasien.username,
+    //   'email': pasien.email,
+    //   'password': pasien.password,
+    //   'umur': pasien.umur,
+    // });
+    //
+    // final response = await http.post(url,
+    //     headers: header,
+    //     body: body);
+    //
+    // if (response.body != null) {
+    //   final json = jsonEncode(response.body).toString();
+    //   print(response.body);
+    //   Navigator.pop(context);
+    // }
+  // }
+
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      backgroundColor: Colors.white,
+      // key: _scaffoldKey,
+      body: Builder(builder: (BuildContext context) {
+        return SafeArea(
+          child: NotificationListener<OverscrollIndicatorNotification>(
+            onNotification: (OverscrollIndicatorNotification overscroll) {
+              overscroll.disallowGlow();
+              return;
+            },
+            child: SingleChildScrollView(
+
+              child: Form(
+                  key: _formKey,
+                  child: Column(
+                    children: [
+                      Container(
+                        height: MediaQuery.of(context).size.height,
+                        width: MediaQuery.of(context).size.width,
+                        decoration: const BoxDecoration(
+                          color: const Color(0xffe3f2fd),
+                        ),
+                        child:
+                        Column(
+                          crossAxisAlignment: CrossAxisAlignment.center,
+                          children: <Widget>[
+                            const SizedBox(height: 30,),
+                            new Image.asset(
+                              'assets/Logo.png',
+                              width: 180.0,
+                              height: 180.0,
+                              fit: BoxFit.cover,
+                            ),
+                            const SizedBox(height: 20,),
+                            Container(
+                              width: 325,
+                              height: 495,
+                              decoration: const BoxDecoration(
+                                color: Colors.white,
+                                borderRadius: BorderRadius.all(Radius.circular(15)),
+                              ),
+                              child: Column(
+                                crossAxisAlignment: CrossAxisAlignment.center,
+                                children: [
+                                  const SizedBox(height: 15,),
+                                  const Text("Buat akun baru!",
+                                    style: TextStyle(
+                                        fontSize: 28,
+                                        fontWeight:FontWeight.bold
+                                    ),),
+                                  const SizedBox(height: 10,),
+                                  const Text("Silahkan Register akun RumahSehat",
+                                    style: TextStyle(
+                                      color: Colors.black,
+                                      fontSize: 15,
+                                    ),),
+                                  const SizedBox(height: 15,),
+                                  Container(
+                                    width: 260,
+                                    height: 40,
+                                    child: TextFormField(
+                                      controller: TextEditingController(text: name),
+                                      onChanged: (val) {
+                                        name = val;
+                                      },
+                                      validator: (value) {
+                                        if (value.isEmpty) {
+                                          return 'Name is Empty';
+                                        }
+                                        return null;
+                                      },
+                                      decoration: InputDecoration(
+                                          labelText: "Name",
+                                          border: OutlineInputBorder(
+                                            borderRadius: BorderRadius.all(Radius.circular(8)),
+                                          )
+                                      ),
+                                    ),
+                                  ),
+                                  const SizedBox(height: 15,),
+                                  Container(
+                                    width: 260,
+                                    height: 40,
+                                    child: TextFormField(
+                                      keyboardType: TextInputType.number,
+                                      controller: TextEditingController(text: umur),
+                                      onChanged: (val) {
+                                        umur = val;
+                                      },
+                                      inputFormatters: <TextInputFormatter>[
+                                        FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
+                                      ],
+                                      validator: (value) {
+                                        if (value.isEmpty) {
+                                          return 'Umur is Empty';
+                                        }
+                                        return null;
+                                      },
+                                      decoration: InputDecoration(
+                                          labelText: "Umur",
+                                          border: OutlineInputBorder(
+                                            borderRadius: BorderRadius.all(Radius.circular(8)),
+                                          )
+                                      ),
+                                    ),
+                                  ),
+                                  const SizedBox(height: 15,),
+                                  Container(
+                                    width: 260,
+                                    height: 40,
+                                    child: TextFormField(
+                                      controller: TextEditingController(text: username),
+                                      onChanged: (val) {
+                                        username = val;
+                                      },
+                                      validator: (value) {
+                                        if (value.isEmpty) {
+                                          return 'Username is Empty';
+                                        }
+                                        return null;
+                                      },
+                                      decoration: InputDecoration(
+                                          labelText: "Username",
+                                          border: OutlineInputBorder(
+                                            borderRadius: BorderRadius.all(Radius.circular(8)),
+                                          )
+                                      ),
+                                    ),
+                                  ),
+                                  const SizedBox(height: 15,),
+                                  Container(
+                                    width: 260,
+                                    height: 40,
+                                    child: TextFormField(
+                                      controller: TextEditingController(text: email),
+                                      onChanged: (val) {
+                                        email = val;
+                                      },
+                                      validator: (value) {
+                                        if (value.isEmpty) {
+                                          return 'Email is Empty';
+                                        }
+                                        return null;
+                                      },
+                                      decoration: InputDecoration(
+                                          labelText: "Email",
+                                          border: OutlineInputBorder(
+                                            borderRadius: BorderRadius.all(Radius.circular(8)),
+                                          )
+                                      ),
+                                    ),
+                                  ),
+                                  const SizedBox(height: 15,),
+                                  Container(
+                                    width: 260,
+                                    height: 40,
+                                    child: TextFormField(
+                                      obscureText: _isHidden,
+                                      controller:
+                                      TextEditingController(text: password),
+                                      onChanged: (val) {
+                                        password = val;
+                                      },
+                                      validator: (value) {
+                                        if (value.isEmpty) {
+                                          return 'Password is Empty';
+                                        }
+                                        return null;
+                                      },
+                                      decoration: InputDecoration(
+                                          suffixIcon:
+                                          InkWell(
+                                            onTap: _togglePasswordView,
+                                            child: Icon(
+                                              _isHidden ?
+                                              Icons.visibility :
+                                              Icons.visibility_off,
+                                            ),
+                                          ),
+                                          labelText: "Password",
+                                          border: OutlineInputBorder(
+                                            borderRadius: BorderRadius.all(Radius.circular(8)),
+                                          )
+                                      ),
+                                    ),
+                                  ),
+                                  const SizedBox(height: 30,),
+                                  TextButton(
+                                    onPressed: () async {
+                                      if (_formKey.currentState.validate()) {
+                                        Pasien pasienBaru =
+                                            await registerPasien(name, username, email, password, umur, context);
+                                        setState(() {
+                                          pasien = pasienBaru;
+                                        });
+
+                                        // save();
+                                        // var response = await http.post(
+                                        //     url,
+                                        //     headers: {'Content-Type': 'application/json'},
+                                        //     body: jsonEncode(<String, String>{
+                                        //     'name': pasien.name,
+                                        //     'username': pasien.username,
+                                        //     'email': pasien.email,
+                                        //     'password': pasien.password,
+                                        //     'umur': pasien.umur
+                                        //   }),
+                                        // );
+                                        //
+                                        // String responseString = response.body;
+                                        // print("success1");
+                                        // print(response);
+                                        // print("body empty");
+                                        // if (response.statusCode == 200) {
+                                        //   print("success");
+                                        //   showDialog<String>(
+                                        //     context: context,
+                                        //     builder: (BuildContext context) => AlertDialog(
+                                        //       title: const Text(
+                                        //           'Registrasi berhasil!'),
+                                        //       actions: <Widget>[
+                                        //         TextButton(
+                                        //           onPressed: () =>
+                                        //               Navigator.pop(context, 'OK'),
+                                        //           child: const Text('OK'),
+                                        //         )
+                                        //       ],
+                                        //     ),
+                                        //   );
+                                        }
+                                      // }
+                                    },
+                                    child: Container(
+                                      alignment: Alignment.center,
+                                      width: 250,
+                                      decoration: const BoxDecoration(
+                                        borderRadius: BorderRadius.all(Radius.circular(20)),
+                                        color: const Color(0xff0d47a1),
+                                      ),
+                                      child: Padding(
+                                        padding: EdgeInsets.all(12.0),
+                                        child:
+                                        Text('Register',
+                                          style: TextStyle(
+                                              color: Colors.white,
+                                              fontSize: 20,
+                                              fontWeight: FontWeight.bold
+                                          ),
+                                        ),
+                                      ),
+                                    ),
+                                  ),
+                                  const SizedBox(
+                                    height: 2,
+                                  ),
+                                  Row(
+                                    mainAxisAlignment: MainAxisAlignment.center,
+                                    children: [
+                                      const Text('Sudah punya akun?'),
+                                      TextButton(
+                                        style: TextButton.styleFrom(
+                                          primary: const Color(0xff0d47a1), // Text Color
+                                        ),
+                                        onPressed: () {
+                                          Navigator.pop(context);
+                                        },
+                                        child: const Text('Login',), //TODO: REGISTER PASIEN
+
+                                      ),
+                                    ],
+                                  ),
+                                ],
+                              ),
+                            )
+                          ],
+                        ),
+                      ),
+                    ],
+                  )),
+            ),
+          ),
+        );
+      }),
+    );
+
+  }
+
+  void _togglePasswordView() {
+    setState(() {
+      _isHidden = !_isHidden;
+    });
+  }
+
+  Future<Pasien> registerPasien(
+      String name, String username, String email, String password, String umur, BuildContext context) async {
+    var Url = Uri.parse('http://192.168.1.100:8080/api/pasien');
+    var response = await http.post(Url,
+        headers: <String, String>{
+          "Content-Type": "application/json"
+        },
+        body: jsonEncode(<String, String>{
+          'name': name,
+          'username': username,
+          'email': email,
+          'password': password,
+          'umur': umur,
+        }));
+
+    String responseString = response.body;
+    print(responseString);
+    print("itu response string, dan udah masuk method registerPasien");
+
+    if (response.statusCode == 200) {
+      print("Masuk statuscode == 200");
+      showDialog<String>(
+        context: context,
+        builder: (BuildContext context) => AlertDialog(
+          title: const Text(
+              'Registrasi berhasil!'),
+          actions: <Widget>[
+            TextButton(
+              onPressed: () =>
+                  Navigator.pop(context, 'OK'),
+              child: const Text('OK'),
+            )
+          ],
+        ),
+      );
+    } else {
+      print("anjingggg");
+    }
+  }
+
+}
diff --git a/tk_apap_flutter/pubspec.lock b/tk_apap_flutter/pubspec.lock
index 082b75e..322a397 100644
--- a/tk_apap_flutter/pubspec.lock
+++ b/tk_apap_flutter/pubspec.lock
@@ -162,7 +162,7 @@ packages:
       name: material_color_utilities
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.2.0"
+    version: "0.1.5"
   meta:
     dependency: transitive
     description:
@@ -335,7 +335,7 @@ packages:
       name: source_span
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.9.1"
+    version: "1.9.0"
   stack_trace:
     dependency: transitive
     description:
@@ -370,7 +370,7 @@ packages:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.13"
+    version: "0.4.12"
   typed_data:
     dependency: transitive
     description:
@@ -384,7 +384,7 @@ packages:
       name: vector_math
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.3"
+    version: "2.1.2"
   win32:
     dependency: transitive
     description:
@@ -400,5 +400,5 @@ packages:
     source: hosted
     version: "0.2.0+2"
 sdks:
-  dart: ">=2.18.0-146.0.dev <3.0.0"
+  dart: ">=2.17.0 <3.0.0"
   flutter: ">=3.0.0"
-- 
GitLab


From 2f0f18569a738e925f83cd24055c113a9edfc34b Mon Sep 17 00:00:00 2001
From: Muhammad Tsaqib Ibadillah Wahid <muhammad.tsaqib@ui.ac.id>
Date: Thu, 8 Dec 2022 12:23:09 +0700
Subject: [PATCH 2/3] implementasi registrasi pasien.

---
 .../auth/security/WebSecurityConfig.java      |   2 +-
 .../TK/SpringTkApap/auth/setting/Setting.java |   3 -
 .../user/controller/PasienRestController.java |  11 +-
 .../user/service/PasienRestServiceImpl.java   |  31 +--
 tk_apap_flutter/lib/DTO/Pasien.dart           |   2 +-
 .../lib/pages/CreateAppointment.dart          |  13 +-
 tk_apap_flutter/lib/pages/login.dart          |   7 +-
 tk_apap_flutter/lib/pages/register.dart       | 180 +++++++++---------
 8 files changed, 128 insertions(+), 121 deletions(-)

diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/security/WebSecurityConfig.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/security/WebSecurityConfig.java
index eec65f3..489b108 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/security/WebSecurityConfig.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/security/WebSecurityConfig.java
@@ -101,7 +101,7 @@ public class WebSecurityConfig {
             http.antMatcher("/api/**").cors().and().csrf()
                     .disable()
                     .authorizeRequests()
-                    .antMatchers("/api/authenticate").permitAll()
+                    .antMatchers("/api/authenticate", "/api/pasien/register").permitAll()
                     .antMatchers(HttpMethod.GET, "/api/user").hasAuthority(PASIEN)
                     .anyRequest().hasAnyAuthority(PASIEN, ADMIN)
                     .and()
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java
index 4653082..74652cf 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/auth/setting/Setting.java
@@ -6,11 +6,8 @@ public class Setting {
     }
 
     public static final String CLIENT_BASE_URL = "http://localhost:8080";
-<<<<<<< HEAD
 //    URL deploy  https://apap-tk-53.cs.ui.ac.id
 //    URL local http://localhost:8080
-=======
->>>>>>> main
 
     public static final String CLIENT_LOGIN = CLIENT_BASE_URL + "/validate-ticket";
 
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
index ecfe39e..b183fc4 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
@@ -20,15 +20,20 @@ public class PasienRestController {
     @Autowired
     PasienRestService pasienRestService;
 
-    @PostMapping("/register")
+    @PostMapping(value = "/register")
     private ResponseEntity<String> registerPasien(@RequestBody PasienDTO pasien, BindingResult bindingResult){
         if (bindingResult.hasFieldErrors()) {
             throw new ResponseStatusException(
                     HttpStatus.BAD_REQUEST, "Request body has invalid type or missing field."
             );
         } else {
-            pasienRestService.createPasien(pasien);
-            return ResponseEntity.ok("Created new pasien");
+            PasienModel newPasien = pasienRestService.createPasien(pasien);
+            if (newPasien == null) {
+                throw new ResponseStatusException(
+                        HttpStatus.INTERNAL_SERVER_ERROR, "Username yang sama sudah terdaftar. Silakan gunakan username yang lain."
+                );
+            }
+            return ResponseEntity.ok(String.format("Registrasi berhasil!"));
         }
     }
 
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
index a8dff9b..d37361c 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
@@ -27,18 +27,25 @@ public class PasienRestServiceImpl implements PasienRestService {
 
     @Override
     public PasienModel createPasien(PasienDTO pasienDTO) {
-        PasienModel pasien = new PasienModel();
-
-        pasien.setNama(pasienDTO.getName());
-        pasien.setUsername(pasienDTO.getUsername());
-        pasien.setEmail(pasienDTO.getEmail());
-        pasien.setPassword(authService.encrypt(pasienDTO.getPassword()));
-        pasien.setRole(RolesEnum.PASIEN);
-        pasien.setUmur(Integer.valueOf(pasienDTO.getUmur()));
-        pasien.setSaldo(0);
-        pasien.setListAppointment(new ArrayList<>());
-
-        return pasienDb.save(pasien); }
+
+        for (PasienModel pasien : pasienDb.findAll()) {
+            if (pasienDTO.getUsername().equals(pasien.getUsername())){
+                return null;
+            }
+        }
+
+        PasienModel newPasien = new PasienModel();
+
+        newPasien.setNama(pasienDTO.getName());
+        newPasien.setUsername(pasienDTO.getUsername());
+        newPasien.setEmail(pasienDTO.getEmail());
+        newPasien.setPassword(authService.encrypt(pasienDTO.getPassword()));
+        newPasien.setRole(RolesEnum.PASIEN);
+        newPasien.setUmur(Integer.valueOf(pasienDTO.getUmur()));
+        newPasien.setSaldo(0);
+        newPasien.setListAppointment(new ArrayList<>());
+
+        return pasienDb.save(newPasien); }
 
     @Override
     public List<PasienModel> retrievePasien() { return pasienDb.findAll(); }
diff --git a/tk_apap_flutter/lib/DTO/Pasien.dart b/tk_apap_flutter/lib/DTO/Pasien.dart
index 811cc63..fdb3ada 100644
--- a/tk_apap_flutter/lib/DTO/Pasien.dart
+++ b/tk_apap_flutter/lib/DTO/Pasien.dart
@@ -5,5 +5,5 @@ class Pasien {
   String password = '';
   String umur = '';
 
-  Pasien(this.name, this.username, this.email, this.password, this.umur);
+  Pasien();
 }
\ No newline at end of file
diff --git a/tk_apap_flutter/lib/pages/CreateAppointment.dart b/tk_apap_flutter/lib/pages/CreateAppointment.dart
index 17c3934..e1477a5 100644
--- a/tk_apap_flutter/lib/pages/CreateAppointment.dart
+++ b/tk_apap_flutter/lib/pages/CreateAppointment.dart
@@ -20,11 +20,7 @@ class _CreateAppointmentState extends State<CreateAppointment> {
   // Data yang diperlukan tanggal dan waktu, dropdown [namaDokter - Tarif]
 
   Future<List<Dokter>> getAllDoktor() async {
-<<<<<<< HEAD:tk_apap_flutter/lib/pages/createAppointment.dart
-    var uri = Uri.parse('http://192.168.1.100:8080/api/doktor/all');
-    http.Response response = await http.get(uri);
-=======
-    var uri = Uri.parse('http://10.0.2.2:8080/api/doktor/all');
+    var uri = Uri.parse('http://10.5.90.122:8080/api/doktor/all');
     dynamic token = await SessionManager().get('token');
     String tknString = ('Bearer $token');
     print(tknString);
@@ -33,7 +29,6 @@ class _CreateAppointmentState extends State<CreateAppointment> {
       'Accept': 'application/json',
       'Content-Type': 'application/json; charset=UTF-8',
       'Authorization': tknString});
->>>>>>> main:tk_apap_flutter/lib/pages/CreateAppointment.dart
     if (response.statusCode == 200) {
       List<Dokter> list = <Dokter>[];
       List jsonData = jsonDecode(response.body);
@@ -108,11 +103,7 @@ class _CreateAppointmentState extends State<CreateAppointment> {
                             String strUsername = username;
                             var response = await http.post(
                               Uri.parse(
-<<<<<<< HEAD:tk_apap_flutter/lib/pages/createAppointment.dart
-                                  'http://192.168.1.100:8080/api/appointment/create'),
-=======
-                                  'http://10.0.2.2:8080/api/appointment/create'), //TODO: Ganti sesuai ipconfig
->>>>>>> main:tk_apap_flutter/lib/pages/CreateAppointment.dart
+                                  'http://10.5.90.122:8080/api/appointment/create'),
                               headers: {
                                 'Accept': 'application/json',
                                 'Content-Type': 'application/json; charset=UTF-8',
diff --git a/tk_apap_flutter/lib/pages/login.dart b/tk_apap_flutter/lib/pages/login.dart
index e87e69d..b128f16 100644
--- a/tk_apap_flutter/lib/pages/login.dart
+++ b/tk_apap_flutter/lib/pages/login.dart
@@ -25,11 +25,8 @@ class _LoginState extends State<Login> {
   UserLogin user = UserLogin("", "");
   bool _isHidden = true;
 
-<<<<<<< HEAD
-  final url = Uri.parse('http://192.168.1.100:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
-=======
-  final url = Uri.parse('http://10.0.2.2:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
->>>>>>> main
+  final url = Uri.parse('http://10.5.90.122:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
+
   final header = <String, String> {
     'Content-Type':
     'application/json; charset=UTF-8'
diff --git a/tk_apap_flutter/lib/pages/register.dart b/tk_apap_flutter/lib/pages/register.dart
index 5820b94..aed187f 100644
--- a/tk_apap_flutter/lib/pages/register.dart
+++ b/tk_apap_flutter/lib/pages/register.dart
@@ -15,17 +15,19 @@ import 'Login.dart';
 class Register extends StatefulWidget {
   static const routeName = '/register';
 
-  Register({Key key}) : super(key: key);
+  const Register({Key key}) : super(key: key);
 
   @override
-  _RegisterState createState() => _RegisterState();
+  State<Register> createState() => _RegisterState();
 }
 
 class _RegisterState extends State<Register> {
-  final _formKey = GlobalKey<FormState>();
+
+  final pasien = Pasien();
+
+  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
   // final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
 
-  Pasien pasien;
   String name;
   String username;
   String email;
@@ -33,9 +35,6 @@ class _RegisterState extends State<Register> {
   String umur;
 
   bool _isHidden = true;
-
-  final url = Uri.parse('http://192.168.1.100:8080/api/pasien'); //TODO:ubah sesuai IP Address, nanti pakai link web
-
   // Future save() async {
   //   var res = await http.post(url,
   //     headers: {'Content-Type': 'application/json'},
@@ -265,47 +264,62 @@ class _RegisterState extends State<Register> {
                                   TextButton(
                                     onPressed: () async {
                                       if (_formKey.currentState.validate()) {
-                                        Pasien pasienBaru =
-                                            await registerPasien(name, username, email, password, umur, context);
-                                        setState(() {
-                                          pasien = pasienBaru;
-                                        });
+                                        // Pasien pasienBaru =
+                                        //     await registerPasien(name, username, email, password, umur, context);
+                                        // setState(() {
+                                        //   pasien = pasienBaru;
+                                        // });
 
                                         // save();
-                                        // var response = await http.post(
-                                        //     url,
-                                        //     headers: {'Content-Type': 'application/json'},
-                                        //     body: jsonEncode(<String, String>{
-                                        //     'name': pasien.name,
-                                        //     'username': pasien.username,
-                                        //     'email': pasien.email,
-                                        //     'password': pasien.password,
-                                        //     'umur': pasien.umur
-                                        //   }),
-                                        // );
-                                        //
-                                        // String responseString = response.body;
-                                        // print("success1");
-                                        // print(response);
-                                        // print("body empty");
-                                        // if (response.statusCode == 200) {
-                                        //   print("success");
-                                        //   showDialog<String>(
-                                        //     context: context,
-                                        //     builder: (BuildContext context) => AlertDialog(
-                                        //       title: const Text(
-                                        //           'Registrasi berhasil!'),
-                                        //       actions: <Widget>[
-                                        //         TextButton(
-                                        //           onPressed: () =>
-                                        //               Navigator.pop(context, 'OK'),
-                                        //           child: const Text('OK'),
-                                        //         )
-                                        //       ],
-                                        //     ),
-                                        //   );
+                                        var response = await http.post(
+                                            Uri.parse(
+                                              'http://10.5.90.122:8080/api/pasien/register'),
+                                            headers: {
+                                              'Accept': 'application/json',
+                                              'Content-Type': 'application/json'},
+                                            body: jsonEncode(<String, String>{
+                                            'name': name,
+                                            'username': username,
+                                            'email': email,
+                                            'password': password,
+                                            'umur': umur
+                                          }),
+                                        );
+                                        if (response.statusCode == 200) {
+                                          showDialog<String>(
+                                            context: context,
+                                            builder: (BuildContext context) => AlertDialog(
+                                              title: const Text(
+                                                  'Registrasi berhasil!'
+                                              ),
+                                              actions: <Widget>[
+                                                TextButton(
+                                                  onPressed: () =>
+                                                      Navigator.push(
+                                                        context,
+                                                        MaterialPageRoute(builder: (context)=>Login())
+                                                      ),
+                                                  child: const Text('OK'),
+                                                )
+                                              ],
+                                            ),
+                                          );
+                                        } else {
+                                          showDialog<String>(
+                                            context: context,
+                                            builder: (BuildContext context) => AlertDialog(
+                                              title: const Text(
+                                                'Username yang sama sudah terdaftar. Silakan gunakan username yang lain.'
+                                              ),
+                                              actions: <Widget>[
+                                                TextButton(onPressed: () => Navigator.pop(context, 'OK'),
+                                                    child: const Text('OK'),
+                                                )
+                                              ],
+                                            )
+                                          );
                                         }
-                                      // }
+                                      }
                                     },
                                     child: Container(
                                       alignment: Alignment.center,
@@ -341,7 +355,7 @@ class _RegisterState extends State<Register> {
                                         onPressed: () {
                                           Navigator.pop(context);
                                         },
-                                        child: const Text('Login',), //TODO: REGISTER PASIEN
+                                        child: const Text('Login',),
 
                                       ),
                                     ],
@@ -368,44 +382,40 @@ class _RegisterState extends State<Register> {
     });
   }
 
-  Future<Pasien> registerPasien(
-      String name, String username, String email, String password, String umur, BuildContext context) async {
-    var Url = Uri.parse('http://192.168.1.100:8080/api/pasien');
-    var response = await http.post(Url,
-        headers: <String, String>{
-          "Content-Type": "application/json"
-        },
-        body: jsonEncode(<String, String>{
-          'name': name,
-          'username': username,
-          'email': email,
-          'password': password,
-          'umur': umur,
-        }));
-
-    String responseString = response.body;
-    print(responseString);
-    print("itu response string, dan udah masuk method registerPasien");
-
-    if (response.statusCode == 200) {
-      print("Masuk statuscode == 200");
-      showDialog<String>(
-        context: context,
-        builder: (BuildContext context) => AlertDialog(
-          title: const Text(
-              'Registrasi berhasil!'),
-          actions: <Widget>[
-            TextButton(
-              onPressed: () =>
-                  Navigator.pop(context, 'OK'),
-              child: const Text('OK'),
-            )
-          ],
-        ),
-      );
-    } else {
-      print("anjingggg");
-    }
-  }
+  // Future<Pasien> registerPasien(
+  //     String name, String username, String email, String password, String umur, BuildContext context) async {
+  //   var Url = Uri.parse('http://192.168.1.100:8080/api/pasien');
+  //   var response = await http.post(Url,
+  //       headers: <String, String>{
+  //         "Content-Type": "application/json"
+  //       },
+  //       body: jsonEncode(<String, String>{
+  //         'name': name,
+  //         'username': username,
+  //         'email': email,
+  //         'password': password,
+  //         'umur': umur,
+  //       }));
+  //
+  //   String responseString = response.body;
+  //   print(responseString);
+  //   print("itu response string, dan udah masuk method registerPasien");
+  //
+  //   if (response.statusCode == 200) {
+  //     print("Masuk statuscode == 200");
+  //     showDialog<String>(
+  //       context: context,
+  //       builder: (BuildContext context) => AlertDialog(
+  //         title: const Text(
+  //             'Registrasi berhasil!'),
+  //         actions: <Widget>[
+  //           TextButton(
+  //             onPressed: () =>
+  //                 Navigator.pop(context, 'OK'),
+  //             child: const Text('OK'),
+  //           )
+  //         ],
+  //       ),
+  //     );
 
 }
-- 
GitLab


From 650e2ec582b3ea13dcaf138d9a2210f1d98bcaa7 Mon Sep 17 00:00:00 2001
From: Muhammad Tsaqib Ibadillah Wahid <muhammad.tsaqib@ui.ac.id>
Date: Sun, 11 Dec 2022 15:48:18 +0700
Subject: [PATCH 3/3] feat: implementasi fitur top-up saldo

---
 .../user/controller/PasienRestController.java |   8 +-
 .../user/service/PasienRestService.java       |   2 +-
 .../user/service/PasienRestServiceImpl.java   |   6 +-
 tk_apap_flutter/lib/pages/LihatProfil.dart    |  47 ++-
 tk_apap_flutter/lib/pages/TopUpSaldo.dart     | 388 ++++++++++++++++++
 tk_apap_flutter/lib/pages/login.dart          |   2 +-
 6 files changed, 427 insertions(+), 26 deletions(-)

diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
index ef8079e..862b375 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/controller/PasienRestController.java
@@ -67,13 +67,13 @@ public class PasienRestController {
         return pasienRestService.retrievePasien();
     }
 
-    @PutMapping(value = "/top-up/{uuid}")
-    private PasienModel topUpSaldo(@PathVariable("uuid") String uuid, @RequestBody PasienModel pasien){
+    @PostMapping(value = "/top-up/{username}")
+    private PasienModel topUpSaldo(@PathVariable("username") String username, @RequestBody PasienDTO pasien, BindingResult bindingResult){
         try{
-            return pasienRestService.topUpSaldo(uuid, pasien);
+            return pasienRestService.topUpSaldo(username, pasien);
         } catch (NoSuchElementException e) {
             throw new ResponseStatusException(
-                    HttpStatus.NOT_FOUND, "Pasien dengan id " + uuid + " tidak ditemukan."
+                    HttpStatus.NOT_FOUND, "Pasien dengan username " + username + " tidak ditemukan."
             );
         }
     }
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java
index 4fed5b7..2e742e3 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestService.java
@@ -10,5 +10,5 @@ public interface PasienRestService {
     List<PasienModel> retrievePasien();
     PasienModel getPasien(String uuid);
     PasienModel getPasienByUsername(String username);
-    PasienModel topUpSaldo(String uuid, PasienModel pasienUpdate);
+    PasienModel topUpSaldo(String username, PasienDTO pasienUpdate);
 }
diff --git a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
index 7d75236..a39b057 100644
--- a/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
+++ b/SpringTkApap/src/main/java/spring/TK/SpringTkApap/user/service/PasienRestServiceImpl.java
@@ -66,9 +66,9 @@ public class PasienRestServiceImpl implements PasienRestService {
     }
 
     @Override
-    public PasienModel topUpSaldo(String uuid, PasienModel pasienUpdate) {
-        PasienModel pasien = getPasien(uuid);
-        pasien.setSaldo(pasienUpdate.getSaldo());
+    public PasienModel topUpSaldo(String username, PasienDTO pasienUpdate) {
+        PasienModel pasien = getPasienByUsername(username);
+        pasien.setSaldo(pasien.getSaldo() + Integer.valueOf(pasienUpdate.getSaldo()));
 
         return pasienDb.save(pasien);
     }
diff --git a/tk_apap_flutter/lib/pages/LihatProfil.dart b/tk_apap_flutter/lib/pages/LihatProfil.dart
index 374db93..2bb7b04 100644
--- a/tk_apap_flutter/lib/pages/LihatProfil.dart
+++ b/tk_apap_flutter/lib/pages/LihatProfil.dart
@@ -7,12 +7,13 @@ import 'package:tk_apap_flutter/widgets/drawerWidget.dart';
 import 'package:flutter/material.dart';
 import '../DTO/PasienDTO.dart';
 import 'package:http/http.dart' as http;
+import 'package:tk_apap_flutter/pages/TopUpSaldo.dart';
 
 class LihatProfil extends StatelessWidget {
   static const routeName = '/edit';
 
   Future<PasienDTO> getPasien() async {
-    var uri = Uri.parse('http://10.0.2.2:8080/api/pasien/getself');
+    var uri = Uri.parse('http://192.168.18.47:8080/api/pasien/getself');
     dynamic token = await SessionManager().get('token');
     String tknString = ('Bearer $token');
     http.Response response = await http.get(uri, headers: {
@@ -105,24 +106,36 @@ class LihatProfil extends StatelessWidget {
                       ),
                       FadeAnimation(
                           2,
-                          Container(
-                            height: 50,
-                            decoration: BoxDecoration(
-                              borderRadius: BorderRadius.circular(10),
-                              color: const Color(0xff0d47a1),
-                            ),
-                            child: Center(
-                              child: Text(
-                                "Top up saldo",
-                                style: TextStyle(
-                                  color: Colors.white,
-                                  fontWeight: FontWeight.bold,
-                                  fontSize: 20,
-                                  fontFamily: 'Poppins',
+                          TextButton(
+                            onPressed: () {
+                              Navigator.push(
+                                context,
+                                MaterialPageRoute(
+                                  builder: (context) =>
+                                      TopUpSaldo()),
+                              );
+                            },
+                            child:
+                            Container(
+                              height: 50,
+                              decoration: BoxDecoration(
+                                borderRadius: BorderRadius.circular(10),
+                                color: const Color(0xff0d47a1),
+                              ),
+                              child: Center(
+                                child: Text(
+                                  "Top up saldo",
+                                  style: TextStyle(
+                                    color: Colors.white,
+                                    fontWeight: FontWeight.bold,
+                                    fontSize: 20,
+                                    fontFamily: 'Poppins',
+                                  ),
                                 ),
                               ),
-                            ),
-                          )),
+                            )
+                          ),
+                      ),
                       SizedBox(
                         height: 70,
                       ),
diff --git a/tk_apap_flutter/lib/pages/TopUpSaldo.dart b/tk_apap_flutter/lib/pages/TopUpSaldo.dart
index e69de29..adc2637 100644
--- a/tk_apap_flutter/lib/pages/TopUpSaldo.dart
+++ b/tk_apap_flutter/lib/pages/TopUpSaldo.dart
@@ -0,0 +1,388 @@
+import 'dart:convert';
+import 'dart:developer';
+
+import 'package:flutter_session_manager/flutter_session_manager.dart';
+import 'package:tk_apap_flutter/animation/FadeAnimation.dart';
+import 'package:tk_apap_flutter/widgets/drawerWidget.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import '../DTO/PasienDTO.dart';
+import 'package:http/http.dart' as http;
+
+import 'LihatProfil.dart';
+
+class TopUpSaldo extends StatelessWidget {
+  static const routeName = '/lihatProfile';
+
+  String jumlahTopUp;
+  var textJumlahTopUp = TextEditingController();
+
+  Future<PasienDTO> getPasien() async {
+    var uri = Uri.parse('http://192.168.18.47:8080/api/pasien/getself');
+    dynamic token = await SessionManager().get('token');
+    String tknString = ('Bearer $token');
+    http.Response response = await http.get(uri, headers: {
+      'Accept': 'application/json',
+      'Content-Type': 'application/json; charset=UTF-8',
+      'Authorization': tknString
+    });
+    log(response.statusCode.toString());
+    if (response.statusCode == 200) {
+      Map jsonData = jsonDecode(response.body);
+      PasienDTO pasien = PasienDTO.createPasien(
+          jsonData['name'] as String,
+          jsonData['username'] as String,
+          jsonData['email'] as String,
+          jsonData['saldo'].toString());
+      log("Menembak API get profil pasien.");
+      return pasien;
+    } else {
+      throw response.statusCode;
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final GlobalKey<ScaffoldState> _scaffoldKey =
+    new GlobalKey<ScaffoldState>();
+
+    return Scaffold(
+      backgroundColor: Colors.white,
+      key: _scaffoldKey,
+      drawer: CustomDrawer(),
+      appBar: AppBar(
+        title: Text(
+          'Top Up Saldo',
+          style: TextStyle(
+            fontFamily: 'Poppins',
+            fontWeight: FontWeight.bold,
+          ),
+        ),
+        backgroundColor: const Color(0xff0d47a1),
+        centerTitle: true,
+        leading: IconButton(
+          icon: Icon(
+            Icons.short_text,
+            size: 40,
+          ),
+          onPressed: () => _scaffoldKey.currentState.openDrawer(),
+        ),
+      ),
+      body: FutureBuilder<PasienDTO>(
+          future: getPasien(),
+          builder: (context, snapshot) {
+            if (snapshot.hasData) {
+              PasienDTO pasien = snapshot.data;
+              return SingleChildScrollView(
+                child: Padding(
+                  padding: EdgeInsets.only(top: 35, left: 35, right: 35),
+                  child: Column(
+                    children: <Widget>[
+                      SizedBox(
+                        height: 100,
+                      ),
+                      Container(
+                          child: Text(
+                            'Saldo: ${pasien.saldo.toString()}',
+                            style: TextStyle(
+                              fontSize: 30,
+                            ),
+                          )),
+                      SizedBox(
+                        height: 30,
+                      ),
+                      Container(
+                        width: 260,
+                        height: 40,
+                        child: TextFormField(
+                          keyboardType: TextInputType.number,
+                          controller: textJumlahTopUp,
+                          onChanged: (val) {
+                            jumlahTopUp = val;
+                          },
+                          inputFormatters: <TextInputFormatter>[
+                            FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
+                          ],
+                          validator: (value) {
+                            if (value.isEmpty) {
+                              return 'Jumlah Top Up is Empty';
+                            }
+                            return null;
+                          },
+                          decoration: InputDecoration(
+                              labelText: "Jumlah Top Up",
+                              border: OutlineInputBorder(
+                                borderRadius: BorderRadius.all(Radius.circular(8)),
+                              )
+                          ),
+                        ),
+                      ),
+                      SizedBox(
+                        height: 30,
+                      ),
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        children: [
+                          TextButton(
+                              onPressed: () {
+                                jumlahTopUp = "50000";
+                                textJumlahTopUp.text = jumlahTopUp;
+                              },
+                              child:
+                              Container(
+                                height: 45,
+                                width: 85,
+                                decoration: BoxDecoration(
+                                  borderRadius: BorderRadius.circular(10),
+                                  color: const Color(0xff0d47a1),
+                                ),
+                                child: Center(
+                                  child: Text(
+                                    "50.000",
+                                    textAlign: TextAlign.center,
+                                    style: TextStyle(
+                                      color: Colors.white,
+                                      fontWeight: FontWeight.bold,
+                                      fontSize: 20,
+                                      fontFamily: 'Poppins',
+                                    ),
+                                  ),
+                                ),
+                              )
+                          ),
+                          TextButton(
+                              onPressed: () {
+                                jumlahTopUp = "100000";
+                                textJumlahTopUp.text = jumlahTopUp;
+                              },
+                              child:
+                              Container(
+                                height: 45,
+                                width: 85,
+                                decoration: BoxDecoration(
+                                  borderRadius: BorderRadius.circular(10),
+                                  color: const Color(0xff0d47a1),
+                                ),
+                                child: Center(
+                                  child: Text(
+                                    "100.000",
+                                    textAlign: TextAlign.center,
+                                    style: TextStyle(
+                                      color: Colors.white,
+                                      fontWeight: FontWeight.bold,
+                                      fontSize: 20,
+                                      fontFamily: 'Poppins',
+                                    ),
+                                  ),
+                                ),
+                              )
+                          ),
+                          TextButton(
+                              onPressed: () {
+                                jumlahTopUp = "150000";
+                                textJumlahTopUp.text = jumlahTopUp;
+                              },
+                              child:
+                              Container(
+                                height: 45,
+                                width: 85,
+                                decoration: BoxDecoration(
+                                  borderRadius: BorderRadius.circular(10),
+                                  color: const Color(0xff0d47a1),
+                                ),
+                                child: Center(
+                                  child: Text(
+                                    "150.000",
+                                    textAlign: TextAlign.center,
+                                    style: TextStyle(
+                                      color: Colors.white,
+                                      fontWeight: FontWeight.bold,
+                                      fontSize: 20,
+                                      fontFamily: 'Poppins',
+                                    ),
+                                  ),
+                                ),
+                              )
+                          ),
+                        ]
+                      ),
+                      Row(
+                          mainAxisAlignment: MainAxisAlignment.center,
+                          children: [
+                            TextButton(
+                                onPressed: () {
+                                  jumlahTopUp = "250000";
+                                  textJumlahTopUp.text = jumlahTopUp;
+                                },
+                                child:
+                                Container(
+                                  height: 45,
+                                  width: 85,
+                                  decoration: BoxDecoration(
+                                    borderRadius: BorderRadius.circular(10),
+                                    color: const Color(0xff0d47a1),
+                                  ),
+                                  child: Center(
+                                    child: Text(
+                                      "250.000",
+                                      textAlign: TextAlign.center,
+                                      style: TextStyle(
+                                        color: Colors.white,
+                                        fontWeight: FontWeight.bold,
+                                        fontSize: 20,
+                                        fontFamily: 'Poppins',
+                                      ),
+                                    ),
+                                  ),
+                                )
+                            ),
+                            TextButton(
+                                onPressed: () {
+                                  jumlahTopUp = "500000";
+                                  textJumlahTopUp.text = jumlahTopUp;
+                                },
+                                child:
+                                Container(
+                                  height: 45,
+                                  width: 85,
+                                  decoration: BoxDecoration(
+                                    borderRadius: BorderRadius.circular(10),
+                                    color: const Color(0xff0d47a1),
+                                  ),
+                                  child: Center(
+                                    child: Text(
+                                      "500.000",
+                                      textAlign: TextAlign.center,
+                                      style: TextStyle(
+                                        color: Colors.white,
+                                        fontWeight: FontWeight.bold,
+                                        fontSize: 20,
+                                        fontFamily: 'Poppins',
+                                      ),
+                                    ),
+                                  ),
+                                )
+                            ),
+                            TextButton(
+                                onPressed: () {
+                                  jumlahTopUp = "";
+                                  textJumlahTopUp.text = jumlahTopUp;
+                                },
+                                child:
+                                Container(
+                                  height: 45,
+                                  width: 85,
+                                  decoration: BoxDecoration(
+                                    borderRadius: BorderRadius.circular(10),
+                                    color: const Color(0xff0d47a1),
+                                  ),
+                                  child: Center(
+                                    child: Text(
+                                      "Nominal Lain",
+                                      textAlign: TextAlign.center,
+                                      style: TextStyle(
+                                        color: Colors.white,
+                                        fontWeight: FontWeight.bold,
+                                        fontSize: 18,
+                                        fontFamily: 'Poppins',
+                                      ),
+                                    ),
+                                  ),
+                                )
+                            ),
+                          ]
+                      ),
+                      SizedBox(
+                        height: 30,
+                      ),
+                      TextButton(
+                          onPressed: () async {
+                            dynamic token = await SessionManager().get("token");
+                            String tknString = "Bearer $token";
+                            dynamic username = await SessionManager().get("username");
+                            String strUsername = username;
+                            var response = await http.post(
+                              Uri.parse(
+                                  'http://192.168.18.47:8080/api/pasien/top-up/' + strUsername),
+                              headers: {
+                                'Accept': 'application/json',
+                                'Content-Type': 'application/json; charset=UTF-8',
+                                'Authorization': tknString},
+                              body: jsonEncode(<String, String>{
+                                'nama': pasien.nama,
+                                'username': pasien.username,
+                                'email': pasien.email,
+                                'saldo': jumlahTopUp,
+                              }),
+                            );
+                            if (response.statusCode == 200) {
+                              showDialog<String>(
+                                context: context,
+                                builder: (BuildContext context) => AlertDialog(
+                                  title: const Text(
+                                      'Top up saldo berhasil!'),
+                                  actions: <Widget>[
+                                    TextButton(
+                                      onPressed: () =>
+                                          Navigator.push(
+                                              context,
+                                              MaterialPageRoute(builder: (context) => LihatProfil())
+                                          ),
+                                      child: const Text('OK'),
+                                    )
+                                  ],
+                                ),
+                              );
+                            } else {
+                              showDialog<String>(
+                                context: context,
+                                builder: (BuildContext context) => AlertDialog(
+                                  title: Text(response.reasonPhrase),
+                                  actions: <Widget>[
+                                    TextButton(
+                                      onPressed: () =>
+                                          Navigator.push(
+                                            context,
+                                            MaterialPageRoute(builder: (context) => LihatProfil())
+                                          ),
+                                      child: Text('${response.statusCode}'),
+                                    )
+                                  ],
+                                ),
+                              );
+                            }
+                          },
+                          child:
+                          Container(
+                            height: 50,
+                            decoration: BoxDecoration(
+                              borderRadius: BorderRadius.circular(10),
+                              color: const Color(0xff0d47a1),
+                            ),
+                            child: Center(
+                              child: Text(
+                                "Top up saldo",
+                                style: TextStyle(
+                                  color: Colors.white,
+                                  fontWeight: FontWeight.bold,
+                                  fontSize: 20,
+                                  fontFamily: 'Poppins',
+                                ),
+                              ),
+                            ),
+                          )
+                      ),
+                      SizedBox(
+                        height: 70,
+                      ),
+                    ],
+                  ),
+                ),
+              );
+            } else {
+              return const CircularProgressIndicator();
+            }
+          }),
+    );
+  }
+}
diff --git a/tk_apap_flutter/lib/pages/login.dart b/tk_apap_flutter/lib/pages/login.dart
index 0ddb5ac..49dafdb 100644
--- a/tk_apap_flutter/lib/pages/login.dart
+++ b/tk_apap_flutter/lib/pages/login.dart
@@ -26,7 +26,7 @@ class _LoginState extends State<Login> {
   bool _isHidden = true;
 
   final url = Uri.parse(
-      'http://10.0.2.2:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
+      'http://192.168.18.47:8080/api/authenticate'); //TODO:ubah sesuai IP Address, nanti pakai link web
 
   final header = <String, String>{
     'Content-Type': 'application/json; charset=UTF-8'
-- 
GitLab