139 lines
4.6 KiB
Dart
139 lines
4.6 KiB
Dart
import 'package:dio/dio.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:island/models/activity.dart';
|
|
import 'package:island/pods/network.dart';
|
|
import 'package:material_symbols_icons/symbols.dart';
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:styled_widget/styled_widget.dart';
|
|
|
|
part 'check_in.g.dart';
|
|
|
|
@riverpod
|
|
Future<SnCheckInResult?> checkInResultToday(Ref ref) async {
|
|
final client = ref.watch(apiClientProvider);
|
|
try {
|
|
final resp = await client.get('/accounts/me/check-in');
|
|
return SnCheckInResult.fromJson(resp.data);
|
|
} catch (err) {
|
|
if (err is DioException) {
|
|
if (err.response?.statusCode == 404) {
|
|
return null;
|
|
}
|
|
}
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
class CheckInWidget extends HookConsumerWidget {
|
|
const CheckInWidget({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final todayResult = ref.watch(checkInResultTodayProvider);
|
|
|
|
return Card(
|
|
margin: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
spacing: 16,
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(8),
|
|
child: Container(
|
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
|
width: 56,
|
|
height: 56,
|
|
child:
|
|
Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Text(DateFormat('EEE').format(DateTime.now()))
|
|
.fontSize(16)
|
|
.bold()
|
|
.textColor(
|
|
Theme.of(context).colorScheme.onSecondaryContainer,
|
|
),
|
|
Text(DateFormat('MM/dd').format(DateTime.now()))
|
|
.fontSize(12)
|
|
.textColor(
|
|
Theme.of(context).colorScheme.onSecondaryContainer,
|
|
),
|
|
],
|
|
).center(),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: AnimatedSwitcher(
|
|
duration: const Duration(milliseconds: 300),
|
|
child: todayResult.when(
|
|
data: (result) {
|
|
if (result == null) return _CheckInNoneWidget();
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Text(
|
|
'checkInResultLevel${result.level}',
|
|
).tr().fontSize(15).bold(),
|
|
Text(
|
|
result.tips
|
|
.map(
|
|
(e) => '${e.isPositive ? '宜' : '忌'} ${e.title}',
|
|
)
|
|
.join(' · '),
|
|
).tr().fontSize(11),
|
|
],
|
|
);
|
|
},
|
|
loading: () => _CheckInNoneWidget(),
|
|
error:
|
|
(err, stack) => Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('error').tr().fontSize(15).bold(),
|
|
Text(err.toString()).fontSize(11),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
IconButton.outlined(
|
|
onPressed: () {},
|
|
icon: AnimatedSwitcher(
|
|
duration: const Duration(milliseconds: 300),
|
|
child: todayResult.when(
|
|
data:
|
|
(result) => Icon(
|
|
result == null
|
|
? Symbols.local_fire_department
|
|
: Symbols.event,
|
|
key: ValueKey(result != null),
|
|
),
|
|
loading: () => const Icon(Symbols.refresh),
|
|
error: (_, __) => const Icon(Symbols.error),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
).padding(horizontal: 16, vertical: 12),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _CheckInNoneWidget extends StatelessWidget {
|
|
const _CheckInNoneWidget();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Text('checkInNone').tr().fontSize(15).bold(),
|
|
Text('checkInNoneHint').tr().fontSize(11),
|
|
],
|
|
);
|
|
}
|
|
}
|