@@ -177,19 +177,19 @@ Row(
177177 heroTag: "reject",
178178 onPressed: _nextUser,
179179 backgroundColor: Colors.deepOrange,
180- child: const Icon(Icons.close, color: Colors.white ),
180+ child: const Icon(Icons.close),
181181 ),
182182 FloatingActionButton(
183183 heroTag: "info",
184184 onPressed: () => _showUserInfoBottomSheet(context),
185185 backgroundColor: Colors.orange.shade600,
186- child: const Icon(Icons.info, color: Colors.white ),
186+ child: const Icon(Icons.info),
187187 ),
188188 FloatingActionButton(
189189 heroTag: "accept",
190190 onPressed: _matchSuccess,
191191 backgroundColor: Colors.orange,
192- child: const Icon(Icons.favorite, color: Colors.white ),
192+ child: const Icon(Icons.favorite),
193193 ),
194194 ],
195195)
@@ -410,4 +410,168 @@ Expanded(
410410 ] ,
411411 ),
412412 ),
413- ),
413+ ),
414+
415+ class _ UserCard extends StatelessWidget {
416+ final UserModel user;
417+ final int matchScore;
418+ final String matchType;
419+ final VoidCallback onLike;
420+ final VoidCallback onDislike;
421+ const _ UserCard({
422+ required this.user,
423+ required this.matchScore,
424+ required this.matchType,
425+ required this.onLike,
426+ required this.onDislike,
427+ });
428+
429+ String getAgeText(String learnerBirth) {
430+ try {
431+ final year = int.tryParse(learnerBirth.substring(0, 4));
432+ if (year != null) {
433+ final age = DateTime.now().year - year;
434+ return '年齡:約$age 歲';
435+ }
436+ } catch (_ ) {}
437+ return '年齡:未知';
438+ }
439+
440+ @override
441+ Widget build(BuildContext context) {
442+ return Card(
443+ elevation: 12,
444+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
445+ margin: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
446+ child: Padding(
447+ padding: const EdgeInsets.all(24.0),
448+ child: Column(
449+ mainAxisSize: MainAxisSize.min,
450+ children: [
451+ // 頭像
452+ CircleAvatar(
453+ radius: 40,
454+ backgroundColor: Colors.orange.shade100,
455+ child: Text(user.name.isNotEmpty ? user.name[ 0] : '?',
456+ style: const TextStyle(fontSize: 36, color: Colors.orange)),
457+ ),
458+ const SizedBox(height: 12),
459+ Text(user.name, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
460+ const SizedBox(height: 4),
461+ Text(getAgeText(user.learnerBirth)),
462+ Text('地區:${user.address}'),
463+ const Divider(height: 24),
464+ Text('興趣:${user.habits.join(", ")}'),
465+ Text('可分享:${user.share.join(", ")}'),
466+ Text('想學習:${user.ask.join(", ")}'),
467+ const SizedBox(height: 12),
468+ // 配對分數
469+ if (matchScore >= 0)
470+ Chip(
471+ label: Text('$matchType配對分數:$matchScore',
472+ style: const TextStyle(color: Colors.white)),
473+ backgroundColor: Colors.orange,
474+ ),
475+ const SizedBox(height: 16),
476+ Row(
477+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
478+ children: [
479+ FloatingActionButton(
480+ heroTag: null,
481+ onPressed: onDislike,
482+ backgroundColor: Colors.red,
483+ child: const Icon(Icons.close),
484+ ),
485+ FloatingActionButton(
486+ heroTag: null,
487+ onPressed: onLike,
488+ backgroundColor: Colors.green,
489+ child: const Icon(Icons.favorite),
490+ ),
491+ ] ,
492+ )
493+ ] ,
494+ ),
495+ ),
496+ );
497+ }
498+ }
499+
500+ class MatchHistoryScreen extends StatefulWidget {
501+ const MatchHistoryScreen({super.key});
502+ @override
503+ State<MatchHistoryScreen > createState() => _ MatchHistoryScreenState();
504+ }
505+
506+ class _ MatchHistoryScreenState extends State<MatchHistoryScreen > {
507+ List<Map<String, dynamic>> records = [ ] ;
508+ bool isLoading = true;
509+
510+ @override
511+ void initState() {
512+ super.initState();
513+ _ loadRecords();
514+ }
515+
516+ Future<void > _ loadRecords() async {
517+ final user = FirebaseAuth.instance.currentUser;
518+ if (user == null) return;
519+ final ref = FirebaseDatabase.instance.ref('matches/${user.uid}');
520+ final snapshot = await ref.get();
521+ if (snapshot.exists && snapshot.value != null) {
522+ final data = Map<String, dynamic>.from(snapshot.value as Map);
523+ setState(() {
524+ records = data.entries.map((e) {
525+ final v = Map<String, dynamic>.from(e.value);
526+ v[ 'uid'] = e.key;
527+ return v;
528+ }).toList();
529+ isLoading = false;
530+ });
531+ } else {
532+ setState(() {
533+ records = [ ] ;
534+ isLoading = false;
535+ });
536+ }
537+ }
538+
539+ @override
540+ Widget build(BuildContext context) {
541+ return Scaffold(
542+ appBar: AppBar(title: const Text('配對紀錄')),
543+ body: isLoading
544+ ? const Center(child: CircularProgressIndicator())
545+ : ListView.separated(
546+ itemCount: records.length,
547+ separatorBuilder: (_ , __ ) => const Divider(),
548+ itemBuilder: (context, i) {
549+ final r = records[ i] ;
550+ return ListTile(
551+ leading: const Icon(Icons.person),
552+ title: Text('用戶ID: ${r[ 'uid'] }'),
553+ subtitle: Text('${r[ 'matchType'] }分數: ${r[ 'score'] }'),
554+ trailing: Text(
555+ DateTime.fromMillisecondsSinceEpoch(r[ 'timestamp'] )
556+ .toLocal()
557+ .toString()
558+ .substring(0, 16),
559+ ),
560+ );
561+ },
562+ ),
563+ );
564+ }
565+ }
566+
567+ actions: [
568+ IconButton(
569+ icon: const Icon(Icons.history),
570+ onPressed: () {
571+ Navigator.push(
572+ context,
573+ MaterialPageRoute(builder: (_ ) => const MatchHistoryScreen()),
574+ );
575+ },
576+ ),
577+ ] ,
0 commit comments