Admin Panel
The ShipKit admin panel provides a comprehensive interface for managing users, monitoring system activity, handling feedback, and configuring various system aspects.
Layout
The admin panel uses a protected layout that ensures only admin users can access it:
// src/app/(app)/(admin)/layout.tsx
const navLinks = [
{ href: routes.admin.users, label: "Users" },
{ href: routes.admin.cms, label: "CMS" },
{ href: routes.admin.activity, label: "Activity" },
{ href: routes.admin.feedback, label: "Feedback" },
{ href: routes.admin.payments, label: "Payments" },
{ href: routes.admin.ai, label: "AI" },
];
export default async function AdminLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await auth();
const isAdmin =
session?.user?.email && siteConfig.admin.isAdmin(session.user.email);
if (!isAdmin) {
redirect(routes.home);
}
return (
<>
<Header navLinks={navLinks} />;
{children}
</>
);
}
Features
User Management
The user management section provides a comprehensive interface for managing users:
// src/app/(app)/(admin)/admin/users/page.tsx
export default async function AdminPage() {
const users = await getUsersWithPayments();
return (
<div className="container mx-auto py-10">
<h1 className="mb-8 text-3xl font-bold">User Management</h1>
<DataTable columns={columns} data={users} />
</div>
);
}
User Details Drawer
The user drawer component provides detailed user information and management options:
interface UserDrawerProps {
user: UserData;
open: boolean;
onClose: () => void;
}
export const UserDrawer = ({ user, open, onClose }: UserDrawerProps) => {
// Implementation includes:
// - Basic user information
// - Access management
// - Email communication
// - Activity history
// - Purchase history
};
CMS Management
The CMS section allows administrators to manage content:
export default function CMSPage() {
const [adminSecret, setAdminSecret] = useState("");
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState<{
type: "success" | "error";
text: string;
} | null>(null);
const handleSeed = async (e: React.FormEvent) => {
// Implementation for seeding CMS data
};
return (
<div className="container mx-auto py-10">
<h1 className="mb-8 text-3xl font-bold">CMS Management</h1>
{/* CMS management interface */}
</div>
);
}
Activity Monitoring
The activity log provides insights into system activity:
interface ActivityLogPageProps {
searchParams: Promise<{
search?: string;
category?: string;
severity?: string;
startDate?: string;
endDate?: string;
userId?: string;
teamId?: string;
resourceType?: string;
page?: string;
}>;
}
export default function ActivityLogPage(props: ActivityLogPageProps) {
return (
<div className="container mx-auto py-10">
<Card>
<CardHeader>
<CardTitle>Activity Log</CardTitle>
</CardHeader>
<CardContent>
<Suspense fallback={<ActivityLogLoading />}>
<ActivityLogContent {...props} />
</Suspense>
</CardContent>
</Card>
</div>
);
}
Feedback Management
The feedback section allows administrators to review user feedback:
export default async function FeedbackPage() {
const feedbackItems = await getFeedback();
return (
<div className="container mx-auto py-8">
<h1 className="mb-8 text-3xl font-bold">Feedback</h1>
<div className="grid gap-4">
{/* Feedback items display */}
</div>
</div>
);
}
AI System Management
The AI section provides tools for managing AI features:
export default function AIPage() {
return (
<div className="container mx-auto py-10">
<div className="mb-8">
<h1 className="text-3xl font-bold">AI System</h1>
<p className="mt-2 text-muted-foreground">
Explore the AI loader system that helps onboard and assist AI
programming assistants.
</p>
</div>
<Tabs defaultValue="context" className="space-y-4">
<TabsList>
<TabsTrigger value="context">Context</TabsTrigger>
<TabsTrigger value="analyzer">Analyzer</TabsTrigger>
<TabsTrigger value="assistant">Assistant</TabsTrigger>
</TabsList>
{/* AI management interface */}
</Tabs>
</div>
);
}
Components
Data Table
The data table component provides a reusable interface for displaying and managing data:
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
// Implementation includes:
// - Sorting
// - Filtering
// - Pagination
// - Row selection
}
AI Components
Context Viewer
export const AIContextViewer = () => {
const context = aiLoader.getContext();
return (
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="technologies">
<AccordionTrigger>Technology Stack</AccordionTrigger>
<AccordionContent>
{/* Technology stack display */}
</AccordionContent>
</AccordionItem>
{/* Other context sections */}
</Accordion>
);
};
Analyzer Viewer
export const AIAnalyzerViewer = () => {
const insights = aiAnalyzer.getCodebaseInsights();
const [selectedFeature, setSelectedFeature] = useState("authentication");
return (
<div className="space-y-8">
{/* Feature implementation guide */}
{/* Codebase insights */}
{/* Common pitfalls */}
{/* Recommended tools */}
{/* Performance optimizations */}
</div>
);
};
Assistant Viewer
export const AIAssistantViewer = () => {
const [selectedFeature, setSelectedFeature] = useState("authentication");
const [selectedTech, setSelectedTech] = useState<keyof TechnologyStack>("framework");
return (
<div className="space-y-8">
{/* Implementation guidance */}
{/* Technology best practices */}
{/* Code review guidelines */}
{/* File structure */}
{/* Security guidelines */}
</div>
);
};
Security
Access Control
Role-based access using isAdmin
check
Protected routes and API endpoints
Session validation
Data Protection
Secure handling of sensitive information
Encrypted communication
Input validation and sanitization
Audit Trail
Activity logging
User action tracking
System event monitoring
Best Practices
Performance
Efficient data loading with suspense
Optimized table rendering
Lazy loading of components
User Experience
Responsive design
Clear feedback messages
Intuitive navigation
Code Organization
Component-based architecture
Separation of concerns
Type safety with TypeScript
Error Handling
Form Validation
try {
const result = await seedCMSAction(adminSecret);
setMessage({
type: result.success ? "success" : "error",
text: result.message,
});
} catch (error) {
setMessage({
type: "error",
text: error instanceof Error ? error.message : "An error occurred",
});
}
Loading States
<Suspense fallback={<ActivityLogLoading />}>
<ActivityLogContent {...props} />
</Suspense>
Empty States
{feedbackItems.length === 0 && (
<p className="text-center text-muted-foreground">
No feedback received yet.
</p>
)}
Testing
Component Tests
describe('AdminPanel', () => {
it('should restrict access to admin users', () => {
// Test implementation
});
it('should display user management interface', () => {
// Test implementation
});
it('should handle CMS operations', () => {
// Test implementation
});
});
Integration Tests
describe('AdminIntegration', () => {
it('should manage users effectively', () => {
// Test implementation
});
it('should track activity correctly', () => {
// Test implementation
});
});
Customization
Adding New Features
// Add new nav link
const navLinks = [
...existingLinks,
{ href: routes.admin.newFeature, label: "New Feature" },
];
// Create new page component
export default function NewFeaturePage() {
return (
<div className="container mx-auto py-10">
<h1 className="mb-8 text-3xl font-bold">New Feature</h1>
{/* Feature implementation */}
</div>
);
}
Styling
// Use Tailwind CSS for consistent styling
<div className="rounded-lg border bg-card p-4 text-card-foreground shadow-sm">
{/* Component content */}
</div>
Layout
// Responsive grid layout
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{/* Grid items */}
</div>