Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,4 @@ GitHub: https://github.com/Charushi06
Built with AI, code, and a mission to simplify student life.

---
sonu
75 changes: 71 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ <h1 class="site-title">StudyPlan</h1>
</nav>

<div class="header-right">
<button class="profile-btn">Profile</button>
<button class="profile-btn" id="profile-btn">Profile</button>
<button class="profile-btn" id="logout-btn">Logout</button>
</div>
</header>
Expand Down Expand Up @@ -207,6 +207,62 @@ <h1 class="site-title">StudyPlan</h1>
</div>
</div>
</div>

<!-- Profile Page -->
<div id="profile-section" class="profile-section hidden" style="padding: 32px 40px; color: var(--color-text-primary);">
<h2 style="font-size: 28px; font-weight: 700; margin-bottom: 8px;">User Profile</h2>
<p style="color: var(--color-text-secondary); font-size: 14px; margin-bottom: 32px;">Manage your account details and view study statistics.</p>

<div style="display: grid; grid-template-columns: 280px 1fr; gap: 40px; align-items: start;">
<!-- Left side: Avatar & Info -->
<div style="background: rgba(255, 255, 255, 0.02); border: 1px solid var(--color-border-secondary); border-radius: 16px; padding: 32px 24px; text-align: center; box-shadow: var(--shadow-sm);">
<div id="desktop-profile-avatar" style="width: 110px; height: 110px; border-radius: 50%; background: var(--color-text-info); color: white; display: flex; align-items: center; justify-content: center; font-size: 44px; font-weight: 700; margin: 0 auto 20px; text-transform: uppercase; box-shadow: var(--shadow-md);">
U
</div>
<h3 id="desktop-profile-email" style="font-size: 18px; font-weight: 600; margin: 0 0 6px; word-break: break-all;">user@example.com</h3>
<p style="color: var(--color-text-secondary); font-size: 13px; margin: 0 0 24px;">Student Account</p>
<div style="border-top: 1px solid var(--color-border-secondary); padding-top: 20px;">
<span style="font-size: 12px; color: var(--color-text-tertiary); font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; display: block; margin-bottom: 8px;">Theme Mode</span>
<span id="desktop-profile-theme" style="font-size: 14px; font-weight: 600; color: var(--color-text-primary); text-transform: capitalize;">Light Mode</span>
</div>
</div>

<!-- Right side: Statistics & Performance -->
<div style="display: flex; flex-direction: column; gap: 32px;">
<div>
<h3 style="font-size: 16px; font-weight: 600; margin: 0 0 16px; display: flex; align-items: center; gap: 8px;">
<i class="fas fa-chart-line" style="color: var(--color-text-info);"></i>
Academic Performance & Stats
</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px;">
<div style="background: rgba(255, 255, 255, 0.02); border: 1px solid var(--color-border-secondary); border-radius: 12px; padding: 24px 20px;">
<div style="font-size: 13px; color: var(--color-text-secondary); margin-bottom: 8px;">Completed Tasks</div>
<div id="desktop-profile-completed" style="font-size: 32px; font-weight: 700; color: var(--color-text-success);">0</div>
</div>
<div style="background: rgba(255, 255, 255, 0.02); border: 1px solid var(--color-border-secondary); border-radius: 12px; padding: 24px 20px;">
<div style="font-size: 13px; color: var(--color-text-secondary); margin-bottom: 8px;">Pending Tasks</div>
<div id="desktop-profile-pending" style="font-size: 32px; font-weight: 700; color: var(--color-text-warning);">0</div>
</div>
<div style="background: rgba(255, 255, 255, 0.02); border: 1px solid var(--color-border-secondary); border-radius: 12px; padding: 24px 20px;">
<div style="font-size: 13px; color: var(--color-text-secondary); margin-bottom: 8px;">Estimated Study Time</div>
<div id="desktop-profile-duration" style="font-size: 24px; font-weight: 700; color: var(--color-text-info); margin-top: 8px;">0 mins</div>
</div>
</div>
</div>

<!-- Subject-wise Task Breakdown -->
<div>
<h3 style="font-size: 16px; font-weight: 600; margin: 0 0 16px; display: flex; align-items: center; gap: 8px;">
<i class="fas fa-book-open" style="color: var(--color-text-purple);"></i>
Subject Workload Breakdown
</h3>
<div id="desktop-profile-subjects-list" style="display: flex; flex-direction: column; gap: 12px;">
<!-- Dynamically populated subject stats -->
</div>
</div>
</div>
</div>
</div>
</div>

