From 4b7e929470c6f3f29ee697ed63be3a4d025a9654 Mon Sep 17 00:00:00 2001 From: Mark Siazon <67873853+Iron-Mark@users.noreply.github.com> Date: Wed, 1 Jul 2026 11:01:34 +0800 Subject: [PATCH] chore: polish admin tables and live smoke checks --- docs/demo-checklist.md | 1 + package.json | 1 + scripts/run-live-smoke.js | 42 +++++++++ src/components/ui/table.tsx | 96 +++++++++++++++++++++ src/components/ui/tabs.tsx | 2 +- src/pages/admin/accounts/index.tsx | 68 ++++++++------- src/pages/admin/approvals/index.tsx | 77 +++++++++-------- src/pages/admin/audit-logs/index.tsx | 58 +++++++------ src/pages/admin/dashboard/index.tsx | 10 ++- src/pages/faculty/profile/ProfileHeader.tsx | 4 +- src/pages/faculty/uploaded/index.tsx | 2 +- 11 files changed, 266 insertions(+), 95 deletions(-) create mode 100644 scripts/run-live-smoke.js create mode 100644 src/components/ui/table.tsx diff --git a/docs/demo-checklist.md b/docs/demo-checklist.md index 9646bfa..9940523 100644 --- a/docs/demo-checklist.md +++ b/docs/demo-checklist.md @@ -89,6 +89,7 @@ Local command: ```bash npm run seo:check npm run links:check +npm run smoke:live ``` ## Build Preview Commands diff --git a/package.json b/package.json index 4755dc1..381f17f 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "security:scan": "node scripts/check-secrets.js", "seo:check": "node scripts/check-seo.js", "links:check": "node scripts/check-links.js", + "smoke:live": "node scripts/run-live-smoke.js", "preview": "vite preview", "preview:pages": "node scripts/serve-pages-preview.js", "test": "vitest --config vitest.config.ts" diff --git a/scripts/run-live-smoke.js b/scripts/run-live-smoke.js new file mode 100644 index 0000000..98f03c1 --- /dev/null +++ b/scripts/run-live-smoke.js @@ -0,0 +1,42 @@ +import { spawnSync } from 'node:child_process'; +import { existsSync } from 'node:fs'; +import { join } from 'node:path'; + +const liveUrl = 'https://iron-mark.github.io/Hackathon-Smart-Profile-Management-System/'; +const liveBasePath = '/Hackathon-Smart-Profile-Management-System/'; +const smokeSpecs = [ + 'tests/deep-links.spec.ts', + 'tests/seo.spec.ts', + 'tests/public-demo-responsive.spec.ts', +]; + +const command = join( + process.cwd(), + 'node_modules', + 'playwright', + 'cli.js' +); + +if (!existsSync(command)) { + console.error('Playwright is not installed. Run npm ci before live smoke checks.'); + process.exit(1); +} + +const result = spawnSync( + process.execPath, + [command, 'test', ...smokeSpecs, '--reporter=line'], + { + stdio: 'inherit', + env: { + ...process.env, + PLAYWRIGHT_BASE_URL: liveUrl, + PLAYWRIGHT_BASE_PATH: liveBasePath, + }, + } +); + +if (result.error) { + console.error(result.error.message); +} + +process.exit(result.status ?? 1); diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx new file mode 100644 index 0000000..537a3cd --- /dev/null +++ b/src/components/ui/table.tsx @@ -0,0 +1,96 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Table({ className, ...props }: React.ComponentProps<"table">) { + return ( +
+ + + ) +} + +function TableHeader({ className, ...props }: React.ComponentProps<"thead">) { + return +} + +function TableBody({ className, ...props }: React.ComponentProps<"tbody">) { + return ( + + ) +} + +function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) { + return ( + tr]:last:border-b-0", className)} + {...props} + /> + ) +} + +function TableRow({ className, ...props }: React.ComponentProps<"tr">) { + return ( + + ) +} + +function TableHead({ className, ...props }: React.ComponentProps<"th">) { + return ( +
+ ) +} + +function TableCell({ className, ...props }: React.ComponentProps<"td">) { + return ( + + ) +} + +function TableCaption({ className, ...props }: React.ComponentProps<"caption">) { + return ( +
+ ) +} + +export { + Table, + TableBody, + TableCaption, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, +} diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx index fb01e0a..7bb16fe 100644 --- a/src/components/ui/tabs.tsx +++ b/src/components/ui/tabs.tsx @@ -14,7 +14,7 @@ const TabsList = React.forwardRef<
- - - - - - - - - - - +
NameEmailRoleStatusActions
+ + + Name + Email + Role + Status + Actions + + + {isLoading ? ( Array.from({ length: 3 }).map((_, i) => ( - - - - - - - + + + + + + + + + )) ) : ( users.map((user) => { const deleteBlockReason = getDeleteBlockReason(user); return ( - - - - - - - + + ); }) )} - -
{user.name}{user.email}{user.type || "faculty"} + + {user.name} + {user.email} + {user.type || "faculty"} + Active - + + -
+ +
{!isLoading && users.length === 0 && (

diff --git a/src/pages/admin/approvals/index.tsx b/src/pages/admin/approvals/index.tsx index 149404c..8edb59d 100644 --- a/src/pages/admin/approvals/index.tsx +++ b/src/pages/admin/approvals/index.tsx @@ -5,6 +5,14 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { SidebarProvider } from "@/components/ui/sidebar"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; import getFromDatabase from "@/tools/database/getFromDatabase"; import updateDatabase from "@/tools/database/updateDatabase"; import getFileFromFolder from "@/tools/buckets/getFileFromFolder"; @@ -101,42 +109,43 @@ export default function AdminApprovalsPage() { Faculty Submissions - - - - - - - - - - - - +
Faculty NameDocument TypeFile NameDate SubmittedStatusActions
+ + + Faculty Name + Document Type + File Name + Date Submitted + Status + Actions + + + {isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( - - - - - - - - + + + + + + + + + + )) ) : ( submissions.map((submission) => ( - - - - - - - - + + )) )} - -
{submission.facultyName}{submission.document_type}{submission.file_name} + {submission.facultyName} + {submission.document_type} + {submission.file_name} + {new Date(submission.submitted_at).toLocaleDateString()} - + + {submission.status} - + + {submission.status === "Pending" && ( <> -
+ + {!isLoading && submissions.length === 0 && (

No submissions found. diff --git a/src/pages/admin/audit-logs/index.tsx b/src/pages/admin/audit-logs/index.tsx index fc258d4..523fad7 100644 --- a/src/pages/admin/audit-logs/index.tsx +++ b/src/pages/admin/audit-logs/index.tsx @@ -12,6 +12,14 @@ import { SelectValue, } from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; import getFromDatabase from "@/tools/database/getFromDatabase"; interface AuditLog { @@ -133,39 +141,39 @@ export default function AdminAuditLogsPage() {

- - - - - - - - - - +
TimestampUserActionDetails
+ + + Timestamp + User + Action + Details + + + {isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( - - - - - - + + + + + + )) ) : ( filteredLogs.map((log) => ( - - - - - - + + {log.user_email} + {log.action} + {log.details} + )) )} - -
+ + {new Date(log.timestamp).toLocaleString()} - {log.user_email}{log.action}{log.details}
+ +
{!isLoading && filteredLogs.length === 0 && (

diff --git a/src/pages/admin/dashboard/index.tsx b/src/pages/admin/dashboard/index.tsx index 222acc6..943114f 100644 --- a/src/pages/admin/dashboard/index.tsx +++ b/src/pages/admin/dashboard/index.tsx @@ -205,7 +205,7 @@ export default function AdminDashboard() { Active Sessions (24h) - Recent seeded login activity + Recent seeded login activity

{isLoading ? : activeSessions}
@@ -218,7 +218,7 @@ export default function AdminDashboard() { Pending Approvals - Credentials waiting for review + Credentials waiting for review
{isLoading ? : pendingApprovals}
@@ -276,7 +276,11 @@ export default function AdminDashboard() { ))} - + ( + {value} + )} + /> )} diff --git a/src/pages/faculty/profile/ProfileHeader.tsx b/src/pages/faculty/profile/ProfileHeader.tsx index 575bd70..0499791 100644 --- a/src/pages/faculty/profile/ProfileHeader.tsx +++ b/src/pages/faculty/profile/ProfileHeader.tsx @@ -123,7 +123,7 @@ const ProfileHeader: React.FC = ({ /> ) : (
- Upload Cover Photo + Upload Cover Photo
)}
@@ -154,7 +154,7 @@ const ProfileHeader: React.FC = ({ className='object-cover w-full h-full' /> ) : ( -
+
No Image
)} diff --git a/src/pages/faculty/uploaded/index.tsx b/src/pages/faculty/uploaded/index.tsx index 457e755..47d3697 100644 --- a/src/pages/faculty/uploaded/index.tsx +++ b/src/pages/faculty/uploaded/index.tsx @@ -311,7 +311,7 @@ export default function UploadedFilesPage() { />