Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,25 @@ jobs:

- run: flutter pub get

# 포맷 게이트. post_create_screen.dart 만 일시 제외 — 진행 중 작업(WIP·PR #143)과
# 겹쳐 있어 해당 작업 머지 후 포맷하고 제외를 풀 것.
- name: 포맷 검사
run: |
git ls-files | grep -E '^(lib|test)/.*\.dart$' \
| grep -v '^lib/screen/post_create_screen\.dart$' \
| xargs dart format --output=none --set-exit-if-changed

# info 수준 린트는 실패로 치지 않는다(warning/error 만 게이트).
- run: flutter analyze --no-fatal-infos

- run: flutter test --coverage

# 라인 커버리지 요약(아직 게이트 아님 — 측정·가시화 단계).
- name: 커버리지 요약
# 커버리지 요약 + 하한 게이트(10% 미만이면 실패). 커버리지가 오르는 만큼
# 하한도 따라 올릴 것(현재 12%대).
- name: 커버리지 요약·게이트(≥10%)
shell: bash
run: |
awk -F'[:,]' '/^DA:/{t++; if($3>0) h++}
END{printf "라인 커버리지 %.1f%% (%d/%d)\n", h*100/t, h, t}' \
END{pct=h*100/t; printf "라인 커버리지 %.1f%% (%d/%d)\n", pct, h, t;
exit (pct>=10)?0:1}' \
coverage/lcov.info | tee -a "$GITHUB_STEP_SUMMARY"
20 changes: 17 additions & 3 deletions lib/screen/activity_screens.dart
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,15 @@ class _MyAppointmentsScreenState extends State<MyAppointmentsScreen> {
),
Row(
children: [
for (final (i, w) in const ['일', '월', '화', '수', '목', '금', '토'].indexed)
for (final (i, w) in const [
'일',
'월',
'화',
'수',
'목',
'금',
'토',
].indexed)
Expanded(
child: Center(
child: Text(
Expand All @@ -486,8 +494,14 @@ class _MyAppointmentsScreenState extends State<MyAppointmentsScreen> {
Row(
children: [
for (var dow = 0; dow < 7; dow++)
Expanded(child: _dayCell(week * 7 + dow - firstWeekday + 1,
daysInMonth, counts, todayKey)),
Expanded(
child: _dayCell(
week * 7 + dow - firstWeekday + 1,
daysInMonth,
counts,
todayKey,
),
),
],
),
],
Expand Down
11 changes: 8 additions & 3 deletions lib/screen/admin/admin_business_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ class _DetailSheetState extends State<_DetailSheet> {
_row('주소(도로명)', a.businessAddress),
if ((a.businessAddressJibun ?? '').isNotEmpty)
_row('주소(지번)', a.businessAddressJibun!),
if ((a.businessPhone ?? '').isNotEmpty) _row('업장 전화', a.businessPhone!),
if ((a.businessPhone ?? '').isNotEmpty)
_row('업장 전화', a.businessPhone!),
if ((a.representativeName ?? '').isNotEmpty)
_row('대표자', a.representativeName!),
_row('이메일', a.contactEmail),
Expand Down Expand Up @@ -273,15 +274,19 @@ class _DetailSheetState extends State<_DetailSheet> {
onPressed: () => _openDoc(a.licenseImagePath),
icon: const Icon(Icons.description_outlined),
label: const Text('사업자등록증 열람'),
style: OutlinedButton.styleFrom(minimumSize: const Size.fromHeight(46)),
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(46),
),
),
if (a.extraDocPath != null) ...[
const SizedBox(height: 8),
OutlinedButton.icon(
onPressed: () => _openDoc(a.extraDocPath!),
icon: const Icon(Icons.attach_file),
label: const Text('추가 서류 열람 (영업 등록증 등)'),
style: OutlinedButton.styleFrom(minimumSize: const Size.fromHeight(46)),
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(46),
),
),
],
const SizedBox(height: 20),
Expand Down
3 changes: 1 addition & 2 deletions lib/screen/auth/signup_phone_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,7 @@ class _SignupPhoneScreenState extends State<SignupPhoneScreen> {
.where((p) => p.length >= 10 && p != myPhone)
.toSet()
.toList();
final petDraft =
(!_isBusiness && _petNameCtrl.text.trim().isNotEmpty)
final petDraft = (!_isBusiness && _petNameCtrl.text.trim().isNotEmpty)
? PetDraft(
name: _petNameCtrl.text.trim(),
speciesKind: _petKind,
Expand Down
146 changes: 73 additions & 73 deletions lib/screen/business_register_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,7 @@ class _BusinessRegisterScreenState extends State<BusinessRegisterScreen> {
TextField(
controller: _nameCtrl,
onChanged: (_) => setState(() {}),
decoration: const InputDecoration(
hintText: '사업자등록증에 기재된 상호',
),
decoration: const InputDecoration(hintText: '사업자등록증에 기재된 상호'),
),
const SizedBox(height: 8),
_foldToggle(
Expand Down Expand Up @@ -396,10 +394,7 @@ class _BusinessRegisterScreenState extends State<BusinessRegisterScreen> {
const SizedBox(height: 4),
Text(
'사유: ${_mine?.rejectedReason ?? '-'}',
style: TextStyle(
fontSize: 13,
color: context.colors.textSecondary,
),
style: TextStyle(fontSize: 13, color: context.colors.textSecondary),
),
],
),
Expand Down Expand Up @@ -516,9 +511,10 @@ class _BusinessRegisterScreenState extends State<BusinessRegisterScreen> {
: switch (r.statusCode) {
'02' => '휴업 상태의 사업자번호는 등록할 수 없어요',
'03' => '폐업 상태의 사업자번호는 등록할 수 없어요',
_ => r.error == 'nts_unavailable' || r.error == 'network'
? '국세청 확인에 실패했어요. 잠시 후 다시 시도해주세요'
: '국세청에 등록되지 않은 사업자번호예요',
_ =>
r.error == 'nts_unavailable' || r.error == 'network'
? '국세청 확인에 실패했어요. 잠시 후 다시 시도해주세요'
: '국세청에 등록되지 않은 사업자번호예요',
};
});
}
Expand All @@ -530,9 +526,7 @@ class _BusinessRegisterScreenState extends State<BusinessRegisterScreen> {
return TextField(
controller: _manualAddrCtrl,
onChanged: (_) => setState(() {}),
decoration: const InputDecoration(
hintText: '사업자등록증의 사업장 소재지 (도로명 주소)',
),
decoration: const InputDecoration(hintText: '사업자등록증의 사업장 소재지 (도로명 주소)'),
);
}
return InkWell(
Expand Down Expand Up @@ -801,49 +795,52 @@ class _StatusView extends StatelessWidget {
return ListView(
padding: const EdgeInsets.all(24),
children: [
const SizedBox(height: 8),
Icon(icon, size: 56, color: context.colors.primary),
const SizedBox(height: 16),
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: context.colors.textPrimary,
),
const SizedBox(height: 8),
Icon(icon, size: 56, color: context.colors.primary),
const SizedBox(height: 16),
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: context.colors.textPrimary,
),
const SizedBox(height: 8),
Text(
message,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13.5,
height: 1.5,
color: context.colors.textSecondary,
),
),
const SizedBox(height: 8),
Text(
message,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13.5,
height: 1.5,
color: context.colors.textSecondary,
),
const SizedBox(height: 28),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: context.colors.surface,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: context.colors.border, width: 0.5),
),
child: Column(
children: [
_row(context, '상호', profile.businessName),
if ((profile.storefrontName ?? '').isNotEmpty)
_row(context, '사업장명', profile.storefrontName!),
_row(context, '업종',
businessCategoryLabel(profile.declaredCategory)),
_row(context, '사업자번호', _maskBno(profile.businessRegNo)),
_row(context, '주소', profile.businessAddress),
_row(context, '이메일', profile.contactEmail),
],
),
),
const SizedBox(height: 28),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: context.colors.surface,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: context.colors.border, width: 0.5),
),
child: Column(
children: [
_row(context, '상호', profile.businessName),
if ((profile.storefrontName ?? '').isNotEmpty)
_row(context, '사업장명', profile.storefrontName!),
_row(
context,
'업종',
businessCategoryLabel(profile.declaredCategory),
),
_row(context, '사업자번호', _maskBno(profile.businessRegNo)),
_row(context, '주소', profile.businessAddress),
_row(context, '이메일', profile.contactEmail),
],
),
),
],
);
}
Expand All @@ -862,19 +859,13 @@ class _StatusView extends StatelessWidget {
width: 76,
child: Text(
k,
style: TextStyle(
fontSize: 13,
color: context.colors.textTertiary,
),
style: TextStyle(fontSize: 13, color: context.colors.textTertiary),
),
),
Expanded(
child: Text(
v,
style: TextStyle(
fontSize: 13.5,
color: context.colors.textPrimary,
),
style: TextStyle(fontSize: 13.5, color: context.colors.textPrimary),
),
),
],
Expand Down Expand Up @@ -905,7 +896,10 @@ class _PhotoAlignSheetState extends State<_PhotoAlignSheet> {
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.fromLTRB(
20, 20, 20, 20 + MediaQuery.of(context).padding.bottom,
20,
20,
20,
20 + MediaQuery.of(context).padding.bottom,
),
child: Column(
mainAxisSize: MainAxisSize.min,
Expand Down Expand Up @@ -1082,9 +1076,7 @@ class AddressSearchSheetState extends State<AddressSearchSheet> {
autofocus: true,
textInputAction: TextInputAction.search,
onSubmitted: (_) => _search(),
decoration: const InputDecoration(
hintText: '도로명, 건물명 또는 지번',
),
decoration: const InputDecoration(hintText: '도로명, 건물명 또는 지번'),
),
),
const SizedBox(width: 8),
Expand Down Expand Up @@ -1151,7 +1143,6 @@ class AddressSearchSheetState extends State<AddressSearchSheet> {
}
}


/// 승인 업체 관리 패널 — 업체 정보 요약·수정, 대표 사진 설정/위치 조절/제거.
/// BusinessRegisterScreen(승인 상태)과 업체 모드의 내정보(업체 관리) 최상단에서
/// 공용 — "프로필 한 번 탭으로 수정 도달" 요구의 구현체.
Expand Down Expand Up @@ -1318,7 +1309,9 @@ class _BusinessManagePanelState extends State<BusinessManagePanel> {
onPressed: _openInfoEdit,
icon: const Icon(Icons.edit_outlined, size: 18),
label: const Text('업체 정보 수정'),
style: OutlinedButton.styleFrom(minimumSize: const Size.fromHeight(48)),
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(48),
),
),
const SizedBox(height: 20),
// 계정 단위 활동(하트·친구)은 두 얼굴 공용 — 업체 모드에서도 조회 가능하게.
Expand All @@ -1338,13 +1331,14 @@ class _BusinessManagePanelState extends State<BusinessManagePanel> {
onPressed: () => Navigator.push(
context,
AppPageRoute(
builder: (_) =>
const MyPostsScreen(mode: PostListMode.hearted),
builder: (_) => const MyPostsScreen(mode: PostListMode.hearted),
),
),
icon: const Icon(Icons.favorite_border, size: 18),
label: const Text('하트한 게시글'),
style: OutlinedButton.styleFrom(minimumSize: const Size.fromHeight(48)),
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(48),
),
),
const SizedBox(height: 8),
OutlinedButton.icon(
Expand All @@ -1354,7 +1348,9 @@ class _BusinessManagePanelState extends State<BusinessManagePanel> {
),
icon: const Icon(Icons.group_outlined, size: 18),
label: const Text('내 친구 (Pawing · Pawmate)'),
style: OutlinedButton.styleFrom(minimumSize: const Size.fromHeight(48)),
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(48),
),
),
],
);
Expand Down Expand Up @@ -1450,7 +1446,8 @@ class _BusinessManagePanelState extends State<BusinessManagePanel> {
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
builder: (_) => _PhotoAlignSheet(image: image, initial: initial, name: name),
builder: (_) =>
_PhotoAlignSheet(image: image, initial: initial, name: name),
);
}

Expand All @@ -1472,7 +1469,10 @@ class _BusinessManagePanelState extends State<BusinessManagePanel> {
),
builder: (sheetCtx) => Padding(
padding: EdgeInsets.fromLTRB(
20, 20, 20, 20 + MediaQuery.of(sheetCtx).viewInsets.bottom,
20,
20,
20,
20 + MediaQuery.of(sheetCtx).viewInsets.bottom,
),
child: Column(
mainAxisSize: MainAxisSize.min,
Expand Down
6 changes: 5 additions & 1 deletion lib/screen/main_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ class MainScreen extends StatefulWidget {
/// null 로 리셋한다. 딥링크가 상세를 얹기 전에 "뒤로 갔을 때 보일 탭"을 맞출 때 사용.
static final ValueNotifier<int?> tabRequest = ValueNotifier<int?>(null);

static const tabMap = 0, tabSearch = 1, tabCommunity = 2, tabChat = 3, tabMyInfo = 4;
static const tabMap = 0,
tabSearch = 1,
tabCommunity = 2,
tabChat = 3,
tabMyInfo = 4;

@override
State<MainScreen> createState() => _MainScreenState();
Expand Down
Loading
Loading