Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/cms/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const nextConfig: NextConfig = {
reactCompiler: true,
experimental: {
optimizePackageImports: ["@phosphor-icons/react"],
staleTimes: {
dynamic: 60,
},
},
turbopack: {
root: path.resolve(__dirname, "../.."),
Expand Down Expand Up @@ -48,6 +51,10 @@ const nextConfig: NextConfig = {
protocol: "https",
hostname: "media.marblecms.com",
},
{
protocol: "https",
hostname: "cdn.marblecms.com",
},
],
qualities: [20, 40, 60, 80, 100],
},
Expand Down
134 changes: 134 additions & 0 deletions apps/cms/src/app/(main)/[workspace]/(dashboard)/(home)/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Skeleton } from "@marble/ui/components/skeleton";
import { DashboardBody } from "@/components/layout/wrapper";

const apiBars = [
{ id: "api-1", height: "h-[35%]" },
{ id: "api-2", height: "h-[55%]" },
{ id: "api-3", height: "h-[40%]" },
{ id: "api-4", height: "h-[70%]" },
{ id: "api-5", height: "h-[50%]" },
{ id: "api-6", height: "h-[80%]" },
{ id: "api-7", height: "h-[60%]" },
{ id: "api-8", height: "h-[45%]" },
{ id: "api-9", height: "h-[90%]" },
{ id: "api-10", height: "h-[65%]" },
{ id: "api-11", height: "h-[50%]" },
{ id: "api-12", height: "h-[75%]" },
{ id: "api-13", height: "h-[40%]" },
{ id: "api-14", height: "h-[85%]" },
{ id: "api-15", height: "h-[55%]" },
{ id: "api-16", height: "h-[60%]" },
{ id: "api-17", height: "h-[70%]" },
{ id: "api-18", height: "h-[45%]" },
{ id: "api-19", height: "h-[95%]" },
{ id: "api-20", height: "h-[50%]" },
{ id: "api-21", height: "h-[65%]" },
{ id: "api-22", height: "h-[80%]" },
{ id: "api-23", height: "h-[55%]" },
{ id: "api-24", height: "h-[70%]" },
];

const webhookBars = [
{ id: "wh-1", height: "h-[30%]" },
{ id: "wh-2", height: "h-[60%]" },
{ id: "wh-3", height: "h-[45%]" },
{ id: "wh-4", height: "h-[75%]" },
{ id: "wh-5", height: "h-[55%]" },
{ id: "wh-6", height: "h-[85%]" },
{ id: "wh-7", height: "h-[40%]" },
{ id: "wh-8", height: "h-[65%]" },
{ id: "wh-9", height: "h-[50%]" },
{ id: "wh-10", height: "h-[70%]" },
{ id: "wh-11", height: "h-[35%]" },
{ id: "wh-12", height: "h-[60%]" },
];

const mediaRows = ["media-1", "media-2", "media-3"];

const activityWeeks = Array.from({ length: 53 }, (_, i) => `week-${i}`);
const activityDays = ["d-0", "d-1", "d-2", "d-3", "d-4", "d-5", "d-6"];

function CardHeaderSkeleton() {
return (
<div className="gap-0 px-4 pt-4">
<div className="flex flex-col gap-1">
<div className="flex items-center justify-between gap-4">
<Skeleton className="h-6 w-40" />
<Skeleton className="h-5 w-24 rounded-full" />
</div>
<Skeleton className="mt-1 h-6 w-28" />
</div>
</div>
);
}

