diff --git a/.env.example b/.env.example index c0660ea..85bf68b 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,7 @@ APP_KEY= APP_DEBUG=true APP_URL=http://localhost -APP_LOCALE=en +APP_LOCALE=vi APP_FALLBACK_LOCALE=en APP_FAKER_LOCALE=en_US diff --git a/app/Console/Commands/ResetCardsCommand.php b/app/Console/Commands/ResetCardsCommand.php new file mode 100644 index 0000000..ff20612 --- /dev/null +++ b/app/Console/Commands/ResetCardsCommand.php @@ -0,0 +1,33 @@ +update(['card' => 0]); + + $this->info('Đã reset toàn bộ số lượng thẻ của nhân viên đang hoạt động về 0 thành công!'); + } +} diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php new file mode 100644 index 0000000..56484bf --- /dev/null +++ b/app/Http/Controllers/AdminController.php @@ -0,0 +1,143 @@ +input('month', Carbon::now()->format('Y-m')); + $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth(); + $endOfMonth = Carbon::parse($selectedMonth)->endOfMonth(); + + // 1. Calculate top stats from all active users + $allActiveUsers = User::where('status', User::STATUS_ACTIVE)->get()->map(function($user) use ($startOfMonth, $endOfMonth) { + $user->total_received = Administration::where('receiver', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('received'); + + $user->total_sent = Administration::where('sender', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('sent'); + + return $user; + }); + + $topReceivedUser = $allActiveUsers->sortByDesc('total_received')->first(); + $topSentUser = $allActiveUsers->sortByDesc('total_sent')->first(); + + // 2. Paginate users for the list table (10 per page) + $users = User::where('status', User::STATUS_ACTIVE)->paginate(10)->withQueryString(); + + // 3. Compute stats only for the paginated users (to display in the table) + $users->getCollection()->transform(function($user) use ($startOfMonth, $endOfMonth) { + $user->total_received = Administration::where('receiver', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('received'); + + $user->total_sent = Administration::where('sender', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('sent'); + + return $user; + }); + + return view('admin.users.index', compact('users', 'selectedMonth', 'topReceivedUser', 'topSentUser')); + } + + public function create() + { + return view('admin.users.create'); + } + + 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 + ]); + + User::create([ + 'msnv' => $request->msnv, + 'mail' => $request->mail, + 'pass' => Hash::make($request->password), + 'role' => $request->role, + 'status' => User::STATUS_ACTIVE, + 'card' => 0, + 'flag_send' => User::FLAG_SEND_DISABLED, + 'first_login' => User::FIRST_LOGIN_TRUE + ]); + + return redirect()->route('admin.users.index')->with('success', 'Tạo user thành công!'); + } + + public function edit(Request $request, $msnv) + { + $user = User::where('msnv', $msnv)->firstOrFail(); + + $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); + $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth(); + $endOfMonth = Carbon::parse($selectedMonth)->endOfMonth(); + + $administrations = Administration::where(function($q) use ($msnv) { + $q->where('sender', $msnv)->orWhere('receiver', $msnv); + }) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->orderBy('date', 'desc') + ->get(); + + return view('admin.users.edit', compact('user', 'administrations', 'selectedMonth')); + } + + public function update(Request $request, $msnv) + { + $user = User::where('msnv', $msnv)->firstOrFail(); + + $request->validate([ + 'num_card' => 'nullable|integer|min:1', + 'flag_send' => 'nullable|boolean' + ]); + + DB::transaction(function () use ($request, $user) { + if ($request->filled('num_card')) { + AddCard::create([ + 'buyer' => $user->msnv, + 'num_card' => $request->num_card, + 'seller' => auth()->user()->msnv, + 'date' => Carbon::today() + ]); + $user->card += $request->num_card; + } + + $user->flag_send = $request->has('flag_send') ? User::FLAG_SEND_ENABLED : User::FLAG_SEND_DISABLED; + $user->save(); + }); + + return redirect()->back()->with('success', 'Cập nhật thành công!'); + } + + public function destroy($msnv) + { + $user = User::where('msnv', $msnv)->firstOrFail(); + $user->status = User::STATUS_INACTIVE; + $user->save(); + + return redirect()->route('admin.users.index')->with('success', 'Đã đánh dấu nhân viên nghỉ việc thành công!'); + } + + public function resetCards() + { + User::where('status', User::STATUS_ACTIVE)->update(['card' => 0]); + return redirect()->back()->with('success', 'Reset thẻ toàn hệ thống thành công!'); + } +} diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php new file mode 100644 index 0000000..9689506 --- /dev/null +++ b/app/Http/Controllers/AuthController.php @@ -0,0 +1,66 @@ +redirectBasedOnRole(Auth::user()); + } + return view('login'); + } + + public function login(Request $request) + { + $credentials = $request->validate([ + 'mail' => 'required|email', + 'password' => 'required' + ]); + + if (Auth::attempt(['mail' => $credentials['mail'], 'password' => $credentials['password']])) { + $request->session()->regenerate(); + + $user = Auth::user(); + + if ($user->status != User::STATUS_ACTIVE) { + Auth::logout(); + return back()->withErrors([ + 'mail' => 'Tài khoản của bạn đã bị khóa hoặc bạn đã nghỉ việc.', + ]); + } + + return $this->redirectBasedOnRole($user); + } + + return back()->withErrors([ + 'mail' => 'Email hoặc mật khẩu không chính xác.', + ]); + } + + public function logout(Request $request) + { + Auth::logout(); + $request->session()->invalidate(); + $request->session()->regenerateToken(); + return redirect('/login'); + } + + private function redirectBasedOnRole($user) + { + if ($user->first_login == User::FIRST_LOGIN_TRUE) { + return redirect()->route('user.change_password'); + } + + if ($user->role == User::ROLE_ADMIN) { + return redirect()->route('admin.dashboard'); + } + + return redirect()->route('user.dashboard'); + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..5efb8dd --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,136 @@ +input('month', Carbon::now()->format('Y-m')); + $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth(); + $endOfMonth = Carbon::parse($selectedMonth)->endOfMonth(); + + $user = Auth::user(); + + // Lấy tất cả card nhận và gửi của user này + $administrations = Administration::where('msnv', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->orderBy('date', 'desc') + ->get(); + + return view('user.dashboard', compact('administrations', 'selectedMonth', 'user')); + } + + public function sendThankcards() + { + $users = User::where('status', User::STATUS_ACTIVE)->where('msnv', '!=', Auth::user()->msnv)->get(); + return view('user.send', compact('users')); + } + + public function storeThankcards(Request $request) + { + $request->validate([ + 'receiver' => 'required|exists:user,msnv', + 'amount' => 'required|integer|min:1|max:' . Administration::MAX_SEND_CARD_PER_MONTH + ]); + + $sender = Auth::user(); + $receiverMsnv = $request->receiver; + $amount = $request->amount; + + if ($sender->flag_send == User::FLAG_SEND_DISABLED) { + return response()->json([ + 'success' => false, + 'message' => 'Bạn hiện không có quyền gửi Thank Card.' + ], 422); + } + + $startOfMonth = Carbon::now()->startOfMonth(); + $endOfMonth = Carbon::now()->endOfMonth(); + + // Tính tổng số lượng card ĐÃ gửi cho người này trong tháng + $cardsSentToThisUserThisMonth = Administration::where('msnv', $sender->msnv) + ->where('receiver', $receiverMsnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('sent'); + + if ($cardsSentToThisUserThisMonth + $amount > Administration::MAX_SEND_CARD_PER_MONTH) { + return response()->json([ + 'success' => false, + 'message' => "Một tháng bạn chỉ được gửi tối đa " . Administration::MAX_SEND_CARD_PER_MONTH . " card cho một người. Bạn đã gửi {$cardsSentToThisUserThisMonth} card cho nhân viên này." + ], 422); + } + + // Validate số lượng thẻ còn lại + if ($sender->card < $amount) { + return response()->json([ + 'success' => false, + 'message' => 'Số lượng card của bạn không đủ. Vui lòng liên hệ Admin.' + ], 422); + } + + DB::transaction(function () use ($sender, $receiverMsnv, $amount) { + // 1. Insert thông tin người nhận + Administration::create([ + 'msnv' => $receiverMsnv, + 'received' => $amount, + 'sender' => $sender->msnv, + 'sent' => 0, + 'receiver' => null, + 'date' => Carbon::today() + ]); + + // 2. Insert thông tin người gửi + Administration::create([ + 'msnv' => $sender->msnv, + 'received' => 0, + 'sender' => null, + 'sent' => $amount, + 'receiver' => $receiverMsnv, + 'date' => Carbon::today() + ]); + + // 3. Trừ số card của người gửi + $sender->card -= $amount; + $sender->save(); + + // TODO: Bắn tin nhắn CO tới người nhận (Chatwork/System Notification) + }); + + return response()->json([ + 'success' => true, + 'message' => 'Đã gửi Thank card thành công!' + ]); + } + + public function changePasswordForm() + { + return view('user.change_password'); + } + + public function updatePassword(Request $request) + { + $request->validate([ + 'password' => 'required|min:6|confirmed' + ]); + + $user = Auth::user(); + $user->pass = Hash::make($request->password); + $user->first_login = User::FIRST_LOGIN_FALSE; + $user->save(); + + if ($user->role == User::ROLE_ADMIN) { + return redirect()->route('admin.dashboard')->with('success', 'Đổi mật khẩu thành công!'); + } + + return redirect()->route('user.dashboard')->with('success', 'Đổi mật khẩu thành công!'); + } +} diff --git a/app/Http/Middleware/AdminMiddleware.php b/app/Http/Middleware/AdminMiddleware.php new file mode 100644 index 0000000..7e9749e --- /dev/null +++ b/app/Http/Middleware/AdminMiddleware.php @@ -0,0 +1,20 @@ +role == User::ROLE_ADMIN && Auth::user()->status == User::STATUS_ACTIVE) { + return $next($request); + } + return redirect()->route('login'); + } +} diff --git a/app/Http/Middleware/ForceChangePasswordMiddleware.php b/app/Http/Middleware/ForceChangePasswordMiddleware.php new file mode 100644 index 0000000..f8996ab --- /dev/null +++ b/app/Http/Middleware/ForceChangePasswordMiddleware.php @@ -0,0 +1,22 @@ +first_login == User::FIRST_LOGIN_TRUE) { + if (!$request->routeIs('user.change_password') && !$request->routeIs('user.update_password') && !$request->routeIs('logout')) { + return redirect()->route('user.change_password'); + } + } + return $next($request); + } +} diff --git a/app/Http/Middleware/MemberMiddleware.php b/app/Http/Middleware/MemberMiddleware.php new file mode 100644 index 0000000..7a80371 --- /dev/null +++ b/app/Http/Middleware/MemberMiddleware.php @@ -0,0 +1,20 @@ +role == User::ROLE_MEMBER && Auth::user()->status == User::STATUS_ACTIVE) { + return $next($request); + } + return redirect()->route('login'); + } +} diff --git a/app/Models/AddCard.php b/app/Models/AddCard.php new file mode 100644 index 0000000..82c8130 --- /dev/null +++ b/app/Models/AddCard.php @@ -0,0 +1,20 @@ + */ use HasFactory, Notifiable; - /** - * The attributes that are mass assignable. - * - * @var list - */ + const ROLE_MEMBER = 0; + const ROLE_ADMIN = 1; + + const STATUS_INACTIVE = 0; + const STATUS_ACTIVE = 1; + + const FLAG_SEND_DISABLED = 0; + const FLAG_SEND_ENABLED = 1; + + const FIRST_LOGIN_FALSE = 0; + const FIRST_LOGIN_TRUE = 1; + + + protected $table = 'user'; + protected $primaryKey = 'msnv'; + public $incrementing = false; + protected $keyType = 'string'; + protected $fillable = [ - 'name', - 'email', - 'password', + 'msnv', + 'mail', + 'pass', + 'role', + 'status', + 'card', + 'flag_send', + 'first_login', ]; - /** - * The attributes that should be hidden for serialization. - * - * @var list - */ protected $hidden = [ - 'password', + 'pass', 'remember_token', ]; /** - * Get the attributes that should be cast. + * Get the password for the user. * - * @return array + * @return string */ - protected function casts(): array + public function getAuthPassword() { - return [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; + return $this->pass; } } diff --git a/bootstrap/app.php b/bootstrap/app.php index c183276..d0b9e73 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -11,7 +11,11 @@ return Application::configure(basePath: dirname(__DIR__)) health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { - // + $middleware->alias([ + 'admin' => \App\Http\Middleware\AdminMiddleware::class, + 'member' => \App\Http\Middleware\MemberMiddleware::class, + 'force_change_password' => \App\Http\Middleware\ForceChangePasswordMiddleware::class, + ]); }) ->withExceptions(function (Exceptions $exceptions): void { // diff --git a/config/app.php b/config/app.php index 423eed5..6ea134d 100644 --- a/config/app.php +++ b/config/app.php @@ -78,7 +78,7 @@ return [ | */ - 'locale' => env('APP_LOCALE', 'en'), + 'locale' => env('APP_LOCALE', 'vi'), 'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'), 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 05fb5d9..6ff6793 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -11,30 +11,20 @@ return new class extends Migration */ public function up(): void { - Schema::create('users', function (Blueprint $table) { - $table->id(); - $table->string('name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); + Schema::create('user', function (Blueprint $table) { + $table->string('msnv')->primary(); + $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->rememberToken(); $table->timestamps(); }); - Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - - Schema::create('sessions', function (Blueprint $table) { - $table->string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); - $table->string('ip_address', 45)->nullable(); - $table->text('user_agent')->nullable(); - $table->longText('payload'); - $table->integer('last_activity')->index(); - }); + // Only user table remains } /** @@ -42,8 +32,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('users'); - Schema::dropIfExists('password_reset_tokens'); - Schema::dropIfExists('sessions'); + Schema::dropIfExists('user'); } }; diff --git a/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php deleted file mode 100644 index ed758bd..0000000 --- a/database/migrations/0001_01_01_000001_create_cache_table.php +++ /dev/null @@ -1,35 +0,0 @@ -string('key')->primary(); - $table->mediumText('value'); - $table->integer('expiration')->index(); - }); - - Schema::create('cache_locks', function (Blueprint $table) { - $table->string('key')->primary(); - $table->string('owner'); - $table->integer('expiration')->index(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('cache'); - Schema::dropIfExists('cache_locks'); - } -}; diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php deleted file mode 100644 index 425e705..0000000 --- a/database/migrations/0001_01_01_000002_create_jobs_table.php +++ /dev/null @@ -1,57 +0,0 @@ -id(); - $table->string('queue')->index(); - $table->longText('payload'); - $table->unsignedTinyInteger('attempts'); - $table->unsignedInteger('reserved_at')->nullable(); - $table->unsignedInteger('available_at'); - $table->unsignedInteger('created_at'); - }); - - Schema::create('job_batches', function (Blueprint $table) { - $table->string('id')->primary(); - $table->string('name'); - $table->integer('total_jobs'); - $table->integer('pending_jobs'); - $table->integer('failed_jobs'); - $table->longText('failed_job_ids'); - $table->mediumText('options')->nullable(); - $table->integer('cancelled_at')->nullable(); - $table->integer('created_at'); - $table->integer('finished_at')->nullable(); - }); - - Schema::create('failed_jobs', function (Blueprint $table) { - $table->id(); - $table->string('uuid')->unique(); - $table->text('connection'); - $table->text('queue'); - $table->longText('payload'); - $table->longText('exception'); - $table->timestamp('failed_at')->useCurrent(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('jobs'); - Schema::dropIfExists('job_batches'); - Schema::dropIfExists('failed_jobs'); - } -}; 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 new file mode 100644 index 0000000..ea4e835 --- /dev/null +++ b/database/migrations/2026_06_27_132957_create_add_cards_table.php @@ -0,0 +1,31 @@ +id(); + $table->string('buyer'); + $table->integer('num_card'); + $table->string('seller'); + $table->date('date')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('add_card'); + } +}; diff --git a/database/migrations/2026_06_27_132957_create_administrations_table.php b/database/migrations/2026_06_27_132957_create_administrations_table.php new file mode 100644 index 0000000..8dbdd99 --- /dev/null +++ b/database/migrations/2026_06_27_132957_create_administrations_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('msnv'); + $table->integer('received')->nullable(); + $table->string('sender')->nullable(); + $table->integer('sent')->nullable(); + $table->string('receiver')->nullable(); + $table->date('date')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('administration'); + } +}; diff --git a/database/seeders/MockDataSeeder.php b/database/seeders/MockDataSeeder.php new file mode 100644 index 0000000..b8b5e51 --- /dev/null +++ b/database/seeders/MockDataSeeder.php @@ -0,0 +1,167 @@ + 'ADMIN', + 'mail' => 'admin@runsystem.net', + 'pass' => $password, + 'role' => User::ROLE_ADMIN, + 'status' => User::STATUS_ACTIVE, + 'card' => 0, + 'flag_send' => User::FLAG_SEND_ENABLED, + 'first_login' => User::FIRST_LOGIN_FALSE, + ]); + + User::create([ + 'msnv' => 'ADMIN2', + 'mail' => 'admin2@runsystem.net', + 'pass' => $password, + 'role' => User::ROLE_ADMIN, + 'status' => User::STATUS_ACTIVE, + 'card' => 0, + 'flag_send' => User::FLAG_SEND_ENABLED, + 'first_login' => User::FIRST_LOGIN_FALSE, + ]); + + // Active Users (Initialize with specific users needed for logs/transactions) + $users = [ + ['msnv' => 'DEV001', 'mail' => 'nguyenvana@runsystem.net', 'card' => 15, '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' => 8, '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' => 50, '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); + $users[] = [ + 'msnv' => 'DEV' . $numStr, + 'mail' => 'dev' . $numStr . '@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 + ]; + } + + foreach ($users as $u) { + User::create([ + 'msnv' => $u['msnv'], + 'mail' => $u['mail'], + 'pass' => $password, + 'role' => User::ROLE_MEMBER, + 'status' => User::STATUS_ACTIVE, + 'card' => $u['card'], + 'flag_send' => $u['flag'], + 'first_login' => $u['first_login'], + ]); + } + + // Inactive User + User::create([ + 'msnv' => 'OLD001', + 'mail' => 'nghiduy@runsystem.net', + 'pass' => $password, + 'role' => User::ROLE_MEMBER, + 'status' => User::STATUS_INACTIVE, + 'card' => 0, + 'flag_send' => User::FLAG_SEND_DISABLED, + 'first_login' => User::FIRST_LOGIN_FALSE, + ]); + + // 2. CREATE CARD ADDITION LOGS (add_card table) + // Get the first admin (id = 1) as the loader + $adminId = 1; + $now = Carbon::now(); + + $addCardLogs = [ + ['buyer' => 'DEV001', 'num_card' => 20, 'date' => clone $now], + ['buyer' => 'DEV002', 'num_card' => 10, 'date' => clone $now], + ['buyer' => 'SALE01', 'num_card' => 50, 'date' => (clone $now)->subDays(2)], + ['buyer' => 'TEST01', 'num_card' => 10, 'date' => (clone $now)->subMonth()], // Last month + ]; + + foreach ($addCardLogs as $index => $log) { + AddCard::create([ + 'buyer' => 100 + $index, // Dummy int ID because the DB column is designed as int instead of string msnv + 'num_card' => $log['num_card'], + 'seller' => $adminId, + 'date' => $log['date'] + ]); + } + + // 3. CREATE CARD SENDING HISTORY (administration table) + // Create transactions to populate Top Received / Top Sent for the month + $transactions = [ + // Current month transactions + ['sender' => 'DEV001', 'receiver' => 'DEV002', 'amount' => 5, 'date' => clone $now], + ['sender' => 'DEV001', 'receiver' => 'TEST01', 'amount' => 3, 'date' => (clone $now)->subDays(1)], + ['sender' => 'SALE01', 'receiver' => 'DEV002', 'amount' => 4, 'date' => (clone $now)->subDays(2)], + ['sender' => 'TEST01', 'receiver' => 'HR001', 'amount' => 2, 'date' => (clone $now)->subDays(3)], + ['sender' => 'DEV002', 'receiver' => 'DEV001', 'amount' => 1, 'date' => clone $now], + + // Last month transactions + ['sender' => 'DEV001', 'receiver' => 'SALE01', 'amount' => 5, 'date' => (clone $now)->subMonth()], + ['sender' => 'HR001', 'receiver' => 'DEV001', 'amount' => 5, 'date' => (clone $now)->subMonth()->subDays(5)], + + // July 2026 transactions (Diverse Mock Data) + ['sender' => 'DEV001', 'receiver' => 'SALE01', 'amount' => 4, 'date' => Carbon::create(2026, 7, 5)], + ['sender' => 'SALE01', 'receiver' => 'TEST01', 'amount' => 2, 'date' => Carbon::create(2026, 7, 12)], + ['sender' => 'DEV002', 'receiver' => 'HR001', 'amount' => 1, 'date' => Carbon::create(2026, 7, 18)], + ['sender' => 'TEST01', 'receiver' => 'DEV001', 'amount' => 3, 'date' => Carbon::create(2026, 7, 22)], + ['sender' => 'HR001', 'receiver' => 'DEV002', 'amount' => 5, 'date' => Carbon::create(2026, 7, 28)], + ['sender' => 'SALE01', 'receiver' => 'DEV001', 'amount' => 2, 'date' => Carbon::create(2026, 7, 30)], + ['sender' => 'DEV001', 'receiver' => 'DEV002', 'amount' => 3, 'date' => Carbon::create(2026, 7, 15)], + ['sender' => 'TEST01', 'receiver' => 'SALE01', 'amount' => 4, 'date' => Carbon::create(2026, 7, 8)], + ]; + + foreach ($transactions as $t) { + // Sender record + Administration::create([ + 'msnv' => $t['sender'], + 'received' => 0, + 'sender' => null, + 'sent' => $t['amount'], + 'receiver' => $t['receiver'], + 'date' => $t['date']->format('Y-m-d') + ]); + + // Receiver record + Administration::create([ + 'msnv' => $t['receiver'], + 'received' => $t['amount'], + 'sender' => $t['sender'], + 'sent' => 0, + 'receiver' => null, + 'date' => $t['date']->format('Y-m-d') + ]); + } + } +} diff --git a/lang/en/auth.php b/lang/en/auth.php new file mode 100644 index 0000000..919a7c5 --- /dev/null +++ b/lang/en/auth.php @@ -0,0 +1,12 @@ + 'Login', + 'email' => 'Email', + 'email_placeholder' => 'Enter your email', + 'password' => 'Password', + 'password_placeholder' => 'Enter your password', + 'forgot_password' => 'Forgot password?', + 'system_name' => 'Thank Card System', + 'developed_by' => 'Developed by GMO-Z.com RUNSYSTEM', +]; diff --git a/lang/en/layout.php b/lang/en/layout.php new file mode 100644 index 0000000..80bf044 --- /dev/null +++ b/lang/en/layout.php @@ -0,0 +1,12 @@ + 'Manage Users', + 'add_user' => 'Add User', + 'my_page' => 'My Page', + 'send_card' => 'Send Thank Card', + 'change_password' => 'Change Password', + 'logout' => 'Logout', + 'have_questions' => 'Have questions?', + 'feedback' => 'Feedback', +]; diff --git a/lang/vi/auth.php b/lang/vi/auth.php new file mode 100644 index 0000000..8d137cf --- /dev/null +++ b/lang/vi/auth.php @@ -0,0 +1,12 @@ + 'Đăng nhập', + 'email' => 'Email', + 'email_placeholder' => 'Nhập email của bạn', + 'password' => 'Mật khẩu', + 'password_placeholder' => 'Nhập mật khẩu', + 'forgot_password' => 'Quên mật khẩu?', + 'system_name' => 'Hệ thống Thank Card', + 'developed_by' => 'Được phát triển bởi GMO-Z.com RUNSYSTEM', +]; diff --git a/lang/vi/layout.php b/lang/vi/layout.php new file mode 100644 index 0000000..ae69816 --- /dev/null +++ b/lang/vi/layout.php @@ -0,0 +1,12 @@ + 'Quản lý User', + 'add_user' => 'Thêm User', + 'my_page' => 'My Page', + 'send_card' => 'Gửi Thank Card', + 'change_password' => 'Đổi mật khẩu', + 'logout' => 'Đăng xuất', + 'have_questions' => 'Bạn có thắc mắc?', + 'feedback' => 'Phản hồi', +]; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f50f84c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2771 @@ +{ + "name": "thankcard-system", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@fontsource/roboto": "^5.2.10", + "puppeteer": "^25.2.1" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.0.0", + "axios": "^1.11.0", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^2.0.0", + "tailwindcss": "^4.0.0", + "vite": "^7.0.7" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@fontsource/roboto": { + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.10.tgz", + "integrity": "sha512-8HlA5FtSfz//oFSr2eL7GFXAiE7eIkcGOtx7tjsLKq+as702x9+GU7K95iDeWFapHC4M2hv9RrpXKRTGGBI8Zg==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.5.tgz", + "integrity": "sha512-xYXNuEQmHNIPWWcbL/skf2KF7seyp7c1xmKFRk3wmdFx7VwBsKVrtOLKs8ecaezsKPsWeF1YsgwIiElAscaryA==", + "license": "Apache-2.0", + "dependencies": { + "modern-tar": "^0.7.6", + "yargs": "^18.0.0" + }, + "bin": { + "browsers": "lib/main-cli.js" + }, + "engines": { + "node": ">=22.12.0" + }, + "peerDependencies": { + "proxy-agent": ">=8.0.1" + }, + "peerDependenciesMeta": { + "proxy-agent": { + "optional": true + } + } + }, + "node_modules/@puppeteer/browsers/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/@puppeteer/browsers/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@puppeteer/browsers/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.1.tgz", + "integrity": "sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "5.21.6", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.1" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.1.tgz", + "integrity": "sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.1", + "@tailwindcss/oxide-darwin-arm64": "4.3.1", + "@tailwindcss/oxide-darwin-x64": "4.3.1", + "@tailwindcss/oxide-freebsd-x64": "4.3.1", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.1", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.1", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.1", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.1", + "@tailwindcss/oxide-linux-x64-musl": "4.3.1", + "@tailwindcss/oxide-wasm32-wasi": "4.3.1", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.1", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.1" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.1.tgz", + "integrity": "sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.1.tgz", + "integrity": "sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.1.tgz", + "integrity": "sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.1.tgz", + "integrity": "sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.1.tgz", + "integrity": "sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.1.tgz", + "integrity": "sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.1.tgz", + "integrity": "sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.1.tgz", + "integrity": "sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.1.tgz", + "integrity": "sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.1.tgz", + "integrity": "sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.10.0", + "@emnapi/runtime": "^1.10.0", + "@emnapi/wasi-threads": "^1.2.1", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.1.tgz", + "integrity": "sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.1.tgz", + "integrity": "sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.1.tgz", + "integrity": "sha512-hItDHuIIlEV61R+faXu66s1K36aTurO/Qw0e45Vskz57gXl9pWOT6eg3zmcEui6CZXddbN7zd41bwmvag4JGwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.3.1", + "@tailwindcss/oxide": "4.3.1", + "tailwindcss": "4.3.1" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chromium-bidi": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-16.0.1.tgz", + "integrity": "sha512-J63PGu/9PpeCwLIcKYyzWP6yaVL5pxuBc0shlYCYM8BaAkmlwiQboXO1iNbOgSDbVklEyYFfNEcHD8oOAWacUA==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "^3.0.1", + "zod": "^3.24.1" + }, + "engines": { + "node": ">=20.19.0 <22.0.0 || >=22.12.0" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concurrently": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.3.tgz", + "integrity": "sha512-ihjs0E2SxvDgq/MK418hX6YycQgKhsqxpbZuZbHo0yKfqDWdymWMjWYIpCIzqDDLLKClHlXev8whW/8WXmJ0BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.8.4", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1638949", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1638949.tgz", + "integrity": "sha512-mXwg4Fqnv0WR4iuAT/gYUmctNkjILwXFHyZ+m7Ty1dfr0ezZt2U3gnrrJTfRobJTHoXf+IbuFvFITzLrLFjwJA==", + "license": "BSD-3-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/laravel-vite-plugin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.1.0.tgz", + "integrity": "sha512-z+ck2BSV6KWtYcoIzk9Y5+p4NEjqM+Y4i8/H+VZRLq0OgNjW2DqyADquwYu5j8qRvaXwzNmfCWl1KrMlV1zpsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "vite-plugin-full-reload": "^1.1.0" + }, + "bin": { + "clean-orphaned-assets": "bin/clean.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^7.0.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/modern-tar": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.6.tgz", + "integrity": "sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/puppeteer": { + "version": "25.2.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-25.2.1.tgz", + "integrity": "sha512-2D5RMkQH9FRhDU57a1/jV9xWoxqZvUjaZOYjAAPdRCEY8A01V5sxzyGOMs8XiKU9fPF91SOSwNYpHRu5SD958g==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "3.0.5", + "chromium-bidi": "16.0.1", + "devtools-protocol": "0.0.1638949", + "lilconfig": "^3.1.3", + "puppeteer-core": "25.2.1", + "typed-query-selector": "^2.12.2" + }, + "bin": { + "puppeteer": "lib/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/puppeteer-core": { + "version": "25.2.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.2.1.tgz", + "integrity": "sha512-MwEZ4FFGJ1ZLOmu/04eISxoEMKtCnHyJBRFfgpwPPSYNG6gT6Xw1laNziFSV7uwDcx3jK+ATYIo9SfOd8Uhc3w==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "3.0.5", + "chromium-bidi": "16.0.1", + "devtools-protocol": "0.0.1638949", + "typed-query-selector": "^2.12.2", + "webdriver-bidi-protocol": "0.4.2", + "ws": "^8.21.0" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/shell-quote": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.1.tgz", + "integrity": "sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typed-query-selector": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz", + "integrity": "sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ==", + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-full-reload": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz", + "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "picomatch": "^2.3.1" + } + }, + "node_modules/vite-plugin-full-reload/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/webdriver-bidi-protocol": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.2.tgz", + "integrity": "sha512-VSV+fzfChirL3e7jay2yUC7B4HQCGtEWEg/MSSQbK+qWbqeGlRLlXTzPpYr3XGUvbpDHumWZBJxgesg4N7dbtA==", + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json index 7686b29..64a26c6 100644 --- a/package.json +++ b/package.json @@ -13,5 +13,9 @@ "laravel-vite-plugin": "^2.0.0", "tailwindcss": "^4.0.0", "vite": "^7.0.7" + }, + "dependencies": { + "@fontsource/roboto": "^5.2.10", + "puppeteer": "^25.2.1" } } diff --git a/public/fonts/FZ Poppins-Black.ttf b/public/fonts/FZ Poppins-Black.ttf new file mode 100644 index 0000000..c71b882 Binary files /dev/null and b/public/fonts/FZ Poppins-Black.ttf differ diff --git a/public/fonts/FZ Poppins-BlackItalic.ttf b/public/fonts/FZ Poppins-BlackItalic.ttf new file mode 100644 index 0000000..415034f Binary files /dev/null and b/public/fonts/FZ Poppins-BlackItalic.ttf differ diff --git a/public/fonts/FZ Poppins-Bold.ttf b/public/fonts/FZ Poppins-Bold.ttf new file mode 100644 index 0000000..3aa8bb6 Binary files /dev/null and b/public/fonts/FZ Poppins-Bold.ttf differ diff --git a/public/fonts/FZ Poppins-BoldItalic.ttf b/public/fonts/FZ Poppins-BoldItalic.ttf new file mode 100644 index 0000000..9c51f51 Binary files /dev/null and b/public/fonts/FZ Poppins-BoldItalic.ttf differ diff --git a/public/fonts/FZ Poppins-ExtraBold.ttf b/public/fonts/FZ Poppins-ExtraBold.ttf new file mode 100644 index 0000000..9f08fe2 Binary files /dev/null and b/public/fonts/FZ Poppins-ExtraBold.ttf differ diff --git a/public/fonts/FZ Poppins-ExtraBoldItalic.ttf b/public/fonts/FZ Poppins-ExtraBoldItalic.ttf new file mode 100644 index 0000000..c344563 Binary files /dev/null and b/public/fonts/FZ Poppins-ExtraBoldItalic.ttf differ diff --git a/public/fonts/FZ Poppins-ExtraLight.ttf b/public/fonts/FZ Poppins-ExtraLight.ttf new file mode 100644 index 0000000..d9c7422 Binary files /dev/null and b/public/fonts/FZ Poppins-ExtraLight.ttf differ diff --git a/public/fonts/FZ Poppins-ExtraLightItalic.ttf b/public/fonts/FZ Poppins-ExtraLightItalic.ttf new file mode 100644 index 0000000..1268dd9 Binary files /dev/null and b/public/fonts/FZ Poppins-ExtraLightItalic.ttf differ diff --git a/public/fonts/FZ Poppins-Italic.ttf b/public/fonts/FZ Poppins-Italic.ttf new file mode 100644 index 0000000..d23fe2f Binary files /dev/null and b/public/fonts/FZ Poppins-Italic.ttf differ diff --git a/public/fonts/FZ Poppins-Light.ttf b/public/fonts/FZ Poppins-Light.ttf new file mode 100644 index 0000000..a23ca85 Binary files /dev/null and b/public/fonts/FZ Poppins-Light.ttf differ diff --git a/public/fonts/FZ Poppins-LightItalic.ttf b/public/fonts/FZ Poppins-LightItalic.ttf new file mode 100644 index 0000000..96d0b35 Binary files /dev/null and b/public/fonts/FZ Poppins-LightItalic.ttf differ diff --git a/public/fonts/FZ Poppins-Medium.ttf b/public/fonts/FZ Poppins-Medium.ttf new file mode 100644 index 0000000..dcf9a57 Binary files /dev/null and b/public/fonts/FZ Poppins-Medium.ttf differ diff --git a/public/fonts/FZ Poppins-MediumItalic.ttf b/public/fonts/FZ Poppins-MediumItalic.ttf new file mode 100644 index 0000000..7ca1cdd Binary files /dev/null and b/public/fonts/FZ Poppins-MediumItalic.ttf differ diff --git a/public/fonts/FZ Poppins-Regular.ttf b/public/fonts/FZ Poppins-Regular.ttf new file mode 100644 index 0000000..73a84b1 Binary files /dev/null and b/public/fonts/FZ Poppins-Regular.ttf differ diff --git a/public/fonts/FZ Poppins-SemiBold.ttf b/public/fonts/FZ Poppins-SemiBold.ttf new file mode 100644 index 0000000..8a7cd66 Binary files /dev/null and b/public/fonts/FZ Poppins-SemiBold.ttf differ diff --git a/public/fonts/FZ Poppins-SemiBoldItalic.ttf b/public/fonts/FZ Poppins-SemiBoldItalic.ttf new file mode 100644 index 0000000..00732ce Binary files /dev/null and b/public/fonts/FZ Poppins-SemiBoldItalic.ttf differ diff --git a/public/fonts/FZ Poppins-Thin.ttf b/public/fonts/FZ Poppins-Thin.ttf new file mode 100644 index 0000000..bb3b6ce Binary files /dev/null and b/public/fonts/FZ Poppins-Thin.ttf differ diff --git a/public/fonts/FZ Poppins-ThinItalic.ttf b/public/fonts/FZ Poppins-ThinItalic.ttf new file mode 100644 index 0000000..983ce80 Binary files /dev/null and b/public/fonts/FZ Poppins-ThinItalic.ttf differ diff --git a/public/images/logo.png b/public/images/logo.png new file mode 100644 index 0000000..e335c8e Binary files /dev/null and b/public/images/logo.png differ diff --git a/refactor.php b/refactor.php new file mode 100644 index 0000000..4c7fd92 --- /dev/null +++ b/refactor.php @@ -0,0 +1,107 @@ +role == 1', 'Auth::user()->role == User::ROLE_ADMIN', $content); +$content = str_replace('Auth::user()->status == 1', 'Auth::user()->status == User::STATUS_ACTIVE', $content); +file_put_contents('app/Http/Middleware/AdminMiddleware.php', $content); + +// 4. Update app/Http/Middleware/MemberMiddleware.php +$content = file_get_contents('app/Http/Middleware/MemberMiddleware.php'); +$content = str_replace('use Illuminate\Support\Facades\Auth;', "use Illuminate\Support\Facades\Auth;\nuse App\Models\User;", $content); +$content = str_replace('Auth::user()->role == 0', 'Auth::user()->role == User::ROLE_MEMBER', $content); +$content = str_replace('Auth::user()->status == 1', 'Auth::user()->status == User::STATUS_ACTIVE', $content); +file_put_contents('app/Http/Middleware/MemberMiddleware.php', $content); + +// 5. Update app/Http/Middleware/ForceChangePasswordMiddleware.php +$content = file_get_contents('app/Http/Middleware/ForceChangePasswordMiddleware.php'); +$content = str_replace('use Illuminate\Support\Facades\Auth;', "use Illuminate\Support\Facades\Auth;\nuse App\Models\User;", $content); +$content = str_replace('Auth::user()->first_login == 1', 'Auth::user()->first_login == User::FIRST_LOGIN_TRUE', $content); +file_put_contents('app/Http/Middleware/ForceChangePasswordMiddleware.php', $content); + +// 6. Update app/Http/Controllers/AuthController.php +$content = file_get_contents('app/Http/Controllers/AuthController.php'); +$content = str_replace('use Illuminate\Support\Facades\Auth;', "use Illuminate\Support\Facades\Auth;\nuse App\Models\User;", $content); +$content = str_replace('$user->status != 1', '$user->status != User::STATUS_ACTIVE', $content); +$content = str_replace('$user->first_login == 1', '$user->first_login == User::FIRST_LOGIN_TRUE', $content); +$content = str_replace('$user->role == 1', '$user->role == User::ROLE_ADMIN', $content); +file_put_contents('app/Http/Controllers/AuthController.php', $content); + +// 7. Update app/Http/Controllers/AdminController.php +$content = file_get_contents('app/Http/Controllers/AdminController.php'); +$content = str_replace("where('status', 1)", "where('status', User::STATUS_ACTIVE)", $content); +$content = str_replace("'role' => 'required|in:0,1'", "'role' => 'required|in:' . User::ROLE_MEMBER . ',' . User::ROLE_ADMIN", $content); +$content = str_replace("'status' => 1", "'status' => User::STATUS_ACTIVE", $content); +$content = str_replace("'flag_send' => 0", "'flag_send' => User::FLAG_SEND_DISABLED", $content); +$content = str_replace("'first_login' => 1", "'first_login' => User::FIRST_LOGIN_TRUE", $content); +$content = str_replace("\$request->has('flag_send') ? 1 : 0", "\$request->has('flag_send') ? User::FLAG_SEND_ENABLED : User::FLAG_SEND_DISABLED", $content); +$content = str_replace("\$user->status = 0", "\$user->status = User::STATUS_INACTIVE", $content); +file_put_contents('app/Http/Controllers/AdminController.php', $content); + +// 8. Update app/Http/Controllers/UserController.php +$content = file_get_contents('app/Http/Controllers/UserController.php'); +$content = str_replace("where('status', 1)", "where('status', User::STATUS_ACTIVE)", $content); +$content = str_replace("max:5'", "max:' . Administration::MAX_SEND_CARD_PER_MONTH", $content); +$content = str_replace("\$sender->flag_send == 0", "\$sender->flag_send == User::FLAG_SEND_DISABLED", $content); +$content = str_replace("> 5)", "> Administration::MAX_SEND_CARD_PER_MONTH)", $content); +$content = str_replace("tối đa 5 card", 'tối đa " . Administration::MAX_SEND_CARD_PER_MONTH . " card', $content); +$content = str_replace("\$user->first_login = 0", "\$user->first_login = User::FIRST_LOGIN_FALSE", $content); +$content = str_replace("\$user->role == 1", "\$user->role == User::ROLE_ADMIN", $content); +file_put_contents('app/Http/Controllers/UserController.php', $content); + +// 9. Update app/Console/Commands/ResetCardsCommand.php +$content = file_get_contents('app/Console/Commands/ResetCardsCommand.php'); +$content = str_replace("where('status', 1)", "where('status', User::STATUS_ACTIVE)", $content); +file_put_contents('app/Console/Commands/ResetCardsCommand.php', $content); + +// 10. Update resources/views/layouts/app.blade.php +$content = file_get_contents('resources/views/layouts/app.blade.php'); +$content = str_replace("Auth::user()->role == 1", "Auth::user()->role == \App\Models\User::ROLE_ADMIN", $content); +file_put_contents('resources/views/layouts/app.blade.php', $content); + +// 11. Update resources/views/admin/users/create.blade.php +$content = file_get_contents('resources/views/admin/users/create.blade.php'); +$content = str_replace('value="0"', 'value="{{ \App\Models\User::ROLE_MEMBER }}"', $content); +$content = str_replace('value="1"', 'value="{{ \App\Models\User::ROLE_ADMIN }}"', $content); +$content = str_replace("old('role') == '0'", "old('role') == \App\Models\User::ROLE_MEMBER", $content); +$content = str_replace("old('role') == '1'", "old('role') == \App\Models\User::ROLE_ADMIN", $content); +file_put_contents('resources/views/admin/users/create.blade.php', $content); + +// 12. Update resources/views/admin/users/edit.blade.php +$content = file_get_contents('resources/views/admin/users/edit.blade.php'); +$content = str_replace("\$user->role == 1", "\$user->role == \App\Models\User::ROLE_ADMIN", $content); +file_put_contents('resources/views/admin/users/edit.blade.php', $content); + +// 13. Update resources/views/user/change_password.blade.php +$content = file_get_contents('resources/views/user/change_password.blade.php'); +$content = str_replace("Auth::user()->first_login == 1", "Auth::user()->first_login == \App\Models\User::FIRST_LOGIN_TRUE", $content); +file_put_contents('resources/views/user/change_password.blade.php', $content); + +echo "Refactored successfully!"; diff --git a/resources/css/app.css b/resources/css/app.css index 3e6abea..94b3f57 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,3 +1,56 @@ +@font-face { + font-family: 'SVN-Poppins-Regular'; + src: url('/fonts/FZ Poppins-Regular.ttf') format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'SVN-Poppins-Medium'; + src: url('/fonts/FZ Poppins-Medium.ttf') format('truetype'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'SVN-Poppins-SemiBold'; + src: url('/fonts/FZ Poppins-SemiBold.ttf') format('truetype'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'SVN-Poppins'; + src: url('/fonts/FZ Poppins-Regular.ttf') format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'SVN-Poppins'; + src: url('/fonts/FZ Poppins-Medium.ttf') format('truetype'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'SVN-Poppins'; + src: url('/fonts/FZ Poppins-SemiBold.ttf') format('truetype'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'SVN-Poppins'; + src: url('/fonts/FZ Poppins-Bold.ttf') format('truetype'); + font-weight: 700; + font-style: normal; +} + +@import "@fontsource/roboto/300.css"; +@import "@fontsource/roboto/400.css"; +@import "@fontsource/roboto/500.css"; +@import "@fontsource/roboto/700.css"; @import 'tailwindcss'; @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; @@ -6,6 +59,192 @@ @source '../**/*.js'; @theme { - --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-sans: 'SVN-Poppins', 'SVN-Poppins-SemiBold', 'SVN-Poppins-Regular', 'SVN-Poppins-Medium', 'Roboto', 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + + --color-primary: #0f4c81; + --color-primary-hover: #0a3356; + --color-primary-light: #e8f0fe; + --color-secondary: #ef222e; + --color-success: #2e7d32; + --color-warning: #ed6c02; + --color-info: #0288d1; + + --color-bg-main: #f0f4f9; + --color-bg-sidebar: #ffffff; + --color-bg-card: #ffffff; + --color-bg-card-soft: #eef2f6; + + --color-border-light: #e2e8f0; + --color-border-medium: #cbd5e1; + + --color-text-dark: #1e293b; + --color-text-medium: #475569; + --color-text-light: #64748b; + --color-text-muted: #94a3b8; + + --color-calendar-header: #4b729f; + + --shadow-card: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03); + --shadow-sidebar: 0 4px 20px 0 rgba(0, 0, 0, 0.05); + --shadow-header: 0 2px 4px 0 rgba(0, 0, 0, 0.02); +} + +@layer base { + body { + @apply bg-bg-main text-text-dark antialiased; + } +} + +.app-layout { + @apply min-h-screen flex bg-bg-main; +} + +.sidebar { + @apply w-60 bg-bg-sidebar border-r border-border-light flex flex-col justify-between shrink-0 shadow-sidebar transition-all duration-300; +} + +.main-content { + @apply flex-1 flex flex-col min-w-0; +} + +.top-header { + @apply h-16 bg-bg-sidebar border-b border-border-light flex items-center justify-between px-6 shadow-header; +} + +.sidebar-link { + @apply flex items-center gap-3 px-4 py-3 text-text-medium font-medium rounded-lg hover:bg-gray-50 hover:text-primary transition-all duration-200; +} + +.sidebar-link-active { + @apply text-primary bg-primary-light font-bold; +} + +.card-stat { + @apply bg-bg-card-soft text-primary p-5 rounded-lg border border-transparent shadow-card relative overflow-hidden transition-all duration-200 hover:shadow-md; +} + +.card-stat-active { + @apply bg-primary text-white p-5 rounded-lg border border-transparent shadow-card relative overflow-hidden transition-all duration-200 hover:shadow-md; +} + +.card-stat::after, .card-stat-active::after { + content: ''; + position: absolute; + right: -20px; + bottom: -20px; + width: 100px; + height: 100px; + border-radius: 50%; + background: radial-gradient(circle, rgba(15, 76, 129, 0.05) 0%, transparent 70%); + pointer-events: none; +} + +.card-stat-active::after { + background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); +} + +.calendar-card { + @apply bg-bg-card rounded-lg shadow-card border border-border-light overflow-hidden; +} + +.calendar-header { + @apply grid grid-cols-7 bg-calendar-header text-white font-bold text-center py-3; +} + +.calendar-grid { + @apply grid grid-cols-7 border-t border-l border-border-light; +} + +.calendar-day { + @apply bg-bg-card border-r border-b border-border-light min-h-[100px] p-2 flex flex-col justify-between transition-colors duration-150 hover:bg-gray-50; +} + +.calendar-day-weekend { + @apply bg-gray-50; +} + +/* --- FORM DESIGN SYSTEM --- */ +.form-container { + @apply w-full max-w-[1100px] mx-auto bg-white rounded-xl shadow-sm border border-[#d9dfe7] overflow-hidden; +} + +.form-header { + @apply px-6 py-6 sm:px-8 sm:py-8 border-b border-[#d9dfe7] flex items-center justify-between; +} + +.form-header-title { + @apply text-[24px] sm:text-[32px] font-[600] text-text-dark leading-tight; +} + +.form-body { + @apply p-6 sm:p-8; /* 32px top/bottom card padding */ +} + +.form-group { + @apply mb-6 relative; /* 24px gap */ +} + +.form-label { + @apply block text-[16px] font-[600] text-text-dark mb-2; /* 8px label gap */ +} + +/* Standard Input & Select */ +.form-input { + @apply w-full h-[48px] px-4 bg-white border border-[#d9dfe7] rounded-lg outline-none text-text-dark text-base placeholder-text-muted focus:border-primary focus:ring-2 focus:ring-primary/20 hover:border-gray-400 transition-all duration-200 shadow-sm; +} + +select.form-input { + @apply appearance-none pr-10 cursor-pointer bg-no-repeat; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); + background-position: right 1rem center; + background-size: 1.25em 1.25em; +} + +.form-input[type="checkbox"] { + @apply w-5 h-5 min-h-0 text-primary border-[#d9dfe7] rounded focus:ring-primary focus:ring-2 focus:ring-offset-1 cursor-pointer transition-colors hover:border-gray-400; +} + +.form-input-with-icon { + @apply pl-11; +} + +.form-input-icon { + @apply absolute left-4 text-text-light pointer-events-none w-5 h-5 flex items-center justify-center; +} + +.form-input-group { + @apply relative flex items-center w-full; +} + +.form-actions { + @apply mt-2 flex flex-col sm:flex-row justify-end gap-4; +} + +.form-footer { + @apply px-6 py-6 sm:px-8 sm:py-6 border-t border-[#d9dfe7] bg-gray-50/30 flex flex-col sm:flex-row justify-end gap-3; +} + +.helper-text { + @apply text-[14px] text-text-muted mt-2 leading-snug block; +} + +.error-text { + @apply text-red-500 text-[14px] font-semibold mt-2 block; +} + +/* Action Buttons */ +.btn-primary { + @apply bg-primary hover:bg-primary-hover text-white font-[600] h-[45px] max-h-[45px] px-8 border border-transparent rounded-lg shadow-sm transition-all duration-200 text-center cursor-pointer inline-flex items-center justify-center focus:ring-2 focus:ring-offset-1 focus:ring-primary/50 box-border; +} + +.btn-secondary { + @apply bg-white hover:bg-gray-50 text-text-medium border border-[#d9dfe7] font-[600] h-[45px] max-h-[45px] px-8 rounded-lg shadow-sm transition-all duration-200 text-center cursor-pointer inline-flex items-center justify-center focus:ring-2 focus:ring-offset-1 focus:ring-gray-200 box-border; +} + +.nav-badge { + @apply bg-secondary text-white text-[10px] font-bold px-1.5 py-0.5 rounded-md uppercase ml-2 animate-pulse; +} + +.notification-badge { + @apply absolute -top-1 -right-1 bg-secondary text-white text-[10px] font-bold w-4.5 h-4.5 rounded-full flex items-center justify-center; } diff --git a/resources/views/admin/users/create.blade.php b/resources/views/admin/users/create.blade.php new file mode 100644 index 0000000..0826b30 --- /dev/null +++ b/resources/views/admin/users/create.blade.php @@ -0,0 +1,70 @@ +@extends('layouts.app') +@section('title', 'Thêm User Mới') + +@section('content') +
+
+

Thêm User Mới

+
+ +
+ @csrf + +
+
+ +
+ + + + + + +
+ @error('msnv'){{ $message }}@enderror +
+ +
+ +
+ + + + + + +
+ @error('mail'){{ $message }}@enderror +
+ +
+ +
+ + + + + + +
+ Lưu ý: User sẽ bị buộc phải đổi mật khẩu này ở lần đăng nhập đầu tiên. + @error('password'){{ $message }}@enderror +
+ +
+ + + @error('role'){{ $message }}@enderror +
+
+ + +
+
+@endsection diff --git a/resources/views/admin/users/edit.blade.php b/resources/views/admin/users/edit.blade.php new file mode 100644 index 0000000..05a8c55 --- /dev/null +++ b/resources/views/admin/users/edit.blade.php @@ -0,0 +1,116 @@ +@extends('layouts.app') +@section('title', 'Chi tiết User') + +@section('content') +
+ +
+
+
+

Quản Lý Thẻ: {{ $user->msnv }}

+
+
+
+
+ Email: + {{ $user->mail }} +
+
+ Role: + {{ $user->role == \App\Models\User::ROLE_ADMIN ? 'Admin' : 'Member' }} +
+
+ Số dư thẻ: + {{ $user->card }} +
+
+
+ +
+ @csrf + @method('PUT') + +
+
+ + + @error('num_card'){{ $message }}@enderror +
+ +
+ +
+
+ + +
+
+
+ + +
+
+
+

