본문 바로가기
Flutter & Dart

[Flutter]플러터 디데이 & 가계부 앱 [러브페이] 만들기(3) - 디데이

by Sudarii 2024. 2. 16.
728x90

 

2024.02.15 - [Flutter & Dart] - Flutter & Dart 디데이 & 가계부 앱 [러브페이] 만들기(2) - 파이어베이스

 

Flutter & Dart 디데이 & 가계부 앱 [러브페이] 만들기(2) - 파이어베이스

https://dongkyu.tistory.com/50 Flutter & Dart 디데이 & 가계부 앱 [러브페이] 만들기(1) - 바텀네비게이션 디데이, 가계부가 합쳐진 앱을 만들고자 한다. 앱 이름은 러브페이 라고 지었다. 앱은 홈(디데이),

dongkyu.tistory.com

지난 글에 이어 이번엔 디데이 탭의 플러터 소스를 작성 할 것이다.

 

사진과 같은 형태의 디데이 리스트를 만들 것이다.

 

1. 디데이 만들기

	Scaffold(
        appBar: AppBar(
          centerTitle: false,
          title: Row(
            children: [
              const Icon(Icons.star_rate, size: 25),
              const SizedBox(width: 10),
              Text('The D-Day Memorys', style: AppTextStyle().blackBold18),
            ],
          ),
        ),
        body: GestureDetector(
          onTap: () {
            FocusScope.of(context).unfocus();
          },
          child: SafeArea(
            child: Stack(
              children: [
                Column(
                  children: [
                    Expanded(
                      child: Container(
                          height: Get.height,
                          padding: const EdgeInsets.all(15),
                          child: myList()),
                    ),
                  ],
                ),
                Positioned(
                    right: 20,
                    bottom: 20,
                    child: InkWell(
                      onTap: () {
                        Get.to(() => const Page1Input(
                            date: '', documentId: '', subject: ''));
                      },
                      child: Container(
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(50),
                            color: AppColors().titleColor),
                        width: 50,
                        height: 50,
                        child: Center(
                            child: Icon(
                          Icons.add,
                          color: AppColors().colorwhite,
                        )),
                      ),
                    ))
              ],
            ),
          ),
        ));

 

추가 버튼은 스크롤이 이동되어도 하단에 고정되어야 하기 때문에  스택 + 포지션으로 위치를 설정 했다.

 

  Widget myList() {
    return SingleChildScrollView(
      child: Column(
        children: [
          Obx(
            () => ListView.builder(
              shrinkWrap: true, 
              physics: const ScrollPhysics(),
              itemCount: controller.ddaySearch.length,
              itemBuilder: (context, index) {
                return InkWell(
                  onTap: () {
                    Get.to(() => Page1Input(
                          subject: controller.ddaySearch[index].subject,
                          date: controller.ddaySearch[index].date,
                          documentId: controller.ddaySearch[index].id,
                        ));
                  },
                  child: Container(
                    margin: const EdgeInsets.symmetric(vertical: 10),
                    padding: const EdgeInsets.all(10),
                    decoration: BoxDecoration(
                      border: Border.all(
                        width: 1,
                      ),
                      color: AppColors().colorwhite,
                      borderRadius: BorderRadius.circular(5),
                    ),
                    height: 100,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Flexible(
                              child: Text(
                                controller.ddaySearch[index].subject,
                                style: AppTextStyle().black16,
                              ),
                            ),
                            InkWell(
                                onTap: () {
                                  showDialog(
                                      context: context,
                                      builder: (context) => DeletePop(
                                          text: '해당 기념일을 삭제하시겠습니까?',
                                          callback: () async {
                                            await controller.delData(controller
                                                .ddaySearch[index].id);
                                            Get.back();
                                          }));
                                },
                                child: const Icon(Icons.delete, weight: 20))
                          ],
                        ),
                        Text(
                            '${controller.ddaySearch[index].date} (${controller.getDayKor(controller.ddaySearch[index].date)})',
                            style: AppTextStyle().color99999914),
                        const Spacer(),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: [
                            controller.getDateDifference(
                                        controller.ddaySearch[index].date) <
                                    0
                                ? Text(
                                    'D -  ${controller.getDateDifference(controller.ddaySearch[index].date) * -1} ',
                                    style: AppTextStyle().blackBold22,
                                  )
                                : Text(
                                    'D +  ${controller.getDateDifference(controller.ddaySearch[index].date)}',
                                    style: AppTextStyle().blackBold22,
                                  ),
                          ],
                        )
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

 

휴지통 이미지를 클릭 시 해당 디데이를 삭제 하기 위해 showDialog를 이용해 DeletePop 위젯을 호출 하였다.

 

 

DeletePop은 팝업창에 적을 메시지, 확인 버튼 클릭 시 행동 할 이벤트를 받으며 취소 버튼을 클릭 시 팝업창을 닫는다.

class DeletePop extends StatelessWidget {
  const DeletePop({super.key, required this.text, required this.callback});
  final String text;
  final Function() callback;
  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Center(
        child: Text(
          text,
          style: AppTextStyle().blackBold18,
        ),
      ),
      buttonPadding: const EdgeInsets.all(0),
      backgroundColor: AppColors().colorwhite,
      actions: <Widget>[
        ClipRRect(
          borderRadius: const BorderRadius.only(
            bottomLeft: Radius.circular(5),
            bottomRight: Radius.circular(5),
          ),
          child: Row(
            children: [
              Flexible(
                fit: FlexFit.tight,
                child: GestureDetector(
                  onTap: () {
                    Get.back();
                  },
                  child: Container(
                    height: 50,
                    decoration: BoxDecoration(
                      color: AppColors().colorwhite,
                      border: Border(
                        top: BorderSide(
                          color: AppColors().coloreeeeee,
                          width: 1.0,
                        ),
                      ),
                    ),
                    child: Center(
                      child: Text(
                        '취소',
                        style: AppTextStyle().color19191918bold,
                      ),
                    ),
                  ),
                ),
              ),
              Container(
                color: AppColors().coloreeeeee,
                width: 1,
                height: 50,
              ),
              Flexible(
                fit: FlexFit.tight,
                child: GestureDetector(
                  onTap: () async {
                    await callback();
                  },
                  child: Container(
                    height: 50,
                    decoration: BoxDecoration(
                      color: AppColors().colorwhite,
                      border: Border(
                        top: BorderSide(
                          color: AppColors().coloreeeeee,
                          width: 1.0,
                        ),
                      ),
                    ),
                    child: Center(
                      child: Text(
                        '확인',
                        style: AppTextStyle().blackBold18,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        )
      ],
    );
  }
}

 

 

getDateDifference는 오늘부터 특정 일자 까지의 차이를 구한다.

  int getDateDifference(String date) {
    var split = date.split('-');
    DateTime targetDate =
        DateTime(int.parse(split[0]), int.parse(split[1]), int.parse(split[2]));

    DateTime today = DateTime.now();
    int differenceInDays = today.difference(targetDate).inDays;
    return differenceInDays;
  }

 

DateTime.now() 는 현 시간을 구하는 것이고 현재.difference(비교일시).inDays 는 현재 - 비교일시  의 일자를 구하는 것이다.

해당 결과가 0보다 크면 D +,  0 보다 작으면 D - 를 위해 사용 하였다.

 

728x90