redirectToLogin('Session expired. Please log in again.'); } try { $db = new Database(); $pdo = $db->getConnection(); } catch (Exception $e) { logError('DB failed: ' . $e->getMessage()); die('System error.'); } // Award onboarding points if (!$user['onboarding_points_awarded']) { try { $pdo->beginTransaction(); $pdo->prepare("INSERT INTO user_points (user_id, points, total_earned) VALUES (?, 10.00, 10.00) ON DUPLICATE KEY UPDATE points = points + 10.00, total_earned = total_earned + 10.00")->execute([$user['id']]); $pdo->prepare("INSERT INTO point_transactions (user_id, transaction_type, points, source, description) VALUES (?, 'earned', 10.00, 'onboarding', 'Welcome bonus for joining Relevant Reflex')")->execute([$user['id']]); $pdo->prepare("UPDATE users SET onboarding_points_awarded = 1 WHERE id = ?")->execute([$user['id']]); $pdo->commit(); $user = getCurrentUser(); } catch (Exception $e) { $pdo->rollback(); } } $userPoints = ['points' => 0, 'total_earned' => 0, 'total_redeemed' => 0]; try { $stmt = $pdo->prepare("SELECT points, total_earned, total_redeemed FROM user_points WHERE user_id = ?"); $stmt->execute([$user['id']]); $p = $stmt->fetch(); if ($p) $userPoints = $p; } catch (Exception $e) {} $profilerSections = ['personal_background'=>'Personal Background','household_family'=>'Household & Family','shopping_lifestyle'=>'Shopping & Lifestyle','technology_digital'=>'Technology & Digital','travel_transportation'=>'Travel & Transportation','health_fitness'=>'Health & Fitness','entertainment_media'=>'Entertainment & Media','food_dining'=>'Food & Dining','financial_services'=>'Financial Services','communication_payments'=>'Communication & Payments']; $profilerCompletion = []; try { $stmt = $pdo->prepare("SELECT section, completion_percentage, is_completed, points_awarded FROM profiler_completion WHERE user_id = ?"); $stmt->execute([$user['id']]); while ($row = $stmt->fetch()) $profilerCompletion[$row['section']] = $row; } catch (Exception $e) {} $completedSections = 0; foreach ($profilerSections as $k => $n) { if (isset($profilerCompletion[$k]) && $profilerCompletion[$k]['is_completed']) $completedSections++; } $mobileVerified = false; $mobileNumber = ''; try { $stmt = $pdo->prepare("SELECT mobile_number, is_verified FROM mobile_verifications WHERE user_id = ?"); $stmt->execute([$user['id']]); $md = $stmt->fetch(); if ($md) { $mobileVerified = $md['is_verified']; $mobileNumber = $md['mobile_number']; } } catch (Exception $e) {} $upiId = ''; try { $stmt = $pdo->prepare("SELECT response FROM user_profiler WHERE user_id = ? AND section = 'profile' AND question_id = 'upi_id'"); $stmt->execute([$user['id']]); $ud = $stmt->fetch(); if ($ud) $upiId = json_decode($ud['response'], true); } catch (Exception $e) {} if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'update_upi') { $newUpiId = isset($_POST['upi_id']) ? sanitize($_POST['upi_id']) : ''; if (!empty($newUpiId) && preg_match('/^[\w\.\-]+@[\w\.\-]+$/', $newUpiId)) { try { $stmt = $pdo->prepare("INSERT INTO user_profiler (user_id, section, question_id, response) VALUES (?, 'profile', 'upi_id', ?) ON DUPLICATE KEY UPDATE response = ?, updated_at = NOW()"); $j = json_encode($newUpiId); $stmt->execute([$user['id'], $j, $j]); $upiId = $newUpiId; $success_message = "UPI ID updated successfully!"; } catch (Exception $e) { $error_message = "Error updating UPI ID."; } } else { $error_message = "Please enter a valid UPI ID (e.g., yourname@paytm)."; } } $userTickets = []; try { $stmt = $pdo->prepare("SELECT st.*, (SELECT COUNT(*) FROM support_messages sm WHERE sm.ticket_id = st.id) as message_count, (SELECT sm.created_at FROM support_messages sm WHERE sm.ticket_id = st.id ORDER BY sm.created_at DESC LIMIT 1) as last_reply FROM support_tickets st WHERE st.user_id = ? ORDER BY st.created_at DESC LIMIT 10"); $stmt->execute([$user['id']]); $userTickets = $stmt->fetchAll(); } catch (Exception $e) {} $userRedemptions = []; try { $stmt = $pdo->prepare("SELECT * FROM redemption_requests WHERE user_id = ? ORDER BY created_at DESC LIMIT 5"); $stmt->execute([$user['id']]); $userRedemptions = $stmt->fetchAll(); } catch (Exception $e) {} // Survey history from shop DB $surveys = []; $surveyStats = ['total'=>0,'completes'=>0,'pending'=>0,'flagged'=>0]; try { $shopPdo = new PDO("mysql:host=localhost;dbname=u752449863_rrshop;charset=utf8mb4","u752449863_rradmin","S@n@h2016",[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC]); $cols = array_column($shopPdo->query("SHOW COLUMNS FROM survey_urls")->fetchAll(), 'Field'); $hasQF = in_array('quality_flag', $cols); $hasLoi = in_array('actual_loi_seconds', $cols); $hasCompAt = in_array('completed_at', $cols); $hasQN = in_array('quality_notes', $cols); $pcols = array_column($shopPdo->query("SHOW COLUMNS FROM projects")->fetchAll(), 'Field'); $hasCS = in_array('closure_status', $pcols); $hasSP = in_array('speedster_threshold_pct', $pcols); $qf = $hasQF ? "su.quality_flag" : "'valid' as quality_flag"; $qn = $hasQN ? "su.quality_notes" : "NULL as quality_notes"; $loi = $hasLoi ? "su.actual_loi_seconds" : "NULL as actual_loi_seconds"; $cat = $hasCompAt ? "su.completed_at" : "NULL as completed_at"; $cs = $hasCS ? "p.closure_status" : "'none' as closure_status"; $sp = $hasSP ? "p.speedster_threshold_pct" : "33.33 as speedster_threshold_pct"; $stmt = $shopPdo->prepare(" SELECT su.status as url_status, su.clicked_at, su.created_at as sent_at, $qf, $qn, $loi, $cat, p.project_id, p.project_name, p.eloi, p.industry, p.status as project_status, $cs, $sp FROM survey_urls su INNER JOIN projects p ON su.project_id = p.project_id WHERE su.sent_to_user_id = ? AND su.status NOT IN ('available') ORDER BY su.created_at DESC LIMIT 30 "); $stmt->execute([$user['id']]); $surveys = $stmt->fetchAll(); foreach ($surveys as $s) { $surveyStats['total']++; if ($s['url_status']==='complete') { $surveyStats['completes']++; $q=$s['quality_flag']??'valid'; if (in_array($q,['speedster','ip_duplicate','client_flagged'])) $surveyStats['flagged']++; elseif ($s['project_status']!=='Closed') $surveyStats['pending']++; } } } catch (Exception $e) { error_log("Survey stats: ".$e->getMessage()); } // Get survey-related point transactions from panel DB $surveyPointsByProject = []; try { $stmt = $pdo->prepare("SELECT reference_id, points, description, created_at FROM point_transactions WHERE user_id = ? AND source IN ('survey','survey_reward') AND transaction_type = 'earned' ORDER BY created_at DESC"); $stmt->execute([$user['id']]); while ($row = $stmt->fetch()) { if ($row['reference_id']) $surveyPointsByProject[$row['reference_id']] = $row; } } catch (Exception $e) {} // Get full rewards history for Rewards tab $rewardsHistory = []; try { $stmt = $pdo->prepare("SELECT transaction_type, points, source, description, reference_id, status, created_at FROM point_transactions WHERE user_id = ? ORDER BY created_at DESC LIMIT 50"); $stmt->execute([$user['id']]); $rewardsHistory = $stmt->fetchAll(); } catch (Exception $e) {} $joinDateFormatted = (new DateTime($user['created_at']))->format('M Y'); $profilePct = round(($completedSections / count($profilerSections)) * 100); $firstName = htmlspecialchars($user['first_name'] ?? explode('@',$user['email'])[0]); $initials = strtoupper(substr($user['first_name']??$user['email'],0,1).substr($user['last_name']??'',0,1)); if (strlen($initials)<2) $initials = strtoupper(substr($user['email'],0,2)); function getSurveyLabel($s) { $st=$s['url_status']; $qf=$s['quality_flag']??'valid'; $ps=$s['project_status']; if ($st==='sent') return ['Invited','label-neutral','Invitation sent. Click the survey link in your email to participate.']; if ($st==='clicked') return ['In Progress','label-warn','You started this survey but haven\'t completed it yet.']; if (in_array($st,['earlyscreenout','latescreenout'])) return ['Screened Out','label-neutral','You did not qualify based on screening criteria.']; if ($st==='quotafull') return ['Quota Full','label-neutral','The survey quota was filled before your response was recorded.']; if ($st==='timeout') return ['Timed Out','label-neutral','Session expired before completion.']; if ($st==='partial') return ['Partial','label-info','Your response was partially recorded.']; if ($st==='complete') { if (in_array($qf,['speedster','ip_duplicate','client_flagged'])) return ['Under Review','label-danger','Flagged for quality review. Points held pending admin decision.']; if ($ps==='Closed') return ['Approved','label-ok','Survey approved. Check Rewards tab for credited points.']; return ['Pending Approval','label-warn','Completed successfully. Points will credit when the project closes.']; } return [ucfirst($st),'label-neutral','']; } function fmtLoi($s){if(!$s)return'-';$m=floor($s/60);$ss=$s%60;return($m?$m.'m ':'').$ss.'s';} function fmtDt($d){if(!$d)return'-';return date('M d, Y g:i A',strtotime($d));} ?> Member Area - Relevant Reflex
Overview
pts