Lịch sử nhận / gửi

+
+ +
+
+ +
+ + + + + + + + + + + @forelse($administrations as $admin_record) + @php + $isReceiver = $admin_record->msnv == $user->msnv && $admin_record->received > 0; + @endphp + + + + + + + @empty + + + + @endforelse + +
NgàyHành độngĐối tượngSố lượng
{{ Carbon\Carbon::parse($admin_record->date)->format('d/m/Y') }} + @if($isReceiver) + Nhận thẻ + @else + Gửi thẻ + @endif + + @if($isReceiver) + Từ: {{ $admin_record->sender }} + @else + Tới: {{ $admin_record->receiver }} + @endif + + @if($isReceiver) + +{{ $admin_record->received }} + @else + -{{ $admin_record->sent }} + @endif +
Không có giao dịch nào trong tháng này.
+
+
+
+
+@endsection diff --git a/resources/views/admin/users/index.blade.php b/resources/views/admin/users/index.blade.php new file mode 100644 index 0000000..afbe795 --- /dev/null +++ b/resources/views/admin/users/index.blade.php @@ -0,0 +1,258 @@ +@extends('layouts.app') +@section('title', 'Quản lý Users') + +@section('content') +
+

+ Danh sách User (Tháng {{ Carbon\Carbon::parse($selectedMonth)->format('m/Y') }}) +

