feat: unified Data Import page — merge Dispo + Skill imports
New /admin/imports page with tabs: - "Dispo Import" tab: renders DispoImportClient (lazy-loaded) - "Skill Matrix" tab: renders BatchSkillImport (lazy-loaded) - Tab state via ?tab= URL param Routing: - /admin/dispo-imports → redirects to /admin/imports?tab=dispo - /admin/skill-import → redirects to /admin/imports?tab=skills - /admin/dispo-imports/[batchId] detail routes still work Sidebar: single "Data Import" link under ACN-Orga (was 2 links) Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { DispoImportClient } from "~/components/admin/DispoImportClient.js";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function DispoImportsPage() {
|
||||
return <DispoImportClient />;
|
||||
export default function DispoImportRedirect() {
|
||||
redirect("/admin/imports?tab=dispo");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
const DispoImportClient = dynamic(
|
||||
() => import("~/components/admin/DispoImportClient.js").then((m) => m.DispoImportClient),
|
||||
{ loading: () => <div className="p-6"><div className="h-8 w-48 shimmer-skeleton rounded" /><div className="mt-4 h-64 shimmer-skeleton rounded-xl" /></div> },
|
||||
);
|
||||
|
||||
const BatchSkillImport = dynamic(
|
||||
() => import("~/components/admin/BatchSkillImport.js").then((m) => m.BatchSkillImport),
|
||||
{ loading: () => <div className="p-6"><div className="h-8 w-48 shimmer-skeleton rounded" /><div className="mt-4 h-64 shimmer-skeleton rounded-xl" /></div> },
|
||||
);
|
||||
|
||||
type Tab = "dispo" | "skills";
|
||||
|
||||
const TABS: { key: Tab; label: string; description: string }[] = [
|
||||
{ key: "dispo", label: "Dispo Import", description: "Import planning data from Dispo V2 workbooks" },
|
||||
{ key: "skills", label: "Skill Matrix", description: "Import skill matrices from XLSX files" },
|
||||
];
|
||||
|
||||
export default function ImportsPage() {
|
||||
const searchParams = useSearchParams();
|
||||
const initialTab = (searchParams.get("tab") as Tab) ?? "dispo";
|
||||
const [activeTab, setActiveTab] = useState<Tab>(initialTab);
|
||||
|
||||
return (
|
||||
<div className="app-page flex h-full flex-col gap-5 pb-6">
|
||||
<div className="app-page-header">
|
||||
<div>
|
||||
<h1 className="app-page-title">Data Import</h1>
|
||||
<p className="app-page-subtitle mt-1">Import planning data and skill matrices</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tab bar */}
|
||||
<div className="flex border-b border-gray-200 dark:border-gray-700">
|
||||
{TABS.map((tab) => (
|
||||
<button
|
||||
key={tab.key}
|
||||
type="button"
|
||||
onClick={() => setActiveTab(tab.key)}
|
||||
className={`px-5 py-2.5 text-sm font-medium border-b-2 -mb-px transition-colors ${
|
||||
activeTab === tab.key
|
||||
? "border-brand-500 text-brand-600 dark:text-brand-400"
|
||||
: "border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
||||
}`}
|
||||
>
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tab content */}
|
||||
<div className="flex-1 min-h-0">
|
||||
{activeTab === "dispo" && <DispoImportClient />}
|
||||
{activeTab === "skills" && <BatchSkillImport />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BatchSkillImport } from "~/components/admin/BatchSkillImport.js";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function BatchSkillImportPage() {
|
||||
return <BatchSkillImport />;
|
||||
export default function SkillImportRedirect() {
|
||||
redirect("/admin/imports?tab=skills");
|
||||
}
|
||||
|
||||
@@ -182,8 +182,7 @@ const adminNavEntries: AdminEntry[] = [
|
||||
{ href: "/admin/org-units", label: "Org Units", icon: <AdminIcon /> },
|
||||
{ href: "/admin/utilization-categories", label: "Util. Categories", icon: <AdminIcon /> },
|
||||
{ href: "/admin/management-levels", label: "Mgmt Levels", icon: <AdminIcon /> },
|
||||
{ href: "/admin/dispo-imports", label: "Dispo Import", icon: <AdminIcon /> },
|
||||
{ href: "/admin/skill-import", label: "Skill Import", icon: <AdminIcon /> },
|
||||
{ href: "/admin/imports", label: "Data Import", icon: <AdminIcon /> },
|
||||
],
|
||||
},
|
||||
{ href: "/admin/calculation-rules", label: "Calc. Rules", icon: <AdminIcon /> },
|
||||
|
||||
Reference in New Issue
Block a user