Figma 설명 프레임 반영 — 로그인·온보딩·스플래시 · HOME · GALAXY · 퀘스트·이클립스·알림

This commit is contained in:
Sn-Kinos
2026-10-06 03:03:20 +09:00
parent 64825e72b0
commit ecf5998725
77 changed files with 2703 additions and 640 deletions
+46 -3
View File
@@ -105,6 +105,18 @@ enum QuestType {
_ => QuestType.unknown,
};
/// 목록 · 상세의 **카테고리** 값 — 명세 `518:88395` · `518:88417` *퀘스트 카테고리 - 등록된 카테고리값*
/// (시안 「건강」 · 「커뮤니티」 · 「출석체크」). 활동이 속한 분류는 `config/questCatalog` 기본값
/// (`functions/src/quest/ugc.ts` — walk · shake → health, vote · sns · streaming → planet …)과 같다.
/// 출석 · 타임어택은 카탈로그 분류가 없어 유형 이름을 쓴다.
String get category => switch (this) {
steps || musicShake => appL10n.questCatHealth,
streaming || vote || sns => appL10n.questCatPlanet,
community => appL10n.questCatCommunity,
place => appL10n.questTypePlace,
_ => label,
};
/// 사람 검토형(C-08) — 참여가 곧 지급이 아니라 제출이다.
bool get reviewed => this == QuestType.vote || this == QuestType.sns;
@@ -315,6 +327,14 @@ class QuestSubmission {
now.difference(submittedAt!) > Duration(hours: hours);
}
/// 사용자 생성 Quest 의 모집 인원이 다 찼는가 — 명세 `523:18176` *참여 인원 충족 시 퀘스트 종료*.
/// 서버 참여 수(`participantCount`)는 지급 · 검토 예약 때 오르고 최종 반려 때 내려간다.
bool questFull(QuestCard card) =>
card.author == QuestAuthor.user &&
card.capacity != null &&
card.capacity! > 0 &&
card.participants >= card.capacity!;
/// 목록 카드 하나.
class QuestCard {
const QuestCard({
@@ -333,12 +353,17 @@ class QuestCard {
this.ugcAdPop = 10,
this.endsAt,
this.publishState = '',
this.authorName = '',
});
final String id;
final String title;
final String categoryName;
/// 만든 사람의 공개 닉네임(`quests.authorName`). 운영 Quest 는 빈 값이다.
/// 신고하기 「신고 정보 영역 — 작성자 닉네임」(Figma `548:21389`)에 쓴다.
final String authorName;
/// 내가 만든 Quest 의 공개 상태(`quests.status`) — `review` · `published` · `rejected` 등.
/// 「내 퀘스트」 카드가 검수 중 · 반려를 공개된 것과 구분해 보인다(10/6 실기기 4-2).
final String publishState;
@@ -398,6 +423,7 @@ class QuestCard {
adMultiplier: adMultiplier,
ugcAdPop: ugcAdPop,
endsAt: endsAt,
authorName: authorName,
publishState: publishState,
);
}
@@ -508,9 +534,11 @@ enum QuestTab {
bool accepts(QuestCard card) => switch (this) {
QuestTab.all => true,
QuestTab.inProgress => card.stage == QuestStage.inProgress,
QuestTab.done =>
card.stage == QuestStage.completed || card.stage == QuestStage.rewarded,
// 명세 `518:88405` — *진행중 - 진행중 탭 / 진행완료 - 진행중 탭 / 보상완료 - 완료 탭*.
// 보상을 받기 전(진행완료)까지는 진행중 탭에 두고, 받은 뒤에 완료 탭으로 옮긴다.
QuestTab.inProgress =>
card.stage == QuestStage.inProgress || card.stage == QuestStage.completed,
QuestTab.done => card.stage == QuestStage.rewarded,
QuestTab.mine => card.stage == QuestStage.mine,
};
}
@@ -610,6 +638,15 @@ abstract interface class QuestRepository {
/// 모르면 null(헤더는 받은 값을 유지한다).
Future<int?> popBalance();
/// 퀘스트 생성에 쓸 수 있는 보유 POP(일반 + 기여 — 서버 예치 `spendSplit` 과 같은 합). 명세
/// `523:18176` 완료 보상 설정 영역 *보유 POP 값*. 모르면 null.
Future<int?> spendableBalance();
/// 오늘 광고 추가 보상을 더 받을 수 있는가(일 한도 — B-03 · 10/3 통합회신 4절 「일 5회」).
/// 별첨 1 ⑥ 「일일 한도 도달 시 노출 제한」 — 다 쓴 사람에게는 보상 안내 모달을 띄우지 않는다.
/// 판정은 서버(`fnAdReward`)가 다시 한다. 읽지 못하면 true(모달을 막지 않는다).
Future<bool> adAvailable();
/// 진행 중 실측 진행도. 걸음 퀘스트만 값을 낸다.
///
/// 명세 `518:88441` 의 *「시작하기」 버튼 진행중으로 변경 후 실시간 목표 실행률
@@ -852,6 +889,12 @@ class SampleQuestRepository implements QuestRepository {
@override
Future<int?> popBalance() async => null;
@override
Future<int?> spendableBalance() async => null;
@override
Future<bool> adAvailable() async => true;
/// **표본은 센서를 읽지 않는다.** 여기서 걸음 수를 지어내면 화면이 카드에 적힌
/// 진행도 대신 만들어 낸 값을 그리게 되고, 목 모드 확인물이 실측처럼 보인다.
@override