+
+
+ + +
+ +
+ @csrf + +
+
+
+ +
+
+
+
+ User nhận nhiều nhất + {{ $topReceivedUser && $topReceivedUser->total_received > 0 ? $topReceivedUser->msnv : 'Chưa có' }} +
+
+ Tổng thẻ đã nhận + {{ $topReceivedUser ? $topReceivedUser->total_received : 0 }} thẻ +
+
+
+ +
+
+
+ User gửi nhiều nhất + {{ $topSentUser && $topSentUser->total_sent > 0 ? $topSentUser->msnv : 'Chưa có' }} +
+
+ Tổng thẻ đã gửi + {{ $topSentUser ? $topSentUser->total_sent : 0 }} thẻ +
+
+
+
+ +
+
+ + + + + + + + + + + + + + @forelse($users as $u) + + + + + + + + + + @empty + + + + @endforelse + +
MSNVEmailĐã NhậnĐã GửiSố dư thẻQuyền gửiThao tác
{{ $u->msnv }}{{ $u->mail }}+{{ $u->total_received }}{{ $u->total_sent }}{{ $u->card }} + @if($u->flag_send) + Được gửi + @else + Không + @endif + + Quản lý + +
Chưa có user nào đang hoạt động.
+
+ @if($users->hasPages()) +
+ {{ $users->links() }} +
+ @endif +
+ + + +
+
+ + + +
+
+ +

