Sofondo
SofondoFrameworkDocs

Sofondo Framework - Example Applications

Complete examples demonstrating how to build real-world admin panels with the Sofondo Framework.

Table of Contents


E-commerce Admin Panel

A complete e-commerce admin panel for managing products, orders, customers, and inventory.

Overview

Features:

  • Product management (CRUD operations)
  • Order tracking and fulfillment
  • Customer management
  • Inventory monitoring
  • Sales analytics dashboard
  • Real-time notifications
// app/(admin)/layout.tsx
import { AdminLayout } from '@sofondo/next';
import {
  LayoutDashboard,
  Package,
  ShoppingCart,
  Users,
  Warehouse,
  BarChart3,
  Settings,
  Tag,
} from 'lucide-react';

const menuItems = [
  {
    icon: LayoutDashboard,
    label: 'Dashboard',
    href: '/dashboard',
    exact: true,
  },
  {
    icon: Package,
    label: 'Products',
    href: '/products',
  },
  {
    icon: ShoppingCart,
    label: 'Orders',
    href: '/orders',
  },
  {
    icon: Users,
    label: 'Customers',
    href: '/customers',
  },
  {
    icon: Warehouse,
    label: 'Inventory',
    href: '/inventory',
  },
  {
    icon: Tag,
    label: 'Categories',
    href: '/categories',
  },
  {
    icon: BarChart3,
    label: 'Analytics',
    href: '/analytics',
  },
  {
    icon: Settings,
    label: 'Settings',
    href: '/settings',
  },
];

export default function EcommerceLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <AdminLayout
      menuItems={menuItems}
      user={{
        name: 'Store Admin',
        email: 'admin@store.com',
      }}
    >
      {children}
    </AdminLayout>
  );
}

Dashboard Page

// app/(admin)/dashboard/page.tsx
import {
  PageHeader,
  StatCard,
  StatGrid,
  DataGrid,
  ProgressBar,
} from '@sofondo/react';
import {
  DollarSign,
  ShoppingCart,
  Users,
  TrendingUp,
  Package,
  AlertCircle,
} from 'lucide-react';
import { getStorageStatus, getStorageColor } from '@sofondo/core';

// Mock data
const recentOrders = [
  {
    id: 'ORD-001',
    customer: 'Alice Johnson',
    amount: '$234.50',
    status: 'Shipped',
    date: '2025-12-01',
  },
  {
    id: 'ORD-002',
    customer: 'Bob Smith',
    amount: '$156.00',
    status: 'Processing',
    date: '2025-12-02',
  },
  {
    id: 'ORD-003',
    customer: 'Carol White',
    amount: '$89.99',
    status: 'Delivered',
    date: '2025-12-03',
  },
];

const lowStockProducts = [
  { id: 1, name: 'Wireless Mouse', stock: 5, reorderPoint: 20 },
  { id: 2, name: 'USB Cable', stock: 8, reorderPoint: 50 },
  { id: 3, name: 'Laptop Stand', stock: 3, reorderPoint: 15 },
];

