game html dan DIO
This commit is contained in:
parent
a211b0675d
commit
9bff9c7fc2
1
.gitignore
vendored
1
.gitignore
vendored
@ -43,3 +43,4 @@ app.*.map.json
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
pubspec.lock
|
||||
|
||||
@ -224,19 +224,19 @@ figcaption {
|
||||
|
||||
<div class="div-grid">
|
||||
<div class="div-item">
|
||||
<img src="assets/html/furikake/nori.jpeg" alt="Nori">
|
||||
<img src="nori.jpeg" alt="Nori">
|
||||
<p>Nori (Rumput Laut)</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/furikake/wijen.jpeg" alt="Biji Wijen">
|
||||
<img src="wijen.jpeg" alt="Biji Wijen">
|
||||
<p>Biji Wijen</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/furikake/ikankering.jpg" alt="Katsuobushi">
|
||||
<img src="ikankering.jpg" alt="Katsuobushi">
|
||||
<p>Katsuobushi (Ikan Kering)</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/furikake/gulagaram.jpg" alt="Garam dan Gula">
|
||||
<img src="gulagaram.jpg" alt="Garam dan Gula">
|
||||
<p>Garam & Gula</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -259,7 +259,7 @@ figcaption {
|
||||
</ul>
|
||||
|
||||
<figure>
|
||||
<img src="assets/html/furikake/furikake.jpg" alt="Contoh produk furikake" class="full-width-image">
|
||||
<img src="furikake.jpg" alt="Contoh produk furikake" class="full-width-image">
|
||||
<figcaption>Berbagai varian produk furikake yang tersedia di pasaran</figcaption>
|
||||
</figure>
|
||||
</section>
|
||||
|
||||
@ -177,23 +177,23 @@
|
||||
|
||||
<div class="div-grid">
|
||||
<div class="div-item">
|
||||
<img src="assets/html/karbohidrat.png" alt="Karbohidrat" />
|
||||
<img src="karbohidrat.png" alt="Karbohidrat" />
|
||||
<p><strong>Karbohidrat</strong><br>Sumber energi seperti nasi, roti, dan kentang.</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/protein.png" alt="Protein" />
|
||||
<img src="protein.png" alt="Protein" />
|
||||
<p><strong>Protein</strong><br>Untuk membangun otot, misalnya ikan, telur, dan tahu.</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/lemak.png" alt="Lemak" />
|
||||
<img src="lemak.png" alt="Lemak" />
|
||||
<p><strong>Lemak</strong><br>Memberikan tenaga, seperti dari kacang-kacangan dan minyak sehat.</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/vitaminmineral.png" alt="Vitamin dan Mineral" />
|
||||
<img src="vitaminmineral.png" alt="Vitamin dan Mineral" />
|
||||
<p><strong>Vitamin dan mineral</strong><br>Dari sayur dan buah yang membantu tubuh bekerja dengan baik.</p>
|
||||
</div>
|
||||
<div class="div-item">
|
||||
<img src="assets/html/seratair.png" alt="Serat dan Air" />
|
||||
<img src="seratair.png" alt="Serat dan Air" />
|
||||
<p><strong>Serat dan air</strong><br>Membantu pencernaan dan menjaga tubuh tetap segar!</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -209,7 +209,7 @@
|
||||
<li>🍽️ Seperempat piring: Protein (seperti ayam atau tempe)</li>
|
||||
<li>🍽️ Sedikit lemak sehat</li>
|
||||
</ul>
|
||||
<img src="assets/html/isipiringku.png" alt="Piring Gizi Seimbang" class="full-width-image">
|
||||
<img src="isipiringku.png" alt="Piring Gizi Seimbang" class="full-width-image">
|
||||
<figcaption>Isi Piringku</figcaption>
|
||||
<p>Selain itu, kita tidak boleh makan terlalu banyak atau terlalu sedikit, karena bisa membuat tubuh tidak sehat. Makan berlebihan bisa menyebabkan obesitas, sedangkan makan terlalu sedikit bisa membuat tubuh lemas dan kurang gizi.</p>
|
||||
</section>
|
||||
|
||||
@ -82,7 +82,7 @@
|
||||
shuffled.forEach((img, i) => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card hidden';
|
||||
card.style.backgroundImage = 'url("freekake.png")';
|
||||
card.style.backgroundImage = 'url("../freekake.png")';
|
||||
card.style.backgroundSize = 'contain';
|
||||
card.style.backgroundRepeat = 'no-repeat';
|
||||
card.style.backgroundPosition = 'center';
|
||||
@ -111,7 +111,7 @@
|
||||
function hideCard(i) {
|
||||
const el = board.children[i];
|
||||
el.classList.add('hidden');
|
||||
el.style.backgroundImage = 'url("freekake.png")';
|
||||
el.style.backgroundImage = 'url("../freekake.png")';
|
||||
el.style.backgroundSize = 'contain';
|
||||
el.style.backgroundRepeat = 'no-repeat';
|
||||
el.style.backgroundPosition = 'center';
|
||||
@ -156,7 +156,6 @@
|
||||
if (selected.length === 2) checkMatch();
|
||||
});
|
||||
|
||||
// 🔍 Expose render and notify Flutter
|
||||
window.render = render;
|
||||
|
||||
if (window.flutter_inappwebview) {
|
||||
|
||||
@ -13,7 +13,7 @@ void main() async {
|
||||
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown, // bisa dihapus jika hanya ingin satu arah
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
|
||||
runApp(const MyApp());
|
||||
|
||||
31
lib/models/users.dart
Normal file
31
lib/models/users.dart
Normal file
@ -0,0 +1,31 @@
|
||||
class Users {
|
||||
int id;
|
||||
// String nama;
|
||||
// String tgl;
|
||||
// String? alamat;
|
||||
|
||||
Users({
|
||||
required this.id,
|
||||
// required this.nama, this.alamat, required this.tgl
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
"id": id,
|
||||
// "nama": nama, "alamat": this.alamat, "tgl": this.tgl
|
||||
};
|
||||
}
|
||||
|
||||
factory Users.fromJson(Map<String, dynamic> map) {
|
||||
return Users(
|
||||
id: map['id'],
|
||||
// nama: map['nama'],
|
||||
// alamat: map['alamat'],
|
||||
// tgl: map['tanggal'],
|
||||
);
|
||||
}
|
||||
|
||||
String toString() {
|
||||
return 'Users{id:$id,}';
|
||||
}
|
||||
}
|
||||
@ -52,11 +52,13 @@ class _ListDetailScreenState extends State<ListDetailScreen> {
|
||||
await controller.loadData(
|
||||
data: html,
|
||||
baseUrl: WebUri(
|
||||
"http://localhost/$base",
|
||||
"file:///android_asset/flutter_assets/$base",
|
||||
), // agar path relatif seperti img1/* jalan
|
||||
mimeType: 'text/html',
|
||||
encoding: 'utf-8',
|
||||
);
|
||||
debugPrint("http://localhost/$base");
|
||||
debugPrint("file:///android_asset/flutter_assets/$base");
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
debugPrint("🚀 onLoadStop called. URL: $url");
|
||||
|
||||
@ -6,10 +6,13 @@ import 'package:flutter/services.dart';
|
||||
import 'package:freekake/components/card_list.dart';
|
||||
import 'package:freekake/components/collection_container%20copy.dart';
|
||||
import 'package:freekake/helpers/color_helper.dart';
|
||||
import 'package:freekake/models/users.dart';
|
||||
import 'package:freekake/screen/pustaka/list_detail_screen.dart';
|
||||
import 'package:freekake/util/api_client.dart';
|
||||
import 'package:list_detail_extension/list_detail_extension.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class ListEducation extends StatefulWidget {
|
||||
final String? selectedCategory;
|
||||
@ -27,6 +30,12 @@ class _ListEducationState extends State<ListEducation> {
|
||||
String? selectedCategory;
|
||||
final listDetailExtension = ListDetailExtension();
|
||||
|
||||
// Data fetch
|
||||
final ApiClient _apiClient = ApiClient();
|
||||
List<Users> _posts = [];
|
||||
bool _isLoading = true;
|
||||
String _error = '';
|
||||
|
||||
Future<void> _initExtension() async {
|
||||
await listDetailExtension.load();
|
||||
}
|
||||
@ -165,6 +174,41 @@ class _ListEducationState extends State<ListEducation> {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _fetchPosts() async {
|
||||
try {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = '';
|
||||
});
|
||||
|
||||
// Melakukan permintaan GET ke endpoint
|
||||
final Response response = await _apiClient.dio.get('auth/users');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// Konversi data JSON ke List
|
||||
List<dynamic> postJson = response.data;
|
||||
_posts = postJson.map((json) => Users.fromJson(json)).toList();
|
||||
} else {
|
||||
_error = 'Gagal memuat data: ${response.statusCode}';
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (e.response != null) {
|
||||
_error =
|
||||
'Server Error: ${e.response?.statusCode} - ${e.response?.statusMessage}';
|
||||
} else {
|
||||
_error = 'Network Error: ${e.message}';
|
||||
}
|
||||
print('DioError: $e');
|
||||
} catch (e) {
|
||||
_error = 'Terjadi kesalahan tidak terduga: $e';
|
||||
print('General Error: $e');
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Map<String, dynamic>> collections = [
|
||||
|
||||
@ -328,13 +328,17 @@ class _PustakaScreenState extends State<PustakaScreen> {
|
||||
Positioned(bottom: 0, left: 0, right: 0, child: MainMenu()),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: bottomPadding * 98,
|
||||
left: (screenWidth - buttonScanSize) / 2,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, -20),
|
||||
child: ScanButton(),
|
||||
),
|
||||
Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
bottom: bottomPadding * 98,
|
||||
left: (screenWidth - buttonScanSize) / 2,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, -20),
|
||||
child: ScanButton(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
36
lib/util/api_client.dart
Normal file
36
lib/util/api_client.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class ApiClient {
|
||||
final Dio _dio = Dio();
|
||||
final String _baseUrl = 'https://api.freekake.com/';
|
||||
|
||||
ApiClient() {
|
||||
_dio.options.baseUrl = _baseUrl;
|
||||
_dio.options.connectTimeout = const Duration(seconds: 5);
|
||||
_dio.options.receiveTimeout = const Duration(seconds: 3);
|
||||
|
||||
_dio.interceptors.add(
|
||||
InterceptorsWrapper(
|
||||
onRequest: (options, handler) {
|
||||
print('REQUEST[${options.method}] => PATH: ${options.path}');
|
||||
// options.headers['Authorization'] = 'Bearer your_token_here';
|
||||
return handler.next(options);
|
||||
},
|
||||
onResponse: (response, handler) {
|
||||
print(
|
||||
'RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}',
|
||||
);
|
||||
return handler.next(response);
|
||||
},
|
||||
onError: (DioException e, handler) {
|
||||
print(
|
||||
'ERROR[${e.response?.statusCode}] => PATH: ${e.requestOptions.path}',
|
||||
);
|
||||
return handler.next(e);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Dio get dio => _dio;
|
||||
}
|
||||
16
pubspec.lock
16
pubspec.lock
@ -129,6 +129,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
dio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dio
|
||||
sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.8.0+1"
|
||||
dio_web_adapter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dio_web_adapter
|
||||
sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
dropdown_button2:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
||||
@ -55,6 +55,7 @@ dependencies:
|
||||
ref: main
|
||||
desktop_webview_window: ^0.2.3
|
||||
flutter_inappwebview: ^6.0.0
|
||||
dio: ^5.0.0
|
||||
# arcore_flutter_plugin: ^0.2.0-alpha
|
||||
# flutter_unity_widget: ^2022.2.1
|
||||
# arcore_flutter_plugin:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user