93 lines
3.8 KiB
Dart
93 lines
3.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:friendly_map/modules/app/app.dart';
|
|
import 'package:friendly_map/modules/core/core.dart';
|
|
|
|
import '../theme.dart';
|
|
import '../widgets/async_view.dart';
|
|
import '../widgets/common.dart';
|
|
import '../widgets/pin_dialog.dart';
|
|
import '../widgets/ring_view.dart';
|
|
import 'circle_group_screen.dart';
|
|
import 'group_detail_screen.dart';
|
|
import 'person_screen.dart';
|
|
|
|
class _Data {
|
|
const _Data(this.hub, this.me);
|
|
final CircleHub hub;
|
|
final String me;
|
|
}
|
|
|
|
/// 학교·회사 원형 보기: 나를 가운데 두고 둘레에 초·중·고·대(또는 회사들)를 놓고,
|
|
/// 그 옆에 대화·통화가 많은 가까운 사람을 보여 준다. 칸을 누르면 그 칸 사람들이 원 모양으로 펼쳐진다.
|
|
class CircleHubScreen extends StatelessWidget {
|
|
const CircleHubScreen({super.key, required this.rootId});
|
|
|
|
final String rootId;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AsyncView<_Data>(
|
|
load: (a) async => _Data(await a.circles.hub(rootId), (await a.profile.me())?.name ?? '나'),
|
|
builder: (context, d) {
|
|
final root = d.hub.root;
|
|
if (root == null) return Scaffold(appBar: AppBar(), body: const EmptyNote('지워진 그룹이에요.'));
|
|
final kind = root.group.kind;
|
|
final color = Pal.ofKind(kind);
|
|
if (!root.open) {
|
|
return Scaffold(
|
|
appBar: AppBar(title: Text(root.group.name)),
|
|
body: Center(
|
|
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
|
const Icon(Icons.lock, size: 48, color: Pal.muted),
|
|
const SizedBox(height: 12),
|
|
FilledButton(onPressed: () => openGroup(context, root), child: const Text('비밀번호로 열기')),
|
|
]),
|
|
),
|
|
);
|
|
}
|
|
final levels = d.hub.levels;
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(root.group.name),
|
|
actions: [IconButton(tooltip: '목록으로 보기', onPressed: () => pushPage(context, GroupDetailScreen(groupId: rootId)), icon: const Icon(Icons.list))],
|
|
),
|
|
body: ListView(padding: const EdgeInsets.only(bottom: 32), children: [
|
|
if (levels.isEmpty)
|
|
const EmptyNote('아래에 칸이 없어요.\n목록으로 보기에서 하위 그룹을 만들어 보세요.')
|
|
else
|
|
RingView(
|
|
center: MeDot(d.me),
|
|
rings: [
|
|
[
|
|
for (final l in levels)
|
|
RingDot(
|
|
label: l.view.group.name,
|
|
sub: '${l.count}명',
|
|
color: l.count == 0 ? Pal.muted : color,
|
|
faded: l.count == 0,
|
|
onTap: () => pushPage(context, CircleGroupScreen(groupId: l.view.group.id)),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
const SectionHeader('가까운 사람'),
|
|
if (d.hub.closest.isEmpty) const EmptyNote('대화나 통화가 쌓이면 가까운 사람이 여기 보여요.'),
|
|
for (final c in d.hub.closest)
|
|
ListTile(
|
|
leading: Avatar(c.person.name, size: 40, color: color),
|
|
title: Text(c.person.name),
|
|
subtitle: Text([
|
|
if (c.subgroup != null) c.subgroup!,
|
|
if (kind == CardKinds.school && c.cohortDiff != null) c.cohort,
|
|
if (kind == CardKinds.company && c.position != null) c.position!,
|
|
].join(' · ')),
|
|
trailing: c.score > 0 ? Text('${c.score}', style: const TextStyle(color: Pal.accent, fontWeight: FontWeight.w700)) : null,
|
|
onTap: () => pushPage(context, PersonScreen(personId: c.person.id)),
|
|
),
|
|
]),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|