Skip to content

Feat/17 matching menu#28

Open
hakyeoung wants to merge 45 commits into
developfrom
feat/17-matching-menu
Open

Feat/17 matching menu#28
hakyeoung wants to merge 45 commits into
developfrom
feat/17-matching-menu

Conversation

@hakyeoung

Copy link
Copy Markdown
Collaborator

[FEAT] 매칭 탭 신규 추가 및 네비게이션 바 수정

💡 작업 내용

  • root_screen.dart 내부 bottomNavigationBar 이름 수정
  • match_list_screen.dart 신규 생성 및 매칭 탭 추가
  • 매칭 탭 내부에 '방 만들기' 기능 구현

⚠️ 특이사항 및 주의사항

  • root_screenbottomNavigationBar 동작 확인을 위해 임시로 club-tab과 병합을 진행했습니다.
  • 이로 인해 현재 PR에 포함된 club-tab 관련 파일들이 불완전할 수 있으니 리뷰 및 테스트 시 참고 부탁드립니다.

📸 스크린샷

매칭탭 관련

match_list make_room

root_screen 내부 bottomNavigationBar 관련

home_screen community_screen my_page

Blueapple031 and others added 30 commits February 19, 2026 01:51
- Club Header / Overview / Members 탭 UI 추가
- 동아리/멤버 더미 모델 추가
- 멤버 탭 클릭 시 print 로그 출력
- 디자인 토큰(AppColors) 적용 및 8pt 여백 준수

Refs #13
- KakaoAuthService, KakaoAuthServiceImpl 구현
- POST /api/auth/kakao 엔드포인트 추가
- KakaoLoginRequest DTO, ErrorCode(KAKAO_*), LoginType.KAKAO 추가
- UserRepository findByKakaoId, existsByKakaoId 추가
- Flutter 카카오 로그인 연동 (auth_service, auth_repository, login_screen)
- POST /api/auth/kakao 엔드포인트 명세 추가
- 요청/응답 필드, 처리 흐름, 에러 코드 문서화
- User Entity에 kakaoId, LoginType.KAKAO 반영
- RootScreen에 initialIndex를 추가해 동아리 탭(인덱스 1) 기본 진입 지원
- root_screen 하단 네비게이션과 ClubScreen 연결

Refs #13
@hakyeoung hakyeoung self-assigned this Mar 6, 2026
@hakyeoung hakyeoung added the frontend Flutter/App 관련 작 label Mar 6, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This is a large PR that significantly extends the PNU Basketball Platform across frontend, backend, and infrastructure. Despite the title suggesting primarily a "matching tab" addition, the PR contains extensive changes including Kakao social login integration, a complete schema redesign (nickname → realName, new club/match tables), an admin backoffice, and navigation restructuring.

Changes:

  • Added matching tab to bottom navigation bar, created MatchListScreen, restructured root_screen.dart navigation items, and added club tab with dummy data
  • Integrated Kakao social login end-to-end (Flutter SDK, backend service, API endpoint), added post-login flows for profile completion and club selection, and renamed nickname to realName throughout the entire stack
  • Created admin backoffice (HTML/CSS/JS) with user management, club management, and match management features; added corresponding backend admin API endpoints and new domain entities (Club, ClubMember, Match, MatchParticipant)

Reviewed changes

Copilot reviewed 101 out of 102 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
frontend/lib/presentation/screens/root/root_screen.dart Restructured bottom nav bar: added matching & club tabs, styling, initialIndex support
frontend/lib/presentation/screens/club/* New club screen with header, info section, and member list widgets
frontend/lib/presentation/screens/auth/login_screen.dart Added Kakao login button, changed login/google handlers to return AuthResponseModel
frontend/lib/presentation/screens/auth/signup_screen.dart Added realName, dateOfBirth, isPnuStudent, department, studentId fields
frontend/lib/presentation/screens/auth/complete_profile_screen.dart New screen for social login users to complete profile
frontend/lib/presentation/screens/auth/club_selection_screen.dart New screen for club selection after signup/login
frontend/lib/data/models/user_model.dart Changed nickname → realName, added new fields
frontend/lib/data/models/club_model.dart New ClubModel with JSON serialization and dummy data
frontend/lib/data/models/auth_response_model.dart Added realName, needsClubSelection fields
frontend/lib/data/repositories/auth_repository.dart Added Kakao login, club selection, profile completion methods
frontend/lib/data/services/auth_service.dart Added Kakao login, completeProfile, club API calls
frontend/lib/presentation/providers/auth_provider.dart Added kakaoLogin, completeProfile, getClubs, selectClub methods
frontend/lib/main.dart Added Kakao SDK initialization
frontend/lib/app.dart Added routes for complete-profile and club-selection, removed AuthGate
frontend/lib/core/constants/app_colors.dart New AppColors constants (duplicates theme version)
frontend/lib/core/constants/api_endpoints.dart Added kakaoLogin, completeProfile, club endpoints
frontend/pubspec.yaml Added kakao_flutter_sdk dependencies
frontend/dart_defines.json Contains leaked Kakao API key
frontend/android/gradle.properties Contains leaked Kakao API key
backend/src/main/java/com/pnu/basketball/domain/*.java New domain entities: Club, ClubMember, Match, MatchParticipant, enums
backend/src/main/java/com/pnu/basketball/domain/User.java Major refactor: nickname→realName, added kakaoId, PNU student fields, stats
backend/src/main/java/com/pnu/basketball/service/auth/KakaoAuthServiceImpl.java New Kakao authentication service
backend/src/main/java/com/pnu/basketball/service/auth/AuthServiceImpl.java Added needsClubSelection to auth response, removed soft-delete checks
backend/src/main/java/com/pnu/basketball/service/club/ClubServiceImpl.java New club service for listing, selecting, status checking
backend/src/main/java/com/pnu/basketball/service/admin/AdminServiceImpl.java New admin service for users, clubs, matches management
backend/src/main/java/com/pnu/basketball/service/user/UserServiceImpl.java Added completeProfile, changed withdraw to hard-delete
backend/src/main/java/com/pnu/basketball/controller/auth/AuthController.java Added Kakao login, complete-profile, club-selection-status endpoints
backend/src/main/java/com/pnu/basketball/controller/admin/AdminController.java New admin REST API controller
backend/src/main/java/com/pnu/basketball/controller/club/ClubController.java New club controller
backend/src/main/java/com/pnu/basketball/repository/*.java New repositories for Club, ClubMember, Match, MatchParticipant
backend/src/main/java/com/pnu/basketball/config/SecurityConfig.java Simplified auth endpoint permits, added admin static files
backend/src/main/resources/static/admin/* Complete admin backoffice (HTML/CSS/JS)
backend/src/main/resources/application.yml New main config file
backend/src/main/resources/application-local.yml Deleted local profile config
docs/database/schema.sql Complete schema rewrite with clubs, matches, posts, comments
docs/database/*.md New schema documentation
scripts/migrate-basketball-tables.sql Migration script for basketball tables
SPEC/AUTH_API_SPEC.md Added Kakao login API specification
.github/workflows/deploy-backend.yml Simplified deployment step
.gitignore Added Kakao key files to ignore list
Comments suppressed due to low confidence (1)

backend/src/main/resources/application-local.yml:1

  • Deleted application-local.yml without replacement: The local profile configuration (Redis-less mode with in-memory token storage) was deleted entirely. The application.yml sets spring.profiles.active: local, but there's no longer an application-local.yml to provide the local profile settings. This means the app.token-storage: memory setting and the Redis auto-configuration exclusion are lost, which could cause the application to fail to start locally if Redis is not available.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +33 to +41
public List<ClubListResponse> getClubs() {
return clubRepository.findAll().stream()
.map(club -> ClubListResponse.builder()
.clubId(club.getId())
.name(club.getName())
.logoUrl(club.getLogoUrl())
.memberCount(clubMemberRepository.countByClub_Id(club.getId()))
.build())
.collect(Collectors.toList());

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N+1 query in club list: getClubs() iterates over all clubs and calls clubMemberRepository.countByClub_Id() for each club, resulting in N+1 queries. Similarly, toAdminClubListResponse calls countByClub_Id() per club. Consider using a single query with a COUNT aggregate or a @Query that joins clubs with a member count subquery.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +2
import 'package:flutter/material.dart';

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent import path: The club widget files (club_member_list.dart, club_info_section.dart, club_header.dart) import AppColors from '../../../../core/constants/app_colors.dart', while root_screen.dart imports AppColors from '../../../core/theme/app_colors.dart'. There appear to be two separate AppColors classes in the project. The club widgets will use a different AppColors than the rest of the app (e.g., the club files reference AppColors.white and AppColors.headerGrey which are only defined in core/constants/app_colors.dart but not necessarily in core/theme/app_colors.dart). This duplication could lead to inconsistent styling. Consider consolidating into a single AppColors class.

Copilot uses AI. Check for mistakes.
// 실제 기기: http://<PC IP>:8080
static const String baseUrl =
String.fromEnvironment('API_BASE_URL', defaultValue: 'https://ddalba.duckdns.org');
//String.fromEnvironment('API_BASE_URL', defaultValue: 'http://localhost:8080');

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out code: This commented-out localhost URL should be removed before merging to keep the codebase clean.

Copilot uses AI. Check for mistakes.
Comment thread frontend/lib/main.dart
Comment on lines +9 to +13
const nativeAppKey = String.fromEnvironment(
'KAKAO_NATIVE_APP_KEY',
defaultValue: '',
);
KakaoSdk.init(nativeAppKey: nativeAppKey);

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KakaoSdk initialized with potentially empty key: If KAKAO_NATIVE_APP_KEY is not provided via --dart-define, the defaultValue is an empty string, and KakaoSdk.init will be called with an empty nativeAppKey. This could cause runtime errors or silent failures when Kakao login is attempted. Consider adding a guard or logging a warning when the key is empty.

Copilot uses AI. Check for mistakes.
Comment thread SPEC/AUTH_API_SPEC.md
Comment on lines +377 to +388
"user": {
"userId": 10,
"email": "user@kakao.com",
"nickname": "카카오사용자",
"profileImageUrl": "https://k.kakaocdn.net/...",
"loginType": "KAKAO",
"isNewUser": true
}
},
"message": "카카오 로그인 성공"
}
```

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kakao login API spec uses nickname instead of realName: The Kakao login response example in the spec shows "nickname": "카카오사용자", but the backend AuthResponse.UserInfo class now uses realName instead of nickname. The spec should be updated to match the actual response format.

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +62
if (authResponse != null && mounted) {
if (authResponse.user.needsClubSelection == true) {
Navigator.of(context).pushReplacementNamed('/club-selection');
} else if (authResponse.user.isNewUser == true) {
Navigator.of(context).pushReplacementNamed('/complete-profile');
} else {
Navigator.of(context).pushReplacementNamed('/home');
}

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent login flow ordering: In _handleKakaoLogin, the check order is needsClubSelectionisNewUser → home. In _handleGoogleLogin, it's isNewUserneedsClubSelection → home. And in _handleLogin, it's needsClubSelection → home (no isNewUser check). The inconsistent ordering could lead to users being routed differently depending on login method. For example, a new Google user who also needs club selection would go to /complete-profile, while a new Kakao user who also needs club selection would go to /club-selection. Ensure the routing logic is consistent across all login methods.

Copilot uses AI. Check for mistakes.
Comment thread frontend/lib/app.dart
title: '딸바',
theme: AppTheme.theme,
home: const AuthGate(),
home: const LoginScreen(),

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed AuthGate, always shows LoginScreen: The home property was changed from AuthGate() (which likely checked auth state) to always showing LoginScreen. This means users who are already logged in (have valid tokens) will always see the login screen when opening the app, breaking the auto-login experience. Consider restoring the AuthGate pattern or implementing similar token-check logic.

Copilot uses AI. Check for mistakes.
Comment thread SPEC/AUTH_API_SPEC.md
| 401 | `KAKAO_TOKEN_INVALID` | 카카오 토큰 검증 실패 |
| 404 | `USER_NOT_FOUND` | 사용자를 찾을 수 없음 |
| 409 | `EMAIL_ALREADY_EXISTS` | 이미 존재하는 이메일 |
| 409 | `NICKNAME_ALREADY_EXISTS` | 이미 존재하는 닉네임 |

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale API spec: The AUTH_API_SPEC.md still references NICKNAME_ALREADY_EXISTS error code (line 631), but this error code has been removed from the backend ErrorCode.java and replaced with STUDENT_ID_ALREADY_EXISTS. The response example at line 663 still shows nickname field. The spec should be updated to reflect the nicknamerealName change throughout.

Suggested change
| 409 | `NICKNAME_ALREADY_EXISTS` | 이미 존재하는 닉네임 |
| 409 | `STUDENT_ID_ALREADY_EXISTS` | 이미 존재하는 학번 |

Copilot uses AI. Check for mistakes.
return userRepository.save(newUser);
}));

userRepository.save(user);

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate redundant userRepository.save(user) call: On line 75, userRepository.save(user) is called after the user has already been saved in each branch of the orElseGet chain (lines 60, 72). Since JPA entities are managed within the transaction, this extra save is unnecessary and could cause confusion.

Copilot uses AI. Check for mistakes.
Comment thread docs/database/schema.sql
Comment on lines +79 to +89
CREATE TABLE matches (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
home_club_id UUID NOT NULL REFERENCES clubs(id) ON DELETE CASCADE,
away_club_id UUID NOT NULL REFERENCES clubs(id) ON DELETE CASCADE,
scheduled_at TIMESTAMP NOT NULL,
state match_state NOT NULL DEFAULT 'SCHEDULED',
home_score INTEGER,
away_score INTEGER,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT chk_match_clubs_different CHECK (home_club_id != away_club_id)
);

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Schema discrepancy between docs and migration: The docs/database/schema.sql defines matches with home_club_id and away_club_id as NOT NULL (lines 81-82), but scripts/migrate-basketball-tables.sql defines them as nullable (lines 46-47) to support QUICK matches. The migration script's approach is correct for the FORMAL/QUICK match design, but schema.sql will reject QUICK matches. These should be kept in sync.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend Flutter/App 관련 작

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants