diff --git a/src/FrontOffice.Main/FrontOffice.Main.csproj b/src/FrontOffice.Main/FrontOffice.Main.csproj index 8134865..f8dcfe2 100644 --- a/src/FrontOffice.Main/FrontOffice.Main.csproj +++ b/src/FrontOffice.Main/FrontOffice.Main.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/FrontOffice.Main/Utilities/NetworkMembershipDtos.cs b/src/FrontOffice.Main/Utilities/NetworkMembershipDtos.cs index 8023a67..3b81991 100644 --- a/src/FrontOffice.Main/Utilities/NetworkMembershipDtos.cs +++ b/src/FrontOffice.Main/Utilities/NetworkMembershipDtos.cs @@ -17,6 +17,10 @@ public class NetworkNodeDto public DateTime? JoinedAt { get; set; } public bool IsClubActive { get; set; } public string? ActivationWeekNumber { get; set; } + /// + /// کد معرف کاربر + /// + public string? ReferralCode { get; set; } } /// @@ -35,6 +39,10 @@ public class FlatNetworkNodeDto public bool IsClubActive { get; set; } public string? ActivationWeekNumber { get; set; } public DateTime? JoinedAt { get; set; } + /// + /// کد معرف کاربر - فقط برای کاربران فعال در باشگاه نمایش داده شود + /// + public string? ReferralCode { get; set; } } /// @@ -72,7 +80,8 @@ public class NetworkTreeDto IsActive = node.IsActive, IsClubActive = node.IsClubActive, ActivationWeekNumber = node.ActivationWeekNumber, - JoinedAt = node.JoinedAt + JoinedAt = node.JoinedAt, + ReferralCode = node.ReferralCode }; result.Add(flatNode); diff --git a/src/FrontOffice.Main/wwwroot/css/org-chart.css b/src/FrontOffice.Main/wwwroot/css/org-chart.css index 09a6786..845cde4 100644 --- a/src/FrontOffice.Main/wwwroot/css/org-chart.css +++ b/src/FrontOffice.Main/wwwroot/css/org-chart.css @@ -414,3 +414,69 @@ overflow: visible; } } + +/* Referral Code Style */ +.node-referral { + display: flex; + align-items: center; + gap: 3px; + margin-top: 2px; + padding: 2px 4px; + background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%); + border-radius: 4px; + cursor: pointer; + transition: all 0.2s ease; + max-width: 100%; +} + +.node-referral:hover { + background: linear-gradient(135deg, #ffe0b2 0%, #ffcc80 100%); + transform: scale(1.02); +} + +.node-referral .referral-icon { + font-size: 8px; +} + +.node-referral .referral-code { + font-size: 8px; + font-weight: 600; + color: #e65100; + font-family: monospace; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Club Active Badge */ +.org-node-card.club-active { + border-right: 3px solid #ff9800; +} + +.org-node-card.club-active .node-avatar-sm { + background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%); +} + +/* Toast Notification */ +.org-chart-toast { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%) translateY(100px); + background: #323232; + color: white; + padding: 12px 24px; + border-radius: 8px; + font-size: 14px; + font-family: 'Vazirmatn', sans-serif; + direction: rtl; + z-index: 10000; + opacity: 0; + transition: all 0.3s ease; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + +.org-chart-toast.show { + transform: translateX(-50%) translateY(0); + opacity: 1; +} diff --git a/src/FrontOffice.Main/wwwroot/js/org-chart.js b/src/FrontOffice.Main/wwwroot/js/org-chart.js index 7399c5d..284ae76 100644 --- a/src/FrontOffice.Main/wwwroot/js/org-chart.js +++ b/src/FrontOffice.Main/wwwroot/js/org-chart.js @@ -59,17 +59,27 @@ window.OrgChart = { const positionClass = data.position === 'Left' ? 'position-left' : data.position === 'Right' ? 'position-right' : 'position-root'; const activeClass = data.isActive ? 'active' : 'inactive'; + const clubActiveClass = data.isClubActive ? 'club-active' : ''; // Avatar - first letter of name const firstChar = data.fullName ? data.fullName.charAt(0) : '?'; + + // نمایش کد معرف فقط برای کاربران فعال در باشگاه + const referralCodeHtml = data.isClubActive && data.referralCode + ? `
+ 📋 + ${data.referralCode} +
` + : ''; return ` -
+
${firstChar}
${data.fullName || 'بدون نام'}
L${data.level || 0}${!isRoot ? ' • ' + (data.position === 'Left' ? 'چپ' : 'راست') : ''}
+ ${referralCodeHtml}
@@ -187,6 +197,63 @@ window.OrgChart = { } }, + /** + * Copy referral code to clipboard + * @param {string} code - The referral code to copy + */ + copyReferralCode: function(code) { + if (navigator.clipboard) { + navigator.clipboard.writeText(code).then(() => { + // Show toast notification + this.showToast('کد معرف کپی شد: ' + code); + }).catch(err => { + console.error('Failed to copy:', err); + this.fallbackCopy(code); + }); + } else { + this.fallbackCopy(code); + } + }, + + /** + * Fallback copy method for older browsers + */ + fallbackCopy: function(text) { + const textArea = document.createElement('textarea'); + textArea.value = text; + textArea.style.position = 'fixed'; + textArea.style.left = '-999999px'; + document.body.appendChild(textArea); + textArea.select(); + try { + document.execCommand('copy'); + this.showToast('کد معرف کپی شد: ' + text); + } catch (err) { + console.error('Fallback copy failed:', err); + } + document.body.removeChild(textArea); + }, + + /** + * Show toast notification + */ + showToast: function(message) { + // Remove existing toast + const existingToast = document.querySelector('.org-chart-toast'); + if (existingToast) existingToast.remove(); + + const toast = document.createElement('div'); + toast.className = 'org-chart-toast'; + toast.textContent = message; + document.body.appendChild(toast); + + setTimeout(() => toast.classList.add('show'), 10); + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => toast.remove(), 300); + }, 2000); + }, + /** * Dispose the chart */