'๋ค์ฟ ์' ํ๋ก ํธ์๋ ๋ ํฌ์งํ ๋ฆฌ์ ๋๋ค!
FE | AI & BE |
---|---|
@jjjooo-it | @ha-seungwon |
'๋ชจ๋ฐ์ผ ํ๋ซํผ' ์์ ์ ๋ค์ผ๋ฉฐ ์งํํ ํ๋ก์ ํธ์ ๋๋ค. 'DAKUA'๋ ์ ํ์์ ์ํ AI ์์ ์์ฝ ์ดํ์ ๋๋ค. ๊ตญ๋ด ์ธ๊ตญ์ธ ์ ํ์์ ์๋ ์ฆ๊ฐํ๋ ์ถ์ธ์ด์ง๋ง, ํ๊ตญ์ด๋ก ์งํ๋๋ ์์ ์ ์ดํดํ์ง ๋ชปํด ์ด๋ ค์์ ๊ฒช๋ ์ ํ์์ด ๋ง์ต๋๋ค. DAKUA๋ ์์ ๋ น์ ํ์ผ์ ์ ๋ก๋ ์ ์ฌ๋ฌ ํํ์ ์์ฝ๋ณธ์ ์ ๊ณตํจ์ผ๋ก์จ ์ ํ์๋ค์ ์์ ์ดํด๋๋ฅผ ๋์ด๊ณ ํ๊ตญ ์ํ์ ์ํํ๊ฒ ์ ์ํ ์ ์๋๋ก ๋์์ค ์ ์์ต๋๋ค.
- ํต์ฌ ๊ธฐ๋ฅ
- ์์ ๋ น์ ํ์ผ ์ ๋ก๋ ํ๊ธฐ
- ์๋ ํด๋ผ์ฐ๋ / ํ ์ค ์์ฝ / ์ ์ฒด ํ ์คํธ ํํ๋ก ์ ๋ฆฌํ์ฌ ์ ๊ณตํ๊ธฐ
- ํด๋๋ฅผ ์์ฑํ์ฌ ์ง๋ ์์ฝ ๊ธฐ๋ก์ ์ ์ฅํ๊ธฐ
- ์ค๊ตญ์ด ์ธ์ด ์ค์ ํ๊ธฐ
- dataSource : ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์์ญ
- dbHelper : Sqlite ์ฌ์ฉ์ ์ํ DB ์ ์ด
- model : ๋ฐ์ดํฐ ์ค๊ณ
- view(front/history/home/setting/widget) : ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ์์ญ
- viewModel : view์ ์ํ ๊ด๋ฆฌ
SQLite๋ฅผ ํตํ ํ์๊ฐ์ /๋ก๊ทธ์ธ/๋ก๊ทธ์์ ๊ตฌํ SQLite
static Future _initDatabaseFactory() async {
sqfliteFfiInit();
databaseFactory = databaseFactoryFfiWeb;
}
static initDB() async {
String path = await getDatabasesPath();
return openDatabase(
join(path, 'my_database.db'),
onCreate: (db, version) {
return db.execute(
"CREATE TABLE users(id TEXT PRIMARY KEY, username TEXT, password TEXT, name TEXT, country TEXT, userID TEXT)",
);
},
version: 1,
);
}
- FilteringTextInputFormatter๋ฅผ ์ด์ฉ ๊ณต์๋ฌธ์ ์ฐธ๊ณ
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'^[a-zA-Z]+$')),
],
...
bool isAllowed = RegExp(r'^[a-zA-Z]+$').hasMatch(value);
if (!isAllowed) {
setState(() {
switch (field) {
case 'username':
nameError = '์ฌ๋ฐ๋ฅธ ์
๋ ฅ๊ฐ์ ๋ฃ์ด์ฃผ์ธ์.';
break;
case 'id':
idError = '์ฌ๋ฐ๋ฅธ ์
๋ ฅ๊ฐ์ ๋ฃ์ด์ฃผ์ธ์.';
break;
case 'password':
passwordError = '์ฌ๋ฐ๋ฅธ ์
๋ ฅ๊ฐ์ ๋ฃ์ด์ฃผ์ธ์.';
break;
}
});
}
- PageRouteBuilder๋ฅผ ์ด์ฉ ๊ณต์๋ฌธ์ ์ฐธ๊ณ
- ์์ํ ๋ํ๋๋๋ก
Navigator.pushReplacement(
context,
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 1500),
pageBuilder: (context, animation, secondaryAnimation) => MiddlePage(user: user),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
var curve = Curves.easeInOut;
//ํ๋ฉด ์ ํ ์ ๋๋ฉ์ด์
var fadeAnimation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: animation,
curve: Interval(0.0, 0.5, curve: curve), // 0๋ถํฐ 0.5๊น์ง๋ ํ๋ ค์ง
));
return FadeTransition(
opacity: fadeAnimation,
child: child,
);
},
),
);
}
- carousel_slider ํจํค์ง ์ด์ฉ carousel_slider
- ์ฌ๋ฌ ์ต์ ์ ์ง์ ํ ์ ์์
options: CarouselOptions(
height: 100,
viewportFraction: 1,
initialPage: 0,
enableInfiniteScroll: true, //๋ฌดํ ์คํฌ๋กค ํ์ฑํ
autoPlay: true, //์๋ ์ฌ์ ํ์ฑํ
autoPlayInterval:
Duration(seconds: 10), //์๋ ์ฌ์ ๊ฐ๊ฒฉ
autoPlayAnimationDuration:
Duration(milliseconds: 8000), //์๋ ์ฌ์ ์ ๋๋ฉ์ด์
์๊ฐ
autoPlayCurve: Curves.fastOutSlowIn,
scrollDirection: Axis.horizontal,
),
- isExpand ๋ณ์์ ExpansionPanel์ ์ด์ฉ ๊ณต์๋ฌธ์ ์ฐธ๊ณ
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: ExpansionPanelList(
expandedHeaderPadding: EdgeInsets.zero,
expansionCallback: (int index, bool isExpanded) {
setState(() {
_isExpanded = !_isExpanded;
});
},
children: [
ExpansionPanel(
headerBuilder: (BuildContext context, bool isExpanded) {
return ListTile(
title: Text(
_isExpanded? aiViewModel.aiSummary?.full_text_data ?? 'no_full'.tr()
: aiViewModel.aiSummary!.text_data ?? 'no_summary'.tr(),
style: TextStyle(fontSize: 16.0),
textAlign: TextAlign.center,
),
);
},
body: _isExpanded?
Container(
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: Text(
"",
style: TextStyle(fontSize: 0.0),
textAlign: TextAlign.center,
),
)
: Container(),
isExpanded: _isExpanded,
),
],
),
),
- easy_localization ํจํค์ง ์ด์ฉ easy_localization
runApp(
EasyLocalization(
supportedLocales: [Locale('ko', 'KR'), Locale('zh', 'CN')],
path: 'assets/translations',
fallbackLocale: Locale('ko', 'KR'), // ๊ธฐ๋ณธ ์ธ์ด
child: const MyApp(),
),
);
- flutter_spinkit ํจํค์ง ์ด์ฉ flutter_spinkit
SpinKitWave(
itemBuilder: (context, index) {
return const DecoratedBox(
decoration: BoxDecoration(color: Colors.green),
);
},
),