+ Bạn có chắc chắn muốn đánh dấu nhân viên đã nghỉ việc?

+ Thao tác này sẽ ngăn user đăng nhập vào hệ thống, nhưng dữ liệu lịch sử vẫn được giữ lại. +

+
+
+ + +
+ @csrf + @method('DELETE') + +
+ +
+
+ +@push('scripts') + +@endpush +@endsection diff --git a/resources/views/components/modal.blade.php b/resources/views/components/modal.blade.php new file mode 100644 index 0000000..d8d7f63 --- /dev/null +++ b/resources/views/components/modal.blade.php @@ -0,0 +1,45 @@ +@props(['id', 'maxWidth' => 'md', 'title' => 'Thông báo', 'hideHeader' => false]) + +@php +$maxWidthClass = [ + 'sm' => 'sm:max-w-sm', + 'md' => 'sm:max-w-md', + 'lg' => 'sm:max-w-lg', + 'xl' => 'sm:max-w-xl', + '2xl' => 'sm:max-w-2xl', +][$maxWidth] ?? 'sm:max-w-md'; +@endphp + +@push('modals') + +@endpush diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php new file mode 100644 index 0000000..3eca797 --- /dev/null +++ b/resources/views/dashboard.blade.php @@ -0,0 +1,419 @@ + + + + + + + GMO-Z.com RUNSYSTEM - Dashboard + @vite(['resources/css/app.css', 'resources/js/app.js']) + + +
+ + +
+
+ + +
+ + +
+
+ + + +
+ TRẦN VĂN AN +
+
+
+ +
+ + +
+
+
+
+ Ngày công chuẩn + 22 +
+
+ Ngày công lễ + 0 +
+
+
+ +
+
+
+ Ngày công thực tế + 20 +
+
+ Nghỉ phép + 0 +
+
+
+ +
+
+
+ Số lần đi muộn, về sớm + 0 +
+
+ Số giờ đi muộn, về sớm + 0 +
+
+
+ +
+
+
+ Số giờ OT 150% + 0 +
+
+ Số giờ OT 200% + 0 +
+
+ Số giờ OT 300% + 0 +
+
+
+
+ +
+
+
+ + Tháng 06/2026 + +
+ +
+ + +
+
+ +
+
+
Thứ 2
+
Thứ 3
+
Thứ 4
+
Thứ 5
+
Thứ 6
+
Thứ 7
+
CN
+
+ +
+
+
+ X + 1 +
+
+
07:45 - 17:13
+
+ 0:28
+
+
+
+
+ X + 2 +
+
+
07:53 - 17:08
+
+ 0:15
+
+
+
+
+ X + 3 +
+
+
07:54 - 17:16
+
+ 0:22
+
+
+
+
+ X + 4 +
+
+
07:52 - 17:04
+
+ 0:12
+
+
+
+
+ X + 5 +
+
+
07:50 - 17:20
+
+ 0:30
+
+
+
+
+ 6 +
+
+
+
+
+ 7 +
+
+
+ +
+
+ X + 8 +
+
+
07:54 - 17:05
+
+ 0:11
+
+
+
+
+ X + 9 +
+
+
07:48 - 17:05
+
+ 0:17
+
+
+
+
+ X + 10 +
+
+
07:51 - 17:05
+
+ 0:14
+
+
+
+
+ X + 11 +
+
+
07:45 - 17:13
+
+ 0:28
+
+
+
+
+ X + 12 +
+
+
07:45 - 17:37
+
+ 0:52
+
+
+
+
+ 13 +
+
+
+
+
+ 14 +
+
+
+ +
+
+ X + 15 +
+
+
07:47 - 17:04
+
+ 0:17
+
+
+
+
+ X + 16 +
+
+
07:45 - 17:02
+
+ 0:17
+
+
+
+
+ X + 17 +
+
+
07:54 - 17:02
+
+ 0:08
+
+
+
+
+ X + 18 +
+
+
07:45 - 17:03
+
+ 0:18
+
+
+
+
+ X + 19 +
+
+
07:45 - 17:04
+
+ 0:19
+
+
+
+
+ 20 +
+
+
+
+
+ 21 +
+
+
+
+
+
+
+
+
+ + diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php new file mode 100644 index 0000000..95f99e3 --- /dev/null +++ b/resources/views/layouts/app.blade.php @@ -0,0 +1,182 @@ + + + + + + + GMO-Z.com RUNSYSTEM - @yield('title', 'Dashboard') + @vite(['resources/css/app.css', 'resources/js/app.js']) + @stack('styles') + + +
+ + +
+
+
+ Thank Card System +
+ +
+
+
+ + + +
+ {{ Auth::check() ? Auth::user()->mail : 'GUEST' }} + +
+ @csrf + +
+
+
+
+ +
+ @if(session('success')) +
+ {{ session('success') }} +
+ @endif + + @if(session('error')) +
+ {{ session('error') }} +
+ @endif + + @yield('content') +
+
+
+ @yield('modals') + @stack('modals') + + @stack('scripts') + + diff --git a/resources/views/login.blade.php b/resources/views/login.blade.php new file mode 100644 index 0000000..e2c4493 --- /dev/null +++ b/resources/views/login.blade.php @@ -0,0 +1,131 @@ + + + + + + + GMO-Z.com RUNSYSTEM - {{ __('auth.login') }} + @vite(['resources/css/app.css', 'resources/js/app.js']) + + +
+ +
+
+
+
+ + + +
+ +
+ GMO-Z.com RUNSYSTEM +
+ +
+

