Architecture¶
Source: pharmanet-admin/src/
Project Structure¶
src/
├── main.jsx # Entry point
├── App.jsx # Provider wrappers (Redux, Router, Theme)
├── routes.jsx # React Router v6 config
├── assets/styles/ # Global CSS + MUI theme (light/dark)
├── components/
│ ├── common/ # DataTable, ErrorBoundary, LoadingSpinner, etc.
│ ├── layouts/ # Header, Sidebar, MainLayout, AuthLayout
│ ├── dashboard/ # Charts, StatsCards, QuickActions
│ ├── products/ # ProductForm, ProductList, VariantManager
│ ├── orders/ # OrderList, OrderDetails, OrderTimeline
│ ├── users/ # UserList, ApprovePharmacies, DocumentViewer
│ ├── payments/ # TransactionList, ChapaConfig, PaymentLogs
│ ├── cms/ # Banners, BannerForm, PageEditor
│ ├── reports/ # SalesReport, ProductPerformance
│ ├── settings/ # GeneralSettings, EmailSettings
│ └── categories/ # CategoryTree, CategoryForm
├── pages/ # Lazy-loaded page components
├── services/ # 18 Supabase service modules
├── store/ # 9 Redux Toolkit slices
├── hooks/ # usePagination, useInactivityLogout, useTokenManager
├── utils/ # Constants, formatters, validators, helpers
└── test/ # Integration, accessibility, visual tests
Routing¶
// src/routes.jsx — createBrowserRouter
const router = createBrowserRouter([
{
path: '/',
element: <ProtectedRoute><MainLayout /></ProtectedRoute>,
children: [
{ index: true, element: <Dashboard /> },
{ path: 'users', element: <Users /> },
{ path: 'products', element: <Products /> },
{ path: 'orders', element: <Orders /> },
{ path: 'payments', element: <Payments /> },
{ path: 'cms', element: <CMS /> },
{ path: 'promotions', element: <Promotions /> },
{ path: 'reports', element: <Reports /> },
{ path: 'settings', element: <Settings /> },
{ path: 'featured-products', element: <AdminFeaturedProducts /> },
{ path: 'subscriptions', element: <AdminPharmacySubscriptions /> },
],
},
{
path: '/auth',
element: <AuthLayout />,
children: [
{ path: 'login', element: <Login /> },
{ path: 'forgot-password', element: <ForgotPassword /> },
{ path: 'reset-password', element: <ResetPassword /> },
],
},
]);
All pages are lazy-loaded with React.lazy() + <Suspense>.
State Management: Redux Toolkit¶
9 slices compose the store:
const store = configureStore({
reducer: {
auth: authReducer,
users: userReducer,
products: productReducer,
orders: orderReducer,
ui: uiReducer,
dashboard: dashboardReducer,
categories: categoryReducer,
featureProduct: featureProductReducer,
pharmacySubscription: pharmacySubscriptionReducer,
},
});
Sidebar Navigation¶
| Item | Icon | Path |
|---|---|---|
| Dashboard | DashboardIcon |
/ |
| Users | PeopleIcon |
/users |
| Categories | CategoryIcon |
/categories |
| Products | InventoryIcon |
/products |
| Orders | ReceiptLongIcon |
/orders |
| Payments | PaymentIcon |
/payments |
| CMS | ArticleIcon |
/cms |
| Reports | AssessmentIcon |
/reports |
| Settings | SettingsIcon |
/settings |
| Featured Products | StarIcon |
/featured-products |
| Subscriptions | LocalPharmacyIcon |
/subscriptions |
| Promotions | CampaignIcon |
/promotions |
Data Flow¶
graph LR
UI[UI Component] --> |useDispatch| THUNK[Async Thunk]
THUNK --> |call| SVC[Service Module]
SVC --> |Supabase query| DB[(PostgreSQL)]
DB --> |response| SVC
SVC --> |return data| THUNK
THUNK --> |dispatch fulfilled| SLICE[Redux Slice]
SLICE --> |update state| STORE[Redux Store]
STORE --> |useSelector| UI
DB --> |Realtime subscription| SLICE
Related¶
- Features Overview — All features by module
- Services — Service layer reference