From 781a0f8aa7e2f3089ba11b6481203c4f02354a49 Mon Sep 17 00:00:00 2001 From: antv Date: Tue, 21 Jul 2026 10:16:06 +0700 Subject: [PATCH] m --- app/Http/Controllers/User/UserController.php | 59 ++++++-- .../Requests/User/SendThankCardRequest.php | 1 + app/Models/Administration.php | 1 + .../User/Contracts/UserServiceInterface.php | 2 +- app/Services/User/UserService.php | 30 ++-- config/card_themes.php | 76 ++++++++++ config/constants.php | 5 + ...dd_template_id_to_administration_table.php | 28 ++++ .../views/components/sidebar-item.blade.php | 2 +- resources/views/components/sidebar.blade.php | 8 +- .../views/components/stat-card.blade.php | 5 +- .../components/transaction-history.blade.php | 10 +- resources/views/user/dashboard.blade.php | 131 +++++++++++++----- .../partials/received_cards_feed.blade.php | 28 ++-- .../user/partials/sent_cards_feed.blade.php | 28 ++-- resources/views/user/ranking.blade.php | 86 +++++++++++- resources/views/user/send.blade.php | 58 ++++---- 17 files changed, 436 insertions(+), 122 deletions(-) create mode 100644 config/card_themes.php create mode 100644 database/migrations/2026_07_20_095829_add_template_id_to_administration_table.php diff --git a/app/Http/Controllers/User/UserController.php b/app/Http/Controllers/User/UserController.php index e4daa62..cd5c596 100644 --- a/app/Http/Controllers/User/UserController.php +++ b/app/Http/Controllers/User/UserController.php @@ -31,22 +31,52 @@ class UserController extends Controller $user = Auth::user(); $administrations = $this->userService->getDashboard($user, $selectedMonth); - $stats = $this->userService->getPersonalStats($user, $selectedMonth); - $receivedRanking = $this->userService->getRankingList('received', $selectedMonth, $user); - $sentRanking = $this->userService->getRankingList('sent', $selectedMonth, $user); + $isAdmin = $user->role == config('constants.ROLE_ADMIN'); + + if ($isAdmin) { + $stats = $this->userService->getPersonalStats($user, $selectedMonth); + $receivedRanking = $this->userService->getRankingList('received', $selectedMonth, $user); + $sentRanking = $this->userService->getRankingList('sent', $selectedMonth, $user); + + $receivedCount = (int) $stats['receivedCount']; + $sentCount = (int) $stats['sentCount']; + $currentRank = (int) $stats['currentRank']; + $receivedRankers = $receivedRanking['rankers']; + $receivedCurrentUserRankItem = $receivedRanking['currentUserRankItem']; + $sentRankers = $sentRanking['rankers']; + $sentCurrentUserRankItem = $sentRanking['currentUserRankItem']; + } else { + // For member, do NOT fetch ranking lists or calculate rank to ensure security and improve DB performance + $startOfMonth = Carbon::parse($selectedMonth)->startOfMonth(); + $endOfMonth = Carbon::parse($selectedMonth)->endOfMonth(); + + $receivedCount = (int) \App\Models\Administration::where('msnv', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('received'); + + $sentCount = (int) \App\Models\Administration::where('msnv', $user->msnv) + ->whereBetween('date', [$startOfMonth, $endOfMonth]) + ->sum('sent'); + + $currentRank = 0; + $receivedRankers = []; + $receivedCurrentUserRankItem = null; + $sentRankers = []; + $sentCurrentUserRankItem = null; + } $dashboardData = new DashboardDataDto( administrations: $administrations, selectedMonth: $selectedMonth, user: $user, - receivedRankers: $receivedRanking['rankers'], - receivedCurrentUserRankItem: $receivedRanking['currentUserRankItem'], - sentRankers: $sentRanking['rankers'], - sentCurrentUserRankItem: $sentRanking['currentUserRankItem'], - receivedCount: (int) $stats['receivedCount'], - sentCount: (int) $stats['sentCount'], - currentRank: (int) $stats['currentRank'] + receivedRankers: $receivedRankers, + receivedCurrentUserRankItem: $receivedCurrentUserRankItem, + sentRankers: $sentRankers, + sentCurrentUserRankItem: $sentCurrentUserRankItem, + receivedCount: $receivedCount, + sentCount: $sentCount, + currentRank: $currentRank ); return view('user.dashboard', $dashboardData->toArray()); @@ -86,7 +116,8 @@ class UserController extends Controller $this->userService->sendThankcards( Auth::user(), (string) $request->input('receiver'), - (int) $request->input('amount') + (int) $request->input('amount'), + (int) $request->input('template_id', 1) ); } catch (ThankCardException $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 422); @@ -175,8 +206,12 @@ class UserController extends Controller } // New page: ranking (both received and sent) with tabs - public function ranking(Request $request): View + public function ranking(Request $request): \Illuminate\View\View { + if (Auth::user()->role !== config('constants.ROLE_ADMIN')) { + abort(404); + } + $selectedMonth = $request->input('month', Carbon::now()->format('Y-m')); $user = Auth::user(); $receivedRanking = $this->userService->getRankingList('received', $selectedMonth, $user); diff --git a/app/Http/Requests/User/SendThankCardRequest.php b/app/Http/Requests/User/SendThankCardRequest.php index 2d5c7c4..6248722 100644 --- a/app/Http/Requests/User/SendThankCardRequest.php +++ b/app/Http/Requests/User/SendThankCardRequest.php @@ -27,6 +27,7 @@ class SendThankCardRequest extends FormRequest Rule::exists('user', 'msnv')->where('status', config('constants.STATUS_ACTIVE')) ], 'amount' => 'required|integer|min:1|max:' . Administration::MAX_SEND_CARD_PER_MONTH, + 'template_id' => 'nullable|integer|in:1,2,3,4', ]; } diff --git a/app/Models/Administration.php b/app/Models/Administration.php index 361407d..4a47026 100644 --- a/app/Models/Administration.php +++ b/app/Models/Administration.php @@ -22,6 +22,7 @@ class Administration extends Model 'sent', 'receiver', 'date', + 'template_id', ]; public function senderUser() diff --git a/app/Services/User/Contracts/UserServiceInterface.php b/app/Services/User/Contracts/UserServiceInterface.php index 25680f7..16c4820 100644 --- a/app/Services/User/Contracts/UserServiceInterface.php +++ b/app/Services/User/Contracts/UserServiceInterface.php @@ -11,7 +11,7 @@ interface UserServiceInterface public function getOtherActiveUsers(User $currentUser): \Illuminate\Database\Eloquent\Collection; - public function sendThankcards(User $sender, string $receiverMsnv, int $amount): void; + public function sendThankcards(User $sender, string $receiverMsnv, int $amount, ?int $templateId = 1): void; public function updatePassword(User $user, string $newPassword): void; diff --git a/app/Services/User/UserService.php b/app/Services/User/UserService.php index ee8876f..b3e84b4 100644 --- a/app/Services/User/UserService.php +++ b/app/Services/User/UserService.php @@ -33,7 +33,7 @@ class UserService implements UserServiceInterface ->get(); } - public function sendThankcards(User $sender, string $receiverMsnv, int $amount): void + public function sendThankcards(User $sender, string $receiverMsnv, int $amount, ?int $templateId = 1): void { if ($sender->flag_send == config('constants.FLAG_SEND_DISABLED')) { throw new \App\Exceptions\ThankCardException(__('messages.error.no_send_permission')); @@ -47,7 +47,7 @@ class UserService implements UserServiceInterface $startOfMonth = Carbon::now()->startOfMonth(); $endOfMonth = Carbon::now()->endOfMonth(); - DB::transaction(function () use ($sender, $receiverMsnv, $amount, $startOfMonth, $endOfMonth) { + DB::transaction(function () use ($sender, $receiverMsnv, $amount, $startOfMonth, $endOfMonth, $templateId) { // Lock sender record to prevent concurrent transaction modifications $lockedSender = User::where('id', $sender->id)->lockForUpdate()->first(); @@ -76,21 +76,23 @@ class UserService implements UserServiceInterface } Administration::create([ - 'msnv' => $receiverMsnv, - 'received' => $amount, - 'sender' => $lockedSender->msnv, - 'sent' => 0, - 'receiver' => null, - 'date' => Carbon::today(), + 'msnv' => $receiverMsnv, + 'received' => $amount, + 'sender' => $lockedSender->msnv, + 'sent' => 0, + 'receiver' => null, + 'date' => Carbon::today(), + 'template_id' => $templateId, ]); Administration::create([ - 'msnv' => $lockedSender->msnv, - 'received' => 0, - 'sender' => null, - 'sent' => $amount, - 'receiver' => $receiverMsnv, - 'date' => Carbon::today(), + 'msnv' => $lockedSender->msnv, + 'received' => 0, + 'sender' => null, + 'sent' => $amount, + 'receiver' => $receiverMsnv, + 'date' => Carbon::today(), + 'template_id' => $templateId, ]); $lockedSender->card -= $amount; diff --git a/config/card_themes.php b/config/card_themes.php new file mode 100644 index 0000000..dc751d5 --- /dev/null +++ b/config/card_themes.php @@ -0,0 +1,76 @@ + [ + 'id' => 1, + 'slug' => 'thu_cam_on', + 'name' => 'Thư cảm ơn', + 'label' => 'THANK CARD', + 'icon' => '💌', + 'deco_bg' => 'linear-gradient(135deg,#FFF5CC,#FFE8A0)', + 'card_bg' => 'linear-gradient(145deg,#FFF9EC,#FFFDF7)', + 'border_color' => '#FFE4A0', + 'blob1' => '#FFD066', + 'blob2' => '#FFAD00', + 'accent_color' => '#B8860B', + 'badge_bg' => 'rgba(255,176,0,0.15)', + 'wave' => 'white', + 'footer_border' => '#FFE4A0', + 'thumb' => 'from-[#FFF9EC] to-[#FFF5DD]', + 'thumb_accent' => '#FFD066', + ], + 2 => [ + 'id' => 2, + 'slug' => 'sakura', + 'name' => 'Sakura', + 'label' => 'SAKURA CARD', + 'icon' => '🌸', + 'deco_bg' => 'linear-gradient(135deg,#FFE8F4,#FFD6EC)', + 'card_bg' => 'linear-gradient(145deg,#FFF8FB,#FFF3F8)', + 'border_color' => '#FFBCD9', + 'blob1' => '#F9A8D4', + 'blob2' => '#F472B6', + 'accent_color' => '#be185d', + 'badge_bg' => 'rgba(244,114,182,0.12)', + 'wave' => 'white', + 'footer_border' => '#FFBCD9', + 'thumb' => 'from-[#FFF5F9] to-[#FFECF4]', + 'thumb_accent' => '#F9A8D4', + ], + 3 => [ + 'id' => 3, + 'slug' => 'appreciation', + 'name' => 'Appreciation', + 'label' => 'APPRECIATION', + 'icon' => '⭐', + 'deco_bg' => 'linear-gradient(135deg,#DBEAFE,#BFDBFE)', + 'card_bg' => 'linear-gradient(145deg,#F0F8FF,#EAF3FF)', + 'border_color' => '#BFDBFE', + 'blob1' => '#93C5FD', + 'blob2' => '#60A5FA', + 'accent_color' => '#1d4ed8', + 'badge_bg' => 'rgba(96,165,250,0.12)', + 'wave' => 'white', + 'footer_border' => '#BFDBFE', + 'thumb' => 'from-[#EFF8FF] to-[#DBEAFE]', + 'thumb_accent' => '#93C5FD', + ], + 4 => [ + 'id' => 4, + 'slug' => 'celebration', + 'name' => 'Celebration', + 'label' => 'CELEBRATION', + 'icon' => '🎉', + 'deco_bg' => 'linear-gradient(135deg,#EDE9FE,#DDD6FE)', + 'card_bg' => 'linear-gradient(145deg,#F8F5FF,#F3EFFF)', + 'border_color' => '#DDD6FE', + 'blob1' => '#C4B5FD', + 'blob2' => '#A78BFA', + 'accent_color' => '#6d28d9', + 'badge_bg' => 'rgba(167,139,250,0.12)', + 'wave' => 'white', + 'footer_border' => '#DDD6FE', + 'thumb' => 'from-[#F5F0FF] to-[#EDE9FE]', + 'thumb_accent' => '#C4B5FD', + ] +]; diff --git a/config/constants.php b/config/constants.php index d7cfa5c..989e45f 100644 --- a/config/constants.php +++ b/config/constants.php @@ -13,6 +13,11 @@ return [ 'FIRST_LOGIN_FALSE' => 0, 'FIRST_LOGIN_TRUE' => 1, + 'TEMPLATE_THU_CAM_ON' => 1, + 'TEMPLATE_SAKURA' => 2, + 'TEMPLATE_APPRECIATION' => 3, + 'TEMPLATE_CELEBRATION' => 4, + 'DEPARTMENTS' => [ 'BIZ-IID - Internet Infra Business Division / BIZ-IID - Sales Enterprise Team (HCM)', 'BIZ-ITOVN - Vietnam Business Division / BIZ-ITOVN - Ho Chi Minh', diff --git a/database/migrations/2026_07_20_095829_add_template_id_to_administration_table.php b/database/migrations/2026_07_20_095829_add_template_id_to_administration_table.php new file mode 100644 index 0000000..6ea50cf --- /dev/null +++ b/database/migrations/2026_07_20_095829_add_template_id_to_administration_table.php @@ -0,0 +1,28 @@ +integer('template_id')->nullable()->default(1)->after('date'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('administration', function (Blueprint $table) { + $table->dropColumn('template_id'); + }); + } +}; diff --git a/resources/views/components/sidebar-item.blade.php b/resources/views/components/sidebar-item.blade.php index 1eb8831..6af8754 100644 --- a/resources/views/components/sidebar-item.blade.php +++ b/resources/views/components/sidebar-item.blade.php @@ -2,7 +2,7 @@ @php $classes = $active - ? 'flex items-center gap-4 px-4 py-3 rounded-xl bg-[#eff4ff] text-[#3462f7] font-semibold transition-all duration-200' + ? 'flex items-center gap-4 px-4 py-3 rounded-xl bg-[#eff4ff] text-[#3462f7] font-medium transition-all duration-200' : 'flex items-center gap-4 px-4 py-3 rounded-xl text-gray-500 hover:bg-gray-50 hover:text-gray-900 font-medium transition-all duration-200'; @endphp diff --git a/resources/views/components/sidebar.blade.php b/resources/views/components/sidebar.blade.php index 86e8cb5..5210913 100644 --- a/resources/views/components/sidebar.blade.php +++ b/resources/views/components/sidebar.blade.php @@ -29,9 +29,11 @@ Thanks đã gửi - - Bảng xếp hạng - + @if(Auth::check() && Auth::user()->role == config('constants.ROLE_ADMIN')) + + Bảng xếp hạng + + @endif @if(Auth::check() && Auth::user()->role == config('constants.ROLE_ADMIN')) diff --git a/resources/views/components/stat-card.blade.php b/resources/views/components/stat-card.blade.php index be17a11..4915187 100644 --- a/resources/views/components/stat-card.blade.php +++ b/resources/views/components/stat-card.blade.php @@ -13,7 +13,10 @@
{{ $title }}
- {{ $value }} + @php + $isShort = is_numeric(str_replace('#', '', $value)) || strlen($value) <= 4; + @endphp + {{ $value }}
@if($growth) diff --git a/resources/views/components/transaction-history.blade.php b/resources/views/components/transaction-history.blade.php index 7588b37..dc7ad57 100644 --- a/resources/views/components/transaction-history.blade.php +++ b/resources/views/components/transaction-history.blade.php @@ -67,12 +67,20 @@ @endif @endif - + @if($isReceiver) +{{ $admin_record->received }} @else -{{ $admin_record->sent }} @endif + @php + $themes = config('card_themes'); + $themeId = $admin_record->template_id ?? 1; + $theme = $themes[$themeId] ?? $themes[1]; + @endphp + + {{ $theme['icon'] }} + @empty diff --git a/resources/views/user/dashboard.blade.php b/resources/views/user/dashboard.blade.php index b532ba1..11744fd 100644 --- a/resources/views/user/dashboard.blade.php +++ b/resources/views/user/dashboard.blade.php @@ -38,15 +38,27 @@ - - - - - + @if(Auth::check() && Auth::user()->role == config('constants.ROLE_ADMIN')) + + + + + + @else + + + + + + @endif
@@ -96,39 +108,86 @@
-
+

Bảng xếp hạng

- Xem tất cả + @if(Auth::check() && Auth::user()->role == config('constants.ROLE_ADMIN')) + Xem tất cả + @endif
-
- - -
+ @if(Auth::check() && Auth::user()->role == config('constants.ROLE_ADMIN')) +
+ + +
-
- -
- @include('user.partials.ranking_list', ['rankers' => array_slice($receivedRankers, 0, 4), 'currentUserRankItem' => $receivedCurrentUserRankItem]) +
+ +
+ @include('user.partials.ranking_list', ['rankers' => array_slice($receivedRankers, 0, 4), 'currentUserRankItem' => $receivedCurrentUserRankItem]) +
+
- -
+ @endif
@@ -142,6 +201,8 @@ const receivedContent = document.getElementById('ranking-received-content'); const sentContent = document.getElementById('ranking-sent-content'); + if (!receivedTab || !sentTab || !receivedContent || !sentContent) return; + const activeClass = 'flex items-center justify-center gap-2 w-[120px] py-2 rounded-[10px] transition-all bg-white shadow-[0_2px_4px_rgba(0,0,0,0.04)] text-[#3462f7] font-bold text-[14px]'; const inactiveClass = 'flex items-center justify-center gap-2 w-[120px] py-2 rounded-[10px] transition-all text-[#64748b] hover:text-gray-800 font-bold text-[14px]'; diff --git a/resources/views/user/partials/received_cards_feed.blade.php b/resources/views/user/partials/received_cards_feed.blade.php index b77135f..3c66a41 100644 --- a/resources/views/user/partials/received_cards_feed.blade.php +++ b/resources/views/user/partials/received_cards_feed.blade.php @@ -1,20 +1,31 @@ +@php +$themes = config('card_themes'); +@endphp + @foreach ($cards as $c) -
+ @php + $themeId = $c->template_id ?? 1; + $theme = $themes[$themeId] ?? $themes[1]; + @endphp +
- 💜 Từ + {{ $theme['icon'] }} Từ - - {{ $c->received }} Thẻ + + {{ $c->received }} Thẻ ({{ $theme['name'] }})
@if($c->senderUser) - + @else -
+
{{ strtoupper(substr($c->sender ?? 'U', 0, 1)) }}
@endif @@ -33,9 +44,10 @@
-
+
Ngày nhận: - {{ \Carbon\Carbon::parse($c->date)->format('d/m/Y') }} + {{ \Carbon\Carbon::parse($c->date)->format('d/m/Y') }}
@endforeach diff --git a/resources/views/user/partials/sent_cards_feed.blade.php b/resources/views/user/partials/sent_cards_feed.blade.php index e42ce54..babb0e5 100644 --- a/resources/views/user/partials/sent_cards_feed.blade.php +++ b/resources/views/user/partials/sent_cards_feed.blade.php @@ -1,20 +1,31 @@ +@php +$themes = config('card_themes'); +@endphp + @foreach ($cards as $c) -
+ @php + $themeId = $c->template_id ?? 1; + $theme = $themes[$themeId] ?? $themes[1]; + @endphp +
- 💌 Gửi tới + {{ $theme['icon'] }} Gửi tới - - {{ $c->sent }} Thẻ + + {{ $c->sent }} Thẻ ({{ $theme['name'] }})
@if($c->receiverUser) - + @else -
+
{{ strtoupper(substr($c->receiver ?? 'U', 0, 1)) }}
@endif @@ -33,9 +44,10 @@
-
+
Ngày gửi: - {{ \Carbon\Carbon::parse($c->date)->format('d/m/Y') }} + {{ \Carbon\Carbon::parse($c->date)->format('d/m/Y') }}
@endforeach diff --git a/resources/views/user/ranking.blade.php b/resources/views/user/ranking.blade.php index c28173b..5622c8b 100644 --- a/resources/views/user/ranking.blade.php +++ b/resources/views/user/ranking.blade.php @@ -10,7 +10,6 @@

🏆 Bảng xếp hạng

Tôn vinh những cá nhân lan tỏa văn hóa cảm ơn và ghi nhận trong tổ chức.

- trophy
@@ -147,8 +146,13 @@ {{-- Users in Group --}}
- @foreach($group as $user) -
+ @php + $total = $group->count(); + $desktopLimit = $total > 12 ? 11 : 12; + $mobileLimit = $total > 4 ? 3 : 4; + @endphp + @foreach($group as $index => $user) +
@@ -160,6 +164,30 @@
@endforeach + + @if($total > 4) + {{-- Mobile Xem Them Button --}} + + @endif + + @if($total > 12) + {{-- Desktop Xem Them Button --}} + + @endif + +
@endforeach @@ -274,8 +302,13 @@ {{-- Users in Group --}}
- @foreach($group as $user) -
+ @php + $total = $group->count(); + $desktopLimit = $total > 12 ? 11 : 12; + $mobileLimit = $total > 4 ? 3 : 4; + @endphp + @foreach($group as $index => $user) +
@@ -287,6 +320,30 @@
@endforeach + + @if($total > 4) + {{-- Mobile Xem Them Button --}} + + @endif + + @if($total > 12) + {{-- Desktop Xem Them Button --}} + + @endif + +
@endforeach @@ -307,6 +364,12 @@ .animate-fade-in { animation: fadeIn 0.4s ease-out forwards; } + +/* Custom classes for hiding excess items */ +.hide-all { display: none !important; } +@media (max-width: 767px) { + .hide-mobile { display: none !important; } +} @endsection @@ -344,5 +407,18 @@ contentReceived.classList.add('hidden'); } } + + function expandGroup(btn) { + const container = btn.closest('.grid'); + const hiddenItems = container.querySelectorAll('.hide-all, .hide-mobile'); + + hiddenItems.forEach(el => { + el.classList.remove('hide-all', 'hide-mobile'); + }); + + // Hide all xem-them buttons in this container + const btns = container.querySelectorAll('.xem-them-btn-mobile, .xem-them-btn-desktop'); + btns.forEach(b => b.style.display = 'none'); + } @endpush diff --git a/resources/views/user/send.blade.php b/resources/views/user/send.blade.php index ff85c80..7bed388 100644 --- a/resources/views/user/send.blade.php +++ b/resources/views/user/send.blade.php @@ -3,12 +3,7 @@ @section('content') @php -$tpls = [ - 1=>['icon'=>'💌','name'=>'Thư cảm ơn', 'thumb'=>'from-[#FFF9EC] to-[#FFF5DD]','thumbAccent'=>'#FFD066'], - 2=>['icon'=>'🌸','name'=>'Sakura', 'thumb'=>'from-[#FFF5F9] to-[#FFECF4]','thumbAccent'=>'#F9A8D4'], - 3=>['icon'=>'⭐','name'=>'Appreciation','thumb'=>'from-[#EFF8FF] to-[#DBEAFE]','thumbAccent'=>'#93C5FD'], - 4=>['icon'=>'🎉','name'=>'Celebration', 'thumb'=>'from-[#F5F0FF] to-[#EDE9FE]','thumbAccent'=>'#C4B5FD'], -]; +$tpls = config('card_themes'); @endphp
@@ -184,32 +179,25 @@ $tpls = [ document.addEventListener('DOMContentLoaded', function() { // ── Theme data ─────────────────────────────────────────────────── - const T = { - 1:{icon:'💌',name:'Thư cảm ơn', label:'THANK CARD', - deco:'linear-gradient(135deg,#FFF5CC,#FFE8A0)', - card:'linear-gradient(145deg,#FFF9EC,#FFFDF7)', - border:'#FFE4A0', blob1:'#FFD066', blob2:'#FFAD00', - accent:'#B8860B', badgeBg:'rgba(255,176,0,0.15)', wave:'white', - footerBorder:'#FFE4A0'}, - 2:{icon:'🌸',name:'Sakura', label:'SAKURA CARD', - deco:'linear-gradient(135deg,#FFE8F4,#FFD6EC)', - card:'linear-gradient(145deg,#FFF8FB,#FFF3F8)', - border:'#FFBCD9', blob1:'#F9A8D4', blob2:'#F472B6', - accent:'#be185d', badgeBg:'rgba(244,114,182,0.12)', wave:'white', - footerBorder:'#FFBCD9'}, - 3:{icon:'⭐',name:'Appreciation',label:'APPRECIATION', - deco:'linear-gradient(135deg,#DBEAFE,#BFDBFE)', - card:'linear-gradient(145deg,#F0F8FF,#EAF3FF)', - border:'#BFDBFE', blob1:'#93C5FD', blob2:'#60A5FA', - accent:'#1d4ed8', badgeBg:'rgba(96,165,250,0.12)', wave:'white', - footerBorder:'#BFDBFE'}, - 4:{icon:'🎉',name:'Celebration', label:'CELEBRATION', - deco:'linear-gradient(135deg,#EDE9FE,#DDD6FE)', - card:'linear-gradient(145deg,#F8F5FF,#F3EFFF)', - border:'#DDD6FE', blob1:'#C4B5FD', blob2:'#A78BFA', - accent:'#6d28d9', badgeBg:'rgba(167,139,250,0.12)', wave:'white', - footerBorder:'#DDD6FE'}, - }; + const cardThemesData = @json(config('card_themes')); + const T = {}; + Object.keys(cardThemesData).forEach(id => { + const item = cardThemesData[id]; + T[id] = { + icon: item.icon, + name: item.name, + label: item.label, + deco: item.deco_bg, + card: item.card_bg, + border: item.border_color, + blob1: item.blob1, + blob2: item.blob2, + accent: item.accent_color, + badgeBg: item.badge_bg, + wave: item.wave, + footerBorder: item.footer_border + }; + }); // ── Theme slugs ────────────────────────────────────────────────── const templateSlugs = { @@ -541,7 +529,11 @@ document.addEventListener('DOMContentLoaded', function() { $.ajax({ url:'{{ route("user.store_send") }}', method:'POST', contentType:'application/json', headers:{'X-CSRF-TOKEN':$('meta[name="csrf-token"]').attr('content')}, - data:JSON.stringify({receiver:msnv,amount:amount}), + data:JSON.stringify({ + receiver: msnv, + amount: amount, + template_id: parseInt(document.getElementById('template_id').value, 10) + }), success:function(res){ if(res.success){ setButtonLoading(false);