export default function EcommerceDashboard() {
  return (
    <>
      <PageHeader
        title="E-commerce Dashboard"
        subtitle="Overview of your store performance"
      />

      {/* Key Metrics */}
      <StatGrid>
        <StatCard
          icon={DollarSign}
          label="Total Revenue"
          value="$45,234"
          change="+12% from last month"
          changeClassName="positive"
        />
        <StatCard
          icon={ShoppingCart}
          label="Total Orders"
          value="1,234"
          change="+8% from last month"
          changeClassName="positive"
        />
        <StatCard
          icon={Users}
          label="Active Customers"
          value="567"
          change="+15% from last month"
          changeClassName="positive"
        />
        <StatCard
          icon={TrendingUp}
          label="Conversion Rate"
          value="3.2%"
          change="+0.5% from last month"
          changeClassName="positive"
        />
      </StatGrid>

      <div style={{ marginTop: '30px' }}>
        <h3>Recent Orders</h3>
        <DataGrid
          data={recentOrders}
          keyField="id"
          columns={[
            { key: 'id', header: 'Order ID', width: '1fr' },
            { key: 'customer', header: 'Customer', width: '2fr' },
            { key: 'amount', header: 'Amount', width: '1fr' },
            { key: 'status', header: 'Status', width: '1fr' },
            { key: 'date', header: 'Date', width: '1fr' },
          ]}
        />
      </div>

      <div style={{ marginTop: '30px' }}>
        <h3>
          <AlertCircle size={20} style={{ verticalAlign: 'middle' }} />
          {' '}Low Stock Alert
        </h3>
        <DataGrid
          data={lowStockProducts}
          keyField="id"
          columns={[
            { key: 'name', header: 'Product', width: '2fr' },
            { key: 'stock', header: 'Current Stock', width: '1fr' },
            { key: 'reorderPoint', header: 'Reorder Point', width: '1fr' },
            {
              key: 'status',
              header: 'Status',
              width: '2fr',
              render: (item) => {
                const status = getStorageStatus(item.stock, item.reorderPoint, true);
                const color = getStorageColor(status);
                return (
                  <div>
                    <ProgressBar
                      value={item.stock}
                      max={item.reorderPoint}
                      color={color}
                      height={8}
                    />
                  </div>
                );
              },
            },
          ]}
        />
      </div>
    </>
  );
}

Products Page

// app/(admin)/products/page.tsx
'use client';

import { useState } from 'react';
import { PageHeader, DataGrid, Skeleton } from '@sofondo/react';
import { useToast } from '@sofondo/react';
import { Plus, Edit, Trash2, Image } from 'lucide-react';

interface Product {
  id: number;
  name: string;
  category: string;
  price: string;
  stock: number;
  status: 'Active' | 'Draft' | 'Out of Stock';
}

const mockProducts: Product[] = [
  { id: 1, name: 'Wireless Mouse', category: 'Electronics', price: '$29.99', stock: 45, status: 'Active' },
  { id: 2, name: 'USB Cable', category: 'Accessories', price: '$9.99', stock: 120, status: 'Active' },
  { id: 3, name: 'Laptop Stand', category: 'Furniture', price: '$49.99', stock: 0, status: 'Out of Stock' },
  { id: 4, name: 'Keyboard', category: 'Electronics', price: '$79.99', stock: 30, status: 'Active' },
  { id: 5, name: 'Monitor Arm', category: 'Furniture', price: '$129.99', stock: 15, status: 'Active' },
];

export default function ProductsPage() {
  const [products, setProducts] = useState<Product[]>(mockProducts);
  const [loading, setLoading] = useState(false);
  const { addToast } = useToast();

  const handleEdit = (product: Product) => {
    addToast(`Editing ${product.name}`, 'info');
  };

  const handleDelete = (product: Product) => {
    setProducts(products.filter(p => p.id !== product.id));
    addToast(`${product.name} deleted`, 'success');
  };

  const handleAddProduct = () => {
    addToast('Add product form would open here', 'info');
  };

  return (
    <>
      <PageHeader
        title="Products"
        subtitle="Manage your product catalog"
        actions={
          <button
            onClick={handleAddProduct}
            style={{
              padding: '8px 16px',
              backgroundColor: 'var(--primary)',
              color: 'white',
              border: 'none',
              borderRadius: '4px',
              cursor: 'pointer',
              display: 'flex',
              alignItems: 'center',
              gap: '8px',
            }}
          >
            <Plus size={16} />
            Add Product
          </button>
        }
      />

      {loading ? (
        <>
          <Skeleton width="100%" height={50} />
          <Skeleton width="100%" height={50} />
          <Skeleton width="100%" height={50} />
        </>
      ) : (
        <DataGrid
          data={products}
          keyField="id"
          columns={[
            {
              key: 'name',
              header: 'Product Name',
              width: '2fr',
              render: (item) => (
                <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                  <Image size={20} />
                  {item.name}
                </div>
              ),
            },
            { key: 'category', header: 'Category', width: '1fr' },
            { key: 'price', header: 'Price', width: '1fr' },
            {
              key: 'stock',
              header: 'Stock',
              width: '1fr',
              render: (item) => (
                <span style={{ color: item.stock === 0 ? 'red' : 'inherit' }}>
                  {item.stock}
                </span>
              ),
            },
            {
              key: 'status',
              header: 'Status',
              width: '1fr',
              render: (item) => (
                <span
                  style={{
                    padding: '4px 8px',
                    borderRadius: '4px',
                    fontSize: '12px',
                    backgroundColor:
                      item.status === 'Active'
                        ? '#e6f7ed'
                        : item.status === 'Out of Stock'
                        ? '#ffe6e6'
                        : '#f0f0f0',
                    color:
                      item.status === 'Active'
                        ? '#0f9d58'
                        : item.status === 'Out of Stock'
                        ? '#ea4335'
                        : '#666',
                  }}
                >
                  {item.status}
                </span>
              ),
            },
            {
              key: 'actions',
              header: 'Actions',
              width: '1fr',
              render: (item) => (
                <div style={{ display: 'flex', gap: '8px' }}>
                  <button
                    onClick={() => handleEdit(item)}
                    style={{
                      padding: '4px 8px',
                      border: '1px solid #ccc',
                      borderRadius: '4px',
                      cursor: 'pointer',
                      background: 'white',
                    }}
                  >
                    <Edit size={14} />
                  </button>
                  <button
                    onClick={() => handleDelete(item)}
                    style={{
                      padding: '4px 8px',
                      border: '1px solid #ea4335',
                      borderRadius: '4px',
                      cursor: 'pointer',
                      background: 'white',
                      color: '#ea4335',
                    }}
                  >
                    <Trash2 size={14} />
                  </button>
                </div>
              ),
            },
          ]}
        />
      )}
    </>
  );
}

Orders Page

// app/(admin)/orders/page.tsx
'use client';

import { useState } from 'react';
import { PageHeader, DataGrid } from '@sofondo/react';
import { Filter, Download } from 'lucide-react';

interface Order {
  id: string;
  customer: string;
  email: string;
  amount: string;
  status: 'Processing' | 'Shipped' | 'Delivered' | 'Cancelled';
  date: string;
}

const mockOrders: Order[] = [
  { id: 'ORD-001', customer: 'Alice Johnson', email: 'alice@email.com', amount: '$234.50', status: 'Shipped', date: '2025-12-01' },
  { id: 'ORD-002', customer: 'Bob Smith', email: 'bob@email.com', amount: '$156.00', status: 'Processing', date: '2025-12-02' },
  { id: 'ORD-003', customer: 'Carol White', email: 'carol@email.com', amount: '$89.99', status: 'Delivered', date: '2025-12-03' },
  { id: 'ORD-004', customer: 'David Brown', email: 'david@email.com', amount: '$445.00', status: 'Processing', date: '2025-12-03' },
  { id: 'ORD-005', customer: 'Eve Davis', email: 'eve@email.com', amount: '$299.99', status: 'Shipped', date: '2025-12-04' },
];

