From 5580b713c372caef608b5baf26dda17b001504a4 Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 21:42:39 +0800 Subject: [PATCH 01/12] refactor: use CSS variables in `dashboard` --- apps/web/app/dashboard/page.tsx | 245 ++++++++++++++++---------------- 1 file changed, 122 insertions(+), 123 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 3d3134e..4873493 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -5,116 +5,116 @@ import { signOut } from "@/lib/auth-client"; import { trpc } from "@/lib/trpc"; export default function Dashboard() { - const router = useRouter(); - const { data } = trpc.user.getCurrent.useQuery(); + const router = useRouter(); + const { data } = trpc.user.getCurrent.useQuery(); - const goToMap = () => router.push("/"); - const goToAdmin = () => router.push("/admin"); + const goToMap = () => router.push("/"); + const goToAdmin = () => router.push("/admin"); - const handleSignOut = async () => { - await signOut(); - router.refresh(); - }; + const handleSignOut = async () => { + await signOut(); + router.refresh(); + }; - return ( -
-
+ return ( +
+
-
- {/* HEADER SECTION */} -
-
- - - - -
+
+ {/* HEADER SECTION */} +
+
+ + + + +
-

- Welcome, {data?.name ? data.name.toUpperCase() : "OPERATOR"}! -

-

You made it to the protected area. 🎉

-
+

+ Welcome, {data?.name ? data.name.toUpperCase() : "UNKNOWN"}! +

+

You made it to the protected area. 🎉

+
- {/* ACTIONS PORTAL */} -
- {/* Primary Action: Go to Map */} - + {/* ACTIONS PORTAL */} +
+ {/* Primary Action: Go to Map */} + - {/* Secondary Action: Admin */} - -
+ {/* Secondary Action: Admin */} + +
- {/* FOOTER & SIGN OUT */} -
- -
-
+ {/* FOOTER & SIGN OUT */} +
+ +
+
- -
- ); -} +
+ ); +} \ No newline at end of file From fe954ae2903bfb3ffbfe3b022b9067588df2ae57 Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 21:54:19 +0800 Subject: [PATCH 02/12] feat: redo user dashboard layout --- apps/web/app/dashboard/page.tsx | 445 ++++++++++++++++++-------------- 1 file changed, 252 insertions(+), 193 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 4873493..89e433b 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -1,270 +1,329 @@ "use client"; +import { useState } from "react"; import { useRouter } from "next/navigation"; import { signOut } from "@/lib/auth-client"; import { trpc } from "@/lib/trpc"; export default function Dashboard() { const router = useRouter(); - const { data } = trpc.user.getCurrent.useQuery(); + const { data, isLoading } = trpc.user.getCurrent.useQuery(); + const [isSidebarOpen, setIsSidebarOpen] = useState(false); const goToMap = () => router.push("/"); - const goToAdmin = () => router.push("/admin"); - + const handleSignOut = async () => { await signOut(); router.refresh(); }; return ( -
-
- -
- {/* HEADER SECTION */} -
-
- - - - -
+
+ {/* --- MOBILE OVERLAY --- */} + {isSidebarOpen && ( +
setIsSidebarOpen(false)} + /> + )} -

- Welcome, {data?.name ? data.name.toUpperCase() : "UNKNOWN"}! -

-

You made it to the protected area. 🎉

+ {/* --- SIDEBAR --- */} + - {/* Secondary Action: Admin */} - -
+ + + + + + +

User Dashboard

+
+ - {/* FOOTER & SIGN OUT */} -
- -
+ {/* --- MAIN --- */} +
+
+
+

+ {isLoading ? "LOADING..." : `Welcome, ${data?.name ? data.name.toUpperCase() : "UNKNOWN"}!`} +

+

You made it!

+
+ +
+

Data will be displayed here.

+
+
+
-
+ ); } \ No newline at end of file From 4a1c067dd8923f7fbfb8b53fa2fd7e71e47fb6b5 Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 22:18:01 +0800 Subject: [PATCH 03/12] feat: create mock user statistics --- apps/web/app/dashboard/page.tsx | 177 +++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 2 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 89e433b..40b319a 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import { useRouter } from "next/navigation"; import { signOut } from "@/lib/auth-client"; import { trpc } from "@/lib/trpc"; +import { PIN_CATEGORIES } from "@/data/pin-categories"; export default function Dashboard() { const router = useRouter(); @@ -17,6 +18,23 @@ export default function Dashboard() { router.refresh(); }; + const mockStats = { + totalPins: 42, + verifiedPins: 38, + pendingPins: 3, + rejectedPins: 1, + comments: 128, + categoryBreakdown: { + academic: 12, + food: 15, + social: 5, + transit: 8, + utility: 2, + } + }; + + const verificationRate = Math.round((mockStats.verifiedPins / mockStats.totalPins) * 100) || 0; + return (
{/* --- MOBILE OVERLAY --- */} @@ -76,8 +94,63 @@ export default function Dashboard() {

You made it!

-
-

Data will be displayed here.

+ {/* --- DASHBOARD GRID --- */} +
+ +
+
+

USER PROFILE

+ ONLINE +
+
+
+
+
+
+
+
+
+ +
+
+

PIN STATISTICS

+
+
+
+
+
+
+
+
+
+
+ +
+
+

PENDING PINS

+ 3 +
+
+
+
+
+
+
+
+
+ +
+
+

RECENT PINS

+
+
+
+
+
+
+
+
+
@@ -272,6 +345,102 @@ export default function Dashboard() { margin: 0; } + /* --- DASHBOARD GRID & CARDS --- */ + .dashboard-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 24px; + } + + .module-card { + background: var(--bg-panel); + border: 1px solid var(--border-color); + border-radius: 16px; + padding: 24px; + display: flex; + flex-direction: column; + gap: 20px; + transition: transform 0.2s ease, box-shadow 0.2s ease; + } + + /* Card Headers */ + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid var(--border-color); + padding-bottom: 12px; + } + + .card-header h3 { + font-family: var(--font-chakra); + font-size: 14px; + font-weight: 800; + color: var(--text-secondary); + letter-spacing: 0.15em; + margin: 0; + } + + /* Badges */ + .status-badge { + background: color-mix(in srgb, var(--neon-green) 15%, transparent); + color: var(--neon-green); + border: 1px solid var(--neon-green); + padding: 4px 8px; + border-radius: 4px; + font-family: var(--font-chakra); + font-size: 10px; + font-weight: 700; + letter-spacing: 0.1em; + } + + .count-badge { + background: color-mix(in srgb, var(--neon-yellow, #FFD700) 15%, transparent); + color: var(--neon-yellow, #FFD700); + border: 1px solid var(--neon-yellow, #FFD700); + padding: 2px 8px; + border-radius: 12px; + font-family: var(--font-nunito); + font-weight: 800; + font-size: 12px; + } + + .card-body { + flex: 1; + display: flex; + flex-direction: column; + } + + .dummy-avatar { + width: 64px; height: 64px; + border-radius: 50%; + background: var(--bg-panel-hover); + margin-bottom: 16px; + } + + .dummy-lines { display: flex; flex-direction: column; gap: 8px; } + .line { height: 12px; background: var(--bg-panel-hover); border-radius: 4px; } + .line.short { width: 40%; } + .line.long { width: 80%; } + + .dummy-stats { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + } + .stat-box { + height: 60px; + background: var(--bg-panel-hover); + border-radius: 8px; + } + + .dummy-list { display: flex; flex-direction: column; gap: 12px; } + .list-item { + height: 48px; + background: var(--bg-panel-hover); + border-radius: 8px; + } + .placeholder-content { height: 300px; border: 1px dashed var(--border-color); @@ -319,6 +488,10 @@ export default function Dashboard() { padding: 0 16px; } + .dashboard-grid { + grid-template-columns: 1fr; + } + .content-area { padding: 24px 16px; } From aa36922a67c44889605f68ca6f161c2776cd753c Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 22:30:51 +0800 Subject: [PATCH 04/12] feat: fill user statistics card --- apps/web/app/dashboard/page.tsx | 201 ++++++++++++++++++++++++++++++-- 1 file changed, 193 insertions(+), 8 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 40b319a..a666b0d 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -32,7 +32,7 @@ export default function Dashboard() { utility: 2, } }; - + const verificationRate = Math.round((mockStats.verifiedPins / mockStats.totalPins) * 100) || 0; return ( @@ -113,14 +113,69 @@ export default function Dashboard() {
-

PIN STATISTICS

+

USER STATISTICS

+ + SYNCED +
-
-
-
-
-
-
+ +
+ {/* Top Stats Grid */} +
+
+ TOTAL PINS ADDED + {mockStats.totalPins} +
+
+ TOTAL COMMENTS + {mockStats.comments} +
+
+ + {/* Verification Integrity Bar */} +
+
+ VERIFICATIONS + {verificationRate}% +
+
+
+
+
+ {mockStats.verifiedPins} VERIFIED + {mockStats.pendingPins} PENDING + {mockStats.rejectedPins} REJECTED +
+
+ + {/* Category Distribution */} +
+ CATEGORY DISTRIBUTION +
+ {PIN_CATEGORIES.map((category) => { + const count = mockStats.categoryBreakdown[category.id as keyof typeof mockStats.categoryBreakdown] || 0; + const percentage = mockStats.totalPins > 0 ? (count / mockStats.totalPins) * 100 : 0; + + return ( +
+
+ {category.label} + {count} +
+
+
+
+
+ ); + })} +
@@ -452,6 +507,136 @@ export default function Dashboard() { font-family: var(--font-chakra); } + /* --- TELEMETRY MODULE STYLES --- */ + .telemetry-body { + gap: 24px; + } + + .stat-label { + font-family: var(--font-chakra); + font-size: 10px; + font-weight: 800; + color: var(--text-secondary); + letter-spacing: 0.15em; + } + + .telemetry-top-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + } + + .stat-block { + background: var(--bg-panel-hover); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 16px; + display: flex; + flex-direction: column; + gap: 4px; + } + + .stat-value { + font-family: var(--font-cubao-wide); + font-size: 32px; + color: var(--text-primary); + letter-spacing: 0.05em; + } + + /* Verification Integrity */ + .integrity-section { + display: flex; + flex-direction: column; + gap: 8px; + } + + .integrity-header { + display: flex; + justify-content: space-between; + align-items: flex-end; + } + + .integrity-percent { + font-family: var(--font-chakra); + font-size: 14px; + font-weight: 800; + color: var(--neon-green); + } + + .progress-track { + height: 6px; + background: var(--bg-panel-hover); + border-radius: 3px; + overflow: hidden; + } + + .progress-fill { + height: 100%; + background: var(--neon-green); + box-shadow: 0 0 10px color-mix(in srgb, var(--neon-green) 50%, transparent); + border-radius: 3px; + transition: width 1s cubic-bezier(0.175, 0.885, 0.32, 1.275); + } + + .integrity-details { + display: flex; + gap: 12px; + font-family: var(--font-chakra); + font-size: 10px; + font-weight: 700; + letter-spacing: 0.05em; + } + + .detail-item.verified { color: var(--neon-green); } + .detail-item.pending { color: var(--neon-yellow, #FFD700); } + .detail-item.rejected { color: #ff4d4d; } + + /* Category Distribution */ + .distribution-section { + display: flex; + flex-direction: column; + gap: 12px; + } + + .category-list { + display: flex; + flex-direction: column; + gap: 10px; + } + + .category-row { + display: flex; + flex-direction: column; + gap: 4px; + } + + .cat-info { + display: flex; + justify-content: space-between; + font-family: var(--font-chakra); + font-size: 11px; + font-weight: 700; + letter-spacing: 0.1em; + } + + .cat-count { + color: var(--text-primary); + font-family: var(--font-nunito); + } + + .cat-track { + height: 4px; + background: var(--bg-panel-hover); + border-radius: 2px; + overflow: hidden; + } + + .cat-fill { + height: 100%; + border-radius: 2px; + transition: width 1s cubic-bezier(0.175, 0.885, 0.32, 1.275); + } + /* Custom Scrollbar */ .custom-vertical-scrollbar::-webkit-scrollbar { width: 8px; } .custom-vertical-scrollbar::-webkit-scrollbar-track { background: transparent; } From a3d1beb38536070a04075095ad43fd8fa47ecc8a Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 22:46:48 +0800 Subject: [PATCH 05/12] feat: create mock pending pins --- apps/web/app/dashboard/page.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index a666b0d..0af9c26 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -30,7 +30,12 @@ export default function Dashboard() { social: 5, transit: 8, utility: 2, - } + }, + pendingList: [ + { id: "p1", title: "Quezon Hall", lat: 14.6549, lng: 121.0645, type: "academic" }, + { id: "p2", title: "Area 2", lat: 14.6532, lng: 121.0681, type: "food" }, + { id: "p3", title: "Sunken Garden", lat: 14.6544, lng: 121.0673, type: "social" }, + ] }; const verificationRate = Math.round((mockStats.verifiedPins / mockStats.totalPins) * 100) || 0; @@ -369,6 +374,7 @@ export default function Dashboard() { flex: 1; padding: 32px; background-color: var(--bg-base); + overflow-y: auto; } .content-container { From b2409e165f114a2db0811554f193e9b99576fd75 Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 22:54:51 +0800 Subject: [PATCH 06/12] feat: fill pending pins card --- apps/web/app/dashboard/page.tsx | 141 ++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 6 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 0af9c26..bf02882 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { useRouter } from "next/navigation"; import { signOut } from "@/lib/auth-client"; import { trpc } from "@/lib/trpc"; -import { PIN_CATEGORIES } from "@/data/pin-categories"; +import { PIN_CATEGORIES, getPinColor } from "@/data/pin-categories"; export default function Dashboard() { const router = useRouter(); @@ -188,13 +188,46 @@ export default function Dashboard() {

PENDING PINS

- 3 + {mockStats.pendingList.length}
-
-
-
-
+
+ {mockStats.pendingList.map((pin) => { + const color = getPinColor(pin.type); + return ( +
+
+
+ {pin.title.charAt(0).toUpperCase()} +
+ +
+ {pin.title} + + {pin.lat.toFixed(4)}, {pin.lng.toFixed(4)} + +
+
+ + +
+ ); + })}
@@ -549,6 +582,102 @@ export default function Dashboard() { letter-spacing: 0.05em; } + /* --- PIN LIST STYLES --- */ + .pin-list { + display: flex; + flex-direction: column; + gap: 12px; + } + + .pin-list-item { + display: flex; + align-items: center; + justify-content: space-between; + background: var(--bg-panel-hover); + border: 1px solid var(--border-color); + border-radius: 12px; + padding: 12px 16px; + transition: all 0.2s ease; + } + + .pin-list-item:hover { + border-color: color-mix(in srgb, var(--text-secondary) 50%, transparent); + background: color-mix(in srgb, var(--bg-panel-hover) 80%, var(--border-color)); + } + + .pin-info-group { + display: flex; + align-items: center; + gap: 16px; + } + + .list-diamond { + width: 32px; + height: 32px; + transform: rotate(45deg); + border: 1.5px solid; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); + } + + .list-diamond span { + transform: rotate(-45deg); + font-family: var(--font-cubao-wide); + font-size: 14px; + } + + /* Text Block */ + .pin-text { + display: flex; + flex-direction: column; + gap: 4px; + } + + .pin-title { + font-family: var(--font-chakra); + font-size: 14px; + font-weight: 700; + color: var(--text-primary); + letter-spacing: 0.05em; + } + + .pin-coords { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; + font-size: 11px; + color: var(--text-secondary); + letter-spacing: 0.05em; + } + + /* Locate Button */ + .locate-btn { + background: transparent; + border: 1px solid var(--border-color); + border-radius: 8px; + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + color: var(--text-secondary); + cursor: pointer; + transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); + flex-shrink: 0; + } + + .locate-btn:hover { + background: color-mix(in srgb, var(--neon-blue) 15%, transparent); + border-color: var(--neon-blue); + color: var(--neon-blue); + transform: scale(1.05); + } + + .locate-btn:active { + transform: scale(0.95); + } + /* Verification Integrity */ .integrity-section { display: flex; From f3cee7b5bbd5909db22fef2d805c7f7531f0010a Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 23:06:55 +0800 Subject: [PATCH 07/12] feat: create mock recent pins --- apps/web/app/dashboard/page.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index bf02882..19db395 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -35,6 +35,10 @@ export default function Dashboard() { { id: "p1", title: "Quezon Hall", lat: 14.6549, lng: 121.0645, type: "academic" }, { id: "p2", title: "Area 2", lat: 14.6532, lng: 121.0681, type: "food" }, { id: "p3", title: "Sunken Garden", lat: 14.6544, lng: 121.0673, type: "social" }, + ], + recentList: [ + { id: "r1", title: "CS Library", lat: 14.6538, lng: 121.0694, type: "academic" }, + { id: "r2", title: "TOKI Jeepney Stop", lat: 14.6551, lng: 121.0621, type: "transit" }, ] }; @@ -610,7 +614,7 @@ export default function Dashboard() { align-items: center; gap: 16px; } - + .list-diamond { width: 32px; height: 32px; From ba3c2eae0dba6756c479e464d6452fe5c61430c7 Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 23:20:00 +0800 Subject: [PATCH 08/12] feat: add local state for bio --- apps/web/app/dashboard/page.tsx | 52 +++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 19db395..1db159d 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -11,6 +11,15 @@ export default function Dashboard() { const { data, isLoading } = trpc.user.getCurrent.useQuery(); const [isSidebarOpen, setIsSidebarOpen] = useState(false); + const [isEditingBio, setIsEditingBio] = useState(false); + const [bioInput, setBioInput] = useState(""); + + const handleSaveBio = () => { + // TODO: Hook this up to trpc.user.updateBio.useMutation() + console.log("Saving new bio:", bioInput); + setIsEditingBio(false); + }; + const goToMap = () => router.push("/"); const handleSignOut = async () => { @@ -239,11 +248,48 @@ export default function Dashboard() {

RECENT PINS

+ + {mockStats.recentList.length} +
-
-
-
+
+ {mockStats.recentList.map((pin) => { + const color = getPinColor(pin.type); + return ( +
+
+
+ {pin.title.charAt(0).toUpperCase()} +
+ +
+ {pin.title} + + {pin.lat.toFixed(4)}, {pin.lng.toFixed(4)} + +
+
+ + +
+ ); + })}
From e975b0179f31928d99aa0f5c703e37199ad3a462 Mon Sep 17 00:00:00 2001 From: ptrn23 Date: Tue, 24 Mar 2026 23:43:01 +0800 Subject: [PATCH 09/12] feat: fill user profile card --- apps/web/app/dashboard/page.tsx | 222 +++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 6 deletions(-) diff --git a/apps/web/app/dashboard/page.tsx b/apps/web/app/dashboard/page.tsx index 1db159d..9c0c4c5 100644 --- a/apps/web/app/dashboard/page.tsx +++ b/apps/web/app/dashboard/page.tsx @@ -118,13 +118,71 @@ export default function Dashboard() {

USER PROFILE

- ONLINE + + {(data as any)?.role === "ADMIN" ? "ADMIN" : "REGULAR USER"} +
-
-
-
-
-
+ +
+
+
+
+ {data?.name ? data.name.charAt(0).toUpperCase() : "O"} +
+
+
+ {data?.name || "UNKNOWN NAME"} + {(data as any)?.email || "UNKNOWN EMAIL"} +
+
+ +
+
+ BIO + {!isEditingBio && ( + + )} +
+ + {isEditingBio ? ( +
+