Flutter consume api login
/// Struktur project Flutter: /// lib/ /// ├── main.dart /// ├── screens/ /// │ ├── login_screen.dart /// │ ├── menu_screen.dart /// │ └── reservasi_screen.dart /// ├── services/ /// │ └── api_service.dart /// └── models/ /// ├── meja_model.dart /// └── menu_model.dart // ==== main.dart ==== import 'package:flutter/material.dart'; import 'screens/login_screen.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Reservasi Meja', home: LoginScreen(), ); } } // ==== screens/login_screen.dart ==== import 'package:flutter/material.dart'; import '../services/api_service.dart'; import 'menu_screen.dart'; class LoginScreen extends StatefulWidget { @override _LoginScreenState createState() => _LoginScreenState(); } class _LoginScreenState extends State { final usernameController = TextEditingController(); final passwordController = TextEditingController(); void login() async { final token = await ApiService.login( usernameController.text, passwordController.text, ); if (token != null) { Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => MenuScreen(token: token)), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Login gagal')), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Login')), body: Padding( padding: const EdgeInsets.all(20.0), child: Column( children: [ TextField(controller: usernameController, decoration: InputDecoration(labelText: 'Username')), TextField(controller: passwordController, decoration: InputDecoration(labelText: 'Password'), obscureText: true), SizedBox(height: 20), ElevatedButton(onPressed: login, child: Text('Login')), ], ), ), ); } } // ==== screens/menu_screen.dart ==== import 'package:flutter/material.dart'; import '../services/api_service.dart'; import '../models/menu_model.dart'; import 'reservasi_screen.dart'; class MenuScreen extends StatelessWidget { final String token; const MenuScreen({super.key, required this.token}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Daftar Menu')), body: FutureBuilder( future: ApiService.getMenu(token), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); if (!snapshot.hasData || snapshot.data!.isEmpty) return Center(child: Text('Tidak ada menu')); final menuList = snapshot.data!; return ListView( children: [ ...menuList.map((m) => ListTile( title: Text(m.nama), subtitle: Text('Rp ${m.harga}'), )), ElevatedButton( child: Text('Pesan Meja'), onPressed: () => Navigator.push( context, MaterialPageRoute(builder: (_) => ReservasiScreen(token: token)), ), ) ], ); }, ), ); } } // ==== screens/reservasi_screen.dart ==== import 'package:flutter/material.dart'; import '../services/api_service.dart'; import '../models/meja_model.dart'; class ReservasiScreen extends StatelessWidget { final String token; const ReservasiScreen({super.key, required this.token}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Reservasi Meja')), body: FutureBuilder( future: ApiService.getMeja(token), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator()); if (!snapshot.hasData) return Center(child: Text('Gagal ambil data')); return ListView( children: snapshot.data! .map((meja) => ListTile( title: Text('Meja ${meja.noMeja} - ${meja.status}'), subtitle: Text('Kapasitas: ${meja.kapasitas} orang'), trailing: ElevatedButton( child: Text('Pesan'), onPressed: () => ApiService.updateMeja(token, meja.id!, 'dipesan'), ), )) .toList(), ); }, ), ); } } // ==== models/menu_model.dart ==== class MenuModel { final int id; final String nama; final int harga; MenuModel({required this.id, required this.nama, required this.harga}); factory MenuModel.fromJson(Map json) { return MenuModel( id: json['id'], nama: jso

