From e9967fa22781d922ba4eb8fb44fe72d200ac4b14 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 10 Nov 2025 21:04:10 +0000
Subject: [PATCH] =IconsManager.php update

---
 inc/rest/routes/ReferralRoutes.php |  383 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 362 insertions(+), 21 deletions(-)

diff --git a/inc/rest/routes/ReferralRoutes.php b/inc/rest/routes/ReferralRoutes.php
index d7f097f..15f293e 100644
--- a/inc/rest/routes/ReferralRoutes.php
+++ b/inc/rest/routes/ReferralRoutes.php
@@ -1,6 +1,7 @@
 <?php
 namespace JVBase\rest\routes;
 
+use JVBase\managers\ReferralManager;
 use JVBase\rest\RestRouteManager;
 use WP_REST_Request;
 use WP_REST_Response;
@@ -15,7 +16,7 @@
  */
 class ReferralRoutes extends RestRouteManager
 {
-
+	protected ReferralManager $manager;
 	public function __construct()
 	{
 		$this->route = 'referrals';
@@ -31,6 +32,49 @@
 			'permission_callback' => [$this, 'checkPermission']
 		]);
 
+		register_rest_route($this->namespace, "/{$this->route}/register", [
+			'methods' => 'POST',
+			'callback' => [$this, 'registerWithReferral'],
+			'permission_callback' => [$this, 'checkRateLimit'],
+			'args' => [
+				'name' => [
+					'required' => true,
+					'type' => 'string',
+					'sanitize_callback' => 'sanitize_text_field'
+				],
+				'email' => [
+					'required' => true,
+					'type' => 'string',
+					'format' => 'email',
+					'validate_callback' => function($param) {
+						return is_email($param);
+					}
+				],
+				'code' => [
+					'required' => true,
+					'type' => 'string',
+					'sanitize_callback' => function($code) {
+						return strtoupper(sanitize_text_field($code));
+					}
+				]
+			]
+		]);
+
+		register_rest_route($this->namespace, '/referrals/check-code', [
+			'methods' => 'POST',
+			'callback' => [$this, 'checkReferralCode'],
+			'permission_callback' => [$this, 'checkRateLimit'],
+			'args' => [
+				'code' => [
+					'required' => true,
+					'type' => 'string',
+					'sanitize_callback' => function($code) {
+						return strtoupper(sanitize_text_field($code));
+					}
+				]
+			]
+		]);
+
 		// Get or create referral code
 		register_rest_route($this->namespace, "/{$this->route}/code", [
 			'methods' => 'GET',
@@ -38,27 +82,11 @@
 			'permission_callback' => [$this, 'checkPermission']
 		]);
 
