Check-in basis

This commit is contained in:
2025-05-08 23:04:06 +08:00
parent 039f5b202f
commit ec2233fbaf
9 changed files with 755 additions and 158 deletions

View File

@ -1,11 +1,138 @@
import 'package:flutter/widgets.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) {
return const Placeholder();
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),
],
);
}
}

View File

@ -0,0 +1,30 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'check_in.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$checkInResultTodayHash() =>
r'0e2af6c1f419b2ee74ee38b6fb5d8071498e75c8';
/// See also [checkInResultToday].
@ProviderFor(checkInResultToday)
final checkInResultTodayProvider =
AutoDisposeFutureProvider<SnCheckInResult?>.internal(
checkInResultToday,
name: r'checkInResultTodayProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$checkInResultTodayHash,
dependencies: null,
allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef CheckInResultTodayRef = AutoDisposeFutureProviderRef<SnCheckInResult?>;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package