Skip to content

Eneza Admin Dashboard ​

The Admin Dashboard is a React + TypeScript application for internal management of the Eneza platform.

Technology Stack ​

ComponentTechnology
FrameworkReact 18
Build ToolVite
LanguageTypeScript
StateReact Query
RoutingReact Router
UITailwind CSS, Radix UI
ChartsRecharts
HostingCloudflare Pages

Project Structure ​

admin-dashboard/
├── src/
│   ├── main.tsx
│   ├── App.tsx
│   ├── pages/                 # Page components (14 modules)
│   │   ├── admins/
│   │   ├── ads/
│   │   ├── advertisers/
│   │   ├── auth/
│   │   ├── dashboard/
│   │   ├── finance/
│   │   ├── kanban/
│   │   ├── notifications/
│   │   ├── screenshots/
│   │   ├── settings/
│   │   ├── subscriptions/
│   │   ├── support/
│   │   ├── system/
│   │   └── users/
│   ├── components/            # Reusable components
│   ├── hooks/                 # Custom hooks
│   ├── services/              # API clients
│   ├── stores/                # Global state
│   ├── types/                 # TypeScript types
│   └── utils/                 # Utilities
├── tailwind.config.js
└── vite.config.ts

Page Modules ​

Dashboard (/dashboard) ​

Main analytics overview.

Files:

  • DashboardPage.tsx - Overview with key metrics

Features:

  • Total users, advertisers, earnings
  • Active campaigns
  • Real-time graphs
  • Recent activity feed

Users (/users) ​

User (poster) management.

Files:

  • UsersPage.tsx - User list with filters
  • UserDetailsPage.tsx - Individual user details
  • UserActivitiesPage.tsx - User activity log

Features:

  • Search by phone/name
  • Filter by country, status, KYC
  • View/edit user profiles
  • Ban/unban users
  • View transaction history
  • View screenshot submissions

Advertisers (/advertisers) ​

Advertiser account management.

Files:

  • AdvertisersPage.tsx - Advertiser list
  • AdvertiserDetailsPage.tsx - Advertiser profile
  • AdvertiserEmailPage.tsx - Email management

Features:

  • Search by company/email
  • View campaigns
  • Credit balance manually
  • View invoices
  • Manage email preferences

Ads (/ads) ​

Ad campaign moderation.

Files:

  • AdsPage.tsx - Ad list with status tabs
  • AdDetailsPage.tsx - Full ad details

Features:

  • Moderation queue (pending review)
  • Approve/reject ads
  • View campaign statistics
  • Edit ad details
  • Pause/resume campaigns
  • Process refunds

Status Tabs:

  • Under Review
  • Active
  • Paused
  • Completed
  • Rejected

Screenshots (/screenshots) ​

Screenshot verification queue.

Files:

  • ScreenshotsPage.tsx - Screenshot queue
  • ScreenshotDetailsPage.tsx - Individual review

Features:

  • Pending review queue
  • Manual approve/reject
  • View AI verification results
  • View fraud scores
  • Bulk approve
  • Request additional proof

Finance (/finance) ​

Financial operations.

Files:

  • FinancePage.tsx - Financial overview
  • TransactionsPage.tsx - All transactions
  • TransactionDetailsPage.tsx
  • DepositsPage.tsx - Advertiser deposits
  • DepositDetailsPage.tsx
  • InvoicesPage.tsx - All invoices
  • InvoiceDetailsPage.tsx
  • RefundsPage.tsx - Refund requests
  • RefundDetailsPage.tsx

Features:

  • Pending withdrawals queue
  • Process payouts (mark as paid)
  • Download invoices
  • View deposit history
  • Process refunds

Settings (/settings) ​

Platform configuration.

Files:

  • SettingsPage.tsx - Settings overview
  • CategoriesPage.tsx - Ad categories
  • CountriesPage.tsx - Country management
  • CountryDetailsPage.tsx
  • CitiesPage.tsx - City management
  • PaymentProcessorsPage.tsx - Mobile money providers
  • AppVersionPage.tsx - Mobile app versions
  • EmailTemplatesPage.tsx - Email templates
  • TestingToolsPage.tsx - Dev tools

