추가 및 상세페이지 작업하기
추가 및 상세페이지 작업하기
추가 및 상세페이지 작업하기



모델링 조금 고쳐보기
우선, 모든 객체가 id
프로퍼티가 있으므로 BaseModel
클래스를 만들었다.
class BaseModel { String? id; }
그리고 기본적으로 추억하는 기억거리를 적은 형태의 글과 영상/사진 형태의 미디어라고 분리하여, 공통적으로 Memory
클래스에서 상속하게 했다.
import 'base.model.dart'; class Memory extends BaseModel { final String memo; final DateTime createdAt; Memory({required this.memo, required this.createdAt}); } class MediaMemory extends Memory { final String url; final String location; MediaMemory({ required this.url, required this.location, required super.memo, required super.createdAt, }); } class WrittenMemory extends Memory { final String content; WrittenMemory({ required this.content, required super.memo, required super.createdAt, }); }
각 추억거리 별 상세페이지
라우트를 요로코롬 분리하는 작업을 했는데, 기본적으로 위 추억거리의 종류에 따라 분기하여 각기 다른 레이아웃의 화면으로 이동하도록 처리하였다.
GoRoute( path: '/lost_person/:lost_person_id', builder: (context, state) { final lostPersonId = state.pathParameters['lost_person_id']!; return LostPersonDetailScreen(lostPersonId: lostPersonId); }, routes: [ GoRoute( path: '/memories', builder: (context, state) { final lostPersonId = state.pathParameters['lost_person_id']!; return MemoryDetailScreen(lostPersonId: lostPersonId); }, ), GoRoute( path: '/item/:item_id', builder: (context, state) { final itemId = state.pathParameters['item_id']!; final itemType = state.uri.queryParameters['item_type'] ?? ''; switch (itemType) { case 'written': return WrittenMemoryDetailPage(itemId: itemId); default: return MediaMemoryDetailPage(itemId: itemId); } }, ), ], ),
위의 핵심은 나름 state.uri.queryParameters
로 각 추억거리의 타입을 받아, 그에 맞는 레이아웃의 화면으로 이동하는 것이다. 이동할 때에는 이런 형태의 url을 응용한다.
context.push('/lost_person/1/item/1?item_type=media');
사진이나 영상을 보이는 상세화면은 이런 레이아웃이다.

글 형태를 보이는 상세화면은 이런 레이아웃이다.

추가 동작
추가 동작은 단순한데, 미리 만들어놓은 FAB에 모달을 띄우면 된다.
floatingActionButton: FloatingActionButton( child: const Icon(Icons.add), onPressed: () => showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 16), child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( leading: const Icon(Icons.photo), title: const Text('Upload Photo'), onTap: () { Navigator.pop(context); // TODO: handle image upload }, ), ListTile( leading: const Icon(Icons.videocam), title: const Text('Upload Video'), onTap: () { Navigator.pop(context); // TODO: handle video upload }, ), ListTile( leading: const Icon(Icons.contact_page_outlined), title: const Text('Upload a Written Memory'), onTap: () { Navigator.pop(context); // TODO: handle text upload }, ), ], ), ); }, ), ),
개인적으로는 BottomSheet
가 깔끔하다고 생각한다.

갈길이 멀긴 하지만 어쨋든 화면 쪽 핵심기능 관련된 레이아웃은 왠만하면 잡은 것 같다. 서버 동작 추가 전에 화면을 조금 더 다듬어 마무리 지을 예정.
Comments
Comments
Comments