From 7339992573c9011570f1f16600b4a33e460b714f Mon Sep 17 00:00:00 2001 From: halina Date: Thu, 17 Oct 2024 12:15:47 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BB=D0=B0=20=D0=B2=D1=81=D0=B5=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?4=20=D0=BB=D0=B0=D0=B1=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flutter_app/lib/domain/models/card.dart | 15 ++ flutter_app/lib/enums/genre.dart | 6 - .../lib/extensions/album_list_extensions.dart | 7 - flutter_app/lib/main.dart | 63 ++------ flutter_app/lib/models/album.dart | 12 -- flutter_app/lib/models/review.dart | 6 - .../details_page/details_page.dart | 54 +++++++ .../lib/presentation/home_page/card.dart | 133 +++++++++++++++++ .../lib/presentation/home_page/home_page.dart | 138 ++++++++++++++++++ .../lib/repositories/album_repository.dart | 20 --- flutter_app/lib/services/album_service.dart | 12 -- flutter_app/lib/widgets/album_card.dart | 57 -------- 12 files changed, 352 insertions(+), 171 deletions(-) create mode 100644 flutter_app/lib/domain/models/card.dart delete mode 100644 flutter_app/lib/enums/genre.dart delete mode 100644 flutter_app/lib/extensions/album_list_extensions.dart delete mode 100644 flutter_app/lib/models/album.dart delete mode 100644 flutter_app/lib/models/review.dart create mode 100644 flutter_app/lib/presentation/details_page/details_page.dart create mode 100644 flutter_app/lib/presentation/home_page/card.dart create mode 100644 flutter_app/lib/presentation/home_page/home_page.dart delete mode 100644 flutter_app/lib/repositories/album_repository.dart delete mode 100644 flutter_app/lib/services/album_service.dart delete mode 100644 flutter_app/lib/widgets/album_card.dart diff --git a/flutter_app/lib/domain/models/card.dart b/flutter_app/lib/domain/models/card.dart new file mode 100644 index 0000000..12438db --- /dev/null +++ b/flutter_app/lib/domain/models/card.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class CardData { + final String text; + final String descriptionText; + final IconData icon; + final String? imageUrl; + + CardData( + this.text, { + required this.descriptionText, + this.icon = Icons.catching_pokemon, + this.imageUrl, + }); +} \ No newline at end of file diff --git a/flutter_app/lib/enums/genre.dart b/flutter_app/lib/enums/genre.dart deleted file mode 100644 index e883a40..0000000 --- a/flutter_app/lib/enums/genre.dart +++ /dev/null @@ -1,6 +0,0 @@ -enum Genre { - rock, - pop, - jazz, - classical, -} \ No newline at end of file diff --git a/flutter_app/lib/extensions/album_list_extensions.dart b/flutter_app/lib/extensions/album_list_extensions.dart deleted file mode 100644 index dc81396..0000000 --- a/flutter_app/lib/extensions/album_list_extensions.dart +++ /dev/null @@ -1,7 +0,0 @@ -import '../models/album.dart'; - -extension AlbumListExtensions on List { - List sortByTitle() { - return this..sort((a, b) => a.title.compareTo(b.title)); - } -} \ No newline at end of file diff --git a/flutter_app/lib/main.dart b/flutter_app/lib/main.dart index e19a0ac..1f19910 100644 --- a/flutter_app/lib/main.dart +++ b/flutter_app/lib/main.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'models/album.dart'; -import 'repositories/album_repository.dart'; -import 'services/album_service.dart'; -import 'widgets/album_card.dart'; + +import 'presentation/home_page/home_page.dart'; void main() { runApp(const MyApp()); @@ -11,57 +9,20 @@ void main() { class MyApp extends StatelessWidget { const MyApp({super.key}); - @override + @override Widget build(BuildContext context) { return MaterialApp( - title: 'Music Reviewer', + title: '7 Kingdoms', theme: ThemeData( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.purpleAccent), - useMaterial3: true - ), - home: const MyHomePage(title: 'Music Reviewer'), - ); - } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - final AlbumRepository _albumRepository = AlbumRepository(); - List _albums = []; - - @override - void initState() { - super.initState(); - _loadAlbums(); - } - - Future _loadAlbums() async { - _albums = await fetchAlbums(); - setState(() {}); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Text(widget.title), - ), - body: ListView.builder( - itemCount: _albums.length, - itemBuilder: (context, index) { - final album = _albums[index]; - return AlbumCard(album: album); - }, + colorScheme: ColorScheme.fromSeed(seedColor: const Color.fromARGB(255, 20, 40, 150)), + useMaterial3: true, ), + darkTheme: ThemeData.dark().copyWith( + colorScheme: ColorScheme.fromSeed(seedColor: const Color.fromARGB(255, 20, 40, 150)), + useMaterial3: true, + ), + themeMode: ThemeMode.light, // Можно изменить на ThemeMode.light или ThemeMode.dark + home: const MyHomePage(title: '7 Kingdoms'), ); } } diff --git a/flutter_app/lib/models/album.dart b/flutter_app/lib/models/album.dart deleted file mode 100644 index 69b58c3..0000000 --- a/flutter_app/lib/models/album.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'review.dart'; -import '../enums/genre.dart'; - -class Album { - final String title; - final String artist; - final Genre genre; - final String imageUrl; - final List reviews = []; - - Album(this.title, this.artist, this.genre, this.imageUrl); -} \ No newline at end of file diff --git a/flutter_app/lib/models/review.dart b/flutter_app/lib/models/review.dart deleted file mode 100644 index f1c8864..0000000 --- a/flutter_app/lib/models/review.dart +++ /dev/null @@ -1,6 +0,0 @@ -class Review { - final String text; - final int rating; - - Review(this.text, this.rating); -} \ No newline at end of file diff --git a/flutter_app/lib/presentation/details_page/details_page.dart b/flutter_app/lib/presentation/details_page/details_page.dart new file mode 100644 index 0000000..1a99e94 --- /dev/null +++ b/flutter_app/lib/presentation/details_page/details_page.dart @@ -0,0 +1,54 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../domain/models/card.dart'; + +class DetailsPage extends StatelessWidget { + final CardData data; + + const DetailsPage(this.data, {super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), // Добавляем общий отступ слева и справа + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(6.0), + child: Image.network( + data.imageUrl ?? '', + fit: BoxFit.cover, + width: double.infinity, + height: 400.0, + ), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 4.0), + child: Text( + data.text, + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + fontSize: 27.0, + fontFamily: 'Times New Roman', // Укажите здесь желаемый шрифт + ), + ), + ), + Text( + data.descriptionText, + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + fontSize: 20.0, + fontFamily: 'Times New Roman', // Укажите здесь желаемый шрифт + ), + ) + ], + ), + ) + ); + } +} \ No newline at end of file diff --git a/flutter_app/lib/presentation/home_page/card.dart b/flutter_app/lib/presentation/home_page/card.dart new file mode 100644 index 0000000..67820a9 --- /dev/null +++ b/flutter_app/lib/presentation/home_page/card.dart @@ -0,0 +1,133 @@ +part of 'home_page.dart'; + +typedef OnLikeCallback = void Function(String title, bool isLiked)?; + +class _Card extends StatefulWidget { + final String text; + final String descriptionText; + final IconData icon; + final String? imageUrl; + final OnLikeCallback onLike; + final VoidCallback? onTap; + + const _Card( + this.text, { + this.icon = Icons.catching_pokemon, + required this.descriptionText, + this.imageUrl, + this.onLike, + this.onTap, + }); + + factory _Card.fromData( + CardData data, { + OnLikeCallback onLike, + VoidCallback? onTap, + }) => + _Card( + data.text, + descriptionText: data.descriptionText, + icon: data.icon, + imageUrl: data.imageUrl, + onLike: onLike, + onTap: onTap, + ); + + @override + State<_Card> createState() => _CardState(); +} + +class _CardState extends State<_Card> { + bool isLiked = false; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: widget.onTap, + child: Container( + margin: const EdgeInsets.all(16), + constraints: const BoxConstraints(minHeight: 140), + decoration: BoxDecoration( + color: Colors.white70, + borderRadius: BorderRadius.circular(20), + border: Border.all(color: Colors.grey.shade200), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.5), + spreadRadius: 4, + offset: const Offset(0, 5), + blurRadius: 8, + ), + ], + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(15), + child: SizedBox( + height: 250, + width: double.infinity, + child: Image.network( + widget.imageUrl ?? '', + fit: BoxFit.cover, + errorBuilder: (_, __, ___) => const Placeholder(), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.text, + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + fontSize: 20.0, + fontFamily: 'Times New Roman', // Укажите здесь желаемый шрифт + ), + ), + ], + ), + ), + ), + Align( + alignment: Alignment.bottomRight, + child: Padding( + padding: const EdgeInsets.only( + left: 8.0, + right: 16.0, + bottom: 16.0, + ), + child: GestureDetector( + onTap: () { + setState(() { + isLiked = !isLiked; + }); + widget.onLike?.call(widget.text, isLiked); + }, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: isLiked + ? const Icon( + Icons.favorite, + color: Colors.redAccent, + key: ValueKey(0), + ) + : const Icon( + Icons.favorite_border, + key: ValueKey(1), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/flutter_app/lib/presentation/home_page/home_page.dart b/flutter_app/lib/presentation/home_page/home_page.dart new file mode 100644 index 0000000..d9fa3ba --- /dev/null +++ b/flutter_app/lib/presentation/home_page/home_page.dart @@ -0,0 +1,138 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../domain/models/card.dart'; +import '../details_page/details_page.dart'; + +part 'card.dart'; + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + final Color _color = const Color.fromARGB(255, 71, 82, 149); + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: _color, + title: Text(widget.title, style: TextStyle(fontFamily: "Times New Roman", color: Colors.white),), + ), + body: const Body(), + ); + } +} + +class Body extends StatelessWidget { + const Body({super.key}); + + @override + Widget build(BuildContext context) { + final data = [ + CardData( + 'Daenerys Targaryen', + descriptionText: 'Mother of Dragons', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/daenerys.jpg', + ), + CardData( + 'Samwell Tarly', + descriptionText: 'Maester', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/sam.jpg', + ), + CardData( + 'Jon Snow', + descriptionText: 'King of the North', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/jon-snow.jpg', + ), + CardData( + 'Arya Stark', + descriptionText: 'No One', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/arya-stark.jpg', + ), + CardData( + 'Sansa Stark', + descriptionText: 'Lady of Winterfell', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/sansa-stark.jpeg', + ), + CardData( + 'Brandon Stark', + descriptionText: 'Lord of Winterfell', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/bran-stark.jpg', + ), + CardData( + 'Ned Stark', + descriptionText: 'Lord of Winterfell', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/ned-stark.jpg', + ), + CardData( + 'Robert Baratheon', + descriptionText: 'Lord of the Seven Kingdoms', + icon: Icons.favorite, + imageUrl: + 'https://thronesapi.com/assets/images/robert-baratheon.jpeg', + ), + ]; + + return Center( + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: data.map((data) { + return _Card.fromData( + data, + onLike: (String title, bool isLiked) => + _showSnackBar(context, title, isLiked), + onTap: () => _navToDetails(context, data), + ); + }).toList(), + ), + ), + ); + } + + void _navToDetails(BuildContext context, CardData data){ + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => DetailsPage(data)), + ); + } + + void _showSnackBar(BuildContext context, String title, bool isLiked) { + WidgetsBinding.instance.addPostFrameCallback((_) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + 'Вам ${isLiked ? 'понравился персонаж' : 'больше не нравится персонаж'} $title', + style: TextStyle(color: Colors.white), + ), + backgroundColor: const Color.fromARGB(255, 71, 82, 149), + duration: const Duration(seconds: 1), + )); + }); + } +} \ No newline at end of file diff --git a/flutter_app/lib/repositories/album_repository.dart b/flutter_app/lib/repositories/album_repository.dart deleted file mode 100644 index 41a2498..0000000 --- a/flutter_app/lib/repositories/album_repository.dart +++ /dev/null @@ -1,20 +0,0 @@ -import '../models/album.dart'; -import '../models/review.dart'; - -class AlbumRepository { - final List _albums = []; - - void addAlbum(Album album) { - _albums.add(album); - } - - void addReview(String albumTitle, Review review) { - final album = _albums.firstWhere((album) => album.title == albumTitle); - album.reviews.add(review); - } - - List getReviews(String albumTitle) { - final album = _albums.firstWhere((album) => album.title == albumTitle); - return album.reviews; - } -} \ No newline at end of file diff --git a/flutter_app/lib/services/album_service.dart b/flutter_app/lib/services/album_service.dart deleted file mode 100644 index f5d15ea..0000000 --- a/flutter_app/lib/services/album_service.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:async'; -import '../models/album.dart'; -import '../enums/genre.dart'; - -Future> fetchAlbums() async { - await Future.delayed(Duration(seconds: 2)); - return [ - Album('The Dark Side of the Moon', 'Pink Floyd', Genre.rock, 'https://upload.wikimedia.org/wikipedia/ru/1/15/The_Dark_Side_of_the_Moon.png'), - Album('Thriller', 'Michael Jackson', Genre.pop, 'https://upload.wikimedia.org/wikipedia/ru/5/59/Thriller_cover.jpg'), - Album('Back in Black', 'AC/DC', Genre.rock, 'https://www.castlerock.ru/upload/iblock/abe/kx6ghd078yfccf5vzaqc19zcv3lt96jc.jpg'), - ]; -} \ No newline at end of file diff --git a/flutter_app/lib/widgets/album_card.dart b/flutter_app/lib/widgets/album_card.dart deleted file mode 100644 index ffa2386..0000000 --- a/flutter_app/lib/widgets/album_card.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:flutter/material.dart'; -import '../models/album.dart'; - -class AlbumCard extends StatelessWidget { - final Album album; - - const AlbumCard({super.key, required this.album}); - - @override - Widget build(BuildContext context) { - return Card( - margin: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.network( - album.imageUrl, - width: double.infinity, - height: 150, - fit: BoxFit.cover, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - album.title, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - Text( - album.artist, - style: const TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - Text( - '${album.reviews.length} reviews', - style: const TextStyle( - fontSize: 14, - fontStyle: FontStyle.italic, - color: Colors.grey, - ), - ), - ], - ), - ), - ], - ), - ); - } -} \ No newline at end of file