name27 / flutter

0 stars 0 forks source link

todo 리스트 #94

Open name27 opened 1 year ago

name27 commented 1 year ago

image image image

main.dart

import 'package:blog_app/pages/main_page.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MainPage(),
    );
  }
}

main_page.dart

import 'dart:ui';

import 'package:blog_app/model/todo.dart';
import 'package:blog_app/widget/filter_bottom_sheet.dart';
import 'package:blog_app/widget/todoTile.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Future<List<Todo>> readData() async {
    var dio = Dio();
    var url = 'https://jsonplaceholder.typicode.com/todos';
    var res = await dio.get(url);
    if (res.statusCode == 200) {
      var data = List<Map<String, dynamic>>.from(res.data);
      return data.map((e) => Todo.fromMap(e)).toList();
    }
    return [];
  }

  TodoFilter selected = TodoFilter.all;
  onApply(TodoFilter filter) {
    selected = filter;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        title: Text("Todo App"),
        elevation: 0,
        backgroundColor: Colors.transparent,
        foregroundColor: Colors.black,
        actions: [
          IconButton(
              onPressed: () {
                showModalBottomSheet<void>(
                    context: context,
                    builder: (BuildContext context) {
                      return FilterBottomSheet(
                          filter: selected, onApply: onApply);
                    });
              },
              icon: Icon(Icons.wifi)),
          IconButton(
              onPressed: () {
                setState(() {});
              },
              icon: Icon(Icons.refresh))
        ],
      ),
      body: Stack(
        children: [
          Center(
            child: FutureBuilder(
              future: readData(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.data != null) {
                    return ListView.builder(
                        itemCount: snapshot.data?.length ?? 0,
                        itemBuilder: (context, index) {
                          var widget;
                          switch (selected) {
                            case TodoFilter.completed:
                              if (snapshot.data![index].completed) {
                                var data = widget = Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: TodoTile(todo: snapshot.data![index]),
                                );
                              } else {
                                widget = SizedBox();
                              }
                              break;
                            case TodoFilter.incompleted:
                              if (!snapshot.data![index].completed) {
                                widget = Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: TodoTile(todo: snapshot.data![index]),
                                );
                              } else {
                                widget = SizedBox();
                              }
                              break;
                            case TodoFilter.all:
                              widget = Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: TodoTile(todo: snapshot.data![index]),
                              );
                              break;
                          }
                          return widget;
                        });
                  }
                }
                return CircularProgressIndicator();
              },
            ),
          ),
          ClipRRect(
            child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
                child: Container(
                  height: 85,
                )),
          )
        ],
      ),
    );
  }
}

todo.dart

class Todo {
  int userId;
  int id;
  String title;
  bool completed;

  Todo(
      {required this.userId,
      required this.id,
      required this.title,
      required this.completed});

  factory Todo.fromMap(Map<String, dynamic> map) {
    return Todo(
        userId: map['userId'],
        id: map['id'],
        title: map['title'],
        completed: map['completed']);
  }
}

todoTile.dart

import 'package:blog_app/model/todo.dart';
import 'package:flutter/material.dart';

class TodoTile extends StatelessWidget {
  const TodoTile({super.key, required this.todo});
  final Todo todo;

  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: Key(todo.id.toString()),
      child: Container(
        margin: const EdgeInsets.all(8),
        decoration: BoxDecoration(
          color: todo.completed ? Colors.green.shade100 : null,
          border: todo.completed
              ? Border.all(
                  color: Colors.green,
                )
              : null,
          borderRadius: BorderRadius.circular(8),
        ),
        child: ListTile(
          title: Text(
            todo.title,
            style: TextStyle(
              color: todo.completed ? Colors.green : null,
              fontWeight: FontWeight.bold,
            ),
          ),
          trailing: todo.completed
              ? const Icon(
                  Icons.check_circle,
                  color: Colors.green,
                )
              : null,
        ),
      ),
    );
  }
}