/// Struktur project Flutter:
/// lib/
/// ├── main.dart
/// ├── screens/
/// │ ├── login_screen.dart
/// │ ├── menu_screen.dart
/// │ └── reservasi_screen.dart
/// ├── services/
/// │ └── api_service.dart
/// └── models/
/// ├── meja_model.dart
/// └── menu_model.dart
// ==== main.dart ====
import 'package:flutter/material.dart';
import 'screens/login_screen.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Reservasi Meja',
home: LoginScreen(),
);
}
}
// ==== screens/login_screen.dart ====
import 'package:flutter/material.dart';
import '../services/api_service.dart';
import 'menu_screen.dart';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State {
final usernameController = TextEditingController();
final passwordController = TextEditingController();
void login() async {
final token = await ApiService.login(
usernameController.text,
passwordController.text,
);
if (token != null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => MenuScreen(token: token)),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Login gagal')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextField(controller: usernameController, decoration: InputDecoration(labelText: 'Username')),
TextField(controller: passwordController, decoration: InputDecoration(labelText: 'Password'), obscureText: true),
SizedBox(height: 20),
ElevatedButton(onPressed: login, child: Text('Login')),
],
),
),
);
}
}
// ==== screens/menu_screen.dart ====
import 'package:flutter/material.dart';
import '../services/api_service.dart';
import '../models/menu_model.dart';
import 'reservasi_screen.dart';
class MenuScreen extends StatelessWidget {
final String token;
const MenuScreen({super.key, required this.token});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Daftar Menu')),
body: FutureBuilder>(
future: ApiService.getMenu(token),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator());
if (!snapshot.hasData || snapshot.data!.isEmpty) return Center(child: Text('Tidak ada menu'));
final menuList = snapshot.data!;
return ListView(
children: [
...menuList.map((m) => ListTile(
title: Text(m.nama),
subtitle: Text('Rp ${m.harga}'),
)),
ElevatedButton(
child: Text('Pesan Meja'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => ReservasiScreen(token: token)),
),
)
],
);
},
),
);
}
}
// ==== screens/reservasi_screen.dart ====
import 'package:flutter/material.dart';
import '../services/api_service.dart';
import '../models/meja_model.dart';
class ReservasiScreen extends StatelessWidget {
final String token;
const ReservasiScreen({super.key, required this.token});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Reservasi Meja')),
body: FutureBuilder>(
future: ApiService.getMeja(token),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return Center(child: CircularProgressIndicator());
if (!snapshot.hasData) return Center(child: Text('Gagal ambil data'));
return ListView(
children: snapshot.data!
.map((meja) => ListTile(
title: Text('Meja ${meja.noMeja} - ${meja.status}'),
subtitle: Text('Kapasitas: ${meja.kapasitas} orang'),
trailing: ElevatedButton(
child: Text('Pesan'),
onPressed: () => ApiService.updateMeja(token, meja.id!, 'dipesan'),
),
))
.toList(),
);
},
),
);
}
}
// ==== models/menu_model.dart ====
class MenuModel {
final int id;
final String nama;
final int harga;
MenuModel({required this.id, required this.nama, required this.harga});
factory MenuModel.fromJson(Map json) {
return MenuModel(
id: json['id'],
nama: json['nama'],
harga: json['harga'],
);
}
}
// ==== models/meja_model.dart ====
class MejaModel {
final int? id;
final int noMeja;
final int kapasitas;
final String status;
MejaModel({this.id, required this.noMeja, required this.kapasitas, required this.status});
factory MejaModel.fromJson(Map json) {
return MejaModel(
id: json['id'],
noMeja: json['no_meja'],
kapasitas: json['kapasitas'],
status: json['status'],
);
}
}
// ==== services/api_service.dart ====
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/menu_model.dart';
import '../models/meja_model.dart';
class ApiService {
static const baseUrl = 'http://127.0.0.1:8000/api';
static Future login(String username, String password) async {
final response = await http.post(
Uri.parse('$baseUrl/login/'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'username': username, 'password': password}),
);
if (response.statusCode == 200) {
final json = jsonDecode(response.body);
return json['access'];
}
return null;
}
static Future> getMenu(String token) async {
final response = await http.get(
Uri.parse('$baseUrl/menu/'),
headers: {'Authorization': 'Bearer $token'},
);
if (response.statusCode == 200) {
final List data = jsonDecode(response.body);
return data.map((e) => MenuModel.fromJson(e)).toList();
}
return [];
}
static Future> getMeja(String token) async {
final response = await http.get(
Uri.parse('$baseUrl/meja/'),
headers: {'Authorization': 'Bearer $token'},
);
if (response.statusCode == 200) {
final List data = jsonDecode(response.body);
return data.map((e) => MejaModel.fromJson(e)).toList();
}
return [];
}
static Future updateMeja(String token, int id, String status) async {
await http.patch(
Uri.parse('$baseUrl/meja/$id/'),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
},
body: jsonEncode({"status": status}),
);
}
}
ataww
//registrasi
import 'package:flutter/material.dart';
import '../services/api_service.dart';
import 'login_screen.dart';
class RegistrationScreen extends StatefulWidget {
@override
_RegistrationScreenState createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State {
final usernameController = TextEditingController();
final passwordController = TextEditingController();
final emailController = TextEditingController();
final phoneController = TextEditingController();
final addressController = TextEditingController();
bool isLoading = false;
void register() async {
setState(() {
isLoading = true;
});
final success = await ApiService.register(
usernameController.text,
passwordController.text,
emailController.text,
phoneController.text,
addressController.text,
);
setState(() {
isLoading = false;
});
if (success) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Registrasi berhasil! Silahkan login')),
);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => LoginScreen()),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Registrasi gagal')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Registrasi')),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Column(
children: [
TextField(controller: usernameController, decoration: InputDecoration(labelText: 'Username')),
TextField(controller: passwordController, decoration: InputDecoration(labelText: 'Password'), obscureText: true),
TextField(controller: emailController, decoration: InputDecoration(labelText: 'Email')),
TextField(controller: phoneController, decoration: InputDecoration(labelText: 'Nomor HP')),
TextField(controller: addressController, decoration: InputDecoration(labelText: 'Alamat')),
SizedBox(height: 20),
isLoading
? CircularProgressIndicator()
: ElevatedButton(onPressed: register, child: Text('Daftar')),
TextButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => LoginScreen()),
);
},
child: Text('Sudah punya akun? Login'),
)
],
),
),
),
);
}
}
login
import 'package:flutter/material.dart';
import '../services/api_service.dart';
import 'menu_screen.dart';
import 'registration_screen.dart';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State {
final usernameController = TextEditingController();
final passwordController = TextEditingController();
bool isLoading = false;
void login() async {
setState(() {
isLoading = true;
});
final token = await ApiService.login(
usernameController.text,
passwordController.text,
);
setState(() {
isLoading = false;
});
if (token != null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => MenuScreen(token: token)),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Login gagal')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login')),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(controller: usernameController, decoration: InputDecoration(labelText: 'Username')),
TextField(controller: passwordController, decoration: InputDecoration(labelText: 'Password'), obscureText: true),
SizedBox(height: 20),
isLoading
? CircularProgressIndicator()
: ElevatedButton(onPressed: login, child: Text('Login')),
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => RegistrationScreen()),
);
},
child: Text('Belum punya akun? Daftar'),
)
],
),
),
);
}
}