Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update material menu page #71

Merged
merged 3 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added app/assets/icon/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app/lib/core/constants/assets.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class Assets {
static const flagDir = 'assets/images/flags/';
static const icon = 'assets/icon/icon.png';
static const logo = 'assets/images/logo.png';
static const bebrasPandaiText = 'assets/images/bebras-banner.png';
static const studyBackground = 'assets/images/study-background.jpg';
Expand Down
11 changes: 0 additions & 11 deletions app/lib/core/constants/bebras_book_id.dart

This file was deleted.

13 changes: 0 additions & 13 deletions app/lib/core/constants/bebras_group_category.dart

This file was deleted.

27 changes: 27 additions & 0 deletions app/lib/features/material/menu/data/repositories/material.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'package:injectable/injectable.dart';

import '../../../../../services/firebase_service.dart';

@injectable
class MaterialRepository {
FirebaseFirestore db = FirebaseFirestore.instance;

MaterialRepository() {
db.settings = FirebaseService.settings;
}

Stream<QuerySnapshot> getListMaterials() {
try {
return db.collection('learning_material').snapshots();
} on FirebaseException catch (e) {
if (kDebugMode) {
print("Failed with error '${e.code}': '${e.message}'");
}
return const Stream.empty();
} catch (e) {
throw Exception(e.toString());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class BebrasGroupCategory {
final int index;
final String key;
final String label;

const BebrasGroupCategory(
this.index,
this.key,
this.label,
);
}

List<BebrasGroupCategory> bebrasGroupList = [
const BebrasGroupCategory(0, 'umum', 'Umum'),
const BebrasGroupCategory(1, 'sikecil', 'siKecil'),
const BebrasGroupCategory(2, 'siaga', 'Siaga'),
const BebrasGroupCategory(3, 'penggalang', 'Penggalang'),
const BebrasGroupCategory(4, 'penegak', 'Penegak'),
];
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:printing/printing.dart';

import '../../../../../core/bases/enum/button_type.dart';
import '../../../../../core/bases/widgets/atoms/button.dart';
import '../../../../../core/bases/widgets/layout/bebras_scaffold.dart';
import '../../../../../core/constants/assets.dart';
import '../../../../../core/constants/bebras_group_category.dart';
import '../../data/repositories/material.dart';
import '../model/bebras_group_category.dart';

part 'material_menu.dart';
250 changes: 133 additions & 117 deletions app/lib/features/material/menu/presentation/pages/material_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,48 +8,103 @@ class MaterialMenu extends StatefulWidget {
}

class _MaterialMenuState extends State<MaterialMenu> {
final Stream<QuerySnapshot> materialsStream =
FirebaseFirestore.instance.collection('learning_material').snapshots();
String basePath =
'/storage/emulated/0/Android/data/com.toki.bebras_pandai/files/PDF_Download/';

int filterIndex = 0;
String? selectedValue;

int filterIndex = 0;
MaterialRepository materialRepository = MaterialRepository();
late Stream<QuerySnapshot> materialsStream;

@override
void initState() {
super.initState();
_initializeStream();
}

Future<void> _initializeStream() async {
try {
materialsStream = materialRepository.getListMaterials();
} catch (e) {
print('Error initializing stream: $e');
}
}

Widget customRadioButton(String text, int index) {
Widget materialTab(String text, int index) {
return Container(
constraints: const BoxConstraints(
minWidth: 100,
maxWidth: 130,
),
child: Button(
buttonType: filterIndex == index ? ButtonType.primary : null,
text: text,
fontSize: 14,
innerVerticalPadding: 12,
onTap: () {
setState(() {
filterIndex = index;
});
},
),
);
}

Widget materialItem(
String docId,
String title,
String url,
// ignore: avoid_positional_boolean_parameters
bool isPrintable,
) {
return InkWell(
onTap: () {
setState(() {
filterIndex = index;
});
context.push(
Uri(
path: '/material/$docId',
queryParameters: {
'id': docId,
'title': title,
'pdfUrl': url,
},
).toString(),
);
},
child: Container(
alignment: Alignment.center,
height: 40,
width: 130,
height: 60,
padding: const EdgeInsets.all(10),
margin: const EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
border: Border.all(),
color: (filterIndex == index) ? Colors.black87 : Colors.white,
boxShadow: [
BoxShadow(
color: (filterIndex == index) ? Colors.white : Colors.black,
blurRadius: 2,
offset: (filterIndex == index)
// ignore: use_named_constants
? const Offset(0, 0)
: const Offset(2, 2), // shadow direction: bottom right
color: Colors.blue[50],
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Image.asset(
Assets.icon,
width: 40,
),
const SizedBox(
width: 10,
),
Expanded(
child: Text(title),
),
if (isPrintable)
IconButton(
onPressed: () {
_generatePdf(docId);
},
icon: const Icon(
Icons.print_rounded,
size: 28,
color: Colors.blue,
),
iconSize: 28,
),
],
),
child: Text(
text,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: (filterIndex == index) ? Colors.white : Colors.black,
),
),
),
);
}
Expand All @@ -72,28 +127,14 @@ class _MaterialMenuState extends State<MaterialMenu> {
const SizedBox(
height: 30,
),
Container(
SizedBox(
height: 40,
width: 296,
decoration: BoxDecoration(border: Border.all()),
width: MediaQuery.of(context).size.height - 10,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
customRadioButton(
'siKecil',
bebrasGroupList[0].index,
),
customRadioButton(
'Siaga',
bebrasGroupList[1].index,
),
customRadioButton(
'Penggalang',
bebrasGroupList[2].index,
),
customRadioButton(
'Penegak',
bebrasGroupList[3].index,
...bebrasGroupList.map(
(e) => materialTab(e.label, e.index),
),
],
),
Expand Down Expand Up @@ -122,81 +163,56 @@ class _MaterialMenuState extends State<MaterialMenu> {
return const Text('Loading');
}

return Container(
height: 360,
decoration: BoxDecoration(border: Border.all()),
child: ListView(
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
final materialDoc =
document.data()! as Map<String, dynamic>;
final isDocPrintable =
File('$basePath${document.id}.pdf')
.existsSync();
if (materialDoc['challenge_group'] ==
bebrasGroupList[filterIndex]
.bebrasChallengeKey) {
return InkWell(
onTap: () {
context.push(
Uri(
path: '/material/${document.id}',
queryParameters: {
'id': document.id,
'title': materialDoc['title'],
'pdfUrl': materialDoc['url'],
},
).toString(),
var displayEmpty = true;
final boxHeight =
MediaQuery.of(context).size.height * 0.65;
return SingleChildScrollView(
child: SizedBox(
height: boxHeight,
width: double.infinity,
child: ListView(
children: [
...snapshot.data!.docs.map((d) {
final materialDoc =
d.data()! as Map<String, dynamic>;
if (materialDoc['challenge_group'] ==
bebrasGroupList[filterIndex].key) {
displayEmpty = false;
return materialItem(
d.id,
materialDoc['title'] as String,
materialDoc['url'] as String,
File('$basePath${d.id}.pdf').existsSync(),
);
},
child: Container(
height: 80,
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
decoration:
BoxDecoration(border: Border.all()),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 7,
vertical: 10,
}
return Container();
}),
if (displayEmpty)
Transform.translate(
offset: const Offset(
0,
-10,
), // Set the desired offset
child: Container(
height: boxHeight,
padding: const EdgeInsets.all(10),
margin: const EdgeInsets.only(
bottom: 12,
top: 12,
),
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 140,
child: Text(
materialDoc['title'].toString(),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
isDocPrintable
? IconButton(
onPressed: () {
_generatePdf(document.id);
},
icon: const Icon(
Icons.print_rounded,
size: 36,
color: Colors.blue,
),
iconSize: 36,
)
: const SizedBox(),
],
child: const Center(
child: Text(
'Materi belum ada',
),
),
),
),
);
}
return Container();
}).toList(),
],
),
),
);
},
Expand Down
1 change: 1 addition & 0 deletions app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ flutter:

# To add assets to your application, add an assets section, like this:
assets:
- assets/icon/
- assets/images/
- assets/images/flags/
- .env
Expand Down
Loading