forked from eatvio/eatvio_app
fixed layout of diets feed and added text styles
This commit is contained in:
4
assets/icons/eye2.svg
Normal file
4
assets/icons/eye2.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="10" viewBox="0 0 16 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.21875 0.253125C4.6625 0.509375 2.32188 1.875 0.4125 4.22813C0.028125 4.7 0 4.75625 0 5.00938C0 5.24687 0.046875 5.32812 0.48125 5.85625C2.56562 8.39062 5.22813 9.78125 8 9.78125C10.8063 9.78125 13.4781 8.36875 15.5875 5.77187C15.9719 5.3 16 5.24375 16 4.99062C16 4.75312 15.9531 4.67188 15.5188 4.14375C13.4156 1.58437 10.7312 0.196875 7.94063 0.221875C7.69063 0.224999 7.36562 0.2375 7.21875 0.253125ZM8.70625 1.73125C9.80937 1.96875 10.7344 2.77812 11.1406 3.85625C11.2875 4.24687 11.325 4.475 11.3219 5.01562C11.3219 5.45625 11.3125 5.55312 11.2406 5.81875C10.925 7.00312 10.0031 7.925 8.81875 8.24063C8.55313 8.3125 8.45625 8.32187 8.01562 8.32187C7.475 8.325 7.24688 8.2875 6.85625 8.14062C5.77813 7.73438 4.98438 6.825 4.72813 5.70625C4.64687 5.35313 4.65625 4.59062 4.74375 4.24062C5.07812 2.90937 6.09063 1.95937 7.45 1.7C7.72813 1.64687 8.4 1.6625 8.70625 1.73125Z" fill="#A3A3A3"/>
|
||||
<path d="M7.45312 3.2625C7.13125 3.36875 6.94688 3.48438 6.70312 3.73438C6.35 4.09063 6.1875 4.49062 6.1875 5C6.1875 5.525 6.35 5.91875 6.71562 6.28438C7.08125 6.65 7.475 6.8125 8 6.8125C8.50938 6.8125 8.90937 6.65 9.26562 6.29688C9.64688 5.92188 9.8125 5.53125 9.8125 5.00312C9.8125 4.83438 9.79063 4.62188 9.76562 4.52187C9.60625 3.90937 9.09063 3.39375 8.47813 3.23438C8.19688 3.1625 7.71875 3.175 7.45312 3.2625Z" fill="#A3A3A3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
3
assets/icons/filter2.svg
Normal file
3
assets/icons/filter2.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="25" height="17" viewBox="0 0 25 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.2083 16.25C10.8424 16.25 10.5356 16.1262 10.288 15.8786C10.0405 15.6311 9.91667 15.3243 9.91667 14.9583C9.91667 14.5924 10.0405 14.2856 10.288 14.038C10.5356 13.7905 10.8424 13.6667 11.2083 13.6667H13.7917C14.1576 13.6667 14.4644 13.7905 14.712 14.038C14.9595 14.2856 15.0833 14.5924 15.0833 14.9583C15.0833 15.3243 14.9595 15.6311 14.712 15.8786C14.4644 16.1262 14.1576 16.25 13.7917 16.25H11.2083ZM6.04167 9.79167C5.67569 9.79167 5.36892 9.66788 5.12135 9.42031C4.87378 9.17274 4.75 8.86597 4.75 8.5C4.75 8.13403 4.87378 7.82726 5.12135 7.57969C5.36892 7.33212 5.67569 7.20833 6.04167 7.20833H18.9583C19.3243 7.20833 19.6311 7.33212 19.8786 7.57969C20.1262 7.82726 20.25 8.13403 20.25 8.5C20.25 8.86597 20.1262 9.17274 19.8786 9.42031C19.6311 9.66788 19.3243 9.79167 18.9583 9.79167H6.04167ZM2.16667 3.33333C1.80069 3.33333 1.49392 3.20955 1.24635 2.96198C0.998785 2.71441 0.875 2.40764 0.875 2.04167C0.875 1.67569 0.998785 1.36892 1.24635 1.12135C1.49392 0.873785 1.80069 0.75 2.16667 0.75H22.8333C23.1993 0.75 23.5061 0.873785 23.7536 1.12135C24.0012 1.36892 24.125 1.67569 24.125 2.04167C24.125 2.40764 24.0012 2.71441 23.7536 2.96198C23.5061 3.20955 23.1993 3.33333 22.8333 3.33333H2.16667Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
3
assets/icons/repost.svg
Normal file
3
assets/icons/repost.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="13" viewBox="0 0 16 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.63752 0.25246C8.57688 0.283273 8.49841 0.334627 8.4663 0.368864C8.32005 0.526351 8.30935 0.635907 8.30579 2.08753V3.48094L8.1203 3.49806C8.01685 3.50833 7.73863 3.5323 7.5032 3.55284C5.38794 3.74799 3.56518 4.50803 2.29531 5.72684C1.13959 6.8361 0.426183 8.31853 0.133685 10.2118C0.0516433 10.7562 -0.0268316 11.9339 0.00883882 12.153C0.0552104 12.4406 0.279934 12.6255 0.583133 12.6255C0.836393 12.6255 0.957673 12.5501 1.21093 12.2386C1.54267 11.8278 2.20971 11.2047 2.59851 10.941C3.83628 10.0988 5.03837 9.80439 7.51033 9.72907L8.30222 9.7051L8.31292 11.1567C8.32362 12.7624 8.32005 12.7384 8.55904 12.9028C8.72313 13.0158 9.01563 13.0329 9.17614 12.9404C9.34023 12.848 15.5754 7.56876 15.7217 7.39758C16.0998 6.95593 16.0926 6.22327 15.7003 5.7782C15.5719 5.62756 9.33666 0.351746 9.19041 0.266155C9.04773 0.183988 8.79804 0.17714 8.63752 0.25246ZM12.2759 4.37109C13.9631 5.79874 14.8335 6.55879 14.8335 6.59987C14.8335 6.64438 13.9274 7.43181 12.1689 8.92109L9.50074 11.1807L9.48291 10.1125C9.46507 9.07173 9.46151 9.04434 9.38303 8.91767C9.33666 8.8492 9.22252 8.74649 9.13334 8.69513L8.96569 8.60269L7.89558 8.60612C5.96937 8.61639 4.87785 8.74649 3.7578 9.10597C2.97305 9.35589 2.13836 9.80096 1.5498 10.2803C1.41782 10.3864 1.30368 10.4686 1.29654 10.4617C1.28941 10.4549 1.30724 10.3214 1.33578 10.1604C1.8637 7.16477 3.70786 5.35367 6.80763 4.78877C7.31415 4.69976 7.75289 4.65182 8.41993 4.61759C8.95499 4.59362 8.99066 4.58678 9.14761 4.49091C9.25819 4.42587 9.34736 4.33685 9.40087 4.24099C9.48291 4.09377 9.48291 4.07323 9.48291 3.04272V1.99851L9.60062 2.10464C9.66126 2.15942 10.8669 3.18309 12.2759 4.37109Z" fill="#6D6D6D"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -147,9 +147,14 @@ class AppRouter {
|
||||
GoRoute(
|
||||
path: '/about-diet-screen',
|
||||
name: 'aboutDietScreen',
|
||||
builder: (context, state) => AboutDietScreen(
|
||||
diet: state.extra as Diet,
|
||||
),
|
||||
builder: (context, state) {
|
||||
final data = state.extra as Map<String, dynamic>;
|
||||
return AboutDietScreen(
|
||||
diet: data['diet'] as Diet,
|
||||
index: data['index'] as int,
|
||||
navigateToComments: data['navigateToComments'] as bool,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/blog-post-create-screen',
|
||||
|
||||
105
lib/core/data/diet/repositories/diet_repository.dart
Normal file
105
lib/core/data/diet/repositories/diet_repository.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:eatvio_app/core/data/diet/services/diet_service.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class DietRepository {
|
||||
DietRepository({required this.dietsService});
|
||||
final DietService dietsService;
|
||||
|
||||
final _dietLikeStateStreamController = StreamController<DietLikesState>.broadcast();
|
||||
final _dietFavoriteStateStreamController = StreamController<DietFavoriteState>.broadcast();
|
||||
final _dietCommentsStateStreamController = StreamController<DietCommentsState>.broadcast();
|
||||
Stream get dietLikeState => _dietLikeStateStreamController.stream;
|
||||
Stream get dietFavoriteState => _dietFavoriteStateStreamController.stream;
|
||||
Stream get dietCommentsState => _dietCommentsStateStreamController.stream;
|
||||
|
||||
Future<void> likeDiet(int id) async {
|
||||
try {
|
||||
await dietsService.likeDiet(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Diet> getDiet(int id) async {
|
||||
try {
|
||||
final diet = await dietsService.getDiet(id: id);
|
||||
return diet;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addToFavorite(int id) async {
|
||||
try {
|
||||
await dietsService.addToFavorite(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> removeFromFavorite(int id) async {
|
||||
try {
|
||||
await dietsService.removeFromFavorite(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
void emitLikesStateToFeed(DietLikesState state) => _dietLikeStateStreamController.add(state);
|
||||
void emitFavoriteStateToFeed(DietFavoriteState state) => _dietFavoriteStateStreamController.add(state);
|
||||
void emitCommentsStateToFeed(DietCommentsState state) => _dietCommentsStateStreamController.add(state);
|
||||
}
|
||||
|
||||
class DietLikesState extends Equatable {
|
||||
final bool wasLikedByMe;
|
||||
final int totalLikes;
|
||||
final int index;
|
||||
|
||||
DietLikesState({
|
||||
required this.wasLikedByMe,
|
||||
required this.totalLikes,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
wasLikedByMe,
|
||||
totalLikes,
|
||||
index,
|
||||
];
|
||||
}
|
||||
|
||||
class DietFavoriteState extends Equatable {
|
||||
final bool isFavorite;
|
||||
final int index;
|
||||
|
||||
DietFavoriteState({
|
||||
required this.isFavorite,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
isFavorite,
|
||||
index,
|
||||
];
|
||||
}
|
||||
|
||||
class DietCommentsState extends Equatable {
|
||||
final int index;
|
||||
final int totalComments;
|
||||
|
||||
DietCommentsState({
|
||||
required this.index,
|
||||
required this.totalComments,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
index,
|
||||
totalComments,
|
||||
];
|
||||
}
|
||||
@@ -2,11 +2,11 @@ import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
part 'diets_service.g.dart';
|
||||
part 'diet_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class DietsService {
|
||||
factory DietsService(Dio dio, {String baseUrl}) = _DietsService;
|
||||
abstract class DietService {
|
||||
factory DietService(Dio dio, {String baseUrl}) = _DietService;
|
||||
|
||||
@POST('/api/diets/{id}/like')
|
||||
Future<void> likeDiet({
|
||||
@@ -23,14 +23,8 @@ abstract class DietsService {
|
||||
@Path() required int id,
|
||||
});
|
||||
|
||||
@POST('/api/diets/{id}/unliked')
|
||||
Future<void> unlikeDiet({
|
||||
@Path() required int id,
|
||||
});
|
||||
|
||||
@GET('/api/diets/show/{id}')
|
||||
Future<Diet> getDiet({
|
||||
@Path() required int id,
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'diets_service.dart';
|
||||
part of 'diet_service.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RetrofitGenerator
|
||||
@@ -8,8 +8,8 @@ part of 'diets_service.dart';
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
|
||||
|
||||
class _DietsService implements DietsService {
|
||||
_DietsService(
|
||||
class _DietService implements DietService {
|
||||
_DietService(
|
||||
this._dio, {
|
||||
this.baseUrl,
|
||||
this.errorLogger,
|
||||
@@ -96,31 +96,6 @@ class _DietsService implements DietsService {
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> unlikeDiet({required int id}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(Options(
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/diets/${id}/unliked',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(
|
||||
baseUrl: _combineBaseUrls(
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Diet> getDiet({required int id}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
44
lib/core/widgets/bookmark_button.dart
Normal file
44
lib/core/widgets/bookmark_button.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BookmarkButton extends StatelessWidget {
|
||||
const BookmarkButton({
|
||||
super.key,
|
||||
required this.onTap,
|
||||
required this.color,
|
||||
required this.isFavorite,
|
||||
required this.width,
|
||||
required this.height,
|
||||
required this.size,
|
||||
this.shape,
|
||||
this.borderRadius,
|
||||
});
|
||||
final void Function() onTap;
|
||||
final Color color;
|
||||
final BoxShape? shape;
|
||||
final bool isFavorite;
|
||||
final BorderRadiusGeometry? borderRadius;
|
||||
final double width;
|
||||
final double height;
|
||||
final double size;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: shape ?? BoxShape.rectangle,
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: Icon(
|
||||
isFavorite ? Icons.bookmark : Icons.bookmark_border_rounded,
|
||||
color: appTheme.black,
|
||||
size: size,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
66
lib/core/widgets/diet_info_row.dart
Normal file
66
lib/core/widgets/diet_info_row.dart
Normal file
@@ -0,0 +1,66 @@
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/type_badges.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class DietInfoRow extends StatelessWidget {
|
||||
const DietInfoRow({super.key, required this.diet, this.itemsBackgroundColor, this.disableDescriptionOfTypes = false});
|
||||
final Color? itemsBackgroundColor;
|
||||
final Diet diet;
|
||||
final bool disableDescriptionOfTypes;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
InfoBouble(
|
||||
backgroundColor: itemsBackgroundColor,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/time2.svg',
|
||||
width: 13.3,
|
||||
height: 13.3,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
diet.duration.toString() + ' ' + getDayForm(diet.duration, s),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
InfoBouble(
|
||||
backgroundColor: itemsBackgroundColor,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/people.svg',
|
||||
width: 13.3,
|
||||
height: 13.3,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'80 человек прошли',
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
InfoBouble(
|
||||
backgroundColor: itemsBackgroundColor,
|
||||
children: [
|
||||
TypeBadges(type: diet.type, disableDescriptionOfTypes: disableDescriptionOfTypes),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
51
lib/core/widgets/feed_icon_button.dart
Normal file
51
lib/core/widgets/feed_icon_button.dart
Normal file
@@ -0,0 +1,51 @@
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class FeedIconButton extends StatelessWidget {
|
||||
const FeedIconButton({super.key, this.icon, this.svgIcon, this.text, this.onTap, this.iconColor, this.backgroundColor, this.textColor});
|
||||
final IconData? icon;
|
||||
final SvgPicture? svgIcon;
|
||||
final String? text;
|
||||
final Function()? onTap;
|
||||
final Color? iconColor;
|
||||
final Color? backgroundColor;
|
||||
final Color? textColor;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: onTap ?? () {},
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor ?? appTheme.gray100,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 32,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (svgIcon != null) svgIcon!,
|
||||
if (icon != null)
|
||||
Icon(
|
||||
icon,
|
||||
size: 16,
|
||||
color: iconColor ?? appTheme.gray600,
|
||||
),
|
||||
if (text != null) ...[
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
text!,
|
||||
style: TextStyles.textSMedium.copyWith(
|
||||
color: textColor ?? appTheme.gray600,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
Text(
|
||||
state.chatRoom.users['to_chat_user']!.name,
|
||||
style: CustomTextStyles.titleSmallBold.copyWith(
|
||||
color: PrimaryColors().blueGray800,
|
||||
color: PrimaryColors().black,
|
||||
),
|
||||
),
|
||||
AnimatedCrossFade(
|
||||
|
||||
@@ -2,24 +2,27 @@ import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_state.dart';
|
||||
import 'package:eatvio_app/features/diets/repositories/diets_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
AboutDietCubit({required this.dietsRepository}) : super(AboutDietState.initial());
|
||||
final DietsRepository dietsRepository;
|
||||
final DietRepository dietsRepository;
|
||||
|
||||
Future<void> getDiet(int id) async {
|
||||
Future<void> getDiet(int id, {int? index}) async {
|
||||
try {
|
||||
final diet = await dietsRepository.getDiet(id);
|
||||
if (index != null) {
|
||||
dietsRepository.emitCommentsStateToFeed(DietCommentsState(index: index, totalComments: diet.totalComments));
|
||||
}
|
||||
emit(AboutDietState.loaded(diet));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getDietWithLoading(int id) async{
|
||||
Future<void> getDietWithLoading(int id) async {
|
||||
try {
|
||||
emit(AboutDietState.loading());
|
||||
final diet = await dietsRepository.getDiet(id);
|
||||
@@ -29,7 +32,7 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> likeDiet(int id) async {
|
||||
Future<void> likeDiet(int id, int dietIndexInFeed) async {
|
||||
if (state is! DietStateLoaded) return;
|
||||
|
||||
final currentDiet = (state as DietStateLoaded).diet;
|
||||
@@ -39,12 +42,15 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
totalLikes: currentDiet.totalLikes - 1,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
dietsRepository.emitLikesStateToFeed(DietLikesState(wasLikedByMe: updatedDiet.wasLikedByMe, totalLikes: updatedDiet.totalLikes, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(updatedDiet));
|
||||
} else {
|
||||
final updatedDiet = currentDiet.copyWith(
|
||||
totalLikes: currentDiet.totalLikes + 1,
|
||||
wasLikedByMe: true,
|
||||
);
|
||||
|
||||
dietsRepository.emitLikesStateToFeed(DietLikesState(wasLikedByMe: updatedDiet.wasLikedByMe, totalLikes: updatedDiet.totalLikes, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(updatedDiet));
|
||||
}
|
||||
|
||||
@@ -57,13 +63,15 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
await getDiet(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
dietsRepository
|
||||
.emitLikesStateToFeed(DietLikesState(wasLikedByMe: currentDiet.wasLikedByMe, totalLikes: currentDiet.totalLikes, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(currentDiet));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addToFavorite(int id) async {
|
||||
Future<void> addToFavorite(int id, int dietIndexInFeed) async {
|
||||
if (state is! DietStateLoaded) return;
|
||||
|
||||
final currentDiet = (state as DietStateLoaded).diet;
|
||||
@@ -71,6 +79,7 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
final updatedDiet = currentDiet.copyWith(
|
||||
isFavorite: true,
|
||||
);
|
||||
dietsRepository.emitFavoriteStateToFeed(DietFavoriteState(isFavorite: updatedDiet.isFavorite, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(updatedDiet));
|
||||
|
||||
EasyDebounce.debounce(
|
||||
@@ -79,16 +88,19 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
() async {
|
||||
try {
|
||||
await dietsRepository.addToFavorite(id);
|
||||
await getDiet(id);
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
await getDiet(id);
|
||||
});
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
dietsRepository.emitFavoriteStateToFeed(DietFavoriteState(isFavorite: currentDiet.isFavorite, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(currentDiet));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeFromFavorite(int id) async {
|
||||
Future<void> removeFromFavorite(int id, int dietIndexInFeed) async {
|
||||
if (state is! DietStateLoaded) return;
|
||||
|
||||
final currentDiet = (state as DietStateLoaded).diet;
|
||||
@@ -96,6 +108,7 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
final updatedDiet = currentDiet.copyWith(
|
||||
isFavorite: false,
|
||||
);
|
||||
dietsRepository.emitFavoriteStateToFeed(DietFavoriteState(isFavorite: updatedDiet.isFavorite, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(updatedDiet));
|
||||
|
||||
EasyDebounce.debounce(
|
||||
@@ -104,9 +117,12 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
() async {
|
||||
try {
|
||||
await dietsRepository.removeFromFavorite(id);
|
||||
await getDiet(id);
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
await getDiet(id);
|
||||
});
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
dietsRepository.emitFavoriteStateToFeed(DietFavoriteState(isFavorite: currentDiet.isFavorite, index: dietIndexInFeed));
|
||||
emit(AboutDietState.loaded(currentDiet));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,7 +4,9 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/core/widgets/diet_info_row.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_state.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
|
||||
@@ -14,13 +16,13 @@ import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart'
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/more_options.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/start_diet_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/type_badges.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/locator_service.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -30,9 +32,11 @@ import 'package:rive/rive.dart' hide LinearGradient;
|
||||
|
||||
class AboutDietScreen extends StatefulWidget {
|
||||
final Diet diet;
|
||||
final int index;
|
||||
final bool navigateToComments;
|
||||
late final List<int> selectedIndexes;
|
||||
|
||||
AboutDietScreen({super.key, required this.diet}) {
|
||||
AboutDietScreen({super.key, required this.diet, required this.index, required this.navigateToComments}) {
|
||||
selectedIndexes = List.generate(diet.dailySchedule.length, (_) => 0);
|
||||
}
|
||||
|
||||
@@ -47,7 +51,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
final textEditingController = TextEditingController();
|
||||
bool isMoreOptionsVisible = false;
|
||||
|
||||
bool _jumped = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -60,6 +64,13 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
void _scrollToBottom() {
|
||||
_jumped = true;
|
||||
scrollController.jumpTo(
|
||||
scrollController.position.maxScrollExtent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
@@ -83,440 +94,389 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
builder: (BuildContext context, CommentsState state) {
|
||||
return BlocBuilder<AboutDietCubit, AboutDietState>(
|
||||
builder: (context, dietState) {
|
||||
return dietState is DietStateLoaded
|
||||
? Scaffold(
|
||||
backgroundColor: appTheme.gray100,
|
||||
resizeToAvoidBottomInset: true,
|
||||
bottomSheet: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
if (dietState is DietStateLoaded) {
|
||||
Future.delayed(Duration(milliseconds: 500), () {
|
||||
if (widget.navigateToComments && !_jumped) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
});
|
||||
return Scaffold(
|
||||
backgroundColor: appTheme.gray100,
|
||||
resizeToAvoidBottomInset: true,
|
||||
bottomSheet: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
child: FloatingActionButton.extended(
|
||||
heroTag: 'nextButtonRegistration',
|
||||
highlightElevation: 0,
|
||||
elevation: 0,
|
||||
focusElevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
backgroundColor: appTheme.greenA700,
|
||||
onPressed: () {
|
||||
showModalBottomSheet(context: context, builder: (context) => StartDietBottomSheet());
|
||||
},
|
||||
label: Text(
|
||||
s.startDiet,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: appTheme.whiteA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
child: FloatingActionButton.extended(
|
||||
heroTag: 'nextButtonRegistration',
|
||||
highlightElevation: 0,
|
||||
elevation: 0,
|
||||
focusElevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (dietState.diet.isFavorite) {
|
||||
dietsCubit.removeFromFavorite(widget.diet.id);
|
||||
} else {
|
||||
dietsCubit.addToFavorite(widget.diet.id);
|
||||
}
|
||||
backgroundColor: appTheme.greenA700,
|
||||
onPressed: () {
|
||||
showModalBottomSheet(context: context, builder: (context) => StartDietBottomSheet());
|
||||
},
|
||||
child: Container(
|
||||
width: 52,
|
||||
height: 52,
|
||||
decoration: BoxDecoration(color: appTheme.gray50, shape: BoxShape.circle),
|
||||
child: Icon(
|
||||
dietState.diet.isFavorite ? Icons.bookmark : Icons.bookmark_border_rounded,
|
||||
color: appTheme.blueGray800,
|
||||
size: 24,
|
||||
),
|
||||
label: Text(
|
||||
s.startDiet,
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (replyId != null)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
replyId = null;
|
||||
textEditingController.clear();
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.close_rounded,
|
||||
size: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (replyId != null) SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
child: TextFormField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: textEditingController,
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
height: 1,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
hintText: s.comment.capitalize(),
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
color: Color(0xFFAEAEB2),
|
||||
),
|
||||
filled: true,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (textEditingController.text.length > 2) {
|
||||
commentsCubit.sendComment(
|
||||
id: widget.diet.id.toString(),
|
||||
commentText: textEditingController.text,
|
||||
parentCommentId: replyId,
|
||||
commentSourceType: CommentSourceType.diet,
|
||||
);
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
textEditingController.clear();
|
||||
replyId = null;
|
||||
});
|
||||
dietsCubit.getDiet(widget.diet.id);
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: textEditingController.text.length > 2 ? appTheme.blueA400 : appTheme.gray50,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.send_rounded,
|
||||
size: 18,
|
||||
color: textEditingController.text.length > 2 ? appTheme.whiteA700 : appTheme.blueGray800,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
SizedBox(width: 8),
|
||||
BookmarkButton(
|
||||
isFavorite: dietState.diet.isFavorite,
|
||||
onTap: () {
|
||||
if (dietState.diet.isFavorite) {
|
||||
dietsCubit.removeFromFavorite(widget.diet.id, widget.index);
|
||||
} else {
|
||||
dietsCubit.addToFavorite(widget.diet.id, widget.index);
|
||||
}
|
||||
},
|
||||
width: 52,
|
||||
height: 52,
|
||||
size: 24,
|
||||
shape: BoxShape.circle,
|
||||
color: appTheme.gray50,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.diet.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(id: widget.diet.id),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (replyId != null)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
replyId = null;
|
||||
textEditingController.clear();
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.close_rounded,
|
||||
size: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (replyId != null) SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
child: TextFormField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: textEditingController,
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
hintText: s.comment.capitalize(),
|
||||
hintStyle: TextStyles.textMMedium.copyWith(color: appTheme.lightGray600),
|
||||
filled: true,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (textEditingController.text.length > 2) {
|
||||
commentsCubit.sendComment(
|
||||
id: widget.diet.id.toString(),
|
||||
commentText: textEditingController.text,
|
||||
parentCommentId: replyId,
|
||||
commentSourceType: CommentSourceType.diet,
|
||||
);
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
textEditingController.clear();
|
||||
replyId = null;
|
||||
});
|
||||
Future.delayed(Duration(milliseconds: 500), () {
|
||||
dietsCubit.getDiet(widget.diet.id, index: widget.index);
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
}
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: textEditingController.text.length > 2 ? appTheme.blueA400 : appTheme.gray50,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.send_rounded,
|
||||
size: 18,
|
||||
color: textEditingController.text.length > 2 ? appTheme.whiteA700 : appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
padding: EdgeInsets.only(bottom: 160),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
MainBackgroundBouble(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
),
|
||||
),
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.diet.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(id: widget.diet.id),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
padding: EdgeInsets.only(bottom: 160),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
MainBackgroundBouble(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
Stack(children: [
|
||||
CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.diet.image,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset('assets/icons/eye.svg', width: 18, height: 12),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
dietState.diet.totalViews.toString(),
|
||||
style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
dietsCubit.likeDiet(widget.diet.id);
|
||||
},
|
||||
child: InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/heart.svg',
|
||||
width: 14,
|
||||
height: 12,
|
||||
colorFilter: dietState.diet.wasLikedByMe ? ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn) : null,
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
dietState.diet.totalLikes.toString(),
|
||||
style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset('assets/icons/comment2.svg', width: 13, height: 12),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
dietState.diet.totalComments.toString(),
|
||||
style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
s.about_diet,
|
||||
style: TextStyle(color: appTheme.blueGray800, fontSize: 20, fontWeight: FontWeight.w600),
|
||||
),
|
||||
CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.diet.image,
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/time2.svg',
|
||||
width: 13.3,
|
||||
height: 13.3,
|
||||
SvgPicture.asset('assets/icons/eye.svg', width: 18, height: 12),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
dietState.diet.totalViews.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(widget.diet.duration.toString() + ' ' + getDayForm(widget.diet.duration, s),
|
||||
style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500),),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
dietsCubit.likeDiet(widget.diet.id, widget.index);
|
||||
},
|
||||
child: InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/heart.svg',
|
||||
width: 14,
|
||||
height: 12,
|
||||
colorFilter: dietState.diet.wasLikedByMe ? ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn) : null,
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
dietState.diet.totalLikes.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/people.svg',
|
||||
width: 13.3,
|
||||
height: 13.3,
|
||||
SvgPicture.asset('assets/icons/comment2.svg', width: 13, height: 12),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
dietState.diet.totalComments.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text('80 человек прошли(статика, ещё нет бека)',
|
||||
style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500),),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
InfoBouble(
|
||||
children: [
|
||||
TypeBadges(type: widget.diet.type),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ExpandableText(
|
||||
text: widget.diet.details,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: AuthorCard(
|
||||
author: widget.diet.author,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
MainBackgroundBouble(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Center(
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
s.diet_plan + '(${widget.diet.duration.toString()} ' + getDayForm(widget.diet.duration, s) + ')',
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
s.about_diet,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
DietInfoRow(diet: widget.diet),
|
||||
ExpandableText(
|
||||
text: widget.diet.details,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: AuthorCard(
|
||||
author: widget.diet.author,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
MainBackgroundBouble(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
s.diet_plan + '(${widget.diet.duration.toString()} ' + getDayForm(widget.diet.duration, s) + ')',
|
||||
style: TextStyles.headingXLSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
return _dayOfPlan(widget.diet.dailySchedule[index], index, s);
|
||||
},
|
||||
itemCount: widget.diet.dailySchedule.length,
|
||||
),
|
||||
MainBackgroundBouble(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
dietState.diet.totalComments.toString() + ' ' + getCommentForm(widget.diet.totalComments, s),
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.gray500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),),
|
||||
SizedBox(height: 8),
|
||||
ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
return _dayOfPlan(widget.diet.dailySchedule[index], index, s);
|
||||
},
|
||||
itemCount: widget.diet.dailySchedule.length,
|
||||
),
|
||||
MainBackgroundBouble(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: Column(children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
dietState.diet.totalComments.toString() + ' ' + getCommentForm(widget.diet.totalComments, s),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.gray500,
|
||||
fontWeight: FontWeight.w400,
|
||||
SizedBox(height: 16),
|
||||
if (state is CommentsStateLoading)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: SizedBox(
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: RiveAnimation.asset(
|
||||
'assets/rive_animations/loading.riv',
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
if (state is CommentsStateLoading)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: SizedBox(
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: RiveAnimation.asset(
|
||||
'assets/rive_animations/loading.riv',
|
||||
),
|
||||
),
|
||||
),
|
||||
if (state is CommentsStateLoaded)
|
||||
CommentsWidget(
|
||||
id: widget.diet.id.toString(),
|
||||
commentSourceType: CommentSourceType.diet,
|
||||
comment: state.comment,
|
||||
replyId: replyId,
|
||||
),
|
||||
],),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
: Scaffold(
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: RiveAnimation.asset(
|
||||
'assets/rive_animations/loading.riv',
|
||||
if (state is CommentsStateLoaded)
|
||||
CommentsWidget(
|
||||
id: widget.diet.id.toString(),
|
||||
commentSourceType: CommentSourceType.diet,
|
||||
comment: state.comment,
|
||||
replyId: replyId,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: SizedBox(
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: RiveAnimation.asset(
|
||||
'assets/rive_animations/loading.riv',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -537,10 +497,8 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
label: Text((index + 1).toString()),
|
||||
labelStyle: TextStyle(
|
||||
labelStyle: TextStyles.textXSSemibold.copyWith(
|
||||
color: index == widget.selectedIndexes[dayNumber] ? Colors.white : appTheme.gray600,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 12,
|
||||
),
|
||||
selected: widget.selectedIndexes[dayNumber] == index,
|
||||
backgroundColor: appTheme.gray100,
|
||||
@@ -567,10 +525,8 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
children: [
|
||||
Text(
|
||||
s.day + ' ' + (dayNumber + 1).toString(),
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
style: TextStyles.headingXLSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
@@ -579,10 +535,8 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
),
|
||||
Text(
|
||||
s.meal,
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -618,21 +572,20 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
daily.name,
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.6,
|
||||
child: Text(
|
||||
daily.name,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
daily.quantity.toString() + ' ' + getLocalizedMeasurementUnits(s, daily.portion),
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
style: TextStyles.textMSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
@@ -36,18 +37,14 @@ class AuthorCard extends StatelessWidget {
|
||||
),
|
||||
subtitle: Text(
|
||||
author.authorName,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: appTheme.blueGray800,
|
||||
style: TextStyles.textLSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
s.diet_author,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF6D6F71),
|
||||
style: TextStyles.textSSemibold.copyWith(
|
||||
color: appTheme.gray,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -55,23 +52,23 @@ class AuthorCard extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
'Конслуьтант',
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
InfoBouble(radius: 12, backgroundColor: appTheme.whiteA700, children: [
|
||||
Text(
|
||||
'128-й в рейтинге',
|
||||
style: TextStyle(
|
||||
color: appTheme.blueA400,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
InfoBouble(
|
||||
radius: 12,
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
children: [
|
||||
Text(
|
||||
'128-й в рейтинге',
|
||||
style: TextStyles.textMMediumAuto.copyWith(
|
||||
color: appTheme.blueA400,
|
||||
),
|
||||
),
|
||||
),
|
||||
],),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
|
||||
class CalendarWidget extends StatefulWidget {
|
||||
@@ -10,7 +12,7 @@ class CalendarWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
CalendarFormat _calendarFormat = CalendarFormat.month;
|
||||
CalendarFormat _calendarFormat = CalendarFormat.week;
|
||||
DateTime _focusedDay = DateTime.now();
|
||||
DateTime? _selectedDay = DateTime.now();
|
||||
@override
|
||||
@@ -26,16 +28,25 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
locale: 'ru_RU',
|
||||
startingDayOfWeek: StartingDayOfWeek.monday,
|
||||
focusedDay: _focusedDay,
|
||||
rangeStartDay: _selectedDay,
|
||||
rangeEndDay: _selectedDay?.add(const Duration(days: 6)),
|
||||
calendarFormat: _calendarFormat,
|
||||
calendarBuilders: CalendarBuilders(
|
||||
headerTitleBuilder: (context, day) {
|
||||
final dateFormatter = DateFormat('MMMM', 'ru_RU');
|
||||
return Center(
|
||||
child: Text(
|
||||
'${dateFormatter.format(day).capitalize()}',
|
||||
style: TextStyle(color: appTheme.black, fontSize: 16, fontWeight: FontWeight.w400),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
headerStyle: HeaderStyle(
|
||||
titleCentered: true,
|
||||
formatButtonVisible: false,
|
||||
leftChevronVisible: false,
|
||||
rightChevronVisible: false,
|
||||
),
|
||||
rowHeight: 40,
|
||||
rowHeight: 64,
|
||||
selectedDayPredicate: (day) {
|
||||
return isSameDay(_selectedDay, day);
|
||||
},
|
||||
@@ -58,27 +69,36 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
||||
_focusedDay = focusedDay;
|
||||
},
|
||||
calendarStyle: CalendarStyle(
|
||||
weekendTextStyle: TextStyle(
|
||||
color: appTheme.gray,
|
||||
),
|
||||
defaultTextStyle: TextStyle(
|
||||
color: appTheme.gray,
|
||||
),
|
||||
weekendDecoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
color: appTheme.dividerColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
defaultDecoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
color: appTheme.dividerColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
selectedTextStyle: TextStyle(
|
||||
color: appTheme.whiteA700,
|
||||
),
|
||||
selectedDecoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
todayTextStyle: TextStyle(
|
||||
color: Colors.black,
|
||||
color: appTheme.gray,
|
||||
),
|
||||
todayDecoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: appTheme.blueA400,
|
||||
width: 2,
|
||||
),
|
||||
color: Colors.white,
|
||||
color: appTheme.dividerColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -15,32 +16,35 @@ class CpfcContainer extends StatelessWidget {
|
||||
return Container(
|
||||
color: appTheme.cardBackground,
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Column(
|
||||
children: [
|
||||
Text('$calories', style: TextStyle(color: appTheme.blueGray800, fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
Text(s.calories, style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text('$protein', style: TextStyle(color: appTheme.blueGray800, fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
Text(s.proteins, style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text('$fat', style: TextStyle(color: appTheme.blueGray800, fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
Text(s.fats, style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text('$carbohydrates', style: TextStyle(color: appTheme.blueGray800, fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
Text(s.carbohydrates, style: TextStyle(color: appTheme.blueGray800, fontSize: 12, fontWeight: FontWeight.w500)),
|
||||
],
|
||||
),
|
||||
],),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Text('$calories', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
|
||||
Text(s.calories, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text('$protein', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
|
||||
Text(s.proteins, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text('$fat', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
|
||||
Text(s.fats, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text('$carbohydrates', style: TextStyles.textMSemibold.copyWith(color: appTheme.black)),
|
||||
Text(s.carbohydrates, style: TextStyles.textXSSemibold.copyWith(color: appTheme.black)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
@@ -74,7 +75,7 @@ class _ExpandableTextState extends State<ExpandableText> {
|
||||
children: [
|
||||
Text(
|
||||
isExpanded ? s.hide : s.expand,
|
||||
style: TextStyle(color: appTheme.blueA400, fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.blueA400),
|
||||
),
|
||||
Transform.rotate(angle: isExpanded ? math.pi : 0, child: SvgPicture.asset('assets/icons/arrow_down.svg', width: 12, height: 12)),
|
||||
],
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -17,83 +18,80 @@ class MoreOptions extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return MainBackgroundBouble(
|
||||
enableShadow: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: baseUrl + '/ru/diet/' + id.toString()));
|
||||
showInfoToast(s.link_was_copied);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
s.copy_link,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: appTheme.blueGray800,
|
||||
),
|
||||
enableShadow: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: baseUrl + '/ru/diet/' + id.toString()));
|
||||
showInfoToast(s.link_was_copied);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
s.copy_link,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
|
||||
color: appTheme.black,
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/copy2.svg', width: 16, height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: CustomDivider(),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + id.toString(),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/copy2.svg', width: 16, height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: CustomDivider(),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + id.toString(),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
s.share,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: appTheme.blueGray800,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
s.share,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
|
||||
color: appTheme.black,
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/share2.svg', width: 16, height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/share2.svg', width: 16, height: 20),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: CustomDivider(),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.push('complainingScreen');
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
s.complain,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: appTheme.blueGray800,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: CustomDivider(),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.push('complainingScreen');
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
s.complain,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/complain.svg', width: 16, height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/complain.svg', width: 16, height: 20),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
width: 272,);
|
||||
),
|
||||
width: 272,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/calendar_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/widgets/custom_outlined_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -13,38 +15,45 @@ class StartDietBottomSheet extends StatelessWidget {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 5),
|
||||
SizedBox(height: 4),
|
||||
Container(
|
||||
height: 4,
|
||||
width: 40,
|
||||
decoration: BoxDecoration(color: appTheme.lightGrey, borderRadius: BorderRadius.circular(20)),
|
||||
decoration: BoxDecoration(color: appTheme.lightGray, borderRadius: BorderRadius.circular(20)),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Text(
|
||||
s.startDiet,
|
||||
style: TextStyles.headingXLSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 22),
|
||||
Text(s.startDiet,
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25.0),
|
||||
child: Text(s.choose_start_diet_date,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),),
|
||||
child: Text(
|
||||
s.choose_start_diet_date,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: CustomDivider(),
|
||||
),
|
||||
CalendarWidget(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 16, right: 16, top: 20, bottom: 25),
|
||||
padding: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 28),
|
||||
child: CustomOutlinedButton(
|
||||
height: 52,
|
||||
text: s.continue_,
|
||||
height: 60,
|
||||
text: s.startDiet,
|
||||
buttonTextStyle: TextStyles.textLSemibold.copyWith(
|
||||
color: appTheme.whiteA700,
|
||||
),
|
||||
buttonStyle: ButtonStyle(
|
||||
textStyle: WidgetStatePropertyAll(TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
),
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_portal/flutter_portal.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class TypeBadges extends StatefulWidget {
|
||||
const TypeBadges({super.key, required this.type});
|
||||
const TypeBadges({super.key, required this.type, required this.disableDescriptionOfTypes});
|
||||
|
||||
final DietType type;
|
||||
|
||||
final bool disableDescriptionOfTypes;
|
||||
@override
|
||||
State<TypeBadges> createState() => _TypeBadgesState();
|
||||
}
|
||||
@@ -23,48 +24,56 @@ class _TypeBadgesState extends State<TypeBadges> {
|
||||
final s = S.of(context);
|
||||
final List<(String, Widget)> badgeSource = [];
|
||||
if (widget.type.alko == true) {
|
||||
badgeSource.add((
|
||||
'assets/icons/cocktail.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/cocktail.svg',
|
||||
title: s.alko_type,
|
||||
description: s.alko_type_desc,
|
||||
)
|
||||
),);
|
||||
badgeSource.add(
|
||||
(
|
||||
'assets/icons/cocktail.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/cocktail.svg',
|
||||
title: s.alko_type,
|
||||
description: s.alko_type_desc,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
if (widget.type.veg == true) {
|
||||
badgeSource.add((
|
||||
'assets/icons/broccoli.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/broccoli.svg',
|
||||
title: s.vegan_type,
|
||||
description: s.vegan_type_desc,
|
||||
)
|
||||
),);
|
||||
badgeSource.add(
|
||||
(
|
||||
'assets/icons/broccoli.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/broccoli.svg',
|
||||
title: s.vegan_type,
|
||||
description: s.vegan_type_desc,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
if (widget.type.corb == true) {
|
||||
badgeSource.add((
|
||||
'assets/icons/bread.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/bread.svg',
|
||||
title: s.corb_type,
|
||||
description: s.corb_type_desc,
|
||||
)
|
||||
),);
|
||||
badgeSource.add(
|
||||
(
|
||||
'assets/icons/bread.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/bread.svg',
|
||||
title: s.corb_type,
|
||||
description: s.corb_type_desc,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
if (widget.type.meat == true) {
|
||||
badgeSource.add((
|
||||
'assets/icons/meat2.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/meat2.svg',
|
||||
title: s.meat_type,
|
||||
description: s.meat_type_desc,
|
||||
)
|
||||
),);
|
||||
badgeSource.add(
|
||||
(
|
||||
'assets/icons/meat2.svg',
|
||||
_InfoOverlayEntry(
|
||||
onClose: closeOverlay,
|
||||
assetPath: 'assets/icons/meat2.svg',
|
||||
title: s.meat_type,
|
||||
description: s.meat_type_desc,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
return Row(
|
||||
children: List.generate(
|
||||
@@ -81,19 +90,21 @@ class _TypeBadgesState extends State<TypeBadges> {
|
||||
),
|
||||
portalFollower: badgeSource[index].$2,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
for (int stateIndex = 0; stateIndex < overlaysVisibilityState.length; stateIndex++) {
|
||||
if (index != stateIndex) {
|
||||
setState(() {
|
||||
overlaysVisibilityState[stateIndex] = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
overlaysVisibilityState[stateIndex] = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
onTap: widget.disableDescriptionOfTypes
|
||||
? null
|
||||
: () {
|
||||
for (int stateIndex = 0; stateIndex < overlaysVisibilityState.length; stateIndex++) {
|
||||
if (index != stateIndex) {
|
||||
setState(() {
|
||||
overlaysVisibilityState[stateIndex] = false;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
overlaysVisibilityState[stateIndex] = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: index != badgeSource.length - 1 ? 8.0 : 0),
|
||||
child: SvgPicture.asset(
|
||||
@@ -152,22 +163,19 @@ class _InfoOverlayEntry extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
decoration: TextDecoration.none,
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
description,
|
||||
softWrap: true,
|
||||
style: TextStyle(
|
||||
style: TextStyles.textXSSemibold.copyWith(
|
||||
decoration: TextDecoration.none,
|
||||
color: appTheme.blueGray800,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: appTheme.black,
|
||||
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import 'package:eatvio_app/features/diets/services/diets_service.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
|
||||
class DietsRepository {
|
||||
DietsRepository({required this.dietsService});
|
||||
final DietsService dietsService;
|
||||
|
||||
Future<void> likeDiet(int id) async {
|
||||
try {
|
||||
await dietsService.likeDiet(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> unlikeDiet(int id) async {
|
||||
try {
|
||||
await dietsService.unlikeDiet(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Diet> getDiet(int id) async {
|
||||
try {
|
||||
final diet = await dietsService.getDiet(id: id);
|
||||
return diet;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addToFavorite(int id) async {
|
||||
try {
|
||||
await dietsService.addToFavorite(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> removeFromFavorite(int id) async {
|
||||
try {
|
||||
await dietsService.removeFromFavorite(id: id);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/core/models/pagination_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
@@ -36,6 +37,7 @@ class Diet with _$Diet {
|
||||
}) = _Diet;
|
||||
|
||||
factory Diet.fromJson(Map<String, dynamic> json) => _$DietFromJson(json);
|
||||
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
||||
@@ -1,15 +1,44 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart';
|
||||
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class DietsCubit extends Cubit<DietsState> {
|
||||
final FeedRepository feedRepository;
|
||||
final DietRepository dietsRepository;
|
||||
int currentPage = 1;
|
||||
late int lastPage;
|
||||
bool isLoading = false;
|
||||
String? _query;
|
||||
late final StreamSubscription likesStateSubscription;
|
||||
late final StreamSubscription favoriteStateSubscription;
|
||||
late final StreamSubscription commentsStateSubscription;
|
||||
DietsCubit({
|
||||
required this.feedRepository,
|
||||
required this.dietsRepository,
|
||||
}) : super(const DietsState.loading()) {
|
||||
likesStateSubscription = dietsRepository.dietLikeState.listen((likesState) {
|
||||
_changeDietLikeState(likesState);
|
||||
});
|
||||
favoriteStateSubscription = dietsRepository.dietFavoriteState.listen((favoriteState) {
|
||||
_changeDietFavoriteState(favoriteState);
|
||||
});
|
||||
commentsStateSubscription = dietsRepository.dietCommentsState.listen((commentsState) {
|
||||
_changeDietCommentsState(commentsState);
|
||||
});
|
||||
}
|
||||
|
||||
DietsCubit({required this.feedRepository}) : super(const DietsState.loading());
|
||||
@override
|
||||
Future<void> close() async {
|
||||
likesStateSubscription.cancel();
|
||||
favoriteStateSubscription.cancel();
|
||||
commentsStateSubscription.cancel();
|
||||
super.close();
|
||||
}
|
||||
|
||||
loadDiets({
|
||||
String? query,
|
||||
@@ -20,14 +49,18 @@ class DietsCubit extends Cubit<DietsState> {
|
||||
query: query,
|
||||
);
|
||||
lastPage = dietsPagination.meta.lastPage;
|
||||
emit(DietsState.loaded(
|
||||
dietsList: dietsPagination.data,
|
||||
isLoading: isLoading,
|
||||
),);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: dietsPagination.data,
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DietsState.error(
|
||||
errorMessage: e.toString(),
|
||||
),);
|
||||
emit(
|
||||
DietsState.error(
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +93,195 @@ class DietsCubit extends Cubit<DietsState> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> likeDiet(int id, int index) async {
|
||||
if (state is! DietsStateLoaded) return;
|
||||
|
||||
final currentDiets = (state as DietsStateLoaded).dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[index];
|
||||
if (currentDiet.wasLikedByMe) {
|
||||
dietsForModification[index] = currentDiet.copyWith(
|
||||
totalLikes: currentDiet.totalLikes - 1,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
dietsForModification[index] = currentDiet.copyWith(
|
||||
totalLikes: currentDiet.totalLikes + 1,
|
||||
wasLikedByMe: true,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
EasyDebounce.debounce(
|
||||
'like_diet',
|
||||
Duration(milliseconds: 200),
|
||||
() async {
|
||||
try {
|
||||
await dietsRepository.likeDiet(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...currentDiets,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _changeDietLikeState(DietLikesState likesState) {
|
||||
if (state is! DietsStateLoaded) return;
|
||||
|
||||
final currentDiets = (state as DietsStateLoaded).dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[likesState.index];
|
||||
|
||||
dietsForModification[likesState.index] = currentDiet.copyWith(
|
||||
totalLikes: likesState.totalLikes,
|
||||
wasLikedByMe: likesState.wasLikedByMe,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _changeDietFavoriteState(DietFavoriteState favoriteState) {
|
||||
if (state is! DietsStateLoaded) return;
|
||||
|
||||
final currentDiets = (state as DietsStateLoaded).dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[favoriteState.index];
|
||||
|
||||
dietsForModification[favoriteState.index] = currentDiet.copyWith(
|
||||
isFavorite: favoriteState.isFavorite,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _changeDietCommentsState(DietCommentsState commentsState) {
|
||||
if (state is! DietsStateLoaded) return;
|
||||
|
||||
final currentDiets = (state as DietsStateLoaded).dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[commentsState.index];
|
||||
|
||||
dietsForModification[commentsState.index] = currentDiet.copyWith(
|
||||
totalComments: commentsState.totalComments,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addDietToFavorite(int id, int index) async {
|
||||
if (state is! DietsStateLoaded) return;
|
||||
final currentDiets = (state as DietsStateLoaded).dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[index];
|
||||
|
||||
dietsForModification[index] = currentDiet.copyWith(
|
||||
isFavorite: true,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
EasyDebounce.debounce(
|
||||
'add_or_remove_diet_from_favorite',
|
||||
Duration(milliseconds: 200),
|
||||
() async {
|
||||
try {
|
||||
await dietsRepository.addToFavorite(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...currentDiets,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeDietFromFavorite(int id, int index) async {
|
||||
if (state is! DietsStateLoaded) return;
|
||||
final currentDiets = (state as DietsStateLoaded).dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[index];
|
||||
|
||||
dietsForModification[index] = currentDiet.copyWith(
|
||||
isFavorite: false,
|
||||
);
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...dietsForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
EasyDebounce.debounce(
|
||||
'add_or_remove_diet_from_favorite',
|
||||
Duration(milliseconds: 200),
|
||||
() async {
|
||||
try {
|
||||
await dietsRepository.removeFromFavorite(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(
|
||||
DietsState.loaded(
|
||||
dietsList: [
|
||||
...currentDiets,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/blog_post_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/diets_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/filter_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/plan_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/recipes_widget.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/tags_modal_widget.dart';
|
||||
@@ -282,17 +283,26 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
child: BlocBuilder<DietsCubit, DietsState>(
|
||||
builder: (BuildContext context, DietsState state) {
|
||||
if (state is DietsStateLoaded) {
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return DietsWidget(diet: state.dietsList[index]);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.dietsList.length,
|
||||
return Stack(
|
||||
children: [
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return DietsWidget(diet: state.dietsList[index], index: index);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.dietsList.length,
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
bottom: 74,
|
||||
child: FilterWidget(),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (state is DietsStateError) {
|
||||
return Scaffold(
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:dismissible_page/dismissible_page.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
@@ -153,7 +154,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
_iconButton(
|
||||
FeedIconButton(
|
||||
icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: totalLikes.toString(),
|
||||
iconColor: isLiked ? Colors.red.withOpacity(0.8) : null,
|
||||
@@ -171,7 +172,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
},
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
_iconButton(
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset(
|
||||
'assets/icons/comment.svg',
|
||||
height: 20,
|
||||
@@ -188,7 +189,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
_iconButton(
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset(
|
||||
height: 20,
|
||||
width: 20,
|
||||
@@ -225,40 +226,4 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_iconButton({IconData? icon, SvgPicture? svgIcon, String? text, Function()? onTap, Color? iconColor, Color? backgroundColor, Color? textColor}) {
|
||||
return InkWell(
|
||||
onTap: onTap ?? () {},
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Ink(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor ?? appTheme.gray100,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 32,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (svgIcon != null) svgIcon,
|
||||
if (icon != null)
|
||||
Icon(
|
||||
icon,
|
||||
size: 20,
|
||||
color: iconColor ?? appTheme.gray600,
|
||||
),
|
||||
if (text != null) SizedBox(width: 8),
|
||||
if (text != null)
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
color: textColor ?? appTheme.gray600,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class _CommentsWidgetState extends State<CommentsWidget> {
|
||||
comment.authorName,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.grey,
|
||||
color: appTheme.gray,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -81,7 +81,7 @@ class _CommentsWidgetState extends State<CommentsWidget> {
|
||||
comment.body,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -93,7 +93,7 @@ class _CommentsWidgetState extends State<CommentsWidget> {
|
||||
comment.createdAt.format('dd MMMM', 'ru'),
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.grey,
|
||||
color: appTheme.gray,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
@@ -108,7 +108,7 @@ class _CommentsWidgetState extends State<CommentsWidget> {
|
||||
s.answer,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.grey,
|
||||
color: appTheme.gray,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/diet_info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
|
||||
import 'package:eatvio_app/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class DietsWidget extends StatefulWidget {
|
||||
final Diet diet;
|
||||
|
||||
const DietsWidget({super.key, required this.diet});
|
||||
final int index;
|
||||
const DietsWidget({
|
||||
super.key,
|
||||
required this.diet,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
@override
|
||||
State<DietsWidget> createState() => _DietsWidgetState();
|
||||
@@ -18,21 +30,21 @@ class DietsWidget extends StatefulWidget {
|
||||
class _DietsWidgetState extends State<DietsWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () => GoRouter.of(context).pushNamed('aboutDietScreen', extra: widget.diet),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutDietScreen', extra: {'diet': widget.diet, 'index': widget.index, 'navigateToComments': false}),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.diet.image,
|
||||
@@ -40,148 +52,121 @@ class _DietsWidgetState extends State<DietsWidget> {
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 8,
|
||||
bottom: 8,
|
||||
child: Wrap(
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_iconButton(Icons.fastfood, '139.9 ккал'),
|
||||
SizedBox(width: 8),
|
||||
_iconButton(Icons.timer_rounded, widget.diet.state),
|
||||
SizedBox(width: 8),
|
||||
_iconButton(Icons.fast_forward_rounded, widget.diet.duration.toString()),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 8,
|
||||
top: 8,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.favorite_rounded,
|
||||
size: 16,
|
||||
color: Colors.black,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
widget.diet.totalLikes.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 8,
|
||||
top: 8,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.visibility_rounded,
|
||||
size: 16,
|
||||
color: Colors.black,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
widget.diet.totalViews.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(
|
||||
widget.diet.name,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.diet.details.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Html(
|
||||
data: widget.diet.details.length > 200 ? widget.diet.details.substring(0, 200) : widget.diet.details,
|
||||
style: {
|
||||
"*": Style(
|
||||
color: Colors.black87,
|
||||
),
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (widget.diet.isFavorite) {
|
||||
await context.read<DietsCubit>().removeDietFromFavorite(widget.diet.id, widget.index);
|
||||
} else {
|
||||
await context.read<DietsCubit>().addDietToFavorite(widget.diet.id, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: widget.diet.isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
if (widget.diet.details.length > 200)
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: DietInfoRow(
|
||||
diet: widget.diet,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'Читать полностью...',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
widget.diet.name,
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_iconButton(IconData icon, [String? text]) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.8),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 32,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
size: 16,
|
||||
color: Colors.black,
|
||||
if (widget.diet.details.isNotEmpty) ...[
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Html(
|
||||
data: widget.diet.details.length > 200 ? widget.diet.details.substring(0, 200) + '...' : widget.diet.details,
|
||||
style: {
|
||||
"*": Style(
|
||||
margin: Margins.zero,
|
||||
color: appTheme.black,
|
||||
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
|
||||
fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
if (text != null) SizedBox(width: 8),
|
||||
if (text != null)
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, top: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: widget.diet.wasLikedByMe ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: widget.diet.totalLikes.toString(),
|
||||
iconColor: widget.diet.wasLikedByMe ? appTheme.blueA400 : null,
|
||||
backgroundColor: widget.diet.wasLikedByMe ? appTheme.transparentBlue : null,
|
||||
onTap: () async {
|
||||
await context.read<DietsCubit>().likeDiet(widget.diet.id, widget.index);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
text: widget.diet.totalComments.toString(),
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutDietScreen', extra: {'diet': widget.diet, 'index': widget.index, 'navigateToComments': true}),
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/repost.svg'),
|
||||
text: '0',
|
||||
onTap: () async {
|
||||
final result = await Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + widget.diet.id.toString(),
|
||||
),
|
||||
);
|
||||
switch (result.status) {
|
||||
case ShareResultStatus.success:
|
||||
case ShareResultStatus.dismissed:
|
||||
case ShareResultStatus.unavailable:
|
||||
}
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/eye2.svg'),
|
||||
text: widget.diet.totalViews.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
24
lib/features/feed/presentation/widgets/filter_widget.dart
Normal file
24
lib/features/feed/presentation/widgets/filter_widget.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class FilterWidget extends StatelessWidget {
|
||||
const FilterWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 20, top: 12, bottom: 12, right: 24),
|
||||
width: 70,
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
borderRadius: BorderRadius.horizontal(left: Radius.circular(100)),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
'assets/icons/filter2.svg',
|
||||
width: 24,
|
||||
height: 16,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -153,4 +153,5 @@ class FeedRepository {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,5 +74,6 @@ abstract class FeedService {
|
||||
@POST('/api/blogPosts/{id}/unliked')
|
||||
Future<void> unlikedBlogPost({
|
||||
@Path() required int id,
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ MessageLookupByLibrary? _findExact(String localeName) {
|
||||
Future<bool> initializeMessages(String localeName) {
|
||||
var availableLocale = Intl.verifiedLocale(
|
||||
localeName, (locale) => _deferredLibraries[locale] != null,
|
||||
onFailure: (_) => null,);
|
||||
onFailure: (_) => null);
|
||||
if (availableLocale == null) {
|
||||
return new SynchronousFuture(false);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"alko_type": MessageLookupByLibrary.simpleMessage("Алкоголь"),
|
||||
"alko_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.",),
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
|
||||
"allergies_presence":
|
||||
MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
"another_form_of_comment":
|
||||
@@ -42,7 +42,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"archived": MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate": MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Средние показатели давления:",),
|
||||
"Средние показатели давления:"),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
@@ -51,11 +51,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"chest_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике",),
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике"),
|
||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры обязательны к заполнению",),
|
||||
"Все замеры обязательны к заполнению"),
|
||||
"circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры должны быть числами",),
|
||||
"Все замеры должны быть числами"),
|
||||
"circumferences_chart":
|
||||
MessageLookupByLibrary.simpleMessage("График обхватов"),
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
@@ -70,7 +70,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"corb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"corb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",),
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
@@ -83,17 +83,17 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"do_you_have_hypotension_tendency":
|
||||
MessageLookupByLibrary.simpleMessage("Есть ли у вас гипотония?"),
|
||||
"do_you_take_pills": MessageLookupByLibrary.simpleMessage(
|
||||
"Принимаете ли вы лекарства или бады?",),
|
||||
"Принимаете ли вы лекарства или бады?"),
|
||||
"down_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Элетронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты",),
|
||||
"Необходимо ввести адрес электронной почты"),
|
||||
"email_invalid": MessageLookupByLibrary.simpleMessage(
|
||||
"Некорректный адрес электронной почты",),
|
||||
"Некорректный адрес электронной почты"),
|
||||
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите любую дополнительную информацию на своё усмотрение:",),
|
||||
"Введите любую дополнительную информацию на своё усмотрение:"),
|
||||
"enter_information":
|
||||
MessageLookupByLibrary.simpleMessage("Введите информацию..."),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
@@ -102,16 +102,16 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"favorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши любимые/нелюбимые продукты питания?",),
|
||||
"Ваши любимые/нелюбимые продукты питания?"),
|
||||
"female": MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information":
|
||||
MessageLookupByLibrary.simpleMessage("Заполните информацию:"),
|
||||
"finish": MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя обязательно для заполнения",),
|
||||
"Имя обязательно для заполнения"),
|
||||
"first_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени должен быть минимум 1 символ",),
|
||||
"В имени должен быть минимум 1 символ"),
|
||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"height_measurements":
|
||||
@@ -126,9 +126,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Фамилия обязательна для заполнения",),
|
||||
"Фамилия обязательна для заполнения"),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов",),
|
||||
"В фамилии должен быть минимум 6 символов"),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"link_was_copied":
|
||||
MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"),
|
||||
@@ -137,7 +137,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму.",),
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"msg_network_err":
|
||||
MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
@@ -146,9 +146,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя пользователя обязательно для заполнения",),
|
||||
"Имя пользователя обязательно для заполнения"),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов",),
|
||||
"В имени пользователя должно быть минимум 6 символов"),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account":
|
||||
MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
@@ -158,9 +158,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"password_confirmation_mismatch":
|
||||
MessageLookupByLibrary.simpleMessage("Пароли не совпадают"),
|
||||
"password_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароль обязателен для заполнения",),
|
||||
"Пароль обязателен для заполнения"),
|
||||
"password_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В пароле должно быть минимум 6 символов",),
|
||||
"В пароле должно быть минимум 6 символов"),
|
||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"place_of_living":
|
||||
MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
@@ -169,9 +169,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"preferred_language":
|
||||
MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"),
|
||||
"pressure_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления обязательны к заполнению",),
|
||||
"Все показатели давления обязательны к заполнению"),
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами",),
|
||||
"Все показатели давления должны быть числами"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
@@ -180,11 +180,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:",),
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
|
||||
"unfavorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Верхние показатели давления:",),
|
||||
"Верхние показатели давления:"),
|
||||
"user_authorization":
|
||||
MessageLookupByLibrary.simpleMessage("Аутентификация"),
|
||||
"user_registration":
|
||||
@@ -192,7 +192,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья.",),
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
@@ -203,7 +203,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"what_is_your_name":
|
||||
MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя",),
|
||||
"Неверные данные пользователя"),
|
||||
"your_blood_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Ваше артериальное давление?"),
|
||||
"your_favorite_sports":
|
||||
@@ -211,6 +211,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class S {
|
||||
|
||||
static S get current {
|
||||
assert(_current != null,
|
||||
'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.',);
|
||||
'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.');
|
||||
return _current!;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class S {
|
||||
static S of(BuildContext context) {
|
||||
final instance = S.maybeOf(context);
|
||||
assert(instance != null,
|
||||
'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?',);
|
||||
'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?');
|
||||
return instance!;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/data/diet/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/core/data/diet/services/diet_service.dart';
|
||||
import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_cubit.dart';
|
||||
@@ -18,8 +20,6 @@ import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||
import 'package:eatvio_app/features/diary/repositories/diary_repository.dart';
|
||||
import 'package:eatvio_app/features/diary/services/diary_service.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/bloc/about_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diets/repositories/diets_repository.dart';
|
||||
import 'package:eatvio_app/features/diets/services/diets_service.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
@@ -62,7 +62,7 @@ Future<void> init() async {
|
||||
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl(), chatRepository: sl()));
|
||||
sl.registerFactory<ProfileAvatarCubit>(() => ProfileAvatarCubit(profileRepository: sl()));
|
||||
sl.registerFactory<RecipeCreateCubit>(() => RecipeCreateCubit(recipeRepository: sl()));
|
||||
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl()));
|
||||
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl(), dietsRepository: sl()));
|
||||
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl()));
|
||||
sl.registerFactory<ChatSelectCubit>(() => ChatSelectCubit(chatRepository: sl()));
|
||||
sl.registerFactory<PlansCubit>(() => PlansCubit(plansRepository: sl()));
|
||||
@@ -83,7 +83,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<ConsultantRepository>(() => ConsultantRepository(consultantService: sl()));
|
||||
sl.registerLazySingleton<DiaryRepository>(() => DiaryRepository(diaryService: sl()));
|
||||
sl.registerLazySingleton<GlossaryRepository>(() => GlossaryRepository(glossaryService: sl()));
|
||||
sl.registerLazySingleton<DietsRepository>(() => DietsRepository(dietsService: sl()));
|
||||
sl.registerLazySingleton<DietRepository>(() => DietRepository(dietsService: sl()));
|
||||
|
||||
// Services
|
||||
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
||||
@@ -97,9 +97,8 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<ConsultantService>(() => ConsultantService(sl()));
|
||||
sl.registerLazySingleton<DiaryService>(() => DiaryService(sl()));
|
||||
sl.registerLazySingleton<GlossaryService>(() => GlossaryService(sl()));
|
||||
sl.registerLazySingleton<DietsService>(() => DietsService(sl()));
|
||||
|
||||
|
||||
sl.registerLazySingleton<DietService>(() => DietService(sl()));
|
||||
|
||||
// External
|
||||
sl.registerLazySingleton(
|
||||
() => Dio(
|
||||
|
||||
@@ -54,7 +54,7 @@ class AppDecoration {
|
||||
|
||||
static BoxDecoration get outlineBlueGray => BoxDecoration(
|
||||
border: Border.all(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
width: 1,
|
||||
strokeAlign: strokeAlignOutside,
|
||||
),
|
||||
@@ -90,7 +90,7 @@ class BorderRadiusStyle {
|
||||
|
||||
static BoxDecoration get outlineBlueGray => BoxDecoration(
|
||||
border: Border.all(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
width: 1,
|
||||
strokeAlign: strokeAlignOutside,
|
||||
),
|
||||
|
||||
@@ -24,15 +24,15 @@ class CustomTextStyles {
|
||||
);
|
||||
|
||||
static get bodyMediumBluegray800 => theme.textTheme.bodyMedium!.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
);
|
||||
|
||||
static get bodyMediumBluegray800_1 => theme.textTheme.bodyMedium!.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
);
|
||||
|
||||
static get bodyMediumBluegray800_2 => theme.textTheme.bodyMedium!.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
);
|
||||
|
||||
static get bodyMediumWhiteA700 => theme.textTheme.bodyMedium!.copyWith(
|
||||
@@ -45,17 +45,17 @@ class CustomTextStyles {
|
||||
);
|
||||
|
||||
static get bodySmallMulishBluegray800 => theme.textTheme.bodySmall!.mulish.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
static get bodySmallMulishBluegray80012 => theme.textTheme.bodySmall!.mulish.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
static get bodySmallMulishBluegray80012_1 => theme.textTheme.bodySmall!.mulish.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
@@ -116,16 +116,16 @@ class CustomTextStyles {
|
||||
);
|
||||
|
||||
static get titleSmallBluegray800 => theme.textTheme.titleSmall!.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
);
|
||||
|
||||
static get titleSmallBluegray800Bold => theme.textTheme.titleSmall!.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
fontWeight: FontWeight.w700,
|
||||
);
|
||||
|
||||
static get titleSmallBluegray800ExtraBold => theme.textTheme.titleSmall!.copyWith(
|
||||
color: appTheme.blueGray800,
|
||||
color: appTheme.black,
|
||||
fontWeight: FontWeight.w800,
|
||||
);
|
||||
|
||||
@@ -165,8 +165,6 @@ class CustomTextStyles {
|
||||
static get titleSmallSegoeUIOnPrimary => theme.textTheme.titleSmall!.segoeUI.copyWith(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension on TextStyle {
|
||||
@@ -179,4 +177,52 @@ extension on TextStyle {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TextStyles {
|
||||
static const headingXLSemibold = TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textLSemibold = TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textMSemibold = TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textMMedium = TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
);
|
||||
|
||||
static const textMMediumAuto = TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textSSemibold = TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textSMedium = TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textXSSemibold = TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.255,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class PrimaryColors {
|
||||
// BlueGray
|
||||
Color get blueGray300 => Color(0XFF9AA5B1);
|
||||
|
||||
Color get blueGray800 => Color(0XFF323F4B);
|
||||
Color get black => Color(0XFF323F4B);
|
||||
|
||||
Color get blueGray900 => Color(0XFF2A2F4C);
|
||||
|
||||
@@ -169,9 +169,13 @@ class PrimaryColors {
|
||||
|
||||
Color get dividerColor => Color(0xFFF1F2F6);
|
||||
|
||||
Color get grey => Color(0xFF6D6F71);
|
||||
Color get gray => Color(0xFF6D6F71);
|
||||
|
||||
Color get lightGrey => Color(0xFFCECECE);
|
||||
Color get lightGray600 => Color(0xFFB0B0B0);
|
||||
|
||||
Color get lightGray => Color(0xFFCECECE);
|
||||
|
||||
Color get transparentBlue => Color(0xFF2F80ED).withOpacity(0.1);
|
||||
}
|
||||
|
||||
PrimaryColors get appTheme => ThemeHelper().themeColor();
|
||||
|
||||
Reference in New Issue
Block a user