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
13 changes: 13 additions & 0 deletions css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -4161,6 +4161,19 @@ body {
.tasks-section { flex: 1; overflow-y: auto; padding: 0 24px 24px; scroll-behavior: smooth; }
.tasks-section::-webkit-scrollbar { width: 6px; }
.tasks-section::-webkit-scrollbar-thumb { background: var(--color-border-secondary); border-radius: 10px; }
.profile-section { flex: 1; overflow-y: auto; padding: 24px; display: flex; flex-direction: column; gap: 24px; }
.profile-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; }
.profile-page-title { font-size: 24px; font-weight: 700; color: var(--color-text-primary); }
.profile-page-subtitle { margin: 8px 0 0; color: var(--color-text-secondary); max-width: 640px; line-height: 1.6; }
.profile-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.profile-card { background: var(--color-background-primary); border: 1px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 24px; box-shadow: var(--shadow-sm); }
.profile-card h2 { margin: 0 0 16px; font-size: 16px; font-weight: 700; color: var(--color-text-primary); }
.profile-field { display: flex; justify-content: space-between; gap: 16px; margin-bottom: 14px; font-size: 14px; color: var(--color-text-secondary); }
.profile-field-label { color: var(--color-text-tertiary); font-weight: 600; }
.profile-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.profile-stat-value { display: block; font-size: 22px; font-weight: 700; color: var(--color-text-primary); margin-bottom: 4px; }
.profile-summary-card p { margin: 0; color: var(--color-text-secondary); line-height: 1.8; }
@media (max-width: 900px) { .profile-grid { grid-template-columns: 1fr; } }
.tasks-actions-bar {
margin-top: 18px;
display: flex;
Expand Down
64 changes: 63 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Automatically organize tasks and study plans using AI">
<title>StudyPlan</title>
<meta property="og:title" content="StudyPlan — AI-Powered Study Planner">
<meta property="og:description" content="Automatically organize tasks and study plans using AI">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="StudyPlan — AI-Powered Study Planner">
<meta name="twitter:description" content="Automatically organize tasks and study plans using AI">
<link rel="stylesheet" href="/css/index.css">

<script src="/js/lib/confetti.browser.min.js"></script>
Expand Down Expand Up @@ -62,7 +69,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 +214,61 @@ <h1 class="site-title">StudyPlan</h1>
</div>
</div>
</div>

<div id="profile-section" class="profile-section hidden">
<div class="profile-header">
<div>
<div class="profile-page-title">Profile</div>
<p class="profile-page-subtitle">View your account summary, study stats, and future account settings in one place.</p>
</div>
</div>

<div class="profile-grid">
<section class="profile-card">
<h2>Account details</h2>
<div class="profile-field">
<span class="profile-field-label">Username</span>
<span id="profile-username">StudyPlan User</span>
</div>
<div class="profile-field">
<span class="profile-field-label">Email</span>
<span id="profile-email">user@studyplan.app</span>
</div>
<div class="profile-field">
<span class="profile-field-label">Member since</span>
<span id="profile-joined">June 2026</span>
</div>
</section>

<section class="profile-card">
<h2>Study statistics</h2>
<div class="profile-stats">
<div>
<span class="profile-stat-value" id="profile-completed-count">0</span>
<span>Completed</span>
</div>
<div>
<span class="profile-stat-value" id="profile-pending-count">0</span>
<span>Pending</span>
</div>
<div>
<span class="profile-stat-value" id="profile-archived-count">0</span>
<span>Archived</span>
</div>
<div>
<span class="profile-stat-value" id="profile-subjects-count">0</span>
<span>Subjects</span>
</div>
</div>
</section>
</div>

<section class="profile-card profile-summary-card">
<h2>Account overview</h2>
<p id="profile-summary-text">Your profile information and study statistics will update automatically as you use StudyPlan.</p>
</section>
</div>

</div>

<!-- Right Panel -->
Expand Down
98 changes: 98 additions & 0 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,89 @@ function renderFocusTasks() {
}
}

function renderProfileSection() {
if (!profileSection) return;

const tasks = store.tasks || [];
const subjects = store.subjects || [];
const completedCount = tasks.filter(t => t.status === 'Done').length;
const pendingCount = tasks.filter(t => t.status !== 'Done' && !t.archived).length;
const archivedCount = tasks.filter(t => t.archived).length;
const subjectsCount = subjects.length;
const username = localStorage.getItem('studyplan_username') || 'StudyPlan User';
const email = localStorage.getItem('studyplan_email') || 'user@studyplan.app';
const joinedDate = localStorage.getItem('studyplan_joined') || 'June 2026';

profileSection.innerHTML = `
<div class="profile-header">
<div>
<div class="profile-page-title">Profile</div>
<p class="profile-page-subtitle">View your account summary, study stats, and future account settings in one place.</p>
</div>
</div>

<div class="profile-grid">
<section class="profile-card">
<h2>Account details</h2>
<div class="profile-field">
<span class="profile-field-label">Username</span>
<span>${escapeHtml(username)}</span>
</div>
<div class="profile-field">
<span class="profile-field-label">Email</span>
<span>${escapeHtml(email)}</span>
</div>
<div class="profile-field">
<span class="profile-field-label">Member since</span>
<span>${escapeHtml(joinedDate)}</span>
</div>
</section>

<section class="profile-card">
<h2>Study statistics</h2>
<div class="profile-stats">
<div>
<span class="profile-stat-value">${completedCount}</span>
<span>Completed</span>
</div>
<div>
<span class="profile-stat-value">${pendingCount}</span>
<span>Pending</span>
</div>
<div>
<span class="profile-stat-value">${archivedCount}</span>
<span>Archived</span>
</div>
<div>
<span class="profile-stat-value">${subjectsCount}</span>
<span>Subjects</span>
</div>
</div>
</section>
</div>

<section class="profile-card profile-summary-card">
<h2>Account overview</h2>
<p>Your profile information and study statistics will update automatically as you use StudyPlan.</p>
</section>
`;
}

function showProfileSection() {
currentView = 'profile';
document.querySelector('.cal-section')?.classList.add('hidden');
document.getElementById('tasks-section')?.classList.add('hidden');
document.getElementById('focus-section')?.classList.add('hidden');
profileSection?.classList.remove('hidden');
topbar?.classList.add('hidden');
renderProfileSection();
}

function hideProfileSection() {
profileSection?.classList.add('hidden');
topbar?.classList.remove('hidden');
}

function formatDate(dateStr) {
if (!dateStr) return 'No Date';
const d = new Date(dateStr);
Expand Down Expand Up @@ -1219,6 +1302,7 @@ store.subscribe(renderTasks);
store.subscribe(renderExtraction);
store.subscribe(renderCalendar);
store.subscribe(renderFocusTasks);
store.subscribe(renderProfileSection);
store.subscribe(renderSidebarSubjects);

document.addEventListener('DOMContentLoaded', () => {
Expand Down Expand Up @@ -1291,6 +1375,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 @@ -1300,6 +1385,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 @@ -1309,6 +1395,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 @@ -1319,6 +1406,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 All @@ -1327,6 +1415,16 @@ document.addEventListener('DOMContentLoaded', () => {
});
}

<if (profileBtn) {
profileBtn.addEventListener('click', () => {
showProfileSection();
});
}

document.getElementById('cal-prev').addEventListener('click', () => {
currentMonthDate.setMonth(currentMonthDate.getMonth() - 1);
renderCalendar();
});
document.getElementById('cal-next').addEventListener('click', () => {
currentMonthDate.setMonth(currentMonthDate.getMonth() + 1);
renderCalendar();
Expand Down