Skip to content

Commit 7002272

Browse files
feat(admin): migrate panel to TSX and unify dashboard chrome
- Migrate admin pages from Vue SFCs to TypeScript TSX components and redesign. - New resources/js/components/admin/ui.tsx: AdminPageHeader, SegmentedTabs, AdminSelect, sub-nav, buttons, lists, table shell; all 18 admin pages migrated. - Fix invisible segmented active state in dark mode (gray-700 pill, no ring/glow); hover rows use spaced lists instead of divide+hover-pill outline clash. - Dark-safe native selects (color-scheme + themed options); Bulk Rename into node header; boxed moderation table; mobile header-action wrapping. - app.blade.php resolves the Inertia page entry by existing extension (.vue vs .tsx) so migrated pages load in production builds.
1 parent 3b48544 commit 7002272

50 files changed

Lines changed: 8287 additions & 7293 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.cr-query.graphql‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
query {
2+
repository(owner: "hscstack", name: "platform") {
3+
pullRequest(number: 366) {
4+
reviewThreads(first: 100) {
5+
nodes {
6+
id
7+
isResolved
8+
isOutdated
9+
path
10+
comments(first: 10) {
11+
nodes {
12+
body
13+
commit {
14+
oid
15+
}
16+
}
17+
}
18+
}
19+
}
20+
}
21+
}
22+
}

‎resources/js/app.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@ router.on('navigate', () => {
2020

2121
createInertiaApp({
2222
title: (title) => (title ? `${title} - ${appName}` : appName),
23+
// Dual-extension page resolver: `.vue` SFCs first, `.tsx`
24+
// `defineComponent` pages (e.g. admin TSX proof-of-concept) as fallback.
25+
resolve: (name) => {
26+
const pages = import.meta.glob('./pages/**/*.{vue,tsx}') as Record<
27+
string,
28+
() => Promise<{ default: unknown }>
29+
>;
30+
const loader =
31+
pages[`./pages/${name}.vue`] ?? pages[`./pages/${name}.tsx`];
32+
33+
if (!loader) {
34+
throw new Error(`Page not found: ${name}`);
35+
}
36+
37+
return loader().then((module) => module.default ?? module);
38+
},
2339
layout: (name) => {
2440
switch (true) {
2541
case name.startsWith('admin/'):

‎resources/js/components/admin/BulkImageModal.vue‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ const submitForm = async () => {
569569
<!-- Compression Status Bar -->
570570
<div
571571
v-if="isCompressing"
572-
class="border-t border-slate-100 bg-indigo-50/70 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-indigo-950/30"
572+
class="border-t border-slate-200/60 bg-indigo-50/70 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-indigo-950/30"
573573
>
574574
<div
575575
class="flex items-center gap-2 text-xs font-medium text-indigo-600 dark:text-indigo-400"
@@ -582,7 +582,7 @@ const submitForm = async () => {
582582
<!-- Upload Progress Bar -->
583583
<div
584584
v-if="!isCompressing && isSaving && uploadProgress !== null"
585-
class="border-t border-slate-100 bg-slate-50/80 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/80"
585+
class="border-t border-slate-200/60 bg-slate-50/80 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/80"
586586
>
587587
<div class="mb-1.5 flex items-center justify-between text-xs">
588588
<span
@@ -623,7 +623,7 @@ const submitForm = async () => {
623623

624624
<!-- Footer -->
625625
<div
626-
class="flex items-center justify-end gap-2 border-t border-slate-100 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/60"
626+
class="flex items-center justify-end gap-2 border-t border-slate-200/60 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/60"
627627
>
628628
<button
629629
type="button"

‎resources/js/components/admin/BulkRenameModal.vue‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ const handleSubmit = () => {
167167

168168
<!-- Before & After Preview Card -->
169169
<div
170-
class="rounded-xl border border-slate-200 bg-slate-50/70 p-3.5 dark:border-gray-800 dark:bg-gray-800/40"
170+
class="rounded-xl border border-slate-200 bg-slate-50/70 p-3.5 dark:border-slate-800/60 dark:bg-gray-800/40"
171171
>
172172
<div
173173
class="mb-2.5 flex items-center justify-between text-[11px] font-bold tracking-wider text-slate-500 uppercase dark:text-gray-400"
@@ -222,7 +222,7 @@ const handleSubmit = () => {
222222

223223
<!-- Footer -->
224224
<div
225-
class="flex items-center justify-end gap-2 border-t border-slate-100 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/60"
225+
class="flex items-center justify-end gap-2 border-t border-slate-200/60 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/60"
226226
>
227227
<button
228228
type="button"

‎resources/js/components/admin/BulkVideoModal.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ const submitForm = () => {
317317

318318
<!-- Footer -->
319319
<div
320-
class="flex items-center justify-end gap-2 border-t border-slate-100 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/60"
320+
class="flex items-center justify-end gap-2 border-t border-slate-200/60 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/60"
321321
>
322322
<button
323323
type="button"

‎resources/js/components/admin/CreateNodeModal.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ const submitForm = () => {
321321

322322
<!-- Footer -->
323323
<div
324-
class="flex items-center justify-end gap-2 border-t border-slate-100 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/60"
324+
class="flex items-center justify-end gap-2 border-t border-slate-200/60 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/60"
325325
>
326326
<button
327327
type="button"

‎resources/js/components/admin/CreateResourceModal.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ const submitForm = () => {
446446

447447
<!-- Footer -->
448448
<div
449-
class="flex items-center justify-end gap-2 border-t border-slate-100 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/60"
449+
class="flex items-center justify-end gap-2 border-t border-slate-200/60 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/60"
450450
>
451451
<button
452452
type="button"

‎resources/js/components/admin/CreateSubjectModal.vue‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ const submitForm = () => {
351351
{{ name || 'Subject Name' }}
352352
</h4>
353353
<span
354-
class="py-0.2 inline-flex rounded px-1 text-[9px] font-bold uppercase"
354+
class="inline-flex rounded px-1 py-0.5 text-[9px] font-bold uppercase"
355355
:class="
356356
course === 'ssc'
357357
? 'bg-amber-100 text-amber-700 dark:bg-amber-950/60 dark:text-amber-300'
@@ -510,7 +510,7 @@ const submitForm = () => {
510510

511511
<!-- Footer -->
512512
<div
513-
class="flex items-center justify-end gap-2 border-t border-slate-100 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-gray-800 dark:bg-gray-900/60"
513+
class="flex items-center justify-end gap-2 border-t border-slate-200/60 bg-slate-50/60 px-4 py-3 sm:px-6 dark:border-slate-800/60 dark:bg-gray-900/60"
514514
>
515515
<button
516516
type="button"

‎resources/js/components/admin/NodeHeader.vue‎

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script setup lang="ts">
22
import { Link } from '@inertiajs/vue3';
33
import {
4-
ArrowLeft,
54
ChevronDown,
65
ChevronRight,
76
FolderPlus,
@@ -16,7 +15,6 @@ defineProps<{
1615
subject: any;
1716
parent?: any | null;
1817
breadcrumbs: Array<{ name: string; link: string }>;
19-
backUrl: string;
2018
isFrozen: boolean;
2119
isDirectlyFrozen: boolean;
2220
isInheritedFrozen: boolean;
@@ -55,7 +53,7 @@ onUnmounted(() => document.removeEventListener('click', closeDropdowns));
5553
<!-- Dedicated Breadcrumb Navigation Bar (Separate Row) -->
5654
<div
5755
v-if="breadcrumbs.length > 0"
58-
class="mb-3.5 flex items-center rounded-xl bg-slate-50/80 px-3 py-2 text-xs font-medium text-slate-500 sm:text-sm dark:bg-gray-800/40 dark:text-gray-400"
56+
class="mb-3.5 flex items-center rounded-xl bg-white/70 px-3 py-2 text-xs font-medium text-slate-500 ring-1 ring-slate-200/60 backdrop-blur-xl sm:text-sm dark:bg-slate-900/60 dark:text-gray-400 dark:ring-slate-800/60"
5957
>
6058
<nav
6159
class="no-scrollbar flex min-w-0 flex-wrap items-center gap-1.5"
@@ -87,11 +85,11 @@ onUnmounted(() => document.removeEventListener('click', closeDropdowns));
8785
<!-- Freeze Notice Banner -->
8886
<div
8987
v-if="isFrozen"
90-
class="mb-3.5 flex items-center gap-2.5 rounded-xl border px-3.5 py-2.5 text-xs font-medium"
88+
class="mb-3.5 flex items-center gap-2.5 rounded-xl px-3.5 py-2.5 text-xs font-medium ring-1"
9189
:class="
9290
isDirectlyFrozen
93-
? 'border-sky-200 bg-sky-50 text-sky-800 dark:border-sky-800/60 dark:bg-sky-950/40 dark:text-sky-300'
94-
: 'border-amber-200 bg-amber-50/80 text-amber-800 dark:border-amber-800/60 dark:bg-amber-950/40 dark:text-amber-300'
91+
? 'bg-sky-50/80 text-sky-800 ring-sky-200/70 dark:bg-sky-500/10 dark:text-sky-300 dark:ring-sky-500/25'
92+
: 'bg-amber-50/80 text-amber-800 ring-amber-200/70 dark:bg-amber-500/10 dark:text-amber-300 dark:ring-amber-500/25'
9593
"
9694
>
9795
<Lock
@@ -114,38 +112,30 @@ onUnmounted(() => document.removeEventListener('click', closeDropdowns));
114112

115113
<!-- Compact Page Title Bar -->
116114
<div
117-
class="mb-3.5 flex shrink-0 items-center justify-between gap-2 border-b border-slate-100 pb-3 sm:gap-3 dark:border-gray-800"
115+
class="flex flex-wrap items-center justify-between gap-2 border-b border-slate-200/60 pb-4 sm:gap-3 dark:border-slate-800/60"
118116
>
119-
<div class="flex min-w-0 flex-1 items-center gap-2 sm:gap-2.5">
120-
<Link
121-
:href="backUrl"
122-
class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-500 shadow-2xs transition-colors hover:bg-slate-50 hover:text-slate-700 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200"
123-
title="Go back"
124-
>
125-
<ArrowLeft class="h-4 w-4" :stroke-width="2.2" />
126-
</Link>
127-
128-
<h3
129-
class="truncate text-sm font-bold tracking-tight text-slate-900 sm:text-base dark:text-gray-100"
117+
<div class="flex min-w-0 flex-1 items-center sm:gap-2.5">
118+
<h1
119+
class="truncate text-base font-bold tracking-tight text-slate-900 sm:text-lg dark:text-gray-100"
130120
>
131121
{{ parent?.name ? parent.name : subject.name }}
132-
</h3>
122+
</h1>
133123
</div>
134124

135-
<div class="flex shrink-0 items-center gap-1.5 sm:gap-2">
125+
<div class="ms-auto flex items-center gap-1.5 sm:gap-2">
136126
<!-- Toggle Freeze Button -->
137127
<button
138128
v-if="parent?.id && can('freeze nodes')"
139129
type="button"
140130
:disabled="isTogglingFreeze"
141131
@click="emit('toggle-freeze')"
142-
class="inline-flex cursor-pointer items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs font-semibold shadow-2xs transition-colors disabled:opacity-50 sm:px-3"
132+
class="inline-flex h-8 cursor-pointer items-center gap-1.5 rounded-[10px] px-2.5 text-xs font-semibold ring-1 transition-colors duration-150 disabled:opacity-50 sm:px-3"
143133
:class="
144134
isDirectlyFrozen
145-
? 'border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:border-emerald-800 dark:bg-emerald-950/50 dark:text-emerald-300 dark:hover:bg-emerald-900/50'
135+
? 'bg-emerald-50/80 text-emerald-700 ring-emerald-300/60 hover:bg-emerald-100 dark:bg-emerald-500/10 dark:text-emerald-300 dark:ring-emerald-500/20 dark:hover:bg-emerald-500/15'
146136
: isInheritedFrozen
147-
? 'border-amber-200 bg-amber-50 text-amber-700 hover:bg-amber-100 dark:border-amber-800 dark:bg-amber-950/50 dark:text-amber-300 dark:hover:bg-amber-900/50'
148-
: 'border-sky-200 bg-sky-50 text-sky-700 hover:bg-sky-100 dark:border-sky-800 dark:bg-sky-950/50 dark:text-sky-300 dark:hover:bg-sky-900/50'
137+
? 'bg-amber-50/80 text-amber-700 ring-amber-300/60 hover:bg-amber-100 dark:bg-amber-500/10 dark:text-amber-300 dark:ring-amber-500/20 dark:hover:bg-amber-500/15'
138+
: 'bg-sky-50/80 text-sky-700 ring-sky-300/60 hover:bg-sky-100 dark:bg-sky-500/10 dark:text-sky-300 dark:ring-sky-500/20 dark:hover:bg-sky-500/15'
149139
"
150140
:title="
151141
isDirectlyFrozen
@@ -179,7 +169,7 @@ onUnmounted(() => document.removeEventListener('click', closeDropdowns));
179169
<button
180170
type="button"
181171
@click="isFolderDropdownOpen = !isFolderDropdownOpen"
182-
class="inline-flex cursor-pointer items-center gap-1 rounded-lg border border-slate-200 bg-white px-2.5 py-1.5 text-xs font-semibold text-slate-700 shadow-2xs transition-colors hover:bg-slate-50 sm:gap-1.5 sm:px-3 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700"
172+
class="inline-flex h-8 cursor-pointer items-center gap-1 rounded-[10px] bg-white/70 px-2.5 text-xs font-semibold text-slate-700 ring-1 ring-slate-200/60 backdrop-blur transition-colors hover:bg-white/90 hover:text-slate-900 sm:gap-1.5 sm:px-3 dark:bg-slate-900/60 dark:text-gray-300 dark:ring-slate-800/60 dark:hover:bg-slate-900/85 dark:hover:text-gray-100"
183173
>
184174
<FolderPlus
185175
class="h-3.5 w-3.5 text-slate-500 dark:text-gray-400"
@@ -194,7 +184,7 @@ onUnmounted(() => document.removeEventListener('click', closeDropdowns));
194184

195185
<div
196186
v-if="isFolderDropdownOpen"
197-
class="absolute right-0 z-10 mt-1.5 w-44 rounded-xl border border-slate-100 bg-white p-1 shadow-lg dark:border-gray-800 dark:bg-gray-900"
187+
class="absolute right-0 z-10 mt-1.5 w-44 rounded-xl bg-white/90 p-1 shadow-lg ring-1 ring-slate-200/70 backdrop-blur-xl dark:bg-slate-900/90 dark:ring-slate-800/70"
198188
>
199189
<button
200190
type="button"

‎resources/js/components/admin/NodeRow.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const handleDelete = () => {
2929
<template>
3030
<div
3131
@click="router.visit(`${$page.url}/${node?.slug}`)"
32-
class="group relative flex cursor-pointer items-center justify-between gap-3 rounded-xl border border-slate-100 bg-white p-3 transition-colors duration-150 hover:border-indigo-200 hover:bg-slate-50/50 sm:p-3.5 dark:border-gray-800 dark:bg-gray-900 dark:hover:border-indigo-500/30 dark:hover:bg-gray-800/40"
32+
class="group relative flex cursor-pointer items-center justify-between gap-3 rounded-xl bg-white/70 p-3 ring-1 ring-slate-200/60 backdrop-blur-xl transition-colors duration-150 hover:bg-white/85 hover:ring-indigo-300/70 sm:p-3.5 dark:bg-slate-900/60 dark:ring-slate-800/60 dark:hover:bg-slate-900/75 dark:hover:ring-indigo-500/40"
3333
>
3434
<!-- Left: Icon + Full Title -->
3535
<div class="flex min-w-0 flex-1 items-center gap-3">

0 commit comments

Comments
 (0)