✨ Event dairy
This commit is contained in:
@@ -941,5 +941,6 @@
|
|||||||
"pinPostReplyDisabledHint": "This post is not a reply",
|
"pinPostReplyDisabledHint": "This post is not a reply",
|
||||||
"pin": "Pin",
|
"pin": "Pin",
|
||||||
"unpinPostHint": "Are you sure you want to unpin this post?",
|
"unpinPostHint": "Are you sure you want to unpin this post?",
|
||||||
"all": "All"
|
"all": "All",
|
||||||
|
"statusPresent": "Present"
|
||||||
}
|
}
|
||||||
|
@@ -855,5 +855,6 @@
|
|||||||
"newSecretGenerated": "已生成新密钥",
|
"newSecretGenerated": "已生成新密钥",
|
||||||
"copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。",
|
"copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。",
|
||||||
"expiresIn": "过期时间(秒)",
|
"expiresIn": "过期时间(秒)",
|
||||||
"isOidc": "OIDC 兼容"
|
"isOidc": "OIDC 兼容",
|
||||||
|
"statusPresent": "至今"
|
||||||
}
|
}
|
||||||
|
@@ -54,7 +54,7 @@ sealed class SnEventCalendarEntry with _$SnEventCalendarEntry {
|
|||||||
const factory SnEventCalendarEntry({
|
const factory SnEventCalendarEntry({
|
||||||
required DateTime date,
|
required DateTime date,
|
||||||
required SnCheckInResult? checkInResult,
|
required SnCheckInResult? checkInResult,
|
||||||
required List<dynamic> statuses,
|
required List<SnAccountStatus> statuses,
|
||||||
}) = _SnEventCalendarEntry;
|
}) = _SnEventCalendarEntry;
|
||||||
|
|
||||||
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@@ -861,7 +861,7 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnEventCalendarEntry {
|
mixin _$SnEventCalendarEntry {
|
||||||
|
|
||||||
DateTime get date; SnCheckInResult? get checkInResult; List<dynamic> get statuses;
|
DateTime get date; SnCheckInResult? get checkInResult; List<SnAccountStatus> get statuses;
|
||||||
/// Create a copy of SnEventCalendarEntry
|
/// Create a copy of SnEventCalendarEntry
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -894,7 +894,7 @@ abstract mixin class $SnEventCalendarEntryCopyWith<$Res> {
|
|||||||
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -916,7 +916,7 @@ class _$SnEventCalendarEntryCopyWithImpl<$Res>
|
|||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<SnAccountStatus>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnEventCalendarEntry
|
/// Create a copy of SnEventCalendarEntry
|
||||||
@@ -1010,7 +1010,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry() when $default != null:
|
case _SnEventCalendarEntry() when $default != null:
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||||
@@ -1031,7 +1031,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry():
|
case _SnEventCalendarEntry():
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||||
@@ -1048,7 +1048,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry() when $default != null:
|
case _SnEventCalendarEntry() when $default != null:
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||||
@@ -1063,13 +1063,13 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
||||||
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<dynamic> statuses}): _statuses = statuses;
|
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<SnAccountStatus> statuses}): _statuses = statuses;
|
||||||
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
||||||
|
|
||||||
@override final DateTime date;
|
@override final DateTime date;
|
||||||
@override final SnCheckInResult? checkInResult;
|
@override final SnCheckInResult? checkInResult;
|
||||||
final List<dynamic> _statuses;
|
final List<SnAccountStatus> _statuses;
|
||||||
@override List<dynamic> get statuses {
|
@override List<SnAccountStatus> get statuses {
|
||||||
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_statuses);
|
return EqualUnmodifiableListView(_statuses);
|
||||||
@@ -1109,7 +1109,7 @@ abstract mixin class _$SnEventCalendarEntryCopyWith<$Res> implements $SnEventCal
|
|||||||
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1131,7 +1131,7 @@ class __$SnEventCalendarEntryCopyWithImpl<$Res>
|
|||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<SnAccountStatus>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -87,7 +87,10 @@ _SnEventCalendarEntry _$SnEventCalendarEntryFromJson(
|
|||||||
: SnCheckInResult.fromJson(
|
: SnCheckInResult.fromJson(
|
||||||
json['check_in_result'] as Map<String, dynamic>,
|
json['check_in_result'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
statuses: json['statuses'] as List<dynamic>,
|
statuses:
|
||||||
|
(json['statuses'] as List<dynamic>)
|
||||||
|
.map((e) => SnAccountStatus.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
||||||
@@ -95,5 +98,5 @@ Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
|||||||
) => <String, dynamic>{
|
) => <String, dynamic>{
|
||||||
'date': instance.date.toIso8601String(),
|
'date': instance.date.toIso8601String(),
|
||||||
'check_in_result': instance.checkInResult?.toJson(),
|
'check_in_result': instance.checkInResult?.toJson(),
|
||||||
'statuses': instance.statuses,
|
'statuses': instance.statuses.map((e) => e.toJson()).toList(),
|
||||||
};
|
};
|
||||||
|
@@ -2,7 +2,9 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/account.dart';
|
||||||
import 'package:island/models/activity.dart';
|
import 'package:island/models/activity.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:island/widgets/account/event_details_widget.dart';
|
import 'package:island/widgets/account/event_details_widget.dart';
|
||||||
import 'package:table_calendar/table_calendar.dart';
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
@@ -87,25 +89,57 @@ class EventCalendarWidget extends HookConsumerWidget {
|
|||||||
return Center(child: Text(text));
|
return Center(child: Text(text));
|
||||||
},
|
},
|
||||||
markerBuilder: (context, day, events) {
|
markerBuilder: (context, day, events) {
|
||||||
var checkInResult =
|
final checkInResult =
|
||||||
events.whereType<SnCheckInResult>().firstOrNull;
|
events.whereType<SnCheckInResult>().firstOrNull;
|
||||||
|
final statuses = events.whereType<SnAccountStatus>().toList();
|
||||||
|
|
||||||
|
final textColor =
|
||||||
|
isSameDay(selectedDay.value, day)
|
||||||
|
? Theme.of(context).colorScheme.onPrimary
|
||||||
|
: isSameDay(DateTime.now(), day)
|
||||||
|
? Theme.of(context).colorScheme.onPrimary
|
||||||
|
: Theme.of(context).colorScheme.onSurface;
|
||||||
|
|
||||||
|
final shadow =
|
||||||
|
isSameDay(selectedDay.value, day) ||
|
||||||
|
isSameDay(DateTime.now(), day)
|
||||||
|
? [
|
||||||
|
Shadow(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
offset: const Offset(0, 1),
|
||||||
|
blurRadius: 4,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: null;
|
||||||
|
|
||||||
if (checkInResult != null) {
|
if (checkInResult != null) {
|
||||||
return Positioned(
|
return Positioned(
|
||||||
top: 32,
|
top: 32,
|
||||||
child: Text(
|
child: Row(
|
||||||
|
spacing: 2,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
'checkInResultT${checkInResult.level}'.tr(),
|
'checkInResultT${checkInResult.level}'.tr(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
color:
|
color: textColor,
|
||||||
isSameDay(selectedDay.value, day)
|
shadows: shadow,
|
||||||
? Theme.of(context).colorScheme.onPrimaryContainer
|
|
||||||
: isSameDay(DateTime.now(), day)
|
|
||||||
? Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.onSecondaryContainer
|
|
||||||
: Theme.of(context).colorScheme.onSurface,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (statuses.isNotEmpty) ...[
|
||||||
|
Icon(
|
||||||
|
switch (statuses.first.attitude) {
|
||||||
|
0 => Symbols.sentiment_satisfied,
|
||||||
|
2 => Symbols.sentiment_dissatisfied,
|
||||||
|
_ => Symbols.sentiment_neutral,
|
||||||
|
},
|
||||||
|
size: 12,
|
||||||
|
color: textColor,
|
||||||
|
shadows: shadow,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:island/models/activity.dart';
|
import 'package:island/models/activity.dart';
|
||||||
|
import 'package:island/services/time.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@@ -53,6 +54,33 @@ class EventDetailsWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(top: 8),
|
).padding(top: 8),
|
||||||
|
if (event!.statuses.isNotEmpty) ...[
|
||||||
|
const Gap(16),
|
||||||
|
Text('statusLabel').tr().fontSize(16).bold(),
|
||||||
|
],
|
||||||
|
for (final status in event!.statuses) ...[
|
||||||
|
Row(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
Icon(switch (status.attitude) {
|
||||||
|
0 => Symbols.sentiment_satisfied,
|
||||||
|
2 => Symbols.sentiment_dissatisfied,
|
||||||
|
_ => Symbols.sentiment_neutral,
|
||||||
|
}),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(status.label),
|
||||||
|
Text(
|
||||||
|
'${status.createdAt.formatSystem()} - ${status.clearedAt?.formatSystem() ?? 'present'.tr()}',
|
||||||
|
).fontSize(11).opacity(0.8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(vertical: 8),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (event?.checkInResult == null && (event?.statuses.isEmpty ?? true))
|
if (event?.checkInResult == null && (event?.statuses.isEmpty ?? true))
|
||||||
|
Reference in New Issue
Block a user