| <?php |
| ini_set('display_errors', 1); |
| ini_set('display_startup_errors', 1); |
| error_reporting(E_ALL); |
|
|
| session_start(); |
|
|
| |
| $host = '127.0.0.1'; |
| $dbname = 'jmdb'; |
| $username = 'root'; |
| $password = 'YourStrongPassword123'; |
|
|
| try { |
| $pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); |
| $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
| } catch(PDOException $e) { |
| die("Database connection failed: " . $e->getMessage()); |
| } |
|
|
| if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) { |
| header('Location: ../../index.php'); |
| exit; |
| } |
|
|
| |
| if (!isset($_SESSION['user_id']) && isset($_SESSION['username'])) { |
| $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?"); |
| $stmt->execute([$_SESSION['username']]); |
| $user = $stmt->fetch(PDO::FETCH_ASSOC); |
| if ($user) { |
| $_SESSION['user_id'] = $user['id']; |
| } |
| } |
|
|
| if (!isset($_SESSION['user_id'])) { |
| header('Location: ../../index.php'); |
| exit; |
| } |
|
|
| |
| $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); |
| $stmt->execute([$_SESSION['user_id']]); |
| $user = $stmt->fetch(PDO::FETCH_ASSOC); |
|
|
| if (!$user) { |
| session_destroy(); |
| header('Location: ../../index.php'); |
| exit; |
| } |
|
|
| |
| $username = $user['username'] ?? $_SESSION['username']; |
| $email = $user['email'] ?? $_SESSION['email']; |
| $tier = $user['tier'] ?? $_SESSION['tier']; |
| $package = $user['package'] ?? $_SESSION['package']; |
| $balance = $user['balance'] ?? $_SESSION['balance']; |
| $total_deposits = $user['total_deposits'] ?? $_SESSION['total_deposits']; |
| $total_withdrawals = $user['total_withdrawals'] ?? $_SESSION['total_withdrawals']; |
| $rewards = $user['rewards'] ?? $_SESSION['rewards']; |
|
|
| |
| $first_name = $user['first_name'] ?? 'Maha'; |
| $last_name = $user['last_name'] ?? 'Ibrahim'; |
| $phone_number = $user['phone_number'] ?? '254712345678'; |
| $country_code = $user['country_code'] ?? 'KE'; |
| $status = $user['status'] ?? 'Dormant'; |
| $member_since = $user['member_since'] ?? '2023-01-15'; |
|
|
| |
| $member_since_formatted = date('d M Y', strtotime($member_since)); |
| $earnings = $total_deposits - $total_withdrawals; |
|
|
| |
| $_SESSION['username'] = $username; |
| $_SESSION['email'] = $email; |
| $_SESSION['tier'] = $tier; |
| $_SESSION['package'] = $package; |
| $_SESSION['balance'] = $balance; |
| $_SESSION['total_deposits'] = $total_deposits; |
| $_SESSION['total_withdrawals'] = $total_withdrawals; |
| $_SESSION['rewards'] = $rewards; |
| ?> |
| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Profile | Japanese Motors</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700;800&display=swap" rel="stylesheet"> |
| <script src="https://unpkg.com/feather-icons"></script> |
| <style> |
| :root { |
| --bg: |
| --card: |
| --card-2: |
| --accent: |
| --muted: rgba(255,255,255,0.6); |
| font-family: 'Poppins', system-ui, Arial; |
| } |
| |
| body { |
| background: var(--bg); |
| font-family: 'Poppins', sans-serif; |
| transition: all 0.3s ease; |
| min-height: 100vh; |
| } |
| |
| .sidebar { |
| width: 250px; |
| height: 100vh; |
| background: |
| color: |
| position: fixed; |
| top: 0; |
| left: -250px; |
| transition: all 0.3s ease; |
| z-index: 1000; |
| overflow-y: auto; |
| } |
| |
| .sidebar.active { |
| left: 0; |
| } |
| |
| |
| margin-left: 0; |
| transition: all 0.3s ease; |
| } |
| |
| .sidebar.active ~ |
| margin-left: 250px; |
| } |
| |
| header { |
| background: |
| color: white; |
| padding: 15px 20px; |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| position: relative; |
| z-index: 900; |
| transition: all 0.3s ease; |
| } |
| |
| .sidebar.active ~ |
| margin-left: 250px; |
| } |
| |
| .menu-toggle { |
| background: transparent; |
| border: none; |
| color: white; |
| font-size: 1.5rem; |
| cursor: pointer; |
| } |
| |
| .logo-section { |
| padding: 15px; |
| border-bottom: 1px solid |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| } |
| |
| .brand { |
| font-size: 1.2rem; |
| font-weight: 700; |
| color: |
| } |
| |
| .subtitle { |
| font-size: 0.75rem; |
| color: |
| } |
| |
| .menu { |
| list-style: none; |
| padding: 0; |
| margin: 0; |
| } |
| |
| .menu li a { |
| display: flex; |
| align-items: center; |
| padding: 12px 20px; |
| color: white; |
| text-decoration: none; |
| transition: background 0.3s; |
| } |
| |
| .menu li a:hover { |
| background: |
| } |
| |
| .menu li a i { |
| margin-right: 12px; |
| } |
| |
| .user-footer { |
| padding: 15px; |
| background: |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| position: sticky; |
| bottom: 0; |
| } |
| |
| .avatar { |
| width: 35px; |
| height: 35px; |
| background: |
| border-radius: 50%; |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| font-weight: bold; |
| color: white; |
| } |
| |
| .card { |
| background: var(--card); |
| border-radius: 12px; |
| padding: 26px; |
| color: white; |
| box-shadow: 0 6px 0 rgba(0,0,0,0.08) inset; |
| display: none; |
| } |
| |
| .card.active { |
| display: block; |
| } |
| |
| .profile-avatar { |
| width: 100px; |
| height: 100px; |
| border-radius: 50%; |
| background: |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| margin: 0 auto; |
| font-size: 2rem; |
| font-weight: bold; |
| } |
| |
| .form-group { |
| margin: 12px 0; |
| } |
| |
| label { |
| display: block; |
| margin-bottom: 8px; |
| color: rgba(255,255,255,0.85); |
| } |
| |
| input, select { |
| width: 100%; |
| padding: 14px; |
| border-radius: 10px; |
| border: 1px solid rgba(255,255,255,0.05); |
| background: transparent; |
| color: white; |
| } |
| |
| .btn { |
| display: inline-block; |
| padding: 14px 24px; |
| border-radius: 10px; |
| background: var(--accent); |
| color: |
| font-weight: 700; |
| border: none; |
| cursor: pointer; |
| width: 100%; |
| } |
| |
| .btn-outline { |
| background: transparent; |
| border: 1px solid var(--accent); |
| color: var(--accent); |
| } |
| |
| .tab { |
| padding: 10px 20px; |
| border-bottom: 2px solid transparent; |
| cursor: pointer; |
| } |
| |
| .tab.active { |
| border-bottom: 2px solid var(--accent); |
| color: var(--accent); |
| } |
|
|
| .notification { |
| position: fixed; |
| top: 20px; |
| right: 20px; |
| padding: 15px 20px; |
| border-radius: 8px; |
| color: white; |
| z-index: 10000; |
| animation: slideIn 0.3s ease; |
| } |
|
|
| .notification.success { background: |
| .notification.error { background: |
| .notification.info { background: |
|
|
| .activity-item { |
| padding: 15px; |
| border-bottom: 1px solid rgba(255,255,255,0.1); |
| display: flex; |
| align-items: center; |
| } |
|
|
| .activity-item:last-child { |
| border-bottom: none; |
| } |
|
|
| .activity-icon { |
| width: 40px; |
| height: 40px; |
| border-radius: 50%; |
| background: rgba(255,255,255,0.1); |
| display: flex; |
| align-items: center; |
| justify-content: center; |
| margin-right: 15px; |
| } |
|
|
| @keyframes slideIn { |
| from { transform: translateX(100%); opacity: 0; } |
| to { transform: translateX(0); opacity: 1; } |
| } |
|
|
| .loading { |
| opacity: 0.6; |
| pointer-events: none; |
| } |
| |
| @media (max-width: 768px) { |
| .tabs { |
| flex-direction: column; |
| } |
| } |
| </style> |
| </head> |
| <body> |
| <!-- Sidebar --> |
| <aside class="sidebar" id="sidebar"> |
| <div class="logo-section"> |
| <i data-feather="zap" class="text-yellow-400"></i> |
| <div> |
| <h2 class="brand">JMOTORS</h2> |
| <p class="subtitle">Marketing Platform</p> |
| </div> |
| </div> |
| |
| <ul class="menu"> |
| <li><a href="index.php"><i data-feather="home"></i> Dashboard</a></li> |
| <li><a href="meta-uploads.php"><i data-feather="upload"></i> Meta Uploads</a></li> |
| <li><a href="transactions.php"><i data-feather="repeat"></i> Transactions</a></li> |
| <li><a href="transfer.php"><i data-feather="send"></i> Transfer</a></li> |
| <li><a href="daily-product.php"><i data-feather="shopping-bag"></i> Daily Product</a></li> |
| <li><a href="withdraw.php"><i data-feather="dollar-sign"></i> Withdraw</a></li> |
| <li><a href="packages.php"><i data-feather="package"></i> Packages</a></li> |
| <li><a href="loan.php"><i data-feather="credit-card"></i> Loan</a></li> |
| <li><a href="recharge.php"><i data-feather="battery-charging"></i> Recharge</a></li> |
| <li><a href="agent-approval.php"><i data-feather="user-check"></i> Agent Approval</a></li> |
| <li><a href="access-token.php"><i data-feather="key"></i> Access Token</a></li> |
| <li><a href="agent-claim.php"><i data-feather="tag"></i> Agent Claim</a></li> |
| <li><a href="team.php"><i data-feather="users"></i> Team</a></li> |
| </ul> |
| |
| <ul class="menu bottom"> |
| <li><a href="profile.php" class="active-page"><i data-feather="user"></i> Profile</a></li> |
| <li><a href="settings.php"><i data-feather="settings"></i> Settings</a></li> |
| <li><a href="whatsapp-channel.php"><i data-feather="message-square"></i> Whatsapp Channel</a></li> |
| <li><a href="customer-care.php"><i data-feather="headphones"></i> Customer Care</a></li> |
| </ul> |
| |
| <div class="user-footer"> |
| <div class="avatar"><?php echo substr($username, 0, 2); ?></div> |
| <div> |
| <h4><?php echo htmlspecialchars($username); ?></h4> |
| <p><?php echo htmlspecialchars($tier); ?> - Marketer</p> |
| </div> |
| </div> |
| </aside> |
| |
| <!-- Main Content --> |
| <div id="content"> |
| <header class="bg-gray-800 text-white p-4"> |
| <div class="flex items-center"> |
| <button class="menu-toggle" id="menu-toggle"> |
| <i data-feather="menu"></i> |
| </button> |
| <div class="ml-4 font-bold text-xl">Jmotors</div> |
| </div> |
| <nav class="flex items-center space-x-6"> |
| <a href="transfer.php" class="hover:text-yellow-300">Transfer</a> |
| <a href="loan.php" class="hover:text-yellow-300">Loans</a> |
| <a href="dailyproduct.php" class="hover:text-yellow-300">New Product</a> |
| <div class="w-9 h-9 rounded-full bg-gradient-to-r from-yellow-300 to-orange-400 flex items-center justify-center font-bold"> |
| <?php echo substr($first_name, 0, 1) . substr($last_name, 0, 1); ?> |
| </div> |
| </nav> |
| </header> |
| |
| <main class="p-4"> |
| <div class="max-w-3xl mx-auto"> |
| <div class="card mb-6 active"> |
| <div class="flex flex-col md:flex-row items-center gap-6"> |
| <div class="profile-avatar"><?php echo substr($first_name, 0, 1) . substr($last_name, 0, 1); ?></div> |
| <div class="text-center md:text-left"> |
| <h2 class="text-2xl font-bold"><?php echo htmlspecialchars($first_name . ' ' . $last_name); ?></h2> |
| <p class="text-gray-300"><?php echo htmlspecialchars($status); ?> Marketer</p> |
| <p class="text-sm mt-2">Member since: <?php echo $member_since_formatted; ?></p> |
| </div> |
| </div> |
| </div> |
| |
| <div class="flex tabs border-b border-gray-700 mb-6"> |
| <div class="tab active" data-tab="personal">Personal Info</div> |
| <div class="tab" data-tab="security">Security</div> |
| <div class="tab" data-tab="activity">Activity</div> |
| </div> |
| |
| <!-- Personal Info Tab --> |
| <div class="card active" id="personal-tab"> |
| <h3 class="text-lg font-bold mb-6">Personal Information</h3> |
| |
| <form id="profileForm"> |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> |
| <div class="form-group"> |
| <label>First Name</label> |
| <input type="text" name="first_name" value="<?php echo htmlspecialchars($first_name); ?>" id="first_name"> |
| </div> |
| <div class="form-group"> |
| <label>Last Name</label> |
| <input type="text" name="last_name" value="<?php echo htmlspecialchars($last_name); ?>" id="last_name"> |
| </div> |
| </div> |
| |
| <div class="form-group"> |
| <label>Email Address</label> |
| <input type="email" name="email" value="<?php echo htmlspecialchars($email); ?>" id="email"> |
| </div> |
| |
| <div class="form-group"> |
| <label>Phone Number</label> |
| <input type="tel" name="phone_number" value="<?php echo htmlspecialchars($phone_number); ?>" id="phone_number"> |
| </div> |
| |
| <div class="form-group"> |
| <label>Country</label> |
| <select name="country_code" id="country" required> |
| <option value="">Select your country</option> |
| </select> |
| </div> |
| |
| <div class="flex gap-4 mt-6"> |
| <button type="submit" class="btn" id="saveBtn">Save Changes</button> |
| <button type="button" class="btn btn-outline" id="cancelBtn">Cancel</button> |
| </div> |
| </form> |
| </div> |
| |
| <!-- Security Tab --> |
| <div class="card" id="security-tab"> |
| <h3 class="text-lg font-bold mb-6">Security Settings</h3> |
| |
| <form id="securityForm"> |
| <div class="form-group"> |
| <label>Current Password</label> |
| <input type="password" name="current_password" id="current_password" required> |
| </div> |
| |
| <div class="form-group"> |
| <label>New Password</label> |
| <input type="password" name="new_password" id="new_password" required minlength="6"> |
| </div> |
| |
| <div class="form-group"> |
| <label>Confirm New Password</label> |
| <input type="password" name="confirm_password" id="confirm_password" required minlength="6"> |
| </div> |
| |
| <div class="flex gap-4 mt-6"> |
| <button type="submit" class="btn" id="changePasswordBtn">Change Password</button> |
| </div> |
| </form> |
| |
| <div class="mt-8 pt-6 border-t border-gray-700"> |
| <h4 class="text-md font-bold mb-4">Security Recommendations</h4> |
| <ul class="space-y-2 text-sm text-gray-300"> |
| <li>• Use a strong, unique password</li> |
| <li>• Enable two-factor authentication if available</li> |
| <li>• Regularly update your password</li> |
| <li>• Never share your password with anyone</li> |
| </ul> |
| </div> |
| </div> |
| |
| <!-- Activity Tab --> |
| <div class="card" id="activity-tab"> |
| <h3 class="text-lg font-bold mb-6">Recent Activity</h3> |
| |
| <div id="activityList" class="space-y-4"> |
| <div class="text-center py-8 text-gray-400"> |
| <i data-feather="activity" class="w-12 h-12 mx-auto mb-4"></i> |
| <p>Loading activity history...</p> |
| </div> |
| </div> |
| |
| <div class="mt-6 text-center"> |
| <button class="btn btn-outline" id="loadMoreActivity">Load More</button> |
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
| |
| <script> |
| feather.replace(); |
| |
| // Countries data |
| const countries = [ |
| { name: "Afghanistan", dial_code: "+93", code: "AF" }, |
| { name: "Albania", dial_code: "+355", code: "AL" }, |
| { name: "Algeria", dial_code: "+213", code: "DZ" }, |
| { name: "Andorra", dial_code: "+376", code: "AD" }, |
| { name: "Angola", dial_code: "+244", code: "AO" }, |
| { name: "Antigua and Barbuda", dial_code: "+1-268", code: "AG" }, |
| { name: "Argentina", dial_code: "+54", code: "AR" }, |
| { name: "Armenia", dial_code: "+374", code: "AM" }, |
| { name: "Australia", dial_code: "+61", code: "AU" }, |
| { name: "Austria", dial_code: "+43", code: "AT" }, |
| { name: "Azerbaijan", dial_code: "+994", code: "AZ" }, |
| { name: "Bahamas", dial_code: "+1-242", code: "BS" }, |
| { name: "Bahrain", dial_code: "+973", code: "BH" }, |
| { name: "Bangladesh", dial_code: "+880", code: "BD" }, |
| { name: "Barbados", dial_code: "+1-246", code: "BB" }, |
| { name: "Belarus", dial_code: "+375", code: "BY" }, |
| { name: "Belgium", dial_code: "+32", code: "BE" }, |
| { name: "Belize", dial_code: "+501", code: "BZ" }, |
| { name: "Benin", dial_code: "+229", code: "BJ" }, |
| { name: "Bhutan", dial_code: "+975", code: "BT" }, |
| { name: "Bolivia", dial_code: "+591", code: "BO" }, |
| { name: "Bosnia and Herzegovina", dial_code: "+387", code: "BA" }, |
| { name: "Botswana", dial_code: "+267", code: "BW" }, |
| { name: "Brazil", dial_code: "+55", code: "BR" }, |
| { name: "Brunei", dial_code: "+673", code: "BN" }, |
| { name: "Bulgaria", dial_code: "+359", code: "BG" }, |
| { name: "Burkina Faso", dial_code: "+226", code: "BF" }, |
| { name: "Burundi", dial_code: "+257", code: "BI" }, |
| { name: "Cabo Verde", dial_code: "+238", code: "CV" }, |
| { name: "Cambodia", dial_code: "+855", code: "KH" }, |
| { name: "Cameroon", dial_code: "+237", code: "CM" }, |
| { name: "Canada", dial_code: "+1", code: "CA" }, |
| { name: "Central African Republic", dial_code: "+236", code: "CF" }, |
| { name: "Chad", dial_code: "+235", code: "TD" }, |
| { name: "Chile", dial_code: "+56", code: "CL" }, |
| { name: "China", dial_code: "+86", code: "CN" }, |
| { name: "Colombia", dial_code: "+57", code: "CO" }, |
| { name: "Comoros", dial_code: "+269", code: "KM" }, |
| { name: "Congo (Brazzaville)", dial_code: "+242", code: "CG" }, |
| { name: "Congo (Kinshasa)", dial_code: "+243", code: "CD" }, |
| { name: "Costa Rica", dial_code: "+506", code: "CR" }, |
| { name: "Croatia", dial_code: "+385", code: "HR" }, |
| { name: "Cuba", dial_code: "+53", code: "CU" }, |
| { name: "Cyprus", dial_code: "+357", code: "CY" }, |
| { name: "Czechia", dial_code: "+420", code: "CZ" }, |
| { name: "Denmark", dial_code: "+45", code: "DK" }, |
| { name: "Djibouti", dial_code: "+253", code: "DJ" }, |
| { name: "Dominica", dial_code: "+1-767", code: "DM" }, |
| { name: "Dominican Republic", dial_code: "+1-809", code: "DO" }, |
| { name: "Ecuador", dial_code: "+593", code: "EC" }, |
| { name: "Egypt", dial_code: "+20", code: "EG" }, |
| { name: "El Salvador", dial_code: "+503", code: "SV" }, |
| { name: "Equatorial Guinea", dial_code: "+240", code: "GQ" }, |
| { name: "Eritrea", dial_code: "+291", code: "ER" }, |
| { name: "Estonia", dial_code: "+372", code: "EE" }, |
| { name: "Eswatini", dial_code: "+268", code: "SZ" }, |
| { name: "Ethiopia", dial_code: "+251", code: "ET" }, |
| { name: "Fiji", dial_code: "+679", code: "FJ" }, |
| { name: "Finland", dial_code: "+358", code: "FI" }, |
| { name: "France", dial_code: "+33", code: "FR" }, |
| { name: "Gabon", dial_code: "+241", code: "GA" }, |
| { name: "Gambia", dial_code: "+220", code: "GM" }, |
| { name: "Georgia", dial_code: "+995", code: "GE" }, |
| { name: "Germany", dial_code: "+49", code: "DE" }, |
| { name: "Ghana", dial_code: "+233", code: "GH" }, |
| { name: "Greece", dial_code: "+30", code: "GR" }, |
| { name: "Grenada", dial_code: "+1-473", code: "GD" }, |
| { name: "Guatemala", dial_code: "+502", code: "GT" }, |
| { name: "Guinea", dial_code: "+224", code: "GN" }, |
| { name: "Guinea-Bissau", dial_code: "+245", code: "GW" }, |
| { name: "Guyana", dial_code: "+592", code: "GY" }, |
| { name: "Haiti", dial_code: "+509", code: "HT" }, |
| { name: "Honduras", dial_code: "+504", code: "HN" }, |
| { name: "Hungary", dial_code: "+36", code: "HU" }, |
| { name: "Iceland", dial_code: "+354", code: "IS" }, |
| { name: "India", dial_code: "+91", code: "IN" }, |
| { name: "Indonesia", dial_code: "+62", code: "ID" }, |
| { name: "Iran", dial_code: "+98", code: "IR" }, |
| { name: "Iraq", dial_code: "+964", code: "IQ" }, |
| { name: "Ireland", dial_code: "+353", code: "IE" }, |
| { name: "Israel", dial_code: "+972", code: "IL" }, |
| { name: "Italy", dial_code: "+39", code: "IT" }, |
| { name: "Jamaica", dial_code: "+1-876", code: "JM" }, |
| { name: "Japan", dial_code: "+81", code: "JP" }, |
| { name: "Jordan", dial_code: "+962", code: "JO" }, |
| { name: "Kazakhstan", dial_code: "+7", code: "KZ" }, |
| { name: "Kenya", dial_code: "+254", code: "KE" }, |
| { name: "Kiribati", dial_code: "+686", code: "KI" }, |
| { name: "Kuwait", dial_code: "+965", code: "KW" }, |
| { name: "Kyrgyzstan", dial_code: "+996", code: "KG" }, |
| { name: "Laos", dial_code: "+856", code: "LA" }, |
| { name: "Latvia", dial_code: "+371", code: "LV" }, |
| { name: "Lebanon", dial_code: "+961", code: "LB" }, |
| { name: "Lesotho", dial_code: "+266", code: "LS" }, |
| { name: "Liberia", dial_code: "+231", code: "LR" }, |
| { name: "Libya", dial_code: "+218", code: "LY" }, |
| { name: "Liechtenstein", dial_code: "+423", code: "LI" }, |
| { name: "Lithuania", dial_code: "+370", code: "LT" }, |
| { name: "Luxembourg", dial_code: "+352", code: "LU" }, |
| { name: "Madagascar", dial_code: "+261", code: "MG" }, |
| { name: "Malawi", dial_code: "+265", code: "MW" }, |
| { name: "Malaysia", dial_code: "+60", code: "MY" }, |
| { name: "Maldives", dial_code: "+960", code: "MV" }, |
| { name: "Mali", dial_code: "+223", code: "ML" }, |
| { name: "Malta", dial_code: "+356", code: "MT" }, |
| { name: "Marshall Islands", dial_code: "+692", code: "MH" }, |
| { name: "Mauritania", dial_code: "+222", code: "MR" }, |
| { name: "Mauritius", dial_code: "+230", code: "MU" }, |
| { name: "Mexico", dial_code: "+52", code: "MX" }, |
| { name: "Micronesia", dial_code: "+691", code: "FM" }, |
| { name: "Moldova", dial_code: "+373", code: "MD" }, |
| { name: "Monaco", dial_code: "+377", code: "MC" }, |
| { name: "Mongolia", dial_code: "+976", code: "MN" }, |
| { name: "Montenegro", dial_code: "+382", code: "ME" }, |
| { name: "Morocco", dial_code: "+212", code: "MA" }, |
| { name: "Mozambique", dial_code: "+258", code: "MZ" }, |
| { name: "Myanmar", dial_code: "+95", code: "MM" }, |
| { name: "Namibia", dial_code: "+264", code: "NA" }, |
| { name: "Nauru", dial_code: "+674", code: "NR" }, |
| { name: "Nepal", dial_code: "+977", code: "NP" }, |
| { name: "Netherlands", dial_code: "+31", code: "NL" }, |
| { name: "New Zealand", dial_code: "+64", code: "NZ" }, |
| { name: "Nicaragua", dial_code: "+505", code: "NI" }, |
| { name: "Niger", dial_code: "+227", code: "NE" }, |
| { name: "Nigeria", dial_code: "+234", code: "NG" }, |
| { name: "North Korea", dial_code: "+850", code: "KP" }, |
| { name: "North Macedonia", dial_code: "+389", code: "MK" }, |
| { name: "Norway", dial_code: "+47", code: "NO" }, |
| { name: "Oman", dial_code: "+968", code: "OM" }, |
| { name: "Pakistan", dial_code: "+92", code: "PK" }, |
| { name: "Palau", dial_code: "+680", code: "PW" }, |
| { name: "Palestine", dial_code: "+970", code: "PS" }, |
| { name: "Panama", dial_code: "+507", code: "PA" }, |
| { name: "Papua New Guinea", dial_code: "+675", code: "PG" }, |
| { name: "Paraguay", dial_code: "+595", code: "PY" }, |
| { name: "Peru", dial_code: "+51", code: "PE" }, |
| { name: "Philippines", dial_code: "+63", code: "PH" }, |
| { name: "Poland", dial_code: "+48", code: "PL" }, |
| { name: "Portugal", dial_code: "+351", code: "PT" }, |
| { name: "Qatar", dial_code: "+974", code: "QA" }, |
| { name: "Romania", dial_code: "+40", code: "RO" }, |
| { name: "Russia", dial_code: "+7", code: "RU" }, |
| { name: "Rwanda", dial_code: "+250", code: "RW" }, |
| { name: "Saint Kitts and Nevis", dial_code: "+1-869", code: "KN" }, |
| { name: "Saint Lucia", dial_code: "+1-758", code: "LC" }, |
| { name: "Saint Vincent and the Grenadines", dial_code: "+1-784", code: "VC" }, |
| { name: "Samoa", dial_code: "+685", code: "WS" }, |
| { name: "San Marino", dial_code: "+378", code: "SM" }, |
| { name: "Sao Tome and Principe", dial_code: "+239", code: "ST" }, |
| { name: "Saudi Arabia", dial_code: "+966", code: "SA" }, |
| { name: "Senegal", dial_code: "+221", code: "SN" }, |
| { name: "Serbia", dial_code: "+381", code: "RS" }, |
| { name: "Seychelles", dial_code: "+248", code: "SC" }, |
| { name: "Sierra Leone", dial_code: "+232", code: "SL" }, |
| { name: "Singapore", dial_code: "+65", code: "SG" }, |
| { name: "Slovakia", dial_code: "+421", code: "SK" }, |
| { name: "Slovenia", dial_code: "+386", code: "SI" }, |
| { name: "Solomon Islands", dial_code: "+677", code: "SB" }, |
| { name: "Somalia", dial_code: "+252", code: "SO" }, |
| { name: "South Africa", dial_code: "+27", code: "ZA" }, |
| { name: "South Korea", dial_code: "+82", code: "KR" }, |
| { name: "South Sudan", dial_code: "+211", code: "SS" }, |
| { name: "Spain", dial_code: "+34", code: "ES" }, |
| { name: "Sri Lanka", dial_code: "+94", code: "LK" }, |
| { name: "Sudan", dial_code: "+249", code: "SD" }, |
| { name: "Suriname", dial_code: "+597", code: "SR" }, |
| { name: "Sweden", dial_code: "+46", code: "SE" }, |
| { name: "Switzerland", dial_code: "+41", code: "CH" }, |
| { name: "Syria", dial_code: "+963", code: "SY" }, |
| { name: "Taiwan", dial_code: "+886", code: "TW" }, |
| { name: "Tajikistan", dial_code: "+992", code: "TJ" }, |
| { name: "Tanzania", dial_code: "+255", code: "TZ" }, |
| { name: "Thailand", dial_code: "+66", code: "TH" }, |
| { name: "Timor-Leste", dial_code: "+670", code: "TL" }, |
| { name: "Togo", dial_code: "+228", code: "TG" }, |
| { name: "Tonga", dial_code: "+676", code: "TO" }, |
| { name: "Trinidad and Tobago", dial_code: "+1-868", code: "TT" }, |
| { name: "Tunisia", dial_code: "+216", code: "TN" }, |
| { name: "Turkey", dial_code: "+90", code: "TR" }, |
| { name: "Turkmenistan", dial_code: "+993", code: "TM" }, |
| { name: "Tuvalu", dial_code: "+688", code: "TV" }, |
| { name: "Uganda", dial_code: "+256", code: "UG" }, |
| { name: "Ukraine", dial_code: "+380", code: "UA" }, |
| { name: "United Arab Emirates", dial_code: "+971", code: "AE" }, |
| { name: "United Kingdom", dial_code: "+44", code: "GB" }, |
| { name: "United States", dial_code: "+1", code: "US" }, |
| { name: "Uruguay", dial_code: "+598", code: "UY" }, |
| { name: "Uzbekistan", dial_code: "+998", code: "UZ" }, |
| { name: "Vanuatu", dial_code: "+678", code: "VU" }, |
| { name: "Vatican City", dial_code: "+379", code: "VA" }, |
| { name: "Venezuela", dial_code: "+58", code: "VE" }, |
| { name: "Vietnam", dial_code: "+84", code: "VN" }, |
| { name: "Yemen", dial_code: "+967", code: "YE" }, |
| { name: "Zambia", dial_code: "+260", code: "ZM" }, |
| { name: "Zimbabwe", dial_code: "+263", code: "ZW"}, |
| ]; |
|
|
| document.addEventListener('DOMContentLoaded', function() { |
| const toggleBtn = document.getElementById('menu-toggle'); |
| const sidebar = document.getElementById('sidebar'); |
| const content = document.getElementById('content'); |
| |
| toggleBtn.addEventListener('click', function() { |
| sidebar.classList.toggle('active'); |
| content.classList.toggle('active'); |
| }); |
|
|
| |
| const countrySelect = document.getElementById("country"); |
| const userCountryCode = "<?php echo $country_code; ?>"; |
| |
| countries.forEach(c => { |
| const option = document.createElement("option"); |
| option.value = c.code; |
| option.textContent = `${c.name} (${c.dial_code})`; |
| if (c.code === userCountryCode) { |
| option.selected = true; |
| } |
| countrySelect.appendChild(option); |
| }); |
| |
| |
| const tabs = document.querySelectorAll('.tab'); |
| const tabContents = document.querySelectorAll('.card'); |
| |
| tabs.forEach(tab => { |
| tab.addEventListener('click', function() { |
| const tabName = this.getAttribute('data-tab'); |
| |
| // Update tabs |
| tabs.forEach(t => t.classList.remove('active')); |
| this.classList.add('active'); |
| |
| // Update content |
| tabContents.forEach(content => { |
| content.classList.remove('active'); |
| if (content.id === `${tabName}-tab`) { |
| content.classList.add('active'); |
| } |
| }); |
| |
| |
| if (tabName === 'activity') { |
| loadActivity(); |
| } |
| }); |
| }); |
|
|
| |
| new ProfileManager(); |
| }); |
|
|
| |
| class ProfileManager { |
| constructor() { |
| this.originalData = {}; |
| this.activityOffset = 0; |
| this.init(); |
| } |
|
|
| init() { |
| this.setupEventListeners(); |
| this.loadOriginalData(); |
| } |
|
|
| loadOriginalData() { |
| this.originalData = { |
| first_name: document.getElementById('first_name').value, |
| last_name: document.getElementById('last_name').value, |
| email: document.getElementById('email').value, |
| phone_number: document.getElementById('phone_number').value, |
| country_code: document.getElementById('country').value |
| }; |
| } |
|
|
| setupEventListeners() { |
| |
| const profileForm = document.getElementById('profileForm'); |
| const securityForm = document.getElementById('securityForm'); |
| const loadMoreBtn = document.getElementById('loadMoreActivity'); |
|
|
| |
| const inputs = profileForm.querySelectorAll('input, select'); |
| inputs.forEach(input => { |
| input.addEventListener('input', this.debounce((e) => { |
| this.autoSaveField(e.target.name, e.target.value); |
| }, 1000)); |
| }); |
|
|
| profileForm.addEventListener('submit', (e) => { |
| e.preventDefault(); |
| this.saveProfile(); |
| }); |
|
|
| document.getElementById('cancelBtn').addEventListener('click', () => { |
| this.cancelChanges(); |
| }); |
|
|
| |
| securityForm.addEventListener('submit', (e) => { |
| e.preventDefault(); |
| this.changePassword(); |
| }); |
|
|
| |
| if (loadMoreBtn) { |
| loadMoreBtn.addEventListener('click', () => { |
| this.loadMoreActivity(); |
| }); |
| } |
| } |
|
|
| async autoSaveField(field, value) { |
| try { |
| const response = await this.makeRequest('profile_handler.php', { |
| action: 'update_profile', |
| [field]: value |
| }); |
|
|
| if (response.success) { |
| this.showNotification('Auto-saved successfully', 'success'); |
| } |
| } catch (error) { |
| console.error('Auto-save failed:', error); |
| } |
| } |
|
|
| async saveProfile() { |
| const formData = new FormData(document.getElementById('profileForm')); |
| const data = Object.fromEntries(formData.entries()); |
|
|
| try { |
| this.setLoading(true, 'saveBtn', 'Saving...'); |
| |
| const response = await this.makeRequest('profile_handler.php', { |
| action: 'update_profile', |
| ...data |
| }); |
|
|
| if (response.success) { |
| this.showNotification('Profile updated successfully!', 'success'); |
| this.loadOriginalData(); |
| this.updateProfileDisplay(data); |
| } else { |
| throw new Error(response.message); |
| } |
| } catch (error) { |
| this.showNotification('Error: ' + error.message, 'error'); |
| } finally { |
| this.setLoading(false, 'saveBtn', 'Save Changes'); |
| } |
| } |
|
|
| async changePassword() { |
| const formData = new FormData(document.getElementById('securityForm')); |
| const data = Object.fromEntries(formData.entries()); |
|
|
| try { |
| this.setLoading(true, 'changePasswordBtn', 'Changing...'); |
| |
| const response = await this.makeRequest('profile_handler.php', { |
| action: 'change_password', |
| ...data |
| }); |
|
|
| if (response.success) { |
| this.showNotification('Password changed successfully!', 'success'); |
| document.getElementById('securityForm').reset(); |
| } else { |
| throw new Error(response.message); |
| } |
| } catch (error) { |
| this.showNotification('Error: ' + error.message, 'error'); |
| } finally { |
| this.setLoading(false, 'changePasswordBtn', 'Change Password'); |
| } |
| } |
|
|
| async loadActivity() { |
| try { |
| const response = await this.makeRequest('profile_handler.php', { |
| action: 'get_activity' |
| }); |
|
|
| if (response.success) { |
| this.displayActivity(response.activities); |
| } |
| } catch (error) { |
| console.error('Failed to load activity:', error); |
| document.getElementById('activityList').innerHTML = |
| '<div class="text-center py-8 text-gray-400">Failed to load activity history</div>'; |
| } |
| } |
|
|
| async loadMoreActivity() { |
| this.activityOffset += 10; |
| try { |
| const response = await this.makeRequest('../api/profile_handler.php', { |
| action: 'get_activity', |
| offset: this.activityOffset |
| }); |
|
|
| if (response.success && response.activities.length > 0) { |
| this.displayActivity(response.activities, true); |
| } else { |
| this.showNotification('No more activities to load', 'info'); |
| } |
| } catch (error) { |
| console.error('Failed to load more activity:', error); |
| } |
| } |
|
|
| displayActivity(activities, append = false) { |
| const activityList = document.getElementById('activityList'); |
| |
| if (!activities || activities.length === 0) { |
| if (!append) { |
| activityList.innerHTML = |
| '<div class="text-center py-8 text-gray-400">No activity history found</div>'; |
| } |
| return; |
| } |
|
|
| const activitiesHTML = activities.map(activity => ` |
| <div class="activity-item"> |
| <div class="activity-icon"> |
| <i data-feather="${this.getActivityIcon(activity.activity_type)}"></i> |
| </div> |
| <div class="flex-1"> |
| <div class="font-medium">${activity.description}</div> |
| <div class="text-sm text-gray-400">${new Date(activity.timestamp).toLocaleString()}</div> |
| </div> |
| <div class="text-sm text-gray-400 capitalize">${activity.activity_type.replace('_', ' ')}</div> |
| </div> |
| `).join(''); |
|
|
| if (append) { |
| activityList.innerHTML += activitiesHTML; |
| } else { |
| activityList.innerHTML = activitiesHTML; |
| } |
|
|
| feather.replace(); |
| } |
|
|
| getActivityIcon(activityType) { |
| const icons = { |
| 'profile_update': 'user', |
| 'password_change': 'lock', |
| 'login': 'log-in', |
| 'logout': 'log-out', |
| 'default': 'activity' |
| }; |
| return icons[activityType] || icons.default; |
| } |
|
|
| cancelChanges() { |
| document.getElementById('first_name').value = this.originalData.first_name; |
| document.getElementById('last_name').value = this.originalData.last_name; |
| document.getElementById('email').value = this.originalData.email; |
| document.getElementById('phone_number').value = this.originalData.phone_number; |
| document.getElementById('country').value = this.originalData.country_code; |
| |
| this.showNotification('Changes cancelled', 'info'); |
| } |
|
|
| updateProfileDisplay(data) { |
| |
| const avatar = document.querySelector('.profile-avatar'); |
| const nameDisplay = document.querySelector('.text-2xl.font-bold'); |
| const userAvatar = document.querySelector('.w-9.h-9.rounded-full'); |
| |
| if (avatar) { |
| avatar.textContent = (data.first_name?.[0] || '') + (data.last_name?.[0] || ''); |
| } |
| if (nameDisplay) { |
| nameDisplay.textContent = `${data.first_name} ${data.last_name}`; |
| } |
| if (userAvatar) { |
| userAvatar.textContent = (data.first_name?.[0] || '') + (data.last_name?.[0] || ''); |
| } |
| } |
|
|
| setLoading(loading, buttonId, text) { |
| const button = document.getElementById(buttonId); |
| if (loading) { |
| button.classList.add('loading'); |
| button.textContent = text; |
| button.disabled = true; |
| } else { |
| button.classList.remove('loading'); |
| button.textContent = text; |
| button.disabled = false; |
| } |
| } |
|
|
| async makeRequest(url, data) { |
| const formData = new FormData(); |
| for (const key in data) { |
| formData.append(key, data[key]); |
| } |
|
|
| const response = await fetch(url, { |
| method: 'POST', |
| body: formData |
| }); |
|
|
| return await response.json(); |
| } |
|
|
| showNotification(message, type = 'info') { |
| |
| const existingNotifications = document.querySelectorAll('.notification'); |
| existingNotifications.forEach(notification => notification.remove()); |
|
|
| |
| const notification = document.createElement('div'); |
| notification.className = `notification ${type}`; |
| notification.textContent = message; |
|
|
| document.body.appendChild(notification); |
|
|
| |
| setTimeout(() => { |
| notification.remove(); |
| }, 3000); |
| } |
|
|
| debounce(func, wait) { |
| let timeout; |
| return function executedFunction(...args) { |
| const later = () => { |
| clearTimeout(timeout); |
| func(...args); |
| }; |
| clearTimeout(timeout); |
| timeout = setTimeout(later, wait); |
| }; |
| } |
| } |
|
|
| |
| function loadActivity() { |
| const profileManager = new ProfileManager(); |
| profileManager.loadActivity(); |
| } |
| </script> |
| </body> |
| </html> |