From e674af146a966c4723319bc7ec37a416bb54837e Mon Sep 17 00:00:00 2001 From: Kirill <117719052+KirillFirsof@users.noreply.github.com> Date: Fri, 20 Dec 2024 12:17:48 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A7=D0=B8=D1=81=D1=82=D0=BE=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B2=D0=BE=D0=B2=D1=8B=20=D0=BF=D0=B8=D1=88=D1=83=20?= =?UTF-8?q?=D1=87=D1=82=D0=BE=D0=B1=20=D0=B1=D1=8B=D0=BB=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 1437 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1061 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 1909 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 2742 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 4185 -> 0 bytes assets/launcher.png | Bin 26012 -> 0 bytes l10n/app_en.arb | 11 +- l10n/app_ru.arb | 11 +- lib/components/locale/l10n/app_locale.dart | 54 ++++- lib/components/locale/l10n/app_locale_en.dart | 25 ++- lib/components/locale/l10n/app_locale_ru.dart | 25 ++- lib/data/dtos/Task.dart | 33 +++ lib/data/dtos/films_dto.dart | 60 ----- lib/data/mapper/films_mapper.dart | 38 ---- lib/data/repositories/api_interface.dart | 2 +- lib/data/repositories/mock_repository.dart | 2 +- .../repositories/potter_films_repository.dart | 44 ---- lib/data/repositories/repository.dart | 82 +++++++ lib/domain/models/home.dart | 3 +- lib/main.dart | 8 +- lib/presentaition/home_page/bloc/bloc.dart | 32 +-- lib/presentaition/home_page/bloc/events.dart | 9 +- lib/presentaition/home_page/bloc/state.dart | 3 - lib/presentaition/home_page/card.dart | 77 +++---- lib/presentaition/home_page/home_page.dart | 209 ++++++++++++++---- local.properties | 8 + makefile | 5 +- pubspec.yaml | 1 - 28 files changed, 474 insertions(+), 268 deletions(-) delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 assets/launcher.png create mode 100644 lib/data/dtos/Task.dart delete mode 100644 lib/data/dtos/films_dto.dart delete mode 100644 lib/data/mapper/films_mapper.dart delete mode 100644 lib/data/repositories/potter_films_repository.dart create mode 100644 lib/data/repositories/repository.dart create mode 100644 local.properties diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 3f746144fc3a53e2452cf7c163d7b732fc691dd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1437 zcmV;O1!DS%P)g5w7@n~wiIXNxNDB&;;IO-JLU5`C5(h5adR=}5M%#1S?smKQ73Xrf96&f*tyXd6x|naz&o3`8zw`%>=rp{GBSOlbf06&>Q%dQe`TO{r zuL=*}t$cl+l2v$4g?ET5#-8N zHZ?IQE8IW#QiQQ!n9t|o)&y_(01Vf~2)7$cloO0$b}bgoaf}qaWEchy7HTK#Z9#)! zg$o+I3Z_!2B;U?(#qe>D%XwhkjF$|fOBIv7Vu*nk6Ru1-=@KlMyB{N3D3v&C{6DfO zB%LcJ3D9BYLAd;y+y{$lCju*mQ4K~8hT*yx*sXNB5$h7iqk3IreVg%;VYXhj_%jj? zM4PwQs)}(oM&=%$aH%vI7||P`<7|wCxgyUzGztcL2x}X}1QFJdfQcZBn1JEBn8U+E zsjrU&F@foJd$oBS+klr06NGJ?a~ubtFpBqjJse3S(yxn=-N-Oe4CQlOXCbRlGM^nd zkC{Xg3sglr*vy&Pn8X5Ak(NRe^;iN+p^apob|D;PsnARi%>JY4jmI+~2`Lpz(`*%* z@v27Y{SV)Hj$QunW1r`WnrPbrdfK_`{qhqr&GLI6Xf?86UlATtXeZ(ThR{)XOpzZz zl`&iw18>W1C}!rvUw`&-q3hoN_&wn^X4{io3SKfyuoJBOc?axPng{;XGI<#``SY2` zJbL~9>pVcKeg2}e9+MEGeB*8I6*E?kB~YGkPK9NQCekUGB)2drH6o5BV})k$-}2l7 z+UWW-Jv^!(?M0!GaD1UJ$;#nk{*Et4C=g9c$@r)#8P?B z0)`BUaQYsB1q|}*1p$^HD=}V5o5auM3sb(mqp)WIm~GftfzpCR;aF0Bl8Sa|V`Q$4 zI*6s;x>?2)SMJ+@Hcm#Pywa^Cfnj3bRBfTTEST;4-N+(Z@EOKT1%vvRPbeFOX2L@W zqBBJdNvDlz-V#kFmcBJE2#CtxvlQ&k!tqkH9jf z*XxnQlqyPyW8OTDDd|}d7^b90U;%^QWxZ4}x0W%77n%xt7J|%UgH>LYH1`E0)BYyG zI$i;RR;)e)TrTRdEW83zDy=SU~0`gj|7JRH`V@9>6V-8vbvn=c65jTlYpWiFk5q`YTAV1k`s9q&z^ot>SYp04sg r7-s1mO}bNGPxd(p*6|9+%YgY81s&5cZ2^$Y00000NkvXXu0mjfP#d3h diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 122e71f4e27809499a2ab34e8dd7811ba973e0e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1061 zcmV+=1ls$FP) z%Wl&^6rIOS^DN0%bce)euwhZDV#A^mf5Mj_gy@DZ03rAR1QP4+yKK@VPV=zMnYoSY zPV9K>>FY|ZCMVVPopawVt=H?>Y^IdzbUIg8SN(oJNs{a9>)~+tBshs@CKSi9loBTx z2z%2s#Tf@593VcXRyLbWhT~96Padb~bjozi=ktt4AQ_Ei_?NS@AD=&ckP+YPvezGd z{EEZH`?tf_Z}iDKPdyIa+-2wI=SoSD-h9Mm`Nr#1EdKrNoV;tMmRhYAlTSpe)e2@p zFZi#-C*yIU#z1-J{hyX8%hG-yWMVA;>tYwj!hgx_*tfjza9rS1~n^UN^2pCsfgnQ(a@|& z2Dl8BBfvFfLcLxO-2-eRxKI)hj0j8wS0x@NiE&SnO2M3&W@Msi8_y`(7 zIQZO;b8RgYDe=AX)Z^e`y{yP2H`HqiA-E7qxGs1*JUm2*fkrOv`*Dq+E^?XaYw-rR z_tfLyl=VU!@C+QJWxNu%Ot@U|pTSChJq{k^vfVV3JJqtT&}cN`8UWtL<1yC;i~yDR zW~X(;@_1EpHu`tX_e?1OvdRepeB`NA2?w!8$Zv1V7HO zx)SFcfy8&)ELe+^*k6x>n*p2Yg8wr2!LOJE_Ty?>l%rHEa|U&Vi7&*5ryd8t|IL-c z(u@X!0Z76L_M&nl_;E&UsKj@-4i;0LNaL=adK?^nG-I{0!aOHdD)B6C`qH{7XOQ0Z zb00k}9>lK|1e4k!sj*P44xh(K-#&Mq+$36Cq7+Gdi(1!Uf&hL$L5(a+>_OX76e3is z!{_lmE0Ek)sk#${As#IGclbP>&obIF#KFWBrNIPYvMh|?8+oBZC)Z46nL}Q1YzbO>?{5qK9BEC zjF}+1IIHVU5N2Ww;`bq3R;$D3aji>R7T?uVkAqXK4xh(+-R`8!qHd4VuDoq$4C}bBUCxij@U#vBTL|gC)n+!70xDU^PJzO?1?Qe fhC=@N@(}oc2Xik~A|RXp00000NkvXXu0mjfe{uuF diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 4e139fc643e9bf8c59eb0cb0497004070866348d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1909 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 diff --git a/l10n/app_en.arb b/l10n/app_en.arb index 12efc72..432e2d2 100644 --- a/l10n/app_en.arb +++ b/l10n/app_en.arb @@ -2,8 +2,15 @@ "@@locale": "en", "search": "Search", - "liked": "liked!", - "disliked": "disliked :(", + "complete": "Complete!", + "uncomplete": "Not complete :(", + "delete": "Delete", + "addtask": "Add Task", + "cancel": "Cancel", + "addbutton": "Add", + "nameplaceholder": "Enter task name", + "descriptionplaceholder": "Enter task description", + "imageplaceholder": "Select image", "arbEnding": "Чтобы не забыть про отсутствие запятой :)" } \ No newline at end of file diff --git a/l10n/app_ru.arb b/l10n/app_ru.arb index 2c4995d..5f160dd 100644 --- a/l10n/app_ru.arb +++ b/l10n/app_ru.arb @@ -2,8 +2,15 @@ "@@locale": "ru", "search": "Поиск", - "liked": "понравился!", - "disliked": "Уже не нравится :(", + "complete": "Выполнено!", + "uncomplete": "Ещё не выполнена :(", + "delete": "Удалено", + "addtask": "Добавить задачу", + "cancel": "Отмена", + "addbutton": "Добавить", + "nameplaceholder": "Введите название задачи", + "descriptionplaceholder": "Введите описание задачи", + "imageplaceholder": "выберите изображение", "arbEnding": "Чтобы не забыть про отсутствие запятой :)" } \ No newline at end of file diff --git a/lib/components/locale/l10n/app_locale.dart b/lib/components/locale/l10n/app_locale.dart index b67c8f3..6afc3b1 100644 --- a/lib/components/locale/l10n/app_locale.dart +++ b/lib/components/locale/l10n/app_locale.dart @@ -101,17 +101,59 @@ abstract class AppLocale { /// **'Поиск'** String get search; - /// No description provided for @liked. + /// No description provided for @complete. /// /// In ru, this message translates to: - /// **'понравился!'** - String get liked; + /// **'Выполнено!'** + String get complete; - /// No description provided for @disliked. + /// No description provided for @uncomplete. /// /// In ru, this message translates to: - /// **'Уже не нравится :('** - String get disliked; + /// **'Ещё не выполнена :('** + String get uncomplete; + + /// No description provided for @delete. + /// + /// In ru, this message translates to: + /// **'Удалено'** + String get delete; + + /// No description provided for @addtask. + /// + /// In ru, this message translates to: + /// **'Добавить задачу'** + String get addtask; + + /// No description provided for @cancel. + /// + /// In ru, this message translates to: + /// **'Отмена'** + String get cancel; + + /// No description provided for @addbutton. + /// + /// In ru, this message translates to: + /// **'Добавить'** + String get addbutton; + + /// No description provided for @nameplaceholder. + /// + /// In ru, this message translates to: + /// **'Введите название задачи'** + String get nameplaceholder; + + /// No description provided for @descriptionplaceholder. + /// + /// In ru, this message translates to: + /// **'Введите описание задачи'** + String get descriptionplaceholder; + + /// No description provided for @imageplaceholder. + /// + /// In ru, this message translates to: + /// **'выберите изображение'** + String get imageplaceholder; /// No description provided for @arbEnding. /// diff --git a/lib/components/locale/l10n/app_locale_en.dart b/lib/components/locale/l10n/app_locale_en.dart index 599548c..c258c23 100644 --- a/lib/components/locale/l10n/app_locale_en.dart +++ b/lib/components/locale/l10n/app_locale_en.dart @@ -10,10 +10,31 @@ class AppLocaleEn extends AppLocale { String get search => 'Search'; @override - String get liked => 'liked!'; + String get complete => 'Complete!'; @override - String get disliked => 'disliked :('; + String get uncomplete => 'Not complete :('; + + @override + String get delete => 'Delete'; + + @override + String get addtask => 'Add Task'; + + @override + String get cancel => 'Cancel'; + + @override + String get addbutton => 'Add'; + + @override + String get nameplaceholder => 'Enter task name'; + + @override + String get descriptionplaceholder => 'Enter task description'; + + @override + String get imageplaceholder => 'Select image'; @override String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)'; diff --git a/lib/components/locale/l10n/app_locale_ru.dart b/lib/components/locale/l10n/app_locale_ru.dart index 8bf7ec0..8cd721e 100644 --- a/lib/components/locale/l10n/app_locale_ru.dart +++ b/lib/components/locale/l10n/app_locale_ru.dart @@ -10,10 +10,31 @@ class AppLocaleRu extends AppLocale { String get search => 'Поиск'; @override - String get liked => 'понравился!'; + String get complete => 'Выполнено!'; @override - String get disliked => 'Уже не нравится :('; + String get uncomplete => 'Ещё не выполнена :('; + + @override + String get delete => 'Удалено'; + + @override + String get addtask => 'Добавить задачу'; + + @override + String get cancel => 'Отмена'; + + @override + String get addbutton => 'Добавить'; + + @override + String get nameplaceholder => 'Введите название задачи'; + + @override + String get descriptionplaceholder => 'Введите описание задачи'; + + @override + String get imageplaceholder => 'выберите изображение'; @override String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)'; diff --git a/lib/data/dtos/Task.dart b/lib/data/dtos/Task.dart new file mode 100644 index 0000000..d66be83 --- /dev/null +++ b/lib/data/dtos/Task.dart @@ -0,0 +1,33 @@ +class Task { + final int id; + final String name; + final String description; + final String date; + final String imageUrl; + + Task({ + required this.id, + required this.name, + required this.description, + required this.date, + required this.imageUrl + }); + + Map toJson() { + return { + 'name': name, + 'description': description, + 'date': date, + 'imageUrl': imageUrl + }; + } + factory Task.fromJson(Map json) { + return Task( + id: json['id'], + name: json['name'], + description: json['description'], + date: json['date'], + imageUrl: json['imageUrl'] + ); + } +} \ No newline at end of file diff --git a/lib/data/dtos/films_dto.dart b/lib/data/dtos/films_dto.dart deleted file mode 100644 index 009399c..0000000 --- a/lib/data/dtos/films_dto.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -part 'films_dto.g.dart'; - -@JsonSerializable(createToJson: false) -class FilmsDto { - final List? data; - final MetaDto? meta; - - const FilmsDto({ - this.data, - this.meta, - }); - - factory FilmsDto.fromJson(Map json) => _$FilmsDtoFromJson(json); -} - -@JsonSerializable(createToJson: false) -class FilmDataDto { - final String? id; - final String? type; - final FilmAttributesDataDto? attributes; - - const FilmDataDto({this.id, this.type, this.attributes}); - - factory FilmDataDto.fromJson(Map json) => _$FilmDataDtoFromJson(json); -} - -@JsonSerializable(createToJson: false) -class FilmAttributesDataDto { - final String? title; - final DateTime? release_date; - final String? budget; - final String? poster; - - const FilmAttributesDataDto({this.title, this.release_date, this.budget, this.poster}); - - factory FilmAttributesDataDto.fromJson(Map json) => - _$FilmAttributesDataDtoFromJson(json); -} - -@JsonSerializable(createToJson: false) -class MetaDto { - final PaginationDto? pagination; - - const MetaDto({this.pagination}); - - factory MetaDto.fromJson(Map json) => _$MetaDtoFromJson(json); -} - -@JsonSerializable(createToJson: false) -class PaginationDto { - final int? current; - final int? next; - final int? last; - - const PaginationDto({this.current, this.next, this.last}); - - factory PaginationDto.fromJson(Map json) => _$PaginationDtoFromJson(json); -} diff --git a/lib/data/mapper/films_mapper.dart b/lib/data/mapper/films_mapper.dart deleted file mode 100644 index 22b23e8..0000000 --- a/lib/data/mapper/films_mapper.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:testlab/data/dtos/films_dto.dart'; -import 'package:testlab/domain/models/card.dart'; -import 'package:testlab/domain/models/home.dart'; -import 'package:intl/intl.dart'; - -const _imagePlaceholder = - 'https://ralfvanveen.com/wp-content/uploads/2021/06/Placeholder-_-Glossary.svg'; - -extension FilmsDtoToModel on FilmsDto { - HomeData toDomain() => HomeData( - data: data?.map((e) => e.toDomain()).toList(), - nextPage: meta?.pagination?.next, - ); -} - -extension FilmDataDtoToModel on FilmDataDto { - CardData toDomain() => CardData( - attributes?.title ?? 'UNKNOWN', - imageUrl: attributes?.poster ?? _imagePlaceholder, - descriptionText: - _makeDescriptionText(formatDateToString(attributes?.release_date), attributes?.budget), - id: id, - ); - - String formatDateToString(DateTime? date) { - return date != null ? DateFormat('yyyy-MM-dd').format(date) : 'UNKNOWN DATE'; - } - - String _makeDescriptionText(String? release_date, String? budget) { - return release_date != null && budget != null - ? '$release_date \n $budget' - : release_date != null - ? 'release: $release_date' - : budget != null - ? 'budget: $budget' - : ''; - } -} diff --git a/lib/data/repositories/api_interface.dart b/lib/data/repositories/api_interface.dart index 6760b2c..e03b911 100644 --- a/lib/data/repositories/api_interface.dart +++ b/lib/data/repositories/api_interface.dart @@ -3,5 +3,5 @@ import 'package:testlab/domain/models/home.dart'; typedef OnErrorCallback = void Function(String? error); abstract class ApiInterface { - Future loadData({OnErrorCallback? onError}); + Future loadData(String name); } diff --git a/lib/data/repositories/mock_repository.dart b/lib/data/repositories/mock_repository.dart index c83abc8..3b62fb8 100644 --- a/lib/data/repositories/mock_repository.dart +++ b/lib/data/repositories/mock_repository.dart @@ -5,7 +5,7 @@ import 'package:testlab/domain/models/home.dart'; class MockRepository extends ApiInterface { @override - Future loadData({OnErrorCallback? onError}) async { + Future loadData(String name) async { return HomeData(data: [ CardData( 'Mobile dev', diff --git a/lib/data/repositories/potter_films_repository.dart b/lib/data/repositories/potter_films_repository.dart deleted file mode 100644 index b4b0d99..0000000 --- a/lib/data/repositories/potter_films_repository.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:dio/dio.dart'; -import 'package:testlab/data/dtos/films_dto.dart'; -import 'package:testlab/data/mapper/films_mapper.dart'; -import 'package:testlab/data/repositories/api_interface.dart'; -import 'package:pretty_dio_logger/pretty_dio_logger.dart'; -import 'package:testlab/domain/models/home.dart'; - -class PotterFilmsRepository extends ApiInterface { - static final Dio _dio = Dio() - ..interceptors.add(PrettyDioLogger( - requestHeader: true, - requestBody: true, - )); - - static const String _baseUrl = 'https://api.potterdb.com'; - - @override - Future loadData({ - OnErrorCallback? onError, - String? q, - int page = 1, - int pageSize = 5, - }) async { - try { - const String url = '$_baseUrl/v1/movies'; - - final Response response = await _dio.get>( - url, - queryParameters: { - 'filter[title_cont]': q, - 'page[number]': page, - 'page[size]': pageSize, - }, - ); - - final FilmsDto dto = FilmsDto.fromJson(response.data as Map); - final HomeData data = dto.toDomain(); - return data; - } on DioException catch (e) { - onError?.call(e.error?.toString()); - return null; - } - } -} diff --git a/lib/data/repositories/repository.dart b/lib/data/repositories/repository.dart new file mode 100644 index 0000000..6cb4d17 --- /dev/null +++ b/lib/data/repositories/repository.dart @@ -0,0 +1,82 @@ +import 'dart:convert'; +import 'dart:async'; +import 'package:http/http.dart' as http; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +import '../../domain/models/card.dart'; +import '../../domain/models/home.dart'; +import '../dtos/Task.dart'; +import 'api_interface.dart'; + +class repository extends ApiInterface { + Future loadData(String name) async { + final response = await http.get(Uri.parse('http://192.168.1.67:8080/api/1.0/task/name/$name')); + //final response = await http.get(Uri.parse('http://192.168.112.64:8080/api/1.0/task/name/$name')); + + if (response.statusCode == 200) { + List jsonResponse = json.decode(utf8.decode(response.bodyBytes)); + + List cardDataList = jsonResponse.map((taskJson) { + Task task = Task.fromJson(taskJson); + + return CardData( + task.name, + descriptionText: '${task.description}\nДата: ${task.date}', + imageUrl: task.imageUrl, + icon: Icons.close, + id: task.id.toString(), + ); + }).toList(); + + return HomeData(data: cardDataList); + } else { + throw Exception('Не удалось загрузить задачи'); + } + } + + Future addTask(String taskName, String taskDescription, String? taskImageUrl) async { + + DateTime now = DateTime.now(); + + String formattedDate = DateFormat('dd.MM.yyyy').format(now); + + String defaultImageUrl = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTOwRConBYl2t6L8QMOAQqa5FDmPB_bg7EnGA&s"; + + String finalImageUrl = taskImageUrl ?? defaultImageUrl; + + final response = await http.post( + Uri.parse('http://192.168.1.67:8080/api/1.0/task'), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + body: jsonEncode(Task( + id: 0, + name: taskName, + description: taskDescription, + date: formattedDate, + imageUrl: finalImageUrl, + ).toJson()), + ); + + if (response.statusCode == 200) { + } else { + throw Exception('Ошибка при добавлении задачи'); + } + } + + Future deleteTask(int taskId) async { + final response = await http.delete( + Uri.parse('http://192.168.1.67:8080/api/1.0/task/$taskId'), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + ); + + if (response.statusCode == 200) { + // Задача успешно удалена + } else { + throw Exception('Ошибка при удалении задачи'); + } + } +} \ No newline at end of file diff --git a/lib/domain/models/home.dart b/lib/domain/models/home.dart index 2f0ba57..a1bd389 100644 --- a/lib/domain/models/home.dart +++ b/lib/domain/models/home.dart @@ -2,7 +2,6 @@ import 'card.dart'; class HomeData { final List? data; - final int? nextPage; - HomeData({this.data, this.nextPage}); + HomeData({this.data}); } diff --git a/lib/main.dart b/lib/main.dart index b5bf78a..02b794b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:testlab/presentaition/home_page/home_page.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:testlab/presentaition/home_page/bloc/bloc.dart'; -import 'data/repositories/potter_films_repository.dart'; +import 'data/repositories/repository.dart'; import 'package:testlab/presentaition/like_bloc/like_bloc.dart'; import 'package:testlab/presentaition/locale_bloc/locale_bloc.dart'; import 'package:testlab/presentaition/locale_bloc/locale_state.dart'; @@ -34,15 +34,15 @@ class MyApp extends StatelessWidget { colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), - home: RepositoryProvider( + home: RepositoryProvider( lazy: true, - create: (_) => PotterFilmsRepository(), + create: (_) => repository(), child: BlocProvider( lazy: false, create: (context) => LikeBloc(), child: BlocProvider( lazy: false, - create: (context) => HomeBloc(context.read()), + create: (context) => HomeBloc(context.read()), child: const MyHomePage(title: 'Фирсов Кирилл Алексеевич'), ), ), diff --git a/lib/presentaition/home_page/bloc/bloc.dart b/lib/presentaition/home_page/bloc/bloc.dart index 3d899c4..9c673e4 100644 --- a/lib/presentaition/home_page/bloc/bloc.dart +++ b/lib/presentaition/home_page/bloc/bloc.dart @@ -1,39 +1,39 @@ import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:testlab/data/repositories/potter_films_repository.dart'; import 'package:testlab/presentaition/home_page/bloc/events.dart'; import 'package:testlab/presentaition/home_page/bloc/state.dart'; +import '../../../data/repositories/repository.dart'; + class HomeBloc extends Bloc { - final PotterFilmsRepository repo; + final repository repo; HomeBloc(this.repo) : super(const HomeState()) { on(_onLoadData); + on(_onAddTask); } Future _onLoadData(HomeLoadDataEvent event, Emitter emit) async { - if (event.nextPage == null) { - emit(state.copyWith(isLoading: true)); - } else { - emit(state.copyWith(isPaginationLoading: true)); - } + emit(state.copyWith(isLoading: true)); String? error; - final data = await repo.loadData( - q: event.search, - page: event.nextPage ?? 1, - onError: (e) => error = e, - ); + final data = await repo.loadData(event.search.toString()); - if (event.nextPage != null) { - data?.data?.insertAll(0, state.data?.data ?? []); - } + + //data?.data?.insertAll(0, state.data?.data ?? []); emit(state.copyWith( isLoading: false, - isPaginationLoading: false, data: data, error: error, )); } + + Future _onAddTask(HomeAddTaskEvent eventTask, Emitter emit) async { + emit(state.copyWith(isLoading: true)); + + String? error; + + await repo.addTask(eventTask.name.toString(), eventTask.name.toString(), eventTask.name.toString(),); + } } diff --git a/lib/presentaition/home_page/bloc/events.dart b/lib/presentaition/home_page/bloc/events.dart index cefba70..2f8272e 100644 --- a/lib/presentaition/home_page/bloc/events.dart +++ b/lib/presentaition/home_page/bloc/events.dart @@ -4,7 +4,12 @@ abstract class HomeEvent { class HomeLoadDataEvent extends HomeEvent { final String? search; - final int? nextPage; - const HomeLoadDataEvent({this.search, this.nextPage}); + const HomeLoadDataEvent({this.search}); +} + +class HomeAddTaskEvent extends HomeEvent { + final String? name; + + const HomeAddTaskEvent({this.name}); } diff --git a/lib/presentaition/home_page/bloc/state.dart b/lib/presentaition/home_page/bloc/state.dart index 2990318..d415d75 100644 --- a/lib/presentaition/home_page/bloc/state.dart +++ b/lib/presentaition/home_page/bloc/state.dart @@ -9,13 +9,11 @@ part 'state.g.dart'; class HomeState extends Equatable { final HomeData? data; final bool isLoading; - final bool isPaginationLoading; final String? error; const HomeState({ this.data, this.isLoading = false, - this.isPaginationLoading = false, this.error, }); @@ -23,7 +21,6 @@ class HomeState extends Equatable { List get props => [ data, isLoading, - isPaginationLoading, error, ]; } diff --git a/lib/presentaition/home_page/card.dart b/lib/presentaition/home_page/card.dart index 8769405..9a10929 100644 --- a/lib/presentaition/home_page/card.dart +++ b/lib/presentaition/home_page/card.dart @@ -1,6 +1,7 @@ part of 'home_page.dart'; typedef OnLikeCallback = void Function(String? id, String title, bool isLiked)?; +typedef OnDeleteCallback = void Function(String? id, String title)?; class _Card extends StatelessWidget { final String text; @@ -8,6 +9,7 @@ class _Card extends StatelessWidget { final IconData icon; final String? imageUrl; final OnLikeCallback onLike; + final OnDeleteCallback onDelete; final VoidCallback? onTap; final String? id; final bool isLiked; @@ -18,6 +20,7 @@ class _Card extends StatelessWidget { required this.descriptionText, this.imageUrl, this.onLike, + this.onDelete, this.onTap, this.id, this.isLiked = false, @@ -26,6 +29,7 @@ class _Card extends StatelessWidget { factory _Card.fromData( CardData data, { OnLikeCallback onLike, + OnDeleteCallback onDelete, VoidCallback? onTap, bool isLiked = false, }) => @@ -35,18 +39,12 @@ class _Card extends StatelessWidget { icon: data.icon, imageUrl: data.imageUrl, onLike: onLike, + onDelete: onDelete, onTap: onTap, isLiked: isLiked, id: data.id, ); - /*@override - State<_Card> createState() => _CardState(); -} - -class _CardState extends State<_Card> { - bool isLiked = false;*/ - @override Widget build(BuildContext context) { return GestureDetector( @@ -89,19 +87,6 @@ class _CardState extends State<_Card> { Expanded( child: Stack( children: [ - Align( - alignment: Alignment.bottomLeft, - child: Padding( - padding: const EdgeInsets.only( - left: 8.0, - right: 8.0, - bottom: 16.0, - ), - child: Icon( - icon, - ), - ), - ), Padding( padding: const EdgeInsets.only(left: 3.0, top: 3.0), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -124,30 +109,38 @@ class _CardState extends State<_Card> { ), ], )), - Align( - alignment: Alignment.bottomRight, - child: Padding( - padding: const EdgeInsets.only( - right: 16.0, - bottom: 16.0, - ), - child: GestureDetector( - onTap: () => onLike?.call(id, text, isLiked), - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - child: isLiked - ? const Icon( - Icons.thumb_up, - color: Colors.redAccent, - key: ValueKey(0), - ) - : const Icon( - Icons.thumb_up_off_alt, - key: ValueKey(1), - ), + Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () => onDelete?.call(id, text), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Icon( + icon, ), ), - ), + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: GestureDetector( + onTap: () => onLike?.call(id, text, isLiked), + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: isLiked + ? const Icon( + Icons.check_box_rounded, + color: Colors.redAccent, + key: ValueKey(0), + ) + : const Icon( + Icons.check_box, + key: ValueKey(1), + ), + ), + ), + ), + ], ), ], ), diff --git a/lib/presentaition/home_page/home_page.dart b/lib/presentaition/home_page/home_page.dart index d805c37..0fc0dd5 100644 --- a/lib/presentaition/home_page/home_page.dart +++ b/lib/presentaition/home_page/home_page.dart @@ -8,6 +8,7 @@ import 'package:testlab/presentaition/home_page/bloc/bloc.dart'; import 'package:testlab/presentaition/home_page/bloc/events.dart'; import 'package:testlab/presentaition/home_page/bloc/state.dart'; import 'package:testlab/domain/models/card.dart'; +import '../../data/repositories/repository.dart'; import '../common/svg_objects.dart'; import '../like_bloc/like_bloc.dart'; import '../like_bloc/like_event.dart'; @@ -58,7 +59,6 @@ class Body extends StatefulWidget { class BodyState extends State { final searchController = TextEditingController(); - final scrollController = ScrollController(); @override void initState() { @@ -67,27 +67,12 @@ class BodyState extends State { context.read().add(const HomeLoadDataEvent()); context.read().add(const LoadLikesEvent()); }); - - scrollController.addListener(_onNextPageListener); super.initState(); } - void _onNextPageListener() { - if (scrollController.offset > scrollController.position.maxScrollExtent) { - final bloc = context.read(); - if (!bloc.state.isPaginationLoading) { - bloc.add(HomeLoadDataEvent( - search: searchController.text, - nextPage: bloc.state.data?.nextPage, - )); - } - } - } - @override void dispose() { searchController.dispose(); - scrollController.dispose(); super.dispose(); } @@ -129,7 +114,7 @@ class BodyState extends State { CupertinoIcons.clear, color: Colors.white, ), - placeholder: 'Search...', + placeholder: context.locale.search, placeholderStyle: const TextStyle( color: Colors.white54, ), @@ -167,37 +152,51 @@ class BodyState extends State { return Expanded( child: RefreshIndicator( onRefresh: _onRefresh, - child: ListView.builder( - controller: scrollController, - padding: EdgeInsets.zero, - itemCount: state.data?.data?.length ?? 0, - itemBuilder: (context, index) { - final data = state.data?.data?[index]; - return data != null - ? _Card.fromData( - data, - onLike: _onLike, - isLiked: likeState.likedIds?.contains(data.id) == true, - onTap: () => _navToDetails(context, data), - ) - : const SizedBox.shrink(); - }, - ), + child: Stack( + children: [ + ListView.builder( + padding: EdgeInsets.zero, + itemCount: state.data?.data?.length ?? 0, + itemBuilder: (context, index) { + final data = state.data?.data?[index]; + return data != null + ? _Card.fromData( + data, + onDelete: _onDelete, + onLike: _onLike, + isLiked: likeState.likedIds?.contains(data.id) == true, + onTap: () => _navToDetails(context, data), + ) + : const SizedBox.shrink(); + }, + ), + Positioned( + bottom: 16, + right: 16, + child: FloatingActionButton( + onPressed: () { + _showAddTaskDialog(context); + }, + tooltip: 'Добавить задачу', + child: Icon(Icons.add), + ), + ), + ] + ) ), ); }, ), ), - BlocBuilder( - builder: (context, state) => state.isPaginationLoading - ? const CircularProgressIndicator() - : const SizedBox.shrink(), - ), ], ), ); } + + + + Future _onRefresh() { context.read().add(HomeLoadDataEvent(search: searchController.text)); return Future.value(null); @@ -214,7 +213,7 @@ class BodyState extends State { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( - '$title ${isLiked ? context.locale.liked : context.locale.disliked}', + '$title ${isLiked ? context.locale.complete : context.locale.uncomplete}', style: const TextStyle( color: Colors.white, fontSize: 18, @@ -227,10 +226,142 @@ class BodyState extends State { }); } + void _showDeleteBar(BuildContext context, String title) { + WidgetsBinding.instance.addPostFrameCallback((_) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + '$title ${context.locale.delete}', + style: const TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + backgroundColor: Colors.black, + duration: const Duration(seconds: 1), + )); + }); + } + + final repository repo = new repository(); + + + + Future _showAddTaskDialog(BuildContext context) async { + + final TextEditingController _taskNameController = TextEditingController(); + final TextEditingController _taskDescriptionController = TextEditingController(); + String? selectedImageUrl; + + List imageUrls = [ + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtsv2O-lLpxro9HH9CUejcymOOnGdQJwjasg&s', + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT--ZMDGsa_8y9r9u0RjAn576ajsVVfsOIcDA&s', + 'https://img-webcalypt.ru/storage/memes/YhGTdxW7HnbmhqAd37XjsMCTj1fHUW7AADagYMDbmyU9VBEhDBbq4d3XNGDWo34FibwtjyeVsyxudpzeViSmHdJ7e6C50tLbZnkZZAP81AV7aM0R8VSi4YEnqgcZ1EtE-md.jpeg', + ]; + + + + return showDialog( + context: context, + barrierDismissible: false, // Разрешить закрытие диалога по нажатию вне его + builder: (BuildContext context) { + return AlertDialog( + title: Text(context.locale.addtask), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: _taskNameController, + decoration: InputDecoration(hintText: context.locale.nameplaceholder), + ), + SizedBox(height: 16.0), + TextField( + controller: _taskDescriptionController, + decoration: InputDecoration(hintText: context.locale.descriptionplaceholder), + maxLines: 5, + minLines: 1, + ), + SizedBox(height: 16.0), + if (selectedImageUrl != null) + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Image.network( + selectedImageUrl!, + width: 70, + height: 70, + fit: BoxFit.cover, + ), + ), + SizedBox(height: 16.0), + DropdownButton( + hint: Text(context.locale.imageplaceholder), + value: selectedImageUrl, + isExpanded: true, + items: imageUrls.map((String url) { + return DropdownMenuItem( + value: url, + child: Row( + children: [ + Image.network(url, width: 50, height: 50), + SizedBox(width: 10), + Expanded(child: Text(url, overflow: TextOverflow.ellipsis)), + ], + ), + ); + }).toList(), + onChanged: (String? value) { + setState(() { + selectedImageUrl = value; + }); + }, + ), + + ], + ), + actions: [ + TextButton( + child: Text(context.locale.cancel), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text(context.locale.addbutton), + onPressed: () async { + await repo.addTask( + _taskNameController.text, + _taskDescriptionController.text, + selectedImageUrl + ); + Navigator.of(context).pop(); + _onRefresh(); + }, + ), + ], + ); + }, + ); + } + void _onLike(String? id, String title, bool isLiked) { if (id != null) { context.read().add(ChangeLikeEvent(id)); _showSnackBar(context, title, !isLiked); } } + + Future _onDelete(String? id, String title) async { + if (id != null) { + try { + int taskId = int.parse(id); + await repo.deleteTask(taskId); + _onRefresh(); + _showDeleteBar(context, title); + } catch (e) { + print("Ошибка преобразования id в int: $e"); + } + } + } + + } diff --git a/local.properties b/local.properties new file mode 100644 index 0000000..0781896 --- /dev/null +++ b/local.properties @@ -0,0 +1,8 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Mon Dec 09 15:56:48 GMT+04:00 2024 +sdk.dir=C\:\\Users\\Admin\\AppData\\Local\\Android\\Sdk diff --git a/makefile b/makefile index 982f849..d1b1b11 100644 --- a/makefile +++ b/makefile @@ -12,4 +12,7 @@ format: res: fgen --output lib/components/resources.g.dart --no-watch --no-preview; \ - make format \ No newline at end of file + make format + +loc: + flutter gen l10n \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 02af619..3baa7de 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -71,7 +71,6 @@ dev_dependencies: flutter_icons: android: "ic_launcher" - ios: true image_path: "assets/launcher.jpg" min_sdk_android: 21