...

آموزش ساخت پنل کاربری اختصاصی ووکامرس

آموزش ساخت پنل کاربری اختصاصی ووکامرس

منبع مقاله: مشاهده مقاله اصلی

معرفی قابلیت

در این آموزش نحوه ساخت یک پنل کاربری اختصاصی برای ووکامرس بررسی می‌شود. هدف این قابلیت، جایگزین کردن پنل پیش‌فرض ووکامرس با یک داشبورد حرفه‌ای، مینیمال و کاملاً سفارشی است تا کاربران بتوانند بخش‌های مختلف حساب کاربری خود را در یک محیط جذاب‌تر مدیریت کنند.

با استفاده از این روش می‌توان بخش‌هایی مانند اطلاعات حساب، سفارش‌ها و امکانات اختصاصی را در قالب یک پنل کاربری جدید نمایش داد.

نحوه عملکرد

پنل پیش‌فرض ووکامرس امکانات پایه‌ای مانند مشاهده سفارش‌ها، مدیریت آدرس‌ها و ویرایش اطلاعات حساب را ارائه می‌دهد، اما از نظر طراحی محدود است.

در این روش یک ساختار اختصاصی برای پنل کاربری ایجاد می‌شود و اطلاعات کاربر از ووکامرس دریافت شده و در قالب یک داشبورد جدید نمایش داده می‌شود.

نحوه اجرا

برای ایجاد این پنل ابتدا کدهای مربوط به ساخت پنل اختصاصی در سایت قرار داده می‌شوند. این کدها یک شورت‌کد جدید ایجاد می‌کنند که امکان نمایش پنل کاربری را در هر بخش دلخواه وردپرس فراهم می‌کند.

مراحل کلی اجرا:

  • اضافه کردن کدهای ساخت پنل کاربری
  • فعال شدن شورت‌کد اختصاصی پنل
  • ایجاد برگه جدید برای نمایش پنل
  • قرار دادن شورت‌کد در برگه موردنظر

نحوه استفاده با شورت‌کد

پس از فعال شدن کد، وارد بخش برگه‌ها > افزودن برگه تازه شوید و یک برگه با نام دلخواه مانند «پروفایل من» یا «پنل کاربری» ایجاد کنید.

در ویرایشگر وردپرس، شورت‌کد زیر را قرار دهید:

[modern_user_panel]

سپس برگه را منتشر کنید.

حالا زمانی که کاربر وارد سایت شده و این برگه را مشاهده کند، پنل کاربری اختصاصی، مینیمال و حرفه‌ای نمایش داده خواهد شد.

امکانات قابل نمایش در پنل

با توجه به ساختار طراحی شده، می‌توان بخش‌های مختلفی مانند:

  • اطلاعات کاربر
  • سفارش‌های ووکامرس
  • بخش‌های اختصاصی فروشگاه
  • امکانات شخصی‌سازی شده

را در پنل قرار داد.

مزایا

  • ایجاد پنل کاربری متفاوت از ظاهر پیش‌فرض ووکامرس
  • بهبود تجربه کاربری مشتریان
  • امکان توسعه و اضافه کردن بخش‌های جدید
  • عدم نیاز به افزونه‌های سنگین
  • کنترل کامل روی ظاهر و امکانات پنل

این روش یک راهکار مناسب برای ساخت پنل‌های کاربری اختصاصی در فروشگاه‌های ووکامرسی است که نیاز به طراحی حرفه‌ای‌تر و امکانات سفارشی دارند.

