готово (еще не сдано)
This commit is contained in:
parent
6bbfbf2586
commit
ec5437699c
6
lib/domain/models/card_data.dart
Normal file
6
lib/domain/models/card_data.dart
Normal file
@ -0,0 +1,6 @@
|
||||
class CardData {
|
||||
final String name;
|
||||
final double price;
|
||||
|
||||
CardData({required this.name, required this.price});
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lab/presentation/home_page/home_page.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
@ -21,93 +22,3 @@ class MyApp extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: ListView.separated(
|
||||
itemBuilder: (context, index) =>
|
||||
Card(name: "test $index", price: 11.0),
|
||||
separatorBuilder: (context, index) => const SizedBox(height: 20),
|
||||
itemCount: 2,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
class Card extends StatefulWidget {
|
||||
const Card({super.key, required this.name, required this.price});
|
||||
|
||||
final String name;
|
||||
final double price;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CardState();
|
||||
}
|
||||
|
||||
class _CardState extends State<Card> {
|
||||
bool _isFavourite = true;
|
||||
|
||||
void toggleIsFavourite() {
|
||||
setState(() {
|
||||
_isFavourite = !_isFavourite;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 50, bottom: 15, left: 40, right: 40),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.black12, width: 2),
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Image.network(
|
||||
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtAT11wKgHrJBUYzIBFogucXg0a9fE0fQXDQ&s"),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 50),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(widget.name, style: TextStyle(fontSize: 17)),
|
||||
Text("${widget.price} Руб",
|
||||
style: TextStyle(fontSize: 17, color: Colors.orange))
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
top: 10,
|
||||
child: IconButton(
|
||||
icon: Icon(_isFavourite ? Icons.favorite : Icons.favorite_border),
|
||||
color: Colors.red,
|
||||
onPressed: toggleIsFavourite,
|
||||
)
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
38
lib/presentation/details_page/details_page.dart
Normal file
38
lib/presentation/details_page/details_page.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lab/domain/models/card_data.dart';
|
||||
|
||||
class DetailsPage extends StatelessWidget {
|
||||
final CardData data;
|
||||
|
||||
const DetailsPage({super.key, required this.data});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Product ${data.name}'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Image.network(
|
||||
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtAT11wKgHrJBUYzIBFogucXg0a9fE0fQXDQ&s"),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
"Цена: ${data.price} Руб",
|
||||
style: const TextStyle(fontSize: 25, color: Colors.orange),
|
||||
),
|
||||
const Text(
|
||||
"Описание: some text some text some text some text some text some text some text some text ",
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
99
lib/presentation/home_page/card.dart
Normal file
99
lib/presentation/home_page/card.dart
Normal file
@ -0,0 +1,99 @@
|
||||
part of "home_page.dart";
|
||||
|
||||
typedef OnLikeFunction = void Function(String text);
|
||||
|
||||
class _Card extends StatefulWidget {
|
||||
final String name;
|
||||
final double price;
|
||||
|
||||
final OnLikeFunction? onLike;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
const _Card(
|
||||
{required this.name,
|
||||
required this.price,
|
||||
this.onLike,
|
||||
this.onTap});
|
||||
|
||||
factory _Card.fromData(
|
||||
CardData data, OnLikeFunction? onLike, VoidCallback? onTap) =>
|
||||
_Card(
|
||||
name: data.name,
|
||||
price: data.price,
|
||||
onTap: onTap,
|
||||
onLike: onLike,
|
||||
);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CardState();
|
||||
}
|
||||
|
||||
class _CardState extends State<_Card> {
|
||||
bool _isFavourite = false;
|
||||
|
||||
void toggleIsFavourite() {
|
||||
setState(() {
|
||||
_isFavourite = !_isFavourite;
|
||||
});
|
||||
widget.onLike?.call(_isFavourite
|
||||
? "Product added in favourite"
|
||||
: "Product deleted from favourite");
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: widget.onTap,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding:
|
||||
const EdgeInsets.only(top: 15, bottom: 15, left: 30, right: 30),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.black12, width: 2),
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: toggleIsFavourite,
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: _isFavourite
|
||||
? const Icon(
|
||||
Icons.favorite,
|
||||
color: Colors.red,
|
||||
key: ValueKey<int>(0),
|
||||
)
|
||||
: const Icon(
|
||||
Icons.favorite_border,
|
||||
color: Colors.red,
|
||||
key: ValueKey<int>(1),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Center(
|
||||
child: Image.network(
|
||||
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTtAT11wKgHrJBUYzIBFogucXg0a9fE0fQXDQ&s"),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 50),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(widget.name, style: const TextStyle(fontSize: 17)),
|
||||
Text("${widget.price} Руб",
|
||||
style: const TextStyle(fontSize: 17, color: Colors.orange))
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
67
lib/presentation/home_page/home_page.dart
Normal file
67
lib/presentation/home_page/home_page.dart
Normal file
@ -0,0 +1,67 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lab/domain/models/card_data.dart';
|
||||
import 'package:lab/presentation/details_page/details_page.dart';
|
||||
|
||||
part 'card.dart';
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
const MyHomePage({super.key, required this.title});
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
void _showSnackBar(BuildContext context, String text) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text(text),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.black54,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
void _navigateToDetailsPage(BuildContext context, CardData data) {
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(builder: (context) => DetailsPage(data: data)),
|
||||
);
|
||||
}
|
||||
|
||||
final cards = [
|
||||
CardData(name: "test 0", price: 11.0),
|
||||
CardData(name: "test 1", price: 22.0)
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: cards.map((cardData) {
|
||||
return Column(
|
||||
children: [
|
||||
_Card.fromData(
|
||||
cardData,
|
||||
(String text) => _showSnackBar(context, text),
|
||||
() => _navigateToDetailsPage(context, cardData),
|
||||
),
|
||||
const SizedBox(height: 20)
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user