Refactor: consolidate accounting routes under Buchhaltung submenu
- New layout route: companies.$id.buchhaltung.tsx with card-based navigation - Renamed 7 accounting routes to use buchhaltung prefix: - companies.$id.bilanzen.tsx → companies.$id.buchhaltung.bilanzen.tsx - companies.$id.ausgaben.tsx → companies.$id.buchhaltung.ausgaben.tsx - companies.$id.ausgaben.kategorien.tsx → companies.$id.buchhaltung.ausgaben.kategorien.tsx - companies.$id.einnahmen.tsx → companies.$id.buchhaltung.einnahmen.tsx - companies.$id.einnahmen.kategorien.tsx → companies.$id.buchhaltung.einnahmen.kategorien.tsx - companies.$id.anlagevermoegen.tsx → companies.$id.buchhaltung.anlagevermoegen.tsx - companies.$id.money.tsx → companies.$id.buchhaltung.money.tsx - Updated routing configuration (app/routes.ts) to use nested layout structure - Updated breadcrumbs in all accounting routes to show Buchhaltung hierarchy - Updated internal links in kategorien pages to use new URLs - Main menu now shows single 'Buchhaltung' card instead of 5 separate items Navigation improvements: - Cleaner main menu (1 item vs 5) - Clear accounting subsection with icon-based navigation - Consistent URL structure (/companies/:id/buchhaltung/*) - Better information hierarchy Build: ✅ Successful Accounting routes: ✅ Accessible Navigation: ✅ Functional Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
+9
-7
@@ -17,13 +17,15 @@ export default [
|
||||
route("companies/:id/invoices/:invoiceId", "routes/companies.$id.invoices.$invoiceId.tsx"),
|
||||
route("companies/:id/invoices/:invoiceId/edit", "routes/companies.$id.invoices.$invoiceId.edit.tsx"),
|
||||
route("companies/:id/reports", "routes/companies.$id.reports.tsx"),
|
||||
route("companies/:id/bilanzen", "routes/companies.$id.bilanzen.tsx"),
|
||||
route("companies/:id/ausgaben", "routes/companies.$id.ausgaben.tsx"),
|
||||
route("companies/:id/ausgaben/kategorien", "routes/companies.$id.ausgaben.kategorien.tsx"),
|
||||
route("companies/:id/einnahmen", "routes/companies.$id.einnahmen.tsx"),
|
||||
route("companies/:id/einnahmen/kategorien", "routes/companies.$id.einnahmen.kategorien.tsx"),
|
||||
route("companies/:id/anlagevermoegen", "routes/companies.$id.anlagevermoegen.tsx"),
|
||||
route("companies/:id/money", "routes/companies.$id.money.tsx"),
|
||||
layout("routes/companies.$id.buchhaltung.tsx", [
|
||||
route("companies/:id/buchhaltung/bilanzen", "routes/companies.$id.buchhaltung.bilanzen.tsx"),
|
||||
route("companies/:id/buchhaltung/ausgaben", "routes/companies.$id.buchhaltung.ausgaben.tsx"),
|
||||
route("companies/:id/buchhaltung/ausgaben/kategorien", "routes/companies.$id.buchhaltung.ausgaben.kategorien.tsx"),
|
||||
route("companies/:id/buchhaltung/einnahmen", "routes/companies.$id.buchhaltung.einnahmen.tsx"),
|
||||
route("companies/:id/buchhaltung/einnahmen/kategorien", "routes/companies.$id.buchhaltung.einnahmen.kategorien.tsx"),
|
||||
route("companies/:id/buchhaltung/anlagevermoegen", "routes/companies.$id.buchhaltung.anlagevermoegen.tsx"),
|
||||
route("companies/:id/buchhaltung/money", "routes/companies.$id.buchhaltung.money.tsx"),
|
||||
]),
|
||||
route("archiv", "routes/archiv.tsx"),
|
||||
route("settings/password", "routes/settings.password.tsx"),
|
||||
]),
|
||||
|
||||
+1
@@ -19,6 +19,7 @@ export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Buchhaltung", href: `/companies/${data.companyId}/buchhaltung/bilanzen` },
|
||||
{ label: "Anlagevermögen" },
|
||||
],
|
||||
};
|
||||
+3
-2
@@ -12,7 +12,8 @@ export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Betriebsausgaben", href: `/companies/${data.companyId}/ausgaben` },
|
||||
{ label: "Buchhaltung", href: `/companies/${data.companyId}/buchhaltung/bilanzen` },
|
||||
{ label: "Betriebsausgaben", href: `/companies/${data.companyId}/buchhaltung/ausgaben` },
|
||||
{ label: "Kategorien" },
|
||||
],
|
||||
};
|
||||
@@ -149,7 +150,7 @@ export default function AusgabenKategorienPage() {
|
||||
return (
|
||||
<div>
|
||||
<Link
|
||||
to={`/companies/${companyId}/ausgaben`}
|
||||
to={`/companies/${companyId}/buchhaltung/ausgaben`}
|
||||
className="inline-flex items-center gap-1 text-sm text-gray-500 hover:text-gray-700 mb-6"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" /> Zurück zu Betriebsausgaben
|
||||
+1
@@ -14,6 +14,7 @@ export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Buchhaltung", href: `/companies/${data.companyId}/buchhaltung/bilanzen` },
|
||||
{ label: "Betriebsausgaben" },
|
||||
],
|
||||
};
|
||||
+1
@@ -11,6 +11,7 @@ export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Buchhaltung", href: `/companies/${data.companyId}/buchhaltung/bilanzen` },
|
||||
{ label: "Bilanzen" },
|
||||
],
|
||||
};
|
||||
+3
-2
@@ -12,7 +12,8 @@ export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Sonstige Einnahmen", href: `/companies/${data.companyId}/einnahmen` },
|
||||
{ label: "Buchhaltung", href: `/companies/${data.companyId}/buchhaltung/bilanzen` },
|
||||
{ label: "Sonstige Einnahmen", href: `/companies/${data.companyId}/buchhaltung/einnahmen` },
|
||||
{ label: "Kategorien" },
|
||||
],
|
||||
};
|
||||
@@ -149,7 +150,7 @@ export default function EinnahmenKategorienPage() {
|
||||
return (
|
||||
<div>
|
||||
<Link
|
||||
to={`/companies/${companyId}/einnahmen`}
|
||||
to={`/companies/${companyId}/buchhaltung/einnahmen`}
|
||||
className="inline-flex items-center gap-1 text-sm text-gray-500 hover:text-gray-700 mb-6"
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" /> Zurück zu Sonstige Einnahmen
|
||||
+1
@@ -14,6 +14,7 @@ export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Buchhaltung", href: `/companies/${data.companyId}/buchhaltung/bilanzen` },
|
||||
{ label: "Sonstige Einnahmen" },
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
import { Outlet, useParams, useLocation, Link } from "react-router";
|
||||
import { requireUser } from "@/session.server";
|
||||
import { Scale, TrendingDown, TrendingUp, Landmark, DollarSign, ChevronRight } from "lucide-react";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
|
||||
export const handle = {
|
||||
breadcrumbs: (data: { companyId: string; companyName: string }) => [
|
||||
{ label: "Mandanten", href: "/companies" },
|
||||
{ label: data.companyName, href: `/companies/${data.companyId}` },
|
||||
{ label: "Buchhaltung" },
|
||||
],
|
||||
};
|
||||
|
||||
export async function loader({ request, params }: { request: Request; params: { id: string } }) {
|
||||
const user = await requireUser(request);
|
||||
// Verify company ownership
|
||||
const { PrismaClient } = await import("@prisma/client");
|
||||
const prisma = new PrismaClient();
|
||||
const company = await prisma.company.findFirst({
|
||||
where: { id: params.id, userId: user.id },
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
await prisma.$disconnect();
|
||||
if (!company) throw new Response("Not Found", { status: 404 });
|
||||
return { companyId: company.id, companyName: company.name };
|
||||
}
|
||||
|
||||
const accountingTabs = [
|
||||
{
|
||||
id: "bilanzen",
|
||||
label: "Bilanzen",
|
||||
icon: Scale,
|
||||
href: "bilanzen",
|
||||
color: "teal",
|
||||
},
|
||||
{
|
||||
id: "ausgaben",
|
||||
label: "Ausgaben",
|
||||
icon: TrendingDown,
|
||||
href: "ausgaben",
|
||||
color: "rose",
|
||||
},
|
||||
{
|
||||
id: "einnahmen",
|
||||
label: "Einnahmen",
|
||||
icon: TrendingUp,
|
||||
href: "einnahmen",
|
||||
color: "emerald",
|
||||
},
|
||||
{
|
||||
id: "anlagevermoegen",
|
||||
label: "Anlagevermögen",
|
||||
icon: Landmark,
|
||||
href: "anlagevermoegen",
|
||||
color: "violet",
|
||||
},
|
||||
{
|
||||
id: "money",
|
||||
label: "Finanzmittel",
|
||||
icon: DollarSign,
|
||||
href: "money",
|
||||
color: "cyan",
|
||||
},
|
||||
];
|
||||
|
||||
export default function BuchhaltungLayout() {
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const companyId = params.id;
|
||||
|
||||
// Determine which tab is active based on current pathname
|
||||
const pathSegments = location.pathname.split("/");
|
||||
const activeSegment = pathSegments[pathSegments.length - 1];
|
||||
const activeTa = accountingTabs.find((tab) => tab.href === activeSegment);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 shadow-sm">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-1">Buchhaltung</h2>
|
||||
<p className="text-sm text-gray-600">Verwaltung von Bilanzen, Ausgaben, Einnahmen und Vermögen</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-5 gap-4">
|
||||
{accountingTabs.map((tab) => {
|
||||
const Icon = tab.icon;
|
||||
const isActive = tab.href === activeSegment;
|
||||
const bgColor = `${tab.color}-50`;
|
||||
const borderColor = `${tab.color}-200`;
|
||||
const textColor = `${tab.color}-600`;
|
||||
const activeBg = `${tab.color}-100`;
|
||||
|
||||
return (
|
||||
<Link key={tab.id} to={`/companies/${companyId}/buchhaltung/${tab.href}`} className="block">
|
||||
<Card
|
||||
className={`hover:shadow-sm transition-all cursor-pointer ${
|
||||
isActive ? `border-${borderColor} bg-${activeBg}` : `hover:border-${borderColor}`
|
||||
}`}
|
||||
>
|
||||
<CardContent className="pt-6 pb-6 flex flex-col items-center gap-3 text-center">
|
||||
<div className={`p-3 rounded-lg bg-${bgColor}`}>
|
||||
<Icon className={`h-5 w-5 text-${textColor}`} />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">{tab.label}</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -233,53 +233,13 @@ export default function CompanyPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to={`/companies/${id}/bilanzen`} className="block">
|
||||
<Card className="hover:border-teal-200 hover:shadow-sm transition-all cursor-pointer">
|
||||
<Link to={`/companies/${id}/buchhaltung/bilanzen`} className="block">
|
||||
<Card className="hover:border-indigo-200 hover:shadow-sm transition-all cursor-pointer">
|
||||
<CardContent className="pt-4 pb-4 flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-teal-50">
|
||||
<Scale className="h-4 w-4 text-teal-600" />
|
||||
<div className="p-2 rounded-lg bg-indigo-50">
|
||||
<Briefcase className="h-4 w-4 text-indigo-600" />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">Bilanzen</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to={`/companies/${id}/ausgaben`} className="block">
|
||||
<Card className="hover:border-rose-200 hover:shadow-sm transition-all cursor-pointer">
|
||||
<CardContent className="pt-4 pb-4 flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-rose-50">
|
||||
<TrendingDown className="h-4 w-4 text-rose-600" />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">Ausgaben</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to={`/companies/${id}/einnahmen`} className="block">
|
||||
<Card className="hover:border-emerald-200 hover:shadow-sm transition-all cursor-pointer">
|
||||
<CardContent className="pt-4 pb-4 flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-emerald-50">
|
||||
<TrendingUp className="h-4 w-4 text-emerald-600" />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">Einnahmen</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to={`/companies/${id}/anlagevermoegen`} className="block">
|
||||
<Card className="hover:border-violet-200 hover:shadow-sm transition-all cursor-pointer">
|
||||
<CardContent className="pt-4 pb-4 flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-violet-50">
|
||||
<PackageSearch className="h-4 w-4 text-violet-600" />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">Anlagevermögen</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
<Link to={`/companies/${id}/money`} className="block">
|
||||
<Card className="hover:border-cyan-200 hover:shadow-sm transition-all cursor-pointer">
|
||||
<CardContent className="pt-4 pb-4 flex items-center gap-3">
|
||||
<div className="p-2 rounded-lg bg-cyan-50">
|
||||
<DollarSign className="h-4 w-4 text-cyan-600" />
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">Finanzmittel</span>
|
||||
<span className="text-sm font-medium text-gray-700">Buchhaltung</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user