백품타 랭킹에 전체랭킹/학년랭킹 필터 추가
grade 쿼리파라미터를 생략하면 전체 학년 통합 랭킹을 주도록 백엔드를 바꾸고, 랭킹 화면에 "N학년"/"전체랭킹" 필 필터를 추가해 시간대 필터(오늘/이번주/전체)와 별도로 고를 수 있게 했다. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,10 +11,12 @@ class StudyRankingController extends ChangeNotifier {
|
|||||||
|
|
||||||
bool _isLoading = true;
|
bool _isLoading = true;
|
||||||
String _period = 'today'; // today / week / total
|
String _period = 'today'; // today / week / total
|
||||||
|
String _scope = 'grade'; // grade / all
|
||||||
List<dynamic> _ranking = [];
|
List<dynamic> _ranking = [];
|
||||||
|
|
||||||
bool get isLoading => _isLoading;
|
bool get isLoading => _isLoading;
|
||||||
String get period => _period;
|
String get period => _period;
|
||||||
|
String get scope => _scope;
|
||||||
List<dynamic> get ranking => _ranking;
|
List<dynamic> get ranking => _ranking;
|
||||||
|
|
||||||
Future<void> init() => fetchRanking();
|
Future<void> init() => fetchRanking();
|
||||||
@@ -25,12 +27,19 @@ class StudyRankingController extends ChangeNotifier {
|
|||||||
await fetchRanking();
|
await fetchRanking();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> setScope(String scope) async {
|
||||||
|
if (_scope == scope) return;
|
||||||
|
_scope = scope;
|
||||||
|
await fetchRanking();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> fetchRanking() async {
|
Future<void> fetchRanking() async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
try {
|
try {
|
||||||
|
final gradeParam = _scope == 'grade' ? '&grade=$grade' : '';
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
Uri.parse('$baseUrl/api/study/ranking?grade=$grade&period=$_period'),
|
Uri.parse('$baseUrl/api/study/ranking?period=$_period$gradeParam'),
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final data = jsonDecode(utf8.decode(response.bodyBytes));
|
final data = jsonDecode(utf8.decode(response.bodyBytes));
|
||||||
|
|||||||
@@ -68,10 +68,24 @@ class _StudyRankingScreenState extends State<StudyRankingScreen> {
|
|||||||
foregroundColor: AppPalette.ink,
|
foregroundColor: AppPalette.ink,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: TitlePill('${widget.grade}학년 공부 랭킹'),
|
title: TitlePill(
|
||||||
|
_controller.scope == 'grade'
|
||||||
|
? '${widget.grade}학년 공부 랭킹'
|
||||||
|
: '전체 공부 랭킹',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
_scopeChip('grade', '${widget.grade}학년'),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
_scopeChip('all', '전체랭킹'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
|
padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -190,4 +204,21 @@ class _StudyRankingScreenState extends State<StudyRankingScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _scopeChip(String value, String label) {
|
||||||
|
final bool selected = _controller.scope == value;
|
||||||
|
return Expanded(
|
||||||
|
child: ChoiceChip(
|
||||||
|
label: Center(child: Text(label, style: const TextStyle(fontSize: 13))),
|
||||||
|
selected: selected,
|
||||||
|
onSelected: (_) => _controller.setScope(value),
|
||||||
|
selectedColor: AppPalette.ink,
|
||||||
|
backgroundColor: AppPalette.mist,
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
color: selected ? Colors.white : Colors.grey[600],
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user