-		// Update referral code
-		register_rest_route($this->namespace, "/{$this->route}/code", [
-			'methods' => 'POST',
-			'callback' => [$this, 'updateReferralCode'],
-			'permission_callback' => [$this, 'checkPermission'],
-			'args' => [
-				'code' => [
-					'required' => true,
-					'type' => 'string',
-					'validate_callback' => function($param) {
-						return preg_match('/^[A-Z0-9]+$/i', $param);
-					}
-				]
-			]
-		]);
-
 		// Track referral click (public endpoint)
 		register_rest_route($this->namespace, "/{$this->route}/track", [
 			'methods' => 'POST',
 			'callback' => [$this, 'trackReferralClick'],
-			'permission_callback' => '__return_true',
+			'permission_callback' => [$this, 'checkRateLimit'],
 			'args' => [
 				'code' => [
 					'required' => true,
@@ -84,13 +112,78 @@
 			]
 		]);
 
-		// Get user stats
-		register_rest_route($this->namespace, "/{$this->route}/stats", [
+		// Send referral invitation
+		register_rest_route($this->namespace, '/'.$this->route.'/invite', [
+			'methods' => 'POST',
+			'callback' => [$this, 'sendInvitation'],
+			'permission_callback' => [$this, 'checkPermission'],
+			'args' => [
+				'email' => [
+					'required' => true,
+					'type' => 'string',
+					'format' => 'email',
+					'validate_callback' => function($param) {
+						return is_email($param);
+					}
+				],
+				'name' => [
+					'required' => true,
+					'type' => 'string',
+					'sanitize_callback' => 'sanitize_text_field'
+				]
+			]
+		]);
+
+		// Send batch invitations
+		register_rest_route($this->namespace, '/'.$this->route.'/invite/batch', [
+			'methods' => 'POST',
+			'callback' => [$this, 'sendBatchInvitations'],
+			'permission_callback' => [$this, 'checkPermission'],
+			'args' => [
+				'invitations' => [
+					'required' => true,
+					'type' => 'array',
+					'validate_callback' => function($param) {
+						return is_array($param) && !empty($param);
+					}
+				]
+			]
+		]);
+
+		// Get invitation stats for current user
+		register_rest_route($this->namespace, '/'.$this->route.'/invite/stats', [
 			'methods' => 'GET',
-			'callback' => [$this, 'getUserStats'],
+			'callback' => [$this, 'getInvitationStats'],
 			'permission_callback' => [$this, 'checkPermission']
 		]);
 
+		// Export referrals for Jane App
+		register_rest_route($this->namespace, '/'.$this->route.'/export', [
+			'methods' => 'POST',
+			'callback' => [$this, 'exportReferrals'],
+			'permission_callback' => function() {
+				return current_user_can('manage_options');
+			},
+			'args' => [
+				'start_date' => [
+					'required' => true,
+					'type' => 'string',
+					'validate_callback' => function($param) {
+						return (bool) strtotime($param);
+					}
+				],
+				'end_date' => [
+					'required' => true,
+					'type' => 'string',
+					'validate_callback' => function($param) {
+						return (bool) strtotime($param);
+					}
+				]
+			]
+		]);
+
+
+
 		// Get top referrers (admin only)
 		register_rest_route($this->namespace, "/{$this->route}/leaderboard", [
 			'methods' => 'GET',
@@ -127,6 +220,21 @@
 				}
 			]
 		]);
+
+		register_rest_route($this->namespace, "/{$this->route}/add-code", [
+			'methods' 	=> 'POST',
+			'callback'	=> [$this, 'addReferralCodeAfterRegistration'],
+			'permission_callback'	=> [$this, 'checkRateLimit'],
+			'args'	=> [
+				'code'	=> [
+					'required'	=> true,
+					'type'		=> 'string',
+					'sanitize_callback'	=> function ($code) {
+						return strtoupper(sanitize_text_field($code));
+					}
+				]
+			]
+		]);
 	}
 
 	public function checkPermission(WP_REST_Request $request): bool
@@ -310,4 +418,237 @@
 			'settings' => $settings
 		]);
 	}
