add dropdown

This commit is contained in:
Phuoc Nguyen
2025-10-28 16:24:17 +07:00
parent 0010446298
commit 5cfc56f40d
20 changed files with 912 additions and 12 deletions

View File

@@ -0,0 +1,78 @@
import 'package:equatable/equatable.dart';
/// User entity representing a user in the system
class UserEntity extends Equatable {
final int id;
final String firstName;
final String name;
final String? plateNumber;
final String email;
final String phone;
final bool isParent;
final String fullName;
final String fullNameEmail;
final String? referralCode;
final String? avatar;
final int departmentId;
final bool isWareHouseUser;
final int? wareHouseId;
final int roleId;
const UserEntity({
required this.id,
required this.firstName,
required this.name,
this.plateNumber,
required this.email,
required this.phone,
this.isParent = false,
required this.fullName,
required this.fullNameEmail,
this.referralCode,
this.avatar,
required this.departmentId,
this.isWareHouseUser = false,
this.wareHouseId,
required this.roleId,
});
@override
List<Object?> get props => [
id,
firstName,
name,
plateNumber,
email,
phone,
isParent,
fullName,
fullNameEmail,
referralCode,
avatar,
departmentId,
isWareHouseUser,
wareHouseId,
roleId,
];
/// Get display name
String get displayName {
if (fullName.isNotEmpty) return fullName;
if (name.isNotEmpty) return name;
return email;
}
/// Get initials from name (for avatar display)
String get initials {
if (firstName.isNotEmpty && name.isNotEmpty) {
return (firstName.substring(0, 1) + name.substring(0, 1)).toUpperCase();
}
final parts = fullName.trim().split(' ');
if (parts.isEmpty) return '?';
if (parts.length == 1) {
return parts[0].substring(0, 1).toUpperCase();
}
return (parts[0].substring(0, 1) + parts[parts.length - 1].substring(0, 1))
.toUpperCase();
}
}

View File

@@ -0,0 +1,16 @@
import 'package:dartz/dartz.dart';
import '../../../../core/errors/failures.dart';
import '../entities/user_entity.dart';
/// Abstract repository interface for users
abstract class UsersRepository {
/// Get all users (from local storage if available, otherwise from API)
Future<Either<Failure, List<UserEntity>>> getUsers();
/// Sync users from API and save to local storage
Future<Either<Failure, List<UserEntity>>> syncUsers();
/// Clear all users from local storage
Future<Either<Failure, void>> clearUsers();
}

View File

@@ -0,0 +1,18 @@
import 'package:dartz/dartz.dart';
import '../../../../core/errors/failures.dart';
import '../entities/user_entity.dart';
import '../repositories/users_repository.dart';
/// Use case for getting users
/// Follows local-first strategy: returns local users if available,
/// otherwise syncs from API
class GetUsersUseCase {
final UsersRepository repository;
GetUsersUseCase(this.repository);
Future<Either<Failure, List<UserEntity>>> call() async {
return await repository.getUsers();
}
}

View File

@@ -0,0 +1,17 @@
import 'package:dartz/dartz.dart';
import '../../../../core/errors/failures.dart';
import '../entities/user_entity.dart';
import '../repositories/users_repository.dart';
/// Use case for syncing users from API
/// Forces refresh from API and saves to local storage
class SyncUsersUseCase {
final UsersRepository repository;
SyncUsersUseCase(this.repository);
Future<Either<Failure, List<UserEntity>>> call() async {
return await repository.syncUsers();
}
}