-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: 이용약관 페이지 추가를 위한 상품 탭 레이아웃 수정 #18
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 카카오페이 가맹점 신청을 위해 임시로 데이터를 사용했습니다. 추후 서버에서 받아와 뿌릴 예정입니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,3 +38,24 @@ final daysConstant = [ | |
'토', | ||
'일', | ||
]; | ||
|
||
const String termsOfUseContents = | ||
'트티는 회원에게 콘텐츠, 상품 등을 제공하는 서비스 플랫폼입니다. 회원은 컴퓨터, 휴대전화 등 정보통신기기를 사용하여 트티가 회원에게 제공하는 서비스(이하 “서비스”)를 이용할 수 있으며, 서비스의 구체적인 내용과 이용 조건을 이용약관 및 정책, 서비스 페이지 등에서 확인할 수 있습니다.\n이용약관(이하 ”이 약관”)은 서비스 이용과 관련하여 트티와 회원 간의 권리와 의무에 대한 내용을 담고 있습니다.\n1. 계정\n1.1 회원가입\n서비스를 이용하기 위해서는 회원가입에 의하여 생성되는 계정이 필요합니다. 이와 관련하여 트티는 회원에 대한 본인 인증 절차를 진행할 수 있으며, 회원이 회원가입에 필요한 정보 제공을 거절하거나 타인 정보 또는 허위 정보를 입력하는 경우 회원가입이 진행되지 않을 수 있습니다.'; | ||
const String minorContents = | ||
'\n1.2 미성년자\n미성년자는 관련 법령에 따라 회원가입 또는 서비스이용이 제한될 수 있으며, 부모 등 법정대리인의 동의를 얻은 후 서비스이용을 위한 결제를 진행하여야 합니다. 다만 법정대리인이 동의하지 아니한 경우, 미성년자 본인 또는 법정대리인은 결제를 취소할 수 있습니다.\n'; | ||
const String updateOfAccountInfo = | ||
'1.3 계정정보의 갱신\n전자우편주소, 연락처 등 계정정보가 변경된 경우 이를 반영하는 것은 회원의 책임이며 트티의 고의 또는 과실이 없음에도 불구하고 계정정보를 갱신하지 아니하여 발생하는 불이익은 회원이 부담합니다.'; | ||
const String privacyPolicyIntroContents = | ||
'주식회사 이쿠아(이하"회사")는 『개인정보 보호법』 및 관련 법령상의 개인정보 보호규정을 준수하며, 『개인정보 보호법』에 의거한 개인정보 처리방침을 정하여 이용자 권익보호에 최선을 다하고 있습니다.\n회사는 개인정보 처리방침을 통하여 회사가 이용자로부터 제공받은 개인정보를 어떠한 용도와 방식으로 이용하고 있으며, 개인정보보호를 위해 어떠한 조치를 취하고 있는지 알려드립니다.\n'; | ||
const String privacyPolicyTableOfContents = | ||
'1. 개인정보의 처리 목적\n2. 개인정보의 처리 및 보유기간\n3. 처리하는 개인정보의 항목\n'; | ||
const String privacyPolicyPurposeOfProcessingPersonalInfo = | ||
'1. 개인정보의 처리 목적\n회사는 다음의 목적을 위하여 개인정보를 처리합니다.\n① 회원 가입 및 관리\n- 회원제 서비스 이용에 따른 본인 식별, 회원자격 유지ㆍ관리, 서비스 부정이용 방지와 비인가 사용방지, 각종 고지ㆍ통지, 불만처리 및 고객상담 등 민원 처리, 분쟁 조정을 위한 기록보존\n② 재화 또는 서비스 제공\n - 서비스 제공에 관한 계약 이행 및 서비스 제공에 따른 요금정산, 콘텐츠 제공, 구매 및 요금 결제, 환불, 물품배송, 본인인증, 요금추심\n③ 서비스 개선 및 마케팅 활용\n- 신규 서비스(제품) 개발 및 특화, 이벤트 등 홍보성 정보 전달 - 인구통계학적 특성에 따른 서비스 제공 및 광고 게재, 접속 빈도 파악, 회원의 서비스 이용에 대한 통계 분석\n'; | ||
const String privacyPolicyProcessingRetentionPeriodOfPersonalInfo = | ||
'2. 개인정보의 처리 및 보유기간\n회사는 원칙적으로 개인정보 수집 및 이용목적이 달성된 후에는 해당 정보를 지체없이 파기합니다. 다만, 관계법령의 규정에 의하여 보존할 필요가 있는 경우, 회사는 아래와 같이 관계법령에서 정한 일정한 기간 동안 회원정보를 보관하며, 이 경우 회사는 해당 개인정보를 분리하여 보관합니다.\n'; | ||
const String refundPolicyServiceOfSales = | ||
'1. 판매 서비스\n구입한 날로부터 7일 이내 이용한 경우 : 결제 대금 전액\n구입한 날로부터 14일 이내 이용한 경우 : 결제 대금의 5/10\n구입한 날로부터 21일 이내 이용한 경우 : 결제 대금의 2/10\n구입한 날로부터 30일 이후 : 없음\n'; | ||
const String refundPolicyCoachingRights = | ||
'2. 코칭권\n코칭권 이용기간 만료 전 : 결제대금 전액\n코칭권 이용기간 만료 후 : 환불 불가\n-코칭권 이용기간은 구매 당시 부여된 기간을 기준으로 합니다.'; | ||
const String refundPolicyInquiry = | ||
'트티 서비스와 관련하여 궁금하신 사항이 있으시면\n고객센터(대표번호: 010-7415-8850 / 이메일: [email protected] (평일 10:00~18:00 )로 문의 주시기 바랍니다 '; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
class CompanyInfo { | ||
final String title; | ||
final String contents; | ||
final String? subTitle; | ||
final String? subContents; | ||
final VoidCallback onTap; | ||
|
||
const CompanyInfo({ | ||
required this.title, | ||
required this.contents, | ||
this.subContents, | ||
this.subTitle, | ||
required this.onTap, | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 회사 관련 정보 객체를 만들어줬습니다. 일단은 회사 소개 관련 카드를 봤을 때 title, contents, subtitle, subcontents, ontap 메서드로 분해가 되어 이렇게 설정했습니다. |
||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/widgets.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
import 'package:go_router/go_router.dart'; | ||
import 'package:tuti/common/constraints_scaffold.dart'; | ||
import 'package:tuti/common/service/goods_provider.dart'; | ||
import 'package:tuti/common/tuti_text.dart'; | ||
import 'package:tuti/constants/color.dart'; | ||
import 'package:tuti/features/tutis/models/company_info.dart'; | ||
import 'package:tuti/features/tutis/models/goods.dart'; | ||
import 'package:tuti/features/tutis/views/goods_detail_screen.dart'; | ||
import 'package:tuti/features/tutis/views/s_terms_of_use.dart'; | ||
import 'package:tuti/features/tutis/widgets/tuti_widgets/goods_container.dart'; | ||
import 'package:tuti/features/tutis/widgets/tuti_widgets/main_banner.dart'; | ||
import 'package:tuti/features/tutis/widgets/tuti_widgets/w_company_info_card.dart'; | ||
import 'package:universal_html/js.dart'; | ||
import 'package:url_launcher/url_launcher.dart'; | ||
|
||
class PersonalBrandingScreen extends ConsumerWidget { | ||
const PersonalBrandingScreen({super.key}); | ||
|
||
static const String routeName = "personalBranding"; | ||
static const String routePath = "/personalBranding"; | ||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final goodsList = ref.watch(goodsProvider); | ||
CompanyInfo companyInfo = CompanyInfo( | ||
title: '트티', | ||
contents: '기업명: (주) 이쿠아\n 주소: 서울 강남구 테헤란로22길 15 2층\n 전화: 010.7415.8850', | ||
onTap: () { | ||
String urlPath = 'info.tuti20.com'; | ||
launchUrl( | ||
Uri.parse(urlPath), | ||
); | ||
}, | ||
); | ||
CompanyInfo customerCenter = CompanyInfo( | ||
title: '고객센터', | ||
contents: '오전 10 ~ 오후 6시(주말, 공휴일 제외)\n문의하기: 010.7415.8850', | ||
subContents: '이용약관\n\n환불 정책\n\n제휴 및 대외협력', | ||
subTitle: '개인정보처리방침', | ||
onTap: () { | ||
context.push(TermsOfUseScreen.routePath); | ||
}, | ||
); | ||
|
||
List<CompanyInfo> companyInfos = [companyInfo, customerCenter]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 회사 정보 객체를 담은 배열 생성해주었고 이를 매핑하여 회사 정보 관련 카드를 동적으로 생성합니다. |
||
|
||
return ConstraintsScaffold( | ||
child: CustomScrollView( | ||
slivers: <Widget>[ | ||
SliverAppBar( | ||
expandedHeight: 130.h, | ||
floating: false, | ||
pinned: false, | ||
flexibleSpace: FlexibleSpaceBar( | ||
background: TuTiBanner( | ||
onTap: () {}, | ||
margin: EdgeInsets.only( | ||
top: 35.h, bottom: 15.h, left: 40.w, right: 40.w), | ||
title: '오직, 트티에서만 제공하는\n2024년 당신의 커리어 고민 해결 솔루션.', | ||
subtitle: '체계적이고 알찬 개인 맞춤형 레벨업!', | ||
), | ||
), | ||
), | ||
SliverList( | ||
delegate: SliverChildBuilderDelegate( | ||
childCount: | ||
goodsList.value?.length ?? 0, // Handle null values gracefully | ||
(context, index) { | ||
if (goodsList.hasValue) { | ||
return GoodsContainer( | ||
name: goodsList.value![index].name, | ||
discountRate: goodsList.value![index].discountRate, | ||
regularPrice: goodsList.value![index].regularPrice, | ||
discountedPrice: goodsList.value![index].discountedPrice, | ||
discountPolicy: goodsList.value![index].discountPolicy, | ||
); | ||
} else if (goodsList.hasError) { | ||
return SliverToBoxAdapter( | ||
child: Text('Error: ${goodsList.error}'), | ||
); | ||
} else { | ||
return const SliverToBoxAdapter( | ||
child: CircularProgressIndicator(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. List형식으로 상품 컨테이너가 생성되고 있고 상품 컨테이너가 사용하는 Goods 정보는 서버에서 받아오는 AsyncValue 객체이기 때문에 이를 handle하기 위해 hasValue, hasError, else로 분기를 나눠 처리해습니다. |
||
); | ||
} | ||
}, | ||
), | ||
), | ||
SliverList( | ||
delegate: SliverChildBuilderDelegate( | ||
childCount: companyInfos.length, | ||
(context, index) { | ||
return CompanyInfoCard( | ||
title: companyInfos[index].title, | ||
contents: companyInfos[index].contents, | ||
subTitle: companyInfos[index].subTitle, | ||
subContents: companyInfos[index].subContents, | ||
onTap: companyInfos[index].onTap, | ||
); | ||
}, | ||
), | ||
), | ||
], | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import 'dart:js_interop'; | ||
|
||
import 'package:flutter/cupertino.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
import 'package:tuti/common/constraints_scaffold.dart'; | ||
import 'package:tuti/constants/color.dart'; | ||
import 'package:tuti/constants/gaps.dart'; | ||
import 'package:tuti/constants/string.dart'; | ||
import 'package:tuti/features/tutis/models/company_info.dart'; | ||
import 'package:tuti/features/tutis/widgets/tuti_widgets/tuti_header_mobile.dart'; | ||
import 'package:tuti/features/tutis/widgets/tuti_widgets/w_company_info_card.dart'; | ||
|
||
class TermsOfUseScreen extends StatelessWidget { | ||
const TermsOfUseScreen({super.key}); | ||
|
||
static const String routeName = "termsOfUse"; | ||
static const String routePath = "/termsOfUse"; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final List<String> tabs = <String>['이용약관', '개인정보 처리방침', '환불 정책']; | ||
final CompanyInfo termsOfUse = CompanyInfo( | ||
title: '이용약관', | ||
contents: termsOfUseContents + minorContents + updateOfAccountInfo, | ||
onTap: () {}); | ||
final CompanyInfo privacyPolicy = CompanyInfo( | ||
title: '개인정보 처리방침', | ||
contents: privacyPolicyIntroContents + | ||
privacyPolicyTableOfContents + | ||
privacyPolicyPurposeOfProcessingPersonalInfo + | ||
privacyPolicyProcessingRetentionPeriodOfPersonalInfo, | ||
onTap: () {}); | ||
final CompanyInfo refundPolicy = CompanyInfo( | ||
title: '환불 정책', | ||
contents: refundPolicyServiceOfSales + | ||
refundPolicyCoachingRights + | ||
refundPolicyInquiry, | ||
onTap: () {}); | ||
final List<CompanyInfo> companyInfos = [ | ||
termsOfUse, | ||
privacyPolicy, | ||
refundPolicy | ||
]; | ||
|
||
return DefaultTabController( | ||
length: tabs.length, | ||
child: Scaffold( | ||
body: Column( | ||
children: [ | ||
const TuTiHeaderMobile(), | ||
TabBar( | ||
indicatorColor: ColorConstants.primaryColor, | ||
labelColor: ColorConstants.primaryColor, | ||
dividerColor: ColorConstants.primaryColor, | ||
tabs: tabs.map((String name) => Text(name)).toList(), | ||
), | ||
Flexible( | ||
flex: 11, | ||
child: TabBarView( | ||
children: companyInfos | ||
.map((CompanyInfo info) => CompanyInfoCard( | ||
title: info.title, | ||
contents: info.contents, | ||
onTap: info.onTap, | ||
)) | ||
.toList(), | ||
), | ||
), | ||
Flexible( | ||
flex: 1, | ||
child: Container(), | ||
), | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,18 +13,20 @@ class TuTiBanner extends ConsumerWidget { | |
{super.key, | ||
required this.onTap, | ||
required this.title, | ||
required this.subtitle}); | ||
required this.subtitle, | ||
this.margin}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 객체 생성 시 constraintScaffold에서 제약 조건을 부과하고 있어 임의로 해당 배너의 크기를 조절하지 못하여 margin을 받아 custom하게 크기를 조절해주기 위해 margin을 받도록 했습니다. |
||
|
||
final VoidCallback onTap; | ||
final String title; | ||
final String subtitle; | ||
final EdgeInsets? margin; | ||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
return GestureDetector( | ||
onTap: onTap, | ||
child: Container( | ||
margin: EdgeInsets.symmetric(horizontal: 10.w), | ||
margin: margin ?? EdgeInsets.symmetric(horizontal: 10.w), | ||
padding: EdgeInsets.symmetric(horizontal: 13.w, vertical: 10.h), | ||
height: 80.h, | ||
decoration: ShapeDecoration( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
디렉토리에서 파일을 찾을 때 이름을 찾는데 시간을 줄이기 위해 screen 파일은 앞글자를 따 s로 통일 시킬 예정입니다.