diff --git a/app/Http/Controllers/Admin/AdminController.php b/app/Http/Controllers/Admin/AdminController.php
index d1fb405..3160185 100644
--- a/app/Http/Controllers/Admin/AdminController.php
+++ b/app/Http/Controllers/Admin/AdminController.php
@@ -42,13 +42,15 @@ class AdminController extends Controller
public function store(Request $request)
{
$request->validate([
- 'msnv' => 'required|unique:user,msnv',
- 'mail' => 'required|email|unique:user,mail',
- 'password' => 'required|min:6',
- 'role' => 'required|in:' . User::ROLE_MEMBER . ',' . User::ROLE_ADMIN,
+ 'msnv' => 'required|integer|unique:user,msnv',
+ 'name' => 'required|string|max:255',
+ 'mail' => 'required|email|unique:user,mail',
+ 'departments' => 'required|integer|min:1|max:5',
+ 'password' => 'required|string',
+ 'role' => 'required|in:' . User::ROLE_MEMBER . ',' . User::ROLE_ADMIN,
]);
- $this->adminService->createUser($request->only('msnv', 'mail', 'password', 'role'));
+ $this->adminService->createUser($request->only('msnv', 'name', 'mail', 'departments', 'password', 'role'));
return redirect()->route('admin.users.index')->with('success', __('messages.user_create_success'));
}
diff --git a/app/Http/Controllers/User/UserController.php b/app/Http/Controllers/User/UserController.php
index 5794a72..ba8909c 100644
--- a/app/Http/Controllers/User/UserController.php
+++ b/app/Http/Controllers/User/UserController.php
@@ -34,7 +34,10 @@ class UserController extends Controller
public function storeThankcards(Request $request)
{
$request->validate([
- 'receiver' => 'required|exists:user,msnv',
+ 'receiver' => [
+ 'required',
+ \Illuminate\Validation\Rule::exists('user', 'msnv')->where('status', \App\Models\User::STATUS_ACTIVE)
+ ],
'amount' => 'required|integer|min:1|max:' . Administration::MAX_SEND_CARD_PER_MONTH,
]);
diff --git a/app/Models/AddCard.php b/app/Models/AddCard.php
index de3931f..0706ebe 100644
--- a/app/Models/AddCard.php
+++ b/app/Models/AddCard.php
@@ -11,8 +11,7 @@ class AddCard extends Model
protected $table = 'add_card';
public $timestamps = false;
- protected $primaryKey = null;
- public $incrementing = false;
+ protected $primaryKey = 'id';
protected $fillable = [
'buyer',
diff --git a/app/Models/User.php b/app/Models/User.php
index 52b40d5..e2259ad 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -25,14 +25,15 @@ class User extends Authenticatable
protected $table = 'user';
public $timestamps = false;
- protected $primaryKey = 'msnv';
- public $incrementing = false;
- protected $keyType = 'string';
+ protected $primaryKey = 'id';
protected $fillable = [
'msnv',
+ 'name',
'mail',
'pass',
+ 'departments',
+ 'avatar',
'role',
'status',
'card',
diff --git a/app/Services/Admin/AdminService.php b/app/Services/Admin/AdminService.php
index 433fad2..7a74993 100644
--- a/app/Services/Admin/AdminService.php
+++ b/app/Services/Admin/AdminService.php
@@ -66,8 +66,10 @@ class AdminService implements AdminServiceInterface
{
User::create([
'msnv' => $data['msnv'],
+ 'name' => $data['name'],
'mail' => $data['mail'],
'pass' => Hash::make($data['password']),
+ 'departments' => $data['departments'],
'role' => $data['role'],
'status' => User::STATUS_ACTIVE,
'card' => 0,
@@ -83,9 +85,9 @@ class AdminService implements AdminServiceInterface
DB::transaction(function () use ($data, $user) {
if (!empty($data['num_card'])) {
AddCard::create([
- 'buyer' => abs(crc32($user->msnv)) % 1000000,
+ 'buyer' => $user->msnv,
'num_card' => $data['num_card'],
- 'seller' => abs(crc32(Auth::user()->msnv)) % 1000000,
+ 'seller' => Auth::user()->msnv,
'date' => Carbon::today(),
]);
$user->card += $data['num_card'];
diff --git a/app/Services/Auth/AuthService.php b/app/Services/Auth/AuthService.php
index 83a331a..c5b40de 100644
--- a/app/Services/Auth/AuthService.php
+++ b/app/Services/Auth/AuthService.php
@@ -11,14 +11,15 @@ class AuthService implements AuthServiceInterface
{
public function attemptLogin(array $credentials, Request $request): array
{
- if (!Auth::attempt(['mail' => $credentials['mail'], 'password' => $credentials['password']])) {
+ // Manual MD5 password check
+ $user = User::where('mail', $credentials['mail'])->first();
+ if (!$user || $user->pass !== md5($credentials['password'])) {
return ['success' => false, 'error_key' => 'mail', 'error_msg' => __('auth.failed')];
}
+ // Log the user in manually
+ Auth::login($user);
$request->session()->regenerate();
-
- $user = Auth::user();
-
if ($user->status != User::STATUS_ACTIVE) {
Auth::logout();
return ['success' => false, 'error_key' => 'mail', 'error_msg' => __('auth.inactive')];
diff --git a/app/Services/User/UserService.php b/app/Services/User/UserService.php
index 3637651..63284aa 100644
--- a/app/Services/User/UserService.php
+++ b/app/Services/User/UserService.php
@@ -38,6 +38,11 @@ class UserService implements UserServiceInterface
throw new \RuntimeException(__('messages.error.no_send_permission'));
}
+ $receiver = User::where('msnv', $receiverMsnv)->first();
+ if (!$receiver || $receiver->status != User::STATUS_ACTIVE) {
+ throw new \RuntimeException(__('messages.error.receiver_invalid'));
+ }
+
$startOfMonth = Carbon::now()->startOfMonth();
$endOfMonth = Carbon::now()->endOfMonth();
diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php
index 41867cc..cf0ca65 100644
--- a/database/migrations/0001_01_01_000000_create_users_table.php
+++ b/database/migrations/0001_01_01_000000_create_users_table.php
@@ -12,14 +12,18 @@ return new class extends Migration
public function up(): void
{
Schema::create('user', function (Blueprint $table) {
- $table->string('msnv')->primary();
+ $table->increments('id');
+ $table->integer('msnv')->unique();
+ $table->string('name');
$table->string('mail');
$table->string('pass');
- $table->tinyInteger('role')->default(0)->comment('0: member / 1: admin');
- $table->tinyInteger('status')->default(1)->comment('0: đã nghỉ / 1: đang làm');
- $table->integer('card')->nullable();
- $table->tinyInteger('flag_send')->default(0)->comment('0: không được gửi / 1: được gửi');
- $table->tinyInteger('first_login')->default(1)->comment('0: không là lần đầu / 1: lần đầu');
+ $table->integer('departments')->default(1);
+ $table->string('avatar')->nullable();
+ $table->tinyInteger('role')->default(0)->comment('0: member, default / 1: admin');
+ $table->tinyInteger('status')->default(1)->comment('0: đã nghỉ / 1: đang làm, default');
+ $table->integer('card')->default(0);
+ $table->tinyInteger('flag_send')->default(0)->comment('0: không được gửi card / 1: được gửi card');
+ $table->tinyInteger('first_login')->default(1)->comment('0: không là lần đầu / 1: lần đầu, default');
});
// Only user table remains
diff --git a/database/migrations/2026_06_27_132957_create_add_cards_table.php b/database/migrations/2026_06_27_132957_create_add_cards_table.php
index 1ab3bc8..791ac86 100644
--- a/database/migrations/2026_06_27_132957_create_add_cards_table.php
+++ b/database/migrations/2026_06_27_132957_create_add_cards_table.php
@@ -12,10 +12,11 @@ return new class extends Migration
public function up(): void
{
Schema::create('add_card', function (Blueprint $table) {
+ $table->increments('id');
$table->integer('buyer');
$table->integer('num_card');
$table->integer('seller');
- $table->date('date')->nullable();
+ $table->date('date');
});
}
diff --git a/database/migrations/2026_06_27_132957_create_administrations_table.php b/database/migrations/2026_06_27_132957_create_administrations_table.php
index 22b2720..2060a14 100644
--- a/database/migrations/2026_06_27_132957_create_administrations_table.php
+++ b/database/migrations/2026_06_27_132957_create_administrations_table.php
@@ -12,12 +12,12 @@ return new class extends Migration
public function up(): void
{
Schema::create('administration', function (Blueprint $table) {
- $table->id();
- $table->string('msnv');
+ $table->increments('id');
+ $table->integer('msnv');
$table->integer('received')->nullable();
- $table->string('sender')->nullable();
+ $table->integer('sender')->nullable();
$table->integer('sent')->nullable();
- $table->string('receiver')->nullable();
+ $table->integer('receiver')->nullable();
$table->date('date')->nullable();
});
}
diff --git a/database/seeders/MockDataSeeder.php b/database/seeders/MockDataSeeder.php
index b2bb92c..f4b21b5 100644
--- a/database/seeders/MockDataSeeder.php
+++ b/database/seeders/MockDataSeeder.php
@@ -24,14 +24,17 @@ class MockDataSeeder extends Seeder
AddCard::truncate();
DB::statement('SET FOREIGN_KEY_CHECKS=1;');
- $password = Hash::make('123456');
+ // The default password is now set to 1234@Dcba according to the design requirements
+ $password = md5('1234@Dcba');
// 1. CREATE USERS
// Admins
User::create([
- 'msnv' => 'ADMIN',
+ 'msnv' => 9999,
+ 'name' => 'System Admin',
'mail' => 'admin@runsystem.net',
'pass' => $password,
+ 'departments' => 1,
'role' => User::ROLE_ADMIN,
'status' => User::STATUS_ACTIVE,
'card' => 0,
@@ -40,9 +43,11 @@ class MockDataSeeder extends Seeder
]);
User::create([
- 'msnv' => 'ADMIN2',
+ 'msnv' => 9998,
+ 'name' => 'Second Admin',
'mail' => 'admin2@runsystem.net',
'pass' => $password,
+ 'departments' => 1,
'role' => User::ROLE_ADMIN,
'status' => User::STATUS_ACTIVE,
'card' => 0,
@@ -52,19 +57,24 @@ class MockDataSeeder extends Seeder
// Active Users (Initialize with specific users needed for logs/transactions)
$users = [
- ['msnv' => 'DEV001', 'mail' => 'nguyenvana@runsystem.net', 'card' => 10, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_FALSE],
- ['msnv' => 'DEV002', 'mail' => 'tranthingoc@runsystem.net', 'card' => 3, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_FALSE],
- ['msnv' => 'TEST01', 'mail' => 'lekiemthu@runsystem.net', 'card' => 6, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_TRUE], // First-time login
- ['msnv' => 'HR001', 'mail' => 'phongnhansu@runsystem.net', 'card' => 0, 'flag' => User::FLAG_SEND_DISABLED, 'first_login' => User::FIRST_LOGIN_FALSE], // Disabled sending permission
- ['msnv' => 'SALE01', 'mail' => 'bangiang@runsystem.net', 'card' => 36, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_FALSE],
+ ['msnv' => 1001, 'name' => 'Nguyễn Văn A', 'mail' => 'nguyenvana@runsystem.net', 'card' => 10, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_FALSE],
+ ['msnv' => 1002, 'name' => 'Trần Thị Ngọc', 'mail' => 'tranthingoc@runsystem.net', 'card' => 3, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_FALSE],
+ ['msnv' => 1003, 'name' => 'Lê Kim Thư', 'mail' => 'lekiemthu@runsystem.net', 'card' => 6, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_TRUE], // First-time login
+ ['msnv' => 1004, 'name' => 'Phòng Nhân Sự', 'mail' => 'phongnhansu@runsystem.net', 'card' => 0, 'flag' => User::FLAG_SEND_DISABLED, 'first_login' => User::FIRST_LOGIN_FALSE], // Disabled sending permission
+ ['msnv' => 1005, 'name' => 'Bản Giang', 'mail' => 'bangiang@runsystem.net', 'card' => 36, 'flag' => User::FLAG_SEND_ENABLED, 'first_login' => User::FIRST_LOGIN_FALSE],
];
// Generate additional users to reach exactly 100 member users
- for ($i = 3; $i <= 97; $i++) {
- $numStr = str_pad($i, 3, '0', STR_PAD_LEFT);
+ $firstNames = ['Nguyễn', 'Trần', 'Lê', 'Phạm', 'Hoàng', 'Huỳnh', 'Phan', 'Vũ', 'Võ', 'Đặng'];
+ $middleNames = ['Văn', 'Thị', 'Minh', 'Đức', 'Quốc', 'Thanh', 'Hữu', 'Ngọc', 'Quỳnh', 'Thu'];
+ $lastNames = ['Anh', 'Bình', 'Chi', 'Dương', 'Em', 'Giang', 'Huy', 'Khánh', 'Lâm', 'Nam', 'Oanh', 'Phúc', 'Quang', 'Sơn', 'Trang', 'Vy'];
+
+ for ($i = 6; $i <= 100; $i++) {
+ $randomName = $firstNames[array_rand($firstNames)] . ' ' . $middleNames[array_rand($middleNames)] . ' ' . $lastNames[array_rand($lastNames)];
$users[] = [
- 'msnv' => 'DEV' . $numStr,
- 'mail' => 'dev' . $numStr . '@runsystem.net',
+ 'msnv' => 1000 + $i,
+ 'name' => $randomName,
+ 'mail' => 'dev' . str_pad($i, 3, '0', STR_PAD_LEFT) . '@runsystem.net',
'card' => rand(0, 30),
'flag' => rand(0, 5) > 0 ? User::FLAG_SEND_ENABLED : User::FLAG_SEND_DISABLED,
'first_login' => rand(0, 4) == 0 ? User::FIRST_LOGIN_TRUE : User::FIRST_LOGIN_FALSE
@@ -74,8 +84,10 @@ class MockDataSeeder extends Seeder
foreach ($users as $u) {
User::create([
'msnv' => $u['msnv'],
+ 'name' => $u['name'],
'mail' => $u['mail'],
'pass' => $password,
+ 'departments' => rand(1, 5),
'role' => User::ROLE_MEMBER,
'status' => User::STATUS_ACTIVE,
'card' => $u['card'],
@@ -84,12 +96,12 @@ class MockDataSeeder extends Seeder
]);
// For other users, if they have cards, create a matching purchase log in June 2026
- if (!in_array($u['msnv'], ['DEV001', 'DEV002', 'TEST01', 'SALE01'])) {
+ if (!in_array($u['msnv'], [1001, 1002, 1003, 1005])) {
if ($u['card'] > 0) {
AddCard::create([
- 'buyer' => abs(crc32($u['msnv'])) % 1000000,
+ 'buyer' => $u['msnv'],
'num_card' => $u['card'],
- 'seller' => abs(crc32('ADMIN')) % 1000000,
+ 'seller' => 9999,
'date' => '2026-06-01'
]);
}
@@ -98,9 +110,11 @@ class MockDataSeeder extends Seeder
// Inactive User
User::create([
- 'msnv' => 'OLD001',
+ 'msnv' => 9997,
+ 'name' => 'Nghi Duy',
'mail' => 'nghiduy@runsystem.net',
'pass' => $password,
+ 'departments' => 2,
'role' => User::ROLE_MEMBER,
'status' => User::STATUS_INACTIVE,
'card' => 0,
@@ -111,28 +125,28 @@ class MockDataSeeder extends Seeder
// 2. CREATE CARD ADDITION LOGS (add_card table)
// Manual purchase history for specific users:
$addCardLogs = [
- // DEV001: total 30 cards bought
- ['buyer' => 'DEV001', 'num_card' => 15, 'date' => '2026-06-01'],
- ['buyer' => 'DEV001', 'num_card' => 10, 'date' => '2026-07-01'],
- ['buyer' => 'DEV001', 'num_card' => 5, 'date' => '2026-08-01'],
+ // 1001: total 30 cards bought
+ ['buyer' => 1001, 'num_card' => 15, 'date' => '2026-06-01'],
+ ['buyer' => 1001, 'num_card' => 10, 'date' => '2026-07-01'],
+ ['buyer' => 1001, 'num_card' => 5, 'date' => '2026-08-01'],
- // DEV002: total 15 cards bought
- ['buyer' => 'DEV002', 'num_card' => 10, 'date' => '2026-06-02'],
- ['buyer' => 'DEV002', 'num_card' => 5, 'date' => '2026-07-01'],
+ // 1002: total 15 cards bought
+ ['buyer' => 1002, 'num_card' => 10, 'date' => '2026-06-02'],
+ ['buyer' => 1002, 'num_card' => 5, 'date' => '2026-07-01'],
- // TEST01: total 15 cards bought
- ['buyer' => 'TEST01', 'num_card' => 10, 'date' => '2026-06-03'],
- ['buyer' => 'TEST01', 'num_card' => 5, 'date' => '2026-08-02'],
+ // 1003: total 15 cards bought
+ ['buyer' => 1003, 'num_card' => 10, 'date' => '2026-06-03'],
+ ['buyer' => 1003, 'num_card' => 5, 'date' => '2026-08-02'],
- // SALE01: total 50 cards bought
- ['buyer' => 'SALE01', 'num_card' => 50, 'date' => '2026-06-04'],
+ // 1005: total 50 cards bought
+ ['buyer' => 1005, 'num_card' => 50, 'date' => '2026-06-04'],
];
foreach ($addCardLogs as $log) {
AddCard::create([
- 'buyer' => abs(crc32($log['buyer'])) % 1000000,
+ 'buyer' => $log['buyer'],
'num_card' => $log['num_card'],
- 'seller' => abs(crc32('ADMIN')) % 1000000,
+ 'seller' => 9999,
'date' => $log['date']
]);
}
@@ -140,24 +154,24 @@ class MockDataSeeder extends Seeder
// 3. CREATE CARD SENDING HISTORY (administration table)
$transactions = [
// June 2026 transactions
- ['sender' => 'DEV001', 'receiver' => 'SALE01', 'amount' => 5, 'date' => '2026-06-05'],
- ['sender' => 'DEV001', 'receiver' => 'DEV002', 'amount' => 3, 'date' => '2026-06-12'],
- ['sender' => 'DEV002', 'receiver' => 'HR001', 'amount' => 4, 'date' => '2026-06-10'],
- ['sender' => 'TEST01', 'receiver' => 'DEV001', 'amount' => 2, 'date' => '2026-06-15'],
- ['sender' => 'SALE01', 'receiver' => 'DEV002', 'amount' => 5, 'date' => '2026-06-20'],
+ ['sender' => 1001, 'receiver' => 1005, 'amount' => 5, 'date' => '2026-06-05'],
+ ['sender' => 1001, 'receiver' => 1002, 'amount' => 3, 'date' => '2026-06-12'],
+ ['sender' => 1002, 'receiver' => 1004, 'amount' => 4, 'date' => '2026-06-10'],
+ ['sender' => 1003, 'receiver' => 1001, 'amount' => 2, 'date' => '2026-06-15'],
+ ['sender' => 1005, 'receiver' => 1002, 'amount' => 5, 'date' => '2026-06-20'],
// July 2026 transactions
- ['sender' => 'DEV001', 'receiver' => 'DEV002', 'amount' => 5, 'date' => '2026-07-02'],
- ['sender' => 'DEV001', 'receiver' => 'TEST01', 'amount' => 3, 'date' => '2026-07-10'],
- ['sender' => 'DEV002', 'receiver' => 'DEV001', 'amount' => 5, 'date' => '2026-07-15'],
- ['sender' => 'TEST01', 'receiver' => 'HR001', 'amount' => 4, 'date' => '2026-07-08'],
- ['sender' => 'SALE01', 'receiver' => 'DEV002', 'amount' => 4, 'date' => '2026-07-12'],
+ ['sender' => 1001, 'receiver' => 1002, 'amount' => 5, 'date' => '2026-07-02'],
+ ['sender' => 1001, 'receiver' => 1003, 'amount' => 3, 'date' => '2026-07-10'],
+ ['sender' => 1002, 'receiver' => 1001, 'amount' => 5, 'date' => '2026-07-15'],
+ ['sender' => 1003, 'receiver' => 1004, 'amount' => 4, 'date' => '2026-07-08'],
+ ['sender' => 1005, 'receiver' => 1002, 'amount' => 4, 'date' => '2026-07-12'],
// August 2026 transactions
- ['sender' => 'DEV001', 'receiver' => 'SALE01', 'amount' => 4, 'date' => '2026-08-05'],
- ['sender' => 'DEV002', 'receiver' => 'TEST01', 'amount' => 3, 'date' => '2026-08-12'],
- ['sender' => 'TEST01', 'receiver' => 'DEV001', 'amount' => 3, 'date' => '2026-08-10'],
- ['sender' => 'SALE01', 'receiver' => 'HR001', 'amount' => 5, 'date' => '2026-08-15'],
+ ['sender' => 1001, 'receiver' => 1005, 'amount' => 4, 'date' => '2026-08-05'],
+ ['sender' => 1002, 'receiver' => 1003, 'amount' => 3, 'date' => '2026-08-12'],
+ ['sender' => 1003, 'receiver' => 1001, 'amount' => 3, 'date' => '2026-08-10'],
+ ['sender' => 1005, 'receiver' => 1004, 'amount' => 5, 'date' => '2026-08-15'],
];
foreach ($transactions as $t) {
diff --git a/docker/README.md b/docker/README.md
index 7d6c6ae..fac62f6 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -67,16 +67,27 @@ docker compose -f docker/docker-compose.yml exec app composer install
### 4.2. Khi cập nhật giao diện (CSS / JS / Tailwind classes mới)
-Do Docker container không cài Node.js, bạn cần chạy các lệnh compile frontend trực tiếp **ở máy thật (host)**:
+Cập nhật giao diện cần biên dịch lại tài nguyên frontend. Bạn có 2 cách:
-- **Chạy chế độ phát triển (Hot Reload):**
- ```bash
- npm run dev
- ```
-- **Build production tĩnh:**
- ```bash
- npm run build
- ```
+**1️⃣ Chạy trên máy host (đề xuất)**
+```bash
+npm install # một lần, nếu chưa có các package
+npm run dev # Vite dev server, hot‑reload
+```
+
+**2️⃣ Chạy trong Docker (sử dụng container `node`)**
+```bash
+# Cài đặt các package (chỉ chạy 1 lần)
+docker compose -f docker/docker-compose.yml exec node npm install
+
+# Chế độ phát triển (hot‑reload)
+docker compose -f docker/docker-compose.yml exec node npm run dev
+
+# Hoặc biên dịch bản production
+docker compose -f docker/docker-compose.yml exec node npm run build
+```
+
+Container `node` đã expose port **5173**, cho phép truy cập Vite dev server tại `http://localhost:5173`. Khi `npm run dev` đang chạy, mọi thay đổi CSS/JS sẽ tự động cập nhật trong container `app` nhờ volume mount.
### 4.3. Khi cập nhật Database (Migrations)
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 829b35d..da55f96 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -34,6 +34,8 @@ services:
volumes:
- ..:/var/www/html
command: sh -c "npm install && npm run build"
+ ports:
+ - "5173:5173"
networks:
- thankcard-system-network
diff --git a/lang/vi/messages.php b/lang/vi/messages.php
index e20033e..a9928f3 100644
--- a/lang/vi/messages.php
+++ b/lang/vi/messages.php
@@ -12,5 +12,6 @@ return [
'no_send_permission' => 'Bạn hiện không có quyền gửi Thank Card.',
'not_enough_cards' => 'Số lượng card của bạn không đủ. Vui lòng liên hệ Admin.',
'max_send_limit_template' => 'Một tháng bạn chỉ được gửi tối đa :max card cho một người. Bạn đã gửi :sent card cho nhân viên này.',
+ 'receiver_invalid' => 'Người nhận không tồn tại hoặc đã nghỉ việc.',
]
];
diff --git a/resources/views/components/user-form.blade.php b/resources/views/components/user-form.blade.php
index e70ef4e..8a32119 100644
--- a/resources/views/components/user-form.blade.php
+++ b/resources/views/components/user-form.blade.php
@@ -69,11 +69,24 @@