Add API contract Dart models

This commit is contained in:
Codex
2026-07-02 13:00:17 +09:00
parent d890893966
commit 6d05f36dcc
10 changed files with 864 additions and 6 deletions
+23
View File
@@ -0,0 +1,23 @@
class ApiError {
const ApiError({
required this.error,
required this.code,
required this.details,
});
final String error;
final String code;
final Map<String, dynamic> details;
factory ApiError.fromJson(Map<String, dynamic> json) {
return ApiError(
error: json['error'] as String? ?? '',
code: json['code'] as String? ?? '',
details: json['details'] as Map<String, dynamic>? ?? {},
);
}
Map<String, dynamic> toJson() {
return {'error': error, 'code': code, 'details': details};
}
}
@@ -0,0 +1,238 @@
import '../../directory/domain/employee.dart';
class LoginDeviceInfo {
const LoginDeviceInfo({
required this.platform,
required this.appVersion,
required this.deviceName,
});
final String platform;
final String appVersion;
final String deviceName;
factory LoginDeviceInfo.fromJson(Map<String, dynamic> json) {
return LoginDeviceInfo(
platform: json['platform'] as String? ?? '',
appVersion: json['appVersion'] as String? ?? '',
deviceName: json['deviceName'] as String? ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'platform': platform,
'appVersion': appVersion,
'deviceName': deviceName,
};
}
}
class PhoneLoginRequest {
const PhoneLoginRequest({required this.phoneNumber, required this.device});
final String phoneNumber;
final LoginDeviceInfo device;
Map<String, dynamic> toJson() {
return {'phoneNumber': phoneNumber, 'device': device.toJson()};
}
}
class LoginUser {
const LoginUser({
required this.id,
required this.name,
required this.phoneNumber,
required this.tenantId,
required this.tenantName,
required this.tenantSlug,
this.department,
this.grade,
this.position,
this.jobTitle,
});
final String id;
final String name;
final String phoneNumber;
final String tenantId;
final String tenantName;
final String tenantSlug;
final String? department;
final String? grade;
final String? position;
final String? jobTitle;
factory LoginUser.fromJson(Map<String, dynamic> json) {
return LoginUser(
id: json['id'] as String? ?? '',
name: json['name'] as String? ?? '',
phoneNumber: json['phoneNumber'] as String? ?? '',
tenantId: json['tenantId'] as String? ?? '',
tenantName: json['tenantName'] as String? ?? '',
tenantSlug: json['tenantSlug'] as String? ?? '',
department: json['department'] as String?,
grade: json['grade'] as String?,
position: json['position'] as String?,
jobTitle: json['jobTitle'] as String?,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'phoneNumber': phoneNumber,
'tenantId': tenantId,
'tenantName': tenantName,
'tenantSlug': tenantSlug,
'department': department,
'grade': grade,
'position': position,
'jobTitle': jobTitle,
};
}
}
class PhoneLoginResponse {
const PhoneLoginResponse({
required this.status,
required this.token,
required this.expiresAt,
required this.user,
});
final String status;
final String token;
final DateTime expiresAt;
final LoginUser user;
factory PhoneLoginResponse.fromJson(Map<String, dynamic> json) {
return PhoneLoginResponse(
status: json['status'] as String? ?? '',
token: json['token'] as String? ?? '',
expiresAt: DateTime.parse(json['expiresAt'] as String),
user: LoginUser.fromJson(json['user'] as Map<String, dynamic>? ?? {}),
);
}
Map<String, dynamic> toJson() {
return {
'status': status,
'token': token,
'expiresAt': expiresAt.toUtc().toIso8601String(),
'user': user.toJson(),
};
}
}
class UserPermissions {
const UserPermissions({
required this.directory,
required this.organization,
required this.favoritesSync,
});
final bool directory;
final bool organization;
final bool favoritesSync;
factory UserPermissions.fromJson(Map<String, dynamic> json) {
return UserPermissions(
directory: json['directory'] as bool? ?? false,
organization: json['organization'] as bool? ?? false,
favoritesSync: json['favoritesSync'] as bool? ?? false,
);
}
Map<String, dynamic> toJson() {
return {
'directory': directory,
'organization': organization,
'favoritesSync': favoritesSync,
};
}
}
class CurrentUser {
const CurrentUser({
required this.id,
required this.name,
required this.phoneNumber,
required this.email,
required this.tenantId,
required this.tenantName,
required this.tenantSlug,
required this.permissions,
this.department,
this.grade,
this.position,
this.jobTitle,
});
final String id;
final String name;
final String phoneNumber;
final String email;
final String tenantId;
final String tenantName;
final String tenantSlug;
final UserPermissions permissions;
final String? department;
final String? grade;
final String? position;
final String? jobTitle;
factory CurrentUser.fromJson(Map<String, dynamic> json) {
return CurrentUser(
id: json['id'] as String? ?? '',
name: json['name'] as String? ?? '',
phoneNumber: json['phoneNumber'] as String? ?? '',
email: json['email'] as String? ?? '',
tenantId: json['tenantId'] as String? ?? '',
tenantName: json['tenantName'] as String? ?? '',
tenantSlug: json['tenantSlug'] as String? ?? '',
permissions: UserPermissions.fromJson(
json['permissions'] as Map<String, dynamic>? ?? {},
),
department: json['department'] as String?,
grade: json['grade'] as String?,
position: json['position'] as String?,
jobTitle: json['jobTitle'] as String?,
);
}
Employee toEmployee() {
return Employee(
id: id,
name: name,
phoneNumber: phoneNumber,
email: email,
tenantId: tenantId,
tenantName: tenantName,
tenantSlug: tenantSlug,
department: department,
grade: grade,
position: position,
jobTitle: jobTitle,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'phoneNumber': phoneNumber,
'email': email,
'tenantId': tenantId,
'tenantName': tenantName,
'tenantSlug': tenantSlug,
'department': department,
'grade': grade,
'position': position,
'jobTitle': jobTitle,
'permissions': permissions.toJson(),
};
}
}
@@ -0,0 +1,233 @@
class Employee {
const Employee({
required this.id,
required this.name,
required this.phoneNumber,
this.phoneDisplay,
this.email,
required this.tenantId,
required this.tenantName,
required this.tenantSlug,
this.department,
this.grade,
this.position,
this.jobTitle,
this.status,
this.profileImageUrl,
this.sortOrder,
});
final String id;
final String name;
final String phoneNumber;
final String? phoneDisplay;
final String? email;
final String tenantId;
final String tenantName;
final String tenantSlug;
final String? department;
final String? grade;
final String? position;
final String? jobTitle;
final String? status;
final String? profileImageUrl;
final int? sortOrder;
factory Employee.fromJson(Map<String, dynamic> json) {
return Employee(
id: json['id'] as String? ?? '',
name: json['name'] as String? ?? '',
phoneNumber: json['phoneNumber'] as String? ?? '',
phoneDisplay: json['phoneDisplay'] as String?,
email: json['email'] as String?,
tenantId: json['tenantId'] as String? ?? '',
tenantName: json['tenantName'] as String? ?? '',
tenantSlug: json['tenantSlug'] as String? ?? '',
department: json['department'] as String?,
grade: json['grade'] as String?,
position: json['position'] as String?,
jobTitle: json['jobTitle'] as String?,
status: json['status'] as String?,
profileImageUrl: json['profileImageUrl'] as String?,
sortOrder: json['sortOrder'] as int?,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'phoneNumber': phoneNumber,
'phoneDisplay': phoneDisplay,
'email': email,
'tenantId': tenantId,
'tenantName': tenantName,
'tenantSlug': tenantSlug,
'department': department,
'grade': grade,
'position': position,
'jobTitle': jobTitle,
'status': status,
'profileImageUrl': profileImageUrl,
'sortOrder': sortOrder,
};
}
}
class TenantRef {
const TenantRef({
required this.id,
required this.name,
required this.slug,
required this.type,
this.parentId,
});
final String id;
final String name;
final String slug;
final String type;
final String? parentId;
factory TenantRef.fromJson(Map<String, dynamic> json) {
return TenantRef(
id: json['id'] as String? ?? '',
name: json['name'] as String? ?? '',
slug: json['slug'] as String? ?? '',
type: json['type'] as String? ?? '',
parentId: json['parentId'] as String?,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'slug': slug,
'type': type,
'parentId': parentId,
};
}
}
class EmployeeActions {
const EmployeeActions({
required this.call,
required this.sms,
required this.email,
});
final bool call;
final bool sms;
final bool email;
factory EmployeeActions.fromJson(Map<String, dynamic> json) {
return EmployeeActions(
call: json['call'] as bool? ?? false,
sms: json['sms'] as bool? ?? false,
email: json['email'] as bool? ?? false,
);
}
Map<String, dynamic> toJson() {
return {'call': call, 'sms': sms, 'email': email};
}
}
class EmployeeDetail extends Employee {
const EmployeeDetail({
required super.id,
required super.name,
required super.phoneNumber,
super.phoneDisplay,
super.email,
required super.tenantId,
required super.tenantName,
required super.tenantSlug,
super.department,
super.grade,
super.position,
super.jobTitle,
super.status,
super.profileImageUrl,
super.sortOrder,
required this.joinedTenants,
required this.actions,
});
final List<TenantRef> joinedTenants;
final EmployeeActions actions;
factory EmployeeDetail.fromJson(Map<String, dynamic> json) {
return EmployeeDetail(
id: json['id'] as String? ?? '',
name: json['name'] as String? ?? '',
phoneNumber: json['phoneNumber'] as String? ?? '',
phoneDisplay: json['phoneDisplay'] as String?,
email: json['email'] as String?,
tenantId: json['tenantId'] as String? ?? '',
tenantName: json['tenantName'] as String? ?? '',
tenantSlug: json['tenantSlug'] as String? ?? '',
department: json['department'] as String?,
grade: json['grade'] as String?,
position: json['position'] as String?,
jobTitle: json['jobTitle'] as String?,
status: json['status'] as String?,
profileImageUrl: json['profileImageUrl'] as String?,
sortOrder: json['sortOrder'] as int?,
joinedTenants: (json['joinedTenants'] as List<dynamic>? ?? [])
.map((item) => TenantRef.fromJson(item as Map<String, dynamic>))
.toList(),
actions: EmployeeActions.fromJson(
json['actions'] as Map<String, dynamic>? ?? {},
),
);
}
@override
Map<String, dynamic> toJson() {
return {
...super.toJson(),
'joinedTenants': joinedTenants.map((tenant) => tenant.toJson()).toList(),
'actions': actions.toJson(),
};
}
}
class EmployeeListResponse {
const EmployeeListResponse({
required this.items,
required this.limit,
required this.offset,
required this.total,
required this.nextCursor,
});
final List<Employee> items;
final int limit;
final int offset;
final int total;
final String nextCursor;
factory EmployeeListResponse.fromJson(Map<String, dynamic> json) {
return EmployeeListResponse(
items: (json['items'] as List<dynamic>? ?? [])
.map((item) => Employee.fromJson(item as Map<String, dynamic>))
.toList(),
limit: json['limit'] as int? ?? 0,
offset: json['offset'] as int? ?? 0,
total: json['total'] as int? ?? 0,
nextCursor: json['nextCursor'] as String? ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'items': items.map((employee) => employee.toJson()).toList(),
'limit': limit,
'offset': offset,
'total': total,
'nextCursor': nextCursor,
};
}
}
@@ -0,0 +1,20 @@
class FavoriteEmployee {
const FavoriteEmployee({required this.employeeId, required this.createdAt});
final String employeeId;
final DateTime createdAt;
factory FavoriteEmployee.fromJson(Map<String, dynamic> json) {
return FavoriteEmployee(
employeeId: json['employeeId'] as String? ?? '',
createdAt: DateTime.parse(json['createdAt'] as String),
);
}
Map<String, dynamic> toJson() {
return {
'employeeId': employeeId,
'createdAt': createdAt.toUtc().toIso8601String(),
};
}
}
@@ -0,0 +1,130 @@
import '../../directory/domain/employee.dart';
class TenantSummary {
const TenantSummary({
required this.id,
required this.name,
required this.slug,
required this.type,
this.parentId,
required this.memberCount,
required this.totalMemberCount,
});
final String id;
final String name;
final String slug;
final String type;
final String? parentId;
final int memberCount;
final int totalMemberCount;
factory TenantSummary.fromJson(Map<String, dynamic> json) {
return TenantSummary(
id: json['id'] as String? ?? '',
name: json['name'] as String? ?? '',
slug: json['slug'] as String? ?? '',
type: json['type'] as String? ?? '',
parentId: json['parentId'] as String?,
memberCount: json['memberCount'] as int? ?? 0,
totalMemberCount: json['totalMemberCount'] as int? ?? 0,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'slug': slug,
'type': type,
'parentId': parentId,
'memberCount': memberCount,
'totalMemberCount': totalMemberCount,
};
}
}
class TenantListResponse {
const TenantListResponse({required this.items, required this.generatedAt});
final List<TenantSummary> items;
final DateTime generatedAt;
factory TenantListResponse.fromJson(Map<String, dynamic> json) {
return TenantListResponse(
items: (json['items'] as List<dynamic>? ?? [])
.map((item) => TenantSummary.fromJson(item as Map<String, dynamic>))
.toList(),
generatedAt: DateTime.parse(json['generatedAt'] as String),
);
}
Map<String, dynamic> toJson() {
return {
'items': items.map((tenant) => tenant.toJson()).toList(),
'generatedAt': generatedAt.toUtc().toIso8601String(),
};
}
}
class OrgChartCacheInfo {
const OrgChartCacheInfo({
required this.source,
required this.hit,
this.ttlSeconds,
});
final String source;
final bool hit;
final int? ttlSeconds;
factory OrgChartCacheInfo.fromJson(Map<String, dynamic> json) {
return OrgChartCacheInfo(
source: json['source'] as String? ?? '',
hit: json['hit'] as bool? ?? false,
ttlSeconds: json['ttlSeconds'] as int?,
);
}
Map<String, dynamic> toJson() {
return {'source': source, 'hit': hit, 'ttlSeconds': ttlSeconds};
}
}
class OrgChartSnapshot {
const OrgChartSnapshot({
required this.tenants,
required this.employees,
required this.generatedAt,
this.cache,
});
final List<TenantSummary> tenants;
final List<Employee> employees;
final DateTime generatedAt;
final OrgChartCacheInfo? cache;
factory OrgChartSnapshot.fromJson(Map<String, dynamic> json) {
return OrgChartSnapshot(
tenants: (json['tenants'] as List<dynamic>? ?? [])
.map((item) => TenantSummary.fromJson(item as Map<String, dynamic>))
.toList(),
employees: (json['employees'] as List<dynamic>? ?? [])
.map((item) => Employee.fromJson(item as Map<String, dynamic>))
.toList(),
generatedAt: DateTime.parse(json['generatedAt'] as String),
cache: json['cache'] == null
? null
: OrgChartCacheInfo.fromJson(json['cache'] as Map<String, dynamic>),
);
}
Map<String, dynamic> toJson() {
return {
'tenants': tenants.map((tenant) => tenant.toJson()).toList(),
'employees': employees.map((employee) => employee.toJson()).toList(),
'generatedAt': generatedAt.toUtc().toIso8601String(),
'cache': cache?.toJson(),
};
}
}