feat: add admin user management page and support authroizeOnly for nav item
- Introduced a new admin section with user management capabilities, including a dedicated AdminUsersPage. - Updated localization files to support new admin titles in English and Chinese. - Added routing for the admin users page and integrated it into the sidebar configuration. - Created necessary layout and loading components for the admin section. - Implemented a data structure for user management, enhancing the overall admin functionality.
This commit is contained in:
parent
dd6fb4df85
commit
6e1189afc4
@ -436,6 +436,12 @@
|
||||
"dashboard": {
|
||||
"title": "Dashboard"
|
||||
},
|
||||
"admin": {
|
||||
"title": "Admin",
|
||||
"users": {
|
||||
"title": "Users"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"profile": {
|
||||
|
@ -437,6 +437,12 @@
|
||||
"dashboard": {
|
||||
"title": "仪表盘"
|
||||
},
|
||||
"admin": {
|
||||
"title": "系统管理",
|
||||
"users": {
|
||||
"title": "用户管理"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "设置",
|
||||
"profile": {
|
||||
|
46
src/app/[locale]/(protected)/admin/users/page.tsx
Normal file
46
src/app/[locale]/(protected)/admin/users/page.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { ChartAreaInteractive } from '@/components/dashboard/chart-area-interactive';
|
||||
import { DashboardHeader } from '@/components/dashboard/dashboard-header';
|
||||
import { DataTable } from '@/components/dashboard/data-table';
|
||||
import { SectionCards } from '@/components/dashboard/section-cards';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
import data from "./data.json";
|
||||
|
||||
/**
|
||||
* Admin users page
|
||||
*
|
||||
* NOTICE: This is a demo page for the admin, no real data is used,
|
||||
* we will show real data in the future
|
||||
*/
|
||||
export default function AdminUsersPage() {
|
||||
const t = useTranslations();
|
||||
|
||||
const breadcrumbs = [
|
||||
{
|
||||
label: t('Dashboard.admin.title'),
|
||||
isCurrentPage: false,
|
||||
},
|
||||
{
|
||||
label: t('Dashboard.admin.users.title'),
|
||||
isCurrentPage: true,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<DashboardHeader breadcrumbs={breadcrumbs} />
|
||||
|
||||
<div className="flex flex-1 flex-col">
|
||||
<div className="@container/main flex flex-1 flex-col gap-2">
|
||||
<div className="flex flex-col gap-4 py-4 md:gap-6 md:py-6">
|
||||
<SectionCards />
|
||||
<div className="px-4 lg:px-6">
|
||||
<ChartAreaInteractive />
|
||||
</div>
|
||||
<DataTable data={data} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
614
src/app/[locale]/(protected)/dashboard/data.json
Normal file
614
src/app/[locale]/(protected)/dashboard/data.json
Normal file
@ -0,0 +1,614 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"header": "Cover page",
|
||||
"type": "Cover page",
|
||||
"status": "In Process",
|
||||
"target": "18",
|
||||
"limit": "5",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"header": "Table of contents",
|
||||
"type": "Table of contents",
|
||||
"status": "Done",
|
||||
"target": "29",
|
||||
"limit": "24",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"header": "Executive summary",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "10",
|
||||
"limit": "13",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"header": "Technical approach",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "27",
|
||||
"limit": "23",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"header": "Design",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "2",
|
||||
"limit": "16",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"header": "Capabilities",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "20",
|
||||
"limit": "8",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"header": "Integration with existing systems",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "21",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"header": "Innovation and Advantages",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "25",
|
||||
"limit": "26",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"header": "Overview of EMR's Innovative Solutions",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "7",
|
||||
"limit": "23",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"header": "Advanced Algorithms and Machine Learning",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "30",
|
||||
"limit": "28",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"header": "Adaptive Communication Protocols",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "9",
|
||||
"limit": "31",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"header": "Advantages Over Current Technologies",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "12",
|
||||
"limit": "0",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"header": "Past Performance",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "33",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"header": "Customer Feedback and Satisfaction Levels",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "15",
|
||||
"limit": "34",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"header": "Implementation Challenges and Solutions",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "3",
|
||||
"limit": "35",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"header": "Security Measures and Data Protection Policies",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "6",
|
||||
"limit": "36",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"header": "Scalability and Future Proofing",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "4",
|
||||
"limit": "37",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"header": "Cost-Benefit Analysis",
|
||||
"type": "Plain language",
|
||||
"status": "Done",
|
||||
"target": "14",
|
||||
"limit": "38",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"header": "User Training and Onboarding Experience",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "17",
|
||||
"limit": "39",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"header": "Future Development Roadmap",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "11",
|
||||
"limit": "40",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"header": "System Architecture Overview",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "24",
|
||||
"limit": "18",
|
||||
"reviewer": "Maya Johnson"
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"header": "Risk Management Plan",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "15",
|
||||
"limit": "22",
|
||||
"reviewer": "Carlos Rodriguez"
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"header": "Compliance Documentation",
|
||||
"type": "Legal",
|
||||
"status": "In Process",
|
||||
"target": "31",
|
||||
"limit": "27",
|
||||
"reviewer": "Sarah Chen"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"header": "API Documentation",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "8",
|
||||
"limit": "12",
|
||||
"reviewer": "Raj Patel"
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"header": "User Interface Mockups",
|
||||
"type": "Visual",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "25",
|
||||
"reviewer": "Leila Ahmadi"
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"header": "Database Schema",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "20",
|
||||
"reviewer": "Thomas Wilson"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"header": "Testing Methodology",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "17",
|
||||
"limit": "14",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"header": "Deployment Strategy",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "26",
|
||||
"limit": "30",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"header": "Budget Breakdown",
|
||||
"type": "Financial",
|
||||
"status": "In Process",
|
||||
"target": "13",
|
||||
"limit": "16",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"header": "Market Analysis",
|
||||
"type": "Research",
|
||||
"status": "Done",
|
||||
"target": "29",
|
||||
"limit": "32",
|
||||
"reviewer": "Sophia Martinez"
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"header": "Competitor Comparison",
|
||||
"type": "Research",
|
||||
"status": "In Process",
|
||||
"target": "21",
|
||||
"limit": "19",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"header": "Maintenance Plan",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "16",
|
||||
"limit": "23",
|
||||
"reviewer": "Alex Thompson"
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"header": "User Personas",
|
||||
"type": "Research",
|
||||
"status": "In Process",
|
||||
"target": "27",
|
||||
"limit": "24",
|
||||
"reviewer": "Nina Patel"
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"header": "Accessibility Compliance",
|
||||
"type": "Legal",
|
||||
"status": "Done",
|
||||
"target": "18",
|
||||
"limit": "21",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"header": "Performance Metrics",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "23",
|
||||
"limit": "26",
|
||||
"reviewer": "David Kim"
|
||||
},
|
||||
{
|
||||
"id": 36,
|
||||
"header": "Disaster Recovery Plan",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "14",
|
||||
"limit": "17",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"header": "Third-party Integrations",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "25",
|
||||
"limit": "28",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 38,
|
||||
"header": "User Feedback Summary",
|
||||
"type": "Research",
|
||||
"status": "Done",
|
||||
"target": "20",
|
||||
"limit": "15",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"header": "Localization Strategy",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "12",
|
||||
"limit": "19",
|
||||
"reviewer": "Maria Garcia"
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"header": "Mobile Compatibility",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "28",
|
||||
"limit": "31",
|
||||
"reviewer": "James Wilson"
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"header": "Data Migration Plan",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "22",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 42,
|
||||
"header": "Quality Assurance Protocols",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "30",
|
||||
"limit": "33",
|
||||
"reviewer": "Priya Singh"
|
||||
},
|
||||
{
|
||||
"id": 43,
|
||||
"header": "Stakeholder Analysis",
|
||||
"type": "Research",
|
||||
"status": "In Process",
|
||||
"target": "11",
|
||||
"limit": "14",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"header": "Environmental Impact Assessment",
|
||||
"type": "Research",
|
||||
"status": "Done",
|
||||
"target": "24",
|
||||
"limit": "27",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"header": "Intellectual Property Rights",
|
||||
"type": "Legal",
|
||||
"status": "In Process",
|
||||
"target": "17",
|
||||
"limit": "20",
|
||||
"reviewer": "Sarah Johnson"
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"header": "Customer Support Framework",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "25",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"header": "Version Control Strategy",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "15",
|
||||
"limit": "18",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"header": "Continuous Integration Pipeline",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "26",
|
||||
"limit": "29",
|
||||
"reviewer": "Michael Chen"
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"header": "Regulatory Compliance",
|
||||
"type": "Legal",
|
||||
"status": "In Process",
|
||||
"target": "13",
|
||||
"limit": "16",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 50,
|
||||
"header": "User Authentication System",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "28",
|
||||
"limit": "31",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"header": "Data Analytics Framework",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "21",
|
||||
"limit": "24",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"header": "Cloud Infrastructure",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "16",
|
||||
"limit": "19",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 53,
|
||||
"header": "Network Security Measures",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "29",
|
||||
"limit": "32",
|
||||
"reviewer": "Lisa Wong"
|
||||
},
|
||||
{
|
||||
"id": 54,
|
||||
"header": "Project Timeline",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "14",
|
||||
"limit": "17",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 55,
|
||||
"header": "Resource Allocation",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "27",
|
||||
"limit": "30",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 56,
|
||||
"header": "Team Structure and Roles",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "20",
|
||||
"limit": "23",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 57,
|
||||
"header": "Communication Protocols",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "15",
|
||||
"limit": "18",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 58,
|
||||
"header": "Success Metrics",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "30",
|
||||
"limit": "33",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 59,
|
||||
"header": "Internationalization Support",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "23",
|
||||
"limit": "26",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 60,
|
||||
"header": "Backup and Recovery Procedures",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "18",
|
||||
"limit": "21",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 61,
|
||||
"header": "Monitoring and Alerting System",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "25",
|
||||
"limit": "28",
|
||||
"reviewer": "Daniel Park"
|
||||
},
|
||||
{
|
||||
"id": 62,
|
||||
"header": "Code Review Guidelines",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "12",
|
||||
"limit": "15",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 63,
|
||||
"header": "Documentation Standards",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "27",
|
||||
"limit": "30",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 64,
|
||||
"header": "Release Management Process",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "25",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 65,
|
||||
"header": "Feature Prioritization Matrix",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "22",
|
||||
"reviewer": "Emma Davis"
|
||||
},
|
||||
{
|
||||
"id": 66,
|
||||
"header": "Technical Debt Assessment",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "24",
|
||||
"limit": "27",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 67,
|
||||
"header": "Capacity Planning",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "21",
|
||||
"limit": "24",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 68,
|
||||
"header": "Service Level Agreements",
|
||||
"type": "Legal",
|
||||
"status": "Done",
|
||||
"target": "26",
|
||||
"limit": "29",
|
||||
"reviewer": "Assign reviewer"
|
||||
}
|
||||
]
|
@ -9,7 +9,8 @@ import data from "./data.json";
|
||||
/**
|
||||
* Dashboard page
|
||||
*
|
||||
* This is a demo page for the dashboard, no real data is used
|
||||
* NOTICE: This is a demo page for the dashboard, no real data is used,
|
||||
* we will show real data in the future
|
||||
*/
|
||||
export default function DashboardPage() {
|
||||
const t = useTranslations();
|
@ -29,6 +29,12 @@ export function DashboardSidebar({ ...props }: React.ComponentProps<typeof Sideb
|
||||
const { data: session, isPending } = authClient.useSession();
|
||||
const currentUser = session?.user;
|
||||
// console.log('sidebar currentUser:', currentUser);
|
||||
const filteredSidebarLinks = sidebarLinks.filter((link) => {
|
||||
if (link.authorizeOnly) {
|
||||
return link.authorizeOnly.includes(currentUser?.role || '');
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon" {...props}>
|
||||
@ -51,7 +57,7 @@ export function DashboardSidebar({ ...props }: React.ComponentProps<typeof Sideb
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent>
|
||||
<SidebarMain items={sidebarLinks} />
|
||||
<SidebarMain items={filteredSidebarLinks} />
|
||||
</SidebarContent>
|
||||
|
||||
<SidebarFooter className="flex flex-col gap-4">
|
||||
|
@ -69,28 +69,28 @@ export function getNavbarConfig(): NestedMenuItem[] {
|
||||
{
|
||||
title: t('ai.items.text.title'),
|
||||
description: t('ai.items.text.description'),
|
||||
icon: <SquarePenIcon className="site-4 shrink-0" />,
|
||||
icon: <SquarePenIcon className="size-4 shrink-0" />,
|
||||
href: Routes.AIText,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('ai.items.image.title'),
|
||||
description: t('ai.items.image.description'),
|
||||
icon: <ImageIcon className="site-4 shrink-0" />,
|
||||
icon: <ImageIcon className="size-4 shrink-0" />,
|
||||
href: Routes.AIImage,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('ai.items.video.title'),
|
||||
description: t('ai.items.video.description'),
|
||||
icon: <FilmIcon className="site-4 shrink-0" />,
|
||||
icon: <FilmIcon className="size-4 shrink-0" />,
|
||||
href: Routes.AIVideo,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('ai.items.audio.title'),
|
||||
description: t('ai.items.audio.description'),
|
||||
icon: <AudioLinesIcon className="site-4 shrink-0" />,
|
||||
icon: <AudioLinesIcon className="size-4 shrink-0" />,
|
||||
href: Routes.AIAudio,
|
||||
external: false,
|
||||
},
|
||||
@ -102,56 +102,56 @@ export function getNavbarConfig(): NestedMenuItem[] {
|
||||
{
|
||||
title: t('pages.items.about.title'),
|
||||
description: t('pages.items.about.description'),
|
||||
icon: <BuildingIcon className="site-4 shrink-0" />,
|
||||
icon: <BuildingIcon className="size-4 shrink-0" />,
|
||||
href: Routes.About,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.contact.title'),
|
||||
description: t('pages.items.contact.description'),
|
||||
icon: <MailIcon className="site-4 shrink-0" />,
|
||||
icon: <MailIcon className="size-4 shrink-0" />,
|
||||
href: Routes.Contact,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.waitlist.title'),
|
||||
description: t('pages.items.waitlist.description'),
|
||||
icon: <MailboxIcon className="site-4 shrink-0" />,
|
||||
icon: <MailboxIcon className="size-4 shrink-0" />,
|
||||
href: Routes.Waitlist,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.roadmap.title'),
|
||||
description: t('pages.items.roadmap.description'),
|
||||
icon: <SquareKanbanIcon className="site-4 shrink-0" />,
|
||||
icon: <SquareKanbanIcon className="size-4 shrink-0" />,
|
||||
href: Routes.Roadmap,
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.changelog.title'),
|
||||
description: t('pages.items.changelog.description'),
|
||||
icon: <ListChecksIcon className="site-4 shrink-0" />,
|
||||
icon: <ListChecksIcon className="size-4 shrink-0" />,
|
||||
href: Routes.Changelog,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.cookiePolicy.title'),
|
||||
description: t('pages.items.cookiePolicy.description'),
|
||||
icon: <CookieIcon className="site-4 shrink-0" />,
|
||||
icon: <CookieIcon className="size-4 shrink-0" />,
|
||||
href: Routes.CookiePolicy,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.privacyPolicy.title'),
|
||||
description: t('pages.items.privacyPolicy.description'),
|
||||
icon: <ShieldCheckIcon className="site-4 shrink-0" />,
|
||||
icon: <ShieldCheckIcon className="size-4 shrink-0" />,
|
||||
href: Routes.PrivacyPolicy,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('pages.items.termsOfService.title'),
|
||||
description: t('pages.items.termsOfService.description'),
|
||||
icon: <FileTextIcon className="site-4 shrink-0" />,
|
||||
icon: <FileTextIcon className="size-4 shrink-0" />,
|
||||
href: Routes.TermsOfService,
|
||||
external: false,
|
||||
},
|
||||
@ -162,91 +162,91 @@ export function getNavbarConfig(): NestedMenuItem[] {
|
||||
items: [
|
||||
{
|
||||
title: t('blocks.items.hero.title'),
|
||||
icon: <FlameIcon className="site-4 shrink-0" />,
|
||||
icon: <FlameIcon className="size-4 shrink-0" />,
|
||||
href: Routes.HeroBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.logo.title'),
|
||||
icon: <SquareCodeIcon className="site-4 shrink-0" />,
|
||||
icon: <SquareCodeIcon className="size-4 shrink-0" />,
|
||||
href: Routes.LogoBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.features.title'),
|
||||
icon: <WandSparklesIcon className="site-4 shrink-0" />,
|
||||
icon: <WandSparklesIcon className="size-4 shrink-0" />,
|
||||
href: Routes.FeaturesBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.content.title'),
|
||||
icon: <NewspaperIcon className="site-4 shrink-0" />,
|
||||
icon: <NewspaperIcon className="size-4 shrink-0" />,
|
||||
href: Routes.ContentBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.stats.title'),
|
||||
icon: <ChartNoAxesCombinedIcon className="site-4 shrink-0" />,
|
||||
icon: <ChartNoAxesCombinedIcon className="size-4 shrink-0" />,
|
||||
href: Routes.StatsBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.team.title'),
|
||||
icon: <UsersIcon className="site-4 shrink-0" />,
|
||||
icon: <UsersIcon className="size-4 shrink-0" />,
|
||||
href: Routes.TeamBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.testimonials.title'),
|
||||
icon: <ThumbsUpIcon className="site-4 shrink-0" />,
|
||||
icon: <ThumbsUpIcon className="size-4 shrink-0" />,
|
||||
href: Routes.TestimonialsBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.callToAction.title'),
|
||||
icon: <RocketIcon className="site-4 shrink-0" />,
|
||||
icon: <RocketIcon className="size-4 shrink-0" />,
|
||||
href: Routes.CallToActionBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.footer.title'),
|
||||
icon: <FootprintsIcon className="site-4 shrink-0" />,
|
||||
icon: <FootprintsIcon className="size-4 shrink-0" />,
|
||||
href: Routes.FooterBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.pricing.title'),
|
||||
icon: <CircleDollarSignIcon className="site-4 shrink-0" />,
|
||||
icon: <CircleDollarSignIcon className="size-4 shrink-0" />,
|
||||
href: Routes.PricingBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.comparator.title'),
|
||||
icon: <SplitSquareVerticalIcon className="site-4 shrink-0" />,
|
||||
icon: <SplitSquareVerticalIcon className="size-4 shrink-0" />,
|
||||
href: Routes.ComparatorBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.faq.title'),
|
||||
icon: <CircleHelpIcon className="site-4 shrink-0" />,
|
||||
icon: <CircleHelpIcon className="size-4 shrink-0" />,
|
||||
href: Routes.FAQBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.login.title'),
|
||||
icon: <LogInIcon className="site-4 shrink-0" />,
|
||||
icon: <LogInIcon className="size-4 shrink-0" />,
|
||||
href: Routes.LoginBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.signup.title'),
|
||||
icon: <UserPlusIcon className="site-4 shrink-0" />,
|
||||
icon: <UserPlusIcon className="size-4 shrink-0" />,
|
||||
href: Routes.SignupBlocks,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('blocks.items.contact.title'),
|
||||
icon: <MailIcon className="site-4 shrink-0" />,
|
||||
icon: <MailIcon className="size-4 shrink-0" />,
|
||||
href: Routes.ContactBlocks,
|
||||
external: false,
|
||||
},
|
||||
|
@ -8,7 +8,10 @@ import {
|
||||
CreditCardIcon,
|
||||
LayoutDashboardIcon,
|
||||
LockKeyholeIcon,
|
||||
Settings2Icon
|
||||
Settings2Icon,
|
||||
SettingsIcon,
|
||||
UsersIcon,
|
||||
UsersRoundIcon
|
||||
} from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
@ -25,35 +28,48 @@ export function getSidebarConfig(): NestedMenuItem[] {
|
||||
return [
|
||||
{
|
||||
title: t('dashboard.title'),
|
||||
icon: <LayoutDashboardIcon className="site-4 shrink-0" />,
|
||||
icon: <LayoutDashboardIcon className="size-4 shrink-0" />,
|
||||
href: Routes.Dashboard,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('admin.title'),
|
||||
icon: <SettingsIcon className="size-4 shrink-0" />,
|
||||
authorizeOnly: ['admin'],
|
||||
items: [
|
||||
{
|
||||
title: t('admin.users.title'),
|
||||
icon: <UsersRoundIcon className="size-4 shrink-0" />,
|
||||
href: Routes.AdminUsers,
|
||||
external: false,
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t('settings.title'),
|
||||
icon: <Settings2Icon className="site-4 shrink-0" />,
|
||||
icon: <Settings2Icon className="size-4 shrink-0" />,
|
||||
items: [
|
||||
{
|
||||
title: t('settings.profile.title'),
|
||||
icon: <CircleUserRoundIcon className="site-4 shrink-0" />,
|
||||
icon: <CircleUserRoundIcon className="size-4 shrink-0" />,
|
||||
href: Routes.SettingsProfile,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('settings.billing.title'),
|
||||
icon: <CreditCardIcon className="site-4 shrink-0" />,
|
||||
icon: <CreditCardIcon className="size-4 shrink-0" />,
|
||||
href: Routes.SettingsBilling,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('settings.security.title'),
|
||||
icon: <LockKeyholeIcon className="site-4 shrink-0" />,
|
||||
icon: <LockKeyholeIcon className="size-4 shrink-0" />,
|
||||
href: Routes.SettingsSecurity,
|
||||
external: false,
|
||||
},
|
||||
{
|
||||
title: t('settings.notification.title'),
|
||||
icon: <BellIcon className="site-4 shrink-0" />,
|
||||
icon: <BellIcon className="size-4 shrink-0" />,
|
||||
href: Routes.SettingsNotifications,
|
||||
external: false,
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ export enum Routes {
|
||||
|
||||
// dashboard routes
|
||||
Dashboard = '/dashboard',
|
||||
AdminUsers = '/admin/users',
|
||||
SettingsProfile = '/settings/profile',
|
||||
SettingsBilling = '/settings/billing',
|
||||
SettingsSecurity = '/settings/security',
|
||||
|
3
src/types/index.d.ts
vendored
3
src/types/index.d.ts
vendored
@ -42,6 +42,7 @@ export type WebsiteConfig = {
|
||||
* icon?: the icon to display
|
||||
* href?: the url to link to
|
||||
* external?: whether the link is external
|
||||
* authorizeOnly?: the roles that are authorized to see the item
|
||||
*/
|
||||
export type MenuItem = {
|
||||
title: string;
|
||||
@ -49,6 +50,7 @@ export type MenuItem = {
|
||||
icon?: ReactNode;
|
||||
href?: string;
|
||||
external?: boolean;
|
||||
authorizeOnly?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -60,5 +62,6 @@ export type NestedMenuItem = {
|
||||
icon?: ReactNode;
|
||||
href?: string;
|
||||
external?: boolean;
|
||||
authorizeOnly?: string[];
|
||||
items?: MenuItem[];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user