Admin Panel

Comprehensive guide to the ShipKit admin panel

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

  1. Access Control

    • Role-based access using isAdmin check
    • Protected routes and API endpoints
    • Session validation
  2. Data Protection

    • Secure handling of sensitive information
    • Encrypted communication
    • Input validation and sanitization
  3. Audit Trail

    • Activity logging
    • User action tracking
    • System event monitoring

Best Practices

  1. Performance

    • Efficient data loading with suspense
    • Optimized table rendering
    • Lazy loading of components
  2. User Experience

    • Responsive design
    • Clear feedback messages
    • Intuitive navigation
  3. Code Organization

    • Component-based architecture
    • Separation of concerns
    • Type safety with TypeScript

Error Handling

  1. 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",
      });
    }
    
  2. Loading States

    <Suspense fallback={<ActivityLogLoading />}>
      <ActivityLogContent {...props} />
    </Suspense>
    
  3. Empty States

    {feedbackItems.length === 0 && (
      <p className="text-center text-muted-foreground">
        No feedback received yet.
      </p>
    )}
    

Testing

  1. 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
      });
    });
    
  2. Integration Tests

    describe('AdminIntegration', () => {
      it('should manage users effectively', () => {
        // Test implementation
      });
    
      it('should track activity correctly', () => {
        // Test implementation
      });
    });
    

Customization

  1. 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>
      );
    }
    
  2. Styling

    // Use Tailwind CSS for consistent styling
    <div className="rounded-lg border bg-card p-4 text-card-foreground shadow-sm">
      {/* Component content */}
    </div>
    
  3. Layout

    // Responsive grid layout
    <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
      {/* Grid items */}
    </div>