diff --git a/src/index.js b/src/index.js index 1f8d7ad..7c35b17 100644 --- a/src/index.js +++ b/src/index.js @@ -8,7 +8,8 @@ import { } from './templates.js'; import { pointsPage, timelinePage, documentsPage, feesPage, - occupationsPage, stateCriteriaPage, processingTimesPage, englishPage, studentFundPage + occupationsPage, stateCriteriaPage, processingTimesPage, englishPage, studentFundPage, + dashboardOverview } from './visa-tracker.js'; const app = new Hono(); @@ -111,10 +112,28 @@ app.get('/courses', async c => { app.get('/dashboard', async c => { const user = c.get('user'); if (!user) return c.redirect('/login?redirect=/dashboard'); - const { results } = await c.env.DB.prepare( - 'SELECT * FROM inquiries WHERE user_id = ? ORDER BY created_at DESC LIMIT 20' - ).bind(user.id).all(); - return c.html(dashboardPage(user, results)); + const [inquiriesRes, profileRes, docsRes, timelineRes] = await Promise.all([ + c.env.DB.prepare('SELECT * FROM inquiries WHERE user_id=? ORDER BY created_at DESC LIMIT 10').bind(user.id).all(), + c.env.DB.prepare('SELECT * FROM visa_profiles WHERE user_id=?').bind(user.id).first(), + c.env.DB.prepare('SELECT * FROM document_expiries WHERE user_id=? ORDER BY expiry_date ASC LIMIT 5').bind(user.id).all(), + c.env.DB.prepare('SELECT * FROM case_timelines WHERE user_id=?').bind(user.id).all(), + ]); + const { calcPoints } = await import('./visa-data.js'); + const points = profileRes ? calcPoints(profileRes) : null; + const completedStages = (timelineRes.results||[]).filter(s => s.milestone_date).length; + const today = new Date(); + const expiringDocs = (docsRes.results||[]).filter(d => { + const days = Math.round((new Date(d.expiry_date) - today) / 86400000); + return days <= 180; + }); + return c.html(layout('Dashboard', dashboardOverview(user, { + inquiries: inquiriesRes.results||[], + profile: profileRes, + points, + completedStages, + totalStages: 7, + expiringDocs, + }), user)); }); app.get('/dashboard/save', async c => { diff --git a/src/visa-tracker.js b/src/visa-tracker.js index 243fb8e..f57220c 100644 --- a/src/visa-tracker.js +++ b/src/visa-tracker.js @@ -615,3 +615,120 @@ export function studentFundPage(user) { return dashWrap(user, 'student-fund', body); } + +// ── DASHBOARD OVERVIEW (replaces old dashboardPage) ────────────────────────── +export function dashboardOverview(user, { inquiries, profile, points, completedStages, totalStages, expiringDocs }) { + const today = new Date(); + + const quickStats = [ + { + label: 'Migration Points', + value: points ? `${points.total} pts` : '—', + sub: points ? (points.total >= 90 ? 'Competitive' : points.total >= 65 ? 'Getting there' : 'Below threshold') : 'Not calculated', + color: points ? (points.total >= 90 ? '#16a34a' : points.total >= 65 ? '#d97706' : '#dc2626') : '#94a3b8', + href: '/dashboard/points', + icon: '🔢', + }, + { + label: 'Visa Timeline', + value: `${completedStages} / ${totalStages}`, + sub: completedStages === totalStages ? '🎉 Visa granted!' : completedStages === 0 ? 'Not started' : 'In progress', + color: '#1a5bb8', + href: '/dashboard/timeline', + icon: '📅', + }, + { + label: 'Expiring Documents', + value: expiringDocs.length > 0 ? expiringDocs.length : '✓', + sub: expiringDocs.length > 0 ? 'Need attention' : 'All clear', + color: expiringDocs.length > 0 ? '#dc2626' : '#16a34a', + href: '/dashboard/documents', + icon: '📄', + }, + { + label: 'Inquiries', + value: inquiries.length, + sub: 'Total submitted', + color: '#1a5bb8', + href: '/contact', + icon: '📝', + }, + ]; + + const tools = [ + { href: '/dashboard/points', icon: '🔢', label: 'Points Calculator', desc: 'Calculate your skilled migration points score' }, + { href: '/dashboard/timeline', icon: '📅', label: 'Visa Timeline', desc: 'Track your case from skills assessment to grant' }, + { href: '/dashboard/documents', icon: '📄', label: 'Document Expiry', desc: 'Passport, visa, English test, skills assessment' }, + { href: '/dashboard/fees', icon: '💰', label: 'VAC Fee Calculator', desc: 'Estimate your Visa Application Charge' }, + { href: '/dashboard/occupations', icon: '🔍', label: 'Occupation Search', desc: 'MLTSSL/STSOL list with visa eligibility' }, + { href: '/dashboard/state-criteria', icon: '🗺️', label: 'State Criteria', desc: 'SC 190 & 491 min points by state' }, + { href: '/dashboard/processing-times', icon: '⏱️', label: 'Processing Times', desc: 'P25/P50/P75/P90 percentile estimates' }, + { href: '/dashboard/english', icon: '🗣️', label: 'English Requirements', desc: 'IELTS/PTE/TOEFL/OET by visa subclass' }, + { href: '/dashboard/student-fund', icon: '🎓', label: 'Student Fund Calc', desc: 'Minimum savings for student visa' }, + { href: '/courses', icon: '🔎', label: 'CRICOS Course Search', desc: 'Search 26K+ registered courses' }, + { href: '/contact', icon: '📞', label: 'Book Consultation', desc: 'Talk to a Careers Gateway expert' }, + { href: '/health-insurance', icon: '🏥', label: 'Health Insurance', desc: 'Compare OSHC & OVHC policies' }, + ]; + + const body = ` +