97 lines
4.5 KiB
PHP
97 lines
4.5 KiB
PHP
|
|
<?php
|
|
// Calculate Task Counts
|
|
$stmt = $pdo->prepare("SELECT status, COUNT(*) as count FROM tasks WHERE (assignee_type='user' AND assignee_id=?) OR (assignee_type='custom' AND assignor_id=?) GROUP BY status");
|
|
$stmt->execute([$user_id, $user_id]);
|
|
$task_counts = ['pending' => 0, 'in_progress' => 0, 'completed' => 0];
|
|
foreach($stmt->fetchAll() as $row) {
|
|
if(isset($task_counts[$row['status']])) $task_counts[$row['status']] = $row['count'];
|
|
}
|
|
$total_tasks = array_sum($task_counts);
|
|
|
|
// Calculate Passwords count
|
|
$stmt = $pdo->prepare("SELECT COUNT(*) FROM passwords p LEFT JOIN password_shares ps ON p.id = ps.password_id WHERE p.owner_id = ? OR (ps.share_type='user' AND ps.share_id=?)");
|
|
$stmt->execute([$user_id, $user_id]);
|
|
$passwords_count = $stmt->fetchColumn();
|
|
|
|
// Calculate Projects count
|
|
$stmt = $pdo->prepare("SELECT COUNT(*) FROM projects p LEFT JOIN project_shares ps ON p.id = ps.project_id WHERE p.owner_id = ? OR (ps.share_type='user' AND ps.share_id=?)");
|
|
$stmt->execute([$user_id, $user_id]);
|
|
$projects_count = $stmt->fetchColumn();
|
|
|
|
?>
|
|
<div class="header">
|
|
<h1>Dashboard</h1>
|
|
</div>
|
|
|
|
<div class="card" style="display:flex; justify-content:space-between; align-items:center;">
|
|
<div>
|
|
<h3>Welcome, <?= htmlspecialchars($current_user['username']) ?>!</h3>
|
|
<p style="margin-top:0.5rem; color:var(--text-light);"><span id="current-datetime"></span></p>
|
|
</div>
|
|
<div style="text-align:right">
|
|
<div style="font-weight:600; color:var(--primary);">Holiday Info:</div>
|
|
<div id="holiday-info" style="color:var(--text-light);">Loading...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.5rem;">
|
|
<!-- Tasks Card -->
|
|
<div class="card">
|
|
<h3>My Tasks Overview</h3>
|
|
<h1 style="margin: 1rem 0; font-size: 2.5rem; color: var(--primary);"><?= $total_tasks ?> <span style="font-size:1rem; color:var(--text-light);">Total</span></h1>
|
|
<div style="display:flex; justify-content:space-between; margin-top:1rem; border-top:1px solid var(--border); padding-top:1rem;">
|
|
<div>
|
|
<div style="font-size:0.875rem; color:var(--text-light);">Pending</div>
|
|
<div style="font-weight:600;"><?= $task_counts['pending'] ?></div>
|
|
</div>
|
|
<div>
|
|
<div style="font-size:0.875rem; color:var(--text-light);">In Progress</div>
|
|
<div style="font-weight:600; color:#F59E0B;"><?= $task_counts['in_progress'] ?></div>
|
|
</div>
|
|
<div>
|
|
<div style="font-size:0.875rem; color:var(--text-light);">Completed</div>
|
|
<div style="font-weight:600; color:var(--secondary);"><?= $task_counts['completed'] ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Passwords Card -->
|
|
<div class="card" style="display:flex; flex-direction:column; justify-content:center;">
|
|
<h3>My Passwords Vault</h3>
|
|
<h1 style="margin: 1rem 0; font-size: 2.5rem; color: var(--primary);"><?= $passwords_count ?> <span style="font-size:1rem; color:var(--text-light);">Items</span></h1>
|
|
<a href="?action=passwords" class="btn btn-sm">Go to Vault →</a>
|
|
</div>
|
|
|
|
<!-- Projects Card -->
|
|
<div class="card" style="display:flex; flex-direction:column; justify-content:center;">
|
|
<h3>My Projects & Files</h3>
|
|
<h1 style="margin: 1rem 0; font-size: 2.5rem; color: var(--primary);"><?= $projects_count ?> <span style="font-size:1rem; color:var(--text-light);">Files/Folders</span></h1>
|
|
<a href="?action=projects" class="btn btn-sm">Go to Explorer →</a>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Time & Holiday functions
|
|
function updateTime() {
|
|
const now = new Date();
|
|
document.getElementById('current-datetime').textContent = now.toLocaleString();
|
|
}
|
|
setInterval(updateTime, 1000);
|
|
updateTime();
|
|
|
|
fetch('https://date.nager.at/api/v3/NextPublicHolidaysWorldwide')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
if(data && data.length > 0) {
|
|
// Find upcoming holiday for US, or fallback to first worldwide
|
|
let h = data.find(x => x.countryCode === 'US') || data[0];
|
|
document.getElementById('holiday-info').textContent = h.date + ' - ' + h.name + ' (' + h.countryCode + ')';
|
|
} else {
|
|
document.getElementById('holiday-info').textContent = 'No upcoming holidays';
|
|
}
|
|
}).catch(err => {
|
|
document.getElementById('holiday-info').textContent = 'Unable to fetch data';
|
|
});
|
|
</script>
|