diff --git a/lib/add_task_dialog.dart b/lib/add_task_dialog.dart deleted file mode 100644 index 33534fb..0000000 --- a/lib/add_task_dialog.dart +++ /dev/null @@ -1,116 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'task_provider.dart'; -import 'task_model.dart'; -import 'package:intl/intl.dart'; - -class AddTaskDialog extends StatefulWidget { - @override - _AddTaskDialogState createState() => _AddTaskDialogState(); -} - -class _AddTaskDialogState extends State { - final _formKey = GlobalKey(); - String _title = ''; - String? _description; - String? _category; - DateTime? _selectedDeadline; - TaskPriority _selectedPriority = TaskPriority.medium; - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Text('Add New Task'), - content: Form( - key: _formKey, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextFormField( - decoration: InputDecoration(labelText: 'Task Title*'), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter a task title'; - } - return null; - }, - onSaved: (value) { - _title = value ?? ''; - }, - ), - TextFormField( - decoration: InputDecoration(labelText: 'Description (optional)'), - onSaved: (value) { - _description = value; - }, - ), - TextFormField( - decoration: InputDecoration(labelText: 'Category (optional)'), - onSaved: (value) { - _category = value; - }, - ), - SizedBox(height: 20), - Text('Deadline: ${_selectedDeadline != null ? DateFormat('yMMMd').format(_selectedDeadline!) : 'No deadline'}'), - ElevatedButton( - child: Text('Select Deadline'), - onPressed: () => _selectDeadline(context), - ), - DropdownButton( - value: _selectedPriority, - onChanged: (TaskPriority? newValue) { - setState(() { - _selectedPriority = newValue!; - }); - }, - items: TaskPriority.values.map((TaskPriority priority) { - return DropdownMenuItem( - value: priority, - child: Text(priority.toString().split('.').last), - ); - }).toList(), - ), - ], - ), - ), - actions: [ - TextButton( - child: Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ElevatedButton( - child: Text('Add Task'), - onPressed: () { - if (_formKey.currentState!.validate()) { - _formKey.currentState!.save(); - Provider.of(context, listen: false).addTask( - title: _title, - description: _description, - category: _category, - deadline: _selectedDeadline, - priority: _selectedPriority, - ); - Navigator.of(context).pop(); - } - }, - ), - ], - ); - } - - Future _selectDeadline(BuildContext context) async { - final DateTime? picked = await showDatePicker( - context: context, - initialDate: DateTime.now(), - firstDate: DateTime.now(), - lastDate: DateTime(2100), - ); - if (picked != null) { - setState(() { - _selectedDeadline = picked; - }); - } - } -} \ No newline at end of file diff --git a/lib/comment_model.dart b/lib/comment_model.dart new file mode 100644 index 0000000..d174bcb --- /dev/null +++ b/lib/comment_model.dart @@ -0,0 +1,11 @@ +class CommentModel { + final String title; + final String text; + final String? imageUrl; + + CommentModel({ + required this.title, + required this.text, + this.imageUrl, + }); +} diff --git a/lib/comments_widget.dart b/lib/comments_widget.dart new file mode 100644 index 0000000..227cf46 --- /dev/null +++ b/lib/comments_widget.dart @@ -0,0 +1,119 @@ +import 'package:flutter/material.dart'; + +import 'comment_model.dart'; + +class CommentsWidget extends StatelessWidget { + const CommentsWidget({super.key}); + + @override + Widget build(BuildContext context) { + final data = [ + CommentModel( + title: 'Oh my god', + text: 'this app is so cool ' * 10, + imageUrl: + 'https://preview.free3d.com/img/2016/03/1875481443430303321/hld8c0oa.jpg', + ), + CommentModel( + title: 'Listen to me', + text: 'This app is like Half-Life 3 - it will never be released', + imageUrl: + 'https://us-tuna-sounds-images.voicemod.net/356aeabd-18d5-40d8-af31-b479f4eff183-1704672174928.png', + ), + CommentModel( + title: 'BREAKING!!!', + text: 'The next lab work will have DLC in the form of likes', + imageUrl: 'https://i.playground.ru/p/BWixorSTeZQfoPvdVL9lgA.jpeg', + ), + CommentModel( + title: 'Test', + text: 'Test', + ), + CommentModel( + title: 'Test', + text: 'Test', + ), + ]; + + return SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: data.map((e) => _Comment.fromData(e)).toList(), + ), + ); + } +} + +class _Comment extends StatelessWidget { + final String title; + final String text; + final String? imageUrl; + + const _Comment({ + required this.title, + required this.text, + this.imageUrl, + }); + + factory _Comment.fromData(CommentModel model) => _Comment( + title: model.title, + text: model.text, + imageUrl: model.imageUrl, + ); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white70, + borderRadius: BorderRadius.circular(16), + border: Border.all(color: Colors.grey), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.5), + spreadRadius: 4, + offset: const Offset(0, 5), + blurRadius: 8, + ), + ], + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(20), + child: SizedBox( + height: 140, + width: 100, + child: Image.network( + imageUrl ?? '', + fit: BoxFit.cover, + errorBuilder: (_, __, ___) => const Placeholder(), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Theme.of(context).textTheme.headlineLarge, + ), + Text( + text, + style: Theme.of(context).textTheme.bodyLarge, + ) + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/datetime_extension.dart b/lib/datetime_extension.dart deleted file mode 100644 index de1e1af..0000000 --- a/lib/datetime_extension.dart +++ /dev/null @@ -1,19 +0,0 @@ -extension DateTimeFormatting on DateTime { - // Форматирует дату как "DD/MM/YYYY" - String toFormattedDate() { - return "${this.day.toString().padLeft(2, '0')}/${this.month.toString().padLeft(2, '0')}/${this.year}"; - } - - // Форматирует как "x дней осталось" - String toDaysLeft() { - final now = DateTime.now(); - final difference = this.difference(now).inDays; - if (difference < 0) { - return "Overdue by ${difference.abs()} days"; - } else if (difference == 0) { - return "Due today"; - } else { - return "Due in $difference days"; - } - } -} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index ff65563..cec3ae4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,29 +1,73 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'task_provider.dart'; -import 'task_list_screen.dart'; + +import 'comments_widget.dart'; void main() { - runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => TaskProvider()), - ], - child: MyApp(), - ), - ); + runApp(const MyApp()); } class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( - title: 'ToDo List', + title: 'Comments App', debugShowCheckedModeBanner: false, theme: ThemeData( - primarySwatch: Colors.blue, + colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), + useMaterial3: true, ), - home: TaskListScreen(), + home: const MyHomePage(title: 'Comments App'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + Color _color = Colors.transparent; + + @override + void initState() { + super.initState(); + _color = Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: _color, + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.title, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + )), + Text( + 'made by Factorino', + style: TextStyle( + fontSize: 12, + fontStyle: FontStyle.italic, + ), + ), + ], + ), + ), + body: const CommentsWidget(), ); } } diff --git a/lib/task_details_screen.dart b/lib/task_details_screen.dart deleted file mode 100644 index 02cb9bd..0000000 --- a/lib/task_details_screen.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:flutter/material.dart'; -import 'task_model.dart'; -import 'datetime_extension.dart'; - -class TaskDetailsScreen extends StatelessWidget { - final Task task; - - TaskDetailsScreen({required this.task}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(task.title), - ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Category: ${task.category ?? 'Not specified'}', - style: TextStyle(fontSize: 16), - ), - SizedBox(height: 8), - Text( - 'Priority: ${task.priority.name}', - style: TextStyle(fontSize: 16), - ), - SizedBox(height: 8), - Text( - 'Deadline: ${task.deadline != null ? task.deadline!.toFormattedDate() : 'No deadline'}', - style: TextStyle(fontSize: 16), - ), - SizedBox(height: 16), - Text( - 'Description:', - style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - SizedBox(height: 8), - Text( - task.description ?? 'No description available', - style: TextStyle(fontSize: 16), - ), - SizedBox(height: 16), - Text( - 'Completed: ${task.isCompleted ? "Yes" : "No"}', - style: TextStyle(fontSize: 16), - ), - ], - ), - ), - ); - } -} diff --git a/lib/task_list_screen.dart b/lib/task_list_screen.dart deleted file mode 100644 index 2991a0c..0000000 --- a/lib/task_list_screen.dart +++ /dev/null @@ -1,108 +0,0 @@ -import 'dart:math'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'task_provider.dart'; -import 'task_details_screen.dart'; -import 'add_task_dialog.dart'; -import 'task_model.dart'; -import 'datetime_extension.dart'; - -class TaskListScreen extends StatefulWidget { - @override - _TaskListScreenState createState() => _TaskListScreenState(); -} - -class _TaskListScreenState extends State { - Color _color = Colors.transparent; - - @override - void initState() { - super.initState(); - Provider.of(context, listen: false).loadTasks(); - _color = - Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: _color, - title: Column( - crossAxisAlignment: - CrossAxisAlignment.start, // Чтобы текст выровнялся по левому краю - children: [ - Text('ToDo List', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), - Text( - 'made by Factorino', - style: TextStyle( - fontSize: 12, // Размер шрифта для подписи - fontStyle: FontStyle.italic, // Сделаем текст курсивом - ), - ), - ], - ), - actions: [ - IconButton( - icon: Icon(Icons.sort), - onPressed: () { - context.read().sortTasks(); - }, - ), - ], - ), - body: Consumer( - builder: (context, taskProvider, child) { - if (taskProvider.tasks.isEmpty) { - return Center(child: Text('No tasks yet.')); - } - - return ListView.builder( - itemCount: taskProvider.tasks.length, - itemBuilder: (context, index) { - Task task = taskProvider.tasks[index]; - return ListTile( - title: Text(task.title), - subtitle: Text( - '${task.category ?? 'No category'} - ${task.deadline?.toFormattedDate() ?? 'No deadline'}'), - trailing: Checkbox( - value: task.isCompleted, - onChanged: (value) { - context.read().toggleTaskCompletion(task); - }, - ), - onTap: () { - // Открываем экран с деталями задачи - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TaskDetailsScreen(task: task), - ), - ); - }, - onLongPress: () { - context.read().removeTask(task); - }, - ); - }, - ); - }, - ), - floatingActionButton: FloatingActionButton( - onPressed: () => _openAddTaskDialog(context), - backgroundColor: _color, - child: Icon(Icons.add), - ), - ); - } - - void _openAddTaskDialog(BuildContext context) { - showDialog( - context: context, - builder: (BuildContext context) { - return AddTaskDialog(); - }, - ); - } -} diff --git a/lib/task_model.dart b/lib/task_model.dart deleted file mode 100644 index 90467cb..0000000 --- a/lib/task_model.dart +++ /dev/null @@ -1,23 +0,0 @@ -enum TaskPriority { - low, - medium, - high -} - -class Task { - final String title; - final String? description; - final String? category; - final DateTime? deadline; - bool isCompleted; - TaskPriority priority; - - Task({ - required this.title, - this.description, - this.category, - this.deadline, - this.isCompleted = false, - this.priority = TaskPriority.medium, - }); -} \ No newline at end of file diff --git a/lib/task_provider.dart b/lib/task_provider.dart deleted file mode 100644 index 4a9498a..0000000 --- a/lib/task_provider.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter/material.dart'; -import 'task_model.dart'; - -class TaskProvider with ChangeNotifier { - List _tasks = []; - - List get tasks => _tasks; - - // Добавление задачи - void addTask({ - required String title, - String? description, - String? category, - DateTime? deadline, - TaskPriority priority = TaskPriority.medium, - }) { - final task = Task( - title: title, - description: description, - category: category, - deadline: deadline, - priority: priority, - ); - _tasks.add(task); - notifyListeners(); - } - - // Удаление задачи - void removeTask(Task task) { - _tasks.remove(task); - notifyListeners(); - } - - // Изменение состояния задачи - void toggleTaskCompletion(Task task) { - task.isCompleted = !task.isCompleted; - notifyListeners(); - } - - // Сортировка задач по приоритету и дедлайну - void sortTasks() { - _tasks.sort((a, b) { - // Сравнение по приоритету - if (a.priority == b.priority) { - // Если оба дедлайна не null, сравниваем их - if (a.deadline != null && b.deadline != null) { - return a.deadline!.compareTo(b.deadline!); - } - // Если у одной задачи нет дедлайна, она считается "позднее" - if (a.deadline == null) return 1; // Задачи без дедлайна позже - if (b.deadline == null) return -1; // Задачи с дедлайном раньше - return 0; - } - // Сравнение по приоритету - return a.priority.index.compareTo(b.priority.index); - }); - notifyListeners(); - } - - // Метод для завершения всех задач - void completeAllTasks() { - for (var task in _tasks) { - task.isCompleted = true; - } - notifyListeners(); - } - - // Асинхронная загрузка задач - Future loadTasks() async { - if (_tasks.isEmpty) { - _tasks = [ - Task( - title: "Task 1", - category: "Work", - deadline: DateTime.now().add(Duration(days: 1)), - priority: TaskPriority.high), - Task( - title: "Task 2", - category: "Home", - deadline: DateTime.now().add(Duration(days: 2)), - priority: TaskPriority.medium), - Task( - title: "Task 3", - description: "Optional description", - priority: TaskPriority.low), - Task( - title: "Task 4", - category: "Personal", - priority: TaskPriority.high), - ]; - } - notifyListeners(); - } -} diff --git a/pubspec.lock b/pubspec.lock index 8ad20e2..07514d0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -75,14 +75,6 @@ packages: description: flutter source: sdk version: "0.0.0" - intl: - dependency: "direct main" - description: - name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" - url: "https://pub.dev" - source: hosted - version: "0.17.0" leak_tracker: dependency: transitive description: @@ -139,14 +131,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.15.0" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" path: dependency: transitive description: @@ -155,14 +139,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" - provider: - dependency: "direct main" - description: - name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c - url: "https://pub.dev" - source: hosted - version: "6.1.2" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 57762cc..3d616eb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,8 +30,6 @@ environment: dependencies: flutter: sdk: flutter - provider: ^6.0.0 - intl: ^0.17.0 # The following adds the Cupertino Icons font to your application.