added internet permission in manifest added unique app bar titles for each section fixed card layout fixed card details page layout added appbar button for toggling dark mode
139 lines
4.3 KiB
Dart
139 lines
4.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../domain/models/card.dart';
|
|
|
|
typedef OnLikeCallback = void Function(String? id, String title, bool isLiked)?;
|
|
|
|
class CardCrypto extends StatelessWidget {
|
|
final String id;
|
|
final String title;
|
|
final String? imageUrl;
|
|
final String currentPrice;
|
|
final String priceChange;
|
|
final OnLikeCallback onLike;
|
|
final VoidCallback? onTap;
|
|
final bool isLiked;
|
|
|
|
const CardCrypto({
|
|
super.key,
|
|
required this.id,
|
|
required this.title,
|
|
this.imageUrl,
|
|
required this.currentPrice,
|
|
required this.priceChange,
|
|
this.onLike,
|
|
this.onTap,
|
|
this.isLiked = false,
|
|
});
|
|
|
|
factory CardCrypto.fromData(
|
|
CardData data, {
|
|
OnLikeCallback onLike,
|
|
VoidCallback? onTap,
|
|
bool isLiked = false,
|
|
}) => CardCrypto(
|
|
id: data.id,
|
|
title: data.title,
|
|
imageUrl: data.imageUrl,
|
|
currentPrice: data.currentPrice,
|
|
priceChange: data.priceChange,
|
|
onLike: onLike,
|
|
onTap: onTap,
|
|
isLiked: isLiked,
|
|
);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GestureDetector(
|
|
onTap: onTap,
|
|
child: Container(
|
|
margin: const EdgeInsets.fromLTRB(20, 8, 20, 8),
|
|
constraints: const BoxConstraints(minHeight: 140),
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
|
borderRadius: BorderRadius.circular(15),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black38.withOpacity(0.2),
|
|
spreadRadius: 4,
|
|
offset: const Offset(0, 5),
|
|
blurRadius: 6,
|
|
)
|
|
],
|
|
),
|
|
child: IntrinsicHeight(
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: const BorderRadius.only(
|
|
bottomLeft: Radius.circular(15),
|
|
topLeft: Radius.circular(15),
|
|
),
|
|
child: SizedBox(
|
|
height: double.infinity,
|
|
width: 140,
|
|
child: Image.network(
|
|
imageUrl ?? '',
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (_, __, ___) => const Placeholder(),
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(left: 16, top: 8),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: Theme.of(context).textTheme.headlineLarge,
|
|
),
|
|
Text(
|
|
currentPrice,
|
|
style: Theme.of(context).textTheme.bodyLarge),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Row(
|
|
children: [
|
|
const Spacer(),
|
|
Padding(
|
|
padding: const EdgeInsets.fromLTRB(8, 0, 16, 16),
|
|
child: GestureDetector(
|
|
onTap: () => onLike?.call(id, title, isLiked),
|
|
child: AnimatedSwitcher(
|
|
duration: const Duration(milliseconds: 100),
|
|
child: isLiked
|
|
? const Icon(
|
|
Icons.star,
|
|
color: Colors.orangeAccent,
|
|
key: ValueKey(0),
|
|
)
|
|
: const Icon(
|
|
Icons.star_border,
|
|
key: ValueKey(1),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|