Project: RR com 02Apr26 Last Working Codes
ZIP File: Relevant Reflex Com.zip
Extracted on: 2026-04-02 17:18:09
Total Files: 181
================================================================================
FILE: Relevant Reflex Com/about.php
TYPE: PHP
SIZE: 19.68 KB
------------------------------------------------------------
About Us - Relevant Reflex | A Trusted Online Survey Platform in India
About Relevant Reflex
A trusted online survey platform in India, connecting consumers with market research opportunities since 2021.
Our Mission
At Relevant Reflex, we bridge the gap between Indian consumers and global market research companies. Our mission is to provide a trustworthy platform where your opinions matter and are fairly compensated.
We believe that every voice deserves to be heard, and every opinion has value. That's why we've created a secure, user-friendly platform that makes it easy for people across India to participate in market research and earn money for their time and insights.
Why We Started
Founded in 2021, Relevant Reflex was born out of the need for a reliable, India-focused survey platform. We saw too many people getting frustrated with unreliable survey sites that didn't pay or weren't relevant to the Indian market.
Our Impact in Numbers
Since our launch, we've grown into a trusted survey platform serving members across India
50,000+
Active Members
Registered users earning money with surveys
₹25,00,000+
Total Paid Out
Cumulative rewards paid to our members
2,50,000+
Surveys Completed
Successful survey completions by our members
98%
Satisfaction Rate
Members who recommend us to friends*
*Based on internal member survey, Q4 2024, n=500
Our Core Values
These principles guide everything we do at Relevant Reflex
Trust & Security
We protect your data with bank-level security and never share your personal information without consent. Your privacy is our priority.
Fair Compensation
Every survey you complete is fairly compensated. We ensure timely payments and transparent reward structures.
Member-Centric
Our members are at the center of everything we do. We continuously improve our platform based on your feedback.
Innovation
We're constantly evolving our platform with new features and better user experiences to serve you better.
Community
We've built more than a platform - we've built a community of engaged Indian consumers making their voices heard.
Local Focus
We understand the Indian market and provide surveys that are relevant to local consumers and culture.
Ready to Share Your Opinions?
Join thousands of Indians who are earning money with their valuable insights!
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking “Accept All”, you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/admin-auth.php
TYPE: PHP
SIZE: 48.39 KB
------------------------------------------------------------
pdo = $db->getConnection();
} catch (Exception $e) {
logError('Admin auth database connection failed: ' . $e->getMessage());
throw new Exception('Database connection failed');
}
}
/**
* Expose the PDO connection for shared use (e.g. attachment handler)
*/
public function getConnection() {
return $this->pdo;
}
public function login($username, $password, $rememberMe = false) {
try {
// Find admin user
$stmt = $this->pdo->prepare("
SELECT id, username, email, password, full_name, role, status,
COALESCE(allowed_tabs, 'all') as allowed_tabs,
COALESCE(allowed_ticket_types, 'all') as allowed_ticket_types
FROM admin_users
WHERE (username = ? OR email = ?) AND status = 'active'
");
$stmt->execute([$username, $username]);
$admin = $stmt->fetch();
if (!$admin || !verifyPassword($password, $admin['password'])) {
logError('Admin login failed', ['username' => $username]);
return false;
}
// Create session
session_start();
session_regenerate_id(true);
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_id'] = $admin['id'];
$_SESSION['admin_username'] = $admin['username'];
$_SESSION['admin_full_name'] = $admin['full_name'];
$_SESSION['admin_role'] = $admin['role'];
$_SESSION['admin_login_time'] = time();
// Permissions - super_admin always gets 'all'
$_SESSION['admin_allowed_tabs'] = ($admin['role'] === 'super_admin') ? 'all' : $admin['allowed_tabs'];
$_SESSION['admin_allowed_ticket_types'] = ($admin['role'] === 'super_admin') ? 'all' : $admin['allowed_ticket_types'];
// Update last login
$stmt = $this->pdo->prepare("UPDATE admin_users SET last_login = NOW() WHERE id = ?");
$stmt->execute([$admin['id']]);
// Handle remember me
if ($rememberMe) {
$token = generateSecureToken();
$expires = date('Y-m-d H:i:s', strtotime('+30 days'));
$stmt = $this->pdo->prepare("
INSERT INTO admin_sessions (admin_id, session_token, expires_at)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE session_token = ?, expires_at = ?
");
$stmt->execute([$admin['id'], $token, $expires, $token, $expires]);
setcookie('admin_remember_token', $token, strtotime('+30 days'), '/', '', true, true);
}
logError('Admin login successful', [
'admin_id' => $admin['id'],
'username' => $admin['username'],
'role' => $admin['role']
]);
return true;
} catch (Exception $e) {
logError('Admin login error', ['username' => $username, 'error' => $e->getMessage()]);
return false;
}
}
public function logout() {
session_start();
if (isset($_SESSION['admin_id'])) {
logError('Admin logout', ['admin_id' => $_SESSION['admin_id']]);
}
// Clear remember token
if (isset($_COOKIE['admin_remember_token'])) {
try {
$stmt = $this->pdo->prepare("DELETE FROM admin_sessions WHERE session_token = ?");
$stmt->execute([$_COOKIE['admin_remember_token']]);
} catch (Exception $e) {
logError('Error clearing admin remember token', ['error' => $e->getMessage()]);
}
setcookie('admin_remember_token', '', time() - 3600, '/', '', true, true);
}
// Clear session
$_SESSION = [];
session_destroy();
header('Location: support.php');
exit;
}
public function isLoggedIn() {
session_start();
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true) {
return true;
}
// Check remember me token
if (isset($_COOKIE['admin_remember_token'])) {
return $this->checkRememberToken($_COOKIE['admin_remember_token']);
}
return false;
}
private function checkRememberToken($token) {
try {
$stmt = $this->pdo->prepare("
SELECT au.id, au.username, au.full_name, au.role
FROM admin_sessions ass
JOIN admin_users au ON ass.admin_id = au.id
WHERE ass.session_token = ? AND ass.expires_at > NOW() AND au.status = 'active'
");
$stmt->execute([$token]);
$session = $stmt->fetch();
if ($session) {
// Restore session
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_id'] = $session['id'];
$_SESSION['admin_username'] = $session['username'];
$_SESSION['admin_full_name'] = $session['full_name'];
$_SESSION['admin_role'] = $session['role'];
$_SESSION['admin_login_time'] = time();
// Update last login
$stmt = $this->pdo->prepare("UPDATE admin_users SET last_login = NOW() WHERE id = ?");
$stmt->execute([$session['id']]);
return true;
} else {
// Invalid or expired token - delete it
setcookie('admin_remember_token', '', time() - 3600, '/', '', true, true);
}
} catch (Exception $e) {
logError('Error checking admin remember token', ['error' => $e->getMessage()]);
}
return false;
}
public function requireAdmin() {
if (!$this->isLoggedIn()) {
header('Location: support.php');
exit;
}
}
public function getCurrentAdmin() {
if (!$this->isLoggedIn()) {
return null;
}
session_start();
return [
'id' => $_SESSION['admin_id'],
'username' => $_SESSION['admin_username'],
'full_name' => $_SESSION['admin_full_name'],
'role' => $_SESSION['admin_role'],
'allowed_tabs' => $_SESSION['admin_allowed_tabs'] ?? 'all',
'allowed_ticket_types' => $_SESSION['admin_allowed_ticket_types'] ?? 'all'
];
}
/**
* Check if current admin has access to a specific tab
*/
public function hasTabAccess($tabName) {
$allowed = $_SESSION['admin_allowed_tabs'] ?? 'all';
if ($allowed === 'all' || $_SESSION['admin_role'] === 'super_admin') return true;
$tabs = array_map('trim', explode(',', $allowed));
return in_array($tabName, $tabs);
}
/**
* Get allowed ticket sender types for current admin
* Returns array like ['member','partner','client'] or ['all']
*/
public function getAllowedTicketTypes() {
$allowed = $_SESSION['admin_allowed_ticket_types'] ?? 'all';
if ($allowed === 'all' || $_SESSION['admin_role'] === 'super_admin') return ['all'];
return array_map('trim', explode(',', $allowed));
}
public function createAdmin($username, $email, $password, $fullName, $role = 'admin', $mobile = null, $allowedTabs = 'all', $allowedTicketTypes = 'all') {
try {
// Check if username or email already exists
$stmt = $this->pdo->prepare("SELECT id FROM admin_users WHERE username = ? OR email = ?");
$stmt->execute([$username, $email]);
if ($stmt->fetch()) {
return ['success' => false, 'message' => 'A user with this email already exists.'];
}
// Create admin user
$hashedPassword = hashPassword($password);
$stmt = $this->pdo->prepare("
INSERT INTO admin_users (username, email, password, full_name, mobile, role, allowed_tabs, allowed_ticket_types, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active')
");
$result = $stmt->execute([$username, $email, $hashedPassword, $fullName, $mobile, $role, $allowedTabs, $allowedTicketTypes]);
if ($result) {
logError('Admin user created', ['username' => $username, 'email' => $email, 'role' => $role]);
return ['success' => true, 'message' => 'User created successfully.', 'id' => $this->pdo->lastInsertId()];
}
return ['success' => false, 'message' => 'Failed to create user.'];
} catch (Exception $e) {
logError('Error creating admin user', ['username' => $username, 'error' => $e->getMessage()]);
return ['success' => false, 'message' => 'Database error: ' . $e->getMessage()];
}
}
/**
* Update an existing admin user
*/
public function updateAdmin($id, $fullName, $email, $mobile, $role, $allowedTabs, $allowedTicketTypes, $newPassword = null) {
try {
// Prevent editing super_admin role away from user ID 1
$stmt = $this->pdo->prepare("SELECT id, role FROM admin_users WHERE id = ?");
$stmt->execute([$id]);
$existing = $stmt->fetch();
if (!$existing) return ['success' => false, 'message' => 'User not found.'];
// Check email uniqueness (excluding current user)
$stmt = $this->pdo->prepare("SELECT id FROM admin_users WHERE email = ? AND id != ?");
$stmt->execute([$email, $id]);
if ($stmt->fetch()) return ['success' => false, 'message' => 'Email already in use by another user.'];
if ($newPassword) {
$hashed = hashPassword($newPassword);
$stmt = $this->pdo->prepare("
UPDATE admin_users SET full_name = ?, email = ?, username = ?, mobile = ?, role = ?,
allowed_tabs = ?, allowed_ticket_types = ?, password = ?, updated_at = NOW() WHERE id = ?
");
$stmt->execute([$fullName, $email, $email, $mobile, $role, $allowedTabs, $allowedTicketTypes, $hashed, $id]);
} else {
$stmt = $this->pdo->prepare("
UPDATE admin_users SET full_name = ?, email = ?, username = ?, mobile = ?, role = ?,
allowed_tabs = ?, allowed_ticket_types = ?, updated_at = NOW() WHERE id = ?
");
$stmt->execute([$fullName, $email, $email, $mobile, $role, $allowedTabs, $allowedTicketTypes, $id]);
}
logError('Admin user updated', ['admin_id' => $id, 'email' => $email]);
return ['success' => true, 'message' => 'User updated successfully.'];
} catch (Exception $e) {
logError('Error updating admin user', ['id' => $id, 'error' => $e->getMessage()]);
return ['success' => false, 'message' => 'Database error.'];
}
}
/**
* Toggle admin user active/inactive
*/
public function toggleAdminStatus($id) {
try {
$stmt = $this->pdo->prepare("UPDATE admin_users SET status = IF(status='active','inactive','active'), updated_at = NOW() WHERE id = ? AND id != 1");
$stmt->execute([$id]);
return $stmt->rowCount() > 0;
} catch (Exception $e) {
logError('Error toggling admin status', ['id' => $id, 'error' => $e->getMessage()]);
return false;
}
}
/**
* Get detailed admin user by ID
*/
public function getAdminById($id) {
try {
$stmt = $this->pdo->prepare("SELECT id, username, email, full_name, mobile, role, status, allowed_tabs, allowed_ticket_types, created_at, last_login FROM admin_users WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch();
} catch (Exception $e) { return null; }
}
/**
* Get all admin users with full details (for Users tab)
*/
public function getAllAdminUsersDetailed() {
try {
$stmt = $this->pdo->query("SELECT id, username, email, full_name, mobile, role, status, allowed_tabs, allowed_ticket_types, created_at, last_login FROM admin_users ORDER BY id ASC");
return $stmt->fetchAll();
} catch (Exception $e) {
logError('Error fetching admin users detailed', ['error' => $e->getMessage()]);
return [];
}
}
// SUPPORT TICKET METHODS
public function getAllTickets($status = null, $priority = null, $senderType = null, $limit = 50, $offset = 0, $allowedTypes = null) {
try {
$where = "1=1";
$params = [];
if ($status) {
$where .= " AND st.status = ?";
$params[] = $status;
}
if ($priority) {
$where .= " AND st.priority = ?";
$params[] = $priority;
}
if ($senderType) {
if ($senderType === 'member') {
$where .= " AND (st.sender_type = 'member' OR st.sender_type IS NULL)";
} else {
$where .= " AND st.sender_type = ?";
$params[] = $senderType;
}
}
// Permission-based sender_type restriction
if ($allowedTypes && !in_array('all', $allowedTypes)) {
$typePlaceholders = [];
foreach ($allowedTypes as $t) {
if ($t === 'member') {
$typePlaceholders[] = "(st.sender_type = 'member' OR st.sender_type IS NULL)";
} else {
$typePlaceholders[] = "st.sender_type = ?";
$params[] = $t;
}
}
$where .= " AND (" . implode(' OR ', $typePlaceholders) . ")";
}
$stmt = $this->pdo->prepare("
SELECT st.*,
u.email as user_email,
au.full_name as assigned_admin_name,
COALESCE(st.sender_type, 'member') as sender_type,
(SELECT COUNT(*) FROM support_messages sm WHERE sm.ticket_id = st.id) as message_count
FROM support_tickets st
LEFT JOIN users u ON st.user_id = u.id
LEFT JOIN admin_users au ON st.assigned_to = au.id
WHERE $where
ORDER BY st.created_at DESC
LIMIT $limit OFFSET $offset
");
$stmt->execute($params);
$tickets = $stmt->fetchAll();
// For partner tickets, fetch partner info from shop database
$partnerIds = [];
foreach ($tickets as $t) {
if ($t['sender_type'] === 'partner' && $t['sender_id']) {
$partnerIds[$t['sender_id']] = true;
}
}
if (!empty($partnerIds)) {
$partnerInfo = $this->getPartnerInfoFromShop(array_keys($partnerIds));
foreach ($tickets as &$t) {
if ($t['sender_type'] === 'partner' && isset($partnerInfo[$t['sender_id']])) {
$p = $partnerInfo[$t['sender_id']];
$t['partner_name'] = $p['company_name'];
$t['partner_code'] = $p['affiliate_code'];
if (empty($t['user_email'])) {
$t['user_email'] = $p['email'];
}
}
}
unset($t);
}
// For client tickets, fetch client info from shop database
$clientIds = [];
foreach ($tickets as $t) {
if ($t['sender_type'] === 'client' && $t['sender_id']) {
$clientIds[$t['sender_id']] = true;
}
}
if (!empty($clientIds)) {
$clientInfo = $this->getClientInfoFromShop(array_keys($clientIds));
foreach ($tickets as &$t) {
if ($t['sender_type'] === 'client' && isset($clientInfo[$t['sender_id']])) {
$c = $clientInfo[$t['sender_id']];
$t['client_name'] = $c['company_name'];
$t['client_code'] = $c['client_code'];
$t['client_contact'] = $c['contact_person'];
if (empty($t['user_email'])) {
$t['user_email'] = $c['email'];
}
}
}
unset($t);
}
return $tickets;
} catch (Exception $e) {
logError('Error fetching tickets', ['error' => $e->getMessage()]);
return [];
}
}
public function getTicketStats($allowedTypes = null) {
try {
$where = "1=1";
$params = [];
// Permission-based filtering
if ($allowedTypes && !in_array('all', $allowedTypes)) {
$typePlaceholders = [];
foreach ($allowedTypes as $t) {
if ($t === 'member') {
$typePlaceholders[] = "(sender_type = 'member' OR sender_type IS NULL)";
} else {
$typePlaceholders[] = "sender_type = ?";
$params[] = $t;
}
}
$where .= " AND (" . implode(' OR ', $typePlaceholders) . ")";
}
$stmt = $this->pdo->prepare("
SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'open' THEN 1 ELSE 0 END) as open,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
SUM(CASE WHEN status = 'resolved' THEN 1 ELSE 0 END) as resolved,
SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) as closed,
SUM(CASE WHEN sender_type = 'member' OR sender_type IS NULL THEN 1 ELSE 0 END) as member_tickets,
SUM(CASE WHEN sender_type = 'partner' THEN 1 ELSE 0 END) as partner_tickets,
SUM(CASE WHEN sender_type = 'client' THEN 1 ELSE 0 END) as client_tickets
FROM support_tickets
WHERE $where
");
$stmt->execute($params);
return $stmt->fetch();
} catch (Exception $e) {
logError('Error fetching ticket stats', ['error' => $e->getMessage()]);
return ['total' => 0, 'open' => 0, 'pending' => 0, 'resolved' => 0, 'closed' => 0, 'member_tickets' => 0, 'partner_tickets' => 0, 'client_tickets' => 0];
}
}
public function getTicketById($ticketId) {
try {
$stmt = $this->pdo->prepare("
SELECT st.*,
u.email as user_email, u.gender, u.date_of_birth, u.postcode,
au.full_name as assigned_admin_name,
COALESCE(st.sender_type, 'member') as sender_type
FROM support_tickets st
LEFT JOIN users u ON st.user_id = u.id
LEFT JOIN admin_users au ON st.assigned_to = au.id
WHERE st.id = ?
");
$stmt->execute([$ticketId]);
$ticket = $stmt->fetch();
// For partner tickets, fetch partner info from shop database
if ($ticket && $ticket['sender_type'] === 'partner' && $ticket['sender_id']) {
$partnerInfo = $this->getPartnerInfoFromShop([$ticket['sender_id']]);
if (isset($partnerInfo[$ticket['sender_id']])) {
$p = $partnerInfo[$ticket['sender_id']];
$ticket['partner_name'] = $p['company_name'];
$ticket['partner_code'] = $p['affiliate_code'];
$ticket['partner_incharge'] = $p['incharge_name'];
if (empty($ticket['user_email'])) {
$ticket['user_email'] = $p['email'];
}
}
}
// For client tickets, fetch client info from shop database
if ($ticket && $ticket['sender_type'] === 'client' && $ticket['sender_id']) {
$clientInfo = $this->getClientInfoFromShop([$ticket['sender_id']]);
if (isset($clientInfo[$ticket['sender_id']])) {
$c = $clientInfo[$ticket['sender_id']];
$ticket['client_name'] = $c['company_name'];
$ticket['client_code'] = $c['client_code'];
$ticket['client_contact'] = $c['contact_person'];
if (empty($ticket['user_email'])) {
$ticket['user_email'] = $c['email'];
}
}
}
return $ticket;
} catch (Exception $e) {
logError('Error fetching ticket', ['ticket_id' => $ticketId, 'error' => $e->getMessage()]);
return null;
}
}
public function getTicketMessages($ticketId, $includeInternal = false) {
try {
$where = $includeInternal ? "1=1" : "is_internal = 0";
$stmt = $this->pdo->prepare("
SELECT sm.*,
CASE
WHEN sm.sender_type = 'user' THEN u.email
WHEN sm.sender_type = 'admin' THEN au.full_name
END as sender_name
FROM support_messages sm
LEFT JOIN users u ON sm.sender_type = 'user' AND sm.sender_id = u.id
LEFT JOIN admin_users au ON sm.sender_type = 'admin' AND sm.sender_id = au.id
WHERE sm.ticket_id = ? AND $where
ORDER BY sm.created_at ASC
");
$stmt->execute([$ticketId]);
$messages = $stmt->fetchAll();
// For partner ticket messages where sender_name is NULL (partner sender_id not in users table)
// fetch partner info from shop database
$needsPartnerName = false;
foreach ($messages as $msg) {
if ($msg['sender_type'] === 'user' && empty($msg['sender_name'])) {
$needsPartnerName = true;
break;
}
}
if ($needsPartnerName) {
// Get ticket to find partner/client sender_id
$stmtT = $this->pdo->prepare("SELECT sender_type, sender_id FROM support_tickets WHERE id = ?");
$stmtT->execute([$ticketId]);
$ticket = $stmtT->fetch();
if ($ticket && $ticket['sender_type'] === 'partner' && $ticket['sender_id']) {
$partnerInfo = $this->getPartnerInfoFromShop([$ticket['sender_id']]);
$partnerName = isset($partnerInfo[$ticket['sender_id']]) ? $partnerInfo[$ticket['sender_id']]['company_name'] : 'Partner';
foreach ($messages as &$msg) {
if ($msg['sender_type'] === 'user' && empty($msg['sender_name'])) {
$msg['sender_name'] = $partnerName;
}
}
unset($msg);
}
// Client name resolution
if ($ticket && $ticket['sender_type'] === 'client' && $ticket['sender_id']) {
$clientInfo = $this->getClientInfoFromShop([$ticket['sender_id']]);
$clientName = isset($clientInfo[$ticket['sender_id']]) ? $clientInfo[$ticket['sender_id']]['company_name'] : 'Client';
foreach ($messages as &$msg) {
if ($msg['sender_type'] === 'user' && empty($msg['sender_name'])) {
$msg['sender_name'] = $clientName;
}
}
unset($msg);
}
}
return $messages;
} catch (Exception $e) {
logError('Error fetching ticket messages', ['ticket_id' => $ticketId, 'error' => $e->getMessage()]);
return [];
}
}
public function updateTicketStatus($ticketId, $status, $adminId) {
try {
$stmt = $this->pdo->prepare("
UPDATE support_tickets
SET status = ?, resolved_at = CASE WHEN ? = 'resolved' COLLATE utf8mb4_unicode_ci THEN NOW() ELSE resolved_at END
WHERE id = ?
");
$result = $stmt->execute([$status, $status, $ticketId]);
if ($result) {
logError('Ticket status updated', [
'ticket_id' => $ticketId,
'status' => $status,
'admin_id' => $adminId
]);
}
return $result;
} catch (Exception $e) {
logError('Error updating ticket status', ['ticket_id' => $ticketId, 'error' => $e->getMessage()]);
return false;
}
}
/**
* Fetch partner info from the shop database (affiliates table is in u752449863_rrshop)
* @param array $partnerIds Array of affiliate IDs
* @return array Keyed by affiliate ID => [company_name, affiliate_code, email, incharge_name]
*/
private function getPartnerInfoFromShop($partnerIds) {
$result = [];
if (empty($partnerIds)) return $result;
try {
$shopPdo = new PDO(
"mysql:host=localhost;dbname=u752449863_rrshop;charset=utf8mb4",
"u752449863_rradmin",
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);
$placeholders = implode(',', array_fill(0, count($partnerIds), '?'));
$stmt = $shopPdo->prepare("SELECT id, company_name, affiliate_code, email, incharge_name FROM affiliates WHERE id IN ($placeholders)");
$stmt->execute(array_values($partnerIds));
foreach ($stmt->fetchAll() as $row) {
$result[$row['id']] = $row;
}
} catch (Exception $e) {
logError('Error fetching partner info from shop DB', ['error' => $e->getMessage()]);
}
return $result;
}
/**
* Fetch client info from the shop database (clients table is in u752449863_rrshop)
* @param array $clientIds Array of client IDs
* @return array Keyed by client ID => [company_name, client_code, email, contact_person]
*/
private function getClientInfoFromShop($clientIds) {
$result = [];
if (empty($clientIds)) return $result;
try {
$shopPdo = new PDO(
"mysql:host=localhost;dbname=u752449863_rrshop;charset=utf8mb4",
"u752449863_rradmin",
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);
$placeholders = implode(',', array_fill(0, count($clientIds), '?'));
$stmt = $shopPdo->prepare("SELECT id, company_name, client_code, email, contact_person FROM clients WHERE id IN ($placeholders)");
$stmt->execute(array_values($clientIds));
foreach ($stmt->fetchAll() as $row) {
$result[$row['id']] = $row;
}
} catch (Exception $e) {
logError('Error fetching client info from shop DB', ['error' => $e->getMessage()]);
}
return $result;
}
public function assignTicket($ticketId, $adminId) {
try {
$stmt = $this->pdo->prepare("UPDATE support_tickets SET assigned_to = ?, updated_at = NOW() WHERE id = ?");
return $stmt->execute([$adminId, $ticketId]);
} catch (Exception $e) {
logError('Error assigning ticket', ['ticket_id' => $ticketId, 'admin_id' => $adminId, 'error' => $e->getMessage()]);
return false;
}
}
public function addTicketReply($ticketId, $message, $adminId, $isInternal = false) {
try {
$stmt = $this->pdo->prepare("
INSERT INTO support_messages (ticket_id, sender_type, sender_id, message, is_internal)
VALUES (?, 'admin', ?, ?, ?)
");
$result = $stmt->execute([$ticketId, $adminId, $message, $isInternal]);
if ($result) {
// Capture the inserted message ID BEFORE any other queries
$messageId = $this->pdo->lastInsertId();
// Update ticket timestamp
$stmt = $this->pdo->prepare("UPDATE support_tickets SET updated_at = NOW() WHERE id = ?");
$stmt->execute([$ticketId]);
// Return the actual message ID (not boolean) so attachments link correctly
return $messageId;
}
return false;
} catch (Exception $e) {
logError('Error adding ticket reply', ['ticket_id' => $ticketId, 'admin_id' => $adminId, 'error' => $e->getMessage()]);
return false;
}
}
public function getAdminUsers() {
try {
$stmt = $this->pdo->prepare("SELECT id, username, full_name, role FROM admin_users WHERE status = 'active' ORDER BY full_name");
$stmt->execute();
return $stmt->fetchAll();
} catch (Exception $e) {
logError('Error fetching admin users', ['error' => $e->getMessage()]);
return [];
}
}
// REDEMPTION MANAGEMENT METHODS
public function getAllRedemptions($status = null, $dateFilter = null, $limit = 50, $offset = 0) {
try {
$where = "1=1";
$params = [];
if ($status && $status !== 'all') {
$where .= " AND rr.status = ?";
$params[] = $status;
}
if ($dateFilter) {
switch ($dateFilter) {
case 'today':
$where .= " AND DATE(rr.created_at) = CURDATE()";
break;
case 'yesterday':
$where .= " AND DATE(rr.created_at) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)";
break;
case 'this_week':
$where .= " AND rr.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)";
break;
case 'this_month':
$where .= " AND rr.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)";
break;
}
}
$stmt = $this->pdo->prepare("
SELECT rr.*,
u.email as user_email,
au.full_name as processed_by_name,
(SELECT COUNT(*) FROM redemption_requests WHERE user_id = rr.user_id) as user_total_redemptions
FROM redemption_requests rr
LEFT JOIN users u ON rr.user_id = u.id
LEFT JOIN admin_users au ON rr.processed_by = au.id
WHERE $where
ORDER BY rr.created_at DESC
LIMIT $limit OFFSET $offset
");
$stmt->execute($params);
return $stmt->fetchAll();
} catch (Exception $e) {
logError('Error fetching redemptions', ['error' => $e->getMessage()]);
return [];
}
}
public function getRedemptionStats() {
try {
$stmt = $this->pdo->query("
SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing,
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed,
SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) as cancelled,
SUM(CASE WHEN status = 'pending' THEN amount_inr ELSE 0 END) as pending_amount,
SUM(CASE WHEN status IN ('processing', 'completed') THEN amount_inr ELSE 0 END) as processed_amount
FROM redemption_requests
");
return $stmt->fetch();
} catch (Exception $e) {
logError('Error fetching redemption stats', ['error' => $e->getMessage()]);
return [
'total' => 0, 'pending' => 0, 'processing' => 0, 'completed' => 0,
'failed' => 0, 'cancelled' => 0, 'pending_amount' => 0, 'processed_amount' => 0
];
}
}
public function updateRedemptionStatus($redemptionId, $status, $adminNotes, $adminId, $paymentRef = null, $paymentMode = 'UPI', $disbursalDate = null) {
try {
$this->pdo->beginTransaction();
// Get redemption details
$stmt = $this->pdo->prepare("SELECT * FROM redemption_requests WHERE id = ?");
$stmt->execute([$redemptionId]);
$redemption = $stmt->fetch();
if (!$redemption) {
throw new Exception('Redemption request not found');
}
// Update redemption status with payment fields
$stmt = $this->pdo->prepare("
UPDATE redemption_requests
SET status = ?, admin_notes = ?, processed_by = ?, processed_at = NOW(),
payment_reference = ?, payment_mode = ?, disbursal_date = ?,
updated_at = NOW()
WHERE id = ?
");
$finalDisbursalDate = ($status === 'completed' && $disbursalDate) ? $disbursalDate : null;
$finalPaymentRef = ($status === 'completed') ? $paymentRef : null;
$stmt->execute([$status, $adminNotes, $adminId, $finalPaymentRef, $paymentMode, $finalDisbursalDate, $redemptionId]);
// Update point transaction status
$stmt = $this->pdo->prepare("
UPDATE point_transactions
SET status = ?
WHERE reference_id = ? AND transaction_type = 'redeemed'
");
$stmt->execute([$status, $redemption['request_id']]);
// If status is failed or cancelled, refund the points
if (in_array($status, ['failed', 'cancelled'])) {
$stmt = $this->pdo->prepare("
UPDATE user_points
SET points = points + ?, total_redeemed = total_redeemed - ?
WHERE user_id = ?
");
$stmt->execute([$redemption['points_redeemed'], $redemption['points_redeemed'], $redemption['user_id']]);
// Add refund transaction
$refundDescription = "Refund for {$status} redemption request - " . $redemption['request_id'];
$stmt = $this->pdo->prepare("
INSERT INTO point_transactions (user_id, transaction_type, points, source, description, reference_id)
VALUES (?, 'earned', ?, 'refund', ?, ?)
");
$stmt->execute([$redemption['user_id'], $redemption['points_redeemed'], $refundDescription, $redemption['request_id']]);
}
$this->pdo->commit();
logError('Redemption status updated', [
'redemption_id' => $redemptionId,
'request_id' => $redemption['request_id'],
'old_status' => $redemption['status'],
'new_status' => $status,
'admin_id' => $adminId,
'admin_notes' => $adminNotes
]);
return true;
} catch (Exception $e) {
$this->pdo->rollback();
logError('Error updating redemption status', [
'redemption_id' => $redemptionId,
'error' => $e->getMessage()
]);
return false;
}
}
public function getRedemptionById($redemptionId) {
try {
$stmt = $this->pdo->prepare("
SELECT rr.*,
u.email as user_email, u.gender, u.date_of_birth, u.postcode,
au.full_name as processed_by_name,
up.points as user_current_points,
up.total_earned, up.total_redeemed
FROM redemption_requests rr
LEFT JOIN users u ON rr.user_id = u.id
LEFT JOIN admin_users au ON rr.processed_by = au.id
LEFT JOIN user_points up ON rr.user_id = up.user_id
WHERE rr.id = ?
");
$stmt->execute([$redemptionId]);
return $stmt->fetch();
} catch (Exception $e) {
logError('Error fetching redemption', ['redemption_id' => $redemptionId, 'error' => $e->getMessage()]);
return null;
}
}
public function getRecentRedemptions($limit = 5) {
try {
$stmt = $this->pdo->prepare("
SELECT rr.request_id, rr.amount_inr, rr.status, rr.created_at, u.email as user_email
FROM redemption_requests rr
LEFT JOIN users u ON rr.user_id = u.id
ORDER BY rr.created_at DESC
LIMIT ?
");
$stmt->execute([$limit]);
return $stmt->fetchAll();
} catch (Exception $e) {
logError('Error fetching recent redemptions', ['error' => $e->getMessage()]);
return [];
}
}
// ========================================
// PARTNER REDEMPTION METHODS
// ========================================
/**
* Get a separate PDO connection to the rrshop database
*/
private function getShopPdo() {
return new PDO(
"mysql:host=localhost;dbname=u752449863_rrshop;charset=utf8mb4",
"u752449863_rradmin",
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false]
);
}
/**
* Get all partner redemptions with affiliate details
*/
public function getAllPartnerRedemptions($status = null, $dateFilter = null, $limit = 50, $offset = 0) {
try {
$shopPdo = $this->getShopPdo();
$where = "1=1";
$params = [];
if ($status && $status !== 'all') {
$where .= " AND pr.status = ?";
$params[] = $status;
}
if ($dateFilter) {
switch ($dateFilter) {
case 'today':
$where .= " AND DATE(pr.created_at) = CURDATE()";
break;
case 'yesterday':
$where .= " AND DATE(pr.created_at) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)";
break;
case 'this_week':
$where .= " AND pr.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)";
break;
case 'this_month':
$where .= " AND MONTH(pr.created_at) = MONTH(NOW()) AND YEAR(pr.created_at) = YEAR(NOW())";
break;
}
}
$limit = intval($limit);
$offset = intval($offset);
$stmt = $shopPdo->prepare("
SELECT pr.*,
a.company_name, a.affiliate_code, a.email as partner_email,
a.incharge_name, a.mobile
FROM partner_redemptions pr
LEFT JOIN affiliates a ON pr.affiliate_id = a.id
WHERE $where
ORDER BY pr.created_at DESC
LIMIT $limit OFFSET $offset
");
$stmt->execute($params);
return $stmt->fetchAll();
} catch (Exception $e) {
logError('Error fetching partner redemptions', ['error' => $e->getMessage()]);
return [];
}
}
/**
* Get a single partner redemption with full affiliate details
*/
public function getPartnerRedemptionById($redemptionId) {
try {
$shopPdo = $this->getShopPdo();
$stmt = $shopPdo->prepare("
SELECT pr.*,
a.company_name, a.affiliate_code, a.email as partner_email,
a.incharge_name, a.mobile,
a.commission_balance, a.total_commission_earned, a.total_commission_redeemed,
a.total_signups, a.total_verified_signups
FROM partner_redemptions pr
LEFT JOIN affiliates a ON pr.affiliate_id = a.id
WHERE pr.id = ?
");
$stmt->execute([$redemptionId]);
return $stmt->fetch();
} catch (Exception $e) {
logError('Error fetching partner redemption', ['redemption_id' => $redemptionId, 'error' => $e->getMessage()]);
return null;
}
}
/**
* Get partner redemption statistics
*/
public function getPartnerRedemptionStats() {
try {
$shopPdo = $this->getShopPdo();
$stmt = $shopPdo->query("
SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending,
SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing,
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed,
SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END) as rejected,
SUM(CASE WHEN status IN ('pending','processing') THEN amount ELSE 0 END) as pending_amount,
SUM(CASE WHEN status = 'completed' THEN amount ELSE 0 END) as completed_amount
FROM partner_redemptions
");
$result = $stmt->fetch();
return $result ?: ['total' => 0, 'pending' => 0, 'processing' => 0, 'completed' => 0, 'rejected' => 0, 'pending_amount' => 0, 'completed_amount' => 0];
} catch (Exception $e) {
logError('Error fetching partner redemption stats', ['error' => $e->getMessage()]);
return ['total' => 0, 'pending' => 0, 'processing' => 0, 'completed' => 0, 'rejected' => 0, 'pending_amount' => 0, 'completed_amount' => 0];
}
}
/**
* Update partner redemption status with disbursal details
* On 'completed': deducts from commission_balance, adds to total_commission_redeemed
* On 'rejected': refunds if balance was already deducted
*/
public function updatePartnerRedemptionStatus($redemptionId, $newStatus, $adminNotes, $paymentRef, $adminId, $paymentMode = 'UPI', $paymentAmount = null, $disbursalDate = null) {
try {
$shopPdo = $this->getShopPdo();
// Get current redemption
$stmt = $shopPdo->prepare("SELECT * FROM partner_redemptions WHERE id = ?");
$stmt->execute([$redemptionId]);
$redemption = $stmt->fetch();
if (!$redemption) {
logError('Partner redemption not found', ['id' => $redemptionId]);
return false;
}
$oldStatus = $redemption['status'];
$amount = floatval($redemption['amount']);
$affiliateId = $redemption['affiliate_id'];
// Check if admin exists in rrshop.admin_users (FK constraint)
$processedBy = null;
try {
$stmt = $shopPdo->prepare("SELECT id FROM admin_users WHERE id = ?");
$stmt->execute([$adminId]);
if ($stmt->fetch()) {
$processedBy = $adminId;
}
} catch (Exception $e) { /* admin_users may not exist */ }
$shopPdo->beginTransaction();
// Build rejection reason
$rejectionReason = ($newStatus === 'rejected') ? $adminNotes : $redemption['rejection_reason'];
// Ensure null for empty optional fields
if (empty($disbursalDate)) $disbursalDate = ($newStatus === 'completed') ? date('Y-m-d') : null;
if ($paymentAmount === null || $paymentAmount <= 0) $paymentAmount = ($newStatus === 'completed') ? $amount : null;
// Update the redemption record
$stmt = $shopPdo->prepare("
UPDATE partner_redemptions SET
status = ?,
payment_reference = ?,
payment_mode = ?,
payment_amount = ?,
disbursal_date = ?,
notes = ?,
rejection_reason = ?,
processed_by = ?,
processed_at = NOW(),
updated_at = NOW()
WHERE id = ?
");
$stmt->execute([
$newStatus,
$paymentRef ?: null,
$paymentMode ?: 'UPI',
$paymentAmount,
$disbursalDate,
$adminNotes ?: null,
$rejectionReason,
$processedBy,
$redemptionId
]);
// Handle balance changes
if ($newStatus === 'completed' && $oldStatus !== 'completed') {
$stmt = $shopPdo->prepare("
UPDATE affiliates SET
total_commission_redeemed = COALESCE(total_commission_redeemed, 0) + ?
WHERE id = ?
");
$stmt->execute([$amount, $affiliateId]);
} elseif ($newStatus === 'rejected' && $oldStatus === 'completed') {
$stmt = $shopPdo->prepare("
UPDATE affiliates SET
total_commission_redeemed = GREATEST(0, COALESCE(total_commission_redeemed, 0) - ?)
WHERE id = ?
");
$stmt->execute([$amount, $affiliateId]);
}
// Recalculate commission_balance
$stmt = $shopPdo->prepare("SELECT COALESCE(SUM(amount), 0) FROM partner_redemptions WHERE affiliate_id = ? AND status IN ('pending','processing')");
$stmt->execute([$affiliateId]);
$pendingSum = floatval($stmt->fetchColumn());
$stmt = $shopPdo->prepare("
UPDATE affiliates SET
commission_balance = total_commission_earned - COALESCE(total_commission_redeemed, 0) - ?
WHERE id = ?
");
$stmt->execute([$pendingSum, $affiliateId]);
$shopPdo->commit();
logError('Partner redemption updated', [
'redemption_id' => $redemptionId,
'old_status' => $oldStatus,
'new_status' => $newStatus,
'amount' => $amount,
'payment_amount' => $paymentAmount,
'admin_id' => $adminId
]);
return true;
} catch (Exception $e) {
if (isset($shopPdo) && $shopPdo->inTransaction()) {
$shopPdo->rollBack();
}
logError('Error updating partner redemption', ['redemption_id' => $redemptionId, 'error' => $e->getMessage()]);
return 'DB Error: ' . $e->getMessage();
}
}
}
// Utility functions
function adminJsonResponse($success, $message, $data = null) {
header('Content-Type: application/json');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
echo json_encode([
'success' => $success,
'message' => $message,
'data' => $data
]);
exit;
}
?>
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/admin-support.php
TYPE: PHP
SIZE: 117.7 KB
------------------------------------------------------------
logout();
}
// Handle login form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !$auth->isLoggedIn()) {
$username = isset($_POST['username']) ? sanitize($_POST['username']) : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
$rememberMe = isset($_POST['remember_me']);
if ($auth->login($username, $password, $rememberMe)) {
header('Location: support.php');
exit;
} else {
$loginError = 'Invalid username or password.';
}
}
// Handle AJAX requests for logged-in admins
if ($auth->isLoggedIn() && $_SERVER['REQUEST_METHOD'] === 'POST') {
$action = isset($_POST['action']) ? $_POST['action'] : '';
$admin = $auth->getCurrentAdmin();
switch ($action) {
// SUPPORT TICKET ACTIONS
case 'update_status':
$ticketId = isset($_POST['ticket_id']) ? intval($_POST['ticket_id']) : 0;
$status = isset($_POST['status']) ? sanitize($_POST['status']) : '';
if ($ticketId && in_array($status, ['open', 'pending', 'resolved', 'closed'])) {
$success = $auth->updateTicketStatus($ticketId, $status, $admin['id']);
adminJsonResponse($success, $success ? 'Status updated successfully' : 'Failed to update status');
} else {
adminJsonResponse(false, 'Invalid parameters');
}
break;
case 'assign_ticket':
$ticketId = isset($_POST['ticket_id']) ? intval($_POST['ticket_id']) : 0;
$adminId = isset($_POST['admin_id']) ? intval($_POST['admin_id']) : 0;
if ($ticketId && $adminId) {
$success = $auth->assignTicket($ticketId, $adminId);
adminJsonResponse($success, $success ? 'Ticket assigned successfully' : 'Failed to assign ticket');
} else {
adminJsonResponse(false, 'Invalid parameters');
}
break;
case 'add_reply':
$ticketId = isset($_POST['ticket_id']) ? intval($_POST['ticket_id']) : 0;
$message = isset($_POST['message']) ? trim($_POST['message']) : '';
$isInternal = isset($_POST['is_internal']) ? (bool)$_POST['is_internal'] : false;
if ($ticketId && $message) {
$messageId = $auth->addTicketReply($ticketId, $message, $admin['id'], $isInternal);
if ($messageId) {
// Handle file attachments using the exact message ID returned
if ($supportHelperLoaded && !empty($_FILES['attachments']['name'][0])) {
$pdo = $auth->getConnection();
handleSupportAttachments($pdo, intval($messageId), $_FILES['attachments']);
}
adminJsonResponse(true, 'Reply added successfully');
} else {
adminJsonResponse(false, 'Failed to add reply');
}
} else {
adminJsonResponse(false, 'Message cannot be empty');
}
break;
// MEMBER REDEMPTION ACTIONS
case 'update_redemption_status':
$redemptionId = isset($_POST['redemption_id']) ? intval($_POST['redemption_id']) : 0;
$newStatus = isset($_POST['status']) ? sanitize($_POST['status']) : '';
$adminNotes = isset($_POST['admin_notes']) ? sanitize($_POST['admin_notes']) : '';
$paymentRef = isset($_POST['payment_reference']) ? sanitize($_POST['payment_reference']) : null;
$paymentMode = isset($_POST['payment_mode']) ? sanitize($_POST['payment_mode']) : 'UPI';
$disbursalDate = isset($_POST['disbursal_date']) && $_POST['disbursal_date'] !== '' ? sanitize($_POST['disbursal_date']) : null;
if (!in_array($newStatus, ['pending', 'processing', 'completed', 'failed', 'cancelled'])) {
adminJsonResponse(false, 'Invalid status');
}
if ($newStatus === 'completed' && empty($paymentRef)) {
adminJsonResponse(false, 'Transaction reference is required for completed payments');
}
if ($redemptionId && $newStatus) {
$success = $auth->updateRedemptionStatus($redemptionId, $newStatus, $adminNotes, $admin['id'], $paymentRef, $paymentMode, $disbursalDate);
adminJsonResponse($success, $success ? 'Redemption status updated successfully' : 'Failed to update status');
} else {
adminJsonResponse(false, 'Invalid parameters');
}
break;
// PARTNER REDEMPTION ACTIONS
case 'update_partner_redemption_status':
$redemptionId = isset($_POST['redemption_id']) ? intval($_POST['redemption_id']) : 0;
$newStatus = isset($_POST['status']) ? sanitize($_POST['status']) : '';
$adminNotes = isset($_POST['admin_notes']) ? sanitize($_POST['admin_notes']) : '';
$paymentRef = isset($_POST['payment_reference']) ? sanitize($_POST['payment_reference']) : '';
$paymentMode = isset($_POST['payment_mode']) ? sanitize($_POST['payment_mode']) : 'UPI';
$paymentAmount = isset($_POST['payment_amount']) && $_POST['payment_amount'] !== '' ? floatval($_POST['payment_amount']) : null;
$disbursalDate = isset($_POST['disbursal_date']) && $_POST['disbursal_date'] !== '' ? sanitize($_POST['disbursal_date']) : null;
if (!in_array($newStatus, ['pending', 'processing', 'completed', 'rejected'])) {
adminJsonResponse(false, 'Invalid status');
}
if ($newStatus === 'completed' && empty($paymentRef)) {
adminJsonResponse(false, 'Transaction number is required for completed payments');
}
if ($redemptionId && $newStatus) {
$result = $auth->updatePartnerRedemptionStatus($redemptionId, $newStatus, $adminNotes, $paymentRef, $admin['id'], $paymentMode, $paymentAmount, $disbursalDate);
if ($result === true) {
adminJsonResponse(true, 'Partner redemption updated successfully');
} else {
adminJsonResponse(false, is_string($result) ? $result : 'Failed to update status');
}
} else {
adminJsonResponse(false, 'Invalid parameters');
}
break;
case 'create_admin':
$username = isset($_POST['new_username']) ? sanitize($_POST['new_username']) : '';
$email = isset($_POST['new_email']) ? sanitize($_POST['new_email']) : '';
$password = isset($_POST['new_password']) ? $_POST['new_password'] : '';
$fullName = isset($_POST['new_full_name']) ? sanitize($_POST['new_full_name']) : '';
$role = isset($_POST['new_role']) ? sanitize($_POST['new_role']) : 'admin';
if ($username && $email && $password && $fullName) {
$success = $auth->createAdmin($username, $email, $password, $fullName, $role);
adminJsonResponse($success, $success ? 'Admin user created successfully' : 'Failed to create admin user (username or email may already exist)');
} else {
adminJsonResponse(false, 'All fields are required');
}
break;
// USER MANAGEMENT ACTIONS (super_admin only)
case 'create_user':
if ($admin['role'] !== 'super_admin') { adminJsonResponse(false, 'Access denied'); break; }
$uName = isset($_POST['full_name']) ? trim($_POST['full_name']) : '';
$uEmail = isset($_POST['email']) ? trim(strtolower($_POST['email'])) : '';
$uMobile = isset($_POST['mobile']) ? trim($_POST['mobile']) : '';
$uPassword = isset($_POST['password']) ? $_POST['password'] : '';
$uRole = isset($_POST['role']) ? sanitize($_POST['role']) : 'admin';
$uTabs = isset($_POST['allowed_tabs']) ? implode(',', $_POST['allowed_tabs']) : 'all';
$uTicketTypes = isset($_POST['allowed_ticket_types']) ? implode(',', $_POST['allowed_ticket_types']) : 'all';
if (empty($uName) || empty($uEmail) || empty($uPassword)) {
adminJsonResponse(false, 'Name, email and password are required.');
break;
}
if (strlen($uPassword) < 6) {
adminJsonResponse(false, 'Password must be at least 6 characters.');
break;
}
$result = $auth->createAdmin($uEmail, $uEmail, $uPassword, $uName, $uRole, $uMobile, $uTabs, $uTicketTypes);
adminJsonResponse($result['success'], $result['message']);
break;
case 'update_user':
if ($admin['role'] !== 'super_admin') { adminJsonResponse(false, 'Access denied'); break; }
$uId = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
$uName = isset($_POST['full_name']) ? trim($_POST['full_name']) : '';
$uEmail = isset($_POST['email']) ? trim(strtolower($_POST['email'])) : '';
$uMobile = isset($_POST['mobile']) ? trim($_POST['mobile']) : '';
$uRole = isset($_POST['role']) ? sanitize($_POST['role']) : 'admin';
$uTabs = isset($_POST['allowed_tabs']) ? implode(',', $_POST['allowed_tabs']) : 'all';
$uTicketTypes = isset($_POST['allowed_ticket_types']) ? implode(',', $_POST['allowed_ticket_types']) : 'all';
$uPassword = isset($_POST['password']) && !empty($_POST['password']) ? $_POST['password'] : null;
if (!$uId || empty($uName) || empty($uEmail)) {
adminJsonResponse(false, 'Name and email are required.');
break;
}
if ($uPassword && strlen($uPassword) < 6) {
adminJsonResponse(false, 'Password must be at least 6 characters.');
break;
}
$result = $auth->updateAdmin($uId, $uName, $uEmail, $uMobile, $uRole, $uTabs, $uTicketTypes, $uPassword);
adminJsonResponse($result['success'], $result['message']);
break;
case 'toggle_user_status':
if ($admin['role'] !== 'super_admin') { adminJsonResponse(false, 'Access denied'); break; }
$uId = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
if ($uId) {
$success = $auth->toggleAdminStatus($uId);
adminJsonResponse($success, $success ? 'Status toggled successfully' : 'Cannot change this user\'s status');
} else {
adminJsonResponse(false, 'Invalid user ID');
}
break;
default:
adminJsonResponse(false, 'Invalid action');
}
}
// If admin is logged in, get data
if ($auth->isLoggedIn()) {
$admin = $auth->getCurrentAdmin();
$isSuperAdmin = ($admin['role'] === 'super_admin');
$allowedTicketTypes = $auth->getAllowedTicketTypes();
// Get current tab
$currentTab = isset($_GET['tab']) ? sanitize($_GET['tab']) : 'tickets';
// Enforce tab permissions (users tab = super_admin only)
if ($currentTab === 'users' && !$isSuperAdmin) $currentTab = 'tickets';
if (!$isSuperAdmin && !$auth->hasTabAccess($currentTab)) {
// Fallback to first allowed tab
$allTabs = ['tickets','redemptions','partner_redemptions'];
$currentTab = 'tickets';
foreach ($allTabs as $t) {
if ($auth->hasTabAccess($t)) { $currentTab = $t; break; }
}
}
// Get filters from URL
$statusFilter = isset($_GET['status']) ? sanitize($_GET['status']) : null;
$priorityFilter = isset($_GET['priority']) ? sanitize($_GET['priority']) : null;
$senderTypeFilter = isset($_GET['sender_type']) ? sanitize($_GET['sender_type']) : null;
$dateFilter = isset($_GET['date_filter']) ? sanitize($_GET['date_filter']) : null;
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = 25;
$offset = ($page - 1) * $limit;
// Get specific ticket if viewing one
$viewTicketId = isset($_GET['ticket']) ? intval($_GET['ticket']) : null;
$viewTicket = null;
$ticketMessages = [];
$messageAttachments = [];
if ($viewTicketId) {
$viewTicket = $auth->getTicketById($viewTicketId);
if ($viewTicket) {
$ticketMessages = $auth->getTicketMessages($viewTicketId, true);
// Load attachments for all messages
if ($supportHelperLoaded && !empty($ticketMessages)) {
try {
$db = new Database();
$pdo = $db->getConnection();
$msgIds = array_column($ticketMessages, 'id');
if (!empty($msgIds)) {
$messageAttachments = getAttachmentsForMessages($pdo, $msgIds);
}
} catch (Exception $e) {
$messageAttachments = [];
}
}
}
}
// Get specific redemption if viewing one
$viewRedemptionId = isset($_GET['redemption']) ? intval($_GET['redemption']) : null;
$viewRedemption = null;
if ($viewRedemptionId) {
if ($currentTab === 'partner_redemptions') {
$viewRedemption = $auth->getPartnerRedemptionById($viewRedemptionId);
} else {
$viewRedemption = $auth->getRedemptionById($viewRedemptionId);
}
}
// Get data based on current tab
if ($currentTab === 'redemptions') {
$redemptions = $auth->getAllRedemptions($statusFilter, $dateFilter, $limit, $offset);
$redemptionStats = $auth->getRedemptionStats();
} elseif ($currentTab === 'partner_redemptions') {
$partnerRedemptions = $auth->getAllPartnerRedemptions($statusFilter, $dateFilter, $limit, $offset);
$partnerRedemptionStats = $auth->getPartnerRedemptionStats();
} elseif ($currentTab === 'users' && $isSuperAdmin) {
$allAdminUsers = $auth->getAllAdminUsersDetailed();
$editUserId = isset($_GET['edit_user']) ? intval($_GET['edit_user']) : null;
$editUser = $editUserId ? $auth->getAdminById($editUserId) : null;
} else {
$tickets = $auth->getAllTickets($statusFilter, $priorityFilter, $senderTypeFilter, $limit, $offset, $allowedTicketTypes);
$ticketStats = $auth->getTicketStats($allowedTicketTypes);
}
$adminUsers = $auth->getAdminUsers();
}
?>
Support - Relevant Reflex
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/articles.php
TYPE: PHP
SIZE: 27.9 KB
------------------------------------------------------------
Articles & Tips - Relevant Reflex | Maximize Your Survey Earnings
Articles & Tips
Expert advice, tips, and insights to help you maximize your earnings with online surveys in India.
Paid Online Surveys in India: How to Spot Genuine Websites
In the bustling online world of India, paid online surveys have become a popular means for individuals to earn extra income conveniently. Companies and market research firms value the opinions of Indian consumers, and this has led to numerous opportunities to participate in paid surveys. However, with the rise in demand for such opportunities, fraudulent websites have also emerged, preying on unsuspecting individuals.
Learn the key indicators of legitimate survey platforms and avoid falling victim to scams. Essential reading for anyone starting with online surveys in India.
Key Points:
Thorough Research is Key: Look for platforms with strong online presence and positive reviews from Indian users.
Seek Transparent Websites: Legitimate sites provide clear contact information and company details.
Avoid Upfront Fees: Reputable sites never charge registration fees.
Check Payment Methods: Verify that payment methods are reputable and suitable for India.
December 10, 2024 | Tips & Tricks
5 Ways to Maximize Your Survey Earnings
Practical strategies to increase your monthly survey income. From profile optimization to timing your survey participation.
Quick Tips:
Complete your profile 100%
Join multiple legitimate platforms
Check for surveys daily
Be honest in your responses
Participate in profiling surveys
December 5, 2024 | Getting Started
Complete Guide for Survey Beginners in India
Everything you need to know to get started with online surveys in India. From registration to your first payout.
What You'll Learn:
How to choose the right survey sites
Setting up your profile for success
Understanding survey types and rewards
Payment methods available in India
November 28, 2024 | Maximize Earnings
Realistic Earning Expectations from Surveys
Set proper expectations about survey earnings in India. Learn what's realistic and how to achieve consistent monthly income.
Indicative Earnings Range:
Beginners: ₹500-₹1,500/month
Active users: ₹2,000-₹4,000/month
Expert users: ₹5,000+/month
Time investment: 1-2 hours daily
*Indicative ranges only. Individual earnings are not guaranteed and vary. See our Earnings Disclaimer.
November 20, 2024 | India Specific
Best Survey Platforms for Indian Users
Comprehensive review of survey platforms that work best for Indian users, with focus on payment methods and survey availability.
Top Platforms for Indians:
Relevant Reflex (Our platform)
Swagbucks India
Toluna India
ySense (formerly ClixSense)
November 15, 2024 | Tips & Tricks
Time Management Tips for Survey Takers
Learn how to efficiently manage your time while taking surveys. Balance survey participation with your daily routine.
Time Management Tips:
Set specific times for survey participation
Use mobile apps for on-the-go surveys
Prioritize higher-paying surveys
Don't force yourself to qualify for every survey
Ready to Start Your Survey Journey?
Apply these tips and start earning with legitimate online surveys today!
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking “Accept All”, you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/check-session.php
TYPE: PHP
SIZE: 976 B
------------------------------------------------------------
checkSessionTimeout(120);
$isValid = isLoggedIn();
$user = null;
if ($isValid) {
$user = getCurrentUser();
// If user doesn't exist or is not active, invalidate session
if (!$user || $user['status'] !== 'active') {
logout();
$isValid = false;
}
}
echo json_encode([
'valid' => $isValid,
'user_id' => $isValid ? $user['id'] : null,
'email' => $isValid ? $user['email'] : null,
'timestamp' => time()
]);
} catch (Exception $e) {
logError('Session check error', ['error' => $e->getMessage()]);
echo json_encode([
'valid' => false,
'error' => 'Session check failed',
'timestamp' => time()
]);
}
?>
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/close-project-rewards.php
TYPE: PHP
SIZE: 20.69 KB
------------------------------------------------------------
mailed incentive: member gets higher amount (survey took longer)
* - If actual LOI incentive < mailed incentive: member keeps original promise (can't reduce)
* - Final reward = max(mailed_incentive, actual_loi_incentive)
*
* POINTS CONVERSION:
* - 1 point = ₹0.50 (i.e. ₹1 = 2 points)
* - All incentive calculations are in rupees first, then converted to points for crediting
*
* Place in: /public_html/close-project-rewards.php
* Called by: clients/close-project.php when project status changes to "Closed"
*/
// Conversion rate: 1 point = ₹0.50, so ₹1 = 2 points
define('POINTS_PER_RUPEE', 2);
/**
* Calculate incentive from LOI (same formula used in send-invitations.php)
* Base ₹10 + ₹1 per minute beyond 5 minutes
* Returns value in RUPEES
*/
function calculateIncentiveFromLOI($loiMinutes) {
$base = 10;
$extra = max(0, floor($loiMinutes) - 5);
return $base + $extra;
}
/**
* Convert rupees to points
*/
function rupeesToPoints($rupees) {
return round($rupees * POINTS_PER_RUPEE);
}
function processProjectCloseRewards($projectNumericId, $shopPdo = null, $panelPdo = null) {
$summary = [
'members_rewarded' => 0,
'total_member_points' => 0,
'total_member_rupees' => 0,
'affiliates_rewarded' => 0,
'total_affiliate_commission' => 0,
'incentive_note' => '',
'errors' => []
];
try {
// Get DB connections
if ($shopPdo === null) {
if (function_exists('getClientDBConnection')) {
$shopPdo = getClientDBConnection();
} elseif (function_exists('getDBConnection')) {
$shopPdo = getDBConnection();
} else {
throw new Exception('No shop database connection available');
}
}
if ($panelPdo === null) {
if (function_exists('getPanelDBConnection')) {
$panelPdo = getPanelDBConnection();
} else {
$summary['errors'][] = 'No panel DB connection - member points not credited';
$panelPdo = null;
}
}
// Get project details
$stmt = $shopPdo->prepare("SELECT * FROM projects WHERE id = ?");
$stmt->execute([$projectNumericId]);
$project = $stmt->fetch();
if (!$project) {
$summary['errors'][] = 'Project not found';
return $summary;
}
$projectCode = $project['project_id']; // e.g. RRIT130226001
$eloi = (int)($project['eloi'] ?? 0);
// =====================================================
// CALCULATE ACTUAL AVG LOI FOR THE PROJECT
// =====================================================
$actualAvgLoiMinutes = 0;
try {
$stmt = $shopPdo->prepare("
SELECT AVG(actual_loi_seconds) as avg_loi_seconds,
SUM(CASE WHEN actual_loi_seconds IS NOT NULL THEN 1 ELSE 0 END) as with_loi
FROM survey_urls
WHERE project_id = ? AND status = 'complete' AND quality_flag = 'valid'
");
$stmt->execute([$projectCode]);
$loiStats = $stmt->fetch();
if ($loiStats && $loiStats['with_loi'] > 0 && $loiStats['avg_loi_seconds'] > 0) {
$actualAvgLoiMinutes = round($loiStats['avg_loi_seconds'] / 60, 1);
} else {
// Fallback to ELOI if no actual LOI data
$actualAvgLoiMinutes = $eloi;
}
} catch (Exception $e) {
$actualAvgLoiMinutes = $eloi;
}
// Calculate actual-LOI-based incentive (in RUPEES)
$actualLoiIncentive = calculateIncentiveFromLOI($actualAvgLoiMinutes);
// Determine reward per complete from project level (in RUPEES)
$rewardPerComplete = floatval($project['reward_per_complete'] ?? 0);
// Get all selections for this project
$stmt = $shopPdo->prepare("SELECT * FROM project_selections WHERE project_id = ?");
$stmt->execute([$projectNumericId]);
$selections = $stmt->fetchAll();
if (empty($selections)) {
$summary['errors'][] = 'No selections found';
return $summary;
}
foreach ($selections as $selection) {
$selectionId = $selection['id'];
// =====================================================
// DETERMINE MAILED (ORIGINAL) INCENTIVE (in RUPEES)
// =====================================================
$mailedIncentive = $rewardPerComplete > 0 ? $rewardPerComplete : floatval($selection['reward_per_complete'] ?? 0);
if ($mailedIncentive <= 0) {
$mailedIncentive = floatval($selection['incentive_amount'] ?? 0);
}
// =====================================================
// APPLY INCENTIVE MODEL: max(mailed, actual_loi_based)
// Both values are in RUPEES
// =====================================================
$finalRewardRupees = max($mailedIncentive, $actualLoiIncentive);
// Convert RUPEES to POINTS (₹1 = 2 points)
$finalRewardPoints = rupeesToPoints($finalRewardRupees);
// Determine the reason/note
$rewardNote = '';
if ($actualLoiIncentive > $mailedIncentive && $mailedIncentive > 0) {
$rewardNote = ' (Adjusted up: survey avg LOI ' . $actualAvgLoiMinutes . ' min exceeded estimate, incentive increased from ₹' . number_format($mailedIncentive, 0) . ' to ₹' . number_format($finalRewardRupees, 0) . ')';
$summary['incentive_note'] = 'Actual avg LOI (' . $actualAvgLoiMinutes . ' min) exceeded estimate (' . $eloi . ' min). Member incentive adjusted upward.';
} elseif ($actualLoiIncentive < $mailedIncentive && $mailedIncentive > 0) {
$rewardNote = ' (Original promised incentive maintained despite lower avg LOI)';
if (empty($summary['incentive_note'])) {
$summary['incentive_note'] = 'Actual avg LOI (' . $actualAvgLoiMinutes . ' min) was lower than estimate (' . $eloi . ' min). Original promised incentive of ₹' . number_format($mailedIncentive, 0) . ' maintained for members.';
}
}
if ($finalRewardRupees <= 0) {
$summary['errors'][] = "Selection #{$selectionId}: no reward set - skipping member rewards";
}
// Find all selection_members with sample_status = 'complete'
$stmt = $shopPdo->prepare("
SELECT sm.* FROM selection_members sm
WHERE sm.selection_id = ? AND sm.sample_status = 'complete'
");
$stmt->execute([$selectionId]);
$completeMembers = $stmt->fetchAll();
foreach ($completeMembers as $member) {
$userId = $member['user_id'];
try {
// ========================================
// 1. CREDIT MEMBER SURVEY REWARD
// ========================================
if ($finalRewardRupees > 0 && $panelPdo !== null) {
// Check if already credited
$alreadyCredited = false;
try {
$stmt = $shopPdo->prepare("SELECT id FROM survey_rewards_log WHERE user_id = ? AND project_id = ?");
$stmt->execute([$userId, $projectCode]);
$alreadyCredited = (bool)$stmt->fetch();
} catch (Exception $e) { /* table might not exist */ }
if (!$alreadyCredited) {
// Log in shop DB (store POINTS)
try {
$stmt = $shopPdo->prepare("
INSERT INTO survey_rewards_log (user_id, project_id, selection_id, points_awarded, status)
VALUES (?, ?, ?, ?, 'pending')
");
$stmt->execute([$userId, $projectCode, $selectionId, $finalRewardPoints]);
} catch (Exception $e) {
error_log("survey_rewards_log insert: " . $e->getMessage());
}
// Credit POINTS in panel DB
$stmt = $panelPdo->prepare("
UPDATE user_points SET points = points + ?, total_earned = total_earned + ? WHERE user_id = ?
");
$stmt->execute([$finalRewardPoints, $finalRewardPoints, $userId]);
if ($stmt->rowCount() === 0) {
$stmt = $panelPdo->prepare("
INSERT INTO user_points (user_id, points, total_earned) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE points = points + ?, total_earned = total_earned + ?
");
$stmt->execute([$userId, $finalRewardPoints, $finalRewardPoints, $finalRewardPoints, $finalRewardPoints]);
}
// Add transaction record (POINTS) with LOI adjustment note
$txnDesc = 'Survey reward: ' . $projectCode . ' - ' . $project['project_name']
. ' (₹' . number_format($finalRewardRupees, 2) . ' = ' . $finalRewardPoints . ' pts)'
. $rewardNote;
$stmt = $panelPdo->prepare("
INSERT INTO point_transactions (user_id, transaction_type, points, source, description, reference_id)
VALUES (?, 'earned', ?, 'survey_reward', ?, ?)
");
$stmt->execute([$userId, $finalRewardPoints, $txnDesc, $projectCode]);
// Update survey_responses in panel DB
// incentive_amount = RUPEES (what was promised), points_awarded = POINTS
try {
$stmt = $panelPdo->prepare("
INSERT INTO survey_responses (user_id, project_id, selection_id, status, incentive_amount, points_awarded, reward_status, completed_at)
VALUES (?, ?, ?, 'complete', ?, ?, 'pending', NOW())
ON DUPLICATE KEY UPDATE points_awarded = ?, reward_status = 'pending'
");
$stmt->execute([$userId, $projectCode, $selectionId, $finalRewardRupees, $finalRewardPoints, $finalRewardPoints]);
} catch (Exception $e) { /* non-critical */ }
// Update selection_members points_awarded (POINTS)
try {
$stmt = $shopPdo->prepare("UPDATE selection_members SET points_awarded = ? WHERE selection_id = ? AND user_id = ?");
$stmt->execute([$finalRewardPoints, $selectionId, $userId]);
} catch (Exception $e) { /* non-critical */ }
$summary['members_rewarded']++;
$summary['total_member_points'] += $finalRewardPoints;
$summary['total_member_rupees'] += $finalRewardRupees;
}
}
// ==========================================
// 2. CREDIT AFFILIATE REVENUE SHARE
// ==========================================
$stmt = $shopPdo->prepare("
SELECT a.id as affiliate_id, a.signup_reward
FROM affiliate_signups asu
JOIN affiliates a ON asu.affiliate_id = a.id
WHERE asu.panel_user_id = ? AND asu.email_verified = 1
LIMIT 1
");
$stmt->execute([$userId]);
$affiliateLink = $stmt->fetch();
if ($affiliateLink) {
$affiliateId = $affiliateLink['affiliate_id'];
$revenueShare = 0;
// Try survey_reward column first
try {
$stmt = $shopPdo->prepare("SELECT survey_reward FROM affiliates WHERE id = ?");
$stmt->execute([$affiliateId]);
$row = $stmt->fetch();
$revenueShare = floatval($row['survey_reward'] ?? 0);
} catch (Exception $e) { /* column might not exist */ }
// Fallback: revenue_share_per_survey
if ($revenueShare <= 0) {
try {
$stmt = $shopPdo->prepare("SELECT revenue_share_per_survey FROM affiliates WHERE id = ?");
$stmt->execute([$affiliateId]);
$row = $stmt->fetch();
$revenueShare = floatval($row['revenue_share_per_survey'] ?? 0);
} catch (Exception $e) { /* column might not exist */ }
}
// Fallback: percentage of member reward (use RUPEE value)
if ($revenueShare <= 0 && $finalRewardRupees > 0) {
$commPct = floatval($project['affiliate_commission_pct'] ?? 10);
$revenueShare = round($finalRewardRupees * ($commPct / 100), 2);
}
if ($revenueShare > 0) {
$alreadyCredited = false;
try {
$stmt = $shopPdo->prepare("
SELECT id FROM partner_commission_log
WHERE affiliate_id = ? AND type = 'survey_revenue_share' AND reference_id = ? AND panel_user_id = ?
");
$stmt->execute([$affiliateId, $projectCode, $userId]);
$alreadyCredited = (bool)$stmt->fetch();
} catch (Exception $e) { /* table might not exist */ }
if (!$alreadyCredited) {
try {
$stmt = $shopPdo->prepare("
INSERT INTO partner_commission_log (affiliate_id, type, amount, reference_id, panel_user_id, description)
VALUES (?, 'survey_revenue_share', ?, ?, ?, ?)
");
$stmt->execute([$affiliateId, $revenueShare, $projectCode, $userId,
'Survey revenue share: ' . $projectCode . ' - ' . $project['project_name']]);
} catch (Exception $e) {
error_log("partner_commission_log insert: " . $e->getMessage());
}
$stmt = $shopPdo->prepare("
UPDATE affiliates SET total_commission_earned = total_commission_earned + ?,
commission_balance = commission_balance + ? WHERE id = ?
");
$stmt->execute([$revenueShare, $revenueShare, $affiliateId]);
$summary['affiliates_rewarded']++;
$summary['total_affiliate_commission'] += $revenueShare;
}
}
}
// ==========================================
// 3. CREDIT MEMBER REFERRAL SURVEY COMMISSION
// ==========================================
// Check if this user was referred by another member
if ($panelPdo !== null) {
try {
$refStmt = $panelPdo->prepare("
SELECT id, referrer_user_id FROM member_referral_clicks
WHERE referee_user_id = ? AND email_verified = 1
LIMIT 1
");
$refStmt->execute([$userId]);
$refRow = $refStmt->fetch();
if ($refRow && $refRow['referrer_user_id'] != $userId) {
$mReferrerId = $refRow['referrer_user_id'];
$surveyCommPts = 10; // Rs.5 = 10 points
$surveyCommRs = 5.00;
// Prevent double crediting for same user+project
$dupCheck = $panelPdo->prepare("
SELECT COUNT(*) as cnt FROM point_transactions
WHERE user_id = ? AND source = 'member_referral_survey'
AND reference_id = ? AND description LIKE ?
");
$dupCheck->execute([$mReferrerId, $projectCode, '%uid:'.$userId.'%']);
$dupRow = $dupCheck->fetch();
if ($dupRow['cnt'] == 0) {
// Award points to referrer
$panelPdo->prepare("
INSERT INTO user_points (user_id, points, total_earned)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE points = points + ?, total_earned = total_earned + ?
")->execute([$mReferrerId, $surveyCommPts, $surveyCommPts, $surveyCommPts, $surveyCommPts]);
$panelPdo->prepare("
INSERT INTO point_transactions (user_id, transaction_type, points, source, description, reference_id, created_at)
VALUES (?, 'earned', ?, 'member_referral_survey', ?, ?, NOW())
")->execute([
$mReferrerId,
$surveyCommPts,
'Survey referral reward: your referral completed ' . $projectCode . ' (₹5 = 10 pts, uid:' . $userId . ')',
$projectCode
]);
// Update survey_commission_earned on the click record
$panelPdo->prepare("
UPDATE member_referral_clicks
SET survey_commission_earned = survey_commission_earned + ?
WHERE id = ?
")->execute([$surveyCommRs, $refRow['id']]);
}
}
} catch (Exception $e) {
$summary['errors'][] = "Member referral survey commission (user {$userId}): " . $e->getMessage();
}
}
} catch (Exception $e) {
$summary['errors'][] = "User {$userId}: " . $e->getMessage();
}
}
}
} catch (Exception $e) {
$summary['errors'][] = $e->getMessage();
}
return $summary;
}
?>
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/config.php
TYPE: PHP
SIZE: 3.91 KB
------------------------------------------------------------
connection = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
} catch (PDOException $e) {
error_log("Database connection failed: " . $e->getMessage());
die("Connection failed. Please try again later.");
}
}
public function getConnection() {
return $this->connection;
}
}
// Utility functions
function sanitize($data) {
return htmlspecialchars(strip_tags(trim($data)), ENT_QUOTES, 'UTF-8');
}
function generateSecureToken($length = 64) {
return bin2hex(random_bytes($length / 2));
}
function hashPassword($password) {
return password_hash($password, PASSWORD_DEFAULT);
}
function verifyPassword($password, $hash) {
return password_verify($password, $hash);
}
function validateEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL) &&
preg_match('/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/', $email);
}
function validatePassword($password) {
// At least 8 characters
return strlen($password) >= 8;
}
function validateDateOfBirth($dob) {
$date = DateTime::createFromFormat('Y-m-d', $dob);
if (!$date) return false;
// Check if user is at least 18 years old
$today = new DateTime();
$age = $today->diff($date)->y;
return $age >= 18;
}
function validatePostcode($postcode) {
// Indian postal code validation (6 digits)
return preg_match('/^[0-9]{6}$/', $postcode);
}
// JSON response helper
function jsonResponse($success, $message, $data = null) {
header('Content-Type: application/json');
echo json_encode([
'success' => $success,
'message' => $message,
'data' => $data
]);
exit;
}
// Error logging function
function logError($message, $context = []) {
$logMessage = date('Y-m-d H:i:s') . ' - ' . $message;
if (!empty($context)) {
$logMessage .= ' - Context: ' . json_encode($context);
}
error_log($logMessage . PHP_EOL, 3, 'errors.log');
}
?>
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/contact.php
TYPE: PHP
SIZE: 25.38 KB
------------------------------------------------------------
$name,
'email' => $email,
'subject' => $subject,
'message' => substr($message, 0, 100) . '...'
]);
$success_message = 'Thank you for your message! We\'ll get back to you within 24 hours.';
// Clear form data
$_POST = [];
}
}
?>
Contact Us - Relevant Reflex | Get Support for Online Surveys
Contact Us
We're here to help! Get in touch with our support team for any questions or assistance you need.
Email Support
Get help with your account, payments, or technical issues.
Account approval is typically instant after email verification. You can start taking surveys immediately after verifying your email address.
When do I get paid for completed surveys?
Payments are processed according to each survey provider's schedule. Most rewards are credited within 2-5 business days after survey completion.
Why was I disqualified from a survey?
Survey disqualifications happen when your profile doesn't match the target demographic. This is normal and helps ensure survey quality. Keep trying - there are surveys for all profiles!
How can I increase my survey opportunities?
Complete your profile thoroughly, answer profiling questions honestly, and check your dashboard regularly for new opportunities.
Is Relevant Reflex really free to join?
Yes! Joining Relevant Reflex is completely free. We never charge fees to our members. Legitimate survey companies pay YOU for your opinions, not the other way around.
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking “Accept All”, you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/dashboard.php
TYPE: PHP
SIZE: 70.38 KB
------------------------------------------------------------
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','household_classification'=>'Household Classification (ISEC)'];
$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) {}
$panNumber = ''; $panName = ''; $panStatus = '';
try {
$stmt = $pdo->prepare("SELECT question_id, response FROM user_profiler WHERE user_id = ? AND section = 'profile' AND question_id IN ('pan_number','pan_name','pan_status')");
$stmt->execute([$user['id']]);
while ($row = $stmt->fetch()) {
$val = json_decode($row['response'], true);
if ($row['question_id'] === 'pan_number') $panNumber = $val ?: '';
elseif ($row['question_id'] === 'pan_name') $panName = $val ?: '';
elseif ($row['question_id'] === 'pan_status') $panStatus = $val ?: '';
}
if (!empty($panNumber) && empty($panStatus)) $panStatus = 'pending';
} 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)."; }
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'update_pan') {
$newPanNumber = strtoupper(trim($_POST['pan_number'] ?? ''));
$newPanName = trim($_POST['pan_name'] ?? '');
if (!empty($newPanNumber) && preg_match('/^[A-Z]{5}[0-9]{4}[A-Z]$/', $newPanNumber) && !empty($newPanName) && strlen($newPanName) >= 3) {
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO user_profiler (user_id, section, question_id, response) VALUES (?, 'profile', 'pan_number', ?) ON DUPLICATE KEY UPDATE response = ?, updated_at = NOW()");
$j = json_encode($newPanNumber); $stmt->execute([$user['id'], $j, $j]);
$stmt = $pdo->prepare("INSERT INTO user_profiler (user_id, section, question_id, response) VALUES (?, 'profile', 'pan_name', ?) ON DUPLICATE KEY UPDATE response = ?, updated_at = NOW()");
$j2 = json_encode($newPanName); $stmt->execute([$user['id'], $j2, $j2]);
// Reset status to pending on any edit (admin must re-approve)
$stmt = $pdo->prepare("INSERT INTO user_profiler (user_id, section, question_id, response) VALUES (?, 'profile', 'pan_status', ?) ON DUPLICATE KEY UPDATE response = ?, updated_at = NOW()");
$j3 = json_encode('pending'); $stmt->execute([$user['id'], $j3, $j3]);
$pdo->commit();
$panNumber = $newPanNumber; $panName = $newPanName; $panStatus = 'pending';
$success_message = "PAN details saved successfully! Verification is pending.";
} catch (Exception $e) { if ($pdo->inTransaction()) $pdo->rollBack(); $error_message = "Error saving PAN details."; }
} else {
$error_message = "Invalid PAN. Must be 10 characters (e.g., ABCDE1234F) and name must be at least 3 characters.";
}
}
$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, su.rr_proxy_url,
$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()); }
// Compute actionable surveys (can be taken right now)
$actionableSurveys = [];
foreach ($surveys as $s) {
if (in_array($s['url_status'], ['sent','clicked']) && $s['project_status'] === 'Live' && !empty($s['rr_proxy_url']))
$actionableSurveys[] = $s;
}
$actionableCount = count($actionableSurveys);
$firstActionable = $actionableCount > 0 ? $actionableSurveys[0] : null;
// 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','You have been invited to this survey. Click "Take Survey" below to participate.'];
if ($st==='clicked') return ['In Progress','label-warn','You started this survey but haven\'t completed it yet. Click "Continue Survey" below to resume.'];
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
4 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.
4
Give thoughtful answers to open-ended questions. When a survey asks you to type your opinion or explain something in your own words, write a genuine, meaningful response. Vague, gibberish, or nonsensical text (e.g., random letters, copy-pasted filler, or irrelevant answers) will be flagged. Responses containing such text will be marked invalid and the completion will not count — no points will be awarded.
Why this matters: Research clients review every response for quality. Flagged responses (speeding, duplicates, straightlining, or gibberish open-ended answers) 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 →
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.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/disclaimer.php
TYPE: PHP
SIZE: 17.18 KB
------------------------------------------------------------
Earnings Disclaimer - Relevant Reflex | Important Information About Survey Rewards
Earnings Disclaimer
Important information about income potential from participating in online surveys.
Last Updated: March 2026
Important Notice: Please read this Earnings Disclaimer carefully before joining or using Relevant Reflex. Participation in our survey platform does not guarantee any specific level of income or earnings.
1. No Guaranteed Earnings
Relevant Reflex is an online survey platform that connects registered members with paid market research opportunities. We do not guarantee that you will earn any specific amount of money by participating in surveys on our platform.
Earnings from surveys are supplemental in nature and are not intended to replace a primary source of income. The amount you earn depends on many factors that are beyond our control.
2. Factors That Affect Earnings
Your actual earnings will vary based on a number of factors, including but not limited to:
The number and types of surveys available at any given time
Your demographic profile and how well it matches available survey requirements
The frequency and consistency of your participation
Your survey qualification rate (not all respondents qualify for every survey)
The time you invest in completing surveys
Survey availability in your geographic region
The specific research needs of our survey clients at any time
3. Member Testimonials and Income Examples
Any testimonials, earnings examples, or income figures shared on this website — including those from our members — represent individual results and are not typical. These are provided for illustrative purposes only.
Typical Results Disclaimer: The earnings mentioned in member stories and example income ranges on this site reflect individual experiences and do not represent average or typical results. Most members earn modest supplemental income. Your results will vary based on your demographics, time commitment, and survey availability.
We do not make any representation that the earnings experiences described by any member are typical, and individual results will vary significantly.
4. Survey Availability Is Not Guaranteed
The availability of surveys on our platform depends on the requirements of our research clients. We cannot guarantee:
A minimum number of surveys per day, week, or month
Consistent survey availability throughout the year
That you will qualify for every survey you attempt
That surveys will remain open until you complete them
5. Payment and Reward Terms
Rewards are subject to the payment terms and conditions set out in our Terms and Conditions. Rewards are paid via UPI transfer upon reaching the minimum payout threshold of ₹500. Payment timing is subject to verification and processing periods.
6. Not Financial or Professional Advice
Nothing on the Relevant Reflex website, including this page, constitutes financial advice, investment advice, or professional guidance of any kind. Survey participation is a supplemental earning activity only.
7. Contact Us
If you have any questions about this Earnings Disclaimer, please contact us at:
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking "Accept All", you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/doubts.php
TYPE: PHP
SIZE: 27.02 KB
------------------------------------------------------------
How It Works - Relevant Reflex | Complete Guide to Online Surveys
How It Works
Your complete guide to earning money with online surveys. Learn the best practices for maximizing your rewards!
Getting Started is Easy
Follow these simple steps to start earning money with surveys today!
1
Sign Up Free
Create your account with basic information. It takes less than 2 minutes and is completely free.
When you signup, DO NOT provide fake details. Provide your correct details including your gender, age, occupation, company, region etc. Since online paid surveys are sent to almost all age and gender categories and profile types, when you fake your profile, you might not get what you usually get for your actual profile.
Complete Profiler Surveys
Provide as many details as possible about you in the profiler section. This includes your gaming profile, income range, automobile assets, real estate assets, electronics you own and so on. When you attend more profiler surveys, you get more and more surveys related to all these. When you have only a generic profile and not completed the profiler surveys, you will get only those surveys which are based on age and gender.
Choose Languages You Know
Choose the languages that you know. Some people try surveys in other languages. Since you can't translate and understand all languages, you might end up taking more time on the survey than usual duration. When you take such a long duration on any survey, the system might mark you as a fraudulent user.
Be Patient
When you get screened out of many surveys, it means that the survey is not meant for your profile. This also means that there will be surveys targeting you in the future. So, KEEP PARTICIPATING in as many surveys as possible.
Log In Daily
Login every day to see if you have any surveys. Check your mail daily to know if you have any survey invitations. When you don't check the mail or login daily, other users will complete those surveys sooner and you might not get a chance to complete the survey.
Important Guidelines
Avoid Survey Fraud
Never use automated tools, VPNs, or provide inconsistent answers. This can result in account suspension and loss of rewards.
One Account Per Person
Maintain only one account per person. Multiple accounts from the same household or IP address may result in disqualification.
Complete Surveys Promptly
Don't leave surveys incomplete for long periods. Complete them in a reasonable timeframe to maintain your quality score.
Understanding Survey Types
Opinion Surveys
Share your thoughts on products, services, brands, and current topics. These are the most common type of surveys.
5-20 minutes
Product Testing
Test products at home and provide detailed feedback. Higher rewards but limited availability.
1-2 weeks
Focus Groups
Join group discussions on specific topics. These offer the highest rewards but are invitation-only.
1-2 hours
Profile Surveys
Complete these to help us match you with more relevant surveys. Essential for maximizing opportunities.
2-5 minutes
Member Experiences
Real experiences from real people using Relevant Reflex
"Consistent earnings over time"
"I follow all the tips mentioned here and participate regularly. The key is patience and honesty in responses. It's a genuine platform."
- Rajesh K., Software Engineer, Mumbai ✓ Verified Member
"Perfect for students"
"As a college student, this platform helps me earn useful pocket money. I complete surveys between classes and it has been a great experience so far."
- Anjali R., Student, Pune ✓ Verified Member
"Reliable supplemental income"
"Been using Relevant Reflex for over a year. It gives me a reliable supplemental income on the side. Highly recommended for anyone with spare time!"
- Meena T., Homemaker, Bangalore ✓ Verified Member
Disclaimer: These are individual member experiences. Earnings are not guaranteed and will vary based on survey availability, demographic profile, and individual participation. See our Earnings Disclaimer.
Need Help Getting Started?
Our support team is here to help you succeed with online surveys!
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking “Accept All”, you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
Thank you for registering with Relevant Reflex! To activate your account and start earning through paid surveys, please verify your email address by clicking the button below:
If you did not request a password reset, please ignore this email. Your password will not be changed.
For support: support@relevantreflex.com
';
}
}
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/errors.log
TYPE: LOG
SIZE: 0 B
------------------------------------------------------------
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/fix-rupee.php
TYPE: PHP
SIZE: 5.34 KB
------------------------------------------------------------
Rupee Fix";
echo "
Rupee Symbol Fix Script
";
if ($dryRun) {
echo "
DRY RUN MODE - No changes will be made. Add &apply=yes to URL to apply fixes.
";
} else {
echo "
APPLYING FIXES
";
}
// The broken sequence: ₹ is what ₹ looks like when UTF-8 bytes are read as Latin1
// UTF-8 for ₹ (U+20B9) is: 0xE2 0x82 0xB9
// When read as Latin1: â (0xE2) ‚ (0x82) ¹ (0xB9) = ₹
$brokenRupee = "\xC3\xA2\xC2\x82\xC2\xB9"; // Double-encoded UTF-8
$brokenRupee2 = "₹"; // As it appears in source
$replacement = "₹"; // HTML entity for ₹ - works everywhere
// Files to check (relative to this script's directory)
$baseDir = __DIR__;
$files = [
'about.php',
'admin-support.php',
'articles.php',
'dashboard.php',
'doubts.php',
'index.php',
'points-manager.php',
'profiler.php',
'redemption.php',
'signup.php',
'terms.php',
'partners/data-sync.php',
'partners/members.php',
'partners/partner-config.php',
'partners/partner-dashboard.php',
'partners/redemptions.php',
];
$totalFixed = 0;
echo "
";
echo "
File
Occurrences
Status
";
foreach ($files as $relPath) {
$fullPath = $baseDir . '/' . $relPath;
if (!file_exists($fullPath)) {
echo "
$relPath
-
File not found (skip)
";
continue;
}
$content = file_get_contents($fullPath);
// Count occurrences of both patterns
$count1 = substr_count($content, $brokenRupee);
$count2 = substr_count($content, $brokenRupee2);
$totalCount = max($count1, $count2); // They may overlap, take the higher count
// Also check for raw ₹ that might work but could break during file transfer
$rawRupee = "\xE2\x82\xB9"; // Actual UTF-8 bytes for ₹
$rawCount = substr_count($content, $rawRupee);
if ($totalCount === 0 && $rawCount === 0) {
echo "
$relPath
0
Clean
";
continue;
}
if ($totalCount > 0) {
if (!$dryRun) {
// Replace both patterns
$newContent = str_replace($brokenRupee, $replacement, $content);
$newContent = str_replace($brokenRupee2, $replacement, $newContent);
// Also replace raw ₹ with entity for safety
$newContent = str_replace($rawRupee, $replacement, $newContent);
// Don't double-replace: if ₹ already exists, don't touch it
// (the replacements above won't create doubles since we're replacing different patterns)
file_put_contents($fullPath, $newContent);
echo "
Join thousands of Indians who participate in paid market research surveys and earn rewards for sharing their opinions. Survey availability and earnings vary by member profile.
Earnings Disclaimer: Results vary. Earnings from surveys are supplemental and not guaranteed. Individual results depend on survey availability, your demographic profile, and participation frequency. See our Earnings Disclaimer for full details.
Why Choose Relevant Reflex?
We're a trusted online survey platform in India, dedicated to providing genuine earning opportunities.
Trusted & Secure
Your data is protected with industry-standard security measures. We never sell your personal information.
Verified Payments
Get paid through secure UPI transfers.
Flexible Schedule
Take surveys whenever you want, from anywhere. Perfect for students, professionals, and homemakers.
India-Focused
Surveys specifically designed for Indian consumers. Your opinions matter for local and international brands.
Mobile Friendly
Take surveys on your smartphone, tablet, or computer. Our platform works seamlessly across all devices.
24/7 Support
Our dedicated support team is here to help you with any questions or issues you may have.
What Our Members Say
Join thousands of satisfied members who are earning money with Relevant Reflex.
"I've been using Relevant Reflex for 6 months and it helps me cover small expenses. The surveys are interesting and payments are always on time!"
- Priya S., Mumbai
✓ Verified Member January 2025
"Great platform for students like me. I can take surveys between classes and earn pocket money easily."
- Rahul K., Delhi
✓ Verified Member February 2025
"Professional platform with genuine surveys. I appreciate how they respect my time and opinions."
- Sneha M., Bangalore
✓ Verified Member March 2025
Testimonials from real members. Individual results vary. See our Earnings Disclaimer.
Ready to Start Earning?
Join Relevant Reflex today and participate in genuine paid surveys!
Registration takes less than 2 minutes • 100% Free • No spam guaranteed Earnings vary by member. See Earnings Disclaimer.
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking "Accept All", you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/isec-helper.php
TYPE: PHP
SIZE: 8.81 KB
------------------------------------------------------------
[
'no_adult' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>9],
'no_formal' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>11,'degree_regular'=>10,'degree_professional'=>10],
'upto_5' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>9],
'class_6_9' => ['no_adult'=>12,'no_formal'=>11,'upto_5'=>11,'class_6_9'=>10,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>9],
'class_10_14' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>9,'degree_regular'=>8,'degree_professional'=>7],
'degree_regular' => ['no_adult'=>9,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>7,'degree_professional'=>6],
'degree_professional'=> ['no_adult'=>9,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>8,'class_10_14'=>7,'degree_regular'=>6,'degree_professional'=>6],
],
'farmer' => [
'no_adult' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>9],
'no_formal' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>11,'degree_regular'=>10,'degree_professional'=>10],
'upto_5' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>9],
'class_6_9' => ['no_adult'=>12,'no_formal'=>11,'upto_5'=>11,'class_6_9'=>10,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>9],
'class_10_14' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>9,'degree_regular'=>8,'degree_professional'=>7],
'degree_regular' => ['no_adult'=>9,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>7,'degree_professional'=>6],
'degree_professional'=> ['no_adult'=>9,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>8,'class_10_14'=>7,'degree_regular'=>6,'degree_professional'=>5],
],
'worker' => [
'no_adult' => ['no_adult'=>12,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>10,'class_10_14'=>10,'degree_regular'=>8,'degree_professional'=>8],
'no_formal' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>11,'class_6_9'=>11,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>8],
'upto_5' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>7],
'class_6_9' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>9,'class_10_14'=>9,'degree_regular'=>8,'degree_professional'=>7],
'class_10_14' => ['no_adult'=>10,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>6,'degree_professional'=>6],
'degree_regular' => ['no_adult'=>8,'no_formal'=>9,'upto_5'=>8,'class_6_9'=>8,'class_10_14'=>7,'degree_regular'=>5,'degree_professional'=>4],
'degree_professional'=> ['no_adult'=>8,'no_formal'=>9,'upto_5'=>7,'class_6_9'=>7,'class_10_14'=>5,'degree_regular'=>3,'degree_professional'=>3],
],
'trader' => [
'no_adult' => ['no_adult'=>11,'no_formal'=>12,'upto_5'=>11,'class_6_9'=>10,'class_10_14'=>9,'degree_regular'=>6,'degree_professional'=>5],
'no_formal' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>11,'class_6_9'=>10,'class_10_14'=>9,'degree_regular'=>8,'degree_professional'=>8],
'upto_5' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>8,'degree_professional'=>7],
'class_6_9' => ['no_adult'=>10,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>7,'degree_professional'=>5],
'class_10_14' => ['no_adult'=>9,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>8,'class_10_14'=>7,'degree_regular'=>5,'degree_professional'=>4],
'degree_regular' => ['no_adult'=>7,'no_formal'=>9,'upto_5'=>8,'class_6_9'=>7,'class_10_14'=>6,'degree_regular'=>3,'degree_professional'=>2],
'degree_professional'=> ['no_adult'=>6,'no_formal'=>8,'upto_5'=>6,'class_6_9'=>6,'class_10_14'=>4,'degree_regular'=>2,'degree_professional'=>2],
],
'clerical' => [
'no_adult' => ['no_adult'=>10,'no_formal'=>12,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>8,'degree_regular'=>7,'degree_professional'=>6],
'no_formal' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>10,'degree_regular'=>9,'degree_professional'=>8],
'upto_5' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>7,'degree_professional'=>7],
'class_6_9' => ['no_adult'=>10,'no_formal'=>10,'upto_5'=>9,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>7,'degree_professional'=>6],
'class_10_14' => ['no_adult'=>8,'no_formal'=>9,'upto_5'=>8,'class_6_9'=>8,'class_10_14'=>7,'degree_regular'=>6,'degree_professional'=>4],
'degree_regular' => ['no_adult'=>7,'no_formal'=>9,'upto_5'=>8,'class_6_9'=>7,'class_10_14'=>6,'degree_regular'=>4,'degree_professional'=>3],
'degree_professional'=> ['no_adult'=>6,'no_formal'=>8,'upto_5'=>7,'class_6_9'=>6,'class_10_14'=>4,'degree_regular'=>2,'degree_professional'=>2],
],
'managerial' => [
'no_adult' => ['no_adult'=>10,'no_formal'=>12,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>7,'degree_regular'=>5,'degree_professional'=>5],
'no_formal' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>10,'class_10_14'=>10,'degree_regular'=>8,'degree_professional'=>6],
'upto_5' => ['no_adult'=>11,'no_formal'=>11,'upto_5'=>10,'class_6_9'=>9,'class_10_14'=>8,'degree_regular'=>6,'degree_professional'=>6],
'class_6_9' => ['no_adult'=>9,'no_formal'=>9,'upto_5'=>9,'class_6_9'=>8,'class_10_14'=>7,'degree_regular'=>6,'degree_professional'=>6],
'class_10_14' => ['no_adult'=>7,'no_formal'=>9,'upto_5'=>8,'class_6_9'=>7,'class_10_14'=>5,'degree_regular'=>3,'degree_professional'=>3],
'degree_regular' => ['no_adult'=>6,'no_formal'=>8,'upto_5'=>7,'class_6_9'=>6,'class_10_14'=>4,'degree_regular'=>2,'degree_professional'=>1],
'degree_professional'=> ['no_adult'=>5,'no_formal'=>7,'upto_5'=>6,'class_6_9'=>5,'class_10_14'=>3,'degree_regular'=>1,'degree_professional'=>1],
],
];
}
/**
* Compute ISEC tier from the 3 profiler responses
*
* @param string $occupation - Occupation code of CWE
* @param string $maleEducation - Education code of highest educated male adult
* @param string $femaleEducation - Education code of highest educated female adult
* @return int|null - ISEC tier (1-12) or null if cannot compute
*/
function computeISECTier($occupation, $maleEducation, $femaleEducation) {
$grid = getISECGrid();
if (isset($grid[$occupation][$maleEducation][$femaleEducation])) {
return $grid[$occupation][$maleEducation][$femaleEducation];
}
return null;
}
/**
* Get SEC class label from ISEC tier
*
* @param int $tier - ISEC tier (1-12)
* @return string - SEC class (A/B/C/D/E) with description
*/
function getISECClass($tier) {
if ($tier >= 1 && $tier <= 6) return 'A';
if ($tier >= 7 && $tier <= 8) return 'B';
if ($tier >= 9 && $tier <= 10) return 'C';
if ($tier == 11) return 'D';
if ($tier == 12) return 'E';
return null;
}
/**
* Get full SEC class label with description
*/
function getISECClassLabel($tier) {
$labels = [
'A' => 'SEC A — High',
'B' => 'SEC B — Upper Middle',
'C' => 'SEC C — Middle',
'D' => 'SEC D — Lower Middle',
'E' => 'SEC E — Low',
];
$class = getISECClass($tier);
return $class ? $labels[$class] : null;
}
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/login.php
TYPE: PHP
SIZE: 27.37 KB
------------------------------------------------------------
redirectToDashboard();
}
$errors = [];
$form_data = [];
$resend_success = '';
$show_resend = false;
$resend_email = '';
// Handle resend verification request
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'resend_verification') {
$resend_email = isset($_POST['email']) ? sanitize($_POST['email']) : '';
$form_data['email'] = $resend_email;
if (empty($resend_email) || !validateEmail($resend_email)) {
$errors[] = 'Please provide a valid email address.';
} else {
try {
$db = new Database();
$pdo = $db->getConnection();
$clientIP = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
// Rate limit: max 3 resend attempts per IP per hour
try {
$stmt = $pdo->prepare("SELECT COUNT(*) as cnt FROM registration_attempts WHERE ip_address = ? AND attempt_type = 'resend_verification' AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)");
$stmt->execute([$clientIP]);
$attempts = $stmt->fetch();
if ($attempts && $attempts['cnt'] >= 3) {
$errors[] = 'Too many resend attempts. Please try again later or contact support.';
}
} catch (Exception $e) {}
if (empty($errors)) {
// Find the user
$stmt = $pdo->prepare("SELECT id, email, email_verified, status FROM users WHERE email = ?");
$stmt->execute([$resend_email]);
$user = $stmt->fetch();
if (!$user) {
// Don't reveal if email exists - show generic success
$resend_success = 'If an account with that email exists and is unverified, a new verification link has been sent. Please check your inbox and spam folder.';
} elseif ($user['email_verified']) {
$resend_success = 'This email is already verified. You can log in directly.';
} else {
// Delete old verification tokens
$pdo->prepare("DELETE FROM email_verifications WHERE user_id = ?")->execute([$user['id']]);
// Generate new token
$verificationToken = generateSecureToken();
$expiresAt = date('Y-m-d H:i:s', strtotime('+' . TOKEN_EXPIRY_HOURS . ' hours'));
$stmt = $pdo->prepare("INSERT INTO email_verifications (user_id, token, expires_at, created_at) VALUES (?, ?, ?, NOW())");
$stmt->execute([$user['id'], $verificationToken, $expiresAt]);
// Send verification email
require_once 'email.php';
$emailHandler = new EmailHandler();
$emailSent = $emailHandler->sendVerificationEmail($resend_email, $verificationToken);
if ($emailSent) {
logError('Verification email resent', ['user_id' => $user['id'], 'email' => $resend_email]);
$resend_success = 'A new verification link has been sent to your email. Please check your inbox and spam folder. The link expires in ' . TOKEN_EXPIRY_HOURS . ' hours.';
} else {
logError('Failed to resend verification email', ['user_id' => $user['id'], 'email' => $resend_email]);
$errors[] = 'Failed to send verification email. Please try again or contact support@relevantreflex.com.';
}
}
// Log the attempt
try {
$pdo->prepare("INSERT INTO registration_attempts (ip_address, email, attempt_type, success, user_agent) VALUES (?, ?, 'resend_verification', ?, ?)")
->execute([$clientIP, $resend_email, empty($errors) ? 1 : 0, $_SERVER['HTTP_USER_AGENT'] ?? '']);
} catch (Exception $e) {}
}
} catch (Exception $e) {
logError('Error in resend verification: ' . $e->getMessage());
$errors[] = 'System error. Please try again later.';
}
}
}
// Handle login form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !isset($_POST['action'])) {
// Initialize database
try {
$db = new Database();
$pdo = $db->getConnection();
} catch (Exception $e) {
logError('Database connection failed in login.php: ' . $e->getMessage());
$errors[] = 'System error. Please try again later.';
}
if (empty($errors)) {
// Get and sanitize form data
$email = isset($_POST['email']) ? sanitize($_POST['email']) : '';
$password = isset($_POST['password']) ? $_POST['password'] : '';
$rememberMe = isset($_POST['remember_me']) ? true : false;
// Store email for form repopulation
$form_data['email'] = $email;
// Validation
if (empty($email) || empty($password)) {
$errors[] = 'Please provide both email and password.';
} elseif (!validateEmail($email)) {
$errors[] = 'Please provide a valid email address.';
} else {
try {
// Find user by email
$stmt = $pdo->prepare("
SELECT id, email, password, email_verified, status, last_login
FROM users
WHERE email = ?
");
$stmt->execute([$email]);
$user = $stmt->fetch();
if (!$user) {
// Log failed login attempt
logError('Login attempt with non-existent email', ['email' => $email]);
$errors[] = 'Invalid email or password.';
} elseif (!verifyPassword($password, $user['password'])) {
logError('Login attempt with incorrect password', ['email' => $email]);
$errors[] = 'Invalid email or password.';
} elseif (!$user['email_verified']) {
$errors[] = 'Your email is not yet verified.';
$show_resend = true;
$resend_email = $email;
} elseif ($user['status'] !== 'active') {
$message = 'Your account is currently ' . $user['status'] . '.';
if ($user['status'] === 'suspended') {
$message .= ' Please contact support for assistance.';
}
$errors[] = $message;
} else {
// Login successful - create session
session_start();
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_email'] = $user['email'];
$_SESSION['logged_in'] = true;
$_SESSION['login_time'] = time();
// Update last login time
$stmt = $pdo->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
$stmt->execute([$user['id']]);
// Set remember me cookie if requested (30 days)
if ($rememberMe) {
$sessionToken = generateSecureToken();
$expiresAt = date('Y-m-d H:i:s', strtotime('+30 days'));
// Store session token in database
$stmt = $pdo->prepare("
INSERT INTO user_sessions (user_id, session_token, expires_at)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
session_token = VALUES(session_token),
expires_at = VALUES(expires_at)
");
$stmt->execute([$user['id'], $sessionToken, $expiresAt]);
// Set cookie
setcookie('remember_token', $sessionToken, time() + (30 * 24 * 60 * 60), '/', '', true, true);
}
// Clean up expired sessions
$pdo->prepare("DELETE FROM user_sessions WHERE expires_at < NOW()")->execute();
// Log successful login
logError('User login successful', [
'user_id' => $user['id'],
'email' => $user['email'],
'remember_me' => $rememberMe
]);
// Redirect to dashboard
header('Location: dashboard.php');
exit;
}
} catch (PDOException $e) {
logError('Database error during login', [
'error' => $e->getMessage(),
'email' => $email
]);
$errors[] = 'Login failed due to a system error. Please try again later.';
} catch (Exception $e) {
logError('General error during login', [
'error' => $e->getMessage(),
'email' => $email
]);
$errors[] = 'An unexpected error occurred. Please try again later.';
}
}
}
}
?>
Login - Relevant Reflex Paid Online Surveys India
Login to your Account!
You can take Online paid Surveys, Redeem your reward points and update profile - all in one place.
Welcome to Relevant Reflex ("we," "our," or "us"). We are committed to protecting your privacy and ensuring the security of your personal information. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our online survey platform and related services.
Key Principle: We believe in transparency and will never sell your personal data to third parties for marketing purposes.
By using our services, you agree to the collection and use of information in accordance with this Privacy Policy. If you disagree with any part of this policy, please do not use our services.
2. Information We Collect
2.1 Personal Information
We collect the following types of personal information:
Registration Information: Name, email address, date of birth, gender, postal code
Profile Information: Occupation, income range, interests, preferences, household information
Survey Responses: Your answers to survey questions and research studies
Communication Data: Messages you send to our support team
2.2 Technical Information
IP address and location data
Browser type and version
Device information (type, operating system)
Usage data (pages visited, time spent, click patterns)
Cookies and similar tracking technologies
2.3 Financial Information
For payment processing, we may collect:
UPI ID or UPI-linked mobile number (for reward transfers)
Bank account details (for direct transfers)
Payment method preferences
3. How We Use Your Information
3.1 Primary Uses
Survey Matching: To match you with relevant survey opportunities based on your demographics and interests
Account Management: To create and maintain your account, process registrations, and provide customer support
Payment Processing: To calculate, process, and distribute rewards for completed surveys
Communication: To send you survey invitations, account updates, and important service announcements
3.2 Secondary Uses
To improve our platform and user experience
To prevent fraud and maintain platform security
To comply with legal obligations and regulatory requirements
To conduct internal research and analytics
Legal Basis: We process your data based on consent, legitimate interests, contract performance, and legal obligations as per applicable Indian data protection laws.
4. Information Sharing and Disclosure
4.1 Survey Partners
We may share anonymized or aggregated survey data with our research partners and clients. Individual responses are never linked to personal identifiers without explicit consent.
4.2 Service Providers
We work with trusted third-party service providers who assist us with:
Payment processing
Email delivery services
Data hosting and security
Customer support platforms
4.3 Legal Requirements
We may disclose your information if required by law, court order, or to:
Comply with legal processes
Protect our rights and property
Prevent fraud or security threats
Protect the safety of our users
4.4 Business Transfers
In the event of a merger, acquisition, or sale of assets, your information may be transferred as part of the business transaction.
5. Data Security
5.1 Security Measures
We implement industry-standard security measures to protect your information:
SSL encryption for all data transmissions
Secure database storage with access controls
Regular security audits and updates
Employee training on data protection
Multi-factor authentication for admin access
5.2 Data Breach Response
In the unlikely event of a data breach, we will:
Notify affected users within 72 hours
Report to relevant authorities as required
Take immediate steps to secure the breach
Provide guidance on protective measures
6. Your Rights and Choices
Under applicable data protection laws, you have the following rights:
6.1 Access and Portability
Request a copy of your personal data
Download your data in a portable format
View your survey history and earnings
6.2 Correction and Updates
Update your profile information
Correct inaccurate data
Modify communication preferences
6.3 Deletion and Restriction
Request deletion of your account and data
Restrict processing of certain information
Object to specific uses of your data
Exercise Your Rights: To exercise any of these rights, contact us at privacy@relevantreflex.com or through your account settings.
7. Cookies and Tracking Technologies
7.1 Types of Cookies We Use
Essential Cookies: Required for basic platform functionality
Performance Cookies: Help us analyze platform usage and improve performance
Functional Cookies: Remember your preferences and settings
Targeting Cookies: Used to deliver relevant survey opportunities
7.2 Advertising and Analytics Cookies
We use third-party advertising and analytics services, including Google Ads and Google Analytics. These services may set cookies on your device to:
Measure the effectiveness of our advertising campaigns
Show you relevant advertisements on other websites
Analyze how visitors use our website
Google's use of advertising cookies enables it to serve ads based on your prior visits to our site. You may opt out of personalized advertising by visiting Google Ad Settings.
On your first visit to our website, you will see a cookie consent banner. You may accept all cookies or decline non-essential cookies. Essential cookies required for the platform to function will always remain active. You can change your preferences at any time by clearing your browser cookies.
7.4 Cookie Management
You can control cookies through your browser settings. However, disabling certain cookies may limit platform functionality.
8. Data Retention
We retain your information for the following periods:
Active Accounts: Data retained while account is active
Inactive Accounts: Data retained for 2 years after last activity
Survey Data: Anonymized responses may be retained for research purposes
Financial Records: Retained for 7 years as per legal requirements
Marketing Communications: Until you unsubscribe
9. Children's Privacy
Our services are not intended for individuals under 18 years of age. We do not knowingly collect personal information from children. If we discover that we have collected information from a child, we will delete it immediately.
Parents or guardians who believe their child has provided information to us should contact us immediately.
10. International Data Transfers
While we primarily operate within India, some of our service providers may be located internationally. When we transfer data outside India, we ensure:
Adequate protection through contractual safeguards
Compliance with applicable data transfer regulations
Use of standard contractual clauses where required
11. Changes to This Privacy Policy
We may update this Privacy Policy periodically to reflect changes in our practices or applicable laws. We will:
Notify users of material changes via email
Post updates on our website
Provide a clear summary of changes
Allow reasonable time for review before changes take effect
Continued use of our services after policy updates constitutes acceptance of the changes.
12. Contact Us
If you have questions about this Privacy Policy or our data practices, please contact us:
Response Time: We aim to respond to all privacy-related inquiries within 30 days.
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking “Accept All”, you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/profiler-api.php
TYPE: PHP
SIZE: 5.66 KB
------------------------------------------------------------
'Not authenticated']);
exit;
}
$user = getCurrentUser();
if (!$user) {
echo json_encode(['error' => 'User not found']);
exit;
}
// Initialize database
try {
$db = new Database();
$pdo = $db->getConnection();
} catch (Exception $e) {
echo json_encode(['error' => 'Database connection failed']);
exit;
}
$action = isset($_GET['action']) ? $_GET['action'] : '';
switch ($action) {
case 'status':
getProfilerStatus($pdo, $user['id']);
break;
case 'points':
getUserPointsStatus($user['id']);
break;
case 'completion':
getCompletionSummary($pdo, $user['id']);
break;
default:
echo json_encode(['error' => 'Invalid action']);
}
function getProfilerStatus($pdo, $userId) {
$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',
'household_classification' => 'Household Classification (ISEC)'
];
$completion = [];
$totalCompleted = 0;
try {
$stmt = $pdo->prepare("SELECT section, completion_percentage, is_completed, points_awarded FROM profiler_completion WHERE user_id = ?");
$stmt->execute([$userId]);
while ($row = $stmt->fetch()) {
$completion[$row['section']] = [
'name' => $profilerSections[$row['section']],
'percentage' => floatval($row['completion_percentage']),
'completed' => boolval($row['is_completed']),
'points_awarded' => boolval($row['points_awarded'])
];
if ($row['is_completed']) {
$totalCompleted++;
}
}
// Add sections not started
foreach ($profilerSections as $key => $name) {
if (!isset($completion[$key])) {
$completion[$key] = [
'name' => $name,
'percentage' => 0,
'completed' => false,
'points_awarded' => false
];
}
}
// Check mobile verification status
$stmt = $pdo->prepare("SELECT is_verified FROM mobile_verifications WHERE user_id = ?");
$stmt->execute([$userId]);
$mobileVerified = $stmt->fetch();
echo json_encode([
'success' => true,
'sections' => $completion,
'total_sections' => count($profilerSections),
'completed_sections' => $totalCompleted,
'overall_percentage' => round(($totalCompleted / count($profilerSections)) * 100, 2),
'mobile_verified' => $mobileVerified ? boolval($mobileVerified['is_verified']) : false
]);
} catch (Exception $e) {
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}
}
function getUserPointsStatus($userId) {
$pm = new PointsManager();
$points = $pm->getUserPoints($userId);
$nextTier = $pm->getNextRedemptionTier($points['points']);
echo json_encode([
'success' => true,
'points' => $points,
'next_tier' => $nextTier,
'can_redeem' => $points['points'] >= 500,
'rupee_value' => $points['points'] * 0.5
]);
}
function getCompletionSummary($pdo, $userId) {
try {
// Get overall completion stats
$stmt = $pdo->prepare("
SELECT
COUNT(*) as total_sections,
SUM(CASE WHEN is_completed = 1 THEN 1 ELSE 0 END) as completed_sections,
SUM(CASE WHEN points_awarded = 1 THEN 1 ELSE 0 END) as points_awarded_sections
FROM profiler_completion
WHERE user_id = ?
");
$stmt->execute([$userId]);
$stats = $stmt->fetch();
if (!$stats) {
$stats = ['total_sections' => 0, 'completed_sections' => 0, 'points_awarded_sections' => 0];
}
// Get recent transactions
$stmt = $pdo->prepare("
SELECT transaction_type, points, source, description, created_at
FROM point_transactions
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT 5
");
$stmt->execute([$userId]);
$recentTransactions = $stmt->fetchAll();
// Get user points
$pm = new PointsManager();
$points = $pm->getUserPoints($userId);
echo json_encode([
'success' => true,
'completion_stats' => $stats,
'points_summary' => $points,
'recent_transactions' => $recentTransactions,
'potential_earnings' => [
'total_possible' => 90, // 10 sections × 5 points + 20 (ISEC) + 10 bonus + 10 mobile
'remaining' => max(0, 70 - $points['total_earned'])
]
]);
} catch (Exception $e) {
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
}
}
?>
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/profiler.php
TYPE: PHP
SIZE: 73.69 KB
------------------------------------------------------------
redirectToLogin('Session expired. Please log in again.');
}
// Initialize database
try {
$db = new Database();
$pdo = $db->getConnection();
} catch (Exception $e) {
logError('Database connection failed in profiler.php: ' . $e->getMessage());
die('System error. Please try again later.');
}
// Define all profiler sections with their questions
$profilerSections = [
'personal_background' => [
'name' => 'Personal Background',
'description' => 'Tell us about your education, work, and personal details',
'questions' => [
'education_level' => [
'question' => 'What is your highest level of education?',
'type' => 'single',
'options' => [
'below_10th' => 'Below 10th Standard',
'10th_pass' => '10th Standard',
'12th_pass' => '12th Standard/Intermediate',
'diploma' => 'Diploma/ITI',
'graduation' => 'Graduation (Bachelor\'s)',
'post_graduation' => 'Post Graduation (Master\'s)',
'professional' => 'Professional Degree (CA/CS/Engineering/Medical)',
'doctorate' => 'Doctorate/PhD'
]
],
'employment_status' => [
'question' => 'What is your current employment status?',
'type' => 'single',
'options' => [
'student' => 'Student',
'employed_private' => 'Employed - Private Sector',
'employed_government' => 'Employed - Government/Public Sector',
'self_employed' => 'Self Employed/Business Owner',
'freelancer' => 'Freelancer/Consultant',
'homemaker' => 'Homemaker',
'retired' => 'Retired',
'unemployed' => 'Currently Unemployed'
]
],
'occupation_sector' => [
'question' => 'Which sector do you work in? (Skip if not applicable)',
'type' => 'single',
'options' => [
'it_software' => 'IT/Software',
'banking_finance' => 'Banking/Finance',
'healthcare' => 'Healthcare/Medical',
'education' => 'Education/Teaching',
'manufacturing' => 'Manufacturing',
'retail_sales' => 'Retail/Sales',
'government' => 'Government Services',
'agriculture' => 'Agriculture/Farming',
'media_entertainment' => 'Media/Entertainment',
'other' => 'Other'
]
],
'monthly_income' => [
'question' => 'What is your monthly personal income range?',
'type' => 'single',
'options' => [
'no_income' => 'No Income',
'below_15k' => 'Below ₹15,000',
'15k_30k' => '₹15,000 - ₹30,000',
'30k_50k' => '₹30,000 - ₹50,000',
'50k_75k' => '₹50,000 - ₹75,000',
'75k_1l' => '₹75,000 - ₹1,00,000',
'1l_2l' => '₹1,00,000 - ₹2,00,000',
'above_2l' => 'Above ₹2,00,000'
]
],
'work_experience' => [
'question' => 'How many years of work experience do you have?',
'type' => 'single',
'options' => [
'fresher' => 'Fresher (0 years)',
'1_2_years' => '1-2 years',
'3_5_years' => '3-5 years',
'6_10_years' => '6-10 years',
'11_15_years' => '11-15 years',
'above_15_years' => 'More than 15 years'
]
],
'language_preference' => [
'question' => 'Which languages are you comfortable with? (Select all that apply)',
'type' => 'multiple',
'options' => [
'hindi' => 'Hindi',
'english' => 'English',
'tamil' => 'Tamil',
'telugu' => 'Telugu',
'bengali' => 'Bengali',
'marathi' => 'Marathi',
'gujarati' => 'Gujarati',
'kannada' => 'Kannada',
'malayalam' => 'Malayalam',
'punjabi' => 'Punjabi',
'other' => 'Other'
]
]
]
],
'household_family' => [
'name' => 'Household & Family',
'description' => 'Share information about your household and family',
'questions' => [
'family_size' => [
'question' => 'How many people live in your household?',
'type' => 'single',
'options' => [
'1' => '1 (Just me)',
'2' => '2 people',
'3' => '3 people',
'4' => '4 people',
'5' => '5 people',
'6_plus' => '6 or more people'
]
],
'marital_status' => [
'question' => 'What is your marital status?',
'type' => 'single',
'options' => [
'single' => 'Single',
'married' => 'Married',
'divorced' => 'Divorced',
'widowed' => 'Widowed',
'in_relationship' => 'In a relationship'
]
],
'children' => [
'question' => 'Do you have children?',
'type' => 'single',
'options' => [
'no_children' => 'No children',
'expecting' => 'Expecting first child',
'1_child' => '1 child',
'2_children' => '2 children',
'3_children' => '3 children',
'4_plus_children' => '4 or more children'
]
],
'children_age_groups' => [
'question' => 'If you have children, what are their age groups? (Select all that apply)',
'type' => 'multiple',
'options' => [
'infant' => 'Infant (0-2 years)',
'toddler' => 'Toddler (3-5 years)',
'child' => 'Child (6-12 years)',
'teenager' => 'Teenager (13-18 years)',
'adult' => 'Adult (18+ years)',
'not_applicable' => 'Not applicable'
]
],
'house_type' => [
'question' => 'What type of housing do you live in?',
'type' => 'single',
'options' => [
'apartment' => 'Apartment/Flat',
'independent_house' => 'Independent House',
'villa' => 'Villa',
'row_house' => 'Row House/Townhouse',
'rented_room' => 'Rented Room',
'hostel_pg' => 'Hostel/PG',
'other' => 'Other'
]
],
'house_ownership' => [
'question' => 'Is your house?',
'type' => 'single',
'options' => [
'owned' => 'Owned by family',
'rented' => 'Rented',
'company_provided' => 'Company provided',
'family_owned' => 'Joint family property',
'other' => 'Other'
]
],
'pet_ownership' => [
'question' => 'Do you have any pets?',
'type' => 'multiple',
'options' => [
'dog' => 'Dog',
'cat' => 'Cat',
'bird' => 'Birds',
'fish' => 'Fish',
'other_pet' => 'Other pets',
'no_pets' => 'No pets'
]
],
'household_income' => [
'question' => 'What is your total monthly household income?',
'type' => 'single',
'options' => [
'below_15k' => 'Below ₹15,000',
'15k_25k' => '₹15,000 - ₹25,000',
'25k_50k' => '₹25,000 - ₹50,000',
'50k_75k' => '₹50,000 - ₹75,000',
'75k_1l' => '₹75,000 - ₹1,00,000',
'1l_2l' => '₹1,00,000 - ₹2,00,000',
'2l_5l' => '₹2,00,000 - ₹5,00,000',
'above_5l' => 'Above ₹5,00,000',
'prefer_not' => 'Prefer not to say'
]
]
]
],
'shopping_lifestyle' => [
'name' => 'Shopping & Lifestyle',
'description' => 'Tell us about your shopping habits and lifestyle preferences',
'questions' => [
'shopping_frequency' => [
'question' => 'How often do you shop for non-essential items?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'weekly' => 'Weekly',
'bi_weekly' => 'Bi-weekly',
'monthly' => 'Monthly',
'occasionally' => 'Occasionally',
'rarely' => 'Rarely'
]
],
'shopping_preference' => [
'question' => 'Where do you prefer to shop? (Select all that apply)',
'type' => 'multiple',
'options' => [
'online' => 'Online (e-commerce websites)',
'malls' => 'Shopping malls',
'local_stores' => 'Local stores/markets',
'supermarkets' => 'Supermarkets',
'brand_stores' => 'Brand exclusive stores',
'wholesale_markets' => 'Wholesale markets'
]
],
'monthly_shopping_budget' => [
'question' => 'What is your monthly shopping budget for non-essential items?',
'type' => 'single',
'options' => [
'below_2k' => 'Below ₹2,000',
'2k_5k' => '₹2,000 - ₹5,000',
'5k_10k' => '₹5,000 - ₹10,000',
'10k_20k' => '₹10,000 - ₹20,000',
'20k_50k' => '₹20,000 - ₹50,000',
'above_50k' => 'Above ₹50,000'
]
],
'brand_consciousness' => [
'question' => 'How important are brands to you when making purchase decisions?',
'type' => 'single',
'options' => [
'very_important' => 'Very important - I only buy branded products',
'somewhat_important' => 'Somewhat important - I prefer brands but consider alternatives',
'neutral' => 'Neutral - Brand doesn\'t matter much',
'not_important' => 'Not important - I focus on value and quality',
'avoid_brands' => 'I actively avoid expensive brands'
]
],
'online_shopping_frequency' => [
'question' => 'How often do you shop online?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'quarterly' => 'Quarterly',
'rarely' => 'Rarely',
'never' => 'Never'
]
],
'lifestyle_interests' => [
'question' => 'What are your main lifestyle interests? (Select all that apply)',
'type' => 'multiple',
'options' => [
'fitness' => 'Fitness and health',
'cooking' => 'Cooking and food',
'travel' => 'Travel and exploration',
'fashion' => 'Fashion and style',
'home_decor' => 'Home decoration',
'gadgets' => 'Technology and gadgets',
'books' => 'Reading and books',
'movies' => 'Movies and entertainment',
'music' => 'Music',
'sports' => 'Sports',
'art' => 'Art and culture'
]
],
'social_media_usage' => [
'question' => 'Which social media platforms do you actively use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'facebook' => 'Facebook',
'instagram' => 'Instagram',
'twitter' => 'Twitter/X',
'linkedin' => 'LinkedIn',
'youtube' => 'YouTube',
'whatsapp' => 'WhatsApp',
'telegram' => 'Telegram',
'snapchat' => 'Snapchat',
'tiktok' => 'TikTok/Reels',
'none' => 'I don\'t use social media'
]
]
]
],
'technology_digital' => [
'name' => 'Technology & Digital',
'description' => 'Share your technology usage and digital preferences',
'questions' => [
'smartphone_brand' => [
'question' => 'Which smartphone brand do you currently use?',
'type' => 'single',
'options' => [
'samsung' => 'Samsung',
'apple' => 'Apple iPhone',
'xiaomi' => 'Xiaomi/Mi/Redmi',
'oneplus' => 'OnePlus',
'oppo' => 'Oppo',
'vivo' => 'Vivo',
'realme' => 'Realme',
'google' => 'Google Pixel',
'motorola' => 'Motorola',
'other' => 'Other'
]
],
'internet_usage_hours' => [
'question' => 'How many hours do you spend on the internet daily?',
'type' => 'single',
'options' => [
'1_2_hours' => '1-2 hours',
'3_4_hours' => '3-4 hours',
'5_6_hours' => '5-6 hours',
'7_8_hours' => '7-8 hours',
'9_10_hours' => '9-10 hours',
'more_than_10' => 'More than 10 hours'
]
],
'primary_internet_activity' => [
'question' => 'What do you primarily use the internet for? (Select all that apply)',
'type' => 'multiple',
'options' => [
'social_media' => 'Social media',
'entertainment' => 'Entertainment (videos, music)',
'work' => 'Work/Professional',
'shopping' => 'Online shopping',
'news' => 'News and information',
'education' => 'Learning and education',
'gaming' => 'Gaming',
'communication' => 'Communication (calls, messages)',
'banking' => 'Banking and financial services'
]
],
'streaming_services' => [
'question' => 'Which streaming services do you use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'netflix' => 'Netflix',
'amazon_prime' => 'Amazon Prime Video',
'hotstar' => 'Disney+ Hotstar',
'youtube_premium' => 'YouTube Premium',
'sony_liv' => 'Sony LIV',
'zee5' => 'ZEE5',
'voot' => 'Voot',
'mx_player' => 'MX Player',
'spotify' => 'Spotify',
'none' => 'None of these'
]
],
'online_payment_methods' => [
'question' => 'Which online payment methods do you use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'upi' => 'UPI (PhonePe, GooglePay, Paytm)',
'credit_card' => 'Credit Card',
'debit_card' => 'Debit Card',
'net_banking' => 'Net Banking',
'digital_wallet' => 'Digital Wallets',
'cod' => 'Cash on Delivery',
'bank_transfer' => 'Bank Transfer'
]
],
'tech_comfort_level' => [
'question' => 'How would you rate your comfort level with technology?',
'type' => 'single',
'options' => [
'expert' => 'Expert - I\'m very tech-savvy',
'advanced' => 'Advanced - I\'m comfortable with most tech',
'intermediate' => 'Intermediate - I can handle basic to moderate tech tasks',
'beginner' => 'Beginner - I use basic features only',
'minimal' => 'Minimal - I struggle with technology'
]
],
'smart_devices_owned' => [
'question' => 'Which smart devices do you own? (Select all that apply)',
'type' => 'multiple',
'options' => [
'smart_tv' => 'Smart TV',
'smart_speaker' => 'Smart Speaker (Alexa, Google Home)',
'smartwatch' => 'Smartwatch/Fitness Tracker',
'laptop' => 'Laptop',
'tablet' => 'Tablet',
'gaming_console' => 'Gaming Console',
'smart_home' => 'Smart Home Devices',
'none' => 'None of these'
]
]
]
],
'travel_transportation' => [
'name' => 'Travel & Transportation',
'description' => 'Tell us about your travel habits and transportation preferences',
'questions' => [
'travel_frequency' => [
'question' => 'How often do you travel for leisure/vacation?',
'type' => 'single',
'options' => [
'monthly' => 'Monthly',
'quarterly' => 'Every 3-4 months',
'twice_yearly' => 'Twice a year',
'annually' => 'Once a year',
'rarely' => 'Rarely (once in 2-3 years)',
'never' => 'Never'
]
],
'travel_destinations' => [
'question' => 'What type of destinations do you prefer? (Select all that apply)',
'type' => 'multiple',
'options' => [
'domestic_cities' => 'Domestic cities',
'hill_stations' => 'Hill stations',
'beaches' => 'Beaches',
'historical_places' => 'Historical places',
'religious_places' => 'Religious places',
'international' => 'International destinations',
'adventure_spots' => 'Adventure destinations',
'family_spots' => 'Family-friendly places'
]
],
'accommodation_preference' => [
'question' => 'What type of accommodation do you prefer while traveling?',
'type' => 'single',
'options' => [
'luxury_hotels' => 'Luxury hotels (5-star)',
'mid_range_hotels' => 'Mid-range hotels (3-4 star)',
'budget_hotels' => 'Budget hotels',
'resorts' => 'Resorts',
'homestays' => 'Homestays',
'hostels' => 'Hostels',
'airbnb' => 'Airbnb/Rental apartments',
'family_friends' => 'Stay with family/friends'
]
],
'daily_commute_mode' => [
'question' => 'What is your primary mode of daily transportation?',
'type' => 'single',
'options' => [
'own_car' => 'Own car',
'own_bike' => 'Own bike/scooter',
'public_transport' => 'Public transport (bus, metro)',
'auto_rickshaw' => 'Auto rickshaw',
'taxi_cab' => 'Taxi/Cab services',
'ride_sharing' => 'Ride sharing (Ola, Uber)',
'walking' => 'Walking',
'cycling' => 'Cycling',
'work_from_home' => 'Work from home (no commute)'
]
],
'vehicle_ownership' => [
'question' => 'Which vehicles do you own? (Select all that apply)',
'type' => 'multiple',
'options' => [
'car' => 'Car',
'motorcycle' => 'Motorcycle',
'scooter' => 'Scooter',
'bicycle' => 'Bicycle',
'electric_vehicle' => 'Electric vehicle',
'none' => 'None'
]
],
'fuel_type_preference' => [
'question' => 'If you own a vehicle, what fuel type do you prefer?',
'type' => 'single',
'options' => [
'petrol' => 'Petrol',
'diesel' => 'Diesel',
'cng' => 'CNG',
'electric' => 'Electric',
'hybrid' => 'Hybrid',
'not_applicable' => 'Not applicable (don\'t own vehicle)'
]
],
'ride_sharing_usage' => [
'question' => 'How often do you use ride-sharing services (Ola, Uber)?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'occasionally' => 'Occasionally',
'rarely' => 'Rarely',
'never' => 'Never'
]
]
]
],
'health_fitness' => [
'name' => 'Health & Fitness',
'description' => 'Share your health and fitness preferences and habits',
'questions' => [
'exercise_frequency' => [
'question' => 'How often do you exercise or engage in physical activities?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'few_times_week' => 'Few times a week',
'weekly' => 'Once a week',
'monthly' => 'Few times a month',
'rarely' => 'Rarely',
'never' => 'Never'
]
],
'exercise_types' => [
'question' => 'What types of physical activities do you engage in? (Select all that apply)',
'type' => 'multiple',
'options' => [
'gym' => 'Gym workouts',
'running' => 'Running/Jogging',
'walking' => 'Walking',
'yoga' => 'Yoga',
'cycling' => 'Cycling',
'swimming' => 'Swimming',
'sports' => 'Sports (cricket, football, etc.)',
'dancing' => 'Dancing',
'home_workouts' => 'Home workouts',
'none' => 'None'
]
],
'diet_preference' => [
'question' => 'What is your dietary preference?',
'type' => 'single',
'options' => [
'vegetarian' => 'Vegetarian',
'non_vegetarian' => 'Non-vegetarian',
'vegan' => 'Vegan',
'jain_vegetarian' => 'Jain vegetarian',
'eggetarian' => 'Eggetarian',
'flexitarian' => 'Flexitarian (mostly vegetarian)',
'no_preference' => 'No specific preference'
]
],
'health_concerns' => [
'question' => 'Do you have any of these health concerns? (Select all that apply)',
'type' => 'multiple',
'options' => [
'diabetes' => 'Diabetes',
'hypertension' => 'High blood pressure',
'heart_disease' => 'Heart disease',
'obesity' => 'Weight management issues',
'allergies' => 'Allergies',
'digestive_issues' => 'Digestive issues',
'mental_health' => 'Mental health concerns',
'none' => 'None',
'prefer_not_say' => 'Prefer not to say'
]
],
'healthcare_spending' => [
'question' => 'How much do you spend on healthcare annually?',
'type' => 'single',
'options' => [
'below_10k' => 'Below ₹10,000',
'10k_25k' => '₹10,000 - ₹25,000',
'25k_50k' => '₹25,000 - ₹50,000',
'50k_1l' => '₹50,000 - ₹1,00,000',
'above_1l' => 'Above ₹1,00,000',
'not_sure' => 'Not sure'
]
],
'health_insurance' => [
'question' => 'Do you have health insurance?',
'type' => 'single',
'options' => [
'employer_provided' => 'Yes, provided by employer',
'personal_policy' => 'Yes, personal policy',
'family_floater' => 'Yes, family floater policy',
'government_scheme' => 'Yes, government scheme',
'no_insurance' => 'No health insurance',
'not_sure' => 'Not sure'
]
],
'wellness_interests' => [
'question' => 'Which wellness activities interest you? (Select all that apply)',
'type' => 'multiple',
'options' => [
'meditation' => 'Meditation',
'spa_treatments' => 'Spa treatments',
'nutrition_counseling' => 'Nutrition counseling',
'fitness_training' => 'Personal fitness training',
'alternative_medicine' => 'Alternative medicine',
'mental_health_support' => 'Mental health support',
'wellness_retreats' => 'Wellness retreats',
'none' => 'None of these'
]
]
]
],
'entertainment_media' => [
'name' => 'Entertainment & Media',
'description' => 'Tell us about your entertainment preferences and media consumption',
'questions' => [
'tv_watching_hours' => [
'question' => 'How many hours do you watch TV/streaming content daily?',
'type' => 'single',
'options' => [
'none' => 'I don\'t watch TV',
'1_hour' => 'Less than 1 hour',
'1_2_hours' => '1-2 hours',
'2_3_hours' => '2-3 hours',
'3_5_hours' => '3-5 hours',
'more_than_5' => 'More than 5 hours'
]
],
'content_preferences' => [
'question' => 'What type of content do you prefer? (Select all that apply)',
'type' => 'multiple',
'options' => [
'bollywood_movies' => 'Bollywood movies',
'hollywood_movies' => 'Hollywood movies',
'regional_movies' => 'Regional movies',
'tv_serials' => 'TV serials/shows',
'reality_shows' => 'Reality shows',
'news' => 'News',
'documentaries' => 'Documentaries',
'comedy_shows' => 'Comedy shows',
'sports' => 'Sports',
'music_videos' => 'Music videos'
]
],
'movie_genres' => [
'question' => 'Which movie genres do you enjoy? (Select all that apply)',
'type' => 'multiple',
'options' => [
'action' => 'Action',
'comedy' => 'Comedy',
'drama' => 'Drama',
'romance' => 'Romance',
'thriller' => 'Thriller',
'horror' => 'Horror',
'sci_fi' => 'Science Fiction',
'documentary' => 'Documentary',
'biography' => 'Biography',
'animation' => 'Animation'
]
],
'music_preferences' => [
'question' => 'What type of music do you listen to? (Select all that apply)',
'type' => 'multiple',
'options' => [
'bollywood' => 'Bollywood',
'classical_indian' => 'Classical Indian',
'devotional' => 'Devotional/Religious',
'pop' => 'Pop',
'rock' => 'Rock',
'hip_hop' => 'Hip Hop',
'electronic' => 'Electronic/EDM',
'folk' => 'Folk',
'international' => 'International',
'regional' => 'Regional'
]
],
'gaming_habits' => [
'question' => 'How often do you play games (mobile, PC, console)?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'few_times_week' => 'Few times a week',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'rarely' => 'Rarely',
'never' => 'Never'
]
],
'reading_habits' => [
'question' => 'How often do you read books, magazines, or blogs?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'few_times_week' => 'Few times a week',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'rarely' => 'Rarely',
'never' => 'Never'
]
],
'content_consumption_device' => [
'question' => 'Which device do you primarily use for entertainment? (Select all that apply)',
'type' => 'multiple',
'options' => [
'smartphone' => 'Smartphone',
'smart_tv' => 'Smart TV',
'laptop' => 'Laptop',
'tablet' => 'Tablet',
'desktop' => 'Desktop computer',
'gaming_console' => 'Gaming console',
'traditional_tv' => 'Traditional TV'
]
],
'entertainment_spending' => [
'question' => 'How much do you spend on entertainment monthly?',
'type' => 'single',
'options' => [
'below_500' => 'Below ₹500',
'500_1000' => '₹500 - ₹1,000',
'1000_2000' => '₹1,000 - ₹2,000',
'2000_5000' => '₹2,000 - ₹5,000',
'above_5000' => 'Above ₹5,000',
'not_sure' => 'Not sure'
]
]
]
],
'food_dining' => [
'name' => 'Food & Dining',
'description' => 'Share your food preferences and dining habits',
'questions' => [
'cooking_frequency' => [
'question' => 'How often do you cook at home?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'few_times_week' => 'Few times a week',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'rarely' => 'Rarely',
'never' => 'Never - I don\'t cook'
]
],
'cuisine_preferences' => [
'question' => 'Which cuisines do you enjoy? (Select all that apply)',
'type' => 'multiple',
'options' => [
'north_indian' => 'North Indian',
'south_indian' => 'South Indian',
'regional_local' => 'Regional/Local cuisine',
'chinese' => 'Chinese',
'italian' => 'Italian',
'continental' => 'Continental',
'mexican' => 'Mexican',
'thai' => 'Thai',
'japanese' => 'Japanese',
'fast_food' => 'Fast food'
]
],
'dining_out_frequency' => [
'question' => 'How often do you dine out or order food?',
'type' => 'single',
'options' => [
'daily' => 'Daily',
'few_times_week' => 'Few times a week',
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'occasionally' => 'Occasionally',
'rarely' => 'Rarely'
]
],
'food_delivery_apps' => [
'question' => 'Which food delivery apps do you use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'zomato' => 'Zomato',
'swiggy' => 'Swiggy',
'uber_eats' => 'Uber Eats',
'dominos' => 'Domino\'s',
'pizza_hut' => 'Pizza Hut',
'restaurant_direct' => 'Restaurant direct delivery',
'none' => 'None - I don\'t use food delivery'
]
],
'food_spending_monthly' => [
'question' => 'How much do you spend on food (including dining out) monthly?',
'type' => 'single',
'options' => [
'below_3k' => 'Below ₹3,000',
'3k_5k' => '₹3,000 - ₹5,000',
'5k_8k' => '₹5,000 - ₹8,000',
'8k_12k' => '₹8,000 - ₹12,000',
'12k_20k' => '₹12,000 - ₹20,000',
'above_20k' => 'Above ₹20,000'
]
],
'special_dietary_requirements' => [
'question' => 'Do you have any special dietary requirements? (Select all that apply)',
'type' => 'multiple',
'options' => [
'gluten_free' => 'Gluten-free',
'dairy_free' => 'Dairy-free',
'sugar_free' => 'Sugar-free/Low sugar',
'low_sodium' => 'Low sodium',
'organic_only' => 'Organic food only',
'weight_management' => 'Weight management diet',
'diabetic_friendly' => 'Diabetic-friendly',
'none' => 'No special requirements'
]
],
'grocery_shopping_preference' => [
'question' => 'Where do you prefer to buy groceries? (Select all that apply)',
'type' => 'multiple',
'options' => [
'local_stores' => 'Local grocery stores',
'supermarkets' => 'Supermarkets',
'online_delivery' => 'Online grocery delivery',
'wholesale_markets' => 'Wholesale markets',
'organic_stores' => 'Organic/specialty stores',
'convenience_stores' => 'Convenience stores'
]
],
'beverage_preferences' => [
'question' => 'What beverages do you regularly consume? (Select all that apply)',
'type' => 'multiple',
'options' => [
'tea' => 'Tea',
'coffee' => 'Coffee',
'soft_drinks' => 'Soft drinks',
'juices' => 'Fruit juices',
'energy_drinks' => 'Energy drinks',
'health_drinks' => 'Health drinks/Protein shakes',
'alcohol' => 'Alcoholic beverages',
'water_only' => 'Mostly just water'
]
]
]
],
'financial_services' => [
'name' => 'Financial Services',
'description' => 'Tell us about your financial preferences and banking habits',
'questions' => [
'primary_bank' => [
'question' => 'Which is your primary bank?',
'type' => 'single',
'options' => [
'sbi' => 'State Bank of India (SBI)',
'hdfc' => 'HDFC Bank',
'icici' => 'ICICI Bank',
'axis' => 'Axis Bank',
'pnb' => 'Punjab National Bank',
'canara' => 'Canara Bank',
'bob' => 'Bank of Baroda',
'kotak' => 'Kotak Mahindra Bank',
'yes_bank' => 'Yes Bank',
'other' => 'Other'
]
],
'banking_frequency' => [
'question' => 'How often do you visit bank branches?',
'type' => 'single',
'options' => [
'weekly' => 'Weekly',
'monthly' => 'Monthly',
'quarterly' => 'Quarterly',
'rarely' => 'Rarely',
'never' => 'Never - I use only digital banking'
]
],
'investment_products' => [
'question' => 'Which investment products do you currently use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'savings_account' => 'Savings account',
'fixed_deposits' => 'Fixed deposits',
'mutual_funds' => 'Mutual funds',
'stocks' => 'Stocks/Shares',
'ppf' => 'PPF (Public Provident Fund)',
'nps' => 'NPS (National Pension System)',
'life_insurance' => 'Life insurance',
'gold' => 'Gold investments',
'real_estate' => 'Real estate',
'none' => 'None of these'
]
],
'credit_products' => [
'question' => 'Which credit products do you use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'credit_card' => 'Credit card',
'personal_loan' => 'Personal loan',
'home_loan' => 'Home loan',
'car_loan' => 'Car loan',
'education_loan' => 'Education loan',
'business_loan' => 'Business loan',
'overdraft' => 'Overdraft facility',
'none' => 'None'
]
],
'financial_planning' => [
'question' => 'Do you engage in financial planning?',
'type' => 'single',
'options' => [
'professional_advisor' => 'Yes, with a professional financial advisor',
'self_planned' => 'Yes, I plan myself',
'family_guidance' => 'Yes, with family guidance',
'basic_planning' => 'Basic planning only',
'no_planning' => 'No, I don\'t plan financially',
'want_to_start' => 'No, but I want to start'
]
],
'insurance_products' => [
'question' => 'What insurance products do you have? (Select all that apply)',
'type' => 'multiple',
'options' => [
'life_insurance' => 'Life insurance',
'health_insurance' => 'Health insurance',
'vehicle_insurance' => 'Vehicle insurance',
'home_insurance' => 'Home insurance',
'travel_insurance' => 'Travel insurance',
'term_insurance' => 'Term insurance',
'none' => 'No insurance'
]
],
'digital_payment_comfort' => [
'question' => 'How comfortable are you with digital payments?',
'type' => 'single',
'options' => [
'very_comfortable' => 'Very comfortable - I use for all transactions',
'mostly_comfortable' => 'Mostly comfortable - I use for most transactions',
'somewhat_comfortable' => 'Somewhat comfortable - I use for small amounts',
'limited_use' => 'Limited use - Only when necessary',
'prefer_cash' => 'I prefer cash transactions'
]
],
'financial_goals' => [
'question' => 'What are your main financial goals? (Select all that apply)',
'type' => 'multiple',
'options' => [
'emergency_fund' => 'Building emergency fund',
'retirement_planning' => 'Retirement planning',
'home_purchase' => 'Buying a home',
'child_education' => 'Children\'s education',
'wealth_creation' => 'Wealth creation',
'debt_reduction' => 'Reducing debt',
'travel_fund' => 'Travel fund',
'business_investment' => 'Starting/expanding business',
'no_specific_goals' => 'No specific goals'
]
]
]
],
'communication_payments' => [
'name' => 'Communication & Payments',
'description' => 'Share your communication preferences and survey availability',
'questions' => [
'preferred_days_for_surveys' => [
'question' => 'Which days of the week are you available for surveys? (Select all that apply)',
'type' => 'multiple',
'options' => [
'monday' => 'Monday',
'tuesday' => 'Tuesday',
'wednesday' => 'Wednesday',
'thursday' => 'Thursday',
'friday' => 'Friday',
'saturday' => 'Saturday',
'sunday' => 'Sunday',
'any_day' => 'Any day of the week'
]
],
'notification_preferences' => [
'question' => 'How would you like to receive survey notifications? (Select all that apply)',
'type' => 'multiple',
'options' => [
'sms' => 'SMS',
'email' => 'Email',
'whatsapp' => 'WhatsApp',
'app_notification' => 'App notification',
'phone_call' => 'Phone call'
]
],
'primary_communication_language' => [
'question' => 'What is your preferred language for communication?',
'type' => 'single',
'options' => [
'english' => 'English',
'hindi' => 'Hindi',
'tamil' => 'Tamil',
'telugu' => 'Telugu',
'bengali' => 'Bengali',
'marathi' => 'Marathi',
'gujarati' => 'Gujarati',
'kannada' => 'Kannada',
'malayalam' => 'Malayalam',
'punjabi' => 'Punjabi',
'other' => 'Other'
]
],
'survey_participation_time' => [
'question' => 'What time of day do you prefer to participate in surveys? (Select all that apply)',
'type' => 'multiple',
'options' => [
'early_morning' => 'Early Morning (6 AM - 9 AM)',
'mid_morning' => 'Mid Morning (9 AM - 12 PM)',
'afternoon' => 'Afternoon (12 PM - 3 PM)',
'late_afternoon' => 'Late Afternoon (3 PM - 6 PM)',
'evening' => 'Evening (6 PM - 9 PM)',
'night' => 'Night (9 PM - 12 AM)',
'late_night' => 'Late Night (12 AM - 6 AM)',
'flexible' => 'Flexible - any time works for me'
]
],
'device_ownership' => [
'question' => 'Which devices do you use regularly? (Select all that apply)',
'type' => 'multiple',
'options' => [
'smartphone' => 'Smartphone',
'laptop' => 'Laptop/Desktop',
'tablet' => 'Tablet',
'smart_tv' => 'Smart TV',
'smartwatch' => 'Smartwatch',
'feature_phone' => 'Feature Phone (non-smartphone)'
]
],
'online_payment_methods' => [
'question' => 'Which online payment methods do you use? (Select all that apply)',
'type' => 'multiple',
'options' => [
'upi' => 'UPI (PhonePe, GooglePay, Paytm)',
'credit_card' => 'Credit Card',
'debit_card' => 'Debit Card',
'net_banking' => 'Net Banking',
'digital_wallet' => 'Digital Wallets',
'cod' => 'Cash on Delivery',
'bank_transfer' => 'Bank Transfer'
]
],
'survey_types_interest' => [
'question' => 'What types of surveys interest you most? (Select all that apply)',
'type' => 'multiple',
'options' => [
'products' => 'Product reviews and feedback',
'brands' => 'Brand awareness surveys',
'lifestyle' => 'Lifestyle and habits',
'technology' => 'Technology and gadgets',
'entertainment' => 'Entertainment and media',
'politics' => 'Political opinions',
'social_issues' => 'Social issues',
'health' => 'Health and wellness',
'finance' => 'Financial products and services',
'all_types' => 'All types of surveys'
]
]
]
],
'household_classification' => [
'name' => 'Household Classification (ISEC)',
'description' => 'Help us understand your household background for better survey matching. Based on MRSI ISEC 2024 classification.',
'questions' => [
'cwe_occupation' => [
'question' => 'What is the occupation of the Chief Wage Earner (the person who earns the most in your household)?',
'type' => 'single',
'options' => [
'labour' => 'Unskilled / Semi-skilled Labour (daily wage, domestic worker, farm labour)',
'farmer' => 'Farmer / Agricultural Worker (owns or works on farm)',
'worker' => 'Skilled Worker / Artisan / Small Trader (mechanic, carpenter, small shopkeeper)',
'trader' => 'Trader / Business Owner / Contractor (medium/large business, contractor)',
'clerical' => 'Clerical / Supervisory / Junior Officer (office clerk, supervisor, junior govt employee)',
'managerial' => 'Senior Manager / Professional / Executive (doctor, engineer, CA, senior govt officer, executive)',
]
],
'male_education' => [
'question' => 'What is the highest level of education of the most educated male adult (21 years or above) in your household?',
'type' => 'single',
'options' => [
'no_adult' => 'No male adult aged 21+ in household',
'no_formal' => 'No formal schooling / Illiterate',
'upto_5' => 'Schooling up to Class 5',
'class_6_9' => 'Schooling Class 6 to 9',
'class_10_14' => 'Class 10 pass / SSC / HSC / Diploma',
'degree_regular' => 'Graduate / Post-Graduate (regular college degree)',
'degree_professional' => 'Professional Degree (Engineering / Medicine / CA / Law / MBA etc.)',
]
],
'female_education' => [
'question' => 'What is the highest level of education of the most educated female adult (21 years or above) in your household?',
'type' => 'single',
'options' => [
'no_adult' => 'No female adult aged 21+ in household',
'no_formal' => 'No formal schooling / Illiterate',
'upto_5' => 'Schooling up to Class 5',
'class_6_9' => 'Schooling Class 6 to 9',
'class_10_14' => 'Class 10 pass / SSC / HSC / Diploma',
'degree_regular' => 'Graduate / Post-Graduate (regular college degree)',
'degree_professional' => 'Professional Degree (Engineering / Medicine / CA / Law / MBA etc.)',
]
],
]
],
];
// Get the requested section
$currentSection = isset($_GET['section']) ? $_GET['section'] : null;
if (!$currentSection || !isset($profilerSections[$currentSection])) {
header('Location: dashboard.php#profiler');
exit;
}
$section = $profilerSections[$currentSection];
// Get existing responses for this section
$existingResponses = [];
try {
$stmt = $pdo->prepare("SELECT question_id, response FROM user_profiler WHERE user_id = ? AND section = ?");
$stmt->execute([$user['id'], $currentSection]);
while ($row = $stmt->fetch()) {
$existingResponses[$row['question_id']] = json_decode($row['response'], true);
}
} catch (Exception $e) {
logError('Error fetching existing responses', ['user_id' => $user['id'], 'section' => $currentSection, 'error' => $e->getMessage()]);
}
// Determine mode: view (default if has responses) or edit
$hasResponses = !empty($existingResponses);
$editMode = isset($_GET['edit']) && $_GET['edit'] == '1';
// If no responses yet, always edit mode
if (!$hasResponses) $editMode = true;
$successMessage = '';
$errorMessages = [];
// Handle form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$responses = [];
$hasErrors = false;
foreach ($section['questions'] as $questionId => $questionData) {
if ($questionData['type'] === 'single') {
$value = isset($_POST[$questionId]) ? sanitize($_POST[$questionId]) : '';
if (!empty($value)) {
$responses[$questionId] = $value;
} elseif (isset($existingResponses[$questionId])) {
// Cannot empty a previously answered question — keep old response
$responses[$questionId] = $existingResponses[$questionId];
}
} elseif ($questionData['type'] === 'multiple') {
$values = isset($_POST[$questionId]) ? $_POST[$questionId] : [];
if (is_array($values) && !empty($values)) {
$cleanValues = array_map('sanitize', $values);
$responses[$questionId] = $cleanValues;
} elseif (isset($existingResponses[$questionId])) {
// Cannot empty — keep old response
$responses[$questionId] = $existingResponses[$questionId];
}
}
}
if (!$hasErrors) {
try {
$pdo->beginTransaction();
// Save all responses
foreach ($responses as $questionId => $response) {
$stmt = $pdo->prepare("INSERT INTO user_profiler (user_id, section, question_id, response) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE response = ?, updated_at = NOW()");
$responseJson = json_encode($response);
$stmt->execute([$user['id'], $currentSection, $questionId, $responseJson, $responseJson]);
}
// Calculate completion percentage
$totalQuestions = count($section['questions']);
$answeredQuestions = count($responses);
$completionPercentage = ($answeredQuestions / $totalQuestions) * 100;
$isCompleted = $completionPercentage >= 100;
// Update completion status
$stmt = $pdo->prepare("INSERT INTO profiler_completion (user_id, section, total_questions, answered_questions, completion_percentage, is_completed, completed_at) VALUES (?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE answered_questions = ?, completion_percentage = ?, is_completed = ?, completed_at = CASE WHEN ? = 1 THEN NOW() ELSE completed_at END, updated_at = NOW()");
$completedAt = $isCompleted ? date('Y-m-d H:i:s') : null;
$stmt->execute([$user['id'], $currentSection, $totalQuestions, $answeredQuestions, $completionPercentage, $isCompleted, $completedAt, $answeredQuestions, $completionPercentage, $isCompleted, $isCompleted]);
// Award points if section is completed and not already awarded
if ($isCompleted) {
$stmt = $pdo->prepare("SELECT points_awarded FROM profiler_completion WHERE user_id = ? AND section = ?");
$stmt->execute([$user['id'], $currentSection]);
$completion = $stmt->fetch();
if ($completion && !$completion['points_awarded']) {
// ISEC section earns 20 points, all others earn 5
$pointsToAward = ($currentSection === 'household_classification') ? 20 : 5;
$pointsDescription = 'Profiler section completion: ' . $section['name'];
$stmt = $pdo->prepare("INSERT INTO user_points (user_id, points, total_earned) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE points = points + ?, total_earned = total_earned + ?");
$stmt->execute([$user['id'], $pointsToAward, $pointsToAward, $pointsToAward, $pointsToAward]);
$stmt = $pdo->prepare("INSERT INTO point_transactions (user_id, transaction_type, points, source, description) VALUES (?, 'earned', ?, ?, ?)");
$stmt->execute([$user['id'], $pointsToAward, 'profiler_' . $currentSection, $pointsDescription]);
$stmt = $pdo->prepare("UPDATE profiler_completion SET points_awarded = 1 WHERE user_id = ? AND section = ?");
$stmt->execute([$user['id'], $currentSection]);
logError('Profiler points awarded', ['user_id' => $user['id'], 'section' => $currentSection, 'points' => $pointsToAward]);
}
// For ISEC section: compute and save SEC class to users table
if ($currentSection === 'household_classification') {
$occ = $responses['cwe_occupation'] ?? null;
$mEdu = $responses['male_education'] ?? null;
$fEdu = $responses['female_education'] ?? null;
if ($occ && $mEdu && $fEdu) {
$tier = computeISECTier($occ, $mEdu, $fEdu);
$secClass = $tier ? getISECClass($tier) : null;
if ($secClass) {
$stmt = $pdo->prepare("UPDATE users SET isec_class = ?, isec_tier = ?, updated_at = NOW() WHERE id = ?");
$stmt->execute([$secClass, $tier, $user['id']]);
logError('ISEC class computed', ['user_id' => $user['id'], 'tier' => $tier, 'class' => $secClass]);
}
}
}
}
$pdo->commit();
// Reload responses and switch to view mode
$existingResponses = [];
$stmt = $pdo->prepare("SELECT question_id, response FROM user_profiler WHERE user_id = ? AND section = ?");
$stmt->execute([$user['id'], $currentSection]);
while ($row = $stmt->fetch()) {
$existingResponses[$row['question_id']] = json_decode($row['response'], true);
}
$hasResponses = !empty($existingResponses);
$editMode = false;
$successMessage = 'Your responses have been saved successfully!';
} catch (Exception $e) {
$pdo->rollback();
logError('Error saving profiler responses', ['user_id' => $user['id'], 'section' => $currentSection, 'error' => $e->getMessage()]);
$errorMessages[] = 'Error saving your responses. Please try again.';
}
}
}
// Helper: get option label for a value
function getOptionLabel($questionData, $value) {
return isset($questionData['options'][$value]) ? $questionData['options'][$value] : ucwords(str_replace('_', ' ', $value));
}
?>
- Profiler | Relevant Reflex
Complete your profile, earn points, and participate in paid surveys.
Important! Read 4 essential rules before taking any survey to protect your account and earn maximum rewards.
Available Points
₹ value
Surveys Done
total
Profile
%
sections
Total Earned
Since
Complete Profile
Earn up to 70 points
Redeem Rewards
Convert points to cash
Get Help
Support & FAQs
⚠ Read This Before You Take Any Survey
4 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.
4
Give thoughtful answers to open-ended questions. When a survey asks you to type your opinion or explain something in your own words, write a genuine, meaningful response. Vague, gibberish, or nonsensical text (e.g., random letters, copy-pasted filler, or irrelevant answers) will be flagged. Responses containing such text will be marked invalid and the completion will not count — no points will be awarded.
Why this matters: Research clients review every response for quality. Flagged responses (speeding, duplicates, straightlining, or gibberish open-ended answers) 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 →
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.
Share your link with friends, groups, or on social media
✍️
They register using your link and verify their email
You earn ₹5 (10 pts)
📋
Every time they complete a survey
You earn ₹5 (10 pts) more
💰
Rewards go directly into your points balance for redemption
Where to Share Your Link
💬 Messaging Apps: WhatsApp groups, Telegram channels & groups, Instagram DMs 📱 Social Media: Facebook posts & stories, Instagram Reels/Shorts, YouTube video descriptions, Twitter/X threads 📣 Promotions: Digital ad banners, blog articles, email newsletters, LinkedIn posts ⚠️ Fair Use: Referral rewards are for genuine referrals only. Multiple clicks from the same IP are limited. Self-referrals are not counted. Abuse may result in reward reversal.
Click & Signup History
#
Referred Email
Clicked
Signed Up
Verified
Signup Reward
Survey Earnings
🔗
No referral clicks yet. Share your link to get started!
$r): ?>
Not signed up
✓ YesPending
✓ Verified⏳ Pending—
₹5 PaidProcessing—
0): ?>
₹₹0.00
Referral Reward Transactions
Date
Type
Points
Description
💰
No referral rewards yet. Start sharing your link!
Signup RewardSurvey Reward
+ pts
₹
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/reset-password.php
TYPE: PHP
SIZE: 10.56 KB
------------------------------------------------------------
getConnection();
$stmt = $pdo->prepare("
SELECT email, expires_at
FROM password_resets
WHERE token = ? AND expires_at > NOW()
");
$stmt->execute([$token]);
$reset = $stmt->fetch();
if ($reset) {
$email = $reset['email'];
$isValidToken = true;
}
} catch (Exception $e) {
logError('Error checking reset token', ['error' => $e->getMessage()]);
}
}
// Handle password reset form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $isValidToken) {
$newPassword = isset($_POST['password']) ? $_POST['password'] : '';
$confirmPassword = isset($_POST['confirm_password']) ? $_POST['confirm_password'] : '';
// Validation
$errors = [];
if (empty($newPassword)) {
$errors[] = 'Password is required.';
}
if (empty($confirmPassword)) {
$errors[] = 'Please confirm your password.';
}
if (!validatePassword($newPassword)) {
$errors[] = 'Password must be at least 8 characters long.';
}
if ($newPassword !== $confirmPassword) {
$errors[] = 'Passwords do not match.';
}
if (empty($errors)) {
try {
// Start transaction
$pdo->beginTransaction();
// Hash new password
$hashedPassword = hashPassword($newPassword);
// Update user password
$stmt = $pdo->prepare("UPDATE users SET password = ?, updated_at = NOW() WHERE email = ?");
$stmt->execute([$hashedPassword, $email]);
// Delete used reset token
$stmt = $pdo->prepare("DELETE FROM password_resets WHERE token = ?");
$stmt->execute([$token]);
// Delete all user sessions (force re-login)
$stmt = $pdo->prepare("DELETE FROM user_sessions WHERE user_id = (SELECT id FROM users WHERE email = ?)");
$stmt->execute([$email]);
// Commit transaction
$pdo->commit();
logError('Password reset successful', ['email' => $email]);
// Redirect to success page
showResetResult(true, 'Password Reset Successful', 'Your password has been reset successfully. You can now log in with your new password.');
} catch (PDOException $e) {
if ($pdo->inTransaction()) {
$pdo->rollback();
}
logError('Database error during password reset', [
'error' => $e->getMessage(),
'email' => $email
]);
$errors[] = 'Failed to reset password due to a system error. Please try again later.';
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollback();
}
logError('General error during password reset', [
'error' => $e->getMessage(),
'email' => $email
]);
$errors[] = 'An unexpected error occurred. Please try again later.';
}
}
}
function showResetResult($success, $title, $message) {
$statusClass = $success ? 'success' : 'error';
$statusColor = $success ? '#28a745' : '#dc3545';
$iconClass = $success ? 'fa-check-circle' : 'fa-exclamation-triangle';
?>
- Relevant Reflex
Didn't receive the email? Check your spam/junk folder. If it's not there, click below to resend.
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking "Accept All", you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/sms-config.php
TYPE: PHP
SIZE: 11.78 KB
------------------------------------------------------------
gateway = 'twofactor'; // Using 2Factor as primary gateway
// SMS Gateway configurations
$this->config = [
'msg91' => [
'auth_key' => 'YOUR_MSG91_AUTH_KEY', // Replace with actual key
'template_id' => 'YOUR_TEMPLATE_ID', // Replace with actual template ID
'route' => '4', // Transactional route
'country' => '91'
],
'textlocal' => [
'api_key' => 'YOUR_TEXTLOCAL_API_KEY',
'username' => 'YOUR_TEXTLOCAL_USERNAME',
'hash' => 'YOUR_TEXTLOCAL_HASH',
'sender' => 'TXTLCL' // 6 characters or less
],
'twofactor' => [
'api_key' => '79d4feb6-d168-11ea-9fa5-0200cd936042', // Your actual 2Factor API key
'sender_id' => 'RELREF', // Matches 2Factor dashboard: Sender Id = RELREF
'template_name' => 'Profile OTP' // Matches 2Factor dashboard: Template Name = Profile OTP
],
'fast2sms' => [
'api_key' => 'YOUR_FAST2SMS_API_KEY',
'route' => 'dlt', // DLT route for OTP
'sender_id' => 'FSTSMS'
]
];
}
/**
* Send OTP SMS
*/
public function sendOTP($mobileNumber, $otpCode, $templateMessage = null) {
// Clean mobile number
$mobileNumber = preg_replace('/[^0-9]/', '', $mobileNumber);
// Remove leading zero if present
if (substr($mobileNumber, 0, 1) === '0') {
$mobileNumber = substr($mobileNumber, 1);
}
// Default OTP message
if (!$templateMessage) {
$templateMessage = "Your Relevant Reflex verification code is: {$otpCode}. Valid for 10 minutes. Do not share this with anyone.";
}
switch ($this->gateway) {
case 'msg91':
return $this->sendViaMSG91($mobileNumber, $otpCode, $templateMessage);
case 'textlocal':
return $this->sendViaTextLocal($mobileNumber, $templateMessage);
case 'twofactor':
return $this->sendViaTwoFactor($mobileNumber, $otpCode);
case 'fast2sms':
return $this->sendViaFast2SMS($mobileNumber, $templateMessage);
default:
return $this->mockSend($mobileNumber, $otpCode); // For testing
}
}
/**
* MSG91 SMS Gateway
*/
private function sendViaMSG91($mobileNumber, $otpCode, $message) {
$config = $this->config['msg91'];
$url = "https://api.msg91.com/api/v5/otp";
$data = [
'template_id' => $config['template_id'],
'mobile' => $config['country'] . $mobileNumber,
'authkey' => $config['auth_key'],
'otp' => $otpCode,
'extra_param' => json_encode(['otp' => $otpCode])
];
return $this->makeAPICall($url, $data, 'POST');
}
/**
* TextLocal SMS Gateway
*/
private function sendViaTextLocal($mobileNumber, $message) {
$config = $this->config['textlocal'];
$url = "https://api.textlocal.in/send/";
$data = [
'apikey' => $config['api_key'],
'numbers' => '91' . $mobileNumber,
'message' => $message,
'sender' => $config['sender']
];
return $this->makeAPICall($url, $data, 'POST');
}
/**
* 2Factor SMS Gateway
*
* Uses OTP SMS API with explicit template name to force SMS delivery.
* Template: "XXXX is the OTP to verify your mobile number at Relevant Reflex"
* Sender ID: RELREF | Template Name: Profile OTP
*
* By specifying the template name in the URL, 2Factor uses the registered
* DLT SMS template instead of defaulting to voice calls.
*/
private function sendViaTwoFactor($mobileNumber, $otpCode) {
$config = $this->config['twofactor'];
// OTP API with template name — forces SMS delivery via registered DLT template
// Format: /SMS/{phone}/{otp}/{template_name}
$templateName = urlencode($config['template_name']);
$url = "https://2factor.in/API/V1/{$config['api_key']}/SMS/{$mobileNumber}/{$otpCode}/{$templateName}";
$result = $this->makeAPICall($url, [], 'GET');
// Log the attempt
logError('2Factor OTP SMS with template', [
'mobile' => $mobileNumber,
'template' => $config['template_name'],
'status' => $result['response']['Status'] ?? 'unknown',
'details' => $result['response']['Details'] ?? 'none'
]);
if ($result['success'] && isset($result['response']['Status'])
&& $result['response']['Status'] == 'Success') {
return [
'success' => true,
'message' => 'OTP sent via SMS successfully',
'session_id' => $result['response']['Details'] ?? null,
'response' => $result['response']
];
}
return [
'success' => false,
'message' => 'Failed to send SMS OTP: ' . ($result['response']['Details'] ?? 'Unknown error'),
'response' => $result['response'] ?? []
];
}
/**
* Fast2SMS Gateway
*/
private function sendViaFast2SMS($mobileNumber, $message) {
$config = $this->config['fast2sms'];
$url = "https://www.fast2sms.com/dev/bulkV2";
$data = [
'authorization' => $config['api_key'],
'sender_id' => $config['sender_id'],
'message' => $message,
'route' => $config['route'],
'numbers' => $mobileNumber
];
$headers = [
'authorization: ' . $config['api_key'],
'Content-Type: application/json'
];
return $this->makeAPICall($url, $data, 'POST', $headers);
}
/**
* Mock SMS sending for testing
*/
private function mockSend($mobileNumber, $otpCode) {
logError('Mock SMS sent', [
'mobile' => $mobileNumber,
'otp' => $otpCode,
'message' => 'OTP for testing: ' . $otpCode
]);
return [
'success' => true,
'message' => 'SMS sent successfully (Mock)',
'reference_id' => 'MOCK_' . time()
];
}
/**
* Make API call to SMS gateway
*/
private function makeAPICall($url, $data, $method = 'POST', $headers = []) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if (!empty($data)) {
if (empty($headers) || !in_array('Content-Type: application/json', $headers)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
}
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
logError('SMS API Error', ['error' => $error, 'url' => $url]);
return [
'success' => false,
'message' => 'Network error: ' . $error
];
}
$decodedResponse = json_decode($response, true);
logError('SMS API Response', [
'url' => $url,
'http_code' => $httpCode,
'response' => $decodedResponse ?: $response
]);
// Parse response based on gateway
return $this->parseResponse($decodedResponse ?: $response, $httpCode);
}
/**
* Parse SMS gateway response
*/
private function parseResponse($response, $httpCode) {
if ($httpCode >= 200 && $httpCode < 300) {
return [
'success' => true,
'message' => 'SMS sent successfully',
'response' => $response
];
} else {
return [
'success' => false,
'message' => 'SMS sending failed',
'response' => $response
];
}
}
/**
* Get available SMS balance (if supported by gateway)
*/
public function getBalance() {
switch ($this->gateway) {
case 'msg91':
$config = $this->config['msg91'];
$url = "https://api.msg91.com/api/balance.php?authkey={$config['auth_key']}&type=4";
return $this->makeAPICall($url, [], 'GET');
case 'twofactor':
$config = $this->config['twofactor'];
$url = "https://2factor.in/API/V1/{$config['api_key']}/ADDON_SERVICES/BAL/SMS";
return $this->makeAPICall($url, [], 'GET');
default:
return ['success' => false, 'message' => 'Balance check not supported for this gateway'];
}
}
}
// Global SMS helper function
function sendOTPSMS($mobileNumber, $otpCode) {
$smsManager = new SMSManager();
return $smsManager->sendOTP($mobileNumber, $otpCode);
}
/*
* SETUP INSTRUCTIONS FOR 2FACTOR SMS GATEWAY
* ===========================================
*
* Your 2Factor API Key: 79d4feb6-d168-11ea-9fa5-0200cd936042
*
* FIXING "VOICE CALL INSTEAD OF SMS" ISSUE:
* ------------------------------------------
* The 2Factor OTP API has auto-retry that sends voice calls when SMS fails.
* To get SMS working properly:
*
* STEP 1: Login to https://2factor.in with your account
*
* STEP 2: Disable Voice Auto-Retry
* - Go to Dashboard → Settings (or OTP Settings)
* - Find "Auto Retry" / "Voice OTP Retry" / "Retry Configuration"
* - DISABLE it (turn off voice fallback)
*
* STEP 3: Check DLT Registration (REQUIRED for SMS in India)
* - In India, TRAI requires DLT registration for all SMS
* - Go to 2Factor Dashboard → DLT Settings / SMS Templates
* - You need:
* a) A registered Sender ID (e.g., "RREFX")
* b) A DLT-approved Content Template for OTP
* Example template: "Your Relevant Reflex OTP is {#var#}. Valid for 10 minutes."
* - Update the sender_id and template_name in config above after registering
* - If you don't have DLT registration, register at:
* Jio: https://trueconnect.jio.com
* Airtel: https://www.airtel.in/business/commercial-communication
* Vodafone: https://smartping.live/entity/reg-as
*
* STEP 4: Check SMS Balance
* - Go to Dashboard → Balance
* - Verify you have SMS credits (not just voice credits)
* - Current balance: ~7,038 SMS credits
*
* STEP 5: Test
* - After disabling auto-retry and setting up DLT template
* - Try sending OTP from mobile-verification.php
* - Check errors.log for detailed API responses
*
* HOW THIS CODE WORKS:
* - First tries Transactional SMS API (no voice fallback at all)
* - If that fails, falls back to OTP API (may trigger voice if auto-retry is on)
* - Both attempts are logged to errors.log for debugging
*
*/
?>
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/support-upload-helper.php
TYPE: PHP
SIZE: 10.69 KB
------------------------------------------------------------
SUPPORT_MAX_FILE_SIZE) {
continue;
}
// Validate extension
$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
if (!in_array($ext, SUPPORT_ALLOWED_EXTENSIONS)) {
continue;
}
// Validate MIME type
$finfo = new finfo(FILEINFO_MIME_TYPE);
$detectedType = $finfo->file($tmpName);
if (!in_array($detectedType, SUPPORT_ALLOWED_TYPES)) {
continue;
}
// Generate unique filename
$storedName = 'support_' . $messageId . '_' . uniqid() . '.' . $ext;
$fullPath = $uploadPath . $storedName;
$relativePath = SUPPORT_UPLOAD_URL . $monthDir . '/' . $storedName;
if (move_uploaded_file($tmpName, $fullPath)) {
try {
$stmt = $pdo->prepare("
INSERT INTO support_attachments (message_id, file_name, original_name, file_path, file_type, file_size)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([$messageId, $storedName, $originalName, $relativePath, $detectedType, $fileSize]);
$attachmentIds[] = $pdo->lastInsertId();
} catch (Exception $e) {
// Clean up file if DB insert fails
@unlink($fullPath);
}
}
}
return $attachmentIds;
}
/**
* Get attachments for multiple messages (batch load)
* @param PDO $pdo
* @param array $messageIds Array of message IDs
* @return array Keyed by message_id => [attachments]
*/
function getAttachmentsForMessages($pdo, $messageIds) {
$result = [];
if (empty($messageIds)) return $result;
$placeholders = implode(',', array_fill(0, count($messageIds), '?'));
$stmt = $pdo->prepare("
SELECT * FROM support_attachments
WHERE message_id IN ($placeholders)
ORDER BY created_at ASC
");
$stmt->execute($messageIds);
$attachments = $stmt->fetchAll();
foreach ($attachments as $att) {
$result[$att['message_id']][] = $att;
}
return $result;
}
/**
* Render attachment HTML for display
* @param array $attachments Array of attachment rows
* @return string HTML string
*/
function renderAttachmentsHTML($attachments) {
if (empty($attachments)) return '';
$html = '
Welcome to Relevant Reflex!
These Terms and Conditions ("Terms") govern your use of our online survey platform and related services. Please read them carefully.
1 Acceptance of Terms
By using Relevant Reflex's services, you acknowledge that you have read, understood, and agree to be bound by these Terms, as well as our Privacy Policy.
If you do not agree with any part of these terms, you must not use our services. Your continued use of the platform constitutes acceptance of any modifications to these Terms.
2 Eligibility
2.1 Age Requirement
You must be at least 18 years old to use our services. By registering, you represent and warrant that you meet this age requirement.
2.2 Geographic Requirement
You must be a resident of India to participate in our surveys and receive rewards. This helps us provide relevant survey opportunities and comply with local regulations.
2.3 Account Limitations
You may only maintain one account with Relevant Reflex. Multiple accounts from the same individual are prohibited and may result in account suspension.
3 Account Registration and Security
3.1 Account Responsibility
You are responsible for:
Maintaining the confidentiality of your account information
All activities that occur under your account
Notifying us immediately of any unauthorized use
Ensuring your login credentials are secure
3.2 Accurate Information
You agree to provide accurate and up-to-date information during registration and throughout your use of our services. False or misleading information may result in account termination.
3.3 Account Verification
You must verify your email address and may be required to provide additional verification for account security or compliance purposes.
4 Survey Participation
4.1 Honest Responses
You agree to provide honest and thoughtful responses to surveys. Quality responses are essential for meaningful research.
4.2 Survey Qualification
We reserve the right to disqualify you from a survey if we detect:
Fraudulent or inconsistent responses
Use of automated tools or bots
Excessively fast completion times
Random or nonsensical answers
4.3 Survey Availability
Survey opportunities are based on your demographic profile and survey requirements. We cannot guarantee specific numbers or types of surveys.
Important: Completion of a survey does not guarantee reward if disqualified for quality reasons. We maintain strict quality standards to ensure valuable research data.
5 Rewards and Payments
5.1 Reward Distribution
Rewards will be issued as per the terms specified for each survey. Typical processing times are:
Survey validation: 1-5 business days
Payment processing: 3-7 business days
Bank transfer: 2-3 additional business days
5.2 Reward Modifications
We reserve the right to modify, suspend, or terminate the reward system at any time with reasonable notice to members.
5.3 Reward Restrictions and Payout Terms
Unless specified otherwise:
Rewards are non-transferable between accounts
Accumulated rewards can be withdrawn as cash via UPI once the minimum payout threshold has been reached. Rewards from specific bonus promotions may be subject to additional conditions stated at the time of the promotion.
Minimum payout threshold: ₹500. You must accumulate at least ₹500 in your account balance before requesting a withdrawal.
Payments are processed via UPI transfer to your registered UPI ID. UPI is currently the sole payment method for member withdrawals.
Payment processing may take 3–7 business days after a withdrawal request is submitted and approved.
5.4 Tax Responsibilities
You are responsible for reporting and paying any applicable taxes on rewards received. We may provide necessary documentation for tax purposes.
6 Intellectual Property
6.1 Platform Content
All content on our website, including text, graphics, logos, images, and software, is the property of Relevant Reflex or its licensors and is protected by copyright laws.
6.2 Usage Restrictions
You may not:
Use, reproduce, or distribute our content without express written permission
Modify or create derivative works from our platform
Reverse engineer any part of our services
Use our trademarks or branding without authorization
6.3 User-Generated Content
By providing survey responses and feedback, you grant us a non-exclusive, royalty-free license to use this information for research and platform improvement purposes.
7 Prohibited Conduct
You agree NOT to engage in any of the following activities:
7.1 Technical Violations
Use automated means (bots, scripts) to access our services or complete surveys
Attempt to interfere with the proper functioning of our website
Circumvent any security measures or access controls
Use VPNs or proxy services to mask your location
7.2 Identity and Fraud
Impersonate any person or entity
Create multiple accounts
Provide false personal information
Share account credentials with others
7.3 Legal Violations
Engage in any activity that violates applicable law or regulation
Violate the rights of other users or third parties
Transmit harmful, threatening, or offensive content
Engage in harassment or discrimination
Enforcement: Violation of these terms may result in immediate account suspension or termination, forfeiture of rewards, and potential legal action.
8 Termination
8.1 Termination by Us
We reserve the right to suspend or terminate your account at our discretion, without notice, for:
Violation of these Terms
Fraudulent activity
Extended inactivity (24+ months)
Legal or regulatory requirements
8.2 Termination by You
You may terminate your account at any time by:
Using the account deletion option in your settings
Contacting our support team
Sending a written request to support@relevantreflex.com
8.3 Effects of Termination
Upon termination:
Your access to the platform will be immediately revoked
Pending rewards may be forfeited (depending on circumstances)
Your personal data will be handled according to our Privacy Policy
Certain provisions of these Terms will survive termination
9 Limitation of Liability
9.1 Service Disclaimer
Our services are provided "as is" without warranties of any kind. We do not guarantee:
Uninterrupted or error-free service
Specific survey availability or earnings
Compatibility with all devices or browsers
Accuracy of third-party content
9.2 Liability Limitations
Relevant Reflex is not liable for any indirect, incidental, special, or consequential damages, including:
Loss of profits or earnings
Business interruption
Data loss or corruption
Emotional distress
9.3 Maximum Liability
Our total liability for any claim arising from these Terms shall not exceed the amount paid to you in the past 12 months, or ₹1,000, whichever is greater.
10 Indemnification
You agree to indemnify and hold Relevant Reflex harmless from any claims, losses, or damages arising from:
Your use of our services
Violation of these Terms
Violation of any law or regulation
Infringement of third-party rights
Your survey responses or other content
11 Privacy Policy
Your privacy is important to us. Our Privacy Policy explains how we collect, use, and protect your information. By using our services, you also agree to our Privacy Policy.
Key privacy principles:
We never sell your personal data to third parties
Your survey responses are anonymized for research
You control your data and can request deletion
We use industry-standard security measures
12 Changes to Terms
12.1 Modification Process
We may modify these Terms at any time. When we make changes, we will:
Update the "Last Modified" date
Notify active users via email
Provide a summary of significant changes
Allow reasonable time for review (minimum 30 days for material changes)
12.2 Acceptance of Changes
Continued use of our services after changes constitutes acceptance of the modified Terms. If you disagree with changes, you should terminate your account before they take effect.
13 Governing Law and Jurisdiction
13.1 Applicable Law
These Terms are governed by the laws of India, without regard to conflict of law principles.
13.2 Jurisdiction
Any disputes shall be subject to the exclusive jurisdiction of the courts in Tamil Nadu, India.
13.3 Dispute Resolution
Before pursuing legal action, we encourage users to:
Contact our support team to resolve issues
Allow 30 days for resolution attempts
Consider mediation for complex disputes
14 Contact Information
If you have questions about these Terms, please contact us:
Relevant Reflex
Ethirmedu, NH 544
Tamilnadu - 638183
India
Thank you for using Relevant Reflex!
We appreciate your participation in our survey community and your commitment to providing quality responses.
We use cookies to improve your experience and for advertising purposes (including Google Ads). By clicking “Accept All”, you consent to our use of cookies as described in our Privacy Policy. You may decline non-essential cookies.
-------------------- END OF FILE --------------------
FILE: Relevant Reflex Com/ticket-guide.php
TYPE: PHP
SIZE: 34.52 KB
------------------------------------------------------------
Support Ticket Guide - How It Works | Relevant Reflex
Support Ticket Guide
Learn how our support ticket system works and how to get the best help from our team.
Our support ticket system is designed to provide you with efficient, trackable help for any issues or questions you may have. Each ticket gets a unique number and goes through a structured process to ensure nothing gets missed.
How to Create a Support Ticket
Login to your account - Visit your dashboard
Go to Support section - Click "Support" in the navigation
Fill out the form - Provide subject and detailed description
Every support ticket goes through different statuses as our team works to resolve your issue. Here's what each status means:
OPEN
What it means: Your ticket has been received and is waiting for our support team to review it.
What happens next: A support agent will review your issue and respond with initial guidance or questions.
Can you reply? Yes, you can add more information anytime.
PENDING
What it means: Our support team has responded and is waiting for your reply or action.
What happens next: Please check your email and dashboard for our response. We may need more information or be waiting for you to try a suggested solution.
Can you reply? Yes, please respond to keep the conversation going.
RESOLVED
What it means: Our team believes your issue has been solved, but we want to make sure!
What happens next: Please test the solution and let us know if it worked. If the issue persists, just reply and we'll reopen the ticket.
Can you reply? Yes, you can confirm the fix worked or report if issues continue.
CLOSED
What it means: Your issue has been completely resolved and the ticket is archived.
What happens next: Nothing! Your issue is solved. If you have a new problem, please create a new ticket.
Can you reply? No, closed tickets cannot be reopened. Please create a new ticket for new issues.
Priority Levels
When creating a ticket, choose the priority level that best matches your situation:
LOWGeneral Questions
24-48 hours
Use for: How-to questions, feature requests, general inquiries
MEDIUMStandard Issues
12-24 hours
Use for: Account issues, survey problems, payment questions
HIGHUrgent Problems
4-8 hours
Use for: Cannot access account, missing payments, data issues
URGENTCritical Issues
1-2 hours
Use for: Security concerns, service outages, data loss
Typical Workflow
Example: "I can't access my account"
Day 1 - You create ticket
OPEN "I can't log in to my account"
Day 1 - We respond (4 hours later)
PENDING "Can you try resetting your password? Click here..."
Day 2 - You reply
PENDING "I tried but didn't receive the reset email"
Day 2 - We investigate and fix
RESOLVED "Found the issue - email was blocked. Fixed it and reset your password to: [new password]"
Day 2 - You confirm
RESOLVED "Perfect! I can log in now. Thank you!"
Day 3 - We close ticket
CLOSED Issue resolved successfully.
Response Times
We strive to respond to all tickets promptly. Our target response times are:
Business Hours
Monday-Friday: 9:00 AM - 6:00 PM IST Saturday: 10:00 AM - 4:00 PM IST Sunday: Closed (emergency only)
Response Goals
Urgent: Within 2 hours High: Within 8 hours Medium: Within 24 hours Low: Within 48 hours
Pro Tip
Response times are for first response. Complex issues may require multiple exchanges, but we'll keep you updated on progress throughout the resolution process.
Best Practices
DO
Be specific - Include error messages, screenshots
One issue per ticket - Don't combine multiple problems
Choose correct priority - Be honest about urgency
Respond promptly - Reply to our questions quickly
Provide context - When did it start? What changed?
Be patient - Allow time for investigation
DON'T
Create duplicate tickets - One ticket per issue
Mark everything urgent - Saves urgent for real emergencies
Leave out details - More info = faster resolution
Use inappropriate channels - Keep support in tickets
Get impatient - Quality takes time
Close tickets too early - Make sure it's really fixed
Good Ticket Examples
GOOD Example
Subject: Cannot complete survey ID #12345 - browser crashes
Priority: Medium
Description: "Hi, I'm trying to complete survey #12345 'Shopping Preferences' but on question 8 (the one about brands), my browser (Chrome v91 on Windows 10) crashes and closes. This has happened 3 times now. I've tried clearing my cache and using incognito mode, but same issue. I need to complete this survey by Friday to get the reward. Screenshots attached."
Why this is good: Specific survey ID, exact problem description, browser details, steps already tried, deadline mentioned, screenshots included.
POOR Example
Subject: Survey not working
Priority: Urgent
Description: "Your surveys don't work. Fix it."
Why this is poor: No specific details, wrong priority level, no context, rude tone, impossible to diagnose.
Frequently Asked Questions
Q: Can I reply to a resolved ticket?
A: Yes! If the solution didn't work or you have follow-up questions, just reply to the resolved ticket. We'll reopen it and continue helping.
Q: What happens if I don't respond to a pending ticket?
A: We'll wait 7 days for your response. After that, we'll send a reminder. If there's no response after 14 days, we'll mark it as resolved.
Q: Can I change the priority of my ticket?
A: You can mention in a reply if urgency has changed, but our support team manages priority levels based on actual impact and urgency.
Q: How do I know when you reply to my ticket?
A: You'll receive an email notification and can also check your dashboard support section for updates.
Q: Can I call for support instead?
A: We primarily use tickets to ensure nothing gets lost and maintain quality records. For complex issues, our team may schedule a call as part of the resolution process.