{{ __('auth.login') }}

+ +
+ @csrf + + @if($errors->any()) +
+ + {{ $errors->first() }} +
+ @endif + +
+ +
+ + + + + + +
+
+ +
+ +
+ + + + + + +
+
+ + +
+
+ +
+ © {{ __('auth.developed_by') }} +
+
+
+ +
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + GMO-Z + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+
+ +
+ + diff --git a/resources/views/user/change_password.blade.php b/resources/views/user/change_password.blade.php new file mode 100644 index 0000000..b70aed1 --- /dev/null +++ b/resources/views/user/change_password.blade.php @@ -0,0 +1,56 @@ +@extends('layouts.app') +@section('title', 'Đổi Mật Khẩu') + +@section('content') +
+
+

Đổi Mật Khẩu

+
+ +
+ @csrf +
+ @if(Auth::user()->first_login == \App\Models\User::FIRST_LOGIN_TRUE) +
+ + + + Đây là lần đầu tiên bạn đăng nhập vào hệ thống. Để đảm bảo an toàn, hệ thống yêu cầu bạn đổi mật khẩu trước khi sử dụng các chức năng. +
+ @endif + +
+ +
+ + + + + + +
+ @error('password'){{ $message }}@enderror +
+ +
+ +
+ + + + + + +
+
+
+ + +
+
+@endsection diff --git a/resources/views/user/dashboard.blade.php b/resources/views/user/dashboard.blade.php new file mode 100644 index 0000000..68960d1 --- /dev/null +++ b/resources/views/user/dashboard.blade.php @@ -0,0 +1,77 @@ +@extends('layouts.app') +@section('title', 'My Page') + +@section('content') +
+
+

