Initial commit: Penyerahan final Source code Tugas Akhir
This commit is contained in:
686
lib/widgets/my_course_list.dart
Normal file
686
lib/widgets/my_course_list.dart
Normal file
@ -0,0 +1,686 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:initial_folder/base_service.dart';
|
||||
import 'package:initial_folder/models/my_course_model.dart';
|
||||
import 'package:initial_folder/providers/current_lesson_provider.dart';
|
||||
import 'package:initial_folder/providers/detail_course_provider.dart';
|
||||
import 'package:initial_folder/providers/instructor_provider.dart';
|
||||
import 'package:initial_folder/providers/lesson_course_provider.dart';
|
||||
import 'package:initial_folder/providers/my_course_provider.dart';
|
||||
import 'package:initial_folder/providers/theme_provider.dart';
|
||||
import 'package:initial_folder/screens/course/play_course_page.dart';
|
||||
import 'package:initial_folder/services/course_service.dart';
|
||||
import 'package:initial_folder/services/instructor_service.dart';
|
||||
import 'package:initial_folder/services/lesson_course_service.dart';
|
||||
import 'package:initial_folder/size_config.dart';
|
||||
import 'package:initial_folder/theme.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
import 'package:initial_folder/screens/detail_course/detail_course_screen.dart';
|
||||
import 'package:initial_folder/providers/posting_review_provider.dart'
|
||||
as postReviewProvider;
|
||||
|
||||
class MyCourseList extends StatefulWidget {
|
||||
const MyCourseList({
|
||||
Key? key,
|
||||
required this.dataMyCourseModel,
|
||||
this.onDialogClose,
|
||||
}) : super(key: key);
|
||||
|
||||
final DataMyCourseModel dataMyCourseModel;
|
||||
final VoidCallback? onDialogClose;
|
||||
|
||||
@override
|
||||
State<MyCourseList> createState() => _MyCourseListState();
|
||||
}
|
||||
|
||||
class _MyCourseListState extends State<MyCourseList> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final themeProvider = Provider.of<ThemeProvider>(context);
|
||||
final Brightness brightnessValue =
|
||||
MediaQuery.of(context).platformBrightness;
|
||||
bool isDarkMode = brightnessValue == Brightness.dark;
|
||||
double value = 0.0;
|
||||
if (widget.dataMyCourseModel.rating.length != 0) {
|
||||
value = double.parse(widget.dataMyCourseModel.rating[0].rating!);
|
||||
}
|
||||
TextEditingController _controller = TextEditingController(
|
||||
text: (widget.dataMyCourseModel.rating.length == 0)
|
||||
? ""
|
||||
: widget.dataMyCourseModel.rating[0].review);
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: isDarkMode ? Colors.black : Colors.grey,
|
||||
spreadRadius: 0.01,
|
||||
blurRadius: 2,
|
||||
offset: Offset(0, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
margin: EdgeInsets.only(
|
||||
left: getProportionateScreenWidth(20),
|
||||
right: getProportionateScreenWidth(20),
|
||||
top: getProportionateScreenWidth(10),
|
||||
bottom: 5),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => DetailCourseScreen(
|
||||
resoaktifitas: 'gada',
|
||||
idcourse: widget.dataMyCourseModel.courseId ?? '1',
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: getProportionateScreenWidth(10),
|
||||
left: getProportionateScreenWidth(10),
|
||||
top: getProportionateScreenHeight(10),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(3),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 10,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.dataMyCourseModel.title ?? ' ',
|
||||
style: secondaryTextStyle.copyWith(
|
||||
letterSpacing: 1,
|
||||
fontWeight: semiBold,
|
||||
fontSize: SizeConfig.blockHorizontal! * 3.5,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
SizedBox(height: getProportionateScreenWidth(2)),
|
||||
Text(
|
||||
'${widget.dataMyCourseModel.instructor}',
|
||||
style: thirdTextStyle.copyWith(
|
||||
fontWeight: light,
|
||||
color: Colors.grey.shade600,
|
||||
fontSize: SizeConfig.blockHorizontal! * 3,
|
||||
),
|
||||
),
|
||||
SizedBox(height: getProportionateScreenWidth(6)),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(width: getProportionateScreenWidth(9)),
|
||||
Flexible(
|
||||
flex: 11,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
placeholder: (context, url) => Shimmer(
|
||||
child: Container(
|
||||
color: Colors.black,
|
||||
),
|
||||
gradient: LinearGradient(stops: [
|
||||
0.2,
|
||||
0.5,
|
||||
0.6
|
||||
], colors: [
|
||||
ninthColor,
|
||||
fourthColor,
|
||||
ninthColor
|
||||
])),
|
||||
errorWidget: (context, url, error) =>
|
||||
Icon(Icons.error),
|
||||
imageBuilder: (context, imageUrl) => Container(
|
||||
width: getProportionateScreenWidth(156),
|
||||
height: getProportionateScreenWidth(88),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fill,
|
||||
image: imageUrl,
|
||||
),
|
||||
),
|
||||
),
|
||||
imageUrl: widget.dataMyCourseModel.thumbnail ??
|
||||
'$baseUrl/uploads/courses_thumbnail/course_thumbnail_default_57.jpg',
|
||||
),
|
||||
SizedBox(
|
||||
height: getProportionateScreenHeight(8),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Text(
|
||||
'Progres ${widget.dataMyCourseModel.totalProgress}%',
|
||||
style: thirdTextStyle.copyWith(
|
||||
fontSize: SizeConfig.blockHorizontal! * 3.5,
|
||||
color: Colors.grey.shade600,
|
||||
letterSpacing: 0.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: getProportionateScreenHeight(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.grey.shade300),
|
||||
),
|
||||
Container(
|
||||
width: (SizeConfig.screenWidth -
|
||||
getProportionateScreenWidth(32)) *
|
||||
int.parse(widget.dataMyCourseModel.totalProgress
|
||||
.toString()) /
|
||||
100,
|
||||
height: getProportionateScreenHeight(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: getProportionateScreenWidth(10)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
RatingBarIndicator(
|
||||
itemSize: SizeConfig.blockHorizontal! * 3.5,
|
||||
rating: double.parse(widget
|
||||
.dataMyCourseModel.rating.isEmpty
|
||||
? '0'
|
||||
: widget.dataMyCourseModel.rating[0].rating ??
|
||||
'5'),
|
||||
direction: Axis.horizontal,
|
||||
itemCount: 5,
|
||||
itemBuilder: (context, index) {
|
||||
if (index <
|
||||
double.parse(
|
||||
widget.dataMyCourseModel.rating.isEmpty
|
||||
? '0'
|
||||
: widget.dataMyCourseModel.rating[0]
|
||||
.rating ??
|
||||
'5')) {
|
||||
return FaIcon(
|
||||
FontAwesomeIcons.solidStar,
|
||||
color: primaryColor,
|
||||
);
|
||||
} else {
|
||||
return FaIcon(
|
||||
FontAwesomeIcons.star,
|
||||
color: primaryColor,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
SizedBox(width: getProportionateScreenWidth(5)),
|
||||
InkWell(
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (context) => MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => postReviewProvider
|
||||
.PostingReviewProvider(
|
||||
courseService: CourseService(),
|
||||
),
|
||||
)
|
||||
],
|
||||
child: Consumer<
|
||||
postReviewProvider.PostingReviewProvider>(
|
||||
builder: (context, state, _) {
|
||||
if (state.state ==
|
||||
postReviewProvider
|
||||
.ResultState.uninitilized) {
|
||||
return AlertDialog(
|
||||
surfaceTintColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(5)),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
vertical: 10, horizontal: 10),
|
||||
insetPadding: EdgeInsets.all(1),
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.background,
|
||||
title: Center(
|
||||
child: Text(
|
||||
'Berikan Penilaian',
|
||||
style: thirdTextStyle.copyWith(
|
||||
fontSize: 15,
|
||||
fontWeight: reguler,
|
||||
letterSpacing: 0.2,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.background,
|
||||
),
|
||||
),
|
||||
),
|
||||
content: Container(
|
||||
width:
|
||||
getProportionateScreenWidth(300),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width:
|
||||
getProportionateScreenWidth(
|
||||
170),
|
||||
height:
|
||||
getProportionateScreenWidth(
|
||||
100),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fill,
|
||||
image: NetworkImage(widget
|
||||
.dataMyCourseModel
|
||||
.thumbnail ??
|
||||
'$baseUrl/uploads/courses_thumbnail/course_thumbnail_default_57.jpg'),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height:
|
||||
getProportionateScreenWidth(
|
||||
16)),
|
||||
Text(
|
||||
widget.dataMyCourseModel
|
||||
.title ??
|
||||
'',
|
||||
style: thirdTextStyle
|
||||
.copyWith(
|
||||
letterSpacing: 1,
|
||||
fontWeight:
|
||||
reguler),
|
||||
textAlign:
|
||||
TextAlign.center),
|
||||
SizedBox(
|
||||
height:
|
||||
getProportionateScreenWidth(
|
||||
23),
|
||||
),
|
||||
RatingBar.builder(
|
||||
minRating: 1,
|
||||
itemPadding:
|
||||
EdgeInsets.only(
|
||||
left: 9),
|
||||
initialRating: (widget
|
||||
.dataMyCourseModel
|
||||
.rating
|
||||
.length ==
|
||||
0)
|
||||
? double.parse("0")
|
||||
: double.parse(widget
|
||||
.dataMyCourseModel
|
||||
.rating[0]
|
||||
.rating!),
|
||||
itemSize: 25,
|
||||
maxRating: 5,
|
||||
itemBuilder:
|
||||
(context, _) {
|
||||
return FaIcon(
|
||||
FontAwesomeIcons
|
||||
.solidStar,
|
||||
color: Colors
|
||||
.orange[300]);
|
||||
},
|
||||
onRatingUpdate: (val) {
|
||||
value = val;
|
||||
}),
|
||||
SizedBox(
|
||||
height:
|
||||
getProportionateScreenWidth(
|
||||
16)),
|
||||
SizedBox(
|
||||
width:
|
||||
getProportionateScreenWidth(
|
||||
250),
|
||||
child: TextFormField(
|
||||
validator: (val) {
|
||||
print(value);
|
||||
if ((val == null ||
|
||||
val.isEmpty) ||
|
||||
value == 0.0) {
|
||||
return 'Ulasan dan Rating tidak boleh kosong';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
controller: _controller,
|
||||
textInputAction:
|
||||
TextInputAction.done,
|
||||
cursorColor:
|
||||
secondaryColor,
|
||||
scrollPadding:
|
||||
EdgeInsets.zero,
|
||||
minLines: 2,
|
||||
maxLines: null,
|
||||
decoration:
|
||||
InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Theme.of(
|
||||
context)
|
||||
.brightness ==
|
||||
Brightness.dark
|
||||
? seventeenColor
|
||||
: Colors.grey[200],
|
||||
border:
|
||||
OutlineInputBorder(
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
10,
|
||||
),
|
||||
borderSide:
|
||||
BorderSide
|
||||
.none),
|
||||
hintStyle:
|
||||
secondaryTextStyle
|
||||
.copyWith(
|
||||
color: secondaryColor,
|
||||
letterSpacing: 0.5,
|
||||
fontSize:
|
||||
getProportionateScreenWidth(
|
||||
12),
|
||||
),
|
||||
hintText:
|
||||
"Tulis Ulasan",
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height:
|
||||
getProportionateScreenWidth(
|
||||
10)),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!
|
||||
.validate()) {
|
||||
await state.postingReview(
|
||||
_controller.text,
|
||||
int.parse(widget
|
||||
.dataMyCourseModel
|
||||
.courseId
|
||||
.toString()),
|
||||
value.toInt());
|
||||
await Provider.of<
|
||||
MyCourseProvider>(
|
||||
context,
|
||||
listen: false)
|
||||
.getMyCourse();
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'Kirim Penilaian',
|
||||
style: thirdTextStyle
|
||||
.copyWith(
|
||||
color:
|
||||
Colors.white),
|
||||
),
|
||||
style: ElevatedButton
|
||||
.styleFrom(
|
||||
minimumSize: Size(
|
||||
getProportionateScreenWidth(
|
||||
150),
|
||||
getProportionateScreenHeight(
|
||||
33)),
|
||||
backgroundColor:
|
||||
primaryColor,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (state.state ==
|
||||
postReviewProvider
|
||||
.ResultState.loading) {
|
||||
return AlertDialog(
|
||||
content: Container(
|
||||
height:
|
||||
getProportionateScreenHeight(40),
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (state.state ==
|
||||
postReviewProvider
|
||||
.ResultState.successUpdate) {
|
||||
_controller.clear();
|
||||
// widget.onDialogClose!();
|
||||
|
||||
return AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(10),
|
||||
),
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.background,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
contentPadding:
|
||||
EdgeInsets.fromLTRB(12, 26, 22, 15),
|
||||
content: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom:
|
||||
getProportionateScreenHeight(
|
||||
14)),
|
||||
child: Container(
|
||||
height:
|
||||
getProportionateScreenHeight(
|
||||
30),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Berhasil mengedit ulasan',
|
||||
style: primaryTextStyle.copyWith(
|
||||
fontSize:
|
||||
getProportionateScreenWidth(
|
||||
12),
|
||||
letterSpacing: 0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (state.state ==
|
||||
postReviewProvider
|
||||
.ResultState.successAdd) {
|
||||
_controller.clear();
|
||||
// widget.onDialogClose!();
|
||||
|
||||
return AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(10),
|
||||
),
|
||||
backgroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.background,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
contentPadding: EdgeInsets.fromLTRB(
|
||||
12, 26, 22, 15),
|
||||
content: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom:
|
||||
getProportionateScreenHeight(
|
||||
14)),
|
||||
child: Container(
|
||||
height:
|
||||
getProportionateScreenHeight(
|
||||
30),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Berhasil memberikan ulasan',
|
||||
style: primaryTextStyle.copyWith(
|
||||
fontSize:
|
||||
getProportionateScreenWidth(
|
||||
12),
|
||||
letterSpacing: 0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
} else if (state.state ==
|
||||
postReviewProvider.ResultState.failed) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
'Terjadi Kesalahan',
|
||||
style: primaryTextStyle,
|
||||
),
|
||||
);
|
||||
}
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
'Terjadi Kesalahan',
|
||||
style: primaryTextStyle,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
child: widget.dataMyCourseModel.rating.isEmpty
|
||||
? Text(
|
||||
'Beri Penilaian',
|
||||
style: thirdTextStyle.copyWith(
|
||||
color: themeProvider.themeData == ThemeClass.darkmode
|
||||
?primaryColor : primaryColorligtmode,
|
||||
fontSize:
|
||||
getProportionateScreenHeight(10),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'Edit Penilaian',
|
||||
style: thirdTextStyle.copyWith(
|
||||
color: themeProvider.themeData == ThemeClass.darkmode
|
||||
?primaryColor : primaryColorligtmode,
|
||||
fontSize:
|
||||
getProportionateScreenHeight(10),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(
|
||||
create: (context) =>
|
||||
CurrentLessonProvider(),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => LessonCourseProvider(
|
||||
lessonCourseService:
|
||||
LessonCourseService(),
|
||||
id: int.parse(
|
||||
widget.dataMyCourseModel.courseId ??
|
||||
'0'),
|
||||
),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => DetailCourseProvider(
|
||||
courseService: CourseService(),
|
||||
id: widget.dataMyCourseModel.courseId ??
|
||||
'1'),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => InstructorProvider(
|
||||
instructorService: InstructorService(),
|
||||
id: int.parse(widget
|
||||
.dataMyCourseModel.instructorId!),
|
||||
),
|
||||
),
|
||||
],
|
||||
child: PlayCourse(
|
||||
judul: widget.dataMyCourseModel.title ?? '',
|
||||
instruktur:
|
||||
widget.dataMyCourseModel.instructor ?? '',
|
||||
thumbnail: widget
|
||||
.dataMyCourseModel.thumbnail ??
|
||||
'$baseUrl/uploads/courses_thumbnail/course_thumbnail_default_57.jpg',
|
||||
courseeid:
|
||||
widget.dataMyCourseModel.courseId ?? '',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Mulai',
|
||||
style: thirdTextStyle.copyWith(
|
||||
color: baruTextutih,
|
||||
),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: Size(getProportionateScreenWidth(100),
|
||||
getProportionateScreenHeight(33)),
|
||||
backgroundColor: themeProvider.themeData == ThemeClass.darkmode
|
||||
?primaryColor : primaryColorligtmode,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10))),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: getProportionateScreenHeight(10)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user