Features:

  • Manage ad categories
  • Configure countries (currencies, pricing tiers)
  • Manage cities
  • Configure payment processors
  • Set minimum app versions
  • Edit email templates

Admin Users (/admins) ​

Internal admin management.

Files:

  • AdminUsersPage.tsx - Admin list
  • AdminDetailsPage.tsx - Admin profile
  • PermissionManagementPage.tsx - Role permissions
  • RoleTemplatesPage.tsx - Role templates

Features:

  • Invite new admins
  • Assign roles
  • Configure permissions
  • View admin activity
  • Deactivate admins

Support (/support) ​

Customer support tickets.

Files:

  • SupportPage.tsx - Ticket list
  • SupportTicketDetailsPage.tsx - Ticket thread

Features:

  • View open tickets
  • Reply to tickets
  • Close/resolve tickets
  • Assign to admin
  • View ticket history

Notifications (/notifications) ​

Notification management.

Files:

  • NotificationsPage.tsx - Broadcast list
  • NotificationSettingsPage.tsx - Notification config

Features:

  • Create broadcast notifications
  • Schedule broadcasts
  • Target by country/segment
  • View delivery stats

Kanban (/kanban) ​

Internal task management.

Files:

  • KanbanPage.tsx - Kanban board
  • TaskDetailPage.tsx - Task details

Features:

  • Drag-and-drop tasks
  • Create/edit tasks
  • Assign to admins
  • Track progress

System (/system) ​

System monitoring.

Files:

  • SystemHealthPage.tsx - Health dashboard
  • AlertsPage.tsx - System alerts
  • FailedJobsPage.tsx - Failed jobs
  • ActivityLogsPage.tsx - Audit logs

Features:

  • Service health status
  • View system alerts
  • Retry failed jobs
  • View admin activity logs

Authentication ​

Admin authentication uses JWT tokens with role-based access.

typescript
// services/auth.ts
export const authService = {
  async login(email: string, password: string) {
    const response = await api.post('/admin/auth/login', { email, password });
    localStorage.setItem('adminToken', response.data.token);
    return response.data;
  },

  async logout() {
    await api.post('/admin/auth/logout');
    localStorage.removeItem('adminToken');
  },

  async getCurrentAdmin() {
    const response = await api.get('/admin/auth/me');
    return response.data;
  }
};

Permission Checking ​

typescript
// hooks/usePermission.ts
export function usePermission(permission: string): boolean {
  const { admin } = useAdminStore();

  if (!admin) return false;
  if (admin.role === 'super_admin') return true;

  return admin.permissions.includes(permission);
}

// Usage in components
function AdApproveButton({ adId }: { adId: string }) {
  const canApprove = usePermission('ads:moderate');

  if (!canApprove) return null;

  return <Button onClick={() => approveAd(adId)}>Approve</Button>;
}

API Client ​

typescript
// services/api.ts
import axios from 'axios';

export const api = axios.create({
  baseURL: import.meta.env.VITE_API_URL || 'https://api.eneza.app',
  headers: {
    'Content-Type': 'application/json',
  },
});

// Add auth header
api.interceptors.request.use((config) => {
  const token = localStorage.getItem('adminToken');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Handle auth errors
api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      localStorage.removeItem('adminToken');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

Data Fetching with React Query ​

typescript
// hooks/useUsers.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '../services/api';

export function useUsers(filters: UserFilters) {
  return useQuery({
    queryKey: ['users', filters],
    queryFn: async () => {
      const { data } = await api.get('/admin/users', { params: filters });
      return data;
    },
  });
}

export function useBanUser() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (userId: string) => {
      await api.post(`/admin/users/${userId}/ban`);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['users'] });
    },
  });
}

Deployment ​

Hosted on Cloudflare Pages with automatic deployments.

bash
# Build
npm run build

# Deploy
npx wrangler pages deploy dist --project-name=eneza-admin-dashboard

URLs:

  • Production: https://admin.eneza.app
  • Preview: https://dev-admin.eneza.app

Environment Variables ​

bash
VITE_API_URL=https://api.eneza.app
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...

One chat. Everything done.