ui(step-4): apply reference layout to remaining 7 pages

- catering-services, fitness-trainers, graphic-designers, social-media-managers,
  video-editors, verification, kb: white header, data-table/table-card,
  navy buttons, orange tab underlines, inline styles removed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ashwin Kumar 2026-03-24 05:23:57 +01:00
parent 5cfa4b89be
commit 3ffed6c813
7 changed files with 743 additions and 731 deletions

View file

@ -36,14 +36,13 @@ export default function CateringServicesPage() {
return (
<AdminShell>
<div class="mb-6 flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-bold text-gray-900">Catering Services Management</h1>
<p class="mt-1 text-sm text-gray-500">Manage all catering services accounts on the platform.</p>
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Catering Services Management</h1>
<p class="text-sm text-gray-500 mt-0.5">Manage all catering services accounts on the platform.</p>
</div>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding: 0; overflow: hidden;">
<div class="flex-1 p-6">
<div class="table-card">
<div style="display:flex;gap:12px;padding:16px;border-bottom:1px solid #e2e8f0;flex-wrap:wrap;">
<input
type="text"
@ -65,7 +64,7 @@ export default function CateringServicesPage() {
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Name</th>
@ -88,9 +87,9 @@ export default function CateringServicesPage() {
<Show when={!users.loading && !users.error && filtered().length > 0}>
<For each={filtered()}>
{(item) => (
<tr>
<td style="font-weight:600;color:#0f172a">{item.name || item.full_name || '—'}</td>
<td style="color:#475569">{item.email}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{item.name || item.full_name || '—'}</td>
<td class="text-slate-500">{item.email}</td>
<td>
{item.status?.toUpperCase() === 'ACTIVE' && (
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-700">ACTIVE</span>
@ -103,7 +102,7 @@ export default function CateringServicesPage() {
)}
{!item.status && <span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600"></span>}
</td>
<td style="color:#475569">
<td class="text-slate-500">
{item.created_at ? new Date(item.created_at).toLocaleDateString() : '—'}
</td>
<td>
@ -118,7 +117,9 @@ export default function CateringServicesPage() {
</tbody>
</table>
</div>
</section>
</div>
</div>
</div>
</AdminShell>
);
}

View file

@ -36,14 +36,13 @@ export default function FitnessTrainersPage() {
return (
<AdminShell>
<div class="mb-6 flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-bold text-gray-900">Fitness Trainer Management</h1>
<p class="mt-1 text-sm text-gray-500">Manage all fitness trainer accounts on the platform.</p>
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Fitness Trainer Management</h1>
<p class="text-sm text-gray-500 mt-0.5">Manage all fitness trainer accounts on the platform.</p>
</div>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding: 0; overflow: hidden;">
<div class="flex-1 p-6">
<div class="table-card">
<div style="display:flex;gap:12px;padding:16px;border-bottom:1px solid #e2e8f0;flex-wrap:wrap;">
<input
type="text"
@ -65,7 +64,7 @@ export default function FitnessTrainersPage() {
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Name</th>
@ -88,9 +87,9 @@ export default function FitnessTrainersPage() {
<Show when={!users.loading && !users.error && filtered().length > 0}>
<For each={filtered()}>
{(item) => (
<tr>
<td style="font-weight:600;color:#0f172a">{item.name || item.full_name || '—'}</td>
<td style="color:#475569">{item.email}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{item.name || item.full_name || '—'}</td>
<td class="text-slate-500">{item.email}</td>
<td>
{item.status?.toUpperCase() === 'ACTIVE' && (
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-700">ACTIVE</span>
@ -103,7 +102,7 @@ export default function FitnessTrainersPage() {
)}
{!item.status && <span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600"></span>}
</td>
<td style="color:#475569">
<td class="text-slate-500">
{item.created_at ? new Date(item.created_at).toLocaleDateString() : '—'}
</td>
<td>
@ -118,7 +117,9 @@ export default function FitnessTrainersPage() {
</tbody>
</table>
</div>
</section>
</div>
</div>
</div>
</AdminShell>
);
}

View file

@ -36,14 +36,13 @@ export default function GraphicDesignersPage() {
return (
<AdminShell>
<div class="mb-6 flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-bold text-gray-900">Graphic Designer Management</h1>
<p class="mt-1 text-sm text-gray-500">Manage all graphic designer accounts on the platform.</p>
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Graphic Designer Management</h1>
<p class="text-sm text-gray-500 mt-0.5">Manage all graphic designer accounts on the platform.</p>
</div>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding: 0; overflow: hidden;">
<div class="flex-1 p-6">
<div class="table-card">
<div style="display:flex;gap:12px;padding:16px;border-bottom:1px solid #e2e8f0;flex-wrap:wrap;">
<input
type="text"
@ -65,7 +64,7 @@ export default function GraphicDesignersPage() {
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Name</th>
@ -88,9 +87,9 @@ export default function GraphicDesignersPage() {
<Show when={!users.loading && !users.error && filtered().length > 0}>
<For each={filtered()}>
{(item) => (
<tr>
<td style="font-weight:600;color:#0f172a">{item.name || item.full_name || '—'}</td>
<td style="color:#475569">{item.email}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{item.name || item.full_name || '—'}</td>
<td class="text-slate-500">{item.email}</td>
<td>
{item.status?.toUpperCase() === 'ACTIVE' && (
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-700">ACTIVE</span>
@ -103,7 +102,7 @@ export default function GraphicDesignersPage() {
)}
{!item.status && <span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600"></span>}
</td>
<td style="color:#475569">
<td class="text-slate-500">
{item.created_at ? new Date(item.created_at).toLocaleDateString() : '—'}
</td>
<td>
@ -118,7 +117,9 @@ export default function GraphicDesignersPage() {
</tbody>
</table>
</div>
</section>
</div>
</div>
</div>
</AdminShell>
);
}

View file

@ -215,43 +215,44 @@ export default function KbPage(props: KbPageProps = {}) {
return (
<AdminShell>
<div class="mb-6 flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-bold text-gray-900">Knowledge Base</h1>
<p class="mt-1 text-sm text-gray-500">Manage help articles and categories</p>
</div>
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Knowledge Base</h1>
<p class="text-sm text-gray-500 mt-0.5">Manage help articles and categories</p>
</div>
{/* Tabs */}
<div style="display:flex;border-bottom:2px solid #e2e8f0;margin-bottom:24px;gap:0;overflow-x:auto;">
<div class="bg-white border-b border-gray-200 px-6 flex gap-6 overflow-x-auto">
<button
type="button"
class={`admin-tab${tab() === 'categories' ? ' active' : ''}`}
class={tab() === 'categories' ? 'py-3 border-b-2 border-orange-500 text-orange-600 text-sm font-medium' : 'py-3 border-b-2 border-transparent text-gray-500 hover:text-gray-700 text-sm font-medium transition-colors'}
onClick={() => setTab('categories')}
>
Categories
</button>
<button
type="button"
class={`admin-tab${tab() === 'articles' ? ' active' : ''}`}
class={tab() === 'articles' ? 'py-3 border-b-2 border-orange-500 text-orange-600 text-sm font-medium' : 'py-3 border-b-2 border-transparent text-gray-500 hover:text-gray-700 text-sm font-medium transition-colors'}
onClick={() => setTab('articles')}
>
Articles
</button>
<button
type="button"
class={`admin-tab${tab() === 'create-article' ? ' active' : ''}`}
class={tab() === 'create-article' ? 'py-3 border-b-2 border-orange-500 text-orange-600 text-sm font-medium' : 'py-3 border-b-2 border-transparent text-gray-500 hover:text-gray-700 text-sm font-medium transition-colors'}
onClick={() => setTab('create-article')}
>
Create Article
</button>
</div>
<div class="flex-1 p-6">
{/* Categories Tab */}
<Show when={tab() === 'categories'}>
<div class="mb-6 flex items-start justify-between gap-4" style="margin-bottom:16px">
<div />
<button class="inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors" onClick={() => setShowCatForm(!showCatForm())}>
<button class="inline-flex items-center rounded-lg bg-[#0a1d37] px-4 py-2 text-sm font-semibold text-white hover:bg-[#0f2a4e] transition-colors" onClick={() => setShowCatForm(!showCatForm())}>
{showCatForm() ? 'Cancel' : 'Add Category'}
</button>
</div>
@ -261,7 +262,7 @@ export default function KbPage(props: KbPageProps = {}) {
</Show>
<Show when={showCatForm()}>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="margin-bottom:16px;max-width:480px">
<div class="table-card" style="margin-bottom:16px;max-width:480px">
<h2 style="margin:0 0 16px;font-size:15px;font-weight:700">New Category</h2>
<Show when={catError()}>
<div class="mb-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700" style="margin-bottom:10px">{catError()}</div>
@ -300,17 +301,17 @@ export default function KbPage(props: KbPageProps = {}) {
/>
</div>
<div>
<button class="inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors" type="submit" disabled={catSaving()}>
<button class="inline-flex items-center rounded-lg bg-[#0a1d37] px-4 py-2 text-sm font-semibold text-white hover:bg-[#0f2a4e] transition-colors" type="submit" disabled={catSaving()}>
{catSaving() ? 'Saving...' : 'Create Category'}
</button>
</div>
</form>
</section>
</div>
</Show>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding:0;overflow:hidden">
<div class="table-card">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Name</th>
@ -333,10 +334,10 @@ export default function KbPage(props: KbPageProps = {}) {
<For each={categories()}>
{(cat) => (
<>
<tr>
<td style="font-weight:600;color:#0f172a">{cat.name}</td>
<td style="color:#475569;font-family:monospace;font-size:13px">{cat.slug}</td>
<td style="color:#475569">{cat.article_count ?? '—'}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{cat.name}</td>
<td class="text-slate-500" style="font-family:monospace;font-size:13px">{cat.slug}</td>
<td class="text-slate-500">{cat.article_count ?? '—'}</td>
<td>
<div class="flex items-center justify-end gap-1">
<button class="inline-flex items-center rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors" onClick={() => startEditCat(cat)}>Edit</button>
@ -376,7 +377,7 @@ export default function KbPage(props: KbPageProps = {}) {
/>
</div>
<div style="display:flex;gap:8px">
<button class="inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors" disabled={editCatSaving()} onClick={() => saveEditCat(cat.id)}>
<button class="inline-flex items-center rounded-lg bg-[#0a1d37] px-4 py-2 text-sm font-semibold text-white hover:bg-[#0f2a4e] transition-colors" disabled={editCatSaving()} onClick={() => saveEditCat(cat.id)}>
{editCatSaving() ? 'Saving...' : 'Save'}
</button>
<button class="inline-flex items-center rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors" onClick={cancelEditCat}>Cancel</button>
@ -392,7 +393,7 @@ export default function KbPage(props: KbPageProps = {}) {
</tbody>
</table>
</div>
</section>
</div>
</Show>
{/* Articles Tab */}
@ -411,9 +412,9 @@ export default function KbPage(props: KbPageProps = {}) {
/>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding:0;overflow:hidden">
<div class="table-card">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Title</th>
@ -436,15 +437,15 @@ export default function KbPage(props: KbPageProps = {}) {
<Show when={!articles.loading && !articles.error && filteredArticles().length > 0}>
<For each={filteredArticles()}>
{(article) => (
<tr>
<td style="font-weight:600;color:#0f172a">{article.title}</td>
<td style="color:#475569">{article.category || '—'}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{article.title}</td>
<td class="text-slate-500">{article.category || '—'}</td>
<td>
<span class={`inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600 ${article.status === 'PUBLISHED' ? 'active' : 'draft'}`}>
{article.status || '—'}
</span>
</td>
<td style="color:#475569">
<td class="text-slate-500">
{article.updated_at ? new Date(article.updated_at).toLocaleString() : '—'}
</td>
<td>
@ -466,12 +467,12 @@ export default function KbPage(props: KbPageProps = {}) {
</tbody>
</table>
</div>
</section>
</div>
</Show>
{/* Create Article Tab */}
<Show when={tab() === 'create-article'}>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="max-width:640px">
<div class="table-card" style="max-width:640px">
<h2 style="margin:0 0 20px;font-size:16px;font-weight:700">New Article</h2>
<Show when={artError()}>
<div class="mb-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700" style="margin-bottom:14px">{artError()}</div>
@ -536,13 +537,16 @@ export default function KbPage(props: KbPageProps = {}) {
</select>
</div>
<div>
<button class="inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors" type="submit" disabled={artSaving()}>
<button class="inline-flex items-center rounded-lg bg-[#0a1d37] px-4 py-2 text-sm font-semibold text-white hover:bg-[#0f2a4e] transition-colors" type="submit" disabled={artSaving()}>
{artSaving() ? 'Creating...' : 'Create Article'}
</button>
</div>
</form>
</section>
</div>
</Show>
</div>
</div>
</AdminShell>
);
}

View file

@ -36,14 +36,13 @@ export default function SocialMediaManagersPage() {
return (
<AdminShell>
<div class="mb-6 flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-bold text-gray-900">Social Media Manager Management</h1>
<p class="mt-1 text-sm text-gray-500">Manage all social media manager accounts on the platform.</p>
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Social Media Manager Management</h1>
<p class="text-sm text-gray-500 mt-0.5">Manage all social media manager accounts on the platform.</p>
</div>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding: 0; overflow: hidden;">
<div class="flex-1 p-6">
<div class="table-card">
<div style="display:flex;gap:12px;padding:16px;border-bottom:1px solid #e2e8f0;flex-wrap:wrap;">
<input
type="text"
@ -65,7 +64,7 @@ export default function SocialMediaManagersPage() {
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Name</th>
@ -88,9 +87,9 @@ export default function SocialMediaManagersPage() {
<Show when={!users.loading && !users.error && filtered().length > 0}>
<For each={filtered()}>
{(item) => (
<tr>
<td style="font-weight:600;color:#0f172a">{item.name || item.full_name || '—'}</td>
<td style="color:#475569">{item.email}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{item.name || item.full_name || '—'}</td>
<td class="text-slate-500">{item.email}</td>
<td>
{item.status?.toUpperCase() === 'ACTIVE' && (
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-700">ACTIVE</span>
@ -103,7 +102,7 @@ export default function SocialMediaManagersPage() {
)}
{!item.status && <span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600"></span>}
</td>
<td style="color:#475569">
<td class="text-slate-500">
{item.created_at ? new Date(item.created_at).toLocaleDateString() : '—'}
</td>
<td>
@ -118,7 +117,9 @@ export default function SocialMediaManagersPage() {
</tbody>
</table>
</div>
</section>
</div>
</div>
</div>
</AdminShell>
);
}

View file

@ -4,21 +4,24 @@ import AdminShell from '~/components/AdminShell';
export default function VerificationManagementPage() {
return (
<AdminShell>
<div class="page-hero-card">
<h1 class="text-2xl font-bold text-gray-900">Approval Management</h1>
<p class="mt-1 text-sm text-gray-500" style="margin-top:8px">
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Approval Management</h1>
<p class="text-sm text-gray-500 mt-0.5">
Admin review now lives under Approval Management. Verification remains a user-facing status concept.
</p>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm">
<div class="flex-1 p-6">
<div class="table-card">
<p class="notice" style="margin:0">
Use Approval Management to review companies, customers, candidates, and professional submissions.
</p>
<div class="actions">
<A class="inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors" href="/admin/approval">Open Approval Management</A>
<A class="inline-flex items-center rounded-lg bg-[#0a1d37] px-4 py-2 text-sm font-semibold text-white hover:bg-[#0f2a4e] transition-colors" href="/admin/approval">Open Approval Management</A>
</div>
</div>
</div>
</div>
</section>
</AdminShell>
);
}

View file

@ -36,14 +36,13 @@ export default function VideoEditorsPage() {
return (
<AdminShell>
<div class="mb-6 flex items-start justify-between gap-4">
<div>
<h1 class="text-2xl font-bold text-gray-900">Video Editor Management</h1>
<p class="mt-1 text-sm text-gray-500">Manage all video editor accounts on the platform.</p>
<div class="flex flex-col -mx-6 -mt-6 min-h-full">
<div class="bg-white border-b border-gray-200 px-6 py-4">
<h1 class="text-xl font-semibold text-gray-900">Video Editor Management</h1>
<p class="text-sm text-gray-500 mt-0.5">Manage all video editor accounts on the platform.</p>
</div>
</div>
<section class="rounded-xl border border-gray-200 bg-white shadow-sm" style="padding: 0; overflow: hidden;">
<div class="flex-1 p-6">
<div class="table-card">
<div style="display:flex;gap:12px;padding:16px;border-bottom:1px solid #e2e8f0;flex-wrap:wrap;">
<input
type="text"
@ -65,7 +64,7 @@ export default function VideoEditorsPage() {
</div>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<table data-table class="w-full text-sm">
<thead>
<tr>
<th>Name</th>
@ -88,9 +87,9 @@ export default function VideoEditorsPage() {
<Show when={!users.loading && !users.error && filtered().length > 0}>
<For each={filtered()}>
{(item) => (
<tr>
<td style="font-weight:600;color:#0f172a">{item.name || item.full_name || '—'}</td>
<td style="color:#475569">{item.email}</td>
<tr class="hover:bg-slate-50">
<td class="font-semibold text-slate-900">{item.name || item.full_name || '—'}</td>
<td class="text-slate-500">{item.email}</td>
<td>
{item.status?.toUpperCase() === 'ACTIVE' && (
<span class="inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-700">ACTIVE</span>
@ -103,7 +102,7 @@ export default function VideoEditorsPage() {
)}
{!item.status && <span class="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600"></span>}
</td>
<td style="color:#475569">
<td class="text-slate-500">
{item.created_at ? new Date(item.created_at).toLocaleDateString() : '—'}
</td>
<td>
@ -118,7 +117,9 @@ export default function VideoEditorsPage() {
</tbody>
</table>
</div>
</section>
</div>
</div>
</div>
</AdminShell>
);
}