feat: slicing history page
This commit is contained in:
parent
baee8e35db
commit
26ed9797b8
|
@ -1,5 +1,6 @@
|
||||||
import 'package:get/get_navigation/src/routes/get_route.dart';
|
import 'package:get/get_navigation/src/routes/get_route.dart';
|
||||||
import 'package:quiz_app/app/middleware/auth_middleware.dart';
|
import 'package:quiz_app/app/middleware/auth_middleware.dart';
|
||||||
|
import 'package:quiz_app/feature/history/binding/history_binding.dart';
|
||||||
import 'package:quiz_app/feature/home/binding/home_binding.dart';
|
import 'package:quiz_app/feature/home/binding/home_binding.dart';
|
||||||
import 'package:quiz_app/feature/home/view/home_page.dart';
|
import 'package:quiz_app/feature/home/view/home_page.dart';
|
||||||
import 'package:quiz_app/feature/login/bindings/login_binding.dart';
|
import 'package:quiz_app/feature/login/bindings/login_binding.dart';
|
||||||
|
@ -42,6 +43,7 @@ class AppPages {
|
||||||
NavbarBinding(),
|
NavbarBinding(),
|
||||||
HomeBinding(),
|
HomeBinding(),
|
||||||
SearchBinding(),
|
SearchBinding(),
|
||||||
|
HistoryBinding(),
|
||||||
],
|
],
|
||||||
middlewares: [AuthMiddleware()],
|
middlewares: [AuthMiddleware()],
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:quiz_app/feature/history/controller/history_controller.dart';
|
||||||
|
|
||||||
|
class HistoryBinding extends Bindings {
|
||||||
|
@override
|
||||||
|
void dependencies() {
|
||||||
|
Get.lazyPut(() => HistoryController());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class HistoryItem {
|
||||||
|
final String title;
|
||||||
|
final String date;
|
||||||
|
final int score;
|
||||||
|
final int totalQuestions;
|
||||||
|
final String duration;
|
||||||
|
|
||||||
|
HistoryItem({
|
||||||
|
required this.title,
|
||||||
|
required this.date,
|
||||||
|
required this.score,
|
||||||
|
required this.totalQuestions,
|
||||||
|
required this.duration,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class HistoryController extends GetxController {
|
||||||
|
final historyList = <HistoryItem>[].obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
loadDummyHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadDummyHistory() {
|
||||||
|
historyList.value = [
|
||||||
|
HistoryItem(
|
||||||
|
title: "Fisika Dasar",
|
||||||
|
date: "24 April 2025",
|
||||||
|
score: 8,
|
||||||
|
totalQuestions: 10,
|
||||||
|
duration: "5m 21s",
|
||||||
|
),
|
||||||
|
HistoryItem(
|
||||||
|
title: "Sejarah Indonesia",
|
||||||
|
date: "22 April 2025",
|
||||||
|
score: 7,
|
||||||
|
totalQuestions: 10,
|
||||||
|
duration: "4m 35s",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,128 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:quiz_app/feature/history/controller/history_controller.dart';
|
||||||
|
|
||||||
class HistoryView extends StatelessWidget {
|
class HistoryView extends GetView<HistoryController> {
|
||||||
const HistoryView({super.key});
|
const HistoryView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold();
|
return Scaffold(
|
||||||
|
backgroundColor: const Color(0xFFF8F9FB),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Obx(() {
|
||||||
|
final historyList = controller.historyList;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
"Riwayat Kuis",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const Text(
|
||||||
|
"Lihat kembali hasil kuis yang telah kamu kerjakan",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
if (historyList.isEmpty)
|
||||||
|
const Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
"Belum ada kuis yang dikerjakan.",
|
||||||
|
style: TextStyle(fontSize: 16, color: Colors.grey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: historyList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final item = historyList[index];
|
||||||
|
return _buildHistoryCard(item);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildHistoryCard(HistoryItem item) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.only(bottom: 16),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: const [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black12,
|
||||||
|
blurRadius: 4,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blue.shade100,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.history, color: Colors.blue),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
item.title,
|
||||||
|
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
item.date,
|
||||||
|
style: const TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.check_circle, size: 14, color: Colors.green),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
"Skor: ${item.score}/${item.totalQuestions}",
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
const Icon(Icons.timer, size: 14, color: Colors.grey),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
item.duration,
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue