feat: full studio build -- light theme, canvas thumbnails, i18n (fa/en)
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import Link from "next/link";
|
||||
import { Suspense } from "react";
|
||||
import { Sparkles } from "lucide-react";
|
||||
|
||||
import {
|
||||
DashboardPlanBadge,
|
||||
DashboardPlanBadgeSkeleton,
|
||||
} from "@/components/dashboard/DashboardPlanBadge";
|
||||
import { DashboardSidebarNav } from "@/components/dashboard/DashboardSidebarNav";
|
||||
|
||||
interface DashboardSidebarProps {
|
||||
userEmail: string;
|
||||
userName?: string | null;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
function getInitials(email: string, name?: string | null): string {
|
||||
if (name?.trim()) {
|
||||
const parts = name.trim().split(/\s+/);
|
||||
return parts
|
||||
.slice(0, 2)
|
||||
.map((part) => part[0]?.toUpperCase() ?? "")
|
||||
.join("");
|
||||
}
|
||||
|
||||
return email.slice(0, 2).toUpperCase();
|
||||
}
|
||||
|
||||
export function DashboardSidebar({
|
||||
userEmail,
|
||||
userName,
|
||||
userId,
|
||||
}: DashboardSidebarProps) {
|
||||
const initials = getInitials(userEmail, userName);
|
||||
|
||||
return (
|
||||
<aside className="flex h-full w-60 shrink-0 flex-col border-r border-gray-100 bg-white">
|
||||
<div className="border-b border-gray-100 px-4 py-5">
|
||||
<Link
|
||||
href="/"
|
||||
className="flex items-center gap-2 rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 focus-visible:ring-offset-2"
|
||||
>
|
||||
<span className="flex h-9 w-9 items-center justify-center rounded-lg bg-primary-600 text-white">
|
||||
<Sparkles className="h-5 w-5" aria-hidden />
|
||||
</span>
|
||||
<span className="font-heading text-lg font-bold text-neutral-900">
|
||||
FlatRender
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<DashboardSidebarNav />
|
||||
|
||||
<div className="border-t border-gray-100 p-4">
|
||||
<div className="mb-3 rounded-lg border border-gray-100 bg-neutral-50 p-3">
|
||||
<p className="text-xs font-medium uppercase tracking-wide text-neutral-500">
|
||||
Current plan
|
||||
</p>
|
||||
<Suspense fallback={<DashboardPlanBadgeSkeleton />}>
|
||||
<DashboardPlanBadge userId={userId} />
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-3 rounded-lg px-2 py-2">
|
||||
<div
|
||||
className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary-100 font-heading text-sm font-semibold text-primary-700"
|
||||
aria-hidden
|
||||
>
|
||||
{initials}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="truncate text-sm font-medium text-neutral-900">
|
||||
{userName ?? userEmail.split("@")[0]}
|
||||
</p>
|
||||
<p className="truncate text-xs text-neutral-500">{userEmail}</p>
|
||||
</div>
|
||||
</div>
|
||||
<form action="/auth/sign-out" method="post" className="mt-3">
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full rounded-lg px-3 py-2 text-left text-sm text-neutral-600 transition-colors hover:bg-neutral-50 hover:text-neutral-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 focus-visible:ring-offset-2"
|
||||
>
|
||||
Sign out
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user