mirror of
https://github.com/supabase/supabase.git
synced 2026-10-12 21:05:06 +03:00
187 lines
5.8 KiB
TypeScript
187 lines
5.8 KiB
TypeScript
'use client'
|
|
|
|
import { useEffect, useState, ReactNode } from 'react'
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
import { DatabaseManager } from '@/components/supabase-manager/database'
|
|
import { StorageManager } from '@/components/supabase-manager/storage'
|
|
import { AuthManager } from '@/components/supabase-manager/auth'
|
|
import { UsersManager } from '@/components/supabase-manager/users'
|
|
import { SecretsManager } from '@/components/supabase-manager/secrets'
|
|
import { LogsManager } from '@/components/supabase-manager/logs'
|
|
import { SuggestionsManager } from '@/components/supabase-manager/suggestions'
|
|
import {
|
|
SheetNavigationProvider,
|
|
useSheetNavigation,
|
|
} from '@/contexts/SheetNavigationContext'
|
|
import {
|
|
ChevronLeft,
|
|
ChevronRight,
|
|
Database,
|
|
HardDrive,
|
|
Shield,
|
|
Users,
|
|
KeyRound,
|
|
ScrollText,
|
|
Lightbulb,
|
|
} from 'lucide-react'
|
|
import { Button } from '@/components/ui/button'
|
|
|
|
const queryClient = new QueryClient()
|
|
|
|
interface PlatformKitEmbedProps {
|
|
projectRef: string
|
|
}
|
|
|
|
function PlatformKitContent({ projectRef }: { projectRef: string }) {
|
|
const { stack, push, popTo, reset } = useSheetNavigation()
|
|
|
|
const handleTopLevelNavigation = (title: string, component: ReactNode) => {
|
|
if (stack.length === 1 && stack[0].title === title) {
|
|
return
|
|
}
|
|
reset()
|
|
push({ title, component })
|
|
}
|
|
|
|
const currentView = stack[stack.length - 1]
|
|
const activeManager = stack.length > 0 ? stack[0].title : null
|
|
|
|
const navigationItems = [
|
|
{
|
|
title: 'Database',
|
|
icon: Database,
|
|
component: <DatabaseManager projectRef={projectRef} />,
|
|
},
|
|
{
|
|
title: 'Storage',
|
|
icon: HardDrive,
|
|
component: <StorageManager projectRef={projectRef} />,
|
|
},
|
|
{
|
|
title: 'Auth',
|
|
icon: Shield,
|
|
component: <AuthManager projectRef={projectRef} />,
|
|
},
|
|
{
|
|
title: 'Users',
|
|
icon: Users,
|
|
component: <UsersManager projectRef={projectRef} />,
|
|
},
|
|
{
|
|
title: 'Secrets',
|
|
icon: KeyRound,
|
|
component: <SecretsManager projectRef={projectRef} />,
|
|
},
|
|
{
|
|
title: 'Logs',
|
|
icon: ScrollText,
|
|
component: <LogsManager projectRef={projectRef} />,
|
|
},
|
|
{
|
|
title: 'Suggestions',
|
|
icon: Lightbulb,
|
|
component: <SuggestionsManager projectRef={projectRef} />,
|
|
},
|
|
]
|
|
|
|
return (
|
|
<div className="grid grid-cols-[200px_1fr] h-full overflow-hidden">
|
|
{/* Sidebar */}
|
|
<div className="flex flex-col border-r border-[#2C2C2C] px-3 py-6 pb-3 bg-[#1C1C1C]">
|
|
<div className="px-3 mb-4">
|
|
<h2 className="text-[#808080] font-medium text-xs uppercase tracking-wide">
|
|
Manage Backend
|
|
</h2>
|
|
</div>
|
|
<div className="grow space-y-0.5">
|
|
{navigationItems.map((item) => {
|
|
const Icon = item.icon
|
|
return (
|
|
<Button
|
|
key={item.title}
|
|
variant={activeManager === item.title ? 'secondary' : 'ghost'}
|
|
className={`w-full justify-start text-sm ${
|
|
activeManager === item.title
|
|
? 'bg-[#2C2C2C] text-white'
|
|
: 'text-[#A0A0A0] hover:text-white hover:bg-[#2C2C2C]/50'
|
|
}`}
|
|
onClick={() => handleTopLevelNavigation(item.title, item.component)}
|
|
>
|
|
<Icon className="mr-2 w-4 h-4" />
|
|
{item.title === 'Auth' ? 'Authentication' : item.title}
|
|
</Button>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Content Area */}
|
|
<div className="flex flex-col overflow-hidden h-full bg-[#0E0E0E]">
|
|
{/* Header with breadcrumbs */}
|
|
<div className="flex items-center h-12 shrink-0 px-4 border-b border-[#2C2C2C]">
|
|
{stack.length > 1 && (
|
|
<Button
|
|
variant="outline"
|
|
size="icon"
|
|
className="h-8 w-8 border-[#2C2C2C] bg-transparent hover:bg-[#2C2C2C]"
|
|
onClick={() => popTo(stack.length - 2)}
|
|
>
|
|
<ChevronLeft className="h-4 w-4 text-[#A0A0A0]" />
|
|
</Button>
|
|
)}
|
|
{/* Breadcrumbs */}
|
|
<div className="ml-4 flex items-center gap-1.5 text-sm text-[#A0A0A0]">
|
|
{stack.map((item: { title: string }, index: number) => (
|
|
<div key={`${item.title}-${index}`} className="flex items-center gap-1.5">
|
|
{index > 0 && <ChevronRight className="h-3 w-3" />}
|
|
{index === stack.length - 1 ? (
|
|
<span className="font-medium text-white">{item.title}</span>
|
|
) : (
|
|
<button onClick={() => popTo(index)} className="hover:text-white">
|
|
{item.title}
|
|
</button>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grow overflow-y-auto">
|
|
{currentView ? (
|
|
currentView.component
|
|
) : (
|
|
<div className="flex items-center justify-center h-full">
|
|
<p className="text-[#808080]">
|
|
Select a manager from the sidebar to get started.
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default function PlatformKitEmbed({ projectRef }: PlatformKitEmbedProps) {
|
|
return (
|
|
<div
|
|
className="bg-[#1C1C1C] border border-[#2C2C2C] rounded-lg overflow-hidden"
|
|
style={{ height: 'calc(100vh - 280px)', minHeight: '600px' }}
|
|
>
|
|
<QueryClientProvider client={queryClient}>
|
|
<SheetNavigationProvider
|
|
onStackEmpty={() => {}}
|
|
initialStack={[
|
|
{
|
|
title: 'Database',
|
|
component: <DatabaseManager projectRef={projectRef} />,
|
|
},
|
|
]}
|
|
>
|
|
<PlatformKitContent projectRef={projectRef} />
|
|
</SheetNavigationProvider>
|
|
</QueryClientProvider>
|
|
</div>
|
|
)
|
|
}
|