feat(dashboard): personalized header + reuse dashboard-2 components
- /dashboard now a server component:
* fetches active user + active tenant settings via getActiveContext()
* redirects to /onboarding if user has no tenant yet
* header shows companyName + 'Hoş geldiniz, {firstName}' + Turkish description
- Body reuses dashboard-2 components (Metrics/Sales/Revenue/Transactions/
TopProducts/CustomerInsights/QuickActions). Mock data for now; will be
swapped for live Appwrite queries as modules ship.
- New lib/appwrite/active-context.ts: getActiveContext() returns
{ user, tenantId, settings } for any server component / action.
- Made schema.ts SDK-agnostic by replacing Models.Document import with a
local SystemRow type ({ $id, $createdAt, $updatedAt, $permissions, ... }).
Avoids type clashes between appwrite (browser) and node-appwrite (server).
This commit is contained in:
@@ -1,35 +1,51 @@
|
||||
import { ChartAreaInteractive } from "./components/chart-area-interactive"
|
||||
import { DataTable } from "./components/data-table"
|
||||
import { SectionCards } from "./components/section-cards"
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import data from "./data/data.json"
|
||||
import pastPerformanceData from "./data/past-performance-data.json"
|
||||
import keyPersonnelData from "./data/key-personnel-data.json"
|
||||
import focusDocumentsData from "./data/focus-documents-data.json"
|
||||
import { getActiveContext } from "@/lib/appwrite/active-context";
|
||||
import { CustomerInsights } from "../dashboard-2/components/customer-insights";
|
||||
import { MetricsOverview } from "../dashboard-2/components/metrics-overview";
|
||||
import { QuickActions } from "../dashboard-2/components/quick-actions";
|
||||
import { RecentTransactions } from "../dashboard-2/components/recent-transactions";
|
||||
import { RevenueBreakdown } from "../dashboard-2/components/revenue-breakdown";
|
||||
import { SalesChart } from "../dashboard-2/components/sales-chart";
|
||||
import { TopProducts } from "../dashboard-2/components/top-products";
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const ctx = await getActiveContext();
|
||||
if (!ctx) redirect("/onboarding");
|
||||
|
||||
const firstName = ctx.user.name?.split(" ")[0] ?? "";
|
||||
const companyName = ctx.settings?.companyName ?? "Çalışma alanı";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<>
|
||||
{/* Page Title and Description */}
|
||||
<div className="px-4 lg:px-6">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h1 className="text-2xl font-bold tracking-tight">Dashboard</h1>
|
||||
<p className="text-muted-foreground">Welcome to your admin dashboard</p>
|
||||
<div className="flex-1 space-y-6 px-6 pt-0">
|
||||
<div className="flex flex-col justify-between gap-4 md:flex-row md:items-center md:gap-6">
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-muted-foreground text-sm">{companyName}</p>
|
||||
<h1 className="text-2xl font-bold tracking-tight">
|
||||
{firstName ? `Hoş geldiniz, ${firstName}` : "Genel bakış"}
|
||||
</h1>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
İşletmenizin temel metriklerini ve son hareketleri buradan takip edin.
|
||||
</p>
|
||||
</div>
|
||||
<QuickActions />
|
||||
</div>
|
||||
|
||||
<div className="@container/main px-4 lg:px-6 space-y-6">
|
||||
<SectionCards />
|
||||
<ChartAreaInteractive />
|
||||
<div className="@container/main space-y-6">
|
||||
<MetricsOverview />
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 @5xl:grid-cols-2">
|
||||
<SalesChart />
|
||||
<RevenueBreakdown />
|
||||
</div>
|
||||
<div className="@container/main">
|
||||
<DataTable
|
||||
data={data}
|
||||
pastPerformanceData={pastPerformanceData}
|
||||
keyPersonnelData={keyPersonnelData}
|
||||
focusDocumentsData={focusDocumentsData}
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 @5xl:grid-cols-2">
|
||||
<RecentTransactions />
|
||||
<TopProducts />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
<CustomerInsights />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import "server-only";
|
||||
|
||||
import { Query } from "node-appwrite";
|
||||
|
||||
import { createAdminClient, getCurrentUser } from "./server";
|
||||
import { DATABASE_ID, TABLES, type TenantSettings } from "./schema";
|
||||
import { getActiveTenantId, getUserTeams } from "./tenant";
|
||||
|
||||
export type ActiveContext = {
|
||||
user: { id: string; name: string; email: string };
|
||||
tenantId: string;
|
||||
settings: TenantSettings | null;
|
||||
};
|
||||
|
||||
export async function getActiveContext(): Promise<ActiveContext | null> {
|
||||
const user = await getCurrentUser();
|
||||
if (!user) return null;
|
||||
|
||||
let tenantId = await getActiveTenantId();
|
||||
if (!tenantId) {
|
||||
const teams = await getUserTeams();
|
||||
tenantId = teams?.teams[0]?.$id ?? null;
|
||||
}
|
||||
if (!tenantId) return null;
|
||||
|
||||
let settings: TenantSettings | null = null;
|
||||
try {
|
||||
const { tablesDB } = createAdminClient();
|
||||
const result = await tablesDB.listRows({
|
||||
databaseId: DATABASE_ID,
|
||||
tableId: TABLES.tenantSettings,
|
||||
queries: [Query.equal("tenantId", tenantId), Query.limit(1)],
|
||||
});
|
||||
settings = (result.rows[0] as unknown as TenantSettings) ?? null;
|
||||
} catch {
|
||||
settings = null;
|
||||
}
|
||||
|
||||
return {
|
||||
user: { id: user.$id, name: user.name, email: user.email },
|
||||
tenantId,
|
||||
settings,
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import type { Models } from "appwrite";
|
||||
|
||||
export const DATABASE_ID = "isletmem";
|
||||
|
||||
export const TABLES = {
|
||||
@@ -18,7 +16,17 @@ export const TABLES = {
|
||||
|
||||
export type TableId = (typeof TABLES)[keyof typeof TABLES];
|
||||
|
||||
type Row = Models.Document;
|
||||
export type SystemRow = {
|
||||
$id: string;
|
||||
$createdAt: string;
|
||||
$updatedAt: string;
|
||||
$permissions: string[];
|
||||
$databaseId?: string;
|
||||
$tableId?: string;
|
||||
$sequence?: number;
|
||||
};
|
||||
|
||||
type Row = SystemRow;
|
||||
|
||||
export type TenantRole = "owner" | "admin" | "member";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user