Welcome back, !

Complete your profile, earn points, and participate in paid surveys.

New to surveys? Read 3 essential rules before taking your first survey to protect your account and maximize rewards.
Available Points
value
Surveys Done
total
Profile
%
sections
Total Earned
Since
Complete Profile
Earn up to 50 points
Redeem Rewards
Convert points to cash
Get Help
Support & FAQs
⚠ Read This Before You Take Any Survey
3 essential rules to protect your account and earn maximum rewards
1
Take your time. Read every question carefully. There are no right or wrong answers — we want your genuine opinion. Think about each question and answer what you truly feel. Surveys that are rushed through too quickly get automatically flagged and your response may be rejected without reward.
2
One attempt per person, per device. Each survey can only be taken once from your IP address or device. Duplicate attempts are automatically detected and flagged. Do not try to retake a survey using a different browser, incognito mode, or VPN — it will be caught and may result in account action.
3
Do not straightline your responses. Straightlining means selecting the same answer option for every question in a row (e.g., choosing "Agree" for all statements). This is a well-known indicator of low-quality responses and is flagged by our system. Only select the same answer repeatedly if that genuinely reflects your opinion.
Why this matters: Research clients review every response for quality. Flagged responses (speeding, duplicates, or straightlining) are rejected and no points are awarded. Repeated violations may lead to fewer survey invitations or account restrictions.
Complete your profile for more surveys. done. Continue →
0):?>
Total
Completed
Pending
0?'Under Review':'Approved';?>
0?$surveyStats['flagged']:$surveyStats['completes']-$surveyStats['pending']-$surveyStats['flagged'];?>
How it works: Click any survey to see full details. Completed surveys are reviewed when the project closes. Points are credited once approved. "Under Review" means quality concerns (e.g., LOI below minimum threshold). = normal LOI, = slow, = below threshold.
Survey History
$s): list($lbl,$cls,$desc)=getSurveyLabel($s); $eloiSec = intval($s['eloi']??0)*60; $thPct = floatval($s['speedster_threshold_pct']??33.33); $thSec = $eloiSec>0 ? $eloiSec*($thPct/100) : 0; $aLoi = $s['actual_loi_seconds'] ? intval($s['actual_loi_seconds']) : null; $loiPct = ($eloiSec>0 && $aLoi) ? min(100,round(($aLoi/$eloiSec)*100)) : 0; $loiCls = 'loi-ok'; if ($aLoi && $thSec>0 && $aLoi<$thSec) $loiCls='loi-fast'; elseif ($loiPct>150) $loiCls='loi-slow'; $pts = $surveyPointsByProject[$s['project_id']] ?? null; $rewardTxt = '-'; if ($s['url_status']==='complete') { if ($pts) $rewardTxt = number_format($pts['points'],0).' pts (₹'.number_format($pts['points']*0.5,2).')'; elseif (($s['quality_flag']??'valid')!=='valid') $rewardTxt = 'Held for review'; elseif ($s['project_status']==='Closed') $rewardTxt = 'Awaiting credit'; else $rewardTxt = 'Pending project closure'; } ?>
· ·
Invited On
Started At
Completed At
Your LOI
Expected LOI
min
Min Required LOI
0 ? fmtLoi(round($thSec)).' ('.$thPct.'%)' : '-';?>
Project Status
Reward

