본문 바로가기
TIL

팀프로젝트 : 위치기반 채팅앱

by chengzior 2024. 12. 11.

1. 맡은 부분: 마이페이지

2. 기능 
- 사용자 아이디 표시
- 등록된 반려견 정보 불러와서 그리드뷰에 표시
- 반려견 정보 등록


디렉토리 구조

  • pages
    • my_page
      • my_page.dart
      • my_page_view_model.dart
    • my_page_write
      • my_page_write.dart
      • my_page_write_view_model.dart

기존 강의에서 도움이 될 만한 부분

1. 사용자 아이디 표시

class MyProfileBox extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer(builder: (context, ref, child) {
      final user = ref.watch(userGlobalViewModel);
          Expanded(
            child: user == null
                ? SizedBox()
                : Text(
                    user.username,

user가 null이면 빈 Sizedbox,
null이 아니면 이름 가져와서 표시

반려견 정보도 이런 식으로 가져오면 될 듯.

2. 반려견 정보 등록

1) 텍스트 컨트롤러로 값 받아오기

 

class ProductWritePage extends StatefulWidget {
  ProductWritePage(this.product);
  Product? product;

  @override
  State<ProductWritePage> createState() => _ProductWritePageState();
}

class _ProductWritePageState extends State<ProductWritePage> {
  late final titleController =
      TextEditingController(text: widget.product?.title);
  late final priceController =
      TextEditingController(text: widget.product?.price.toString() ?? '');
  late final contentController =
      TextEditingController(text: widget.product?.content ?? '');
  final formKey = GlobalKey<FormState>();

  @override
  void dispose() {
    titleController.dispose();
    priceController.dispose();
    contentController.dispose();
    super.dispose();
  }

 

 


2) 작성 위젯 구현 및 작성 완료하면 validator로 빠진 내용 없는지 검사

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).unfocus();
      },
      child: Scaffold(
        appBar: AppBar(),
        body: Form(
          key: formKey,
          child: ListView(
            padding: EdgeInsets.all(20),
            children: [
              ProductWritePictureArea(widget.product),
              SizedBox(
                height: 20,
              ),
              ProductCategoryBox(widget.product),
              SizedBox(
                height: 20,
              ),
              TextFormField(
                controller: titleController,
                decoration: InputDecoration(
                  hintText: '상품명을 입력해주세요',
                ),
                validator: ValidatorUtil.validaorTitle,
              ),
              SizedBox(
                height: 20,
              ),
              TextFormField(
                controller: priceController,
                keyboardType: TextInputType.number,
                //숫자 키패드로 구현했으나 블루투스 키보드로 문자를 입력하는 경우 대비
                inputFormatters: [FilteringTextInputFormatter.digitsOnly],
                decoration: InputDecoration(
                  hintText: '가격을 입력해주세요',
                ),
                validator: ValidatorUtil.validaorPrice,
              ),
              SizedBox(
                height: 20,
              ),
              TextFormField(
                controller: contentController,
                decoration: InputDecoration(
                  hintText: '내용을 입력해주세요',
                ),
                validator: ValidatorUtil.validaorContent,
              ),
              SizedBox(
                height: 20,
              ),
              Consumer(builder: (context, ref, child) {
                return ElevatedButton(
                  onPressed: () {
                    onWriteDone(ref);
                  },
                  child: Text('작성완료'),
                );
              }),
            ],
          ),
        ),
      ),
    );
  }
}


3) 마이페이지 업데이트 하기

  void onWriteDone(WidgetRef ref) async {
    formKey.currentState?.validate();
    if (formKey.currentState?.validate() ?? false) {
      final vm = ref.read(productWriteViewModel(widget.product).notifier);
      final result = await vm.upload(
        title: titleController.text,
        content: contentController.text,
        price: int.parse(priceController.text),
      );
      if (result == true) {
        //홈탭 업데이트
        ref.read(homeTabViewModel.notifier).fetchProducts();
        //수정이면 디테일 페이지 업데이트
        if (widget.product != null) {
          ref.read(
            productDetailViewModel(widget.product!.id).notifier,
          );
        }
        Navigator.pop(context);
      }
    }
  }


2-1. validatorUtil

class ValidatorUtil {
  
  //static으로 선언하면 클래스 생성하지 않아도 사용 가능!
  static String? ValidatorId(String? value){
    if(value?.trim().isEmpty?? true){
      return "아이디를 입력해주세요";
    }
    if(value!.length<2){
      return "아이디는 2글자 이상이어야 합니다.";
    }
    return null;
  }
  static String? ValidatorNickname(String? value){
    if(value?.trim().isEmpty?? true){
      return "닉네임을 입력해주세요";
    }
    if(value!.length<2){
      return "닉네임은 2글자 이상이어야 합니다.";
    }
    return null;
  }
  static String? ValidatorPassword(String? value){
    if(value?.trim().isEmpty?? true){
      return "비밀번호를 입력해주세요";
    }
    if(value!.length<2){
      return "비밀번호는 2글자 이상이어야 합니다.";
    }
    return null;
  }

  static String? validaorTitle(String? value){
    if(value?.trim().isEmpty?? true){
      return "상품명을 입력해주세요";
    }
    if(value!.length<2){
      return "상품명은 2글자 이상이어야 합니다.";
    }
    return null;
  }

  static String? validaorPrice(String? value){
    if(value?.trim().isEmpty?? true){
      return "가격을 입력해주세요";
    }
    return null;
  }

  static String? validaorContent(String? value){
    if(value?.trim().isEmpty?? true){
      return "상품내용을 입력해주세요";
    }
    return null;
  }
  
}


2-2) 반려견 정보 등록 모델

pages> > product_write> product_write > product_write_view_model.dart
 Future<bool?> upload({
    required String title,
    required String content,
    required int price,
  }) async {
    if (state.imageFiles.isEmpty) {
      return null;
    }
    if (state.selectedCategory == null) {
      return null;
    }
    //수정
    if (arg != null) {
      final result = await productRepository.update(
          id: arg!.id,
          title: title,
          content: content,
          imageFileIdList: state.imageFiles
              .map(
                (e) => e.id,
              )
              .toList(),
          categoryId: state.selectedCategory!.id,
          price: price);
      return result;
    } else {
      //생성
      final result = await productRepository.create(
          title: title,
          content: content,
          imageFileIdList: state.imageFiles
              .map(
                (e) => e.id,
              )
              .toList(),
          categoryId: state.selectedCategory!.id,
          price: price);
      return result != null;
    }
  }