export default function OrdersPage() {
  const [orders] = useState<Order[]>(mockOrders);
  const [filter, setFilter] = useState<string>('All');

  const filteredOrders = filter === 'All'
    ? orders
    : orders.filter(order => order.status === filter);

  const handleExport = () => {
    console.log('Exporting orders...');
  };

  return (
    <>
      <PageHeader
        title="Orders"
        subtitle={`${filteredOrders.length} orders`}
        actions={
          <div style={{ display: 'flex', gap: '10px' }}>
            <select
              value={filter}
              onChange={(e) => setFilter(e.target.value)}
              style={{
                padding: '8px 16px',
                border: '1px solid #ccc',
                borderRadius: '4px',
                cursor: 'pointer',
              }}
            >
              <option value="All">All Orders</option>
              <option value="Processing">Processing</option>
              <option value="Shipped">Shipped</option>
              <option value="Delivered">Delivered</option>
              <option value="Cancelled">Cancelled</option>
            </select>
            <button
              onClick={handleExport}
              style={{
                padding: '8px 16px',
                border: '1px solid #ccc',
                borderRadius: '4px',
                cursor: 'pointer',
                display: 'flex',
                alignItems: 'center',
                gap: '8px',
              }}
            >
              <Download size={16} />
              Export
            </button>
          </div>
        }
      />

      <DataGrid
        data={filteredOrders}
        keyField="id"
        columns={[
          { key: 'id', header: 'Order ID', width: '1fr' },
          { key: 'customer', header: 'Customer', width: '2fr' },
          { key: 'email', header: 'Email', width: '2fr' },
          { key: 'amount', header: 'Amount', width: '1fr' },
          {
            key: 'status',
            header: 'Status',
            width: '1fr',
            render: (item) => {
              const statusColors = {
                Processing: { bg: '#fff3cd', color: '#856404' },
                Shipped: { bg: '#d1ecf1', color: '#0c5460' },
                Delivered: { bg: '#d4edda', color: '#155724' },
                Cancelled: { bg: '#f8d7da', color: '#721c24' },
              };
              const colors = statusColors[item.status];
              return (
                <span
                  style={{
                    padding: '4px 8px',
                    borderRadius: '4px',
                    fontSize: '12px',
                    backgroundColor: colors.bg,
                    color: colors.color,
                  }}
                >
                  {item.status}
                </span>
              );
            },
          },
          { key: 'date', header: 'Date', width: '1fr' },
        ]}
      />
    </>
  );
}

Educational Platform Dashboard

A comprehensive educational platform for managing courses, students, assignments, and analytics.

Overview

Features:

  • Course management
  • Student enrollment tracking
  • Assignment submission and grading
  • Progress monitoring
  • Analytics and reporting
  • Communication tools
// app/(admin)/layout.tsx
import { AdminLayout } from '@sofondo/next';
import {
  LayoutDashboard,
  BookOpen,
  Users,
  ClipboardList,
  BarChart3,
  MessageSquare,
  Calendar,
  Settings,
  Award,
} from 'lucide-react';

const menuItems = [
  {
    icon: LayoutDashboard,
    label: 'Dashboard',
    href: '/dashboard',
    exact: true,
  },
  {
    icon: BookOpen,
    label: 'Courses',
    href: '/courses',
  },
  {
    icon: Users,
    label: 'Students',
    href: '/students',
  },
  {
    icon: ClipboardList,
    label: 'Assignments',
    href: '/assignments',
  },
  {
    icon: Award,
    label: 'Grades',
    href: '/grades',
  },
  {
    icon: Calendar,
    label: 'Schedule',
    href: '/schedule',
  },
  {
    icon: MessageSquare,
    label: 'Messages',
    href: '/messages',
  },
  {
    icon: BarChart3,
    label: 'Analytics',
    href: '/analytics',
  },
  {
    icon: Settings,
    label: 'Settings',
    href: '/settings',
  },
];

export default function EducationLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <AdminLayout
      menuItems={menuItems}
      user={{
        name: 'Prof. Smith',
        email: 'smith@university.edu',
      }}
    >
      {children}
    </AdminLayout>
  );
}

Dashboard Page

// app/(admin)/dashboard/page.tsx
import {
  PageHeader,
  StatCard,
  StatGrid,
  DataGrid,
  ProgressBar,
} from '@sofondo/react';
import {
  BookOpen,
  Users,
  ClipboardList,
  TrendingUp,
  Award,
  Clock,
} from 'lucide-react';
import { getStorageStatus, getStorageColor } from '@sofondo/core';