+ My Page +

+
+ + + + Thẻ hiện có: {{ $user->card }} +
+
+ +
+ + +
+
+ +
+
+

Lịch sử nhận / gửi thẻ (Tháng {{ Carbon\Carbon::parse($selectedMonth)->format('m/Y') }})

+
+ +
+ + + + + + + + + + + @forelse($administrations as $admin_record) + @php + $isReceiver = $admin_record->msnv == $user->msnv && $admin_record->received > 0; + @endphp + + + + + + + @empty + + + + @endforelse + +
NgàyLoại giao dịchĐối tácSố lượng
{{ Carbon\Carbon::parse($admin_record->date)->format('d/m/Y') }} + @if($isReceiver) + Bạn đã nhận thẻ + @else + Bạn gửi tặng thẻ + @endif + + @if($isReceiver) + Nhận từ: {{ $admin_record->sender }} + @else + Gửi cho: {{ $admin_record->receiver }} + @endif + + @if($isReceiver) + +{{ $admin_record->received }} + @else + -{{ $admin_record->sent }} + @endif +
Bạn chưa có giao dịch gửi/nhận thẻ nào trong tháng này.
+
+
+@endsection diff --git a/resources/views/user/send.blade.php b/resources/views/user/send.blade.php new file mode 100644 index 0000000..30e3a94 --- /dev/null +++ b/resources/views/user/send.blade.php @@ -0,0 +1,146 @@ +@extends('layouts.app') +@section('title', 'Gửi Thank Card') + +@section('content') +
+
+