filter_bottom_sheet.dart

import 'package:flutter/material.dart';

enum TodoFilter { all, completed, incompleted }

class FilterBottomSheet extends StatefulWidget {
  const FilterBottomSheet(
      {Key? key, required this.filter, required this.onApply})
      : super(key: key);
  final TodoFilter filter;
  final Function(TodoFilter) onApply;

  @override
  State<FilterBottomSheet> createState() => _FilterBottomSheetState();
}

class _FilterBottomSheetState extends State<FilterBottomSheet> {
  onApply(TodoFilter filter) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Filter applied: $filter'),
      ),
    );
    widget.onApply(filter);
    Navigator.pop(context);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(16),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          ListTile(
            title: const Text('All'),
            trailing: Checkbox(
              value: widget.filter == TodoFilter.all,
              onChanged: (value) {
                if (value == true) onApply(TodoFilter.all);
              },
            ),
          ),
          ListTile(
            title: const Text('Completed'),
            trailing: Checkbox(
              value: widget.filter == TodoFilter.completed,
              onChanged: (value) {
                if (value == true) onApply(TodoFilter.completed);
              },
            ),
          ),
          ListTile(
            title: const Text('InCompleted'),
            trailing: Checkbox(
              value: widget.filter == TodoFilter.incompleted,
              onChanged: (value) {
                if (value == true) onApply(TodoFilter.incompleted);
              },
            ),
          ),
        ],
      ),
    );
  }
}
name27 commented 1 year ago

Enum 열거형 타입, 서로 연관된 상수를 모아놓은 집합

ex)

enum NewColor {
  red("레드", "red"),
  blue("블루", "blue"),
  white("화이트", "white"),
  amber("엠버","amber");

  final String korean;
  final String english;  
  const NewColor(this.korean, this.english);    
}
print(NewColor.amber.korean);
print(NewColor.amber.english);
name27 commented 1 year ago

main_page.dart

import 'dart:ui';

import 'package:blog_app/model/todo.dart';
import 'package:blog_app/widget/filter_bottom_sheet.dart';
import 'package:blog_app/widget/todoTile.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  List<Todo> todos = [];
  readData() async {
    var dio = Dio();
    var url = 'https://jsonplaceholder.typicode.com/todos';
    var res = await dio.get(url);
    if (res.statusCode == 200) {
      var data = List<Map<String, dynamic>>.from(res.data);
      setState(() => todos = data.map((e) => Todo.fromMap(e)).toList());
    }
  }

  @override
  void initState() {
    super.initState();
    readData();
  }

  TodoFilter selected = TodoFilter.all;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        extendBodyBehindAppBar: true,
        appBar: AppBar(
          title: Text("Todo App"),
          elevation: 0,
          backgroundColor: Colors.transparent,
          foregroundColor: Colors.black,
          flexibleSpace: ClipRRect(
            child: BackdropFilter(
              filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
              child: Container(),
            ),
          ),
          actions: [
            IconButton(
                onPressed: () {
                  showModalBottomSheet<void>(
                      context: context,
                      builder: (BuildContext context) => FilterBottomSheet(
                          filter: selected,
                          onApply: (value) {
                            setState(() => selected = value);
                          }));
                },
                icon: Icon(Icons.wifi)),
            IconButton(
                onPressed: () {
                  readData();
                },
                icon: Icon(Icons.refresh))
          ],
        ),
        body: ListView.builder(
          itemCount: todos.length,
          itemBuilder: (context, index) =>
              TodoTile(todo: filterMaker(todos)[index]),
        ));
  }

  List<Todo> filterMaker(List<Todo> value) {
    switch (selected) {
      case TodoFilter.all:
        return value;
      case TodoFilter.completed:
        return value.where((element) => element.completed == true).toList();
      case TodoFilter.incompleted:
        return value.where((element) => element.completed == false).toList();
    }
  }
}