/**  * Custom Material Design User Dashboard (Pro Stats) - Enhanced Edition  * Shortcode: [modern_user_panel]  * افزوده‌ها: ریسپانسیو کامل، دو نمودار (روند خرید و وضعیت سفارشات)، انیمیشن‌های ورود/شمارش/هاور  */  add_shortcode('modern_user_panel', 'render_modern_user_dashboard_pro');  function render_modern_user_dashboard_pro() {      // 1. بررسی وضعیت ورود کاربر     if ( ! is_user_logged_in() ) {         return '<div class="md-panel-notice" style="text-align:center; padding: 40px; background: #fff; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); font-family: inherit;">برای مشاهده پنل کاربری ابتدا وارد سایت شوید.</div>';     }      $current_user = wp_get_current_user();      // دریافت اطلاعات، سفارشات و دانلودها (در صورت فعال بودن ووکامرس)     $customer_orders    = [];     $customer_downloads = [];     $total_spent        = 0;     $total_order_count  = 0;     $monthly_spending   = [];   // برای نمودار روند خرید ۶ ماه اخیر     $status_counts      = [];   // برای نمودار وضعیت سفارشات      if ( class_exists( 'WooCommerce' ) ) {          // سفارشات برای جدول         $customer_orders = wc_get_orders( array(             'customer' => $current_user->ID,             'limit'    => 10,         ) );          // دانلودها         $customer_downloads = wc_get_customer_available_downloads( $current_user->ID );          // آمار کلی         $total_spent       = wc_get_customer_total_spent( $current_user->ID );         $total_order_count = wc_get_customer_order_count( $current_user->ID );          // ----- داده نمودار ۱: روند خرید ۶ ماه اخیر -----         for ( $i = 5; $i >= 0; $i-- ) {             $month_ts    = strtotime( "-$i months", strtotime( date( 'Y-m-01' ) ) );             $month_start = date( 'Y-m-01 00:00:00', $month_ts );             $month_end   = date( 'Y-m-t 23:59:59', $month_ts );             $label       = date_i18n( 'M', $month_ts );              $month_orders = wc_get_orders( array(                 'customer'     => $current_user->ID,                 'status'       => array( 'wc-completed', 'wc-processing' ),                 'date_created' => $month_start . '...' . $month_end,                 'limit'        => -1,             ) );              $sum = 0;             foreach ( $month_orders as $mo ) {                 $sum += (float) $mo->get_total();             }              $monthly_spending[] = array(                 'label' => $label,                 'value' => round( $sum, 2 ),             );         }          // ----- داده نمودار ۲: وضعیت سفارشات -----         $all_orders = wc_get_orders( array(             'customer' => $current_user->ID,             'limit'    => -1,         ) );         foreach ( $all_orders as $o ) {             $st = wc_get_order_status_name( $o->get_status() );             $status_counts[ $st ] = isset( $status_counts[ $st ] ) ? $status_counts[ $st ] + 1 : 1;         }     }      // محاسبه روزهای عضویت     $registered_date  = strtotime( $current_user->user_registered );     $days_membership  = max( 1, floor( ( time() - $registered_date ) / ( 60 * 60 * 24 ) ) );      // آماده‌سازی برای خروجی جاوااسکریپت     $chart_labels = wp_json_encode( wp_list_pluck( $monthly_spending, 'label' ) );     $chart_values = wp_json_encode( wp_list_pluck( $monthly_spending, 'value' ) );     $status_labels = wp_json_encode( array_keys( $status_counts ) );     $status_values = wp_json_encode( array_values( $status_counts ) );      ob_start();     ?>      <!-- Chart.js (فقط اگر قبلاً در سایت لود نشده) -->     <?php if ( ! wp_script_is( 'chart-js-cdn', 'enqueued' ) && class_exists( 'WooCommerce' ) ) : ?>         <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>     <?php endif; ?>      <!-- فونت وزیرمتن برای ظاهر بهتر متون فارسی (اختیاری) -->     <link rel="preconnect" href="https://fonts.googleapis.com">     <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;500;600;700;800&display=swap" rel="stylesheet">      <!-- 2. استایل‌های Material Design -->     <style>         .md-dashboard-wrapper, .md-dashboard-wrapper * { box-sizing: border-box; }          .md-dashboard-wrapper {             --md-primary: #6200ea;             --md-primary-light: #b388ff;             --md-primary-dark: #4b00b3;             --md-surface: #ffffff;             --md-bg: #f7f6fb;             --md-text: #2b2b33;             --md-text-muted: #78798a;             --md-border: #ececf3;             --md-shadow: 0 4px 20px rgba(20, 10, 60, 0.06);             --md-shadow-hover: 0 14px 34px rgba(20, 10, 60, 0.12);             --md-radius: 18px;             --md-transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);              display: flex;             flex-wrap: wrap;             gap: 24px;             font-family: 'Vazirmatn', inherit;             background-color: transparent;             direction: rtl;             color: var(--md-text);             animation: mdPanelIn 0.5s ease both;         }          @keyframes mdPanelIn {             from { opacity: 0; transform: translateY(14px); }             to   { opacity: 1; transform: translateY(0); }         }          /* سایدبار */         .md-sidebar {             flex: 1 1 260px;             max-width: 280px;             background: var(--md-surface);             border-radius: var(--md-radius);             box-shadow: var(--md-shadow);             overflow: hidden;             align-self: flex-start;             position: sticky;             top: 16px;         }          .md-user-info {             padding: 28px 24px;             text-align: center;             border-bottom: 1px solid var(--md-border);             background: linear-gradient(160deg, rgba(98,0,234,0.06), rgba(179,136,255,0.02));         }          .md-avatar {             width: 84px;             height: 84px;             border-radius: 50%;             margin-bottom: 14px;             border: 3px solid var(--md-primary-light);             padding: 3px;             transition: var(--md-transition);         }         .md-avatar:hover { transform: scale(1.06) rotate(3deg); }          .md-user-name { font-size: 1.1rem; font-weight: 700; margin: 0 0 4px; color: var(--md-text); }         .md-user-email { font-size: 0.8rem; color: var(--md-text-muted); }          .md-nav-list { list-style: none; padding: 10px; margin: 0; }          .md-nav-item {             padding: 14px 18px;             margin-bottom: 4px;             border-radius: 12px;             cursor: pointer;             color: var(--md-text-muted);             transition: var(--md-transition);             font-weight: 500;             font-size: 0.95rem;             display: flex;             align-items: center;             gap: 10px;         }          .md-nav-item svg { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.75; }          .md-nav-item:hover { background-color: rgba(98, 0, 234, 0.06); color: var(--md-primary); transform: translateX(-2px); }         .md-nav-item.active {             background: linear-gradient(90deg, rgba(98,0,234,0.12), rgba(98,0,234,0.04));             color: var(--md-primary);             font-weight: 700;         }         .md-nav-item.active svg { opacity: 1; }          .md-nav-item.logout { color: #d32f2f; margin-top: 8px; border-top: 1px solid var(--md-border); border-radius: 0; padding-top: 18px; }         .md-nav-item.logout:hover { background: rgba(211, 47, 47, 0.06); }          /* محتوا */         .md-content-area {             flex: 3 1 500px;             background: var(--md-surface);             border-radius: var(--md-radius);             box-shadow: var(--md-shadow);             padding: 32px; //             min-height: 420px;         }          .md-tab-content { display: none; }         .md-tab-content.active { display: block; animation: mdFadeIn 0.45s cubic-bezier(0.4,0,0.2,1) both; }          @keyframes mdFadeIn {             from { opacity: 0; transform: translateY(14px); }             to   { opacity: 1; transform: translateY(0); }         }          .md-title {             font-size: 1.4rem; font-weight: 700; color: var(--md-text); margin-top: 0; margin-bottom: 24px;             padding-bottom: 14px; border-bottom: 1px solid var(--md-border);             display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;         }          /* کارت‌های آماری */         .md-stats-grid {             display: grid;             grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));             gap: 18px;             margin-top: 26px;         }          .md-stat-card {             background: var(--md-surface);             border: 1px solid var(--md-border);             border-radius: var(--md-radius);             padding: 20px;             display: flex;             align-items: center;             gap: 16px;             transition: var(--md-transition);             opacity: 0;             animation: mdCardIn 0.5s ease forwards;         }         .md-stat-card:nth-child(1) { animation-delay: 0.05s; }         .md-stat-card:nth-child(2) { animation-delay: 0.15s; }         .md-stat-card:nth-child(3) { animation-delay: 0.25s; }         .md-stat-card:nth-child(4) { animation-delay: 0.35s; }          @keyframes mdCardIn {             from { opacity: 0; transform: translateY(16px) scale(0.97); }             to   { opacity: 1; transform: translateY(0) scale(1); }         }          .md-stat-card:hover {             transform: translateY(-6px);             box-shadow: var(--md-shadow-hover);             border-color: transparent;         }          .md-stat-icon {             width: 56px;             height: 56px;             border-radius: 14px;             display: flex;             align-items: center;             justify-content: center;             flex-shrink: 0;             transition: var(--md-transition);         }         .md-stat-card:hover .md-stat-icon { transform: rotate(-8deg) scale(1.08); }          .md-stat-icon svg { width: 28px; height: 28px; }          .icon-blue   { background: #e3f2fd; color: #1565c0; }         .icon-green  { background: #e8f5e9; color: #2e7d32; }         .icon-purple { background: #f3e5f5; color: #6a1b9a; }         .icon-orange { background: #fff3e0; color: #ef6c00; }          .md-stat-info { display: flex; flex-direction: column; min-width: 0; }         .md-stat-title { font-size: 0.82rem; color: var(--md-text-muted); margin-bottom: 4px; font-weight: 500; }         .md-stat-value { font-size: 1.3rem; font-weight: 800; color: var(--md-text); }          /* بخش نمودارها */         .md-charts-grid {             display: grid;             grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));             gap: 20px;             margin-top: 28px;         }          .md-chart-card {             background: var(--md-surface);             border: 1px solid var(--md-border);             border-radius: var(--md-radius);             padding: 20px;             transition: var(--md-transition);             opacity: 0;             animation: mdCardIn 0.6s ease 0.4s forwards;         }         .md-chart-card:hover { box-shadow: var(--md-shadow-hover); transform: translateY(-3px); }          .md-chart-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }         .md-chart-header h4 { margin: 0; font-size: 1rem; font-weight: 700; color: var(--md-text); }         .md-chart-wrap { position: relative; height: 240px; }          .md-empty-note { text-align: center; padding: 40px 0; color: var(--md-text-muted); font-size: 0.9rem; }          /* دکمه‌ها و فرم‌ها */         .md-btn {             background: var(--md-primary); color: #fff; border: none;             padding: 11px 22px; border-radius: 10px; cursor: pointer;             transition: var(--md-transition); font-family: inherit; font-size: 0.9rem; font-weight: 600;             text-decoration: none; display: inline-block;         }         .md-btn:hover { background: var(--md-primary-dark); box-shadow: 0 6px 16px rgba(98, 0, 234, 0.32); transform: translateY(-2px); }         .md-btn:active { transform: translateY(0); }          .md-btn-outline {             background: transparent; color: var(--md-primary);             border: 1px solid var(--md-primary); padding: 8px 16px;             border-radius: 10px; cursor: pointer; transition: var(--md-transition); text-decoration: none;             font-size: 0.85rem; font-weight: 600;         }         .md-btn-outline:hover { background: var(--md-primary); color: #fff; }          .md-form-group { margin-bottom: 20px; }         .md-form-group label { display: block; margin-bottom: 8px; color: var(--md-text-muted); font-size: 0.9rem; font-weight: 500; }         .md-input { width: 100%; padding: 12px 16px; border: 1px solid var(--md-border); border-radius: 10px; font-family: inherit; transition: var(--md-transition); }         .md-input:focus { outline: none; border-color: var(--md-primary); box-shadow: 0 0 0 4px rgba(98, 0, 234, 0.1); }          /* جداول و وضعیت‌ها */         .md-table { width: 100%; border-collapse: collapse; }         .md-table th, .md-table td { padding: 15px 12px; text-align: right; border-bottom: 1px solid var(--md-border); font-size: 0.92rem; }         .md-table th { color: var(--md-text-muted); font-weight: 600; }         .md-table tbody tr { transition: var(--md-transition); }         .md-table tbody tr:hover { background: rgba(98, 0, 234, 0.03); }          .md-badge { padding: 5px 13px; border-radius: 20px; font-size: 0.78rem; font-weight: 700; white-space: nowrap; }         .badge-success { background: #e8f5e9; color: #2e7d32; }         .badge-info    { background: #e3f2fd; color: #1565c0; }         .badge-warning { background: #fff8e1; color: #f57f17; }         .badge-danger  { background: #ffebee; color: #c62828; }          /* ناوبری موبایل: تب‌های افقی قابل اسکرول */         .md-mobile-tabs { display: none; }          @media (max-width: 900px) {             .md-dashboard-wrapper { flex-direction: column; gap: 16px; }             .md-sidebar { position: static; max-width: 100%; }             .md-user-info { padding: 20px; }             .md-nav-list { display: flex; overflow-x: auto; gap: 6px; padding: 8px; scrollbar-width: thin; }             .md-nav-item { white-space: nowrap; flex-shrink: 0; }             .md-nav-item.logout { border-top: none; padding-top: 14px; }             .md-content-area { padding: 22px; }             .md-stats-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }             .md-charts-grid { grid-template-columns: 1fr; }         }          @media (max-width: 480px) {             .md-stats-grid { grid-template-columns: 1fr 1fr; }             .md-stat-card { padding: 14px; gap: 10px; }             .md-stat-icon { width: 44px; height: 44px; border-radius: 12px; }             .md-stat-icon svg { width: 22px; height: 22px; }             .md-stat-value { font-size: 1.05rem; }             .md-title { font-size: 1.2rem; }             .md-content-area { padding: 16px; }             .md-chart-wrap { height: 200px; }         }     </style>      <!-- 3. ساختار HTML -->     <div class="md-dashboard-wrapper">          <!-- سایدبار -->         <aside class="md-sidebar">             <div class="md-user-info">                 <?php echo get_avatar( $current_user->ID, 84, '', '', array( 'class' => 'md-avatar' ) ); ?>                 <h3 class="md-user-name"><?php echo esc_html( $current_user->display_name ); ?></h3>                 <span class="md-user-email"><?php echo esc_html( $current_user->user_email ); ?></span>             </div>             <ul class="md-nav-list">                 <li class="md-nav-item active" data-target="dashboard">                     <svg fill="currentColor" viewBox="0 0 24 24"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"/></svg>                     پیشخوان                 </li>                 <li class="md-nav-item" data-target="orders">                     <svg fill="currentColor" viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg>                     سفارشات من                 </li>                 <li class="md-nav-item" data-target="downloads">                     <svg fill="currentColor" viewBox="0 0 24 24"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/></svg>                     دانلودهای من                 </li>                 <li class="md-nav-item" data-target="support">                     <svg fill="currentColor" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/></svg>                     پشتیبانی و تیکت‌ها                 </li>                 <li class="md-nav-item" data-target="edit-account">                     <svg fill="currentColor" viewBox="0 0 24 24"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>                     جزئیات حساب                 </li>                 <a href="<?php echo esc_url( wp_logout_url( home_url() ) ); ?>" style="text-decoration: none;">                     <li class="md-nav-item logout">                         <svg fill="currentColor" viewBox="0 0 24 24"><path d="M17 7l-1.41 1.41L17.17 10H9v2h8.17l-1.58 1.59L17 15l4-4zM5 5h7V3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h7v-2H5V5z"/></svg>                         خروج از سیستم                     </li>                 </a>             </ul>         </aside>          <!-- محتوا -->         <main class="md-content-area">              <!-- تب پیشخوان -->             <div id="tab-dashboard" class="md-tab-content active">                 <h2 class="md-title">سلام <?php echo esc_html( $current_user->first_name ?: $current_user->display_name ); ?>! 👋</h2>                 <p style="color: var(--md-text-muted); line-height: 1.9;">                     به پنل کاربری اختصاصی خود خوش آمدید. خلاصه وضعیت حساب کاربری شما در زیر قابل مشاهده است.                 </p>                  <!-- شبکه آماری -->                 <div class="md-stats-grid">                     <div class="md-stat-card">                         <div class="md-stat-icon icon-green">                             <svg fill="currentColor" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1.41 16.09V20h-2.67v-1.93c-1.71-.36-3.16-1.46-3.27-3.4h1.96c.1 1.05.82 1.87 2.65 1.87 1.96 0 2.4-1.08 2.4-1.73 0-.9-.53-1.55-2.64-2.06-2.44-.59-4.03-1.53-4.03-3.67 0-1.86 1.47-2.93 3.19-3.24V4h2.67v1.95c1.48.35 2.79 1.41 2.92 3.12h-1.93c-.1-1.12-.91-1.65-2.35-1.65-1.34 0-2.22.68-2.22 1.6 0 .78.53 1.34 2.72 1.88 2.66.65 3.96 1.7 3.96 3.86 0 2.21-1.7 3.13-3.32 3.33z"/></svg>                         </div>                         <div class="md-stat-info">                             <span class="md-stat-title">مجموع خرید شما</span>                             <span class="md-stat-value"><?php echo class_exists('WooCommerce') ? wc_price( $total_spent ) : '-'; ?></span>                         </div>                     </div>                      <div class="md-stat-card">                         <div class="md-stat-icon icon-blue">                             <svg fill="currentColor" viewBox="0 0 24 24"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></svg>                         </div>                         <div class="md-stat-info">                             <span class="md-stat-title">کل سفارشات</span>                             <span class="md-stat-value" data-count="<?php echo (int) $total_order_count; ?>">0 سفارش</span>                         </div>                     </div>                      <div class="md-stat-card">                         <div class="md-stat-icon icon-purple">                             <svg fill="currentColor" viewBox="0 0 24 24"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/></svg>                         </div>                         <div class="md-stat-info">                             <span class="md-stat-title">دسترسی دانلود</span>                             <span class="md-stat-value" data-count="<?php echo (int) count( $customer_downloads ); ?>">0 فایل</span>                         </div>                     </div>                      <div class="md-stat-card">                         <div class="md-stat-icon icon-orange">                             <svg fill="currentColor" viewBox="0 0 24 24"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg>                         </div>                         <div class="md-stat-info">                             <span class="md-stat-title">سابقه عضویت</span>                             <span class="md-stat-value" data-count="<?php echo (int) $days_membership; ?>">0 روز</span>                         </div>                     </div>                 </div>                  <!-- نمودارها -->                 <?php if ( class_exists( 'WooCommerce' ) ) : ?>                 <div class="md-charts-grid">                     <div class="md-chart-card">                         <div class="md-chart-header">                             <h4>روند خرید ۶ ماه اخیر</h4>                         </div>                         <?php if ( array_sum( wp_list_pluck( $monthly_spending, 'value' ) ) > 0 ) : ?>                             <div class="md-chart-wrap"><canvas id="mdSpendingChart"></canvas></div>                         <?php else : ?>                             <div class="md-empty-note">هنوز داده‌ای برای نمایش روند خرید وجود ندارد.</div>                         <?php endif; ?>                     </div>                     <div class="md-chart-card">                         <div class="md-chart-header">                             <h4>وضعیت سفارشات</h4>                         </div>                         <?php if ( ! empty( $status_counts ) ) : ?>                             <div class="md-chart-wrap"><canvas id="mdStatusChart"></canvas></div>                         <?php else : ?>                             <div class="md-empty-note">هنوز سفارشی ثبت نکرده‌اید.</div>                         <?php endif; ?>                     </div>                 </div>                 <?php endif; ?>             </div>              <!-- تب سفارشات -->             <div id="tab-orders" class="md-tab-content">                 <h2 class="md-title">تاریخچه سفارشات</h2>                 <?php if ( ! empty( $customer_orders ) ) : ?>                     <div style="overflow-x: auto;">                         <table class="md-table">                             <thead>                                 <tr>                                     <th>شماره سفارش</th>                                     <th>تاریخ</th>                                     <th>وضعیت</th>                                     <th>مجموع</th>                                 </tr>                             </thead>                             <tbody>                                 <?php foreach ( $customer_orders as $order ) :                                     $status      = $order->get_status();                                     $status_name = wc_get_order_status_name( $status );                                     $badge_class = 'badge-info';                                     if ( in_array( $status, array( 'completed' ), true ) ) $badge_class = 'badge-success';                                     if ( in_array( $status, array( 'cancelled', 'failed' ), true ) ) $badge_class = 'badge-danger';                                     if ( in_array( $status, array( 'on-hold', 'pending' ), true ) ) $badge_class = 'badge-warning';                                 ?>                                     <tr>                                         <td style="font-weight:700;">#<?php echo esc_html( $order->get_order_number() ); ?></td>                                         <td><?php echo esc_html( wc_format_datetime( $order->get_date_created() ) ); ?></td>                                         <td><span class="md-badge <?php echo esc_attr( $badge_class ); ?>"><?php echo esc_html( $status_name ); ?></span></td>                                         <td><?php echo wp_kses_post( $order->get_formatted_order_total() ); ?></td>                                     </tr>                                 <?php endforeach; ?>                             </tbody>                         </table>                     </div>                 <?php else : ?>                     <div class="md-empty-note">تا کنون هیچ سفارشی ثبت نکرده‌اید.</div>                 <?php endif; ?>             </div>              <!-- تب دانلودها -->             <div id="tab-downloads" class="md-tab-content">                 <h2 class="md-title">فایل‌های دانلودی شما</h2>                 <?php if ( ! empty( $customer_downloads ) ) : ?>                     <div style="overflow-x: auto;">                         <table class="md-table">                             <thead>                                 <tr>                                     <th>نام محصول</th>                                     <th>دسترسی باقی‌مانده</th>                                     <th>عملیات</th>                                 </tr>                             </thead>                             <tbody>                                 <?php foreach ( $customer_downloads as $download ) : ?>                                     <tr>                                         <td><?php echo esc_html( $download['product_name'] ); ?></td>                                         <td><?php echo is_numeric( $download['downloads_remaining'] ) ? esc_html( $download['downloads_remaining'] ) : 'نامحدود'; ?></td>                                         <td>                                             <a href="<?php echo esc_url( $download['download_url'] ); ?>" class="md-btn-outline" download>دانلود فایل</a>                                         </td>                                     </tr>                                 <?php endforeach; ?>                             </tbody>                         </table>                     </div>                 <?php else : ?>                     <div class="md-empty-note">هیچ فایل دانلودی برای حساب شما یافت نشد.</div>                 <?php endif; ?>             </div>              <!-- تب پشتیبانی و تیکت‌ها -->             <div id="tab-support" class="md-tab-content">                 <div class="md-title">                     <span>پشتیبانی و تیکت‌ها</span>                     <button class="md-btn" onclick="alert('اتصال به فرم تیکت')">+ تیکت جدید</button>                 </div>                 <div style="overflow-x: auto;">                     <table class="md-table">                         <thead>                             <tr>                                 <th>شناسه</th>                                 <th>موضوع تیکت</th>                                 <th>وضعیت</th>                                 <th>آخرین بروزرسانی</th>                                 <th>عملیات</th>                             </tr>                         </thead>                         <tbody>                             <tr>                                 <td>#1024</td>                                 <td>مشکل در دانلود فایل دوره آموزشی</td>                                 <td><span class="md-badge badge-warning">در حال بررسی</span></td>                                 <td>۲ ساعت پیش</td>                                 <td><a href="#" class="md-btn-outline">مشاهده</a></td>                             </tr>                             <tr>                                 <td>#1015</td>                                 <td>سوال پیش از خرید درباره قالب</td>                                 <td><span class="md-badge badge-success">پاسخ داده شده</span></td>                                 <td>دیروز</td>                                 <td><a href="#" class="md-btn-outline">مشاهده</a></td>                             </tr>                         </tbody>                     </table>                 </div>             </div>              <!-- تب ویرایش حساب -->             <div id="tab-edit-account" class="md-tab-content">                 <h2 class="md-title">جزئیات حساب کاربری</h2>                 <form action="#" method="post">                     <div style="display: flex; gap: 16px; flex-wrap: wrap;">                         <div class="md-form-group" style="flex: 1 1 200px;">                             <label>نام</label>                             <input type="text" class="md-input" value="<?php echo esc_attr( $current_user->first_name ); ?>" placeholder="نام شما">                         </div>                         <div class="md-form-group" style="flex: 1 1 200px;">                             <label>نام خانوادگی</label>                             <input type="text" class="md-input" value="<?php echo esc_attr( $current_user->last_name ); ?>" placeholder="نام خانوادگی شما">                         </div>                     </div>                      <div class="md-form-group">                         <label>آدرس ایمیل</label>                         <input type="email" class="md-input" value="<?php echo esc_attr( $current_user->user_email ); ?>" disabled style="background: #f2f2f5; cursor: not-allowed;">                     </div>                      <button type="button" class="md-btn">ذخیره تغییرات</button>                 </form>             </div>          </main>     </div>      <!-- 4. منطق جاوااسکریپت -->     <script>     document.addEventListener('DOMContentLoaded', function () {          // ----- تعویض تب‌ها -----         var navItems = document.querySelectorAll('.md-nav-item[data-target]');         var tabContents = document.querySelectorAll('.md-tab-content');          navItems.forEach(function (item) {             item.addEventListener('click', function () {                 navItems.forEach(function (nav) { nav.classList.remove('active'); });                 tabContents.forEach(function (content) { content.classList.remove('active'); });                  this.classList.add('active');                 var targetId = 'tab-' + this.getAttribute('data-target');                 var target = document.getElementById(targetId);                 if (target) target.classList.add('active');             });         });          // ----- شمارنده انیمیشنی برای کارت‌های آماری -----         function animateCount(el) {             var target = parseInt(el.getAttribute('data-count'), 10) || 0;             var suffix = el.textContent.replace(/^[0-9۰-۹,]+\s*/, '');             var duration = 900;             var startTime = null;              function step(timestamp) {                 if (!startTime) startTime = timestamp;                 var progress = Math.min((timestamp - startTime) / duration, 1);                 var eased = 1 - Math.pow(1 - progress, 3);                 var current = Math.floor(eased * target);                 el.textContent = current.toLocaleString('fa-IR') + (suffix ? ' ' + suffix : '');                 if (progress < 1) {                     requestAnimationFrame(step);                 } else {                     el.textContent = target.toLocaleString('fa-IR') + (suffix ? ' ' + suffix : '');                 }             }             requestAnimationFrame(step);         }          document.querySelectorAll('.md-stat-value[data-count]').forEach(function (el) {             animateCount(el);         });          // ----- نمودارها (Chart.js) -----         if (typeof Chart !== 'undefined') {              var mdPrimary = getComputedStyle(document.querySelector('.md-dashboard-wrapper')).getPropertyValue('--md-primary').trim() || '#6200ea';              var spendingCanvas = document.getElementById('mdSpendingChart');             if (spendingCanvas) {                 new Chart(spendingCanvas.getContext('2d'), {                     type: 'line',                     data: {                         labels: <?php echo $chart_labels; ?>,                         datasets: [{                             label: 'مبلغ خرید',                             data: <?php echo $chart_values; ?>,                             fill: true,                             tension: 0.4,                             borderColor: mdPrimary,                             backgroundColor: 'rgba(98, 0, 234, 0.12)',                             pointBackgroundColor: mdPrimary,                             pointRadius: 4,                             pointHoverRadius: 6,                             borderWidth: 2.5                         }]                     },                     options: {                         responsive: true,                         maintainAspectRatio: false,                         animation: { duration: 1200, easing: 'easeOutQuart' },                         plugins: { legend: { display: false } },                         scales: {                             y: { beginAtZero: true, grid: { color: '#f0eefa' } },                             x: { grid: { display: false } }                         }                     }                 });             }              var statusCanvas = document.getElementById('mdStatusChart');             if (statusCanvas) {                 new Chart(statusCanvas.getContext('2d'), {                     type: 'doughnut',                     data: {                         labels: <?php echo $status_labels; ?>,                         datasets: [{                             data: <?php echo $status_values; ?>,                             backgroundColor: ['#6200ea', '#00bfa5', '#ff9100', '#ff5252', '#2979ff', '#aa00ff'],                             borderWidth: 2,                             borderColor: '#ffffff',                             hoverOffset: 10                         }]                     },                     options: {                         responsive: true,                         maintainAspectRatio: false,                         animation: { duration: 1200, easing: 'easeOutQuart' },                         plugins: {                             legend: {                                 position: 'bottom',                                 rtl: true,                                 labels: { font: { family: 'Vazirmatn' }, padding: 14, usePointStyle: true }                             }                         },                         cutout: '65%'                     }                 });             }         }     });     </script>      <?php     return ob_get_clean(); }
مشاهده بیشتر