211 lines
7.1 KiB
Dart
211 lines
7.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import '../../../models/event_model.dart';
|
|
import '../../../utils/url_utils.dart';
|
|
import '../../../utils/enum_mappings.dart';
|
|
import '../../../theme/badges.dart';
|
|
|
|
class BasicInfoTab extends StatelessWidget {
|
|
final Event event;
|
|
final int participantsCount;
|
|
final VoidCallback onShareEvent;
|
|
final VoidCallback onSetEventReminders;
|
|
|
|
const BasicInfoTab({
|
|
super.key,
|
|
required this.event,
|
|
required this.participantsCount,
|
|
required this.onShareEvent,
|
|
required this.onSetEventReminders,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Wrap(
|
|
spacing: 8,
|
|
runSpacing: 4,
|
|
children: [
|
|
_badge(
|
|
text: getEventTypeLabel(event.type),
|
|
color: _getTypeColor(getEventTypeLabel(event.type)),
|
|
icon: _getTypeIcon(getEventTypeLabel(event.type)),
|
|
),
|
|
if (event.status != null)
|
|
BadgeStyles.eventStatus(
|
|
getEventStatusLabel(event.status),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.share),
|
|
onPressed: onShareEvent,
|
|
tooltip: '이벤트 공유',
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
|
|
if (event.description != null && event.description!.isNotEmpty) ...[
|
|
const Text('설명', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 8),
|
|
Container(
|
|
width: double.infinity,
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[100],
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Text(event.description ?? ''),
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
|
|
const Text('이벤트 정보', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 8),
|
|
_infoRow(Icons.calendar_today, '시작: ${DateFormat('yyyy-MM-dd HH:mm').format(event.startDate)}'),
|
|
if (event.endDate != null)
|
|
_infoRow(Icons.calendar_today, '종료: ${DateFormat('yyyy-MM-dd HH:mm').format(event.endDate!)}'),
|
|
if (event.location != null && event.location!.isNotEmpty)
|
|
_infoRow(Icons.location_on, '장소: ${event.location}'),
|
|
if (event.maxParticipants != null)
|
|
_infoRow(Icons.people, '최대 참가자: ${event.maxParticipants}명'),
|
|
if (event.gameCount != null)
|
|
_infoRow(Icons.sports, '게임 수: ${event.gameCount}게임'),
|
|
if (event.participantFee != null)
|
|
_infoRow(
|
|
Icons.attach_money,
|
|
event.participantFee == 0
|
|
? '참가비: 무료'
|
|
: '참가비: ${NumberFormat.currency(locale: 'ko_KR', symbol: '₩', decimalDigits: 0).format(event.participantFee)}',
|
|
),
|
|
if (event.registrationDeadline != null)
|
|
_infoRow(Icons.timer, '신청마감: ${DateFormat('yyyy-MM-dd HH:mm').format(event.registrationDeadline!)}'),
|
|
const SizedBox(height: 16),
|
|
|
|
const Text('공개 접근', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 8),
|
|
if (event.publicHash != null && event.publicHash!.isNotEmpty) ...[
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: _infoRow(
|
|
Icons.link,
|
|
UrlUtils.getEventPublicUrl(event.publicHash!),
|
|
isSelectable: true,
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.copy),
|
|
onPressed: () {
|
|
final publicUrl = UrlUtils.getEventPublicUrl(event.publicHash!);
|
|
UrlUtils.copyUrlToClipboard(context, publicUrl);
|
|
},
|
|
tooltip: 'URL 복사',
|
|
),
|
|
],
|
|
),
|
|
],
|
|
if (event.accessPassword != null && event.accessPassword!.isNotEmpty)
|
|
_infoRow(Icons.lock, '접근 비밀번호: ${event.accessPassword}'),
|
|
|
|
const SizedBox(height: 16),
|
|
const Text('참가자 정보', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 8),
|
|
_infoRow(Icons.people, '현재 참가자: $participantsCount명'),
|
|
|
|
const SizedBox(height: 24),
|
|
ElevatedButton.icon(
|
|
onPressed: onSetEventReminders,
|
|
icon: const Icon(Icons.notifications_active),
|
|
label: const Text('알림 설정'),
|
|
style: ElevatedButton.styleFrom(
|
|
foregroundColor: Colors.white,
|
|
backgroundColor: Colors.green,
|
|
minimumSize: const Size(double.infinity, 48),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _infoRow(IconData icon, String text, {bool isSelectable = false}) {
|
|
final textWidget = isSelectable
|
|
? SelectableText(
|
|
text,
|
|
maxLines: 3,
|
|
onTap: () {},
|
|
)
|
|
: Text(text);
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(icon, size: 20, color: Colors.blueGrey),
|
|
const SizedBox(width: 8),
|
|
Expanded(child: textWidget),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _badge({required String text, required Color color, required IconData icon}) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: color.withOpacity(0.15),
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: color.withOpacity(0.3)),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(icon, size: 16, color: color),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
text,
|
|
style: TextStyle(fontWeight: FontWeight.w600, color: color),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Color _getTypeColor(String type) {
|
|
switch (type) {
|
|
case '정기전':
|
|
return Colors.indigo;
|
|
case '연습':
|
|
return Colors.teal;
|
|
case '대회':
|
|
return Colors.deepOrange;
|
|
default:
|
|
return Colors.blueGrey;
|
|
}
|
|
}
|
|
|
|
IconData _getTypeIcon(String type) {
|
|
switch (type) {
|
|
case '정기전':
|
|
return Icons.event;
|
|
case '연습':
|
|
return Icons.fitness_center;
|
|
case '대회':
|
|
return Icons.emoji_events;
|
|
default:
|
|
return Icons.info;
|
|
}
|
|
}
|
|
}
|