Admin Portal
The Admin Portal (frontend/admin/) is a single-page application built with Vue 3, PrimeVue, and Tailwind CSS. It provides the back-office interface for managing PIX operations, monitoring transactions, and handling compliance workflows.
Technology Stack
| Library | Version | Purpose |
|---|---|---|
| Vue 3 | ^3.4 | UI framework (Composition API) |
| PrimeVue | ^4.0 | Component library |
| Tailwind CSS | ^3.4 | Utility-first styling |
| Vue Router | ^4.3 | Client-side routing |
| Pinia | ^2.1 | State management |
| Axios | ^1.7 | HTTP client |
| Chart.js | ^4.4 | Data visualization |
| VueUse | ^10.0 | Composition utilities |
Project Structure
frontend/admin/
├── src/
│ ├── assets/ # Static assets, global CSS
│ ├── components/
│ │ ├── common/ # Shared UI components
│ │ ├── dashboard/ # Dashboard widgets
│ │ ├── keys/ # Key management components
│ │ ├── payments/ # Payment monitoring
│ │ ├── settlement/ # Settlement views
│ │ └── compliance/ # Fraud & compliance
│ ├── composables/ # Reusable composition functions
│ ├── layouts/ # Page layouts
│ ├── pages/ # Route-level components
│ ├── router/ # Vue Router configuration
│ ├── services/ # API service modules
│ ├── stores/ # Pinia stores
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions
│ ├── App.vue # Root component
│ └── main.ts # Application entry point
├── public/ # Static public files
├── index.html # HTML entry point
├── vite.config.ts # Vite configuration
├── tailwind.config.js # Tailwind configuration
├── tsconfig.json # TypeScript configuration
└── package.jsonFeatures
Dashboard
The main dashboard provides a real-time overview of PIX operations:
- Transaction volume - Live counter and charts for daily transaction volume
- TPS monitor - Real-time transactions per second gauge
- Settlement status - Current settlement window and net position
- Key statistics - Active keys by type with registration trends
- System health - Service status indicators for DICT, SPI, and Settlement
- Alerts panel - Active alerts for liquidity, errors, and compliance events
vue
<template>
<div class="grid grid-cols-12 gap-4 p-4">
<StatsCard
v-for="stat in dashboardStats"
:key="stat.label"
:label="stat.label"
:value="stat.value"
:trend="stat.trend"
class="col-span-3"
/>
<TransactionChart :data="chartData" class="col-span-8" />
<AlertsPanel :alerts="activeAlerts" class="col-span-4" />
<SettlementSummary :settlement="currentSettlement" class="col-span-6" />
<KeyDistribution :keys="keyStats" class="col-span-6" />
</div>
</template>
<script setup lang="ts">
import { useDashboard } from '@/composables/useDashboard'
const { dashboardStats, chartData, activeAlerts, currentSettlement, keyStats } =
useDashboard({ refreshInterval: 5000 })
</script>Key Management
Full PIX key lifecycle management:
- Key listing - Searchable, filterable table of all registered PIX keys
- Key registration - Form for registering new keys with validation
- Key removal - Bulk and individual key removal with confirmation
- Claim management - View, accept, and deny portability and ownership claims
- Key audit trail - Full history of key operations
vue
<template>
<DataTable
:value="keys"
:paginator="true"
:rows="20"
:filters="filters"
filterDisplay="row"
:loading="loading"
sortField="created_at"
:sortOrder="-1"
>
<Column field="key_value" header="Key" :sortable="true">
<template #filter="{ filterModel }">
<InputText v-model="filterModel.value" placeholder="Search keys..." />
</template>
</Column>
<Column field="key_type" header="Type" :sortable="true">
<template #body="{ data }">
<Tag :value="data.key_type" :severity="keyTypeSeverity(data.key_type)" />
</template>
</Column>
<Column field="owner_name" header="Owner" :sortable="true" />
<Column field="account_number" header="Account" />
<Column field="status" header="Status" :sortable="true">
<template #body="{ data }">
<Tag :value="data.status" :severity="statusSeverity(data.status)" />
</template>
</Column>
<Column field="created_at" header="Registered" :sortable="true">
<template #body="{ data }">
{{ formatDateTime(data.created_at) }}
</template>
</Column>
<Column header="Actions">
<template #body="{ data }">
<Button icon="pi pi-eye" @click="viewKey(data)" text rounded />
<Button icon="pi pi-trash" @click="confirmDelete(data)" text rounded severity="danger" />
</template>
</Column>
</DataTable>
</template>Payment Monitoring
Real-time payment tracking and management:
- Transaction list - All PIX transactions with status, amount, and timeline
- Transaction details - Full payment lifecycle with ISO 20022 message viewer
- Return management - Initiate and track payment returns
- Search - Search by end-to-end ID, amount, account, or date range
- Export - CSV and PDF export for compliance reporting
Settlement Management
Settlement cycle monitoring and reconciliation:
- Window overview - Current and historical settlement windows
- Netting results - Gross credits, debits, and net position per window
- Reconciliation - Automated comparison with BACEN statements
- Discrepancy reports - Flagged transactions requiring investigation
- Position history - Historical liquidity position charts
Compliance and Fraud
MED 2.0 compliance and fraud management:
- Infraction reports - Create and manage infraction reports
- MED requests - Handle special return requests
- Fraud dashboard - Real-time fraud indicators and flagged accounts
- Audit log - Complete audit trail of all administrative actions
API Integration
The portal communicates with the Settlement Service API gateway:
typescript
// services/api.ts
import axios from 'axios'
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4003/api/v1',
timeout: 30000,
})
api.interceptors.request.use((config) => {
const token = useAuthStore().token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
useAuthStore().logout()
router.push('/login')
}
return Promise.reject(error)
}
)
export default apiService Modules
typescript
// services/keys.ts
import api from './api'
import type { PixKey, CreateKeyRequest, KeyListParams } from '@/types'
export const keyService = {
list: (params: KeyListParams) =>
api.get<{ data: PixKey[]; total: number }>('/keys', { params }),
get: (keyValue: string) =>
api.get<PixKey>(`/keys/${encodeURIComponent(keyValue)}`),
create: (data: CreateKeyRequest) =>
api.post<PixKey>('/keys', data),
remove: (keyValue: string) =>
api.delete(`/keys/${encodeURIComponent(keyValue)}`),
lookup: (keyValue: string) =>
api.post<PixKey>('/keys/lookup', { key: keyValue }),
}State Management
Pinia stores manage application state:
typescript
// stores/auth.ts
import { defineStore } from 'pinia'
export const useAuthStore = defineStore('auth', {
state: () => ({
user: null as User | null,
token: localStorage.getItem('token'),
}),
getters: {
isAuthenticated: (state) => !!state.token,
hasRole: (state) => (role: string) => state.user?.roles.includes(role),
},
actions: {
async login(credentials: { email: string; password: string }) {
const { data } = await api.post('/auth/login', credentials)
this.token = data.token
this.user = data.user
localStorage.setItem('token', data.token)
},
logout() {
this.token = null
this.user = null
localStorage.removeItem('token')
},
},
})Development
bash
# Install dependencies
cd frontend/admin
npm install
# Start development server
npm run dev # http://localhost:3000
# Run tests
npm test # Unit tests with Vitest
npm run test:e2e # E2E tests with Cypress
# Build for production
npm run build
# Type checking
npm run type-checkEnvironment Variables
bash
# .env.development
VITE_API_URL=http://localhost:4003/api/v1
VITE_WS_URL=ws://localhost:4003/ws
# .env.production
VITE_API_URL=/api/v1
VITE_WS_URL=/ws