Notice
Recent Posts
Recent Comments
Link
250x250
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

혼자서 앱 만드는 개발자 함께하는 AI 세상

[펫버틀러] 반려 동물 고민 상담 앱 - 개발 12 일차 (프로필화면에 달력적용) 본문

펫버틀러

[펫버틀러] 반려 동물 고민 상담 앱 - 개발 12 일차 (프로필화면에 달력적용)

혼앱사 2023. 1. 11. 07:44
반응형
  • 펫버틀러 팻다이어리를 추가하고 메인화면에 일정관리와 다이어리 작성시 볼 수 있도록 수정해 보았다.
  • 관련 패키지를 추가하고 플러터에서 유명한 Table_Calendar  를 사용해보고 한글 설정 해보았다.
  • https://github.com/aleksanderwozniak/table_calendar
 

GitHub - aleksanderwozniak/table_calendar: Highly customizable, feature-packed calendar widget for Flutter

Highly customizable, feature-packed calendar widget for Flutter - GitHub - aleksanderwozniak/table_calendar: Highly customizable, feature-packed calendar widget for Flutter

github.com

 

  • 우선 간단하게 추가하고 이벤트를 등록할 예정이다.

  • 추가는 flutter pub add flutter pub add table_calendar
  • 그리고 한글설정은 따로 해주어야한다.

  • 변경된 화면

 

  • 수정된소스
import 'dart:ffi';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:petbutler/pages/memo_page.dart';
import 'package:petbutler/pages/renderCard.dart';
import 'package:petbutler/utils/database_helper.dart';
import 'package:petbutler/views/htmlView.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:provider/provider.dart';

import '../constants/firestore_constants.dart';
import '../providers/auth_provider.dart';

class PetProfileAdd extends StatefulWidget {
  const PetProfileAdd({Key? key}) : super(key: key);

  @override
  State<PetProfileAdd> createState() => _HomeState();
}