const upcomingAssignments = [
  {
    id: 1,
    course: 'Introduction to React',
    assignment: 'Build a Todo App',
    dueDate: '2025-12-10',
    submissions: 23,
    totalStudents: 30,
  },
  {
    id: 2,
    course: 'Advanced TypeScript',
    assignment: 'Type System Project',
    dueDate: '2025-12-12',
    submissions: 18,
    totalStudents: 25,
  },
  {
    id: 3,
    course: 'Web Design Principles',
    assignment: 'Portfolio Website',
    dueDate: '2025-12-15',
    submissions: 12,
    totalStudents: 28,
  },
];

const recentActivity = [
  { id: 1, student: 'Alice Johnson', action: 'Submitted assignment', course: 'React Basics', time: '5 min ago' },
  { id: 2, student: 'Bob Smith', action: 'Completed course', course: 'TypeScript', time: '15 min ago' },
  { id: 3, student: 'Carol White', action: 'Asked question', course: 'Web Design', time: '1 hour ago' },
];

export default function EducationDashboard() {
  return (
    <>
      <PageHeader
        title="Education Dashboard"
        subtitle="Overview of your courses and students"
      />

      {/* Key Metrics */}
      <StatGrid>
        <StatCard
          icon={BookOpen}
          label="Active Courses"
          value="12"
          change="2 new this semester"
          changeClassName="positive"
        />
        <StatCard
          icon={Users}
          label="Total Students"
          value="234"
          change="+18 from last month"
          changeClassName="positive"
        />
        <StatCard
          icon={ClipboardList}
          label="Pending Assignments"
          value="45"
          change="15 due this week"
          changeClassName="warning"
        />
        <StatCard
          icon={TrendingUp}
          label="Completion Rate"
          value="87%"
          change="+3% from last semester"
          changeClassName="positive"
        />
      </StatGrid>

      <div style={{ marginTop: '30px' }}>
        <h3>
          <Clock size={20} style={{ verticalAlign: 'middle' }} />
          {' '}Upcoming Assignments
        </h3>
        <DataGrid
          data={upcomingAssignments}
          keyField="id"
          columns={[
            { key: 'course', header: 'Course', width: '2fr' },
            { key: 'assignment', header: 'Assignment', width: '2fr' },
            { key: 'dueDate', header: 'Due Date', width: '1fr' },
            {
              key: 'progress',
              header: 'Submissions',
              width: '2fr',
              render: (item) => {
                const percentage = (item.submissions / item.totalStudents) * 100;
                const status = getStorageStatus(percentage, 100, true);
                const color = getStorageColor(status);
                return (
                  <div>
                    <div>{item.submissions} / {item.totalStudents}</div>
                    <ProgressBar
                      value={item.submissions}
                      max={item.totalStudents}
                      color={color}
                      height={6}
                    />
                  </div>
                );
              },
            },
          ]}
        />
      </div>

      <div style={{ marginTop: '30px' }}>
        <h3>Recent Activity</h3>
        <DataGrid
          data={recentActivity}
          keyField="id"
          columns={[
            { key: 'student', header: 'Student', width: '2fr' },
            { key: 'action', header: 'Action', width: '2fr' },
            { key: 'course', header: 'Course', width: '2fr' },
            { key: 'time', header: 'Time', width: '1fr' },
          ]}
        />
      </div>
    </>
  );
}

Courses Page

// app/(admin)/courses/page.tsx
'use client';

import { useState } from 'react';
import { PageHeader, DataGrid } from '@sofondo/react';
import { useToast } from '@sofondo/react';
import { Plus, Edit, Users, BarChart } from 'lucide-react';

interface Course {
  id: number;
  title: string;
  instructor: string;
  students: number;
  completion: number;
  status: 'Active' | 'Archived' | 'Draft';
}

