package web.fridge.domain.food.repository;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import web.fridge.domain.food.entity.FoodStatus;
import web.fridge.domain.member.entity.Member;
import javax.persistence.EntityManager;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static web.fridge.domain.family.entity.QFamily.family;
import static web.fridge.domain.food.entity.QFood.food;
import static web.fridge.domain.fridge.entity.QFridge.fridge;
@Repository
@RequiredArgsConstructor
public class FoodTrackingRepository {
private final EntityManager em;
private final JPAQueryFactory queryFactory;
public Map<FoodStatus, Long> countFoodGroupByStatusAtCurrentMonth(){
List<Tuple> queryResult = queryFactory
.select(food.status, food.count())
.from(food)
.leftJoin(fridge).on(food.fridge.fridgeId.eq(fridge.fridgeId))
.leftJoin(family).on(family.fridge.fridgeId.eq(fridge.fridgeId))
.where(
food.createdAt.eq(LocalDateTime.now().withMonth(LocalDate.now().getMonthValue()))
)
.groupBy(food.status)
.fetch();
Map<FoodStatus, Long> result = new HashMap<>();
for (Tuple tuple : queryResult) {
result.put(tuple.get(food.status), tuple.get(food.count()));
}
return result;
}
public Map<FoodStatus, Long> countFoodCreatedByMemberAtCurrentMonth(Member member){
List<Tuple> queryResult = queryFactory
.select(food.status, food.count())
.from(food)
.leftJoin(fridge).on(food.fridge.fridgeId.eq(fridge.fridgeId))
.leftJoin(family).on(family.fridge.fridgeId.eq(fridge.fridgeId))
.where(family.member.eq(member),
food.createdAt.eq(LocalDateTime.now().withMonth(LocalDate.now().getMonthValue()))
)
.groupBy(food.status)
.fetch();
Map<FoodStatus, Long> result = new HashMap<>();
for (Tuple tuple : queryResult) {
result.put(tuple.get(food.status), tuple.get(food.count()));
}
return result;
}
}
1. [Flutter] iOS 업데이트 때문에 빌드 방식이 바뀌어 모듈 재설정
2. [Flutter] http 요청하기
class FridgePage extends StatefulWidget {
const FridgePage({super.key});
@override
State<FridgePage> createState() => _FridgePageState();
}
class _FridgePageState extends State<FridgePage> {
List info = [];
@override
void initState() {
super.initState();
setState(() {
loadingFoodInfo();
});
}
@override
void didChangeDependencies() {
setState(() {
loadingFoodInfo();
});
}
static final storage = FlutterSecureStorage();
void loadingFoodInfo() async {
final apiUrl = Uri.http('localhost:8080', 'food/fridge/1');
final Map<String, String> tokens = await storage.readAll();
print(tokens['accessToken']);
var foodInfo = await http.get(
apiUrl,
headers: {
"Content-Type": "application/json",
"Authorization": tokens['accessToken'].toString()
},
);
info = jsonDecode(utf8.decode(foodInfo.bodyBytes));
print(info[info.length - 1].toString());
}
3. [Flutter] Flutter_Secure_Storage를 활용한 jwt 로그인 자동화
import 'dart:convert';
import 'dart:io';
import 'package:client/src/model/Auth.dart';
import 'package:client/src/model/auth_platform.dart';
import 'package:client/src/model/page/login_page_model.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:client/src/pages/fridge_page.dart';
import 'package:client/src/pages/route/main_page.dart';
import 'package:flutter/material.dart';
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
import 'package:http/http.dart' as http;
import 'package:client/src/pages/fridge_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:simple_gradient_text/simple_gradient_text.dart';
import '../../flutter_flow/flutter_flow_model.dart';
import '../../flutter_flow/flutter_flow_theme.dart';
import '../../flutter_flow/flutter_flow_widgets.dart';
import '../widgets/setting/kakako_button/kakako_button_widget.dart';
class LogInPage extends StatefulWidget {
const LogInPage({super.key});
@override
State<LogInPage> createState() => _LogInPageState();
}
class _LogInPageState extends State<LogInPage> {
late LoginPageModel _model;
AuthorizationPlatform _platform = AuthorizationPlatform.none;
static final storage = FlutterSecureStorage();
dynamic accessToken = '';
dynamic refreshToken = '';
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_asyncMethod();
});
_model = createModel(context, () => LoginPageModel());
}
_asyncMethod() async {
accessToken = await storage.read(key: 'acessToken');
refreshToken = await storage.read(key: 'refreshToken');
if (accessToken != null && refreshToken != null) {
Navigator.pushNamed(context, '/main');
}
}
void singInWithKakao() async {
try {
bool isInstalled = await isKakaoTalkInstalled();
OAuthToken token = isInstalled
? await UserApi.instance.loginWithKakaoTalk()
: await UserApi.instance.loginWithKakaoAccount();
final url = Uri.https('kapi.kakao.com', 'v2/user/me');
final response = await http.get(
url,
headers: {
HttpHeaders.authorizationHeader: 'Bearer ${token.accessToken}'
},
);
final profile = jsonDecode(response.body);
// final apiUrl = Uri.http('localhost:8080', 'login/kakao');
// final apiResponse = await http.post(apiUrl, body: response.body);
// if (apiResponse.statusCode == 200) {}
setState(() {
_platform = AuthorizationPlatform.kakao;
});
Navigator.push(
context, MaterialPageRoute(builder: (context) => MainPage()));
} catch (error) {
print("카카오톡으로 로그인에 실패하였습니다.");
print(error);
}
}
void signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
if (googleUser != null) {
print(googleUser);
final apiUrl = Uri.https('api.zefridge.xyz', 'login/google');
Map<String, dynamic> googleJsonRequest = {
'id': googleUser.id,
'name': googleUser.displayName,
'profile': googleUser.photoUrl,
'email': googleUser.email
};
final apiResponse = await http.post(apiUrl,
headers: {"Content-Type": "application/json"},
body: jsonEncode(googleJsonRequest));
var authResponse = jsonDecode(utf8.decode(apiResponse.bodyBytes));
print(authResponse);
Auth auth =
Auth(authResponse['accessToken'], authResponse['refreshToken']);
print(authResponse['accessToken']);
storage.write(key: 'accessToken', value: auth.accessToken.toString());
storage.write(key: 'refreshToken', value: auth.refreshToken.toString());
String accessToken = storage.read(key: 'accessToken').toString();
print(accessToken);
// ignore: use_build_context_synchronously
Navigator.push(
context, MaterialPageRoute(builder: (context) => MainPage()));
}
}
Widget _oauth_login_button(String path, VoidCallback onTap) {
var Image = AssetImage('assets/image/$path.png');
return Card(
// elevation: 5.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
clipBehavior: Clip.antiAlias,
child: Ink.image(
image: Image,
width: 300,
height: 60,
fit: BoxFit.fill,
child: InkWell(
onTap: onTap,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
body: Center(
child: _platform != AuthorizationPlatform.none
? Column()
: Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Align(
alignment: AlignmentDirectional(-0.4, 0.0),
child: Padding(
padding:
EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 30.0),
child: GradientText(
'Welcome ZEF,\nZero Wasted Fridge',
textAlign: TextAlign.start,
style:
FlutterFlowTheme.of(context).bodyText1.override(
fontFamily: 'Outfit',
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
colors: [
FlutterFlowTheme.of(context).primaryText,
Color(0xFF395BA9)
],
gradientDirection: GradientDirection.ltr,
gradientType: GradientType.linear,
),
),
),
Stack(
alignment: AlignmentDirectional(0.0, -0.35),
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0.0, 0.0, 0.0, 10.0),
child: FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: '네이버로 시작하기' /* 네이버로 시작하기 */,
options: FFButtonOptions(
width: 300.0,
height: 44.0,
padding: EdgeInsetsDirectional.fromSTEB(
0.0, 0.0, 0.0, 0.0),
iconPadding: EdgeInsetsDirectional.fromSTEB(
0.0, 0.0, 0.0, 0.0),
color: Color(0xFF03C75A),
textStyle: FlutterFlowTheme.of(context)
.subtitle2
.override(
fontFamily: 'Outfit',
color: Colors.white,
),
elevation: 0.0,
borderSide: BorderSide(
color: Colors.transparent,
width: 1.0,
),
borderRadius: BorderRadius.circular(8.0),
),
),
),
Align(
alignment: AlignmentDirectional(-0.7, 0.0),
child: Image.asset(
'assets/image/btnG_.png',
width: 32.0,
height: 32.0,
fit: BoxFit.cover,
),
),
],
),
Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: wrapWithModel(
model: _model.kakakoButtonModel,
updateCallback: () => setState(() {}),
child: KakakoButtonWidget(),
),
),
Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
width: 300.0,
height: 44.0,
child: Stack(
children: [
Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: FFButtonWidget(
onPressed: () {
signInWithGoogle();
},
text: 'Sign in with Google',
icon: Icon(
Icons.add,
color: Colors.transparent,
size: 20.0,
),
options: FFButtonOptions(
width: 300.0,
height: 44.0,
padding: EdgeInsetsDirectional.fromSTEB(
0.0, 0.0, 0.0, 0.0),
iconPadding: EdgeInsetsDirectional.fromSTEB(
0.0, 0.0, 8.0, 0.0),
color: Colors.white,
textStyle: GoogleFonts.getFont(
'Roboto',
color: Color(0xFF606060),
fontSize: 17.0,
),
elevation: 0.0,
borderSide: BorderSide(
color: Colors.transparent,
width: 0.0,
),
),
),
),
Align(
alignment: AlignmentDirectional(-0.9, 0.0),
child: Container(
width: 22.0,
height: 22.0,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
shape: BoxShape.circle,
),
child: Image.network(
'https://i0.wp.com/nanophorm.com/wp-content/uploads/2018/04/google-logo-icon-PNG-Transparent-Background.png?w=1000&ssl=1',
fit: BoxFit.contain,
),
),
),
],
),
),
),
],
)),
),
);
}
}
4. [SpringBoot] queryDSL 사용하기
'회고' 카테고리의 다른 글
2023 정보처리기사 3회 필기 합격 후기 / 4일 준비 (0) | 2023.07.19 |
---|---|
[TEAM 369] Flutter, SpringBoot, AWS로 효율적인 어플리케이션 구축하기 기본편 (1) | 2022.11.25 |
[이상청] 기상청 단기예보 API를 받아와서 처리하기 (0) | 2022.08.08 |
[이상청] OAuth2를 활용한 로그인, 세션 유지 방식의 실패 원인과 해결방안 (0) | 2022.08.07 |