class _HomeState extends State<PetProfileAdd>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;
  @override
  void initState() {
    controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 5),
    )..addListener(() {
        setState(() {});
      });
    // controller.repeat(reverse: true);

    users = this.getUsersLIst();
    //  / getData();

    super.initState();
    getData();
  }

  Future getData() async {
    var url = 'https://XXX.cafe24.com/api/list/PET/DATA';
    var url2 = Uri.parse(url);
    AuthProvider authProvider = context.read<AuthProvider>();
    var currentUserId = authProvider.getUserFirebaseId()!;

    Map<String, String> headers = {
      'x-auth-token': 'widget.token',
      'x-request-id': currentUserId
    };
    http.Response response = await http.get(url2, headers: headers);

    var data = jsonDecode(response.body);
    //Add your data to stream

    data['rows'].sort((a, b) {
      // print(a['순서']);
      // print(b['순서']);
      return a['순서'].compareTo(b['순서']) as int;
    });

    List arr = data['rows'];
    /*
    arr.where((e) {
      return e['승인유무'] == 'N';
    });
*/
    List a = [];
    for (var e in arr) {
      if (e['승인유무'] != 'N') a.add(e);
    }
    setState(() {
      jsonPetList = arr;
    });
  }

  Future<List<Auction3>> getUsersLIst() async {
    return await DatabaseHandler().getAllUsers();
  }

  late Future<List<Auction3>> users;
  int _count = 0;
  final descTextStyle = TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.w800,
    fontFamily: 'Roboto',
    letterSpacing: 0.5,
    fontSize: 18,
    height: 2,
  );
  var _visable = false;
  var secondaryTextColor = Colors.white;
  var primaryTextColor = Colors.black;
  late PickedFile _imageFile;
  File? avatarImageFile;
  bool isLoading = false;
  TextEditingController pet_name = TextEditingController();
  TextEditingController pet_birthday = TextEditingController();
  TextEditingController pet_gender = TextEditingController();
  TextEditingController pet_breed = TextEditingController();
  TextEditingController pet_chip = TextEditingController();
  late AuthProvider authProvider;

  List jsonPetList = [
    ['낑낑이1', 'images/pet/intro1.png'],
    ['낑낑이2', 'images/pet/intro2.png'],
    ['낑낑이3', 'images/pet/intro3.png'],
    ['낑낑이4', 'images/pet/intro4.png'],
  ];

  var fileData = "";
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  // 카메라/갤러리에서 사진 가져올 때 사용함 (image_picker)
  final ImagePicker _picker = ImagePicker();
  final CarouselController _controller = CarouselController();
  @override
  Widget build(BuildContext context) {
    authProvider = Provider.of<AuthProvider>(context);

    Future<http.Response> sendTokenMessage(String id) {
      return http.post(
        Uri.parse(
            'https://iukj.cafe24.com/SETDATA/petbutler/MENU_MGT_S005_S100'),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(<String, String>{
          "mb1": id,
          "mb2": pet_name.text,
          "mb3": pet_birthday.text,
          "mb4": pet_gender.text,
          "mb5": pet_breed.text,
          "mb6": pet_chip.text,
          "mb7": fileData,
        }),
      );
    }

    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.transparent,
          bottomOpacity: 0.0,
          elevation: 0.0, 
          leading: IconButton(
            icon: const Icon(Icons.add_a_photo),
            tooltip: '사진등록',
            onPressed: () {},
          ),
          actions: <Widget>[
            Center(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(0, 0, 8, 0),
                child: InkWell(
                  child: TextButton(
                    style: ButtonStyle(
                      backgroundColor:
                          MaterialStateProperty.resolveWith<Color?>(
                              (Set<MaterialState> states) {
                        return const Color.fromARGB(
                            255, 33, 31, 31); // Defer to the widget's default.
                      }),
                    ),
                    onPressed: () async {
                      if (_formKey.currentState!.validate()) {
                        if (authProvider.getUserFirebaseId()?.isNotEmpty ==
                            true) {
                          var currentUserId = authProvider.getUserFirebaseId()!;
                          sendTokenMessage(currentUserId);
                        }
                      }
                    },
                    child: const Text(
                      '등록',
                      style: TextStyle(
                        color: Color.fromARGB(255, 248, 246, 246),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            Center(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(0, 0, 8, 0),
                child: InkWell(
                  child: TextButton(
                    style: ButtonStyle(
                      backgroundColor:
                          MaterialStateProperty.resolveWith<Color?>(
                              (Set<MaterialState> states) {
                        return const Color.fromARGB(
                            255, 33, 31, 31); // Defer to the widget's default.
                      }),
                    ),
                    onPressed: () async {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => RenderCard(),
                        ),
                      );
                    },
                    child: const Text(
                      '카드놀이',
                      style: TextStyle(
                        color: Color.fromARGB(255, 248, 246, 246),
                      ),
                    ),
                  ),
                ),
              ),
            ),
            Center(
                child: Padding(
                    padding: const EdgeInsets.fromLTRB(0, 0, 8, 0),
                    child: InkWell(
                        child: TextButton(
                      style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.resolveWith<Color?>(
                                (Set<MaterialState> states) {
                          return const Color.fromARGB(255, 252, 85, 2);
                          ; // Defer to the widget's default.
                        }),
                      ),
                      onPressed: () async {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                            builder: (context) => MemoBody(
                              arguments: MemoPageArguments(
                                peerId: 'memo001',
                                peerAvatar: '',
                                peerNickname: '메모',
                                token: '',
                              ),
                            ),
                          ),
                        );
                      },
                      child: const Text('메모',
                          style: TextStyle(
                            color: Color.fromARGB(255, 253, 252, 252),
                          )),
                    )))),
          ],
        ),
        // We're using a Builder here so we have a context that is below the Scaffold
        // to allow calling Scaffold.of(context) so we can show a snackbar.

        body: Builder(builder: (BuildContext context) {
          DatabaseHandler dbHandler = DatabaseHandler();

          return DefaultTextStyle(
            style: Theme.of(context).textTheme.bodyText2!,
            child: LayoutBuilder(
              builder:
                  (BuildContext context, BoxConstraints viewportConstraints) {
                return SingleChildScrollView(
                    child: ConstrainedBox(
                  constraints: BoxConstraints(
                    minHeight: viewportConstraints.minHeight,
                  ),
                  child: Form(
                    key: _formKey,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: <Widget>[
                        SizedBox(
                            height: 330,
                            child: petList(_controller, jsonPetList)),
                        const SizedBox(height: 20),
                        profileImage(1),
                        const SizedBox(height: 20),
                        const Text('우리집 반려견 사진을 등록해주세요',
                            style: TextStyle(
                                color: Colors.black54,
                                fontWeight: FontWeight.normal,
                                fontFamily: 'S-Core',
                                fontSize: 20.0)),
                        itemTextField(Icons.border_color, pet_name, "이름"),
                        itemTextField(Icons.hub, pet_gender, "성별"),
                        itemTextField(Icons.cake, pet_birthday, "생일"),
                        itemTextField(Icons.share, pet_breed, "견종"),
                        itemTextField(Icons.local_offer, pet_chip, "간단소개"),
                        Container(
                          // A fixed-height child.
                          color:
                              const Color.fromARGB(255, 251, 92, 92), // Yellow
                          height: 30.0,
                          alignment: Alignment.center,
                          padding: const EdgeInsets.all(5),
                          child: const Text(' 펫 리스트 ',
                              style: TextStyle(
                                color: Colors.white,
                              )),
                        ),
                        SizedBox(
                          height: 400,
                          child: FutureBuilder(
                              future: users,
                              builder: (context, snapshot) {
                                if (snapshot.hasData) {
                                  var usersList =
                                      snapshot.data as List<Auction3>;
                                  return ListView.builder(
                                      itemCount: usersList.length,
                                      itemBuilder:
                                          (BuildContext context, int index) {
                                        Auction3 user = usersList[index];
                                        return ListTile(
                                          title: TextButton(
                                              onPressed: () {},
                                              child: Align(
                                                  alignment:
                                                      Alignment.centerLeft,
                                                  child: Text(
                                                    textAlign: TextAlign.left,
                                                    "${user.sbjt}    (${user.aucM1})",
                                                    style: const TextStyle(
                                                        color: Colors.black54),
                                                  ))),
                                          trailing: IconButton(
                                            onPressed: () {
                                              _delete(context, dbHandler, user);
                                            },
                                            icon: const Icon(Icons.delete),
                                          ),
                                        );
                                      });
                                } else {
                                  return CircularProgressIndicator(
                                    value: controller.lowerBound,
                                    semanticsLabel:
                                        'Circular progress indicator',
                                  );
                                }
                              }),
                        ),
                      ],
                    ),
                  ),
                ));
              },
            ),
          );
        }));
  }

  bool _isShown = true;

  void _delete(BuildContext context, dbHandler, user) {
    showCupertinoDialog(
        context: context,
        builder: (BuildContext ctx) {
          return CupertinoAlertDialog(
            title: const Text('삭제하기'),
            content: const Text('해당물건을 삭제하시겠습니까?'),
            actions: [
              // The "Yes" button
              CupertinoDialogAction(
                onPressed: () {
                  dbHandler.deleteUser(user.aucNo);

                  Navigator.of(context).pop();
                  initState();
                  setState(() {});
                },
                child: const Text('삭제'),
                isDefaultAction: true,
                isDestructiveAction: true,
              ),
              // The "No" button
              CupertinoDialogAction(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('취소'),
                isDefaultAction: false,
                isDestructiveAction: false,
              )
            ],
          );
        });
  }

  Widget profileImage(index) {
    ImageProvider aa;
    return Center(
      child: Stack(
        children: <Widget>[
          avatarImageFile == null
              ? CircleAvatar(
                  radius: 80,
                  backgroundImage:
                      AssetImage('images/pet/intro/intro$index.png'))
              : CircleAvatar(
                  radius: 80,
                  backgroundImage: FileImage(avatarImageFile!),
                ),
          Positioned(
              bottom: 20,
              right: 20,
              child: InkWell(
                onTap: () async {
                  final pickedFile =
                      await _picker.getImage(source: ImageSource.camera);

                  File? image;
                  if (pickedFile != null) {
                    image = File(pickedFile.path);
                  }
                  if (image != null) {
                    setState(() {
                      avatarImageFile = image;
                      isLoading = true;
                    });
                    // uploadFile();
                  }

                  /*showModalBottomSheet(
                      context: context, builder: ((builder) => bottomSheet()));
                      */
                },
                child: Icon(
                  Icons.photo_camera,
                  color: secondaryTextColor,
                  size: 40,
                ),
              ))
        ],
      ),
    );
  }

  Widget itemTextField(IconData icon, TextEditingController ctr, String name) {
    return Container(
        // A fixed-height child.
        color: Colors.white, // Yellow

        // height: 50.0,
        alignment: Alignment.center,
        padding: const EdgeInsets.fromLTRB(50, 0, 50, 0),
        child: TextFormField(
          controller: ctr,
          validator: (val) {
            // ignore: curly_braces_in_flow_control_structures
            if (name == '이름') if (val!.isEmpty) {
              return '$name 필수사항입니다.';
            } else {
              return null;
            }

            return null;
          },
          decoration: InputDecoration(
              prefixIcon: Icon(
                icon,
                color: primaryTextColor,
              ),
              //  labelText: '이름',
              hintText: name),
        ));
  }

  Widget itemTextView(IconData icon, String name) {
    return Container(
        // A fixed-height child.
        color: Colors.white, // Yellow

        // height: 50.0,
        alignment: Alignment.center,
        padding: const EdgeInsets.fromLTRB(0, 3, 0, 0),
        child: Text(name, style: const TextStyle(fontSize: 15.0)));
  }

  String doubleToString(double d) {
    return chage000(d);
  }

  String doubleNotIntToString(double d) {
    // d=Math.round(d*100/11)/100;
    return (d.toString());
  }

  double nullChangeDoubleValue(String editText) {
    return double.parse(editText);
  }

  String chage000(double str) {
    // Thousand-separator
    var f = NumberFormat('###,###,###,###.##');
    return f.format(str);
  }

  int _current = 0;
  Widget petList(_controller, List TipsList) {
    return Column(children: [
      Expanded(
          child: CarouselSlider(
        carouselController: _controller,
        options: CarouselOptions(
            height: 400,
            scrollDirection: Axis.horizontal,
            enlargeCenterPage: true,
            viewportFraction: 1.0,
            onPageChanged: (index, reason) {
              setState(() {
                _current = index;
              });
            }),
        items: List.generate(TipsList.length, (i) {
          int index = i;
          return Builder(
            builder: (BuildContext context) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Expanded(
                        child: Column(
                          children: [
                            const Chip(
                              label: Text(
                                ' 낑낑이 ',
                                style: TextStyle(
                                    color: Colors.white, fontSize: 15.0),
                              ),
                              backgroundColor: Color.fromARGB(255, 90, 91, 91),
                            ),
                            SizedBox(
                              width: MediaQuery.of(context).size.width - 50,
                              child: Card(
                                  shape: RoundedRectangleBorder(
                                    //모서리를 둥글게 하기 위해 사용
                                    borderRadius: BorderRadius.circular(16.0),
                                  ),
                                  elevation: 4.0, //그림자 깊이
                                  child: Column(
                                    children: [
                                      profileImage(index),
                                      itemTextView(Icons.border_color,
                                          "성별:남아 / 생일: 2020.12.25"),
                                      itemTextView(Icons.border_color,
                                          "견종: 푸들 / 외장칩: 231424234"),
                                      SizedBox(height: 10)
                                    ],
                                  )),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ],
              );
            },
          );
        }).toList(),
      )),
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: List.generate(TipsList.length, (i) {
          int index = i;
          return GestureDetector(
            onTap: () => _controller.animateToPage(i),
            child: Container(
              width: 12.0,
              height: 12.0,
              margin:
                  const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0),
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: (Theme.of(context).brightness == Brightness.dark
                          ? Colors.white
                          : Colors.black)
                      .withOpacity(_current == i ? 0.9 : 0.4)),
            ),
          );
        }).toList(),
      ),
    ]);
  }
}

Widget perNumber(String str, labelTextStyle, TextEditingController value) =>
    Row(
      children: <Widget>[
        Container(
          margin: const EdgeInsets.all(5),
          //padding: EdgeInsets.fromLTRB(10, 20, 30, 40),
          child: SizedBox(height: 30, width: 100, child: Text(str)),
        ),

        const SizedBox(
          height: 20,
          width: 10,
          //child: Container(color: Colors.blue),
        ), //container

        SizedBox(
          height: 30,
          width: 150,
          child: TextField(
            //obscureText: true,
            controller: value,
            keyboardType: TextInputType.number,
            //  inputFormatters: [FilteringTextInputFormatter.],
            decoration: InputDecoration(
              border: const OutlineInputBorder(),
              labelText: '금액',
              labelStyle: labelTextStyle,
            ),
          ),
        ),
        //container
      ], //widget
    );

 

 

728x90
반응형
Comments