Prettier format pending files
This commit is contained in:
parent
89aa046bfe
commit
78d02ec135
8 changed files with 558 additions and 451 deletions
|
|
@ -551,14 +551,70 @@ const App = () => (
|
|||
/>
|
||||
|
||||
{/* Staff Pages Routes - Protected */}
|
||||
<Route path="/staff/announcements" element={<RequireAccess><StaffAnnouncements /></RequireAccess>} />
|
||||
<Route path="/staff/expense-reports" element={<RequireAccess><StaffExpenseReports /></RequireAccess>} />
|
||||
<Route path="/staff/marketplace" element={<RequireAccess><StaffInternalMarketplace /></RequireAccess>} />
|
||||
<Route path="/staff/knowledge-base" element={<RequireAccess><StaffKnowledgeBase /></RequireAccess>} />
|
||||
<Route path="/staff/learning-portal" element={<RequireAccess><StaffLearningPortal /></RequireAccess>} />
|
||||
<Route path="/staff/performance-reviews" element={<RequireAccess><StaffPerformanceReviews /></RequireAccess>} />
|
||||
<Route path="/staff/project-tracking" element={<RequireAccess><StaffProjectTracking /></RequireAccess>} />
|
||||
<Route path="/staff/team-handbook" element={<RequireAccess><StaffTeamHandbook /></RequireAccess>} />
|
||||
<Route
|
||||
path="/staff/announcements"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffAnnouncements />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/expense-reports"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffExpenseReports />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/marketplace"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffInternalMarketplace />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/knowledge-base"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffKnowledgeBase />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/learning-portal"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffLearningPortal />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/performance-reviews"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffPerformanceReviews />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/project-tracking"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffProjectTracking />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/staff/team-handbook"
|
||||
element={
|
||||
<RequireAccess>
|
||||
<StaffTeamHandbook />
|
||||
</RequireAccess>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Explicit 404 route for static hosting fallbacks */}
|
||||
<Route path="/404" element={<FourOhFourPage />} />
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ const ARMS: Arm[] = [
|
|||
];
|
||||
|
||||
const LOGO_URLS: Record<string, string> = {
|
||||
staff: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fc0414efd7af54ef4b821a05d469150d0?format=webp&width=800",
|
||||
staff:
|
||||
"https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fc0414efd7af54ef4b821a05d469150d0?format=webp&width=800",
|
||||
labs: "https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fd93f7113d34347469e74421c3a3412e5?format=webp&width=800",
|
||||
gameforge:
|
||||
"https://cdn.builder.io/api/v1/image/assets%2Ffc53d607e21d497595ac97e0637001a1%2Fcd3534c1caa0497abfd44224040c6059?format=webp&width=800",
|
||||
|
|
|
|||
|
|
@ -367,7 +367,10 @@ export default function CodeLayout({ children, hideFooter }: LayoutProps) {
|
|||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to="/internal-docs" className="cursor-pointer">
|
||||
<Link
|
||||
to="/internal-docs"
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<BookOpen className="mr-2 h-4 w-4" />
|
||||
Internal Docs
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -87,46 +87,46 @@ export default function AdminBlogManager() {
|
|||
loadBlogPosts();
|
||||
}, [loadBlogPosts]);
|
||||
|
||||
const handleDeleteBlogPost = useCallback(
|
||||
async (slug: string) => {
|
||||
setDeleting(slug);
|
||||
try {
|
||||
const res = await fetch(`/api/blog/${slug}`, { method: "DELETE" });
|
||||
if (res.ok) {
|
||||
setBlogPosts((posts) => posts.filter((p) => p.slug !== slug));
|
||||
aethexToast.success({
|
||||
title: "Blog post deleted",
|
||||
description: `Post "${slug}" has been removed`,
|
||||
});
|
||||
} else {
|
||||
aethexToast.error({
|
||||
title: "Failed to delete blog post",
|
||||
description: res.statusText || "Unknown error",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error deleting blog post:", error);
|
||||
aethexToast.error({
|
||||
title: "Error deleting blog post",
|
||||
description: String(error),
|
||||
const handleDeleteBlogPost = useCallback(async (slug: string) => {
|
||||
setDeleting(slug);
|
||||
try {
|
||||
const res = await fetch(`/api/blog/${slug}`, { method: "DELETE" });
|
||||
if (res.ok) {
|
||||
setBlogPosts((posts) => posts.filter((p) => p.slug !== slug));
|
||||
aethexToast.success({
|
||||
title: "Blog post deleted",
|
||||
description: `Post "${slug}" has been removed`,
|
||||
});
|
||||
} else {
|
||||
aethexToast.error({
|
||||
title: "Failed to delete blog post",
|
||||
description: res.statusText || "Unknown error",
|
||||
});
|
||||
} finally {
|
||||
setDeleting(null);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error deleting blog post:", error);
|
||||
aethexToast.error({
|
||||
title: "Error deleting blog post",
|
||||
description: String(error),
|
||||
});
|
||||
} finally {
|
||||
setDeleting(null);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const filteredPosts = blogPosts.filter((post) => {
|
||||
const matchesSearch =
|
||||
post.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
post.slug.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
(post.author && post.author.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
(post.author &&
|
||||
post.author.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
const matchesCategory = !filterCategory || post.category === filterCategory;
|
||||
return matchesSearch && matchesCategory;
|
||||
});
|
||||
|
||||
const categories = Array.from(new Set(blogPosts.map((p) => p.category).filter(Boolean)));
|
||||
const categories = Array.from(
|
||||
new Set(blogPosts.map((p) => p.category).filter(Boolean)),
|
||||
);
|
||||
|
||||
const formatDate = (dateStr?: string | null) => {
|
||||
if (!dateStr) return "—";
|
||||
|
|
@ -149,7 +149,8 @@ export default function AdminBlogManager() {
|
|||
<div>
|
||||
<CardTitle>Blog Management</CardTitle>
|
||||
<CardDescription>
|
||||
{blogPosts.length} published {blogPosts.length === 1 ? "post" : "posts"}
|
||||
{blogPosts.length} published{" "}
|
||||
{blogPosts.length === 1 ? "post" : "posts"}
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button
|
||||
|
|
@ -159,7 +160,11 @@ export default function AdminBlogManager() {
|
|||
disabled={loading}
|
||||
className="gap-2"
|
||||
>
|
||||
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
|
||||
{loading ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
)}
|
||||
{loading ? "Loading..." : "Refresh"}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -201,7 +206,9 @@ export default function AdminBlogManager() {
|
|||
{filteredPosts.length === 0 ? (
|
||||
<div className="text-center py-8">
|
||||
<p className="text-muted-foreground">
|
||||
{blogPosts.length === 0 ? "No blog posts found" : "No matching blog posts"}
|
||||
{blogPosts.length === 0
|
||||
? "No blog posts found"
|
||||
: "No matching blog posts"}
|
||||
</p>
|
||||
{blogPosts.length === 0 && (
|
||||
<Button
|
||||
|
|
@ -231,7 +238,9 @@ export default function AdminBlogManager() {
|
|||
<TableCell className="font-medium">
|
||||
<div className="max-w-xs">
|
||||
<p className="truncate">{post.title}</p>
|
||||
<p className="text-xs text-muted-foreground">{post.slug}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{post.slug}
|
||||
</p>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">
|
||||
|
|
@ -243,7 +252,9 @@ export default function AdminBlogManager() {
|
|||
{post.category}
|
||||
</Badge>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">—</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
—
|
||||
</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">
|
||||
|
|
@ -254,7 +265,9 @@ export default function AdminBlogManager() {
|
|||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => window.open(`/blog/${post.slug}`, "_blank")}
|
||||
onClick={() =>
|
||||
window.open(`/blog/${post.slug}`, "_blank")
|
||||
}
|
||||
title="View published post"
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
|
|
@ -280,12 +293,16 @@ export default function AdminBlogManager() {
|
|||
</Card>
|
||||
|
||||
{deleteConfirm && (
|
||||
<AlertDialog open={!!deleteConfirm} onOpenChange={(open) => !open && setDeleteConfirm(null)}>
|
||||
<AlertDialog
|
||||
open={!!deleteConfirm}
|
||||
onOpenChange={(open) => !open && setDeleteConfirm(null)}
|
||||
>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Delete blog post?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Are you sure you want to delete "{deleteConfirm.title}"? This action cannot be undone.
|
||||
Are you sure you want to delete "{deleteConfirm.title}"? This
|
||||
action cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<div className="flex gap-2 justify-end">
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ export default function AdminSidebar({
|
|||
"w-full flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors",
|
||||
activeTab === item.id
|
||||
? "bg-aethex-500/20 text-aethex-200 border border-aethex-400/30"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-muted/50",
|
||||
)}
|
||||
>
|
||||
{item.icon}
|
||||
|
|
|
|||
|
|
@ -335,410 +335,412 @@ export default function Admin() {
|
|||
<AdminSidebar activeTab={activeTab} onTabChange={setActiveTab} />
|
||||
<div className="flex-1 overflow-y-auto py-8">
|
||||
<div className="container mx-auto px-4 max-w-7xl">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-aethex-200 mb-2">
|
||||
Control Center
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Manage platform, users, content, and integrations · Roles:{" "}
|
||||
<span className="text-aethex-300 font-medium">
|
||||
{roles.join(", ") || "none"}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-aethex-200 mb-2">
|
||||
Control Center
|
||||
</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Manage platform, users, content, and integrations · Roles:{" "}
|
||||
<span className="text-aethex-300 font-medium">
|
||||
{roles.join(", ") || "none"}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onValueChange={setActiveTab}
|
||||
className="space-y-6"
|
||||
>
|
||||
<TabsList className="w-full justify-start gap-2 overflow-x-auto border border-border/40 bg-background/40 px-1 py-1 backdrop-blur flex-wrap h-auto lg:hidden">
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
<TabsTrigger value="system-map">System Map</TabsTrigger>
|
||||
<TabsTrigger value="roadmap">Roadmap</TabsTrigger>
|
||||
<TabsTrigger value="staff">Staff</TabsTrigger>
|
||||
<TabsTrigger value="blogs">Blogs</TabsTrigger>
|
||||
<TabsTrigger value="community">Community</TabsTrigger>
|
||||
<TabsTrigger value="mentorship">Mentorship</TabsTrigger>
|
||||
<TabsTrigger value="arm-metrics">Arm Metrics</TabsTrigger>
|
||||
<TabsTrigger value="discord">Discord</TabsTrigger>
|
||||
<TabsTrigger value="operations">Operations</TabsTrigger>
|
||||
</TabsList>
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onValueChange={setActiveTab}
|
||||
className="space-y-6"
|
||||
>
|
||||
<TabsList className="w-full justify-start gap-2 overflow-x-auto border border-border/40 bg-background/40 px-1 py-1 backdrop-blur flex-wrap h-auto lg:hidden">
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
<TabsTrigger value="system-map">System Map</TabsTrigger>
|
||||
<TabsTrigger value="roadmap">Roadmap</TabsTrigger>
|
||||
<TabsTrigger value="staff">Staff</TabsTrigger>
|
||||
<TabsTrigger value="blogs">Blogs</TabsTrigger>
|
||||
<TabsTrigger value="community">Community</TabsTrigger>
|
||||
<TabsTrigger value="mentorship">Mentorship</TabsTrigger>
|
||||
<TabsTrigger value="arm-metrics">Arm Metrics</TabsTrigger>
|
||||
<TabsTrigger value="discord">Discord</TabsTrigger>
|
||||
<TabsTrigger value="operations">Operations</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="overview" className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Total Members
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{totalMembers || "—"}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Active profiles synced
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Published Posts
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{publishedPosts || "0"}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Blog entries available
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Featured Studios
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{featuredStudios}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Highlighted partners
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Pending Applications
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{pendingProjectApplications}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Awaiting review
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<TabsContent value="overview" className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Total Members
|
||||
</CardTitle>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Command className="h-5 w-5 text-aethex-300" />
|
||||
<CardTitle>Quick Actions</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => navigate("/dashboard")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<BarChart3 className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Dashboard</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
View KPIs
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("blogs")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<PenTool className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Blogs</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Manage posts
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("community")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<Users className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Members</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Manage users
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("operations")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<Settings className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Operations</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Settings & config
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("discord")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<MessageSquare className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Discord</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Bot management
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => navigate("/status")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<Gauge className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Status</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
System health
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="system-map" className="space-y-6">
|
||||
<AdminSystemMap />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="roadmap" className="space-y-6">
|
||||
<AdminRoadmap />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="staff" className="space-y-6">
|
||||
<Tabs defaultValue="operations" className="space-y-4">
|
||||
<TabsList className="w-full justify-start gap-2 border border-border/40 bg-background/40 px-1 py-1 backdrop-blur flex-wrap h-auto">
|
||||
<TabsTrigger value="operations">Operations</TabsTrigger>
|
||||
<TabsTrigger value="directory">Directory</TabsTrigger>
|
||||
<TabsTrigger value="chat">Chat</TabsTrigger>
|
||||
<TabsTrigger value="admin">Admin</TabsTrigger>
|
||||
<TabsTrigger value="docs">Docs</TabsTrigger>
|
||||
<TabsTrigger value="achievements">
|
||||
Achievements
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="operations" className="space-y-6">
|
||||
<AdminStaffOperations />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="directory" className="space-y-6">
|
||||
<AdminStaffDirectory />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="chat" className="space-y-6">
|
||||
<AdminStaffChat />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="admin" className="space-y-6">
|
||||
<AdminStaffAdmin />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="docs" className="space-y-6">
|
||||
<AdminStaffDocs />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="achievements" className="space-y-6">
|
||||
<AdminStaffAchievements />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="blogs" className="space-y-6">
|
||||
<AdminBlogManager />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="community" className="space-y-6">
|
||||
<AdminMemberManager
|
||||
profiles={managedProfiles}
|
||||
selectedId={selectedMemberId}
|
||||
onSelectedIdChange={(id) => setSelectedMemberId(id)}
|
||||
onRefresh={loadProfiles}
|
||||
ownerEmail="admin@aethex.tech"
|
||||
/>
|
||||
<AdminAchievementManager targetUser={selectedMember} />
|
||||
<AdminSpotlightManager profiles={managedProfiles} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="mentorship" className="space-y-6">
|
||||
<AdminMentorshipManager />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="arm-metrics" className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4">
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-yellow-400" />
|
||||
<CardTitle className="text-sm">Labs</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Research</p>
|
||||
<p className="text-lg font-bold">12 projects</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Team</p>
|
||||
<p className="text-lg font-bold">24 members</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-green-400" />
|
||||
<CardTitle className="text-sm">GameForge</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Games</p>
|
||||
<p className="text-lg font-bold">45 shipped</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Players</p>
|
||||
<p className="text-lg font-bold">2.8M MAU</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-blue-400" />
|
||||
<CardTitle className="text-sm">Corp</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Clients</p>
|
||||
<p className="text-lg font-bold">34 active</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">ARR</p>
|
||||
<p className="text-lg font-bold">$4.2M</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-red-400" />
|
||||
<CardTitle className="text-sm">Foundation</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Learners</p>
|
||||
<p className="text-lg font-bold">342 active</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Completion</p>
|
||||
<p className="text-lg font-bold">87.5%</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-purple-400" />
|
||||
<CardTitle className="text-sm">Nexus</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Creators</p>
|
||||
<p className="text-lg font-bold">1,240 active</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Success Rate</p>
|
||||
<p className="text-lg font-bold">68%</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="discord" className="space-y-6">
|
||||
<AdminDiscordManagement />
|
||||
<AdminDiscordDiagnostic />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="operations" className="space-y-6">
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Settings className="h-5 w-5 text-aethex-300" />
|
||||
<CardTitle>Home Banner</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Controls the notice shown at the top of the home page
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{totalMembers || "—"}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Active profiles synced
|
||||
</p>
|
||||
<BannerSettings />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Published Posts
|
||||
</CardTitle>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Grid3x3 className="h-5 w-5 text-yellow-300" />
|
||||
<CardTitle>Featured Studios</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Control studios highlighted across AeThex
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{publishedPosts || "0"}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Blog entries available
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Featured Studios
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{featuredStudios}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Highlighted partners
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium text-muted-foreground">
|
||||
Pending Applications
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-3xl font-bold text-aethex-200">
|
||||
{pendingProjectApplications}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Awaiting review
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Command className="h-5 w-5 text-aethex-300" />
|
||||
<CardTitle>Quick Actions</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => navigate("/dashboard")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<BarChart3 className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Dashboard</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
View KPIs
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("blogs")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<PenTool className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Blogs</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Manage posts
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("community")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<Users className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Members</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Manage users
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("operations")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<Settings className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Operations</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Settings & config
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("discord")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<MessageSquare className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Discord</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Bot management
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => navigate("/status")}
|
||||
className="justify-start h-auto py-3"
|
||||
>
|
||||
<Gauge className="h-4 w-4 mr-2" />
|
||||
<div className="text-left">
|
||||
<div className="font-medium">Status</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
System health
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="system-map" className="space-y-6">
|
||||
<AdminSystemMap />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="roadmap" className="space-y-6">
|
||||
<AdminRoadmap />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="staff" className="space-y-6">
|
||||
<Tabs defaultValue="operations" className="space-y-4">
|
||||
<TabsList className="w-full justify-start gap-2 border border-border/40 bg-background/40 px-1 py-1 backdrop-blur flex-wrap h-auto">
|
||||
<TabsTrigger value="operations">Operations</TabsTrigger>
|
||||
<TabsTrigger value="directory">Directory</TabsTrigger>
|
||||
<TabsTrigger value="chat">Chat</TabsTrigger>
|
||||
<TabsTrigger value="admin">Admin</TabsTrigger>
|
||||
<TabsTrigger value="docs">Docs</TabsTrigger>
|
||||
<TabsTrigger value="achievements">Achievements</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="operations" className="space-y-6">
|
||||
<AdminStaffOperations />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="directory" className="space-y-6">
|
||||
<AdminStaffDirectory />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="chat" className="space-y-6">
|
||||
<AdminStaffChat />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="admin" className="space-y-6">
|
||||
<AdminStaffAdmin />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="docs" className="space-y-6">
|
||||
<AdminStaffDocs />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="achievements" className="space-y-6">
|
||||
<AdminStaffAchievements />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="blogs" className="space-y-6">
|
||||
<AdminBlogManager />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="community" className="space-y-6">
|
||||
<AdminMemberManager
|
||||
profiles={managedProfiles}
|
||||
selectedId={selectedMemberId}
|
||||
onSelectedIdChange={(id) => setSelectedMemberId(id)}
|
||||
onRefresh={loadProfiles}
|
||||
ownerEmail="admin@aethex.tech"
|
||||
/>
|
||||
<AdminAchievementManager targetUser={selectedMember} />
|
||||
<AdminSpotlightManager profiles={managedProfiles} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="mentorship" className="space-y-6">
|
||||
<AdminMentorshipManager />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="arm-metrics" className="space-y-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4">
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-yellow-400" />
|
||||
<CardTitle className="text-sm">Labs</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Research</p>
|
||||
<p className="text-lg font-bold">12 projects</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Team</p>
|
||||
<p className="text-lg font-bold">24 members</p>
|
||||
<div className="space-y-3">
|
||||
{studios.map((s, i) => (
|
||||
<div
|
||||
key={`${s.name}-${i}`}
|
||||
className="p-3 border border-border/40 rounded-lg bg-background/40"
|
||||
>
|
||||
<p className="font-medium">{s.name}</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{s.tagline}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-green-400" />
|
||||
<CardTitle className="text-sm">GameForge</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Games</p>
|
||||
<p className="text-lg font-bold">45 shipped</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Players</p>
|
||||
<p className="text-lg font-bold">2.8M MAU</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-blue-400" />
|
||||
<CardTitle className="text-sm">Corp</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Clients</p>
|
||||
<p className="text-lg font-bold">34 active</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">ARR</p>
|
||||
<p className="text-lg font-bold">$4.2M</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-red-400" />
|
||||
<CardTitle className="text-sm">Foundation</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Learners</p>
|
||||
<p className="text-lg font-bold">342 active</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Completion</p>
|
||||
<p className="text-lg font-bold">87.5%</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-2 w-2 rounded-full bg-purple-400" />
|
||||
<CardTitle className="text-sm">Nexus</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-2 text-xs">
|
||||
<div>
|
||||
<p className="text-muted-foreground">Creators</p>
|
||||
<p className="text-lg font-bold">1,240 active</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-muted-foreground">Success Rate</p>
|
||||
<p className="text-lg font-bold">68%</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="discord" className="space-y-6">
|
||||
<AdminDiscordManagement />
|
||||
<AdminDiscordDiagnostic />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="operations" className="space-y-6">
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Settings className="h-5 w-5 text-aethex-300" />
|
||||
<CardTitle>Home Banner</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Controls the notice shown at the top of the home page
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<BannerSettings />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-card/60 border-border/40 backdrop-blur">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Grid3x3 className="h-5 w-5 text-yellow-300" />
|
||||
<CardTitle>Featured Studios</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Control studios highlighted across AeThex
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
{studios.map((s, i) => (
|
||||
<div
|
||||
key={`${s.name}-${i}`}
|
||||
className="p-3 border border-border/40 rounded-lg bg-background/40"
|
||||
>
|
||||
<p className="font-medium">{s.name}</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{s.tagline}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -140,14 +140,14 @@ export default function Staff() {
|
|||
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-purple-600 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-blob" />
|
||||
<div className="absolute top-1/3 right-1/4 w-96 h-96 bg-violet-600 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-blob animation-delay-2000" />
|
||||
<div className="absolute bottom-1/4 left-1/2 w-96 h-96 bg-purple-500 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-blob animation-delay-4000" />
|
||||
|
||||
|
||||
{/* Grid background */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-5"
|
||||
style={{
|
||||
backgroundImage:
|
||||
'linear-gradient(rgba(139, 92, 246, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(139, 92, 246, 0.1) 1px, transparent 1px)',
|
||||
backgroundSize: '50px 50px',
|
||||
"linear-gradient(rgba(139, 92, 246, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(139, 92, 246, 0.1) 1px, transparent 1px)",
|
||||
backgroundSize: "50px 50px",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -181,7 +181,10 @@ export default function Staff() {
|
|||
The Staff Command Center
|
||||
</h1>
|
||||
<p className="text-lg md:text-xl text-gray-300 max-w-3xl mx-auto leading-relaxed">
|
||||
Unified workspace for internal communications, team collaboration, and operational excellence. Manage projects, track performance, and connect with your team—all in one secure platform.
|
||||
Unified workspace for internal communications, team
|
||||
collaboration, and operational excellence. Manage projects,
|
||||
track performance, and connect with your team—all in one secure
|
||||
platform.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -233,7 +236,8 @@ export default function Staff() {
|
|||
Quick Access Resources
|
||||
</h2>
|
||||
<p className="text-gray-400 text-lg">
|
||||
Everything you need to manage operations, collaborate with your team, and stay informed
|
||||
Everything you need to manage operations, collaborate with
|
||||
your team, and stay informed
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -282,7 +286,9 @@ export default function Staff() {
|
|||
<div className="p-2 rounded-lg bg-purple-500/20">
|
||||
<MessageSquare className="w-6 h-6 text-purple-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Communication & Collaboration</h3>
|
||||
<h3 className="text-xl font-bold">
|
||||
Communication & Collaboration
|
||||
</h3>
|
||||
</div>
|
||||
<ul className="space-y-3">
|
||||
{[
|
||||
|
|
@ -341,7 +347,10 @@ export default function Staff() {
|
|||
Enterprise Security & Privacy
|
||||
</h3>
|
||||
<p className="text-gray-300 leading-relaxed">
|
||||
All staff information is protected with enterprise-grade security. Access is restricted to authenticated team members only. Your data is encrypted, audited, and compliant with privacy regulations.
|
||||
All staff information is protected with enterprise-grade
|
||||
security. Access is restricted to authenticated team members
|
||||
only. Your data is encrypted, audited, and compliant with
|
||||
privacy regulations.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2355,14 +2355,23 @@ export function createServer() {
|
|||
const { data, error } = await query;
|
||||
if (error) {
|
||||
// If table doesn't exist, return empty array (client will use seed data)
|
||||
if (error.message?.includes("does not exist") || error.code === "42P01") {
|
||||
console.log("[Blog] blog_posts table not found, returning empty array");
|
||||
if (
|
||||
error.message?.includes("does not exist") ||
|
||||
error.code === "42P01"
|
||||
) {
|
||||
console.log(
|
||||
"[Blog] blog_posts table not found, returning empty array",
|
||||
);
|
||||
return res.json([]);
|
||||
}
|
||||
console.error("[Blog] Error fetching blog posts:", error);
|
||||
return res.status(500).json({ error: error.message });
|
||||
}
|
||||
console.log("[Blog] Successfully fetched", (data || []).length, "blog posts");
|
||||
console.log(
|
||||
"[Blog] Successfully fetched",
|
||||
(data || []).length,
|
||||
"blog posts",
|
||||
);
|
||||
res.json(data || []);
|
||||
} catch (e: any) {
|
||||
console.error("[Blog] Exception:", e);
|
||||
|
|
@ -2386,7 +2395,10 @@ export function createServer() {
|
|||
// No rows returned - 404
|
||||
return res.status(404).json({ error: "Blog post not found" });
|
||||
}
|
||||
if (error.message?.includes("does not exist") || error.code === "42P01") {
|
||||
if (
|
||||
error.message?.includes("does not exist") ||
|
||||
error.code === "42P01"
|
||||
) {
|
||||
// Table doesn't exist
|
||||
return res.status(404).json({ error: "Blog not configured" });
|
||||
}
|
||||
|
|
@ -4851,7 +4863,10 @@ export function createServer() {
|
|||
// Staff Members API
|
||||
app.get("/api/staff/members", async (_req, res) => {
|
||||
try {
|
||||
console.log("[Staff] GET /api/staff/members - adminSupabase initialized:", !!adminSupabase);
|
||||
console.log(
|
||||
"[Staff] GET /api/staff/members - adminSupabase initialized:",
|
||||
!!adminSupabase,
|
||||
);
|
||||
|
||||
if (!adminSupabase) {
|
||||
console.error("[Staff] adminSupabase is not initialized");
|
||||
|
|
@ -4875,7 +4890,11 @@ export function createServer() {
|
|||
return res.status(500).json({ error: error.message });
|
||||
}
|
||||
|
||||
console.log("[Staff] Successfully fetched", (data || []).length, "staff members");
|
||||
console.log(
|
||||
"[Staff] Successfully fetched",
|
||||
(data || []).length,
|
||||
"staff members",
|
||||
);
|
||||
return res.json(data || []);
|
||||
} catch (e: any) {
|
||||
console.error("[Staff] Unexpected error:", e);
|
||||
|
|
|
|||
Loading…
Reference in a new issue