Add profile functionality #4
@@ -6,6 +6,13 @@ header('Content-Type: application/json');
|
|||||||
require_login();
|
require_login();
|
||||||
|
|
||||||
$user_id = current_user_id();
|
$user_id = current_user_id();
|
||||||
|
$profile_id = $_SESSION['active_profile_id'] ?? null;
|
||||||
|
|
||||||
|
if (!$profile_id) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'error' => 'No active profile']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
$data = json_decode(file_get_contents('php://input'), true);
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
$name = trim($data['name'] ?? '');
|
$name = trim($data['name'] ?? '');
|
||||||
@@ -16,7 +23,7 @@ if ($name === '') {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO projects (user_id, name) VALUES (?, ?)");
|
$stmt = $pdo->prepare("INSERT INTO projects (user_id, profile_id, name) VALUES (?, ?, ?)");
|
||||||
$stmt->execute([$user_id, $name]);
|
$stmt->execute([$user_id, $profile_id, $name]);
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]);
|
echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]);
|
||||||
|
|||||||
11
get_data.php
11
get_data.php
@@ -6,9 +6,16 @@ header('Content-Type: application/json');
|
|||||||
require_login();
|
require_login();
|
||||||
|
|
||||||
$user_id = current_user_id();
|
$user_id = current_user_id();
|
||||||
|
$profile_id = $_SESSION['active_profile_id'] ?? null;
|
||||||
|
|
||||||
$stmt = $pdo->prepare("SELECT * FROM projects WHERE user_id = ? ORDER BY sort_order ASC");
|
if (!$profile_id) {
|
||||||
$stmt->execute([$user_id]);
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'error' => 'No active profile']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM projects WHERE user_id = ? AND profile_id = ? ORDER BY sort_order ASC");
|
||||||
|
$stmt->execute([$user_id, $profile_id]);
|
||||||
$projects = $stmt->fetchAll();
|
$projects = $stmt->fetchAll();
|
||||||
|
|
||||||
foreach ($projects as &$project) {
|
foreach ($projects as &$project) {
|
||||||
|
|||||||
18
get_profiles.php
Normal file
18
get_profiles.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
require 'db.php';
|
||||||
|
require 'auth.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$user_id = current_user_id();
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("SELECT id, name, is_default FROM profiles WHERE user_id = ? ORDER BY is_default DESC, name ASC");
|
||||||
|
$stmt->execute([$user_id]);
|
||||||
|
$profiles = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'active_profile_id' => $_SESSION['active_profile_id'] ?? null,
|
||||||
|
'profiles' => $profiles
|
||||||
|
]);
|
||||||
51
index.php
51
index.php
@@ -144,8 +144,19 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.profile-select {
|
||||||
|
height: 32px; /* match your header-action-btn buttons */
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700; /* or 700 for stronger bold */
|
||||||
|
padding-right: 2.5rem; /* key: reserve space for the arrow */
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.add-project-btn {
|
.add-project-btn {
|
||||||
font-size: 1.4rem;
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600; /* or 700 for stronger bold */
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +271,7 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="d-flex align-items-center gap-3">
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<select id="profileSelect" class="form-select btn-lg profile-select" style="width: 140px;"></select>
|
||||||
<!-- Add Project -->
|
<!-- Add Project -->
|
||||||
<button class="btn btn-success btn-lg header-action-btn"
|
<button class="btn btn-success btn-lg header-action-btn"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
@@ -288,7 +299,6 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -540,9 +550,27 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadProfiles() {
|
||||||
|
fetch('get_profiles.php')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) return;
|
||||||
|
|
||||||
|
const sel = document.getElementById('profileSelect');
|
||||||
|
sel.innerHTML = '';
|
||||||
|
|
||||||
|
data.profiles.forEach(p => {
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = p.id;
|
||||||
|
opt.textContent = p.name;
|
||||||
|
sel.appendChild(opt);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.active_profile_id) {
|
||||||
|
sel.value = String(data.active_profile_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function fetchProjects() {
|
function fetchProjects() {
|
||||||
fetch('get_data.php')
|
fetch('get_data.php')
|
||||||
@@ -957,6 +985,22 @@ document.querySelectorAll('.project-column').forEach(col => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById('profileSelect').addEventListener('change', () => {
|
||||||
|
const profileId = parseInt(document.getElementById('profileSelect').value, 10);
|
||||||
|
|
||||||
|
fetch('set_profile.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ profile_id: profileId })
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) return;
|
||||||
|
fetchProjects();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
@@ -979,6 +1023,7 @@ document.querySelectorAll('.project-column').forEach(col => {
|
|||||||
document.querySelectorAll('.settings-btn').forEach(b => b.style.display = 'none');
|
document.querySelectorAll('.settings-btn').forEach(b => b.style.display = 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadProfiles();
|
||||||
fetchProjects();
|
fetchProjects();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
24
login.php
24
login.php
@@ -33,6 +33,27 @@ $_SESSION['user'] = [
|
|||||||
'can_manage_settings' => intval($user['can_manage_settings']),
|
'can_manage_settings' => intval($user['can_manage_settings']),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Set active profile for this session (default profile if available)
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM profiles WHERE user_id = ? AND is_default = 1 LIMIT 1");
|
||||||
|
$stmt->execute([$_SESSION['user']['id']]);
|
||||||
|
$profileId = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
if (!$profileId) {
|
||||||
|
// Fallback to first profile
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM profiles WHERE user_id = ? ORDER BY id ASC LIMIT 1");
|
||||||
|
$stmt->execute([$_SESSION['user']['id']]);
|
||||||
|
$profileId = $stmt->fetchColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$profileId) {
|
||||||
|
// Last-resort: create a default profile if none exist (useful for new users)
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO profiles (user_id, name, is_default) VALUES (?, 'Default', 1)");
|
||||||
|
$stmt->execute([$_SESSION['user']['id']]);
|
||||||
|
$profileId = $pdo->lastInsertId();
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['active_profile_id'] = (int)$profileId;
|
||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'user' => [
|
'user' => [
|
||||||
@@ -40,5 +61,6 @@ echo json_encode([
|
|||||||
'email' => $_SESSION['user']['email'],
|
'email' => $_SESSION['user']['email'],
|
||||||
'role' => $_SESSION['user']['role'],
|
'role' => $_SESSION['user']['role'],
|
||||||
'can_manage_settings' => $_SESSION['user']['can_manage_settings'],
|
'can_manage_settings' => $_SESSION['user']['can_manage_settings'],
|
||||||
]
|
],
|
||||||
|
'active_profile_id' => $_SESSION['active_profile_id']
|
||||||
]);
|
]);
|
||||||
|
|||||||
14
register.php
14
register.php
@@ -33,10 +33,24 @@ if ($role_id <= 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
|
// Create user
|
||||||
$stmt = $pdo->prepare("INSERT INTO users (email, password_hash, role_id) VALUES (?, ?, ?)");
|
$stmt = $pdo->prepare("INSERT INTO users (email, password_hash, role_id) VALUES (?, ?, ?)");
|
||||||
$stmt->execute([$email, $hash, $role_id]);
|
$stmt->execute([$email, $hash, $role_id]);
|
||||||
|
$userId = (int)$pdo->lastInsertId();
|
||||||
|
|
||||||
|
// Create default profile for this user
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO profiles (user_id, name, is_default) VALUES (?, 'Default', 1)");
|
||||||
|
$stmt->execute([$userId]);
|
||||||
|
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
echo json_encode(['success' => true]);
|
echo json_encode(['success' => true]);
|
||||||
|
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
|
if ($pdo->inTransaction()) $pdo->rollBack();
|
||||||
|
|
||||||
http_response_code(409);
|
http_response_code(409);
|
||||||
echo json_encode(['success' => false, 'error' => 'Account already exists']);
|
echo json_encode(['success' => false, 'error' => 'Account already exists']);
|
||||||
}
|
}
|
||||||
|
|||||||
30
set_profile.php
Normal file
30
set_profile.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
require 'db.php';
|
||||||
|
require 'auth.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
require_login();
|
||||||
|
|
||||||
|
$user_id = current_user_id();
|
||||||
|
|
||||||
|
$input = json_decode(file_get_contents('php://input'), true);
|
||||||
|
$profile_id = (int)($input['profile_id'] ?? 0);
|
||||||
|
|
||||||
|
if ($profile_id <= 0) {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Invalid profile_id']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM profiles WHERE id = ? AND user_id = ?");
|
||||||
|
$stmt->execute([$profile_id, $user_id]);
|
||||||
|
|
||||||
|
if (!$stmt->fetchColumn()) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Profile not allowed']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['active_profile_id'] = $profile_id;
|
||||||
|
|
||||||
|
echo json_encode(['success' => true, 'active_profile_id' => $profile_id]);
|
||||||
Reference in New Issue
Block a user