CourseWork - isDone
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 12 KiB |
@ -427,7 +427,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
@ -484,7 +484,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 267 KiB |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 18 KiB |
@ -1,9 +1,13 @@
|
|||||||
{
|
{
|
||||||
"@@locale": "en",
|
"@@locale": "en",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"liked": "liked!",
|
"liked": "liked",
|
||||||
"disliked": "disliked :(",
|
"disliked": "disliked",
|
||||||
"studentWord": "Student",
|
"activityWord": "Activity",
|
||||||
|
"startTime": "Start:",
|
||||||
|
"endTime": "End:",
|
||||||
|
"description": "Description:",
|
||||||
|
"duration": "Duration:",
|
||||||
|
|
||||||
"arbEnding": "Чтобы не забыть про отсутствие запятой :)"
|
"arbEnding": "Чтобы не забыть про отсутствие запятой :)"
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
{
|
{
|
||||||
"@@locale": "ru",
|
"@@locale": "ru",
|
||||||
"search": "Поиск",
|
"search": "Поиск",
|
||||||
"liked": "Понравился!",
|
"liked": "понравился",
|
||||||
"disliked": "разонравился :(",
|
"disliked": "разонравился",
|
||||||
"studentWord": "Студент",
|
"activityWord": "Активность",
|
||||||
|
"startTime": "Начало:",
|
||||||
|
"endTime": "Окончание:",
|
||||||
|
"description": "Описание:",
|
||||||
|
"duration": "Длительность:",
|
||||||
|
|
||||||
"arbEnding": "Чтобы не забыть про отсутствие запятой :)"
|
"arbEnding": "Чтобы не забыть про отсутствие запятой :)"
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,8 @@ abstract class AppLocale {
|
|||||||
/// Additional delegates can be added by appending to this list in
|
/// Additional delegates can be added by appending to this list in
|
||||||
/// MaterialApp. This list does not have to be used at all if a custom list
|
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||||
/// of delegates is preferred or required.
|
/// of delegates is preferred or required.
|
||||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
|
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||||
|
<LocalizationsDelegate<dynamic>>[
|
||||||
delegate,
|
delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
@ -90,10 +91,7 @@ abstract class AppLocale {
|
|||||||
];
|
];
|
||||||
|
|
||||||
/// A list of this localizations delegate's supported locales.
|
/// A list of this localizations delegate's supported locales.
|
||||||
static const List<Locale> supportedLocales = <Locale>[
|
static const List<Locale> supportedLocales = <Locale>[Locale('en'), Locale('ru')];
|
||||||
Locale('en'),
|
|
||||||
Locale('ru')
|
|
||||||
];
|
|
||||||
|
|
||||||
/// No description provided for @search.
|
/// No description provided for @search.
|
||||||
///
|
///
|
||||||
@ -104,20 +102,44 @@ abstract class AppLocale {
|
|||||||
/// No description provided for @liked.
|
/// No description provided for @liked.
|
||||||
///
|
///
|
||||||
/// In ru, this message translates to:
|
/// In ru, this message translates to:
|
||||||
/// **'Понравился!'**
|
/// **'понравился'**
|
||||||
String get liked;
|
String get liked;
|
||||||
|
|
||||||
/// No description provided for @disliked.
|
/// No description provided for @disliked.
|
||||||
///
|
///
|
||||||
/// In ru, this message translates to:
|
/// In ru, this message translates to:
|
||||||
/// **'разонравился :('**
|
/// **'разонравился'**
|
||||||
String get disliked;
|
String get disliked;
|
||||||
|
|
||||||
/// No description provided for @studentWord.
|
/// No description provided for @activityWord.
|
||||||
///
|
///
|
||||||
/// In ru, this message translates to:
|
/// In ru, this message translates to:
|
||||||
/// **'Студент'**
|
/// **'Активность'**
|
||||||
String get studentWord;
|
String get activityWord;
|
||||||
|
|
||||||
|
/// No description provided for @startTime.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'Начало:'**
|
||||||
|
String get startTime;
|
||||||
|
|
||||||
|
/// No description provided for @endTime.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'Окончание:'**
|
||||||
|
String get endTime;
|
||||||
|
|
||||||
|
/// No description provided for @description.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'Описание:'**
|
||||||
|
String get description;
|
||||||
|
|
||||||
|
/// No description provided for @duration.
|
||||||
|
///
|
||||||
|
/// In ru, this message translates to:
|
||||||
|
/// **'Длительность:'**
|
||||||
|
String get duration;
|
||||||
|
|
||||||
/// No description provided for @arbEnding.
|
/// No description provided for @arbEnding.
|
||||||
///
|
///
|
||||||
@ -142,18 +164,17 @@ class _AppLocaleDelegate extends LocalizationsDelegate<AppLocale> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AppLocale lookupAppLocale(Locale locale) {
|
AppLocale lookupAppLocale(Locale locale) {
|
||||||
|
|
||||||
|
|
||||||
// Lookup logic when only language code is specified.
|
// Lookup logic when only language code is specified.
|
||||||
switch (locale.languageCode) {
|
switch (locale.languageCode) {
|
||||||
case 'en': return AppLocaleEn();
|
case 'en':
|
||||||
case 'ru': return AppLocaleRu();
|
return AppLocaleEn();
|
||||||
|
case 'ru':
|
||||||
|
return AppLocaleRu();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw FlutterError(
|
throw FlutterError(
|
||||||
'AppLocale.delegate failed to load unsupported locale "$locale". This is likely '
|
'AppLocale.delegate failed to load unsupported locale "$locale". This is likely '
|
||||||
'an issue with the localizations generation tool. Please file an issue '
|
'an issue with the localizations generation tool. Please file an issue '
|
||||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||||
'that was used.'
|
'that was used.');
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,25 @@ class AppLocaleEn extends AppLocale {
|
|||||||
String get search => 'Search';
|
String get search => 'Search';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get liked => 'liked!';
|
String get liked => 'liked';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get disliked => 'disliked :(';
|
String get disliked => 'disliked';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get studentWord => 'Student';
|
String get activityWord => 'Activity';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startTime => 'Start:';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get endTime => 'End:';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get description => 'Description:';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get duration => 'Duration:';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)';
|
String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)';
|
||||||
|
@ -10,13 +10,25 @@ class AppLocaleRu extends AppLocale {
|
|||||||
String get search => 'Поиск';
|
String get search => 'Поиск';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get liked => 'Понравился!';
|
String get liked => 'понравился';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get disliked => 'разонравился :(';
|
String get disliked => 'разонравился';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get studentWord => 'Студент';
|
String get activityWord => 'Активность';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startTime => 'Начало:';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get endTime => 'Окончание:';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get description => 'Описание:';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get duration => 'Длительность:';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)';
|
String get arbEnding => 'Чтобы не забыть про отсутствие запятой :)';
|
||||||
|
68
lib/data/dtos/activity_dto.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'activity_dto.g.dart'; // Этот файл будет сгенерирован автоматически
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: false)
|
||||||
|
class ActivitiesDto {
|
||||||
|
final List<ActivityDataDto>? data;
|
||||||
|
final MetaDto? meta;
|
||||||
|
|
||||||
|
const ActivitiesDto({this.data, this.meta});
|
||||||
|
|
||||||
|
factory ActivitiesDto.fromJson(Map<String, dynamic> json) => _$ActivitiesDtoFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: false)
|
||||||
|
class MetaDto {
|
||||||
|
final PaginationDto? pagination;
|
||||||
|
|
||||||
|
const MetaDto({this.pagination});
|
||||||
|
|
||||||
|
factory MetaDto.fromJson(Map<String, dynamic> json) => _$MetaDtoFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: false)
|
||||||
|
class PaginationDto {
|
||||||
|
final int? current;
|
||||||
|
final int? next;
|
||||||
|
final int? last;
|
||||||
|
|
||||||
|
const PaginationDto({
|
||||||
|
this.current,
|
||||||
|
this.next,
|
||||||
|
this.last,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory PaginationDto.fromJson(Map<String, dynamic> json) => _$PaginationDtoFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: false)
|
||||||
|
class ActivityDataDto {
|
||||||
|
final String? id;
|
||||||
|
final String? type;
|
||||||
|
final ActivityAttributesDataDto? attributes;
|
||||||
|
|
||||||
|
const ActivityDataDto({this.id, this.type, this.attributes});
|
||||||
|
|
||||||
|
factory ActivityDataDto.fromJson(Map<String, dynamic> json) => _$ActivityDataDtoFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: false)
|
||||||
|
class ActivityAttributesDataDto {
|
||||||
|
final String? name;
|
||||||
|
final String? description;
|
||||||
|
final String? startTime;
|
||||||
|
final String? endTime;
|
||||||
|
final String? category;
|
||||||
|
|
||||||
|
const ActivityAttributesDataDto({
|
||||||
|
this.name,
|
||||||
|
this.description,
|
||||||
|
this.startTime,
|
||||||
|
this.endTime,
|
||||||
|
this.category,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory ActivityAttributesDataDto.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ActivityAttributesDataDtoFromJson(json);
|
||||||
|
}
|
43
lib/data/dtos/activity_dto.g.dart
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'activity_dto.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ActivitiesDto _$ActivitiesDtoFromJson(Map<String, dynamic> json) => ActivitiesDto(
|
||||||
|
data: (json['data'] as List<dynamic>?)
|
||||||
|
?.map((e) => ActivityDataDto.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
meta: json['meta'] == null ? null : MetaDto.fromJson(json['meta'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
MetaDto _$MetaDtoFromJson(Map<String, dynamic> json) => MetaDto(
|
||||||
|
pagination: json['pagination'] == null
|
||||||
|
? null
|
||||||
|
: PaginationDto.fromJson(json['pagination'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
PaginationDto _$PaginationDtoFromJson(Map<String, dynamic> json) => PaginationDto(
|
||||||
|
current: (json['current'] as num?)?.toInt(),
|
||||||
|
next: (json['next'] as num?)?.toInt(),
|
||||||
|
last: (json['last'] as num?)?.toInt(),
|
||||||
|
);
|
||||||
|
|
||||||
|
ActivityDataDto _$ActivityDataDtoFromJson(Map<String, dynamic> json) => ActivityDataDto(
|
||||||
|
id: json['id'] as String?,
|
||||||
|
type: json['type'] as String?,
|
||||||
|
attributes: json['attributes'] == null
|
||||||
|
? null
|
||||||
|
: ActivityAttributesDataDto.fromJson(json['attributes'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
ActivityAttributesDataDto _$ActivityAttributesDataDtoFromJson(Map<String, dynamic> json) =>
|
||||||
|
ActivityAttributesDataDto(
|
||||||
|
name: json['name'] as String?,
|
||||||
|
description: json['description'] as String?,
|
||||||
|
startTime: json['startTime'] as String?,
|
||||||
|
endTime: json['endTime'] as String?,
|
||||||
|
category: json['category'] as String?,
|
||||||
|
);
|
21
lib/data/mapper/ActivityDataDToModel.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:labs/domain/models/Activity.dart';
|
||||||
|
import 'package:labs/domain/models/home.dart';
|
||||||
|
|
||||||
|
import '../dtos/activity_dto.dart';
|
||||||
|
|
||||||
|
extension ActivityDataDtoToModel on ActivityDataDto {
|
||||||
|
Activity toDomain() => Activity(
|
||||||
|
id: id ?? '0',
|
||||||
|
name: attributes?.name ?? 'Без названия',
|
||||||
|
description: attributes?.description ?? 'Нет описания',
|
||||||
|
startTime: attributes?.startTime ?? '00:00',
|
||||||
|
endTime: attributes?.endTime ?? '00:00',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ActivitiesDtoToModel on ActivitiesDto {
|
||||||
|
HomeData toDomain() => HomeData(
|
||||||
|
data: data?.map((e) => e.toDomain()).toList(),
|
||||||
|
nextPage: meta?.pagination?.next,
|
||||||
|
);
|
||||||
|
}
|
@ -10,9 +10,9 @@ extension CharacterDataDtoToModel on CharacterDataDto {
|
|||||||
'https://gryazoveckij-r19.gosweb.gosuslugi.ru/netcat_files/460/2008/net_foto_muzh.jpg');
|
'https://gryazoveckij-r19.gosweb.gosuslugi.ru/netcat_files/460/2008/net_foto_muzh.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CharactersDtoToModel on CharactersDto {
|
/*extension CharactersDtoToModel on CharactersDto {
|
||||||
HomeData toDomain() => HomeData(
|
HomeData toDomain() => HomeData(
|
||||||
data: data?.map((e) => e.toDomain()).toList(),
|
data: data?.map((e) => e.toDomain()).toList(),
|
||||||
nextPage: meta?.pagination?.next,
|
nextPage: meta?.pagination?.next,
|
||||||
);
|
);
|
||||||
}
|
}*/
|
||||||
|
17
lib/domain/models/Activity.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
class Activity {
|
||||||
|
final String name;
|
||||||
|
final String description;
|
||||||
|
final String startTime;
|
||||||
|
final String endTime;
|
||||||
|
final String? id;
|
||||||
|
final String? image;
|
||||||
|
|
||||||
|
Activity({
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.startTime,
|
||||||
|
required this.endTime,
|
||||||
|
this.id,
|
||||||
|
this.image,
|
||||||
|
});
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
|
import 'package:labs/domain/models/Activity.dart';
|
||||||
|
|
||||||
import 'Student.dart';
|
import 'Student.dart';
|
||||||
|
|
||||||
class HomeData {
|
class HomeData {
|
||||||
final List<Student>? data;
|
final List<Activity>? data;
|
||||||
final int? nextPage;
|
final int? nextPage;
|
||||||
|
|
||||||
HomeData({this.data, this.nextPage});
|
HomeData({this.data, this.nextPage});
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:labs/presentation/home_page/bloc/bloc.dart';
|
import 'package:labs/presentation/home_page/bloc/bloc.dart';
|
||||||
import 'package:labs/presentation/home_page/home_page.dart';
|
import 'package:labs/presentation/home_page/home_page.dart';
|
||||||
import 'package:labs/presentation/like_bloc/like_bloc.dart';
|
import 'package:labs/presentation/like_bloc/like_bloc.dart';
|
||||||
import 'package:labs/repo/potter_repo.dart';
|
import 'package:labs/repo/activity_repo.dart';
|
||||||
import 'University.dart';
|
|
||||||
import 'components/locale/l10n/app_locale.dart';
|
import 'components/locale/l10n/app_locale.dart';
|
||||||
import 'domain/models/Student.dart';
|
import 'domain/models/Activity.dart';
|
||||||
import 'presentation/locale_bloc/locale_bloc.dart';
|
import 'presentation/locale_bloc/locale_bloc.dart';
|
||||||
import 'presentation/locale_bloc/locale_state.dart';
|
import 'presentation/locale_bloc/locale_state.dart';
|
||||||
|
|
||||||
@ -20,46 +18,24 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'University App',
|
title: 'Time Management App',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
scaffoldBackgroundColor: Colors.white, // Устанавливаем белый фон
|
scaffoldBackgroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
home: ScaffoldMessenger(
|
home: ScaffoldMessenger(
|
||||||
child: UniversityScreen(),
|
child: ActivityScreen(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversityScreen extends StatefulWidget {
|
class ActivityScreen extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_UniversityScreenState createState() => _UniversityScreenState();
|
_ActivityScreenState createState() => _ActivityScreenState();
|
||||||
}
|
|
||||||
|
|
||||||
class _UniversityScreenState extends State<UniversityScreen> {
|
|
||||||
final University university = University();
|
|
||||||
final TextEditingController nameController = TextEditingController();
|
|
||||||
final TextEditingController ageController = TextEditingController();
|
|
||||||
List<String> selectedCourses = [];
|
|
||||||
|
|
||||||
void _addStudent() async {
|
|
||||||
await Future.delayed(Duration(seconds: 1));
|
|
||||||
String name = nameController.text;
|
|
||||||
int age = int.tryParse(ageController.text) ?? 0;
|
|
||||||
|
|
||||||
if (name.isNotEmpty && age > 0 && selectedCourses.isNotEmpty) {
|
|
||||||
setState(() {
|
|
||||||
// Создаем новый список курсов для каждого студента
|
|
||||||
List<String> studentCourses = List.from(selectedCourses);
|
|
||||||
university.addStudent(Student(name, age, studentCourses));
|
|
||||||
nameController.clear();
|
|
||||||
ageController.clear();
|
|
||||||
selectedCourses.clear();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ActivityScreenState extends State<ActivityScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider<LocaleBloc>(
|
return BlocProvider<LocaleBloc>(
|
||||||
@ -68,7 +44,7 @@ class _UniversityScreenState extends State<UniversityScreen> {
|
|||||||
child: BlocBuilder<LocaleBloc, LocaleState>(
|
child: BlocBuilder<LocaleBloc, LocaleState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Строев Владимир, ПИбд-32',
|
title: 'Time Management',
|
||||||
locale: state.currentLocale,
|
locale: state.currentLocale,
|
||||||
localizationsDelegates: AppLocale.localizationsDelegates,
|
localizationsDelegates: AppLocale.localizationsDelegates,
|
||||||
supportedLocales: AppLocale.supportedLocales,
|
supportedLocales: AppLocale.supportedLocales,
|
||||||
@ -76,17 +52,17 @@ class _UniversityScreenState extends State<UniversityScreen> {
|
|||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.orangeAccent),
|
colorScheme: ColorScheme.fromSeed(seedColor: Colors.orangeAccent),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
scaffoldBackgroundColor: Colors.white12, // Устанавливаем белый фон
|
scaffoldBackgroundColor: Colors.white12,
|
||||||
),
|
),
|
||||||
home: RepositoryProvider<PotterRepo>(
|
home: RepositoryProvider<ActivityRepository>(
|
||||||
lazy: true,
|
lazy: true,
|
||||||
create: (_) => PotterRepo(),
|
create: (_) => ActivityRepository(),
|
||||||
child: BlocProvider<LikeBloc>(
|
child: BlocProvider<LikeBloc>(
|
||||||
lazy: false,
|
lazy: false,
|
||||||
create: (context) => LikeBloc(),
|
create: (context) => LikeBloc(),
|
||||||
child: BlocProvider<HomeBloc>(
|
child: BlocProvider<HomeBloc>(
|
||||||
lazy: false,
|
lazy: false,
|
||||||
create: (context) => HomeBloc(context.read<PotterRepo>()),
|
create: (context) => HomeBloc(context.read<ActivityRepository>()),
|
||||||
child: const MyHomePage(),
|
child: const MyHomePage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,42 +1,135 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:labs/components/extensions/context_x.dart';
|
||||||
import '../../domain/models/Student.dart';
|
import 'package:labs/domain/models/Activity.dart';
|
||||||
|
|
||||||
class DetailsPage extends StatelessWidget {
|
class DetailsPage extends StatelessWidget {
|
||||||
final Student data;
|
final Activity data;
|
||||||
|
|
||||||
const DetailsPage(this.data, {super.key});
|
const DetailsPage(this.data, {super.key});
|
||||||
|
|
||||||
|
// Метод для преобразования времени в минуты
|
||||||
|
int _timeToMinutes(String time) {
|
||||||
|
final parts = time.split(':');
|
||||||
|
final hours = int.parse(parts[0]);
|
||||||
|
final minutes = int.parse(parts[1]);
|
||||||
|
return hours * 60 + minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Метод для вычисления разницы между временем
|
||||||
|
String _calculateDuration(String startTime, String endTime) {
|
||||||
|
final startMinutes = _timeToMinutes(startTime);
|
||||||
|
final endMinutes = _timeToMinutes(endTime);
|
||||||
|
final duration = endMinutes - startMinutes;
|
||||||
|
|
||||||
|
if (duration < 0) {
|
||||||
|
return 'Ошибка: время окончания меньше времени начала';
|
||||||
|
}
|
||||||
|
|
||||||
|
final hours = duration ~/ 60;
|
||||||
|
final minutes = duration % 60;
|
||||||
|
return 'Длительность: ${hours}ч ${minutes}м';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(),
|
appBar: AppBar(
|
||||||
body: Column(
|
title: Text(
|
||||||
|
data.name,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.blueAccent,
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity, // Растягиваем контейнер на всю ширину
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
colors: [Colors.blueAccent, Colors.lightBlueAccent],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
const SizedBox(height: 16),
|
||||||
padding: const EdgeInsets.only(bottom: 16.0),
|
Text(
|
||||||
child: Image.network(
|
context.locale.description,
|
||||||
data.image ?? '',
|
style: TextStyle(
|
||||||
),
|
fontSize: 16,
|
||||||
),
|
color: Colors.white,
|
||||||
Padding(
|
fontWeight: FontWeight.bold,
|
||||||
padding: const EdgeInsets.only(bottom: 4.0),
|
|
||||||
child: Text(
|
|
||||||
data.name,
|
|
||||||
style: Theme.of(context).textTheme.headlineLarge,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
Student.getYearWord(data.age),
|
data.description,
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
Text(
|
||||||
|
context.locale.startTime,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Courses: ${data.courses.join(", ")}',
|
data.startTime,
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.white70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
context.locale.endTime,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
data.endTime,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.white70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
Text(
|
||||||
|
context.locale.duration,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
_calculateDuration(data.startTime, data.endTime),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:labs/presentation/home_page/bloc/events.dart';
|
import 'package:labs/presentation/home_page/bloc/events.dart';
|
||||||
import 'package:labs/presentation/home_page/bloc/state.dart';
|
import 'package:labs/presentation/home_page/bloc/state.dart';
|
||||||
import 'package:labs/repo/potter_repo.dart';
|
import 'package:labs/repo/activity_repo.dart';
|
||||||
|
|
||||||
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||||
final PotterRepo repo;
|
final ActivityRepository repo;
|
||||||
|
|
||||||
HomeBloc(this.repo) : super(const HomeState()) {
|
HomeBloc(this.repo) : super(const HomeState()) {
|
||||||
on<HomeLoadDataEvent>(_onLoadData);
|
on<HomeLoadDataEvent>(_onLoadData);
|
||||||
|
@ -4,9 +4,9 @@ typedef OnLikeCallBack = void Function(String? id, String title, bool isLiked)?;
|
|||||||
|
|
||||||
class _Card extends StatelessWidget {
|
class _Card extends StatelessWidget {
|
||||||
final String name;
|
final String name;
|
||||||
final int age;
|
final String description;
|
||||||
final List<String> courses;
|
final String startTime;
|
||||||
final String? imageUrl;
|
final String endTime;
|
||||||
final OnLikeCallBack onLike;
|
final OnLikeCallBack onLike;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
final String? id;
|
final String? id;
|
||||||
@ -14,22 +14,22 @@ class _Card extends StatelessWidget {
|
|||||||
|
|
||||||
const _Card(
|
const _Card(
|
||||||
this.name, {
|
this.name, {
|
||||||
required this.age,
|
required this.description,
|
||||||
required this.courses,
|
required this.startTime,
|
||||||
this.imageUrl,
|
required this.endTime,
|
||||||
this.onLike,
|
this.onLike,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.id,
|
this.id,
|
||||||
this.isLiked = false,
|
this.isLiked = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory _Card.fromData(Student data,
|
factory _Card.fromData(Activity data,
|
||||||
{OnLikeCallBack onLike, VoidCallback? onTap, bool isLiked = false}) =>
|
{OnLikeCallBack onLike, VoidCallback? onTap, bool isLiked = false}) =>
|
||||||
_Card(
|
_Card(
|
||||||
data.name,
|
data.name,
|
||||||
age: data.age,
|
description: data.description,
|
||||||
courses: data.courses,
|
startTime: data.startTime,
|
||||||
imageUrl: data.image,
|
endTime: data.endTime,
|
||||||
onLike: onLike,
|
onLike: onLike,
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
isLiked: isLiked,
|
isLiked: isLiked,
|
||||||
@ -40,85 +40,66 @@ class _Card extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
child: Container(
|
child: Card(
|
||||||
margin: const EdgeInsets.only(top: 16, left: 16, right: 16, bottom: 16),
|
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
constraints: const BoxConstraints(minHeight: 140),
|
elevation: 4,
|
||||||
decoration: BoxDecoration(
|
shape: RoundedRectangleBorder(
|
||||||
color: Colors.blueAccent,
|
borderRadius: BorderRadius.circular(12),
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.2),
|
|
||||||
spreadRadius: 2,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: Offset(0, 3),
|
|
||||||
),
|
),
|
||||||
],
|
color: Colors.white,
|
||||||
),
|
|
||||||
child: IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.bottomLeft,
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.all(16.0),
|
||||||
left: 8.0,
|
|
||||||
right: 16,
|
|
||||||
bottom: 16,
|
|
||||||
),
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => onLike?.call(id, name, isLiked),
|
|
||||||
child: AnimatedSwitcher(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
child: isLiked
|
|
||||||
? const Icon(
|
|
||||||
Icons.favorite,
|
|
||||||
color: Colors.lightBlueAccent,
|
|
||||||
key: ValueKey<int>(0),
|
|
||||||
)
|
|
||||||
: const Icon(Icons.favorite_border),
|
|
||||||
key: ValueKey<int>(0),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 16),
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(name, style: Theme.of(context).textTheme.bodyLarge),
|
Text(
|
||||||
SizedBox(height: 12),
|
name,
|
||||||
Text('Age: ${Student.getYearWord(age)}',
|
style: const TextStyle(
|
||||||
style: Theme.of(context).textTheme.bodyLarge),
|
fontSize: 18,
|
||||||
SizedBox(height: 12),
|
fontWeight: FontWeight.bold,
|
||||||
Text('Courses: ${courses.join(", ")}',
|
color: Colors.blueAccent,
|
||||||
style: Theme.of(context).textTheme.bodyMedium),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
const SizedBox(height: 8),
|
||||||
child: ClipRRect(
|
Text(
|
||||||
borderRadius: const BorderRadius.only(
|
description,
|
||||||
bottomRight: Radius.circular(20),
|
style: const TextStyle(
|
||||||
topRight: Radius.circular(20),
|
fontSize: 16,
|
||||||
|
color: Colors.grey,
|
||||||
),
|
),
|
||||||
child: Stack(
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'${context.locale.startTime} $startTime',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${context.locale.endTime} $endTime',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.black54,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Positioned.fill(
|
GestureDetector(
|
||||||
child: Image.network(
|
onTap: () => onLike?.call(id, name, isLiked),
|
||||||
imageUrl ?? '',
|
child: Icon(
|
||||||
fit: BoxFit.cover,
|
isLiked ? Icons.favorite : Icons.favorite_border,
|
||||||
errorBuilder: (_, __, ___) => const Placeholder(),
|
color: isLiked ? Colors.red : Colors.grey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import 'package:labs/presentation/details_page/details_page.dart';
|
|||||||
import 'package:labs/presentation/home_page/bloc/events.dart';
|
import 'package:labs/presentation/home_page/bloc/events.dart';
|
||||||
import 'package:labs/presentation/like_bloc/like_event.dart';
|
import 'package:labs/presentation/like_bloc/like_event.dart';
|
||||||
import 'package:labs/presentation/like_bloc/like_state.dart';
|
import 'package:labs/presentation/like_bloc/like_state.dart';
|
||||||
import 'package:labs/repo/potter_repo.dart';
|
import 'package:labs/repo/activity_repo.dart';
|
||||||
import '../../components/utils/debounce.dart';
|
import '../../components/utils/debounce.dart';
|
||||||
import '../../domain/models/Student.dart';
|
import '../../domain/models/Activity.dart';
|
||||||
import '../common/svg_objects.dart';
|
import '../common/svg_objects.dart';
|
||||||
import '../like_bloc/like_bloc.dart';
|
import '../like_bloc/like_bloc.dart';
|
||||||
import '../locale_bloc/locale_bloc.dart';
|
import '../locale_bloc/locale_bloc.dart';
|
||||||
@ -16,6 +16,7 @@ import '../locale_bloc/locale_events.dart';
|
|||||||
import '../locale_bloc/locale_state.dart';
|
import '../locale_bloc/locale_state.dart';
|
||||||
import 'bloc/bloc.dart';
|
import 'bloc/bloc.dart';
|
||||||
import 'bloc/state.dart';
|
import 'bloc/state.dart';
|
||||||
|
|
||||||
part 'card.dart';
|
part 'card.dart';
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
class MyHomePage extends StatefulWidget {
|
||||||
@ -42,8 +43,8 @@ class _Body extends StatefulWidget {
|
|||||||
class _BodyState extends State<_Body> {
|
class _BodyState extends State<_Body> {
|
||||||
final searchController = TextEditingController();
|
final searchController = TextEditingController();
|
||||||
final scrollController = ScrollController();
|
final scrollController = ScrollController();
|
||||||
final PotterRepo repo = PotterRepo();
|
final ActivityRepository repo = ActivityRepository();
|
||||||
late Future<List<Student>?> data;
|
late Future<List<Activity>?> data;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -88,7 +89,15 @@ class _BodyState extends State<_Body> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Padding(
|
body: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
colors: [Colors.blueAccent, Colors.lightBlueAccent],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -123,7 +132,8 @@ class _BodyState extends State<_Body> {
|
|||||||
builder: (context, state) => state.error != null
|
builder: (context, state) => state.error != null
|
||||||
? Text(
|
? Text(
|
||||||
state.error ?? '',
|
state.error ?? '',
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.red),
|
style:
|
||||||
|
Theme.of(context).textTheme.headlineSmall?.copyWith(color: Colors.red),
|
||||||
)
|
)
|
||||||
: state.isLoading
|
: state.isLoading
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
@ -142,7 +152,8 @@ class _BodyState extends State<_Body> {
|
|||||||
? _Card.fromData(
|
? _Card.fromData(
|
||||||
data,
|
data,
|
||||||
onLike: _onLike,
|
onLike: _onLike,
|
||||||
isLiked: likeState.likedIds?.contains(data.id) == true,
|
isLiked:
|
||||||
|
likeState.likedIds?.contains(data.id) == true,
|
||||||
onTap: () => _navToDetails(context, data),
|
onTap: () => _navToDetails(context, data),
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: const SizedBox.shrink();
|
||||||
@ -161,10 +172,11 @@ class _BodyState extends State<_Body> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _navToDetails(BuildContext context, Student data) {
|
void _navToDetails(BuildContext context, Activity data) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(builder: (context) => DetailsPage(data)),
|
CupertinoPageRoute(builder: (context) => DetailsPage(data)),
|
||||||
@ -180,7 +192,7 @@ class _BodyState extends State<_Body> {
|
|||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
'${context.locale.studentWord} $title ${isLiked ? context.locale.liked : context.locale.disliked}',
|
'${context.locale.activityWord} $title ${isLiked ? context.locale.liked : context.locale.disliked}',
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.lightBlueAccent,
|
backgroundColor: Colors.lightBlueAccent,
|
||||||
|
66
lib/repo/activity_repo.dart
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import 'package:labs/domain/models/Activity.dart';
|
||||||
|
import 'package:labs/domain/models/home.dart';
|
||||||
|
import 'api_interface.dart';
|
||||||
|
|
||||||
|
class ActivityRepository extends ApiInterface {
|
||||||
|
@override
|
||||||
|
Future<HomeData?> loadData(
|
||||||
|
{OnErrorCallback? onError, String? q, int page = 1, int pageSize = 25}) async {
|
||||||
|
try {
|
||||||
|
// Мок-данные для активностей
|
||||||
|
final List<Activity> mockActivities = [
|
||||||
|
Activity(
|
||||||
|
id: '1',
|
||||||
|
name: 'Утренняя пробежка',
|
||||||
|
description: 'Пробежка в парке',
|
||||||
|
startTime: '07:00',
|
||||||
|
endTime: '07:30',
|
||||||
|
),
|
||||||
|
Activity(
|
||||||
|
id: '2',
|
||||||
|
name: 'Работа над проектом',
|
||||||
|
description: 'Завершение курсовой работы',
|
||||||
|
startTime: '10:00',
|
||||||
|
endTime: '12:00',
|
||||||
|
),
|
||||||
|
Activity(
|
||||||
|
id: '3',
|
||||||
|
name: 'Обед',
|
||||||
|
description: 'Обед в кафе',
|
||||||
|
startTime: '13:00',
|
||||||
|
endTime: '14:00',
|
||||||
|
),
|
||||||
|
Activity(
|
||||||
|
id: '4',
|
||||||
|
name: 'Чтение книги',
|
||||||
|
description: 'Чтение главы из книги "Тайм-менеджмент"',
|
||||||
|
startTime: '15:00',
|
||||||
|
endTime: '16:00',
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Фильтрация данных по поисковой строке
|
||||||
|
final filteredActivities = mockActivities.where((activity) {
|
||||||
|
return q == null ||
|
||||||
|
activity.name.toLowerCase().contains(q.toLowerCase()) ||
|
||||||
|
activity.description.toLowerCase().contains(q.toLowerCase());
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
// Пагинация
|
||||||
|
final startIndex = (page - 1) * pageSize;
|
||||||
|
final endIndex = startIndex + pageSize;
|
||||||
|
final paginatedActivities =
|
||||||
|
filteredActivities.sublist(startIndex, endIndex.clamp(0, filteredActivities.length));
|
||||||
|
|
||||||
|
// Возвращаем данные в формате HomeData
|
||||||
|
return HomeData(
|
||||||
|
data: paginatedActivities,
|
||||||
|
nextPage: endIndex < filteredActivities.length ? page + 1 : null,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// Обработка ошибок
|
||||||
|
onError?.call(e.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,8 +32,8 @@ class PotterRepo extends ApiInterface {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final CharactersDto dto = CharactersDto.fromJson(response.data as Map<String, dynamic>);
|
final CharactersDto dto = CharactersDto.fromJson(response.data as Map<String, dynamic>);
|
||||||
final HomeData data = dto.toDomain();
|
/*final HomeData data = dto.toDomain();
|
||||||
return data;
|
return data;*/
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
onError?.call(e.error?.toString());
|
onError?.call(e.error?.toString());
|
||||||
return null;
|
return null;
|
||||||
|
16
pubspec.lock
@ -1,6 +1,14 @@
|
|||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
_discoveryapis_commons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _discoveryapis_commons
|
||||||
|
sha256: "113c4100b90a5b70a983541782431b82168b3cae166ab130649c36eb3559d498"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.7"
|
||||||
_fe_analyzer_shared:
|
_fe_analyzer_shared:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -346,6 +354,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
googleapis:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: googleapis
|
||||||
|
sha256: "864f222aed3f2ff00b816c675edf00a39e2aaf373d728d8abec30b37bee1a81c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "13.2.0"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -14,12 +14,13 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
|
|
||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
dio: ^5.4.2+1
|
dio: ^5.7.0
|
||||||
pretty_dio_logger: ^1.3.1
|
pretty_dio_logger: ^1.3.1
|
||||||
equatable: ^2.0.5
|
equatable: ^2.0.5
|
||||||
flutter_bloc: ^8.1.6
|
flutter_bloc: ^8.1.6
|
||||||
copy_with_extension_gen: ^5.0.4
|
copy_with_extension_gen: ^5.0.4
|
||||||
flutter_svg: 2.0.7
|
flutter_svg: 2.0.7
|
||||||
|
googleapis: ^13.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|