mobile_adaptive_learning/lib/features/learning/widgets/section_card.dart

191 lines
6.7 KiB
Dart

import 'package:english_learning/core/services/constants.dart';
import 'package:english_learning/core/widgets/loading/shimmer_loading_widget.dart';
import 'package:english_learning/features/learning/modules/model/section_model.dart';
import 'package:flutter/material.dart';
import 'package:english_learning/core/utils/styles/theme.dart';
import 'package:cached_network_image/cached_network_image.dart';
class SectionCard extends StatefulWidget {
final Section? section;
final VoidCallback? onTap;
final bool isLoading;
const SectionCard({
super.key,
this.section,
this.onTap,
this.isLoading = false,
});
@override
State<SectionCard> createState() => _SectionCardState();
}
class _SectionCardState extends State<SectionCard>
with AutomaticKeepAliveClientMixin {
String _getFullImageUrl(String thumbnail) {
if (thumbnail.startsWith('http')) {
return thumbnail;
} else {
return '${mediaUrl}section/$thumbnail';
}
}
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
if (widget.isLoading) {
return Card(
color: AppColors.whiteColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 1,
margin: const EdgeInsets.symmetric(vertical: 8.0),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ShimmerLoadingWidget(
width: 90,
height: 104,
borderRadius: BorderRadius.circular(8),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ShimmerLoadingWidget(
width: MediaQuery.of(context).size.width * 0.4,
height: 20,
borderRadius: BorderRadius.circular(4),
),
const SizedBox(height: 12),
Column(
children: List.generate(
3,
(index) => Padding(
padding:
EdgeInsets.only(bottom: index != 2 ? 6.0 : 0),
child: ShimmerLoadingWidget(
width: MediaQuery.of(context).size.width *
(0.8 - (index * 0.1)),
height: 12,
borderRadius: BorderRadius.circular(4),
),
),
),
),
],
),
),
],
),
),
);
}
return Hero(
tag: 'section_${widget.section?.id}',
child: Material(
type: MaterialType.transparency,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
child: GestureDetector(
onTap: widget.onTap,
child: Card(
color: AppColors.whiteColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 1,
margin: const EdgeInsets.symmetric(vertical: 6.0),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CachedNetworkImage(
imageUrl:
_getFullImageUrl(widget.section?.thumbnail ?? ''),
width: 90,
height: 104,
fit: BoxFit.cover,
placeholder: (context, url) => ShimmerLoadingWidget(
width: 90,
height: 104,
borderRadius: BorderRadius.circular(8),
),
errorWidget: (context, url, error) => Container(
width: 90,
height: 104,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(8),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.image_not_supported,
color: Colors.grey[400],
size: 24,
),
const SizedBox(height: 4),
Text(
'Image not\navailable',
style: TextStyle(
color: Colors.grey[600],
fontSize: 10,
),
textAlign: TextAlign.center,
),
],
),
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.section?.name ?? '',
style: AppTextStyles.blackTextStyle.copyWith(
fontSize: 16,
fontWeight: FontWeight.w900,
),
),
const SizedBox(height: 4),
Text(
widget.section?.description ?? '',
style: AppTextStyles.disableTextStyle.copyWith(
fontSize: 13,
fontWeight: FontWeight.w500,
),
maxLines: 4,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
),
),
),
),
);
}
}