feat: 대시보드에 라이선스 만료 요약 및 Lookup 데이터 캐싱 시스템 구현
Some checks failed
Flutter Test & Quality Check / Test on macos-latest (push) Has been cancelled
Flutter Test & Quality Check / Test on ubuntu-latest (push) Has been cancelled
Flutter Test & Quality Check / Build APK (push) Has been cancelled

- License Expiry Summary API 연동 완료
  - 30/60/90일 내 만료 예정 라이선스 요약 표시
  - 대시보드 상단에 알림 카드로 통합
  - 만료 임박 순서로 색상 구분 (빨강/주황/노랑)

- Lookup 데이터 전역 캐싱 시스템 구축
  - LookupService 및 RemoteDataSource 생성
  - 전체 lookup 데이터 일괄 로드 및 캐싱
  - 타입별 필터링 지원

- 새로운 모델 추가
  - LicenseExpirySummary (Freezed)
  - LookupData, LookupCategory, LookupItem 모델

- CLAUDE.md 문서 업데이트
  - 미사용 API 활용 계획 추가
  - 구현 우선순위 정의

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
JiWoong Sul
2025-08-08 14:42:20 +09:00
parent 740a691406
commit 844c7bd92f
15 changed files with 2105 additions and 4 deletions

View File

@@ -0,0 +1,656 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'lookup_data.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
LookupData _$LookupDataFromJson(Map<String, dynamic> json) {
return _LookupData.fromJson(json);
}
/// @nodoc
mixin _$LookupData {
@JsonKey(name: 'equipment_types')
List<LookupItem> get equipmentTypes => throw _privateConstructorUsedError;
@JsonKey(name: 'equipment_statuses')
List<LookupItem> get equipmentStatuses => throw _privateConstructorUsedError;
@JsonKey(name: 'license_types')
List<LookupItem> get licenseTypes => throw _privateConstructorUsedError;
@JsonKey(name: 'manufacturers')
List<LookupItem> get manufacturers => throw _privateConstructorUsedError;
@JsonKey(name: 'user_roles')
List<LookupItem> get userRoles => throw _privateConstructorUsedError;
@JsonKey(name: 'company_statuses')
List<LookupItem> get companyStatuses => throw _privateConstructorUsedError;
@JsonKey(name: 'warehouse_types')
List<LookupItem> get warehouseTypes => throw _privateConstructorUsedError;
/// Serializes this LookupData to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of LookupData
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$LookupDataCopyWith<LookupData> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $LookupDataCopyWith<$Res> {
factory $LookupDataCopyWith(
LookupData value, $Res Function(LookupData) then) =
_$LookupDataCopyWithImpl<$Res, LookupData>;
@useResult
$Res call(
{@JsonKey(name: 'equipment_types') List<LookupItem> equipmentTypes,
@JsonKey(name: 'equipment_statuses') List<LookupItem> equipmentStatuses,
@JsonKey(name: 'license_types') List<LookupItem> licenseTypes,
@JsonKey(name: 'manufacturers') List<LookupItem> manufacturers,
@JsonKey(name: 'user_roles') List<LookupItem> userRoles,
@JsonKey(name: 'company_statuses') List<LookupItem> companyStatuses,
@JsonKey(name: 'warehouse_types') List<LookupItem> warehouseTypes});
}
/// @nodoc
class _$LookupDataCopyWithImpl<$Res, $Val extends LookupData>
implements $LookupDataCopyWith<$Res> {
_$LookupDataCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of LookupData
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? equipmentTypes = null,
Object? equipmentStatuses = null,
Object? licenseTypes = null,
Object? manufacturers = null,
Object? userRoles = null,
Object? companyStatuses = null,
Object? warehouseTypes = null,
}) {
return _then(_value.copyWith(
equipmentTypes: null == equipmentTypes
? _value.equipmentTypes
: equipmentTypes // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
equipmentStatuses: null == equipmentStatuses
? _value.equipmentStatuses
: equipmentStatuses // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
licenseTypes: null == licenseTypes
? _value.licenseTypes
: licenseTypes // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
manufacturers: null == manufacturers
? _value.manufacturers
: manufacturers // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
userRoles: null == userRoles
? _value.userRoles
: userRoles // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
companyStatuses: null == companyStatuses
? _value.companyStatuses
: companyStatuses // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
warehouseTypes: null == warehouseTypes
? _value.warehouseTypes
: warehouseTypes // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
) as $Val);
}
}
/// @nodoc
abstract class _$$LookupDataImplCopyWith<$Res>
implements $LookupDataCopyWith<$Res> {
factory _$$LookupDataImplCopyWith(
_$LookupDataImpl value, $Res Function(_$LookupDataImpl) then) =
__$$LookupDataImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{@JsonKey(name: 'equipment_types') List<LookupItem> equipmentTypes,
@JsonKey(name: 'equipment_statuses') List<LookupItem> equipmentStatuses,
@JsonKey(name: 'license_types') List<LookupItem> licenseTypes,
@JsonKey(name: 'manufacturers') List<LookupItem> manufacturers,
@JsonKey(name: 'user_roles') List<LookupItem> userRoles,
@JsonKey(name: 'company_statuses') List<LookupItem> companyStatuses,
@JsonKey(name: 'warehouse_types') List<LookupItem> warehouseTypes});
}
/// @nodoc
class __$$LookupDataImplCopyWithImpl<$Res>
extends _$LookupDataCopyWithImpl<$Res, _$LookupDataImpl>
implements _$$LookupDataImplCopyWith<$Res> {
__$$LookupDataImplCopyWithImpl(
_$LookupDataImpl _value, $Res Function(_$LookupDataImpl) _then)
: super(_value, _then);
/// Create a copy of LookupData
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? equipmentTypes = null,
Object? equipmentStatuses = null,
Object? licenseTypes = null,
Object? manufacturers = null,
Object? userRoles = null,
Object? companyStatuses = null,
Object? warehouseTypes = null,
}) {
return _then(_$LookupDataImpl(
equipmentTypes: null == equipmentTypes
? _value._equipmentTypes
: equipmentTypes // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
equipmentStatuses: null == equipmentStatuses
? _value._equipmentStatuses
: equipmentStatuses // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
licenseTypes: null == licenseTypes
? _value._licenseTypes
: licenseTypes // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
manufacturers: null == manufacturers
? _value._manufacturers
: manufacturers // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
userRoles: null == userRoles
? _value._userRoles
: userRoles // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
companyStatuses: null == companyStatuses
? _value._companyStatuses
: companyStatuses // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
warehouseTypes: null == warehouseTypes
? _value._warehouseTypes
: warehouseTypes // ignore: cast_nullable_to_non_nullable
as List<LookupItem>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$LookupDataImpl implements _LookupData {
const _$LookupDataImpl(
{@JsonKey(name: 'equipment_types')
required final List<LookupItem> equipmentTypes,
@JsonKey(name: 'equipment_statuses')
required final List<LookupItem> equipmentStatuses,
@JsonKey(name: 'license_types')
required final List<LookupItem> licenseTypes,
@JsonKey(name: 'manufacturers')
required final List<LookupItem> manufacturers,
@JsonKey(name: 'user_roles') required final List<LookupItem> userRoles,
@JsonKey(name: 'company_statuses')
required final List<LookupItem> companyStatuses,
@JsonKey(name: 'warehouse_types')
required final List<LookupItem> warehouseTypes})
: _equipmentTypes = equipmentTypes,
_equipmentStatuses = equipmentStatuses,
_licenseTypes = licenseTypes,
_manufacturers = manufacturers,
_userRoles = userRoles,
_companyStatuses = companyStatuses,
_warehouseTypes = warehouseTypes;
factory _$LookupDataImpl.fromJson(Map<String, dynamic> json) =>
_$$LookupDataImplFromJson(json);
final List<LookupItem> _equipmentTypes;
@override
@JsonKey(name: 'equipment_types')
List<LookupItem> get equipmentTypes {
if (_equipmentTypes is EqualUnmodifiableListView) return _equipmentTypes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_equipmentTypes);
}
final List<LookupItem> _equipmentStatuses;
@override
@JsonKey(name: 'equipment_statuses')
List<LookupItem> get equipmentStatuses {
if (_equipmentStatuses is EqualUnmodifiableListView)
return _equipmentStatuses;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_equipmentStatuses);
}
final List<LookupItem> _licenseTypes;
@override
@JsonKey(name: 'license_types')
List<LookupItem> get licenseTypes {
if (_licenseTypes is EqualUnmodifiableListView) return _licenseTypes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_licenseTypes);
}
final List<LookupItem> _manufacturers;
@override
@JsonKey(name: 'manufacturers')
List<LookupItem> get manufacturers {
if (_manufacturers is EqualUnmodifiableListView) return _manufacturers;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_manufacturers);
}
final List<LookupItem> _userRoles;
@override
@JsonKey(name: 'user_roles')
List<LookupItem> get userRoles {
if (_userRoles is EqualUnmodifiableListView) return _userRoles;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_userRoles);
}
final List<LookupItem> _companyStatuses;
@override
@JsonKey(name: 'company_statuses')
List<LookupItem> get companyStatuses {
if (_companyStatuses is EqualUnmodifiableListView) return _companyStatuses;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_companyStatuses);
}
final List<LookupItem> _warehouseTypes;
@override
@JsonKey(name: 'warehouse_types')
List<LookupItem> get warehouseTypes {
if (_warehouseTypes is EqualUnmodifiableListView) return _warehouseTypes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_warehouseTypes);
}
@override
String toString() {
return 'LookupData(equipmentTypes: $equipmentTypes, equipmentStatuses: $equipmentStatuses, licenseTypes: $licenseTypes, manufacturers: $manufacturers, userRoles: $userRoles, companyStatuses: $companyStatuses, warehouseTypes: $warehouseTypes)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$LookupDataImpl &&
const DeepCollectionEquality()
.equals(other._equipmentTypes, _equipmentTypes) &&
const DeepCollectionEquality()
.equals(other._equipmentStatuses, _equipmentStatuses) &&
const DeepCollectionEquality()
.equals(other._licenseTypes, _licenseTypes) &&
const DeepCollectionEquality()
.equals(other._manufacturers, _manufacturers) &&
const DeepCollectionEquality()
.equals(other._userRoles, _userRoles) &&
const DeepCollectionEquality()
.equals(other._companyStatuses, _companyStatuses) &&
const DeepCollectionEquality()
.equals(other._warehouseTypes, _warehouseTypes));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
const DeepCollectionEquality().hash(_equipmentTypes),
const DeepCollectionEquality().hash(_equipmentStatuses),
const DeepCollectionEquality().hash(_licenseTypes),
const DeepCollectionEquality().hash(_manufacturers),
const DeepCollectionEquality().hash(_userRoles),
const DeepCollectionEquality().hash(_companyStatuses),
const DeepCollectionEquality().hash(_warehouseTypes));
/// Create a copy of LookupData
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$LookupDataImplCopyWith<_$LookupDataImpl> get copyWith =>
__$$LookupDataImplCopyWithImpl<_$LookupDataImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$LookupDataImplToJson(
this,
);
}
}
abstract class _LookupData implements LookupData {
const factory _LookupData(
{@JsonKey(name: 'equipment_types')
required final List<LookupItem> equipmentTypes,
@JsonKey(name: 'equipment_statuses')
required final List<LookupItem> equipmentStatuses,
@JsonKey(name: 'license_types')
required final List<LookupItem> licenseTypes,
@JsonKey(name: 'manufacturers')
required final List<LookupItem> manufacturers,
@JsonKey(name: 'user_roles') required final List<LookupItem> userRoles,
@JsonKey(name: 'company_statuses')
required final List<LookupItem> companyStatuses,
@JsonKey(name: 'warehouse_types')
required final List<LookupItem> warehouseTypes}) = _$LookupDataImpl;
factory _LookupData.fromJson(Map<String, dynamic> json) =
_$LookupDataImpl.fromJson;
@override
@JsonKey(name: 'equipment_types')
List<LookupItem> get equipmentTypes;
@override
@JsonKey(name: 'equipment_statuses')
List<LookupItem> get equipmentStatuses;
@override
@JsonKey(name: 'license_types')
List<LookupItem> get licenseTypes;
@override
@JsonKey(name: 'manufacturers')
List<LookupItem> get manufacturers;
@override
@JsonKey(name: 'user_roles')
List<LookupItem> get userRoles;
@override
@JsonKey(name: 'company_statuses')
List<LookupItem> get companyStatuses;
@override
@JsonKey(name: 'warehouse_types')
List<LookupItem> get warehouseTypes;
/// Create a copy of LookupData
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$LookupDataImplCopyWith<_$LookupDataImpl> get copyWith =>
throw _privateConstructorUsedError;
}
LookupItem _$LookupItemFromJson(Map<String, dynamic> json) {
return _LookupItem.fromJson(json);
}
/// @nodoc
mixin _$LookupItem {
String get code => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
String? get description => throw _privateConstructorUsedError;
@JsonKey(name: 'display_order')
int? get displayOrder => throw _privateConstructorUsedError;
@JsonKey(name: 'is_active')
bool get isActive => throw _privateConstructorUsedError;
Map<String, dynamic>? get metadata => throw _privateConstructorUsedError;
/// Serializes this LookupItem to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of LookupItem
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$LookupItemCopyWith<LookupItem> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $LookupItemCopyWith<$Res> {
factory $LookupItemCopyWith(
LookupItem value, $Res Function(LookupItem) then) =
_$LookupItemCopyWithImpl<$Res, LookupItem>;
@useResult
$Res call(
{String code,
String name,
String? description,
@JsonKey(name: 'display_order') int? displayOrder,
@JsonKey(name: 'is_active') bool isActive,
Map<String, dynamic>? metadata});
}
/// @nodoc
class _$LookupItemCopyWithImpl<$Res, $Val extends LookupItem>
implements $LookupItemCopyWith<$Res> {
_$LookupItemCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of LookupItem
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? code = null,
Object? name = null,
Object? description = freezed,
Object? displayOrder = freezed,
Object? isActive = null,
Object? metadata = freezed,
}) {
return _then(_value.copyWith(
code: null == code
? _value.code
: code // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
displayOrder: freezed == displayOrder
? _value.displayOrder
: displayOrder // ignore: cast_nullable_to_non_nullable
as int?,
isActive: null == isActive
? _value.isActive
: isActive // ignore: cast_nullable_to_non_nullable
as bool,
metadata: freezed == metadata
? _value.metadata
: metadata // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,
) as $Val);
}
}
/// @nodoc
abstract class _$$LookupItemImplCopyWith<$Res>
implements $LookupItemCopyWith<$Res> {
factory _$$LookupItemImplCopyWith(
_$LookupItemImpl value, $Res Function(_$LookupItemImpl) then) =
__$$LookupItemImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String code,
String name,
String? description,
@JsonKey(name: 'display_order') int? displayOrder,
@JsonKey(name: 'is_active') bool isActive,
Map<String, dynamic>? metadata});
}
/// @nodoc
class __$$LookupItemImplCopyWithImpl<$Res>
extends _$LookupItemCopyWithImpl<$Res, _$LookupItemImpl>
implements _$$LookupItemImplCopyWith<$Res> {
__$$LookupItemImplCopyWithImpl(
_$LookupItemImpl _value, $Res Function(_$LookupItemImpl) _then)
: super(_value, _then);
/// Create a copy of LookupItem
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? code = null,
Object? name = null,
Object? description = freezed,
Object? displayOrder = freezed,
Object? isActive = null,
Object? metadata = freezed,
}) {
return _then(_$LookupItemImpl(
code: null == code
? _value.code
: code // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
description: freezed == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String?,
displayOrder: freezed == displayOrder
? _value.displayOrder
: displayOrder // ignore: cast_nullable_to_non_nullable
as int?,
isActive: null == isActive
? _value.isActive
: isActive // ignore: cast_nullable_to_non_nullable
as bool,
metadata: freezed == metadata
? _value._metadata
: metadata // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$LookupItemImpl implements _LookupItem {
const _$LookupItemImpl(
{required this.code,
required this.name,
this.description,
@JsonKey(name: 'display_order') this.displayOrder,
@JsonKey(name: 'is_active') this.isActive = true,
final Map<String, dynamic>? metadata})
: _metadata = metadata;
factory _$LookupItemImpl.fromJson(Map<String, dynamic> json) =>
_$$LookupItemImplFromJson(json);
@override
final String code;
@override
final String name;
@override
final String? description;
@override
@JsonKey(name: 'display_order')
final int? displayOrder;
@override
@JsonKey(name: 'is_active')
final bool isActive;
final Map<String, dynamic>? _metadata;
@override
Map<String, dynamic>? get metadata {
final value = _metadata;
if (value == null) return null;
if (_metadata is EqualUnmodifiableMapView) return _metadata;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(value);
}
@override
String toString() {
return 'LookupItem(code: $code, name: $name, description: $description, displayOrder: $displayOrder, isActive: $isActive, metadata: $metadata)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$LookupItemImpl &&
(identical(other.code, code) || other.code == code) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.displayOrder, displayOrder) ||
other.displayOrder == displayOrder) &&
(identical(other.isActive, isActive) ||
other.isActive == isActive) &&
const DeepCollectionEquality().equals(other._metadata, _metadata));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, code, name, description,
displayOrder, isActive, const DeepCollectionEquality().hash(_metadata));
/// Create a copy of LookupItem
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$LookupItemImplCopyWith<_$LookupItemImpl> get copyWith =>
__$$LookupItemImplCopyWithImpl<_$LookupItemImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$LookupItemImplToJson(
this,
);
}
}
abstract class _LookupItem implements LookupItem {
const factory _LookupItem(
{required final String code,
required final String name,
final String? description,
@JsonKey(name: 'display_order') final int? displayOrder,
@JsonKey(name: 'is_active') final bool isActive,
final Map<String, dynamic>? metadata}) = _$LookupItemImpl;
factory _LookupItem.fromJson(Map<String, dynamic> json) =
_$LookupItemImpl.fromJson;
@override
String get code;
@override
String get name;
@override
String? get description;
@override
@JsonKey(name: 'display_order')
int? get displayOrder;
@override
@JsonKey(name: 'is_active')
bool get isActive;
@override
Map<String, dynamic>? get metadata;
/// Create a copy of LookupItem
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$LookupItemImplCopyWith<_$LookupItemImpl> get copyWith =>
throw _privateConstructorUsedError;
}