광고 추가 보상 서버 시청 검증 · 사용자 퀘스트 승인 후 공개 · TIME ATTACK 모드 · 만보기 퀘스트 · 위치 퀘스트 지도 선택 · 운영 퀘스트 보상 재원
This commit is contained in:
@@ -35,6 +35,8 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
final _manualTitle = TextEditingController();
|
||||
final _reward = TextEditingController();
|
||||
final _participants = TextEditingController();
|
||||
// 만보기 목표 걸음(Figma `259:45798` 「목표 0 / 10,000」).
|
||||
final _goal = TextEditingController();
|
||||
|
||||
/// 이 화면 한 번의 생성 요청 키 — 응답 유실 뒤 다시 눌러도 서버가 한 건으로 묶는다.
|
||||
final _clientSeq = DateTime.now().microsecondsSinceEpoch.toString();
|
||||
@@ -52,7 +54,7 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
for (final c in [_title, _description, _manualTitle, _reward, _participants]) {
|
||||
for (final c in [_title, _description, _manualTitle, _reward, _participants, _goal]) {
|
||||
// 입력이 바뀔 때마다 미리보기와 완료 버튼 활성화가 함께 움직여야 한다.
|
||||
c.addListener(() => setState(() {}));
|
||||
}
|
||||
@@ -65,7 +67,7 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final c in [_title, _description, _url, _manualTitle, _reward, _participants]) {
|
||||
for (final c in [_title, _description, _url, _manualTitle, _reward, _participants, _goal]) {
|
||||
c.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
@@ -88,6 +90,7 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
bool get _ready {
|
||||
if (_activity == null || _title.text.trim().isEmpty) return false;
|
||||
if (_needs('place') && _place == null) return false;
|
||||
if (_needs('goal') && _intOf(_goal) <= 0) return false;
|
||||
if (_needs('link')) {
|
||||
final link = _link;
|
||||
if (link == null || !(link.ok || (link.failed && _manualTitle.text.trim().isNotEmpty))) {
|
||||
@@ -105,7 +108,7 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
categoryName: _activity?.name ?? _category?.name ?? context.l10n.questNoCategory,
|
||||
author: QuestAuthor.user,
|
||||
stage: QuestStage.mine,
|
||||
goal: 1,
|
||||
goal: _needs('goal') ? _intOf(_goal) : 1,
|
||||
progress: 0,
|
||||
rewardPop: _intOf(_reward),
|
||||
// 시안 — *참여 인원 : 0 / 0*. 분모가 모집 인원이다.
|
||||
@@ -284,6 +287,15 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
const SizedBox(height: AppSpace.s3),
|
||||
],
|
||||
|
||||
if (_needs('goal')) ...[
|
||||
TextField(
|
||||
controller: _goal,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: _field(context.l10n.questGoalSteps),
|
||||
),
|
||||
const SizedBox(height: AppSpace.s3),
|
||||
],
|
||||
|
||||
if (_needs('place')) ...[
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
@@ -377,13 +389,11 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
if (!mounted) return;
|
||||
_places = places;
|
||||
}
|
||||
final name = await Navigator.of(context, rootNavigator: true).push<String>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => PlacePickerScreen(places: [for (final p in _places) p.name]),
|
||||
),
|
||||
final picked = await Navigator.of(context, rootNavigator: true).push<QuestPlace>(
|
||||
MaterialPageRoute(builder: (_) => PlacePickerScreen(places: _places)),
|
||||
);
|
||||
if (name == null || !mounted) return;
|
||||
setState(() => _place = _places.firstWhere((p) => p.name == name));
|
||||
if (picked == null || !mounted) return;
|
||||
setState(() => _place = picked);
|
||||
}
|
||||
|
||||
/// 공개일을 1일째로 최대 [QuestCatalog.maxDays] 일째까지. 남은 1시간 미만 판정은 서버가 한다.
|
||||
@@ -433,7 +443,9 @@ class _QuestCreateScreenState extends State<QuestCreateScreen> {
|
||||
endDate: _endDate,
|
||||
url: _needs('link') ? _link?.url : null,
|
||||
manualTitle: _needs('link') && (_link?.failed ?? false) ? _manualTitle.text.trim() : null,
|
||||
placeId: _needs('place') ? _place?.id : null,
|
||||
placeId: _needs('place') && !(_place?.isPin ?? true) ? _place?.id : null,
|
||||
pin: _needs('place') && (_place?.isPin ?? false) ? _place : null,
|
||||
goal: _needs('goal') ? _intOf(_goal) : null,
|
||||
),
|
||||
);
|
||||
} on BackendException catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user