<!-- Right Panel -->
Expand Down Expand Up @@ -382,8 +438,9 @@ <h3 style="font-size:12px; font-weight:700; text-transform:uppercase; color:var(
return;
}

localStorage.setItem('studyplan_user', JSON.stringify({ email: data.email }));
localStorage.setItem('studyplan_user', JSON.stringify({ email: data.email || email }));
document.getElementById('auth-modal').style.display = 'none';
window.location.reload();

} catch (err) {
errorEl.textContent = 'Network error. Please try again.';
Expand All @@ -392,8 +449,18 @@ <h3 style="font-size:12px; font-weight:700; text-transform:uppercase; color:var(
});

// Check if already logged in
if (localStorage.getItem('studyplan_user')) {
document.getElementById('auth-modal').style.display = 'none';
const loggedInUser = localStorage.getItem('studyplan_user');
if (loggedInUser) {
try {
const parsed = JSON.parse(loggedInUser);
if (parsed && parsed.email) {
document.getElementById('auth-modal').style.display = 'none';
} else {
localStorage.removeItem('studyplan_user');
}
} catch (e) {
localStorage.removeItem('studyplan_user');
}
}

// Logout Button Functionality
Expand Down
131 changes: 131 additions & 0 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,100 @@ store.subscribe(renderCalendar);
store.subscribe(renderFocusTasks);
store.subscribe(renderSidebarSubjects);

function updateDesktopProfilePage() {
const userStr = localStorage.getItem('studyplan_user');
let email = 'guest@example.com';
if (userStr) {
try {
const user = JSON.parse(userStr);
email = user.email || email;
} catch (e) {
console.error(e);
}
}

const avatarEl = document.getElementById('desktop-profile-avatar');
const emailEl = document.getElementById('desktop-profile-email');
if (emailEl) emailEl.textContent = email;
if (avatarEl && email) {
avatarEl.textContent = email.charAt(0).toUpperCase();
}

// Theme
const themeEl = document.getElementById('desktop-profile-theme');
if (themeEl) {
const isDarkMode = localStorage.getItem('studyplan_dark_mode') === 'true';
themeEl.textContent = isDarkMode ? 'Dark Mode' : 'Light Mode';
}

// Stats
const completedCount = store.tasks.filter(t => t.status === 'Done').length;
const pendingCount = store.tasks.filter(t => t.status !== 'Done' && !t.archived).length;
const totalMins = store.tasks.reduce((acc, t) => acc + (Number(t.estimated_duration) || 0), 0);

const completedEl = document.getElementById('desktop-profile-completed');
const pendingEl = document.getElementById('desktop-profile-pending');
const durationEl = document.getElementById('desktop-profile-duration');

if (completedEl) completedEl.textContent = completedCount;
if (pendingEl) pendingEl.textContent = pendingCount;
if (durationEl) durationEl.textContent = formatDuration(totalMins);

// Subject-wise breakdown
const subjectsListEl = document.getElementById('desktop-profile-subjects-list');
if (subjectsListEl) {
const subjects = store.subjects;
const tasks = store.tasks;

if (subjects.length === 0) {
subjectsListEl.innerHTML = '<div style="color: var(--color-text-secondary); font-size: 13px;">No subjects defined yet.</div>';
return;
}

const html = subjects.map(sub => {
const subTasks = tasks.filter(t => t.subject_id === sub.id && !t.archived);
const subCompleted = subTasks.filter(t => t.status === 'Done').length;
const subTotal = subTasks.length;
const percent = subTotal > 0 ? Math.round((subCompleted / subTotal) * 100) : 0;

return `
<div style="background: rgba(255, 255, 255, 0.01); border: 1px solid var(--color-border-secondary); border-radius: 8px; padding: 14px 16px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<div style="display: flex; align-items: center; gap: 8px;">
<span style="width: 10px; height: 10px; border-radius: 50%; background: ${sub.color || 'var(--color-text-info)'};"></span>
<span style="font-size: 14px; font-weight: 600;">${sub.name}</span>
</div>
<span style="font-size: 12px; color: var(--color-text-secondary); font-weight: 500;">
${subCompleted}/${subTotal} completed (${percent}%)
</span>
</div>
<div style="height: 6px; background: rgba(255, 255, 255, 0.05); border-radius: 3px; overflow: hidden;">
<div style="height: 100%; width: ${percent}%; background: ${sub.color || 'var(--color-text-info)'}; border-radius: 3px;"></div>
</div>
</div>
`;
}).join('');

subjectsListEl.innerHTML = html;
}
}

store.subscribe(updateDesktopProfilePage);

function hideProfileSection() {
const profileSection = document.getElementById('profile-section');
if (profileSection) profileSection.classList.add('hidden');

const topbar = document.querySelector('.topbar');
if (topbar) topbar.style.display = '';

const greeting = document.querySelector('.dashboard-greeting');
if (greeting) greeting.style.display = '';

const studyTime = document.getElementById('daily-study-time');
if (studyTime) studyTime.style.display = '';
}

document.addEventListener('DOMContentLoaded', () => {
if (newSubjectColorsEl) {
SUBJECT_COLORS.forEach(c => {
Expand Down Expand Up @@ -1166,6 +1260,7 @@ document.addEventListener('DOMContentLoaded', () => {

calendarBtn.addEventListener('click', () => {
currentView = 'calendar';
hideProfileSection();
document.querySelector('.cal-section').classList.remove('hidden');
document.getElementById('tasks-section').classList.remove('hidden');
document.getElementById('focus-section').classList.add('hidden');
Expand All @@ -1175,6 +1270,7 @@ document.addEventListener('DOMContentLoaded', () => {

allTasksBtn.addEventListener('click', () => {
currentView = 'all-tasks';
hideProfileSection();
document.querySelector('.cal-section').classList.add('hidden');
document.getElementById('tasks-section').classList.remove('hidden');
document.getElementById('focus-section').classList.add('hidden');
Expand All @@ -1184,6 +1280,7 @@ document.addEventListener('DOMContentLoaded', () => {

archivedTasksBtn.addEventListener('click', () => {
currentView = 'archived';
hideProfileSection();
document.querySelector('.cal-section').classList.add('hidden');
document.getElementById('tasks-section').classList.remove('hidden');
document.getElementById('focus-section').classList.add('hidden');
Expand All @@ -1194,6 +1291,7 @@ document.addEventListener('DOMContentLoaded', () => {
if(focusModeBtn) {
focusModeBtn.addEventListener('click', () => {
currentView = 'focus';
hideProfileSection();
document.querySelector('.cal-section').classList.add('hidden');
document.getElementById('tasks-section').classList.add('hidden');
document.getElementById('focus-section').classList.remove('hidden');
Expand Down Expand Up @@ -1317,6 +1415,39 @@ addItemsBtn.addEventListener('click', () => {
pasteInput.value = '';
}
});

// Profile Section Logic
const profileSection = document.getElementById('profile-section');
const profileBtn = document.getElementById('profile-btn');

if (profileBtn && profileSection) {
profileBtn.addEventListener('click', (e) => {
e.preventDefault();
currentView = 'profile';

// Hide other views
document.querySelector('.cal-section')?.classList.add('hidden');
document.getElementById('tasks-section')?.classList.add('hidden');
document.getElementById('focus-section')?.classList.add('hidden');

const topbar = document.querySelector('.topbar');
if (topbar) topbar.style.setProperty('display', 'none', 'important');

const greeting = document.querySelector('.dashboard-greeting');
if (greeting) greeting.style.setProperty('display', 'none', 'important');

const studyTime = document.getElementById('daily-study-time');
if (studyTime) studyTime.style.setProperty('display', 'none', 'important');

// Show profile section
profileSection.classList.remove('hidden');

// Update sidebar active status to none
document.querySelectorAll('.sidebar .nav-item').forEach(el => el.classList.remove('active'));

updateDesktopProfilePage();
});
}
});

// Ensures the button is hidden on initial page load if the textarea is empty
Expand Down
2 changes: 1 addition & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ app.post('/api/auth/signup', (req, res) => {
return res.status(400).json({ error: 'User already exists' });
}
users[email] = { email, password };
res.json({ success: true, message: 'Account created successfully' });
res.json({ success: true, message: 'Account created successfully', email });
});

app.post('/api/auth/login', (req, res) => {
Expand Down