import 'package:flutter/material.dart'; import '../../core/theme/tokens.dart'; import '../../core/i18n/app_locale.dart'; /// 위치 선택 — 화면 대조 원장 F4 · Figma `371:356705`. /// /// 명세 `567:19531` — *분류 특정 위치를 선택했을 경우 목표 수치(특정 위치) 필드 활성화*. /// /// **지도를 붙이지 않았다.** 지오펜스 반경(D-08)과 대상 장소 등록이 모두 Admin /// 운영값이고 아직 확정되지 않았다. 지금 지도 SDK 를 넣으면 최소 지원 OS 가 /// 다시 움직인다(플러그인 선검증 §3.5). **장소 선택 동선은 여기서 완결**되고, /// 지도 표시는 대상 장소가 확정된 뒤 이 화면 안에서 바뀐다. class PlacePickerScreen extends StatefulWidget { const PlacePickerScreen({super.key, this.places = defaultPlaces}); final List places; /// 어드민에 등록될 장소의 표본. **정책값이 아니다.** static const defaultPlaces = [ '홍대 팝업스토어', 'HYBE 사옥', 'SM 코엑스 아티움', '올림픽공원 체조경기장', '고척 스카이돔', ]; @override State createState() => _PlacePickerScreenState(); } class _PlacePickerScreenState extends State { String _query = ''; String? _selected; List get _visible => widget.places .where((p) => _query.isEmpty || p.contains(_query)) .toList(); @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(leading: const CloseButton()), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 시안 `371:356705` 머리 — 안내 문구 + 고른 장소. 지도 자리는 아래 검색 목록이다. Padding( padding: const EdgeInsets.fromLTRB(16, 20, 16, 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( context.l10n.placePickPrompt, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w600, height: 1.4, letterSpacing: -0.45, color: AppColors.onCosmic, ), ), const SizedBox(height: 10), Text( _selected ?? '', style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w400, height: 1.4, color: Color(0xFFCDCDCD), ), ), ], ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: AppSpace.s4), child: TextField( decoration: InputDecoration( labelText: context.l10n.placeSearch, prefixIcon: Icon(Icons.search), ), onChanged: (v) => setState(() => _query = v.trim()), ), ), Expanded( child: _visible.isEmpty ? Center( child: Text( context.l10n.commonNoResults, style: Theme.of(context).textTheme.bodyMedium, ), ) // 디폴트 미선택 · 단수 선택. : RadioGroup( groupValue: _selected, onChanged: (v) => setState(() => _selected = v), child: ListView.builder( itemCount: _visible.length, itemBuilder: (context, i) { final place = _visible[i]; return RadioListTile( value: place, title: Text(place), secondary: const Icon(Icons.place_outlined), ); }, ), ), ), SafeArea( top: false, child: Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: FilledButton( onPressed: _selected == null ? null : () => Navigator.of(context).pop(_selected), style: FilledButton.styleFrom( minimumSize: const Size.fromHeight(56), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.sm), ), backgroundColor: AppColors.cosmicAccent, foregroundColor: Colors.black, textStyle: const TextStyle( fontFamily: AppFonts.body, fontSize: 16, fontWeight: FontWeight.w600, height: 24 / 16, ), ), child: Text(context.l10n.commonSelectDone), ), ), ), ], ), ); }