const mockCourses: Course[] = [
  { id: 1, title: 'Introduction to React', instructor: 'Prof. Smith', students: 30, completion: 75, status: 'Active' },
  { id: 2, title: 'Advanced TypeScript', instructor: 'Dr. Johnson', students: 25, completion: 60, status: 'Active' },
  { id: 3, title: 'Web Design Principles', instructor: 'Prof. Brown', students: 28, completion: 85, status: 'Active' },
  { id: 4, title: 'Database Systems', instructor: 'Dr. Davis', students: 22, completion: 45, status: 'Active' },
  { id: 5, title: 'Python for Beginners', instructor: 'Prof. Wilson', students: 35, completion: 90, status: 'Active' },
];

export default function CoursesPage() {
  const [courses] = useState<Course[]>(mockCourses);
  const { addToast } = useToast();

  const handleEdit = (course: Course) => {
    addToast(`Editing ${course.title}`, 'info');
  };

  const handleViewStudents = (course: Course) => {
    addToast(`Viewing students for ${course.title}`, 'info');
  };

  const handleViewAnalytics = (course: Course) => {
    addToast(`Viewing analytics for ${course.title}`, 'info');
  };

  return (
    <>
      <PageHeader
        title="Courses"
        subtitle="Manage your courses"
        actions={
          <button
            onClick={() => addToast('Create course form would open', 'info')}
            style={{
              padding: '8px 16px',
              backgroundColor: 'var(--primary)',
              color: 'white',
              border: 'none',
              borderRadius: '4px',
              cursor: 'pointer',
              display: 'flex',
              alignItems: 'center',
              gap: '8px',
            }}
          >
            <Plus size={16} />
            Create Course
          </button>
        }
      />

      <DataGrid
        data={courses}
        keyField="id"
        columns={[
          { key: 'title', header: 'Course Title', width: '3fr' },
          { key: 'instructor', header: 'Instructor', width: '2fr' },
          {
            key: 'students',
            header: 'Students',
            width: '1fr',
            render: (item) => (
              <span style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
                <Users size={14} />
                {item.students}
              </span>
            ),
          },
          {
            key: 'completion',
            header: 'Avg. Completion',
            width: '1fr',
            render: (item) => `${item.completion}%`,
          },
          {
            key: 'status',
            header: 'Status',
            width: '1fr',
            render: (item) => (
              <span
                style={{
                  padding: '4px 8px',
                  borderRadius: '4px',
                  fontSize: '12px',
                  backgroundColor: item.status === 'Active' ? '#e6f7ed' : '#f0f0f0',
                  color: item.status === 'Active' ? '#0f9d58' : '#666',
                }}
              >
                {item.status}
              </span>
            ),
          },
          {
            key: 'actions',
            header: 'Actions',
            width: '2fr',
            render: (item) => (
              <div style={{ display: 'flex', gap: '8px' }}>
                <button
                  onClick={() => handleEdit(item)}
                  style={{
                    padding: '4px 8px',
                    border: '1px solid #ccc',
                    borderRadius: '4px',
                    cursor: 'pointer',
                    background: 'white',
                  }}
                >
                  <Edit size={14} />
                </button>
                <button
                  onClick={() => handleViewStudents(item)}
                  style={{
                    padding: '4px 8px',
                    border: '1px solid #ccc',
                    borderRadius: '4px',
                    cursor: 'pointer',
                    background: 'white',
                  }}
                >
                  <Users size={14} />
                </button>
                <button
                  onClick={() => handleViewAnalytics(item)}
                  style={{
                    padding: '4px 8px',
                    border: '1px solid #ccc',
                    borderRadius: '4px',
                    cursor: 'pointer',
                    background: 'white',
                  }}
                >
                  <BarChart size={14} />
                </button>
              </div>
            ),
          },
        ]}
      />
    </>
  );
}

Students Page

