Notice
Recent Posts
Recent Comments
Link
250x250
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- 플러터#
- 쇼핑몰관리시스템#매입관리#시트메타#매입채널#엑셀업로드
- 마이봇#문서챗봇#PDF#TEXT#유투브#챗봇만들기#랭체인# langchain#벡터데이터#자료검색#챗GPT#GPT4#챗지피티
- 펫버틀러#서버연동#프로필등록#로그인서버연동#이미지#동영상#업로드용 화면#앱개발#플러터#반려생활#로딩바#loading bar#
- ax5#tree#grid#단계별 펼치기# depth #시트메타
- 커피#그라인더#통돌이 오픈 #로스팅#드립커피#생두#원두
- 시트메타#관리시스템#테이블연동#품목관리
- 마이봇#API 설정
- fcm#메세지전송#안드로이드메세지#플러터메세지전송
- PDF#챗봇검색#서비스#GPT4#PGT3.5#GPT#랭체인#챗봇#CHATBOT#LLM#문서검색
- 로우코드#lowcode#erp#관리시스템#시트메이트#시트메타#엑셀업로드#엑셀다운로드#그리드#데이터관리#생산관리시스템#로그관리#히스토리#입력체크
- 마이봇#핸드폰대체#
- mediasaop#webrtc#미디어서버#
- 로우코드#ERP#관리시스템#상품관리#선택박스#자동화프로그램
- 마이봇#pdf챗봇#상담챗봇#faq챗봇#chatgpt#랭체인#llm
- 마이봇#챗봇
- 광동온더그린#프랜즈#가상CC#스크린골프#
- 플러터#sms#mms#문자보내기
- figma#flutter#dhwise#피그마#플러터#피그마 to 플러터 #figma to flutter
- 임대사업자#리걸테크#legaltech#마이봇#챗봇#법률챗봇#임대사업자챗봇#chatgpt#
- PDF검색#PDF검색챗봇#NEXTJS#스터디#스타트업#랭체이#langchain#prisma#sqlite#
- flutter#채팅창@메모창#url링크#날짜추가
- flutterfire configure#파이어베이스#플러터
- 마이봇#chatgpt#ai#인공지능
- firebase#message#메세지#플러터#안드로이드
- flutter#ios#앱개발#마이봇#
- 마이봇#아이폰#아이폰심사#IT고시#
- flutter#sqlite#chatGPT#
- postgres#vector
- #창작#SNS#스포츠#반려동물#연애#과제#레시피#활동#건강#운세#글쓰기#비즈니스 #AI비서#챗GPT#CHATGPT
Archives
- Today
- Total
혼자서 앱 만드는 개발자 함께하는 AI 세상
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 12 일차 (프로필화면에 달력적용) 본문
반응형
- 펫버틀러 팻다이어리를 추가하고 메인화면에 일정관리와 다이어리 작성시 볼 수 있도록 수정해 보았다.
- 관련 패키지를 추가하고 플러터에서 유명한 Table_Calendar 를 사용해보고 한글 설정 해보았다.
- https://github.com/aleksanderwozniak/table_calendar
- 우선 간단하게 추가하고 이벤트를 등록할 예정이다.
- 추가는 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
반응형
'펫버틀러' 카테고리의 다른 글
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 14 일차 (파일백업을 위해 퍼미션 체크) (2) | 2023.01.23 |
---|---|
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 13 일차 (설정 화면 만들기) (0) | 2023.01.23 |
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 11 일차 (동영상 썸네일 / 플레이어 적용 ) (0) | 2023.01.02 |
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 10 일차 (이미지/동영상 첨부 업로드 시 로딩 바 prograss loading bar ) (0) | 2023.01.01 |
[펫버틀러] 반려 동물 고민 상담 앱 - 개발 9 일차 (메모 이미지 동영상 첨부 화면 개발 / 로그인 토큰 처리 확인 ) (0) | 2022.12.28 |
Comments