+
+	/**
+	 * Send a single referral invitation
+	 *
+	 * @param WP_REST_Request $request
+	 * @return WP_REST_Response
+	 */
+	public function sendInvitation(WP_REST_Request $request): WP_REST_Response
+	{
+		$user_id = get_current_user_id();
+		$email = sanitize_email($request->get_param('email'));
+		$name = sanitize_text_field($request->get_param('name'));
+
+		// Send invitation via ReferralManager
+		$referral_manager = JVB()->referrals();
+		$result = $referral_manager->sendReferralInvitation($user_id, $email, $name);
+
+		if (is_wp_error($result)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => $result->get_error_message(),
+				'code' => $result->get_error_code()
+			], 400);
+		}
+
+		return new WP_REST_Response($result, 200);
+	}
+
+	/**
+	 * Send batch referral invitations
+	 *
+	 * @param WP_REST_Request $request
+	 * @return WP_REST_Response
+	 */
+	public function sendBatchInvitations(WP_REST_Request $request): WP_REST_Response
+	{
+		$user_id = get_current_user_id();
+		$invitations = $request->get_param('invitations');
+
+		// Validate invitation format
+		foreach ($invitations as $invite) {
+			if (empty($invite['email']) || empty($invite['name'])) {
+				return new WP_REST_Response([
+					'success' => false,
+					'message' => 'Each invitation must have email and name'
+				], 400);
+			}
+		}
+
+		// Send batch via ReferralManager
+		$referral_manager = JVB()->referrals();
+		$result = $referral_manager->sendBatchReferralInvitations($user_id, $invitations);
+
+		return new WP_REST_Response($result, 200);
+	}
+
+	/**
+	 * Get invitation stats for current user
+	 *
+	 * @param WP_REST_Request $request
+	 * @return WP_REST_Response
+	 */
+	public function getInvitationStats(WP_REST_Request $request): WP_REST_Response
+	{
+		$user_id = get_current_user_id();
+
+		$referral_manager = JVB()->referrals();
+		$stats = $referral_manager->getUserInvitationStats($user_id);
+
+		return new WP_REST_Response([
+			'success' => true,
+			'stats' => $stats
+		], 200);
+	}
+
+	/**
+	 * Export referrals for Jane App cross-reference
+	 * Admin only
+	 *
+	 * @param WP_REST_Request $request
+	 * @return WP_REST_Response
+	 */
+	public function exportReferrals(WP_REST_Request $request): WP_REST_Response
+	{
+		$start_date = sanitize_text_field($request->get_param('start_date'));
+		$end_date = sanitize_text_field($request->get_param('end_date'));
+
+		$referral_manager = JVB()->referrals();
+		$csv_content = $referral_manager->exportReferrals($start_date, $end_date);
+
+		// Return CSV for download
+		return new WP_REST_Response([
+			'success' => true,
+			'csv' => $csv_content,
+			'filename' => sprintf('referrals_%s_to_%s.csv', $start_date, $end_date)
+		], 200);
+	}
+
+	public function registerWithReferral(WP_REST_Request $request): WP_REST_Response
+	{
+		$name = sanitize_text_field($request->get_param('name'));
+		$email = sanitize_email($request->get_param('email'));
+		$code = strtoupper(sanitize_text_field($request->get_param('code')));
+
+		// Validate email
+		if (!is_email($email)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Invalid email address'
+			], 400);
+		}
+
+		// Check if user exists
+		if (email_exists($email)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'An account with this email already exists'
+			], 400);
+		}
+
+		// Validate referral code
+		$referral_manager = JVB()->referrals();
+		$referrer = $referral_manager->getUserByReferralCode($code);
+
+		if (!$referrer) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Invalid referral code'
+			], 404);
+		}
+
+		// Get reward text
+		$settings = $referral_manager->getRewardSettings();
+		$reward_amount = $settings['referee_reward_amount'] ?? 20;
+		$reward_type = $settings['referee_reward_type'] ?? 'percentage';
+		$reward_text = $reward_type === 'percentage'
+			? "{$reward_amount}% off your first treatment!"
+			: "\${$reward_amount} off your first treatment!";
+
+		// Send magic link with referral context via MagicLinkManager
+		$magic_link_manager = new \JVBase\managers\MagicLinkManager();
+
+		$result = $magic_link_manager->sendMagicLink(
+			$email,
+			\JVBase\managers\MagicLinkManager::TYPE_REFERRAL,
+			[
+				'name' => $name,
+				'referral_code' => $code,
+				'referrer_id' => $referrer->ID,
+				'referrer_name' => $referrer->display_name,
+				'reward_text' => $reward_text
+			]
+		);
+
+		if (is_wp_error($result)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Failed to send registration link. Please try again.'
+			], 500);
+		}
+
+		return new WP_REST_Response([
+			'success' => true,
+			'message' => 'Check your email! We sent you a link to complete your registration.',
+			'email' => $email
+		], 200);
+	}
+
+	public function checkReferralCode(WP_REST_Request $request): WP_REST_Response
+	{
+		$code = strtoupper(sanitize_text_field($request->get_param('code')));
+
+		if (empty($code)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Code is required'
+			], 400);
+		}
+
+		$referral_manager = JVB()->referrals();
+		$referrer = $referral_manager->getUserByReferralCode($code);
+
+		if (!$referrer) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Invalid referral code'
+			], 404);
+		}
+		if (is_user_logged_in() && get_current_user_id() === $referrer->ID) {
+			return $this->error('You cannot use your own referral code', 'self_referral', 400);
+		}
+
+		// Return basic referrer info (no sensitive data)
+		return new WP_REST_Response([
+			'success' => true,
+			'code' => $code,
+			'referrer_name' => $referrer->display_name,
+		], 200);
+	}
+
+	public function addReferralCodePostRegistration(WP_REST_Request $request): WP_REST_Response
+	{
+		if (!$this->manager) {
+			$this->manager = JVB()->referrals();
+		}
+		$user_id = get_current_user_id();
+		$code = $request->get_param('code');
+
+		// Check if user already has a referral (can't change)
+		$existing = $this->manager->getReferralByReferee($user_id);
+		if ($existing) {
+			return $this->error('You already have a referral code applied', 'already_referred', 400);
+		}
+
+		// Validate the code exists
+		$referrer = $this->manager->getUserByReferralCode($code);
+		if (!$referrer) {
+			return $this->error('Invalid referral code', 'invalid_code', 400);
+		}
+
+		// Create the referral
+		$user = wp_get_current_user();
+		$result = $this->manager->createReferral($referrer->ID, $user_id, $code);
+
+		if ($result) {
+			return $this->success([
+				'message' => 'Referral code applied successfully!',
+				'referrer_name' => $referrer->display_name
+			]);
+		}
+
+		return $this->error('Failed to apply referral code', 'creation_failed', 500);
+	}
 }

--
Gitblit v1.10.0