feat(db): mesh data model — meshes, members, invites, audit log
- pgSchema "mesh" with 4 tables isolating the peer mesh domain - Enums: visibility, transport, tier, role - audit_log is metadata-only (E2E encryption enforced at broker/client) - Cascade on mesh delete, soft-delete via archivedAt/revokedAt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
29
apps/web/src/modules/admin/layout/details-list.tsx
Normal file
29
apps/web/src/modules/admin/layout/details-list.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { cn } from "@turbostarter/ui";
|
||||
|
||||
export const DetailsList = ({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"ul">) => {
|
||||
return (
|
||||
<ul
|
||||
className={cn(
|
||||
"xl:*:px- -m-px grid grid-cols-1 gap-y-8 @lg/details:grid-cols-2 @lg/details:gap-y-0 @3xl/details:grid-cols-3",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const DetailsListItem = ({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"li">) => (
|
||||
<li
|
||||
className={cn(
|
||||
"px-1 @lg/details:border @lg/details:px-6 @lg/details:py-8 @3xl/details:px-8 @3xl/details:py-10 [&:not(:first-child)]:-ms-px [&:not(:first-child)]:-mt-px",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
90
apps/web/src/modules/admin/layout/sidebar.tsx
Normal file
90
apps/web/src/modules/admin/layout/sidebar.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { memo } from "react";
|
||||
|
||||
import { isKey } from "@turbostarter/i18n";
|
||||
import { getTranslation } from "@turbostarter/i18n/server";
|
||||
import { Icons } from "@turbostarter/ui-web/icons";
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenuItem,
|
||||
SidebarRail,
|
||||
} from "@turbostarter/ui-web/sidebar";
|
||||
import { SidebarMenu } from "@turbostarter/ui-web/sidebar";
|
||||
import {
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
} from "@turbostarter/ui-web/sidebar";
|
||||
import { Sidebar } from "@turbostarter/ui-web/sidebar";
|
||||
|
||||
import { pathsConfig } from "~/config/paths";
|
||||
import { SidebarLink } from "~/modules/common/layout/dashboard/sidebar-link";
|
||||
import { TurboLink } from "~/modules/common/turbo-link";
|
||||
import { UserNavigation } from "~/modules/user/user-navigation";
|
||||
|
||||
import type { User } from "@turbostarter/auth";
|
||||
import type { Icon } from "@turbostarter/ui-web/icons";
|
||||
|
||||
interface AdminSidebarProps {
|
||||
readonly user: User;
|
||||
readonly menu: {
|
||||
label: string;
|
||||
items: {
|
||||
title: string;
|
||||
href: string;
|
||||
icon: Icon;
|
||||
}[];
|
||||
}[];
|
||||
}
|
||||
|
||||
export const AdminSidebar = memo<AdminSidebarProps>(async ({ user, menu }) => {
|
||||
const { t, i18n } = await getTranslation({ ns: "common" });
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarHeader>
|
||||
<TurboLink
|
||||
href={pathsConfig.index}
|
||||
className="flex items-center gap-3 p-2 transition-[padding] group-data-[collapsible=icon]:p-0.5"
|
||||
>
|
||||
<Icons.Logo className="text-primary h-8 transition-[width,height]" />
|
||||
<Icons.LogoText className="text-foreground h-4 group-data-[collapsible=icon]:hidden" />
|
||||
</TurboLink>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
{menu.map((group) => (
|
||||
<SidebarGroup key={group.label}>
|
||||
<SidebarGroupLabel className="uppercase">
|
||||
{isKey(group.label, i18n, "common")
|
||||
? t(group.label)
|
||||
: group.label}
|
||||
</SidebarGroupLabel>
|
||||
<SidebarMenu>
|
||||
{group.items.map((item) => {
|
||||
const title = isKey(item.title, i18n, "common")
|
||||
? t(item.title)
|
||||
: item.title;
|
||||
return (
|
||||
<SidebarMenuItem key={item.href}>
|
||||
<SidebarLink href={item.href} tooltip={title}>
|
||||
<item.icon />
|
||||
<span>{title}</span>
|
||||
</SidebarLink>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
</SidebarMenu>
|
||||
</SidebarGroup>
|
||||
))}
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<UserNavigation user={user} />
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarFooter>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user