// app/(admin)/students/page.tsx
'use client';

import { useState } from 'react';
import { PageHeader, DataGrid, ProgressBar } from '@sofondo/react';
import { Search, Mail } from 'lucide-react';
import { getStorageStatus, getStorageColor } from '@sofondo/core';

interface Student {
  id: number;
  name: string;
  email: string;
  enrolledCourses: number;
  completedCourses: number;
  overallProgress: number;
  lastActive: string;
}

const mockStudents: Student[] = [
  { id: 1, name: 'Alice Johnson', email: 'alice@university.edu', enrolledCourses: 4, completedCourses: 2, overallProgress: 78, lastActive: '2 hours ago' },
  { id: 2, name: 'Bob Smith', email: 'bob@university.edu', enrolledCourses: 3, completedCourses: 1, overallProgress: 65, lastActive: '1 day ago' },
  { id: 3, name: 'Carol White', email: 'carol@university.edu', enrolledCourses: 5, completedCourses: 3, overallProgress: 92, lastActive: '30 min ago' },
  { id: 4, name: 'David Brown', email: 'david@university.edu', enrolledCourses: 3, completedCourses: 0, overallProgress: 45, lastActive: '3 days ago' },
  { id: 5, name: 'Eve Davis', email: 'eve@university.edu', enrolledCourses: 4, completedCourses: 2, overallProgress: 88, lastActive: '1 hour ago' },
];

export default function StudentsPage() {
  const [students] = useState<Student[]>(mockStudents);
  const [searchTerm, setSearchTerm] = useState('');

  const filteredStudents = students.filter(student =>
    student.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
    student.email.toLowerCase().includes(searchTerm.toLowerCase())
  );

  return (
    <>
      <PageHeader
        title="Students"
        subtitle={`${filteredStudents.length} students enrolled`}
        actions={
          <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
            <Search size={16} />
            <input
              type="text"
              placeholder="Search students..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              style={{
                padding: '8px 12px',
                border: '1px solid #ccc',
                borderRadius: '4px',
                width: '250px',
              }}
            />
          </div>
        }
      />

      <DataGrid
        data={filteredStudents}
        keyField="id"
        columns={[
          { key: 'name', header: 'Student Name', width: '2fr' },
          {
            key: 'email',
            header: 'Email',
            width: '2fr',
            render: (item) => (
              <a
                href={`mailto:${item.email}`}
                style={{ color: 'var(--primary)', textDecoration: 'none' }}
              >
                {item.email}
              </a>
            ),
          },
          {
            key: 'courses',
            header: 'Courses',
            width: '1fr',
            render: (item) => `${item.completedCourses}/${item.enrolledCourses}`,
          },
          {
            key: 'progress',
            header: 'Overall Progress',
            width: '2fr',
            render: (item) => {
              const status = getStorageStatus(item.overallProgress, 100, true);
              const color = getStorageColor(status);
              return (
                <div>
                  <div style={{ marginBottom: '4px' }}>{item.overallProgress}%</div>
                  <ProgressBar
                    value={item.overallProgress}
                    max={100}
                    color={color}
                    height={6}
                  />
                </div>
              );
            },
          },
          { key: 'lastActive', header: 'Last Active', width: '1fr' },
        ]}
      />
    </>
  );
}

Common Patterns

Pattern 1: Data Fetching with Loading States

'use client';

import { useState, useEffect } from 'react';
import { DataGrid, Skeleton } from '@sofondo/react';

export function DataWithLoading() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchData().then(result => {
      setData(result);
      setLoading(false);
    });
  }, []);

  if (loading) {
    return (
      <>
        <Skeleton width="100%" height={50} />
        <Skeleton width="100%" height={50} />
        <Skeleton width="100%" height={50} />
      </>
    );
  }

  return (
    <DataGrid
      data={data}
      keyField="id"
      columns={[/* ... */]}
    />
  );
}

Pattern 2: Form with Toast Notifications

'use client';

import { useState } from 'react';
import { useToast } from '@sofondo/react';

export function FormWithToast() {
  const [formData, setFormData] = useState({ name: '', email: '' });
  const { addToast } = useToast();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    try {
      await saveData(formData);
      addToast('Data saved successfully!', 'success');
      setFormData({ name: '', email: '' });
    } catch (error) {
      addToast('Failed to save data', 'error');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
      <button type="submit">Save</button>
    </form>
  );
}

Pattern 3: Status Indicators with Progress

import { ProgressBar } from '@sofondo/react';
import { getStorageStatus, getStorageColor } from '@sofondo/core';

export function StatusIndicator({ current, max }: { current: number; max: number }) {
  const status = getStorageStatus(current, max, true);
  const color = getStorageColor(status);
  const percentage = (current / max) * 100;

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '4px' }}>
        <span>{current} / {max}</span>
        <span>{percentage.toFixed(0)}%</span>
      </div>
      <ProgressBar value={current} max={max} color={color} height={8} />
    </div>
  );
}

Pattern 4: Responsive Actions

'use client';

import { useMediaQuery } from '@sofondo/react';
import { MoreVertical } from 'lucide-react';

export function ResponsiveActions() {
  const isMobile = useMediaQuery('(max-width: 768px)');

  if (isMobile) {
    return (
      <button>
        <MoreVertical size={16} />
      </button>
    );
  }

  return (
    <div style={{ display: 'flex', gap: '8px' }}>
      <button>Edit</button>
      <button>Delete</button>
      <button>Share</button>
    </div>
  );
}

Integration Examples

With React Query

'use client';

import { useQuery } from '@tanstack/react-query';
import { DataGrid, Skeleton } from '@sofondo/react';

export function ProductList() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['products'],
    queryFn: fetchProducts,
  });

  if (isLoading) {
    return (
      <>
        <Skeleton width="100%" height={50} />
        <Skeleton width="100%" height={50} />
      </>
    );
  }

  if (error) {
    return <div>Error loading products</div>;
  }

  return (
    <DataGrid
      data={data}
      keyField="id"
      columns={[/* ... */]}
    />
  );
}

With Form Libraries (React Hook Form)

'use client';

import { useForm } from 'react-hook-form';
import { useToast } from '@sofondo/react';

export function ProductForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();
  const { addToast } = useToast();

  const onSubmit = async (data) => {
    try {
      await saveProduct(data);
      addToast('Product saved!', 'success');
    } catch (error) {
      addToast('Failed to save product', 'error');
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name', { required: true })} />
      {errors.name && <span>Name is required</span>}
      <button type="submit">Save</button>
    </form>
  );
}

With State Management (Zustand)

'use client';

import { create } from 'zustand';
import { useToast } from '@sofondo/react';

const useStore = create((set) => ({
  products: [],
  addProduct: (product) => set((state) => ({
    products: [...state.products, product]
  })),
}));

export function ProductManager() {
  const { products, addProduct } = useStore();
  const { addToast } = useToast();

  const handleAdd = () => {
    addProduct({ id: Date.now(), name: 'New Product' });
    addToast('Product added!', 'success');
  };

  return (
    <div>
      <button onClick={handleAdd}>Add Product</button>
      {/* Render products */}
    </div>
  );
}

Summary

These examples demonstrate:

E-commerce Admin - Complete product, order, and customer management ✅ Educational Platform - Course, student, and assignment tracking ✅ Common Patterns - Reusable patterns for loading, forms, status, and responsive design ✅ Integrations - Working with popular React libraries

All examples use Sofondo Framework components with best practices for building production-ready admin panels.

Next Steps

  1. Copy and customize these examples for your use case
  2. Refer to the API Reference for complete component documentation
  3. Follow the Migration Strategy for integrating into existing projects
  4. Check the Configuration Guide for customization options