사용자 화면 문구·표본 데이터 · 퀘스트 참여 흐름 · HOME 진입 구획 · 미니맵 · 공통 확인 창 배치 수정
This commit is contained in:
@@ -5,6 +5,7 @@ import '../../core/data/invite_code.dart';
|
||||
import '../../core/data/server_clock.dart';
|
||||
import 'home_data.dart';
|
||||
import '../quest/quest_data.dart' show QuestType;
|
||||
import '../quest/quest_repository_firestore.dart' show questToday;
|
||||
import '../../core/i18n/app_locale.dart';
|
||||
|
||||
/// 홈의 실 서버 구현 — 화면 대조 원장 F1.
|
||||
@@ -137,10 +138,13 @@ class FirestoreHomeRepository implements HomeRepository {
|
||||
.collection('heroGiftProducts')
|
||||
.where('active', isEqualTo: true)
|
||||
.get();
|
||||
// 인기 K-INSIDE — 기능명세서 v1.4 §2.114-7 「최대 3개 소팅(미해결 + 고액 포인트 순)」.
|
||||
// 미해결(`open`) 먼저, 그 안에서 현상금 큰 순. 정렬은 아래 [popularInsides].
|
||||
// ponytail: 현상금 상위 20건 안에서만 고른다. (status, bountyPop) 색인을 배포하면 질의로 옮긴다.
|
||||
final insidesF = db
|
||||
.collection('questions')
|
||||
.orderBy('createdAt', descending: true)
|
||||
.limit(3)
|
||||
.orderBy('bountyPop', descending: true)
|
||||
.limit(20)
|
||||
.get();
|
||||
|
||||
final wallet = (await walletF).data() ?? const <String, dynamic>{};
|
||||
@@ -167,7 +171,9 @@ class FirestoreHomeRepository implements HomeRepository {
|
||||
final campaigns = (await campaignF).docs
|
||||
.where((d) => !blocked.contains(d.data()['creatorUid']))
|
||||
.toList();
|
||||
final insides = (await insidesF).docs;
|
||||
final insides = popularInsides([
|
||||
for (final doc in (await insidesF).docs) doc.data(),
|
||||
]);
|
||||
|
||||
final progressById = {for (final doc in progress) doc.id: doc.data()};
|
||||
final policy = (await policyF).data() ?? const <String, dynamic>{};
|
||||
@@ -185,7 +191,7 @@ class FirestoreHomeRepository implements HomeRepository {
|
||||
],
|
||||
briefings: [for (final doc in briefings) ?_briefing(doc.data())],
|
||||
campaign: campaigns.isEmpty ? null : _campaign(campaigns.first.data()),
|
||||
insides: [for (final doc in insides) _inside(doc.data())],
|
||||
insides: [for (final data in insides) _inside(data)],
|
||||
items: [for (final doc in (await itemsF).docs) _item(doc.id, doc.data())],
|
||||
);
|
||||
}
|
||||
@@ -284,7 +290,8 @@ class FirestoreHomeRepository implements HomeRepository {
|
||||
members: validInt(fandom['memberCount']),
|
||||
requiredMembers: targets?.members,
|
||||
// Q-PN-01 A안 — 탄생은 창립자만.
|
||||
isFounder: fandom['founderUid'] != null && fandom['founderUid'] == _backend.uid,
|
||||
isFounder:
|
||||
fandom['founderUid'] != null && fandom['founderUid'] == _backend.uid,
|
||||
requiredSfpi: validNumber(next?['requiredSfpi']),
|
||||
nebulaGoalPassed: goalPassed,
|
||||
);
|
||||
@@ -296,9 +303,10 @@ class FirestoreHomeRepository implements HomeRepository {
|
||||
Map<String, dynamic>? progress,
|
||||
Map<String, dynamic> policy,
|
||||
) {
|
||||
final done =
|
||||
(progress?.intOr('count') ?? 0) >= quest.intOr('dailyLimit', 1);
|
||||
final started = (progress?.intOr('count') ?? 0) > 0;
|
||||
// 퀘스트 목록 · 상세와 같은 판정(`questToday`) — 오늘(KST) 행만 센다.
|
||||
final (:count, :done) =
|
||||
questToday(QuestType.parse(quest.strOr('type')), quest, progress, policy);
|
||||
final started = count > 0;
|
||||
return QuestSummary(
|
||||
title: quest.strOr('title'),
|
||||
rewardPop: QuestType.parse(quest.strOr('type')).rewardFrom(quest, policy),
|
||||
@@ -354,6 +362,15 @@ String _timeAgo(DateTime at) {
|
||||
return appL10n.timeDaysAgo('${gap.inDays}');
|
||||
}
|
||||
|
||||
/// 인기 K-INSIDE 3건 — 미해결(`status == open`) 먼저, 같은 묶음 안에서는 현상금 큰 순.
|
||||
/// 입력이 현상금 내림차순이라 미해결 묶음만 앞으로 옮기면 된다.
|
||||
List<Map<String, dynamic>> popularInsides(
|
||||
List<Map<String, dynamic>> byBounty,
|
||||
) => [
|
||||
...byBounty.where((q) => q['status'] == 'open'),
|
||||
...byBounty.where((q) => q['status'] != 'open'),
|
||||
].take(3).toList();
|
||||
|
||||
/// 오늘 날짜(KST `YYYY-MM-DD`) — 서버 `briefings.dayKey` 와 같은 규약이다.
|
||||
///
|
||||
/// 단말 시간대로 끊으면 해외 사용자의 「오늘」이 서버의 `dayKey` 와 달라 브리핑이
|
||||
|
||||
Reference in New Issue
Block a user