| | |
| | | ]; |
| | | |
| | | if (Features::hasIntegration('cloudflare') && JVB()->connect('cloudflare')->isSetUp()) { |
| | | $requirements[] = 'cloudflare-turnstile'; |
| | | JVB()->connect('cloudflare')->enqueueTurnstileScripts(); |
| | | } |
| | | if (is_singular(BASE.'dash')) { |
| | | $requirements[] = 'jvb-form'; |
| | | $requirements[] = 'jvb-view'; |
| | | |
| | | wp_enqueue_script('jvb-referral-admin', |
| | | JVB_URL.'assets/js/min/referralAdmin.min.js', |
| | | ['jvb-referral'], |
| | | '1.0.0', |
| | | true); |
| | | } |
| | | wp_enqueue_script( |
| | | 'jvb-referral', |
| | |
| | | { |
| | | $yesterday = date('Y-m-d', strtotime('-1 day')); |
| | | |
| | | // Get new referrals from yesterday |
| | | $new_referrals = $this->wpdb->get_results($this->wpdb->prepare( |
| | | "SELECT |
| | | r.*, |
| | | u.display_name as referrer_name |
| | | "SELECT r.*, u.display_name as referrer_name |
| | | FROM {$this->referrals_table} r |
| | | JOIN {$this->wpdb->users} u ON r.referrer_id = u.ID |
| | | WHERE DATE(r.referred_at) = %s |
| | |
| | | $yesterday |
| | | )); |
| | | |
| | | // Only send if there's at least 1 new referral |
| | | if (empty($new_referrals)) { |
| | | return; |
| | | } |
| | | |
| | | // Build email content |
| | | $content = '<h2>Daily Referral Report</h2>'; |
| | | $content .= '<p><strong>' . count($new_referrals) . '</strong> new referral' . |
| | | (count($new_referrals) !== 1 ? 's' : '') . ' yesterday (' . $yesterday . ')</p>'; |
| | | $content = JVB()->email()->h1('Daily Referral Report'); |
| | | $content .= JVB()->email()->stat( |
| | | count($new_referrals), |
| | | count($new_referrals) === 1 ? 'New Referral' : 'New Referrals', |
| | | 'From ' . $yesterday |
| | | ); |
| | | |
| | | $content .= '<table style="width:100%; border-collapse: collapse; margin: 20px 0;">'; |
| | | $content .= '<thead><tr style="background: #f5f5f5;">'; |
| | | $content .= '<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Referee</th>'; |
| | | $content .= '<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Email</th>'; |
| | | $content .= '<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Referrer</th>'; |
| | | $content .= '<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Code</th>'; |
| | | $content .= '</tr></thead><tbody>'; |
| | | $content .= JVB()->email()->spacer(20); |
| | | $content .= JVB()->email()->h2('New Referrals'); |
| | | |
| | | // Build list of referrals |
| | | foreach ($new_referrals as $ref) { |
| | | $content .= '<tr>'; |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($ref->referee_name)); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($ref->referee_email)); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($ref->referrer_name)); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($ref->referral_code)); |
| | | $content .= '</tr>'; |
| | | $cardContent = sprintf( |
| | | '<p><strong>%s</strong> (%s)</p>', |
| | | esc_html($ref->referee_name), |
| | | esc_html($ref->referee_email) |
| | | ); |
| | | $cardContent .= sprintf( |
| | | '<p style="font-size:13px;color:%s;">Referred by: %s | Code: %s</p>', |
| | | JVB()->email()->colours['dark-200'], |
| | | esc_html($ref->referrer_name), |
| | | JVB()->email()->badge($ref->referral_code, 'info') |
| | | ); |
| | | |
| | | $content .= JVB()->email()->card($cardContent); |
| | | } |
| | | |
| | | $content .= '</tbody></table>'; |
| | | |
| | | // Get admin email |
| | | $to = get_option('admin_email'); |
| | | $subject = sprintf('[%s] %d New Referral%s', |
| | | $subject = sprintf( |
| | | '[%s] %d New Referral%s', |
| | | get_bloginfo('name'), |
| | | count($new_referrals), |
| | | count($new_referrals) !== 1 ? 's' : ''); |
| | | count($new_referrals) !== 1 ? 's' : '' |
| | | ); |
| | | |
| | | |
| | | JVB()->email()->sendEmail($to, $subject, $content); |
| | | JVB()->email()->sendEmail($to, $subject, $content, 'DAILY REPORT'); |
| | | } |
| | | |
| | | /** |
| | |
| | | $top_referrers = $this->getTopReferrers(10, 'week'); |
| | | $total_referrals = $this->wpdb->get_var( |
| | | "SELECT COUNT(*) FROM {$this->referrals_table} |
| | | WHERE referred_at >= DATE_SUB(NOW(), INTERVAL 1 WEEK)" |
| | | WHERE referred_at >= DATE_SUB(NOW(), INTERVAL 1 WEEK)" |
| | | ); |
| | | |
| | | if ($total_referrals == 0) { |
| | | return; |
| | | } |
| | | |
| | | $content = JVB()->email()->h1('Weekly Referral Summary'); |
| | | $content .= JVB()->email()->stat( |
| | | $total_referrals, |
| | | 'Total Referrals', |
| | | 'This week' |
| | | ); |
| | | |
| | | $content .= JVB()->email()->spacer(30); |
| | | $content .= JVB()->email()->h2('Top 10 Referrers'); |
| | | |
| | | // Leaderboard style |
| | | $rank = 1; |
| | | foreach ($top_referrers as $referrer) { |
| | | $rankBadge = $rank <= 3 |
| | | ? JVB()->email()->badge('#' . $rank, $rank === 1 ? 'success' : 'info') |
| | | : '<span style="font-weight:600;color:' . JVB()->email()->colours['dark-200'] . ';">#' . $rank . '</span>'; |
| | | |
| | | $cardContent = sprintf( |
| | | '<p>%s <strong>%s</strong></p>', |
| | | $rankBadge, |
| | | esc_html($referrer->user_name) |
| | | ); |
| | | |
| | | $stats = [ |
| | | JVB()->email()->stat($referrer->referral_count, 'Total Referrals'), |
| | | JVB()->email()->stat($referrer->treated_count, 'Treated') |
| | | ]; |
| | | $cardContent .= JVB()->email()->grid($stats, 2); |
| | | |
| | | $content .= JVB()->email()->card($cardContent); |
| | | $rank++; |
| | | } |
| | | |
| | | $to = get_option('admin_email'); |
| | | $subject = '[' . get_bloginfo('name') . '] Weekly Referral Summary - ' . date('F j, Y'); |
| | | |
| | | $message = $this->generateWeeklyReportEmail($top_referrers, $total_referrals); |
| | | |
| | | JVB()->email()->sendEmail($to, $subject, $message); |
| | | JVB()->email()->sendEmail($to, $subject, $content, 'WEEKLY SUMMARY'); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Generate HTML email for daily report |
| | | * |
| | | * @param array $referrals |
| | | * @param string $period |
| | | * @return string |
| | | */ |
| | | protected function generateReportEmail(array $referrals, string $period): string |
| | | { |
| | | $count = count($referrals); |
| | | |
| | | $content = sprintf('<p>You have <strong>%d new referral%s</strong> today.</p>', |
| | | $count, |
| | | $count !== 1 ? 's' : '' |
| | | ); |
| | | |
| | | $content .= '<table style="width:100%; border-collapse: collapse; margin: 20px 0;">'; |
| | | $content .= '<thead><tr style="background: #f5f5f5; text-align: left;">'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Referred By</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">New User</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Email</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Status</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Time</th>'; |
| | | $content .= '</tr></thead><tbody>'; |
| | | |
| | | foreach ($referrals as $referral) { |
| | | $content .= '<tr>'; |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($referral->referrer_name ?? 'Unknown')); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($referral->referee_name)); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($referral->referee_email)); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html(ucfirst($referral->status))); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html(date('g:i A', strtotime($referral->referred_at)))); |
| | | $content .= '</tr>'; |
| | | } |
| | | |
| | | $content .= '</tbody></table>'; |
| | | $content .= '<p><small>See attached CSV for full details.</small></p>'; |
| | | |
| | | return jvbGetEmailTemplate($content, 'Daily Referral Report'); |
| | | } |
| | | |
| | | /** |
| | | * Generate HTML email for weekly report |
| | | * |
| | | * @param array $top_referrers |
| | |
| | | $total_referrals !== 1 ? 's' : '' |
| | | ); |
| | | |
| | | $content .= '<h3>Top 10 Referrers This Week</h3>'; |
| | | $content .= '<table style="width:100%; border-collapse: collapse; margin: 20px 0;">'; |
| | | $content .= '<thead><tr style="background: #f5f5f5; text-align: left;">'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Rank</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">User</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Total Referrals</th>'; |
| | | $content .= '<th style="padding: 10px; border: 1px solid #ddd;">Treated</th>'; |
| | | $content .= '</tr></thead><tbody>'; |
| | | |
| | | $referrers = []; |
| | | $rank = 1; |
| | | foreach ($top_referrers as $referrer) { |
| | | $content .= '<tr>'; |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%d</td>', $rank++); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%s</td>', |
| | | esc_html($referrer->user_name)); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%d</td>', |
| | | $referrer->referral_count); |
| | | $content .= sprintf('<td style="padding: 10px; border: 1px solid #ddd;">%d</td>', |
| | | $referrer->treated_count); |
| | | $content .= '</tr>'; |
| | | $referrers[] = [ |
| | | 'label' => '#' . $rank++ . ' - ' . esc_html($referrer->user_name), |
| | | 'value' => sprintf( |
| | | '<strong>Total Referrals:</strong> %d | <strong>Treated:</strong> %d', |
| | | $referrer->referral_count, |
| | | $referrer->treated_count |
| | | ) |
| | | ]; |
| | | } |
| | | |
| | | $content .= '</tbody></table>'; |
| | | $content .= JVB()->email()->table($referrers, 'Top 10 Referrers This Week'); |
| | | |
| | | return jvbGetEmailTemplate($content, 'Weekly Referral Summary'); |
| | | return $content; |
| | | } |
| | | |
| | | /** |
| | |
| | | 'autocomplete'=>'off', |
| | | 'data-referrer' => $referrer_name |
| | | ]).' |
| | | '.$turnstile.' |
| | | <button type="button" class="button-secondary check-code-btn"> |
| | | '.jvbIcon('check-circle', ['size' => 16]).' Verify Code |
| | | </button> |
| | |
| | | <p class="helper-text"> |
| | | We\'ll send you a link to complete your registration. |
| | | </p> |
| | | '.$turnstile.' |
| | | </form> |
| | | <div class="success-content" hidden> |
| | | <h3>Check Your Email!</h3> |
| | |
| | | <h4>Your Referral Link</h4> |
| | | <div class="copy-group row btw nowrap"> |
| | | <code id="referral-link" class="copy-target"><?= esc_url($share_url) ?></code> |
| | | <button type="button" class="copy-btn" data-target="referral-link" aria-label="Copy referral link"> |
| | | <?php echo jvbIcon('copy', ['size' => 16]); ?> |
| | | <button type="button" class="copy-btn" data-target="referral-link" title="Copy referral link"> |
| | | <?= jvbIcon('copy'); ?> |
| | | <?= jvbIcon('check-circle'); ?> |
| | | </button> |
| | | </div> |
| | | <p class="hint">Quickest and easiest: autofills your code.</p> |
| | |
| | | <h4>Your Code</h4> |
| | | <div class="copy-group row btw nowrap"> |
| | | <code id="referral-code" class="copy-target"><?= esc_html($referral_code) ?></code> |
| | | <button type="button" class="copy-btn" data-target="referral-code" aria-label="Copy referral code"> |
| | | <?php echo jvbIcon('copy', ['size' => 16]); ?> |
| | | <button type="button" class="copy-btn" data-target="referral-code" title="Copy referral code"> |
| | | <?= jvbIcon('copy'); ?> |
| | | <?= jvbIcon('check-circle'); ?> |
| | | </button> |
| | | </div> |
| | | <p class="hint">Manually copy and paste the code</p> |
| | |
| | | |
| | | <!-- Referral Code Card --> |
| | | <div class="card"> |
| | | <h3>Share Code</h3> |
| | | <div class="row btw nowrap"> |
| | | <code class="code"><?= esc_html($referral_code) ?></code> |
| | | <button class="button copy-btn" data-code="<?= esc_attr($referral_code) ?>"> |
| | | Copy Code |
| | | </button> |
| | | </div> |
| | | <h3>Share Link</h3> |
| | | <div class="row btw nowrap"> |
| | | <code class="share-link"> |
| | | <?= home_url('/?ref=' . $referral_code) ?> |
| | | </code> |
| | | <button class="button copy-btn" data-code="<?= home_url('/?ref=' . $referral_code) ?>"> |
| | | Copy Link |
| | | <code id="referral-link" class="copy-target"><?= home_url('/?ref=' . $referral_code) ?></code> |
| | | <button type="button" class="copy-btn" data-target="referral-link" title="Copy referral link"> |
| | | <?= jvbIcon('copy'); ?> |
| | | <?= jvbIcon('check-circle'); ?> |
| | | </button> |
| | | </div> |
| | | <h3>Share Code</h3> |
| | | <div class="row btw nowrap"> |
| | | <code id="referral-code" class="copy-target"><?= esc_html($referral_code) ?></code> |
| | | <button type="button" class="copy-btn" data-target="referral-code" title="Copy referral code"> |
| | | <?= jvbIcon('copy'); ?> |
| | | <?= jvbIcon('check-circle'); ?> |
| | | </button> |
| | | </div> |
| | | </div> |
| | |
| | | $referrer_first_name = $referrer ? strtok($referrer->display_name, ' ') : 'Your friend'; |
| | | |
| | | // Get reward text |
| | | $reward_text = $this->getRewardText(false); // Just "20% off" or "$25 off" |
| | | $reward_text = $this->getRewardText(); // Just "20% off" or "$25 off" |
| | | |
| | | $booking_url = apply_filters('jvb_referral_booking_url', home_url('/contact')); |
| | | $estimate_url = apply_filters('jvb_referral_estimate_url', home_url('/estimate')); |