export default function Loading() {
return (
<DashboardBody className="flex flex-col gap-8 pt-10 pb-16" size="compact">
<div className="flex w-full flex-col gap-6 md:grid md:gap-x-10 md:gap-y-8">
<div className="col-span-full flex flex-col gap-4 rounded-[20px] bg-surface p-2">
<CardHeaderSkeleton />
<div className="flex h-84 items-end justify-between gap-2 rounded-[12px] bg-background p-4 shadow-xs">
{apiBars.map((bar) => (
<Skeleton
className={`w-full rounded-t-md ${bar.height}`}
key={bar.id}
/>
))}
</div>
</div>

<div className="flex flex-col gap-6 lg:grid lg:grid-cols-2 lg:gap-8">
<div className="flex flex-col gap-4 rounded-[20px] bg-surface p-2">
<CardHeaderSkeleton />
<div className="flex h-60 items-end justify-between gap-2 rounded-[12px] bg-background p-4 shadow-xs">
{webhookBars.map((bar) => (
<Skeleton
className={`w-full rounded-t-md ${bar.height}`}
key={bar.id}
/>
))}
</div>
</div>

<div className="flex flex-col gap-4 rounded-[20px] bg-surface p-2">
<CardHeaderSkeleton />
<ul className="flex h-60 flex-col gap-2 overflow-hidden rounded-[12px]">
{mediaRows.map((id) => (
<li
className="flex items-center gap-4 rounded-[18px] bg-background p-2.5"
key={id}
>
<Skeleton className="size-20 shrink-0 rounded-[8px]" />
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-40" />
<Skeleton className="h-3 w-20" />
<Skeleton className="h-3 w-24" />
</div>
</li>
))}
</ul>
</div>
</div>

<div className="flex flex-col gap-4 rounded-[20px] bg-surface p-2">
<CardHeaderSkeleton />
<div className="rounded-[12px] bg-background p-4 shadow-xs">
<div className="flex gap-[3px] overflow-hidden">
{activityWeeks.map((week) => (
<div className="flex flex-col gap-[3px]" key={week}>
{activityDays.map((day) => (
<Skeleton
className="size-[13px] rounded-[2px]"
key={`${week}-${day}`}
/>
))}
</div>
))}
</div>
</div>
</div>
</div>
</DashboardBody>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { QUERY_KEYS } from "@/lib/queries/keys";
import { useWorkspace } from "@/providers/workspace";
import type { UsageDashboardData } from "@/types/dashboard";

export default function PageClient() {
export default function PageClient({
initialUsage,
}: {
initialUsage?: UsageDashboardData;
}) {
const workspaceId = useWorkspaceId();
const { isFetchingWorkspace } = useWorkspace();

Expand All @@ -28,6 +32,7 @@ export default function PageClient() {
return response.json();
},
enabled: Boolean(workspaceId) && !isFetchingWorkspace,
initialData: initialUsage,
staleTime: 1000 * 60 * 10,
});

Expand Down
14 changes: 12 additions & 2 deletions apps/cms/src/app/(main)/[workspace]/(dashboard)/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { notFound } from "next/navigation";
import { getDashboardUsageMetrics } from "@/lib/queries/dashboard/usage";
import { getDashboardWorkspaceId } from "@/lib/queries/dashboard/workspace";
import PageClient from "./page-client";

export const metadata = {
title: "Home",
description: "Workspace overview and metrics",
};

async function Page() {
return <PageClient />;
async function Page({ params }: { params: Promise<{ workspace: string }> }) {
const { workspace } = await params;
const workspaceId = await getDashboardWorkspaceId(workspace);
if (!workspaceId) {
notFound();
}

const usage = await getDashboardUsageMetrics(workspaceId);
return <PageClient initialUsage={usage} />;
}

export default Page;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ResourceTableSkeleton } from "@/components/shared/resource-table-skeleton";

export default function Loading() {
return <ResourceTableSkeleton />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { QUERY_KEYS } from "@/lib/queries/keys";
import { useWorkspace } from "@/providers/workspace";
import type { Author } from "@/types/author";

function PageClient() {
function PageClient({ initialAuthors }: { initialAuthors?: Author[] }) {
const workspaceId = useWorkspaceId();
const { isFetchingWorkspace } = useWorkspace();

Expand All @@ -31,9 +31,13 @@ function PageClient() {
toast.error(
error instanceof Error ? error.message : "Failed to fetch authors"
);
throw error instanceof Error
? error
: new Error("Failed to fetch authors");
}
},
enabled: Boolean(workspaceId) && !isFetchingWorkspace,
initialData: initialAuthors,
});

if (isFetchingWorkspace || !workspaceId || isLoading) {
Expand Down
14 changes: 12 additions & 2 deletions apps/cms/src/app/(main)/[workspace]/(dashboard)/authors/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { getDashboardAuthors } from "@/lib/queries/dashboard/authors";
import { getDashboardWorkspaceId } from "@/lib/queries/dashboard/workspace";
import PageClient from "./page-client";

export const metadata: Metadata = {
title: "Authors",
description: "Manage your authors",
};

async function Page() {
return <PageClient />;
async function Page({ params }: { params: Promise<{ workspace: string }> }) {
const { workspace } = await params;
const workspaceId = await getDashboardWorkspaceId(workspace);
if (!workspaceId) {
notFound();
}

const authors = await getDashboardAuthors(workspaceId);
return <PageClient initialAuthors={authors} />;
}

export default Page;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ResourceTableSkeleton } from "@/components/shared/resource-table-skeleton";

export default function Loading() {
return <ResourceTableSkeleton />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const CategoryModal = dynamic(() =>
)
);

function PageClient() {
function PageClient({ initialCategories }: { initialCategories?: Category[] }) {
const workspaceId = useWorkspaceId();
const { isFetchingWorkspace } = useWorkspace();
const [showCreateModal, setShowCreateModal] = useState(false);
Expand All @@ -45,9 +45,13 @@ function PageClient() {
toast.error(
error instanceof Error ? error.message : "Failed to fetch categories"
);
throw error instanceof Error
? error
: new Error("Failed to fetch categories");
}
},
enabled: !!workspaceId && !isFetchingWorkspace,
initialData: initialCategories,
});

if (isFetchingWorkspace || !workspaceId || isLoading) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { notFound } from "next/navigation";
import { getDashboardCategories } from "@/lib/queries/dashboard/taxonomy";
import { getDashboardWorkspaceId } from "@/lib/queries/dashboard/workspace";
import PageClient from "./page-client";

export const metadata = {
title: "Categories",
description: "Manage your categories",
};

function Page() {
return <PageClient />;
async function Page({ params }: { params: Promise<{ workspace: string }> }) {
const { workspace } = await params;
const workspaceId = await getDashboardWorkspaceId(workspace);
if (!workspaceId) {
notFound();
}

const categories = await getDashboardCategories(workspaceId);
return <PageClient initialCategories={categories} />;
}

export default Page;
5 changes: 0 additions & 5 deletions apps/cms/src/app/(main)/[workspace]/(dashboard)/loading.tsx

This file was deleted.

Loading
Loading