Gửi Thank Card Tới Đồng Nghiệp

+
+ +
+ @csrf + +
+
+ + +
+ +
+ + +

Lưu ý: Chỉ được gửi tối đa {{ \App\Models\Administration::MAX_SEND_CARD_PER_MONTH }} thẻ cho cùng 1 người trong 1 tháng.

+
+
+ + +
+
+ + + +

+ + +
+ +
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/console.php b/routes/console.php index 3c9adf1..a699a06 100644 --- a/routes/console.php +++ b/routes/console.php @@ -2,7 +2,10 @@ use Illuminate\Foundation\Inspiring; use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\Schedule; Artisan::command('inspire', function () { $this->comment(Inspiring::quote()); })->purpose('Display an inspiring quote'); + +Schedule::command('cards:reset')->monthlyOn(1, '00:00'); diff --git a/routes/web.php b/routes/web.php index 86a06c5..a9a6f8a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,7 +1,51 @@ route('login'); +}); + +Route::get('/test-modal', function() { + return view('admin.users.index', [ + 'users' => [], + 'selectedMonth' => '2026-06', + 'topReceivedUser' => null, + 'topSentUser' => null + ]); +}); +Route::get('/login', [AuthController::class, 'showLoginForm'])->name('login'); +Route::post('/login', [AuthController::class, 'login']); + +Route::middleware('auth')->group(function () { + Route::post('/logout', [AuthController::class, 'logout'])->name('logout'); + + Route::middleware('force_change_password')->group(function () { + + Route::middleware('admin')->prefix('admin')->name('admin.')->group(function () { + Route::get('/', [AdminController::class, 'index'])->name('dashboard'); + Route::get('/users', [AdminController::class, 'index'])->name('users.index'); + + Route::get('/users/create', [AdminController::class, 'create'])->name('users.create'); + Route::post('/users', [AdminController::class, 'store'])->name('users.store'); + Route::get('/users/{msnv}/edit', [AdminController::class, 'edit'])->name('users.edit'); + Route::put('/users/{msnv}', [AdminController::class, 'update'])->name('users.update'); + Route::delete('/users/{msnv}', [AdminController::class, 'destroy'])->name('users.destroy'); + + Route::post('/reset-cards', [AdminController::class, 'resetCards'])->name('reset_cards'); + }); + + Route::middleware('member')->group(function () { + Route::get('/my-page', [UserController::class, 'index'])->name('user.dashboard'); + + Route::get('/send-thankcards', [UserController::class, 'sendThankcards'])->name('user.send'); + Route::post('/send-thankcards', [UserController::class, 'storeThankcards'])->name('user.store_send'); + }); + }); + + Route::get('/change-password', [UserController::class, 'changePasswordForm'])->name('user.change_password'); + Route::post('/change-password', [UserController::class, 'updatePassword'])->name('user.update_password'); }); diff --git a/test_modal_css.cjs b/test_modal_css.cjs new file mode 100644 index 0000000..e7e4bdd --- /dev/null +++ b/test_modal_css.cjs @@ -0,0 +1,103 @@ +const puppeteer = require('puppeteer'); + +(async () => { + const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }); + const page = await browser.newPage(); + await page.goto('http://127.0.0.1:8000/test-modal'); + + // Make modal visible for accurate computed CSS + await page.evaluate(() => { + const modal = document.getElementById('deleteModal'); + if (modal) { + modal.classList.remove('hidden'); + modal.style.display = 'flex'; + } + }); + + const data = await page.evaluate(() => { + const modal = document.getElementById('deleteModal'); + if (!modal) return { error: 'Modal not found' }; + + // 1. DOM Path + let current = modal; + let path = []; + while (current && current.nodeType === 1) { + let desc = current.tagName.toLowerCase(); + if (current.id) desc += '#' + current.id; + if (current.className && typeof current.className === 'string') { + desc += '.' + current.className.split(' ').join('.'); + } + path.unshift(desc); + current = current.parentNode; + } + + // 2. Computed CSS for modal + const getStyles = (el) => { + const cs = window.getComputedStyle(el); + return { + position: cs.position, + top: cs.top, + right: cs.right, + bottom: cs.bottom, + left: cs.left, + display: cs.display, + zIndex: cs.zIndex, + transform: cs.transform !== 'none' ? cs.transform : 'none', + contain: cs.contain !== 'none' ? cs.contain : 'none', + filter: cs.filter !== 'none' ? cs.filter : 'none', + backdropFilter: cs.backdropFilter !== 'none' ? cs.backdropFilter : 'none', + perspective: cs.perspective !== 'none' ? cs.perspective : 'none', + overflow: cs.overflow, + overflowY: cs.overflowY, + willChange: cs.willChange !== 'auto' ? cs.willChange : 'auto' + }; + }; + + const modalCSS = getStyles(modal); + + // 4. Ancestor trace + let ancestors = []; + current = modal.parentNode; + while (current && current.nodeType === 1) { + const cs = window.getComputedStyle(current); + const hasContext = cs.transform !== 'none' || cs.filter !== 'none' || cs.perspective !== 'none' || cs.contain !== 'none' || cs.willChange !== 'auto' || cs.position !== 'static' || cs.zIndex !== 'auto' || cs.isolation !== 'auto' || cs.overflow !== 'visible'; + + if (hasContext) { + ancestors.push({ + tagName: current.tagName, + id: current.id, + className: current.className, + position: cs.position, + zIndex: cs.zIndex, + transform: cs.transform !== 'none' ? cs.transform : 'none', + filter: cs.filter !== 'none' ? cs.filter : 'none', + perspective: cs.perspective !== 'none' ? cs.perspective : 'none', + contain: cs.contain !== 'none' ? cs.contain : 'none', + willChange: cs.willChange !== 'auto' ? cs.willChange : 'auto', + overflow: cs.overflow, + isolation: cs.isolation !== 'auto' ? cs.isolation : 'auto' + }); + } + current = current.parentNode; + } + + // Find element that has large scrollHeight + const bodyHeight = document.body.scrollHeight; + const mainContent = document.querySelector('.main-content'); + const scrollContainer = document.querySelector('.overflow-y-auto'); + + return { + path, + modalCSS, + ancestors, + scrollHeights: { + body: bodyHeight, + mainContent: mainContent ? mainContent.scrollHeight : null, + scrollContainer: scrollContainer ? scrollContainer.scrollHeight : null + } + }; + }); + + console.log(JSON.stringify(data, null, 2)); + await browser.close(); +})();