From ac444cba221832c012c0435fdc8339fe9f37febb Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 11 May 2026 18:35:04 +0000
Subject: [PATCH] =Some changes to the CRUD.js editing, timeline post configuration
---
inc/managers/ReferralManager.php | 898 +++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 556 insertions(+), 342 deletions(-)
diff --git a/inc/managers/ReferralManager.php b/inc/managers/ReferralManager.php
index 2f7468a..fe97fea 100644
--- a/inc/managers/ReferralManager.php
+++ b/inc/managers/ReferralManager.php
@@ -1,12 +1,10 @@
<?php
namespace JVBase\managers;
-use JVBase\managers\MagicLinkManager;
-use JVBase\integrations\Cloudflare;
-use JVBase\meta\MetaForm;
+use JVBase\meta\Form;
use JVBase\ui\CRUDSkeleton;
use JVBase\ui\Tabs;
-use JVBase\utility\Features;
+use JVBase\base\Site;
use WP_User;
use WP_Error;
@@ -24,11 +22,19 @@
{
protected $wpdb;
protected MagicLinkManager $magic_link;
- protected CacheManager $cache;
+ protected Cache $cache;
+ protected Cache $requestCache;
+ protected Cache $statsCache;
protected string $referrals_table;
protected ?int $referralPage = null;
protected string $rewards_table;
+ protected CustomTable $referrals;
+ protected CustomTable $codes;
+ protected CustomTable $janeClients;
+ protected CustomTable $rewards;
+ protected CustomTable $treatments;
+
// Default reward settings
protected array $default_settings = [
'referrer_reward_applies_to' => 'per_user', // 'per_user' or 'flat_total'
@@ -37,18 +43,28 @@
'referee_reward_type' => 'percentage', // 'percentage' or 'fixed'
'referee_reward_amount' => 20, // 20% or $20
'referee_reward_applies_to' => 'first_order', // 'first_order' or 'all_orders'
- 'referral_role' => BASE.'client'
];
- protected string $role = BASE.'client';
+ protected string $role;
protected array $settings;
public function __construct()
{
+ $this->defineTables();
+ $this->role = Site::getDefaultReferralRole();
+ $this->default_settings['referral_role'] = $this->role;
global $wpdb;
$this->wpdb = $wpdb;
- $this->cache = CacheManager::for('referrals', WEEK_IN_SECONDS);
+ $this->cache = Cache::for('referrals', WEEK_IN_SECONDS);
+ $this->requestCache = Cache::for('referral_requests', WEEK_IN_SECONDS)->connect('referrals', true);
+ $this->statsCache = Cache::for('referral_stats', WEEK_IN_SECONDS)->connect('referrals', true);
+ if (JVB_TESTING) {
+ $this->cache->flush();
+ $this->requestCache->flush();
+ $this->statsCache->flush();
+ }
+
$this->referrals_table = $wpdb->prefix . BASE . 'referrals';
$this->rewards_table = $wpdb->prefix . BASE . 'referral_rewards';
@@ -58,7 +74,7 @@
add_action('jvbUserRegistered', [$this, 'processRegistrationToken'], 10, 3);
add_action('jvb_add_token_inputs', [$this, 'addLoginInputs'], 10, 1);
- add_action('jvbUserRegistered', [$this, 'processReferral'], 10, 1);
+ add_action('user_register', [$this, 'processReferral'], 10, 1);
// Add meta boxes for admin to manage referrals
add_action('show_user_profile', [$this, 'displayUserReferralInfo']);
@@ -92,6 +108,182 @@
add_filter('jvb_admin_page_submission', [$this, 'handleAdminSubmission'], 10, 3);
}
+ protected function defineTables():void
+ {
+ $this->defineReferralsTable();
+ $this->defineCodeTable();
+ $this->defineJaneClientsTable();
+ $this->defineRewardsTable();
+ $this->defineTreatmentsTable();
+ }
+ protected function defineReferralsTable():void
+ {
+ $table = CustomTable::for('referrals');
+
+ $table->setColumns([
+ 'id' => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+ 'from_user' => "{$table->getUserIDType()} NOT NULL",
+ 'to_user' => "{$table->getUserIDType()} NOT NULL",
+ 'to_name' => 'varchar(255) NOT NULL',
+ 'to_email' => 'varchar(255) NOT NULL',
+ 'to_phone' => 'varchar(50) NOT NULL',
+ 'referral_code'=> 'varchar(50) NOT NULL',
+ 'status' => "ENUM('pending', 'consulted', 'treated', 'cancelled') DEFAULT 'pending'",
+ 'created_at'=> 'datetime DEFAULT CURRENT_TIMESTAMP',
+ 'consulted_at'=> 'datetime DEFAULT NULL',
+ 'treated_at'=> 'datetime DEFAULT NULL',
+ 'treatment_count' => 'int DEFAULT 0',
+ 'notes' => 'text DEFAULT NULL',
+ ]);
+
+ $table->setKeys([
+ ['key' => 'PRIMARY', 'value' => 'id'],
+ ['key' => 'UNIQUE', 'value' => '(`to_user`)'],
+ 'from_user (`from_user`)',
+ 'status (`status`)',
+ 'code (`referral_code`)',
+ 'date (`created_at`)',
+ 'consult (`consulted_at`)'
+ ]);
+
+ $base = BASE;
+ $table->setConstraints([
+ "CONSTRAINT `{$base}referral_from_user_fk` FOREIGN KEY (`from_user`)
+ REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE",
+ "CONSTRAINT `{$base}referral_to_user_fk` FOREIGN KEY (`to_user`)
+ REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE"
+ ]);
+ $table->defineTable();
+ $this->referrals = $table;
+ }
+
+ protected function defineCodeTable():void
+ {
+ $table = CustomTable::for('referrals_codes');
+
+ $table->setColumns([
+ 'id' => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+ 'user_id' => "{$table->getUserIDType()} NOT NULL",
+ 'code' => 'varchar(50) NOT NULL',
+ 'created_at'=> 'datetime DEFAULT CURRENT_TIMESTAMP',
+ ]);
+
+ $table->setKeys([
+ ['key' => 'PRIMARY', 'value' => '(`id`)'],
+ ['key' => 'UNIQUE', 'value' => '(`code`)'],
+ 'user (`user_id`)',
+ ]);
+
+ $base = BASE;
+ $table->setConstraints([
+ "CONSTRAINT `{$base}referral_code_user_fk` FOREIGN KEY (`user_id`)
+ REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE",
+ ]);
+ $table->defineTable();
+ $this->codes = $table;
+ }
+ protected function defineJaneClientsTable():void
+ {
+ $table = CustomTable::for('referrals_jane_clients');
+
+ $table->setColumns([
+ 'id' => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+ 'patient_guid' => 'varchar(50) NOT NULL',
+ 'user_id' => "{$table->getUserIDType()} NOT NULL",
+ 'first_name' => 'varchar(100) NOT NULL',
+ 'last_name' => 'varchar(100) NOT NULL',
+ 'email' => 'varchar(255) NOT NULL',
+ 'imported_at' => 'datetime DEFAULT CURRENT_TIMESTAMP',
+ 'updated_at' => 'datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
+ ]);
+
+ $table->setKeys([
+ ['key' => 'PRIMARY', 'value' => '(`id`)'],
+ ['key' => 'UNIQUE', 'value' => '(`patient_guid`)'],
+ 'user (`user_id`)',
+ 'email (`email`)',
+ ]);
+
+ $base = BASE;
+ $table->setConstraints([
+ "CONSTRAINT `{$base}jane_clients_user` FOREIGN KEY (`user_id`)
+ REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE",
+ ]);
+ $table->defineTable();
+ $this->janeClients = $table;
+ }
+ protected function defineRewardsTable():void
+ {
+ $table = CustomTable::for('referrals_rewards');
+
+ $table->setColumns([
+ 'id' => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+ 'referral_id' => 'bigint(20) unsigned NOT NULL',
+ 'user_id' => "{$table->getUserIDType()} NOT NULL",
+ 'reward_type' => "ENUM('referrer', 'referee') NOT NULL",
+ 'amount' => 'decimal(10,2) NOT NULL',
+ 'reward_calculation'=> "ENUM('percentage', 'fixed')",
+ 'status' => "ENUM('available', 'redeemed', 'expired', 'cancelled') DEFAULT 'available'",
+ 'created_at' => 'datetime NOT NULL DEFAULT CURRENT_TIMESTAMP',
+ 'updated_at' => 'datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
+ 'redeemed_at' => 'datetime DEFAULT NULL',
+ 'expires_at' => 'datetime DEFAULT NULL',
+ 'notes' => 'text DEFAULT NULL',
+ ]);
+
+ $table->setKeys([
+ ['key' => 'PRIMARY', 'value' => '(`id`)'],
+ 'referral (`referral_id`)',
+ 'user (`user_id`)',
+ 'status (`status`)',
+ 'type (`reward_type`)'
+ ]);
+
+ $base = BASE;
+ $table->setConstraints([
+ "CONSTRAINT `{$base}reward_referral` FOREIGN KEY (`referral_id`)
+ REFERENCES `{$this->referrals->getFullTableName()}` (`id`) ON DELETE CASCADE",
+ "CONSTRAINT `{$base}reward_user` FOREIGN KEY (`user_id`)
+ REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE"
+ ]);
+ $table->defineTable();
+ $this->rewards = $table;
+ }
+ protected function defineTreatmentsTable():void
+ {
+ $table = CustomTable::for('referral_treatments');
+
+ $table->setColumns([
+ 'id' => 'bigint(20) unsigned NOT NULL AUTO_INCREMENT',
+ 'referral_id' => 'bigint(20) unsigned NOT NULL',
+ 'user_id' => "{$table->getUserIDType()} NOT NULL",
+ 'treatment_type'=> 'varchar(100) NOT NULL', //Tier 1-6, Brows, etc
+ 'treatment_date'=> 'datetime NOT NULL',
+ 'invoice_number'=> 'varchar(50) DEFAULT NULL',
+ 'amount' => 'decimal(10,2) DEFAULT NULL',
+ 'status' => "ENUM('completed', 'no_show', 'cancelled') DEFAULT 'completed'",
+ 'imported_at' => 'datetime DEFAULT CURRENT_TIMESTAMP',
+ ]);
+
+ $table->setKeys([
+ ['key' => 'PRIMARY', 'value' => '(`id`)'],
+ 'referral (`referral_id`)',
+ 'user (`user_id`)',
+ 'date (`treatment_date`)',
+ 'type (`treatment_type`)',
+ ]);
+
+ $base = BASE;
+ $table->setConstraints([
+ "CONSTRAINT `{$base}treatment_referral` FOREIGN KEY (`referral_id`)
+ REFERENCES `{$this->referrals->getFullTableName()}` (`id`) ON DELETE CASCADE",
+ "CONSTRAINT `{$base}treatment_user` FOREIGN KEY (`user_id`)
+ REFERENCES `{$table->getUserTable()}` (`ID`) ON DELETE CASCADE"
+ ]);
+ $table->defineTable();
+ $this->treatments = $table;
+ }
+
public function getSettings():array
{
return $this->settings;
@@ -141,12 +333,18 @@
'jvb-data-store',
];
- if (Features::hasIntegration('cloudflare') && JVB()->connect('cloudflare')->isSetUp()) {
- $requirements[] = 'cloudflare-turnstile';
+ if (Site::hasIntegration('cloudflare') && JVB()->connect('cloudflare')->isSetUp()) {
+ 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',
@@ -175,6 +373,26 @@
}
}
+ public function createCode(int $user_id, string $code):string|false
+ {
+ $code = sanitize_title($code);
+ $existing = $this->codes->get(['code' => $code]);
+ if ($existing) {
+ if ($existing['user_id'] !== $user_id) {
+ return false;
+ }
+ return $code;
+ }
+ $success = $this->codes->insert([
+ 'user_id' => $user_id,
+ 'code' => $code
+ ]);
+ if ($success) {
+ return $code;
+ }
+ return false;
+ }
+
/**
* Generate or get existing referral code for a user
*
@@ -182,32 +400,35 @@
* @param string|null $custom_code Optional custom code
* @return string|WP_Error
*/
- public function getUserReferralCode(int $user_id, ?string $custom_code = null)
+ public function getUserReferralCode(int $user_id, ?string $custom_code = null):string|false
{
$user = get_userdata($user_id);
if (!$user) {
- return new WP_Error('invalid_user', 'User not found');
+ return false;
}
- // Check if user already has a code
- $existing_code = get_user_meta($user_id, BASE . 'referral_code', true);
-
- if ($existing_code && !$custom_code) {
- return $existing_code;
+ $existing = $this->codes->pluck('code', ['user_id' => $user_id],'created_at', 'DESC');
+ if (!empty($existing) && !$custom_code) {
+ return $existing[0];
+ }
+ if ($custom_code && !empty($existing) && !in_array($custom_code, $existing)) {
+ $test = $this->createCode($user_id, $custom_code);
+ if ($test) {
+ return $this->codes->pluck('code', ['user_id' => $user_id], 'created_at', 'DESC')[0];
+ } else {
+ return $existing[0];
+ }
}
// Generate new code if custom provided or none exists
- $code = $custom_code ?: $this->generateReferralCode($user);
+ $code = $this->generateReferralCode($user);
- // Validate uniqueness
- if ($this->isCodeTaken($code, $user_id)) {
- return new WP_Error('code_taken', 'This referral code is already in use');
+ $success = $this->createCode($user_id, $code);
+ if ($success) {
+ return $this->codes->pluck('code', ['user_id' => $user_id], 'created_at', 'DESC')[0];
}
- // Save the code
- update_user_meta($user_id, BASE . 'referral_code', $code);
-
- return $code;
+ return false;
}
/**
@@ -240,24 +461,11 @@
* Check if a referral code is already taken
*
* @param string $code
- * @param int|null $exclude_user_id
* @return bool
*/
- protected function isCodeTaken(string $code, ?int $exclude_user_id = null): bool
+ protected function isCodeTaken(string $code): bool
{
- $args = [
- 'meta_key' => BASE . 'referral_code',
- 'meta_value' => $code,
- 'fields' => 'ID',
- 'number' => 1
- ];
-
- if ($exclude_user_id) {
- $args['exclude'] = [$exclude_user_id];
- }
-
- $users = get_users($args);
- return !empty($users);
+ return (bool) $this->codes->get(['code' => $code]);
}
public function processRegistrationToken(int $user_id, string $email, array $data): void
@@ -284,60 +492,58 @@
* Track a new referral when user registers
*
* @param int $user_id
+ * @param array $userData
* @return bool;
*/
- public function processReferral(int $user_id): bool
+ public function processReferral(int $user_id, array $userData): bool
{
- // Try to get code from user meta first (set during registration)
- $referral_code = get_user_meta($user_id, BASE . 'pending_referral_code', true);
+ $referral = $this->referrals->get(['to_user' => $user_id]);
- if (empty($referral_code)) {
+ if (empty($referral)) {
+ $referral = $this->referrals->get(['to_email' => $userData['email']]);
+ }
+ if (empty($referral)) {
// Check session/cookie if not in meta
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$referral_code = $_SESSION[BASE . 'referral_code'] ?? $_COOKIE[BASE . 'referral_code'] ?? '';
+ if (!empty ($referral_code)) {
+ $referral = [
+ 'to_user' => $user_id,
+ 'referral_code' => $referral_code,
+ 'to_email' => $userData['user_email']
+ ];
+ }
}
- if (empty($referral_code)) {
+ if (empty($referral)) {
return false; // No referral code - regular registration
}
// Find the referrer
- $referrer = $this->getUserByReferralCode($referral_code);
- if (!$referrer) {
- delete_user_meta($user_id, BASE . 'pending_referral_code');
+ $referrer = $this->codes->pluck('user_id', ['code' => $referral['referral_code']]);
+ if (empty($referrer)) {
+ //This should not happen, but whatever
+ return false;
+ }
+ $referrer = $referrer[0];
+ $record = $this->referrals->findOrCreate([
+ 'to_user' => $user_id,
+ 'referral_code' => $referral['referral_code'],
+ ], [
+ 'from_user' => $referrer,
+ 'to_email' => $referral['to_email'],
+ 'to_name' => $userData['first_name'],
+// 'to_phone' =>
+ 'status' => 'pending'
+ ]);
+
+ if (!$record) {
+ error_log('[ReferralManager]::processReferral Could not update record for user: '.print_r($referral, true));
return false;
}
- $user = get_userdata($user_id);
-
- // Check if referral already exists for this user
- $existing = $this->wpdb->get_row($this->wpdb->prepare(
- "SELECT * FROM {$this->referrals_table}
- WHERE referrer_id = %d AND (referee_email = %s OR referee_id = %d)",
- $referrer->ID,
- $user->user_email,
- $user_id
- ));
-
- if (!$existing) {
- // Create new referral record - referred_at captures registration time
- $this->wpdb->insert(
- $this->referrals_table,
- [
- 'referrer_id' => $referrer->ID,
- 'referee_id' => $user_id,
- 'referee_name' => $user->display_name,
- 'referee_email' => $user->user_email,
- 'referee_phone' => get_user_meta($user_id, BASE . 'phone', true) ?: '',
- 'referral_code' => $referral_code,
- 'status' => 'pending', // pending first treatment
- 'referred_at' => current_time('mysql') // When they registered
- ],
- ['%d', '%d', '%s', '%s', '%s', '%s', '%s', '%s']
- );
- }
// Clean up temp data
delete_user_meta($user_id, BASE . 'pending_referral_code');
@@ -349,13 +555,13 @@
}
// Clear caches
- $this->cache->clear();
+ $this->cache->flush();
// Fire action for tracking
- do_action('jvb_referral_processed', $user_id, $referrer->ID, $referral_code);
+ do_action('jvb_referral_processed', $user_id, $referrer->ID, $referral['referral_code']);
// Send notification to referrer
- $this->sendReferrerNotification($referrer->ID, $user->display_name);
+ $this->sendReferrerNotification($referrer->ID, $userData['display_name']);
return true;
}
@@ -513,19 +719,19 @@
*/
public function getUserReferrals(int $user_id, array $args = []): array
{
- return $this->cache->remember(
- $user_id,
+ $defaults = [
+ 'status' => 'all',
+ 'limit' => 100,
+ 'offset' => 0,
+ 'orderby' => 'referred_at',
+ 'order' => 'DESC'
+ ];
+
+ $args = wp_parse_args($args, $defaults);
+
+ return $this->requestCache->remember(
+ $this->requestCache->generateKey(array_merge(['user'=>$user_id], $args)),
function() use ($user_id, $args) {
- $defaults = [
- 'status' => 'all',
- 'limit' => 100,
- 'offset' => 0,
- 'orderby' => 'referred_at',
- 'order' => 'DESC'
- ];
-
- $args = wp_parse_args($args, $defaults);
-
$where = $this->wpdb->prepare("WHERE referrer_id = %d", $user_id);
if ($args['status'] !== 'all') {
@@ -569,37 +775,33 @@
*/
public function getUserStats(int $user_id): array
{
- $cache_key = 'stats_' . $user_id;
- $cached = $this->cache->get($cache_key);
-
- if ($cached !== false) {
- return $cached;
- }
-
- $stats = $this->wpdb->get_row($this->wpdb->prepare(
- "SELECT
+ return $this->statsCache->remember(
+ $user_id,
+ function() use ($user_id) {
+ $stats = $this->wpdb->get_row($this->wpdb->prepare(
+ "SELECT
COUNT(*) as code_used,
SUM(CASE WHEN status IN ('consulted', 'treated') THEN 1 ELSE 0 END) as consultations,
SUM(CASE WHEN status = 'treated' THEN 1 ELSE 0 END) as treatments,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending
FROM {$this->referrals_table}
WHERE referrer_id = %d",
- $user_id
- ), ARRAY_A);
+ $user_id
+ ), ARRAY_A);
- // Get total rewards earned (available + redeemed)
- $rewards = $this->wpdb->get_var($this->wpdb->prepare(
- "SELECT SUM(amount)
+ // Get total rewards earned (available + redeemed)
+ $rewards = $this->wpdb->get_var($this->wpdb->prepare(
+ "SELECT SUM(amount)
FROM {$this->rewards_table}
WHERE user_id = %d AND reward_type = 'referrer'",
- $user_id
- ));
+ $user_id
+ ));
- $stats['total_rewards'] = floatval($rewards ?? 0);
- $stats['user_id'] = $user_id;
- $this->cache->set($cache_key, $stats, HOUR_IN_SECONDS);
-
- return $stats;
+ $stats['total_rewards'] = floatval($rewards ?? 0);
+ $stats['user_id'] = $user_id;
+ return $stats;
+ }
+ );
}
/**
@@ -611,20 +813,23 @@
*/
public function getTopReferrers(int $limit = 10, string $period = 'all'): array
{
- $where = '';
+ return $this->statsCache->remember(
+ $this->statsCache->generateKey(['limit'=>$limit, 'period' => $period]),
+ function() use ($limit, $period) {
+ $where = '';
- if ($period !== 'all') {
- $date_where = match($period) {
- 'day' => "referred_at >= DATE_SUB(NOW(), INTERVAL 1 DAY)",
- 'week' => "referred_at >= DATE_SUB(NOW(), INTERVAL 1 WEEK)",
- 'month' => "referred_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)",
- default => "1=1"
- };
+ if ($period !== 'all') {
+ $date_where = match($period) {
+ 'day' => "referred_at >= DATE_SUB(NOW(), INTERVAL 1 DAY)",
+ 'week' => "referred_at >= DATE_SUB(NOW(), INTERVAL 1 WEEK)",
+ 'month' => "referred_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)",
+ default => "1=1"
+ };
- $where = "WHERE {$date_where}";
- }
+ $where = "WHERE {$date_where}";
+ }
- $query = "SELECT
+ $query = "SELECT
referrer_id,
COUNT(*) as referral_count,
SUM(CASE WHEN status = 'treated' THEN 1 ELSE 0 END) as treated_count
@@ -634,16 +839,19 @@
ORDER BY referral_count DESC
LIMIT {$limit}";
- $results = $this->wpdb->get_results($query);
+ $results = $this->wpdb->get_results($query);
- // Enrich with user data
- foreach ($results as &$result) {
- $user = get_user_by('ID', $result->referrer_id);
- $result->user_name = $user ? $user->display_name : 'Unknown';
- $result->user_email = $user ? $user->user_email : '';
- }
+ // Enrich with user data
+ foreach ($results as &$result) {
+ $user = get_user_by('ID', $result->referrer_id);
+ $result->user_name = $user ? $user->display_name : 'Unknown';
+ $result->user_email = $user ? $user->user_email : '';
+ }
- return $results;
+ return $results;
+ }
+ );
+
}
/**
@@ -653,11 +861,8 @@
{
$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
@@ -665,48 +870,46 @@
$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');
}
/**
@@ -717,19 +920,50 @@
$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');
}
/**
@@ -740,69 +974,30 @@
*/
protected function generateCSV(array $referrals): string
{
- $csv = "Referred By,Referee Name,Referee Email,Referee Phone,Referral Code,Status,Referred At,Treated At\n";
+ $cache = Cache::for('referralCSV', HOUR_IN_SECONDS)->connect('referrals');
+ return $cache->remember(
+ 'csv',
+ function () use ($referrals) {
+ $csv = "Referred By,Referee Name,Referee Email,Referee Phone,Referral Code,Status,Referred At,Treated At\n";
- foreach ($referrals as $referral) {
- $csv .= sprintf(
- '"%s","%s","%s","%s","%s","%s","%s","%s"' . "\n",
- $referral->referrer_name ?? 'Unknown',
- $referral->referee_name,
- $referral->referee_email,
- $referral->referee_phone,
- $referral->referral_code,
- $referral->status,
- $referral->referred_at,
- $referral->treated_at ?? 'Not yet'
- );
- }
+ foreach ($referrals as $referral) {
+ $csv .= sprintf(
+ '"%s","%s","%s","%s","%s","%s","%s","%s"' . "\n",
+ $referral->referrer_name ?? 'Unknown',
+ $referral->referee_name,
+ $referral->referee_email,
+ $referral->referee_phone,
+ $referral->referral_code,
+ $referral->status,
+ $referral->referred_at,
+ $referral->treated_at ?? 'Not yet'
+ );
+ }
- return $csv;
- }
-
- /**
- * 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' : ''
+ return $csv;
+ }
);
- $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');
}
/**
@@ -820,31 +1015,22 @@
$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;
}
/**
@@ -1060,7 +1246,6 @@
JVB()->connect('cloudflare')->renderTurnstile();
$turnstile = ob_get_clean();
- $meta = new MetaForm();
$reward_text = $this->getRewardText(true);
// Pre-fill code if from referral link
@@ -1071,29 +1256,55 @@
$referrer_name = $referrer ? strtok($referrer->display_name, ' ') : '';
}
- $codeForm = '<div class="referral-reward-banner">
- '.jvbIcon('confetti').'
- <h4>Get ' . esc_html($reward_text) . '!</h4>
- ' . ($referrer_name ? '<p>' . esc_html($referrer_name) . ' invited you to join us</p>' : '') . '
- </div>
- <form id="referral-code-form">
- '.jvbFormStatus(). '
- <input type="hidden" name="user_select" value="' . esc_attr(get_option(BASE.'referral_role','client')) . '">
- ' .$meta->return('referral_name', null, [
+ $header = sprintf(
+ '<header><h2>%sGet %s.</h2></header><h3>Have a code?</h3>%s<p>Enter your referral code to get started!</p>',
+ jvbIcon('confetti'),
+ esc_html($reward_text),
+ ($referrer_name ? '<p>' . esc_html($referrer_name) . ' invited you to join us</p>' : '')
+ );
+
+ $codeForm = sprintf(
+ '<form id="referral-code-form">
+ %s
+ <input type="hidden" name="user_select" value="%s">
+ %s%s%s%s
+ <div class="row">
+ <button type="button" class="button-secondary check-code-btn">
+ %s Verify Code
+ </button>
+ <button type="submit">
+ Get Started
+ </button>
+ </div>
+
+ <div class="code-status" hidden></div>
+
+ <p class="hint">
+ We\'ll send you a link to complete your registration.
+ </p>
+ </form>
+ <div class="success-content" hidden>
+ <h3>Check Your Email!</h3>
+ <p>We\'ve sent you a magic link to complete your registration. Click the link to activate your account and claim your reward!</p>
+ <p class="hint">Can\'t find it? Check your spam folder.</p>
+ </div>',
+ jvbFormStatus(),
+ esc_attr(get_option(BASE.'referral_role','client')),
+ Form::render('referral_name', '', [
'required' => true,
'type' => 'text',
'label' => 'Your Name',
'placeholder'=> 'Mister Meeseeks',
'autocomplete'=>'name'
- ]).
- $meta->return('referral_email', null, [
+ ]),
+ Form::render('referral_email', '', [
'required' => true,
'type' => 'email',
'label' => 'Your Email',
'placeholder'=> 'look@me.com',
'autocomplete'=> 'email'
- ]).
- $meta->return('referral_code', $prefill_code, [
+ ]),
+ Form::render('referral_code', $prefill_code, [
'required' => true,
'type' => 'text',
'label' => 'Referral Code',
@@ -1101,54 +1312,53 @@
'maxLength' => 20,
'autocomplete'=>'off',
'data-referrer' => $referrer_name
- ]).'
- <button type="button" class="button-secondary check-code-btn">
- '.jvbIcon('check-circle', ['size' => 16]).' Verify Code
- </button>
- <div class="code-status" hidden></div>
- <button type="submit">
- Get Started
- </button>
+ ]),
+ $turnstile,
+ jvbIcon('check-circle')
+ );
- <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>
- <p>We\'ve sent you a magic link to complete your registration. Click the link to activate your account and claim your reward!</p>
- <p class="hint">Can\'t find it? Check your spam folder.</p>
- </div>';
+ $loginHeader = sprintf(
+ '<header><h2>%sLogin</h2></header><p>Already have an account?<br>Log in to see your rewards!</p>',
+ jvbIcon('sign-in')
+ );
+ $loginForm = sprintf(
+ '<form id="login-form">%s%s%s
+ <button type="submit">%sLogin With Magic Link</button>
+ </form>
+ <div class="success-content" hidden>
+ <h3>Check Your Email!</h3>
+ <p>We\'ve sent you a magic link to log in - no password required! Click the link in your email to log in.</p>
+ <p class="hint">Can\'t find it? Check your spam folder.</p>
+ </div>',
+ jvbFormStatus(),
+ Form::render('login_email', null, [
+ 'required' => true,
+ 'type' => 'email',
+ 'label' => 'Your Email',
+ 'autocomplete'=>'email'
+ ]),
+ $turnstile,
+ jvbIcon('magic-wand')
+ );
- $loginForm = '<form id="login-form">
- '.jvbFormStatus().$meta->return('login_email', null, [
- 'required' => true,
- 'type' => 'email',
- 'label' => 'Your Email',
- 'autocomplete'=>'email'
- ]).'
- '.$turnstile.'
- <button type="submit">Login With Magic Link</button>
-</form>
-<div class="success-content" hidden>
- <h3>Check Your Email!</h3>
- <p>We\'ve sent you a magic link to log in - no password required! Click the link in your email to log in.</p>
- <p class="hint">Can\'t find it? Check your spam folder.</p>
-</div>';
- $footer = '<div class="referral-footer">
- <a href="' . wp_login_url() . '" class="text-link">Prefer to use a password?</a>
- </div>';
+ $footer = sprintf(
+ '<p class="hint">
+ <a href="%s" class="text-link">Prefer to use a password?</a>
+ </p>',
+ wp_login_url()
+ );
$tabs = [
'enterCode' => [
'title' => 'Have a Code?',
'description' => [
'Enter your referral code to get started'
],
+ 'header' => $header,
'content' => $codeForm
],
'login' => [
+ 'header' => $loginHeader,
'title' => 'Login',
'description' => [
'Already have an account? Log in to see your rewards'
@@ -1214,13 +1424,14 @@
public function getLoggedInReferral(int $user_id): string
{
$referral_code = $this->getUserReferralCode($user_id);
- if (is_wp_error($referral_code)) {
+ if (!$referral_code) {
return '';
}
$share_url = $this->getShareURL($referral_code);
ob_start();
?>
+ <div class="wrap">
<header>
<h3>Share the ♡</h3>
<p>Invite friends. Earn rewards.</p>
@@ -1228,12 +1439,13 @@
<?php $this->getShareButtons($user_id); ?>
- <div class="copy-section">
+ <section class="copy">
<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>
@@ -1242,45 +1454,46 @@
<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>
- </div>
+ </section>
- <div class="recent-referrals-section">
+ <section class="recent-referrals">
<h4>Recent Referrals</h4>
<div class="recent-referrals-list" data-user-id="<?= $user_id ?>">
<div class="loading">Loading...</div>
</div>
- </div>
+ </section>
- <div class="stats-summary">
- <div class="stat-row">
+ <section class="stats-summary">
+ <div class="row btw">
<span class="stat-label">Total Referrals</span>
<span class="stat-value" data-stat="total">-</span>
</div>
- <div class="stat-row">
+ <div class="row btw">
<span class="stat-label">Successful</span>
<span class="stat-value" data-stat="treated">-</span>
</div>
- <div class="stat-row">
+ <div class="row btw">
<span class="stat-label">Pending</span>
<span class="stat-value" data-stat="pending">-</span>
</div>
- <div class="stat-row highlight">
+ <div class="row btw highlight">
<span class="stat-label">Available Rewards</span>
<span class="stat-value" data-stat="rewards">$0.00</span>
</div>
- </div>
+ </section>
<a href="<?= get_home_url(null, '/dash/referrals')?>" class="view-dashboard-btn">
Dashboard <?= jvbIcon('arrow-right', ['size' => 16]); ?>
</a>
<p class="hint">Bulk-invite your friends via email - the link will pre-fill their name, email, and code!</p>
-
+ </div>
<?php
return ob_get_clean();
}
@@ -1311,7 +1524,7 @@
$code = $this->getUserReferralCode($user->ID);
$yourCode = '';
- if (!is_wp_error($code)) {
+ if ($code) {
$share_url = $this->getShareURL($code);
$yourCode = sprintf(
'<div class="callout">
@@ -1373,7 +1586,7 @@
$referrer = get_user_by('ID', $user_id);
$referral_code = $this->getUserReferralCode($user_id);
- if (is_wp_error($referral_code)) {
+ if ($referral_code) {
return $referral_code;
}
@@ -2438,10 +2651,11 @@
// Regular users get their referral dashboard
$user_id = get_current_user_id();
- $referral_code = get_user_meta($user_id, BASE . 'referral_code', true);
+ $referral_code = $this->getUserReferralCode($user_id);
if (!$referral_code) {
- $referral_code = $this->getUserReferralCode($user_id);
+ $user = get_userdata($user_id);
+ $referral_code = $this->generateReferralCode($user);
}
$referrals = $this->getUserReferrals($user_id, ['limit' => 20]);
@@ -2475,36 +2689,36 @@
<?php $this->getShareButtons($user_id); ?>
<!-- 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>
+ <details open>
+ <summary>Your Code</summary>
<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>
- </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>
+ </details>
<form class="invite">
<h2>Invite your Friends</h2>
<p>Or, if you prefer, enter your friends name(s) and email(s), and we'll send off some emails.</p>
<p><small>(No data is stored. Your friends will get an email from our email.)</small></p>
<?php
- $meta = new MetaForm();
$invite = [
- 'type' => 'tag_list',
+ 'type' => 'taglist',
'label' => 'Invite Your Friends',
'hint' => 'Add friends to send them a referral link',
'add_label' => 'Add Invite',
- 'tag_format' => '{name} ({email})', // or 'first_field', 'all_fields', 'email', etc.
+ 'tag_format' => '{{name}} ({{email}})', // or 'first_field', 'all_fields', 'email', etc.
'fields' => [
'name' => [
'type' => 'text',
@@ -2535,14 +2749,14 @@
'hint' => 'We\'ll add your code and a link automatically.'
]
];
- $meta->render('invite', [], $invite);
+ echo Form::render('invite', '', $invite);
?>
<details>
<summary class="icon icon-caret-down">Customize Message</summary>
<?php
foreach ($fields as $fieldName => $field) {
$value = (array_key_exists('value', $field)) ? $field['value'] : [];
- $meta->render($fieldName, $value, $field);
+ echo Form::render($fieldName, $value, $field);
}
?>
</details>
@@ -2582,7 +2796,7 @@
$crud = new CRUDSkeleton();
$crud->title('Your Referrals', 'Track friends you\'ve invited and rewards earned')
->content('referral', 'Referral', 'Referrals')
- ->initMeta('custom', 'referral')
+// ->initMeta('custom', 'referral')
->setFields([
'referee_name' => [
'label' => 'Name',
@@ -2657,7 +2871,7 @@
update_option(BASE . 'referral_page_id', $page_id);
// Save client import role
- $import_role = sanitize_text_field($post_data[BASE . 'referral_role'] ?? JVB_USER);
+ $import_role = sanitize_text_field($post_data[BASE . 'referral_role'] ?? Site::getDefaultReferralRole());
update_option(BASE . 'referral_role', $import_role);
// Save reward settings
@@ -2710,7 +2924,7 @@
public function getShareButtons(int $user_id):void
{
$referral_code = $this->getUserReferralCode($user_id);
- if (is_wp_error($referral_code)) {
+ if (!$referral_code) {
return;
}
@@ -2726,7 +2940,7 @@
?>
<nav class="share">
<h4>Quick Share</h4>
- <ul class="share-buttons-grid">
+ <ul>
<a href="mailto:?subject=<?php echo urlencode('Check out ' . get_bloginfo('name')); ?>&body=<?php echo urlencode($share_message . ' ' . $share_url); ?>"
class="button" title="Email">
<?php echo jvbIcon('envelope'); ?>
@@ -2812,7 +3026,7 @@
$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'));
--
Gitblit v1.10.0