No surveys yet.

📊

No Surveys Yet

Complete your profile to receive survey invitations.

Know Me Better

Each section = 5 points. Complete all for 50!

done
Mobile Verification
10 ptsVerify Now
$sn):$c=$profilerCompletion[$sk]??null;$d=$c&&$c['is_completed'];$pct=$c?$c['completion_percentage']:0;$pa=$c&&$c['points_awarded'];$ic=$d?'done':($pct>0?'part':'empty');?>
':round($pct).'%';?>
0?'In progress':'Not started');?>
5 pts0?'Continue':'Start');?>
Available
Total Earned
Redeemed
Redeem Points
=200 && !empty($upiId)):?>

Minimum: 200 points (₹100). Cash via UPI to

Redeem Now =200 && empty($upiId)):?>
You have crossed the minimum redemption amount but have not updated your UPI ID in the Profile section. Please add your UPI ID first.
Update UPI in Profile
Need 200 points (₹100) minimum. You have more needed.
Recent Redemptions
# · pts → ₹
to ·
Paid via · Ref: ·
Rewards History
No rewards yet. Complete your profile and participate in surveys to earn points!
pts
Account
Email
Gender
Date of Birth
Postcode
Status
Active Verified
Mobile
+91 verified
Not verified
Verify
UPI Details

For reward payments.

e.g. yourname@paytm, yourname@phonepe
UPI: